View Javadoc

1   package org.modeshape.graph.request;
2   
3   import java.util.Collections;
4   import java.util.List;
5   import org.modeshape.common.util.CheckArg;
6   import org.modeshape.graph.GraphI18n;
7   import org.modeshape.graph.Location;
8   import org.modeshape.graph.property.Name;
9   import org.modeshape.graph.property.Path;
10  import org.modeshape.graph.property.Property;
11  
12  /**
13   * Instruction to update the values for a certain property on the node at the specified location.
14   * <p>
15   * This request is capable of specifying specific values for the property that will be added or removed. Other values for the
16   * property not be affected by this request. The request contains a workspace name and a location that uniquely identify a node in
17   * the workspace as well as the name of property (that may or may not previously exist) on the node. The request also contains
18   * zero or more values to add and zero or more values to remove from the property. All values will be appended to the list of
19   * values. Removals are processed before additions.
20   * </p>
21   * <p>
22   * Even if the property has no values after this call, the property itself will not be removed by this request.
23   * </p>
24   * <p>
25   * Note that the number of values in a property (e.g., {@link Property#size()}, {@link Property#isEmpty()},
26   * {@link Property#isSingle()}, and {@link Property#isMultiple()}) has no influence on whether the property should be removed. It
27   * is possible for a property to have no values.
28   * </p>
29   */
30  public class UpdateValuesRequest extends ChangeRequest {
31  
32      private static final long serialVersionUID = 1L;
33  
34      private final String workspaceName;
35      private final Location on;
36      private final Name propertyName;
37      private final List<Object> addedValues;
38      private final List<Object> removedValues;
39  
40      private Location actualLocation;
41      private List<Object> actualAddedValues;
42      private List<Object> actualRemovedValues;
43      private boolean actualCreation;
44      private Property actualProperty;
45  
46      public UpdateValuesRequest( String workspaceName,
47                                  Location on,
48                                  Name propertyName,
49                                  List<Object> addedValues,
50                                  List<Object> removedValues ) {
51          super();
52  
53          assert workspaceName != null;
54          assert on != null;
55          assert propertyName != null;
56  
57          this.workspaceName = workspaceName;
58          this.on = on;
59          this.propertyName = propertyName;
60          this.addedValues = addedValues == null ? Collections.emptyList() : addedValues;
61          this.removedValues = removedValues == null ? Collections.emptyList() : removedValues;
62      }
63  
64      /**
65       * Get the location defining the node that is to be updated.
66       * 
67       * @return the location of the node; never null
68       */
69      public Location on() {
70          return on;
71      }
72  
73      /**
74       * Get the name of the property that is to be updated.
75       * 
76       * @return the name of the property; never null
77       */
78      public Name property() {
79          return propertyName;
80      }
81  
82      /**
83       * Get the name of the workspace in which the node exists.
84       * 
85       * @return the name of the workspace; never null
86       */
87      public String inWorkspace() {
88          return workspaceName;
89      }
90  
91      /**
92       * Get the list of values to be added.
93       * 
94       * @return the values (if any) to be added; never null
95       */
96      public List<Object> addedValues() {
97          return addedValues;
98      }
99  
100     /**
101      * Get the list of values to be removed.
102      * 
103      * @return the values (if any) to be removed; never null
104      */
105     public List<Object> removedValues() {
106         return removedValues;
107     }
108 
109     @Override
110     public Location changedLocation() {
111         return on;
112     }
113 
114     @Override
115     public String changedWorkspace() {
116         return workspaceName;
117     }
118 
119     @Override
120     public boolean changes( String workspace,
121                             Path path ) {
122         return workspaceName.equals(workspace) && on.hasPath() && on.getPath().equals(path);
123     }
124 
125     @Override
126     public boolean isReadOnly() {
127         return addedValues.isEmpty() && removedValues.isEmpty();
128     }
129 
130     public void setActualLocation( Location actual,
131                                    List<Object> actualAddedValues,
132                                    List<Object> actualRemovedValues ) {
133         checkNotFrozen();
134         if (!on.equals(actual)) { // not same if actual is null
135             throw new IllegalArgumentException(GraphI18n.actualLocationNotEqualToInputLocation.text(actual, on));
136         }
137         assert actual != null;
138         if (!actual.hasPath()) {
139             throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
140         }
141         this.actualLocation = actual;
142         assert actualLocation != null;
143 
144         assert actualAddedValues != null;
145         assert actualAddedValues.size() <= addedValues.size();
146         assert actualRemovedValues != null;
147         assert actualRemovedValues.size() <= actualRemovedValues.size();
148 
149         this.actualAddedValues = actualAddedValues;
150         this.actualRemovedValues = actualRemovedValues;
151     }
152 
153     /**
154      * Record that the property did not exist prior to the processing of this request and was actually created by this request.
155      * This method must be called when processing the request, and the actual location must have a {@link Location#getPath() path}.
156      * 
157      * @param property the property being created or updated (may not be <code>null</code>)
158      * @param created true if the property was created by this request, or false if this request updated an existing property
159      * @throws IllegalStateException if the request is frozen
160      * @throws IllegalArgumentException if the property is <code>null</code>
161      */
162     public void setActualProperty( Property property,
163                                    boolean created ) {
164         CheckArg.isNotNull(property, "property");
165         checkNotFrozen();
166         this.actualProperty = property;
167         this.actualCreation = created;
168     }
169     
170     /**
171      * Get the actual node property that was created or updated.
172      * 
173      * @return the actual property or <code>null</code> if the actual property was not set
174      */
175     public Property getActualProperty() {
176         return this.actualProperty;
177     }
178 
179     /**
180      * Get the actual location of the node that was updated.
181      * 
182      * @return the actual location, or null if the actual location was not set
183      */
184     public Location getActualLocationOfNode() {
185         return actualLocation;
186     }
187 
188     /**
189      * Get the actual added values. This should always be identical to the list of values that were requested to be added.
190      * 
191      * @return the values that were added to the node when this request was processed; never null
192      */
193     public List<Object> getActualAddedValues() {
194         return actualAddedValues;
195     }
196 
197     /**
198      * Get the actual removed values. This will differ from the values that were requested to be removed if some of the values
199      * that were requested to be removed were not already values for the property.
200      * 
201      * @return the values that were removed from the node when this request was processed; never null
202      */
203     public List<Object> getActualRemovedValues() {
204         return actualRemovedValues;
205     }
206 
207     /**
208      * Get whether the {@link #property() property} was created.
209      * 
210      * @return true if this request created the property, or false if this request changed an existing property
211      */
212     public boolean isNewProperty() {
213         return actualCreation;
214     }
215 
216     /**
217      * {@inheritDoc}
218      * <p>
219      * This method does not clone the results.
220      * </p>
221      * 
222      * @see org.modeshape.graph.request.ChangeRequest#clone()
223      */
224     @Override
225     public UpdateValuesRequest clone() {
226         UpdateValuesRequest request = new UpdateValuesRequest(workspaceName, actualLocation != null ? actualLocation : on,
227                                                               propertyName, addedValues, removedValues);
228         request.setActualLocation(actualLocation, actualAddedValues, actualRemovedValues);
229         
230         // don't call request.setActualProperty(Property, boolean) here as the actual property may have not been set
231         request.actualProperty = actualProperty;
232         request.actualCreation = actualCreation;
233         
234         return request;
235     }
236 }