001    /*
002     * JBoss DNA (http://www.jboss.org/dna)
003     * See the COPYRIGHT.txt file distributed with this work for information
004     * regarding copyright ownership.  Some portions may be licensed
005     * to Red Hat, Inc. under one or more contributor license agreements.
006     * See the AUTHORS.txt file in the distribution for a full listing of 
007     * individual contributors. 
008     *
009     * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010     * is licensed to you under the terms of the GNU Lesser General Public License as
011     * published by the Free Software Foundation; either version 2.1 of
012     * the License, or (at your option) any later version.
013     *
014     * JBoss DNA is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     * Lesser General Public License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this software; if not, write to the Free
021     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023     */
024    package org.jboss.dna.graph.request;
025    
026    import java.util.LinkedList;
027    import java.util.List;
028    import org.jboss.dna.common.util.CheckArg;
029    import org.jboss.dna.graph.GraphI18n;
030    import org.jboss.dna.graph.Location;
031    import org.jboss.dna.graph.property.Path;
032    import org.jboss.dna.graph.property.Property;
033    
034    /**
035     * Instruction that all nodes below a supplied node be deleted. This is similar to {@link DeleteBranchRequest}, except that the
036     * parent node (top node in the branch) is not deleted.
037     */
038    public class DeleteChildrenRequest extends ChangeRequest {
039    
040        private static final long serialVersionUID = 1L;
041    
042        private final Location at;
043        private final String workspaceName;
044        private Location actualLocation;
045        private List<Location> actualChildrenDeleted = new LinkedList<Location>();
046    
047        /**
048         * Create a request to delete all children of the supplied node. The supplied parent node will not be deleted.
049         * 
050         * @param at the location of the parent node
051         * @param workspaceName the name of the workspace containing the parent
052         * @throws IllegalArgumentException if the location or workspace name is null
053         */
054        public DeleteChildrenRequest( Location at,
055                                      String workspaceName ) {
056            CheckArg.isNotNull(at, "at");
057            CheckArg.isNotNull(workspaceName, "workspaceName");
058            this.workspaceName = workspaceName;
059            this.at = at;
060        }
061    
062        /**
063         * Get the location defining the top of the branch to be deleted
064         * 
065         * @return the location of the branch; never null
066         */
067        public Location at() {
068            return at;
069        }
070    
071        /**
072         * Get the name of the workspace in which the branch exists.
073         * 
074         * @return the name of the workspace; never null
075         */
076        public String inWorkspace() {
077            return workspaceName;
078        }
079    
080        /**
081         * {@inheritDoc}
082         * 
083         * @see org.jboss.dna.graph.request.Request#isReadOnly()
084         */
085        @Override
086        public boolean isReadOnly() {
087            return false;
088        }
089    
090        /**
091         * Sets the actual and complete location of the node being deleted. This method must be called when processing the request,
092         * and the actual location must have a {@link Location#getPath() path}.
093         * 
094         * @param actual the actual location of the node being deleted, or null if the {@link #at() current location} should be used
095         * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
096         *         location} as the {@link #at() current location}, or if the actual location does not have a path.
097         * @throws IllegalStateException if the request is frozen
098         */
099        public void setActualLocationOfNode( Location actual ) {
100            checkNotFrozen();
101            if (!at.isSame(actual)) { // not same if actual is null
102                throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, at));
103            }
104            assert actual != null;
105            if (!actual.hasPath()) {
106                throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
107            }
108            this.actualLocation = actual;
109        }
110    
111        /**
112         * Add to the list of children that has been read the supplied children with the given path and identification properties. The
113         * children are added in order.
114         * 
115         * @param children the locations of the children that were read
116         * @throws IllegalArgumentException if the parameter is null
117         * @throws IllegalStateException if the request is frozen
118         * @see #addDeletedChild(Location)
119         * @see #addDeletedChild(Path, Property)
120         * @see #addDeletedChild(Path, Property, Property...)
121         */
122        public void addDeletedChildren( Iterable<Location> children ) {
123            checkNotFrozen();
124            CheckArg.isNotNull(children, "children");
125            for (Location child : children) {
126                if (child != null) this.actualChildrenDeleted.add(child);
127            }
128        }
129    
130        /**
131         * Add to the list of children that has been read the child with the given path and identification properties. The children
132         * should be added in order.
133         * 
134         * @param child the location of the child that was read
135         * @throws IllegalArgumentException if the location is null
136         * @throws IllegalStateException if the request is frozen
137         * @see #addDeletedChild(Path, Property)
138         * @see #addDeletedChild(Path, Property, Property...)
139         */
140        public void addDeletedChild( Location child ) {
141            checkNotFrozen();
142            CheckArg.isNotNull(child, "child");
143            this.actualChildrenDeleted.add(child);
144        }
145    
146        /**
147         * Add to the list of children that has been read the child with the given path and identification properties. The children
148         * should be added in order.
149         * 
150         * @param pathToChild the path of the child that was just read
151         * @param firstIdProperty the first identification property of the child that was just read
152         * @param remainingIdProperties the remaining identification properties of the child that was just read
153         * @throws IllegalArgumentException if the path or identification properties are null
154         * @throws IllegalStateException if the request is frozen
155         * @see #addDeletedChild(Location)
156         * @see #addDeletedChild(Path, Property)
157         */
158        public void addDeletedChild( Path pathToChild,
159                                     Property firstIdProperty,
160                                     Property... remainingIdProperties ) {
161            checkNotFrozen();
162            Location child = Location.create(pathToChild, firstIdProperty, remainingIdProperties);
163            this.actualChildrenDeleted.add(child);
164        }
165    
166        /**
167         * Add to the list of children that has been read the child with the given path and identification property. The children
168         * should be added in order.
169         * 
170         * @param pathToChild the path of the child that was just read
171         * @param idProperty the identification property of the child that was just read
172         * @throws IllegalArgumentException if the path or identification properties are null
173         * @throws IllegalStateException if the request is frozen
174         * @see #addDeletedChild(Location)
175         * @see #addDeletedChild(Path, Property, Property...)
176         */
177        public void addDeletedChild( Path pathToChild,
178                                     Property idProperty ) {
179            checkNotFrozen();
180            Location child = Location.create(pathToChild, idProperty);
181            this.actualChildrenDeleted.add(child);
182        }
183    
184        /**
185         * Get the list of the actual children that were deleted.
186         * 
187         * @return the actual children, or empty if there were no children (if frozen)
188         */
189        public List<Location> getActualChildrenDeleted() {
190            return actualChildrenDeleted;
191        }
192    
193        /**
194         * Get the actual location of the node that was deleted.
195         * 
196         * @return the actual location, or null if the actual location was not set
197         */
198        public Location getActualLocationOfNode() {
199            return actualLocation;
200        }
201    
202        /**
203         * {@inheritDoc}
204         * 
205         * @see org.jboss.dna.graph.request.ChangeRequest#changes(java.lang.String, org.jboss.dna.graph.property.Path)
206         */
207        @Override
208        public boolean changes( String workspace,
209                                Path path ) {
210            return this.workspaceName.equals(workspace) && at.hasPath() && at.getPath().isAtOrBelow(path);
211        }
212    
213        /**
214         * {@inheritDoc}
215         * 
216         * @see org.jboss.dna.graph.request.ChangeRequest#changedLocation()
217         */
218        @Override
219        public Location changedLocation() {
220            return at;
221        }
222    
223        /**
224         * {@inheritDoc}
225         * 
226         * @see org.jboss.dna.graph.request.ChangeRequest#changedWorkspace()
227         */
228        @Override
229        public String changedWorkspace() {
230            return workspaceName;
231        }
232    
233        /**
234         * {@inheritDoc}
235         * 
236         * @see java.lang.Object#equals(java.lang.Object)
237         */
238        @Override
239        public boolean equals( Object obj ) {
240            if (obj == this) return true;
241            if (this.getClass().isInstance(obj)) {
242                DeleteChildrenRequest that = (DeleteChildrenRequest)obj;
243                if (!this.at().equals(that.at())) return false;
244                if (!this.inWorkspace().equals(that.inWorkspace())) return false;
245                return true;
246            }
247            return false;
248        }
249    
250        /**
251         * {@inheritDoc}
252         * 
253         * @see java.lang.Object#toString()
254         */
255        @Override
256        public String toString() {
257            return "delete nodes below " + at() + " in the \"" + workspaceName + "\" workspace";
258        }
259    }