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.Collection;
025    import java.util.Collections;
026    import java.util.HashSet;
027    import java.util.Iterator;
028    import java.util.Set;
029    import org.jboss.dna.common.util.CheckArg;
030    import org.jboss.dna.graph.GraphI18n;
031    import org.jboss.dna.graph.Location;
032    import org.jboss.dna.graph.properties.Name;
033    
034    /**
035     * Instruction to remove properties from the node at the specified location.
036     * 
037     * @author Randall Hauch
038     */
039    public class RemovePropertiesRequest extends Request implements Iterable<Name> {
040    
041        private static final long serialVersionUID = 1L;
042    
043        private final Location from;
044        private final Set<Name> propertyNames;
045        private Location actualLocation;
046    
047        /**
048         * Create a request to remove the properties with the given names from the node at the supplied location.
049         * 
050         * @param from the location of the node to be read
051         * @param propertyNames the names of the properties to be removed from the node
052         * @throws IllegalArgumentException if the location is null or if there are no properties to remove
053         */
054        public RemovePropertiesRequest( Location from,
055                                        Name... propertyNames ) {
056            CheckArg.isNotNull(from, "from");
057            CheckArg.isNotEmpty(propertyNames, "propertyNames");
058            this.from = from;
059            Set<Name> names = new HashSet<Name>();
060            for (Name name : propertyNames) {
061                if (name != null) names.add(name);
062            }
063            this.propertyNames = Collections.unmodifiableSet(names);
064        }
065    
066        /**
067         * Create a request to remove the properties with the given names from the node at the supplied location.
068         * 
069         * @param from the location of the node to be read
070         * @param propertyNames the names of the properties to be removed from the node
071         * @throws IllegalArgumentException if the location is null or if there are no properties to remove
072         */
073        public RemovePropertiesRequest( Location from,
074                                        Iterable<Name> propertyNames ) {
075            CheckArg.isNotNull(from, "from");
076            CheckArg.isNotNull(propertyNames, "propertyNames");
077            this.from = from;
078            Set<Name> names = new HashSet<Name>();
079            for (Name name : propertyNames) {
080                if (name != null) names.add(name);
081            }
082            this.propertyNames = Collections.unmodifiableSet(names);
083            CheckArg.isNotEmpty(this.propertyNames, "propertyNames");
084        }
085    
086        /**
087         * Create a request to remove the properties with the given names from the node at the supplied location.
088         * 
089         * @param from the location of the node to be read
090         * @param propertyNames the names of the properties to be removed from the node
091         * @throws IllegalArgumentException if the location is null or if there are no properties to remove
092         */
093        public RemovePropertiesRequest( Location from,
094                                        Iterator<Name> propertyNames ) {
095            CheckArg.isNotNull(from, "from");
096            CheckArg.isNotNull(propertyNames, "propertyNames");
097            this.from = from;
098            Set<Name> names = new HashSet<Name>();
099            while (propertyNames.hasNext()) {
100                Name name = propertyNames.next();
101                if (name != null) names.add(name);
102            }
103            this.propertyNames = Collections.unmodifiableSet(names);
104            CheckArg.isNotEmpty(this.propertyNames, "propertyNames");
105        }
106    
107        /**
108         * {@inheritDoc}
109         * 
110         * @see org.jboss.dna.graph.requests.Request#isReadOnly()
111         */
112        @Override
113        public boolean isReadOnly() {
114            return false;
115        }
116    
117        /**
118         * Get the location defining the node from which the properties are to be removed.
119         * 
120         * @return the location of the node; never null
121         */
122        public Location from() {
123            return from;
124        }
125    
126        /**
127         * {@inheritDoc}
128         * 
129         * @see java.lang.Iterable#iterator()
130         */
131        public Iterator<Name> iterator() {
132            return this.propertyNames.iterator();
133        }
134    
135        /**
136         * Get the names of the properties that are to be removed from the node.
137         * 
138         * @return the collection of property names; never null and never empty
139         */
140        public Collection<Name> propertyNames() {
141            return propertyNames;
142        }
143    
144        /**
145         * Sets the actual and complete location of the node whose properties were removed. 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 changed, or null if the {@link #from() 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 #from() current location}, or if the actual location does not have a path.
151         */
152        public void setActualLocationOfNode( Location actual ) {
153            if (!from.isSame(actual)) { // not same if actual is null
154                throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, from));
155            }
156            assert actual != null;
157            if (!actual.hasPath()) {
158                throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
159            }
160            this.actualLocation = actual;
161        }
162    
163        /**
164         * Get the actual location of the node whose properties were removed.
165         * 
166         * @return the actual location, or null if the actual location was not set
167         */
168        public Location getActualLocationOfNode() {
169            return actualLocation;
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                RemovePropertiesRequest that = (RemovePropertiesRequest)obj;
181                if (!this.from().equals(that.from())) return false;
182                if (!this.propertyNames().equals(that.propertyNames())) return false;
183                return true;
184            }
185            return false;
186        }
187    
188        /**
189         * {@inheritDoc}
190         * 
191         * @see java.lang.Object#toString()
192         */
193        @Override
194        public String toString() {
195            return "remove from " + from() + " properties named " + propertyNames();
196        }
197    
198    }