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 javax.annotation.Nonnull;
028    import javax.annotation.concurrent.Immutable;
029    import java.sql.Connection;
030    import java.sql.SQLException;
031    import java.util.ArrayList;
032    import java.util.Arrays;
033    import java.util.List;
034    
035    import 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
042    public 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    }