001/*
002 * The MIT License
003 *
004 * Copyright (c) 2012, Ninja Squad
005 *
006 * Permission is hereby granted, free of charge, to any person obtaining a copy
007 * of this software and associated documentation files (the "Software"), to deal
008 * in the Software without restriction, including without limitation the rights
009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010 * copies of the Software, and to permit persons to whom the Software is
011 * furnished to do so, subject to the following conditions:
012 *
013 * The above copyright notice and this permission notice shall be included in
014 * all copies or substantial portions of the Software.
015 *
016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
022 * THE SOFTWARE.
023 */
024
025package com.ninja_squad.dbsetup.operation;
026
027import javax.annotation.Nonnull;
028import javax.annotation.concurrent.Immutable;
029import java.sql.Connection;
030import java.sql.SQLException;
031import java.util.ArrayList;
032import java.util.Arrays;
033import java.util.List;
034
035import com.ninja_squad.dbsetup.bind.BinderConfiguration;
036
037/**
038 * A composite operation or, in other words, an operation which consists in executing a sequence of other operations.
039 * @author JB Nizet
040 */
041@Immutable
042public final class CompositeOperation implements Operation {
043
044    private static final Operation NOP = new Operation() {
045
046        @Override
047        public void execute(Connection connection, BinderConfiguration configuration) {
048            // does nothing since it's a NOP
049        }
050
051        @Override
052        public String toString() {
053            return "NOP";
054        }
055    };
056
057    private final List<Operation> operations;
058
059    private CompositeOperation(List<? extends Operation> operations) {
060        this.operations = new ArrayList<Operation>(operations);
061    }
062
063    /**
064     * Creates a new Operation containing all the given operations
065     * @param operations the sequence of operations
066     */
067    public static Operation sequenceOf(@Nonnull Operation... operations) {
068        return sequenceOf(Arrays.asList(operations));
069    }
070
071    /**
072     * Creates a new Operation containing all the given operations
073     * @param operations the sequence of operations
074     */
075    public static Operation sequenceOf(@Nonnull List<? extends Operation> operations) {
076        if (operations.isEmpty()) {
077            return NOP;
078        }
079        else if (operations.size() == 1) {
080            return operations.get(0);
081        }
082        return new CompositeOperation(operations);
083    }
084
085    /**
086     * Executes the sequence of operations
087     * @throws SQLException as soon as one of the operations in the sequence throws a SQLException
088     */
089    @Override
090    public void execute(Connection connection, BinderConfiguration configuration) throws SQLException {
091        for (Operation operation : operations) {
092            operation.execute(connection, configuration);
093        }
094    }
095
096    @Override
097    public String toString() {
098        StringBuilder builder = new StringBuilder();
099        boolean first = true;
100        for (Operation operation : operations) {
101            if (!first) {
102                builder.append('\n');
103            }
104            else {
105                first = false;
106            }
107            builder.append(operation);
108        }
109        return builder.toString();
110    }
111
112    @Override
113    public int hashCode() {
114        return operations.hashCode();
115    }
116
117    @Override
118    public boolean equals(Object o) {
119        if (this == o) {
120            return true;
121        }
122        if (o == null) {
123            return false;
124        }
125        if (getClass() != o.getClass()) {
126            return false;
127        }
128        CompositeOperation other = (CompositeOperation) o;
129        return this.operations.equals(other.operations);
130    }
131}