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    
025    package com.ninja_squad.dbsetup.operation;
026    
027    import java.sql.Connection;
028    import java.sql.SQLException;
029    import java.util.ArrayList;
030    import java.util.Arrays;
031    import java.util.List;
032    
033    import javax.annotation.Nonnull;
034    import javax.annotation.concurrent.Immutable;
035    
036    import com.ninja_squad.dbsetup.bind.BinderConfiguration;
037    
038    /**
039     * A composite operation or, in other words, an operation which consists in executing a sequence of other operations.
040     * @author JB Nizet
041     */
042    @Immutable
043    public final class CompositeOperation implements Operation {
044    
045        private static final Operation NOP = new Operation() {
046    
047            @Override
048            public void execute(Connection connection, BinderConfiguration configuration) {
049                // does nothing since it's a NOP
050            }
051    
052            @Override
053            public String toString() {
054                return "NOP";
055            }
056        };
057    
058        private final List<Operation> operations;
059    
060        private CompositeOperation(List<? extends Operation> operations) {
061            this.operations = new ArrayList<Operation>(operations);
062        }
063    
064        /**
065         * Creates a new Operation containing all the given operations
066         * @param operations the sequence of operations
067         */
068        public static Operation sequenceOf(@Nonnull Operation... operations) {
069            return sequenceOf(Arrays.asList(operations));
070        }
071    
072        /**
073         * Creates a new Operation containing all the given operations
074         * @param operations the sequence of operations
075         */
076        public static Operation sequenceOf(@Nonnull List<? extends Operation> operations) {
077            if (operations.isEmpty()) {
078                return NOP;
079            }
080            else if (operations.size() == 1) {
081                return operations.get(0);
082            }
083            return new CompositeOperation(operations);
084        }
085    
086        /**
087         * Executes the sequence of operations
088         * @throws SQLException as soon as one of the operations in the sequence throws a SQLException
089         */
090        @Override
091        public void execute(Connection connection, BinderConfiguration configuration) throws SQLException {
092            for (Operation operation : operations) {
093                operation.execute(connection, configuration);
094            }
095        }
096    
097        @Override
098        public String toString() {
099            StringBuilder builder = new StringBuilder();
100            boolean first = true;
101            for (Operation operation : operations) {
102                if (!first) {
103                    builder.append("\n");
104                }
105                else {
106                    first = false;
107                }
108                builder.append(operation);
109            }
110            return builder.toString();
111        }
112    
113        @Override
114        public int hashCode() {
115            return operations.hashCode();
116        }
117    
118        @Override
119        public boolean equals(Object o) {
120            if (this == o) {
121                return true;
122            }
123            if (o == null) {
124                return false;
125            }
126            if (getClass() != o.getClass()) {
127                return false;
128            }
129            CompositeOperation other = (CompositeOperation) o;
130            return this.operations.equals(other.operations);
131        }
132    }