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 java.util.Iterator;
025    import java.util.LinkedList;
026    import java.util.List;
027    import org.jboss.dna.common.util.CheckArg;
028    import org.jboss.dna.graph.GraphI18n;
029    import org.jboss.dna.graph.Location;
030    import org.jboss.dna.graph.connectors.RepositoryConnection;
031    import org.jboss.dna.graph.properties.Path;
032    import org.jboss.dna.graph.properties.Property;
033    
034    /**
035     * Instruction to read all of the children of a node at a specific location.
036     * 
037     * @author Randall Hauch
038     */
039    public class ReadAllChildrenRequest extends CacheableRequest implements Iterable<Location> {
040    
041        private static final long serialVersionUID = 1L;
042    
043        private final Location of;
044        private final List<Location> children = new LinkedList<Location>();
045        private Location actualOf;
046    
047        /**
048         * Create a request to read the children of a node at the supplied location.
049         * 
050         * @param of the location of the node whose children are to be read
051         * @throws IllegalArgumentException if the location is null
052         */
053        public ReadAllChildrenRequest( Location of ) {
054            CheckArg.isNotNull(of, "of");
055            this.of = of;
056        }
057    
058        /**
059         * {@inheritDoc}
060         * 
061         * @see org.jboss.dna.graph.requests.Request#isReadOnly()
062         */
063        @Override
064        public boolean isReadOnly() {
065            return true;
066        }
067    
068        /**
069         * Get the location defining the node whose children are to be read.
070         * 
071         * @return the location of the parent node; never null
072         */
073        public Location of() {
074            return of;
075        }
076    
077        /**
078         * Get the children that were read from the {@link RepositoryConnection} after the request was processed. Each child is
079         * represented by a location.
080         * 
081         * @return the children that were read; never null
082         */
083        public List<Location> getChildren() {
084            return children;
085        }
086    
087        /**
088         * {@inheritDoc}
089         * 
090         * @see java.lang.Iterable#iterator()
091         */
092        public Iterator<Location> iterator() {
093            return children.iterator();
094        }
095    
096        /**
097         * Add to the list of children that has been read the child with the given path and identification properties. The children
098         * should be added in order.
099         * 
100         * @param child the location of the child that was read
101         * @throws IllegalArgumentException if the location is null
102         * @see #addChild(Path, Property)
103         * @see #addChild(Path, Property, Property...)
104         */
105        public void addChild( Location child ) {
106            CheckArg.isNotNull(child, "child");
107            this.children.add(child);
108        }
109    
110        /**
111         * Add to the list of children that has been read the child with the given path and identification properties. The children
112         * should be added in order.
113         * 
114         * @param pathToChild the path of the child that was just read
115         * @param firstIdProperty the first identification property of the child that was just read
116         * @param remainingIdProperties the remaining identification properties of the child that was just read
117         * @throws IllegalArgumentException if the path or identification properties are null
118         * @see #addChild(Location)
119         * @see #addChild(Path, Property)
120         */
121        public void addChild( Path pathToChild,
122                              Property firstIdProperty,
123                              Property... remainingIdProperties ) {
124            Location child = new Location(pathToChild, firstIdProperty, remainingIdProperties);
125            this.children.add(child);
126        }
127    
128        /**
129         * Add to the list of children that has been read the child with the given path and identification property. The children
130         * should be added in order.
131         * 
132         * @param pathToChild the path of the child that was just read
133         * @param idProperty the identification property of the child that was just read
134         * @throws IllegalArgumentException if the path or identification properties are null
135         * @see #addChild(Location)
136         * @see #addChild(Path, Property, Property...)
137         */
138        public void addChild( Path pathToChild,
139                              Property idProperty ) {
140            Location child = new Location(pathToChild, idProperty);
141            this.children.add(child);
142        }
143    
144        /**
145         * Sets the actual and complete location of the node whose children have been read. This method must be called when processing
146         * the request, and the actual location must have a {@link Location#getPath() path}.
147         * 
148         * @param actual the actual location of the node being read, or null if the {@link #of() current location} should be used
149         * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
150         *         location} as the {@link #of() current location}, or if the actual location does not have a path.
151         */
152        public void setActualLocationOfNode( Location actual ) {
153            if (!this.of.isSame(actual)) { // not same if actual is null
154                throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, of));
155            }
156            assert actual != null;
157            if (!actual.hasPath()) {
158                throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
159            }
160            this.actualOf = actual;
161        }
162    
163        /**
164         * Get the actual location of the node whose children were read.
165         * 
166         * @return the actual location, or null if the actual location was not set
167         */
168        public Location getActualLocationOfNode() {
169            return actualOf;
170        }
171    
172        /**
173         * {@inheritDoc}
174         * 
175         * @see java.lang.Object#equals(java.lang.Object)
176         */
177        @Override
178        public boolean equals( Object obj ) {
179            if (this.getClass().isInstance(obj)) {
180                ReadAllChildrenRequest that = (ReadAllChildrenRequest)obj;
181                if (!this.of().equals(that.of())) return false;
182                return true;
183            }
184            return false;
185        }
186    
187        /**
188         * {@inheritDoc}
189         * 
190         * @see java.lang.Object#toString()
191         */
192        @Override
193        public String toString() {
194            return "read children of " + of();
195        }
196    
197    }