001    /*
002     * JBoss, Home of Professional Open Source.
003     * Copyright 2008, Red Hat Middleware LLC, and individual contributors
004     * as indicated by the @author tags. See the copyright.txt file in the
005     * distribution for a full listing of individual contributors. 
006     *
007     * This is free software; you can redistribute it and/or modify it
008     * under the terms of the GNU Lesser General Public License as
009     * published by the Free Software Foundation; either version 2.1 of
010     * the License, or (at your option) any later version.
011     *
012     * This software is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015     * Lesser General Public License for more details.
016     *
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this software; if not, write to the Free
019     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021     */
022    package org.jboss.dna.graph.requests;
023    
024    import org.jboss.dna.common.util.CheckArg;
025    import org.jboss.dna.graph.GraphI18n;
026    import org.jboss.dna.graph.Location;
027    import org.jboss.dna.graph.NodeConflictBehavior;
028    
029    /**
030     * Instruction that a branch be moved from one location into another.
031     * 
032     * @author Randall Hauch
033     */
034    public class MoveBranchRequest extends Request {
035    
036        private static final long serialVersionUID = 1L;
037    
038        public static final NodeConflictBehavior DEFAULT_CONFLICT_BEHAVIOR = NodeConflictBehavior.APPEND;
039    
040        private final Location from;
041        private final Location into;
042        private final NodeConflictBehavior conflictBehavior;
043        private Location actualOldLocation;
044        private Location actualNewLocation;
045    
046        /**
047         * Create a request to move a branch from one location into another.
048         * 
049         * @param from the location of the top node in the existing branch that is to be moved
050         * @param into the location of the existing node into which the branch should be moved
051         * @throws IllegalArgumentException if <code>from</code> or <code>into</code> are null
052         */
053        public MoveBranchRequest( Location from,
054                                  Location into ) {
055            this(from, into, DEFAULT_CONFLICT_BEHAVIOR);
056        }
057    
058        /**
059         * Create a request to move a branch from one location into another.
060         * 
061         * @param from the location of the top node in the existing branch that is to be moved
062         * @param into the location of the existing node into which the branch should be moved
063         * @param conflictBehavior the expected behavior if an equivalently-named child already exists at the <code>into</code>
064         *        location
065         * @throws IllegalArgumentException if any of the parameters are null
066         */
067        public MoveBranchRequest( Location from,
068                                  Location into,
069                                  NodeConflictBehavior conflictBehavior ) {
070            CheckArg.isNotNull(from, "from");
071            CheckArg.isNotNull(into, "into");
072            CheckArg.isNotNull(conflictBehavior, "conflictBehavior");
073            this.from = from;
074            this.into = into;
075            this.conflictBehavior = conflictBehavior;
076        }
077    
078        /**
079         * Get the location defining the top of the branch to be moved
080         * 
081         * @return the from location; never null
082         */
083        public Location from() {
084            return from;
085        }
086    
087        /**
088         * Get the location defining the parent where the branch is to be placed
089         * 
090         * @return the to location; never null
091         */
092        public Location into() {
093            return into;
094        }
095    
096        /**
097         * Get the expected behavior when copying the branch and the {@link #into() destination} already has a node with the same
098         * name.
099         * 
100         * @return the behavior specification
101         */
102        public NodeConflictBehavior conflictBehavior() {
103            return conflictBehavior;
104        }
105    
106        /**
107         * {@inheritDoc}
108         * 
109         * @see org.jboss.dna.graph.requests.Request#isReadOnly()
110         */
111        @Override
112        public boolean isReadOnly() {
113            return false;
114        }
115    
116        /**
117         * Sets the actual and complete location of the node being renamed and its new location. This method must be called when
118         * processing the request, and the actual location must have a {@link Location#getPath() path}.
119         * 
120         * @param oldLocation the actual location of the node before being renamed
121         * @param newLocation the actual location of the node after being renamed
122         * @throws IllegalArgumentException if the either location is null, if the old location does not represent the
123         *         {@link Location#isSame(Location) same location} as the {@link #from() from location}, if the new location does not
124         *         represent the {@link Location#isSame(Location) same location} as the {@link #into() into location}, or if the
125         *         either location does not have a path
126         */
127        public void setActualLocations( Location oldLocation,
128                                        Location newLocation ) {
129            if (!from.isSame(oldLocation)) { // not same if actual is null
130                throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(oldLocation, from));
131            }
132            if (!into.isSame(newLocation, false)) { // not same if actual is null
133                throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(newLocation, into));
134            }
135            assert oldLocation != null;
136            assert newLocation != null;
137            if (!oldLocation.hasPath()) {
138                throw new IllegalArgumentException(GraphI18n.actualOldLocationMustHavePath.text(oldLocation));
139            }
140            if (!newLocation.hasPath()) {
141                throw new IllegalArgumentException(GraphI18n.actualNewLocationMustHavePath.text(newLocation));
142            }
143            this.actualNewLocation = newLocation;
144        }
145    
146        /**
147         * Get the actual location of the node before being moved.
148         * 
149         * @return the actual location of the node before being moved, or null if the actual location was not set
150         */
151        public Location getActualLocationBefore() {
152            return actualOldLocation;
153        }
154    
155        /**
156         * Get the actual location of the node after being moved.
157         * 
158         * @return the actual location of the node after being moved, or null if the actual location was not set
159         */
160        public Location getActualLocationAfter() {
161            return actualNewLocation;
162        }
163    
164        /**
165         * {@inheritDoc}
166         * 
167         * @see java.lang.Object#equals(java.lang.Object)
168         */
169        @Override
170        public boolean equals( Object obj ) {
171            if (this.getClass().isInstance(obj)) {
172                MoveBranchRequest that = (MoveBranchRequest)obj;
173                if (!this.from().equals(that.from())) return false;
174                if (!this.into().equals(that.into())) return false;
175                if (!this.conflictBehavior().equals(that.conflictBehavior())) return false;
176                return true;
177            }
178            return false;
179        }
180    
181        /**
182         * {@inheritDoc}
183         * 
184         * @see java.lang.Object#toString()
185         */
186        @Override
187        public String toString() {
188            return "move branch " + from() + " into " + into();
189        }
190    }