KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > nextapp > echo2 > app > update > ServerComponentUpdate


1 /*
2  * This file is part of the Echo Web Application Framework (hereinafter "Echo").
3  * Copyright (C) 2002-2005 NextApp, Inc.
4  *
5  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * Alternatively, the contents of this file may be used under the terms of
18  * either the GNU General Public License Version 2 or later (the "GPL"), or
19  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20  * in which case the provisions of the GPL or the LGPL are applicable instead
21  * of those above. If you wish to allow use of your version of this file only
22  * under the terms of either the GPL or the LGPL, and not to allow others to
23  * use your version of this file under the terms of the MPL, indicate your
24  * decision by deleting the provisions above and replace them with the notice
25  * and other provisions required by the GPL or the LGPL. If you do not delete
26  * the provisions above, a recipient may use your version of this file under
27  * the terms of any one of the MPL, the GPL or the LGPL.
28  */

29
30 package nextapp.echo2.app.update;
31
32 import java.io.Serializable JavaDoc;
33 import java.util.HashMap JavaDoc;
34 import java.util.HashSet JavaDoc;
35 import java.util.Map JavaDoc;
36 import java.util.Set JavaDoc;
37
38 import nextapp.echo2.app.Component;
39
40 /**
41  * A description of a server-side update to a single component, i.e.,
42  * an update which has occurred on the server and must be propagated
43  * to the client.
44  *
45  * Describes the addition and removal of children to the component.
46  * Describes modifications to properties of the component.
47  * Describes modifications to the <code>LayoutData</code> states of
48  * children of the component.
49  */

50 public class ServerComponentUpdate
51 implements Serializable JavaDoc {
52
53     private static final Component[] EMPTY_COMPONENT_ARRAY = new Component[0];
54     private static final String JavaDoc[] EMPTY_STRING_ARRAY = new String JavaDoc[0];
55     
56     /**
57      * The set of child <code>Component</code>s added to the <code>parent</code>.
58      */

59     private Set JavaDoc addedChildren;
60     
61     /**
62      * The parent component represented in this <code>ServerComponentUpdate</code>.
63      */

64     private Component parent;
65     
66     /**
67      * A mapping between property names of the <code>parent</code> component and
68      * <code>PropertyUpdate</code>s.
69      */

70     private Map JavaDoc propertyUpdates;
71     
72     /**
73      * The set of child <code>Component</code>s removed from the <code>parent</code>.
74      */

75     private Set JavaDoc removedChildren;
76     
77     /**
78      * The set of descendant <code>Component</code>s which are implicitly removed
79      * as they were children of removed children.
80      */

81     private Set JavaDoc removedDescendants;
82
83     /**
84      * The set of child <code>Component</code>s whose <code>LayoutData</code>
85      * was updated.
86      */

87     private Set JavaDoc updatedLayoutDataChildren;
88     
89     /**
90      * Creates a new <code>ServerComponentUpdate</code> representing the given
91      * <code>parent</code> <code>Component</code>.
92      */

93     public ServerComponentUpdate(Component parent) {
94         this.parent = parent;
95     }
96     
97     /**
98      * Adds a description of an added child to the
99      * <code>ServerComponentUpdate</code>.
100      *
101      * @param child the child being added
102      */

103     public void addChild(Component child) {
104         if (addedChildren == null) {
105             addedChildren = new HashSet JavaDoc();
106         }
107         addedChildren.add(child);
108     }
109     
110     /**
111      * Cancels an update to a property. A cancellation of a property update
112      * is performed when the update manager discovers that the state of a
113      * property is already correct on the client.
114      *
115      * @param propertyName the property update to cancel
116      */

117     public void cancelUpdateProperty(String JavaDoc propertyName) {
118         if (propertyUpdates == null) {
119             return;
120         }
121         propertyUpdates.remove(propertyName);
122         if (propertyUpdates.size() == 0) {
123             propertyUpdates = null;
124         }
125     }
126     
127     /**
128      * Appends the removed child and descendant components of the given
129      * <code>ServerComponentUpdate</code> to this
130      * <code>ServerComponentUpdate</code>'s list of removed descendants.
131      * This method is invoked by the <code>ServerUpdateManager</code> when
132      * a component is removed that is an ancestor of a component that has
133      * been updated. In such a case, the descendant
134      * <code>ServerComponentUpdate</code> is destroyed,
135      * and thus its removed descendant components must be stored in the
136      * ancestor <code>ServerComponentUpdate</code>.
137      *
138      * @param update the <code>ServerComponentUpdate</code> whose removed
139      * descendants are to be appended
140      */

141     public void appendRemovedDescendants(ServerComponentUpdate update) {
142         // Append removed descendants.
143
if (update.removedDescendants != null) {
144             if (removedDescendants == null) {
145                 removedDescendants = new HashSet JavaDoc();
146             }
147             removedDescendants.addAll(update.removedDescendants);
148         }
149         // Append removed children.
150
if (update.removedChildren != null) {
151             if (removedDescendants == null) {
152                 removedDescendants = new HashSet JavaDoc();
153             }
154             removedDescendants.addAll(update.removedChildren);
155         }
156     }
157     
158     /**
159      * Returns the child components which have been added to the parent.
160      *
161      * @return the added child components
162      */

163     public Component[] getAddedChildren() {
164         if (addedChildren == null) {
165             return EMPTY_COMPONENT_ARRAY;
166         } else {
167             return (Component[]) addedChildren.toArray(new Component[addedChildren.size()]);
168         }
169     }
170     
171     /**
172      * Returns the parent component being updated.
173      *
174      * @return the parent component
175      */

176     public Component getParent() {
177         return parent;
178     }
179     
180     /**
181      * Returns the child components which have been removed from the parent.
182      * These components may or may not have ever been rendered by the container,
183      * e.g., if a component was added and removed in a single synchronization it
184      * will show up as a removed component even though the container may have
185      * never rendered it.
186      *
187      * @return the removed child components
188      * @see #getRemovedDescendants()
189      */

190     public Component[] getRemovedChildren() {
191         if (removedChildren == null) {
192             return EMPTY_COMPONENT_ARRAY;
193         } else {
194             return (Component[]) removedChildren.toArray(new Component[removedChildren.size()]);
195         }
196     }
197     
198     /**
199      * Returns all descendants of the child components which have been
200      * removed from the parent. This returned array DOES NOT contain the
201      * children which were directly removed from the parent component.
202      * These components may or may not have ever been rendered by the container,
203      * e.g., if a component was added and removed in a single synchronization it
204      * will show up as a removed descendant even though the container may have
205      * never rendered it.
206      *
207      * @return the removed descendant components
208      * @see #getRemovedChildren()
209      */

210     public Component[] getRemovedDescendants() {
211         if (removedDescendants == null) {
212             return EMPTY_COMPONENT_ARRAY;
213         } else {
214             return (Component[]) removedDescendants.toArray(new Component[removedDescendants.size()]);
215         }
216     }
217     
218     /**
219      * Returns the child components whose <code>LayoutData</code> properties
220      * have been updated.
221      *
222      * @return the changed child components
223      */

224     public Component[] getUpdatedLayoutDataChildren() {
225         if (updatedLayoutDataChildren == null) {
226             return EMPTY_COMPONENT_ARRAY;
227         } else {
228             return (Component[]) updatedLayoutDataChildren.toArray(new Component[updatedLayoutDataChildren.size()]);
229         }
230     }
231     
232     /**
233      * Returns a <code>PropertyUpdate</code> describing an update to the
234      * property with the given <code>name</code>.
235      *
236      * @param name the name of the property being updated
237      * @return the <code>PropertyUpdate</code>, or null if none exists
238      * @see #getUpdatedPropertyNames()
239      */

240     public PropertyUpdate getUpdatedProperty(String JavaDoc name) {
241         return propertyUpdates == null ? null : (PropertyUpdate) propertyUpdates.get(name);
242     }
243     
244     /**
245      * Returns the names of all properties being updated in this update.
246      *
247      * @return the names of all updated properties
248      * @see #getUpdatedPropertyNames()
249      */

250     public String JavaDoc[] getUpdatedPropertyNames() {
251         if (propertyUpdates == null) {
252             return EMPTY_STRING_ARRAY;
253         } else {
254             return (String JavaDoc[]) propertyUpdates.keySet().toArray(new String JavaDoc[propertyUpdates.size()]);
255         }
256     }
257     
258     /**
259      * Determines if the specified component has been added
260      * as a child in this update.
261      *
262      * @param component the component to test
263      * @return true if the component was added
264      */

265     public boolean hasAddedChild(Component component) {
266         return addedChildren != null && addedChildren.contains(component);
267     }
268     
269     /**
270      * Determines if the update is adding any children to the parent component.
271      *
272      * @return true if children are being added
273      */

274     public boolean hasAddedChildren() {
275         return addedChildren != null;
276     }
277     
278     /**
279      * Determines if the specified child was removed from the parent component.
280      *
281      * @param component the potentially removed child
282      * @return true if the child was removed
283      */

284     public boolean hasRemovedChild(Component component) {
285         return removedChildren != null && removedChildren.contains(component);
286     }
287     
288     /**
289      * Determines if the update is removing children from the parent
290      * component.
291      *
292      * @return true if children are being removed
293      */

294     public boolean hasRemovedChildren() {
295         return removedChildren != null;
296     }
297     
298     /**
299      * Determines if the update is removing children from the parent that
300      * have descendants.
301      * Having removed descendants implies having removed children.
302      * If none of the children being removed have children, this method
303      * will return false.
304      *
305      * @return true if descendants are being removed
306      */

307     public boolean hasRemovedDescendants() {
308         return removedDescendants != null;
309     }
310     
311     /**
312      * Determines if the update has child components whose
313      * <code>LayoutData</code> states have changed.
314      *
315      * @return true if <code>LayoutData</code> properties are being updated
316      */

317     public boolean hasUpdatedLayoutDataChildren() {
318         return updatedLayoutDataChildren != null;
319     }
320     
321     /**
322      * Determines if the update is updating properties of the parent component.
323      *
324      * @return true if properties are being updated
325      */

326     public boolean hasUpdatedProperties() {
327         return propertyUpdates != null;
328     }
329     
330     /**
331      * Adds a description of a removed child to the
332      * <code>ServerComponentUpdate</code>.
333      *
334      * @param child the child being removed
335      */

336     public void removeChild(Component child) {
337         if (addedChildren != null && addedChildren.contains(child)) {
338             // Remove child from add list if found.
339
addedChildren.remove(child);
340         }
341         if (updatedLayoutDataChildren != null && updatedLayoutDataChildren.contains(child)) {
342             // Remove child from updated layout data list if found.
343
updatedLayoutDataChildren.remove(child);
344         }
345         if (removedChildren == null) {
346             removedChildren = new HashSet JavaDoc();
347         }
348         removedChildren.add(child);
349         
350         Component[] descendants = child.getComponents();
351         for (int i = 0; i < descendants.length; ++i) {
352             removeDescendant(descendants[i]);
353         }
354     }
355     
356     /**
357      * Recursive method to add descriptions of descendants which were
358      * removed.
359      *
360      * @param descendant the removed descendant
361      */

362     public void removeDescendant(Component descendant) {
363         if (removedDescendants == null) {
364             removedDescendants = new HashSet JavaDoc();
365         }
366         removedDescendants.add(descendant);
367         Component[] descendants = descendant.getComponents();
368         for (int i = 0; i < descendants.length; ++i) {
369             removeDescendant(descendants[i]);
370         }
371     }
372     
373     /**
374      * Display debug representation.
375      *
376      * @see java.lang.Object#toString()
377      */

378     public String JavaDoc toString() {
379         StringBuffer JavaDoc out = new StringBuffer JavaDoc();
380         out.append(ServerComponentUpdate.class.getName() + "\n");
381         out.append("- Parent: " + getParent() + "\n");
382         out.append("- Adds: " + addedChildren + "\n");
383         out.append("- Removes: " + removedChildren + "\n");
384         out.append("- DescendantRemoves: " + removedDescendants + "\n");
385         out.append("- ChildLayoutDataUpdates: " + updatedLayoutDataChildren + "\n");
386         out.append("- PropertyUpdates: " + propertyUpdates + "\n");
387         return out.toString();
388     }
389     
390     /**
391      * Adds a description of an update to a child component's
392      * <code>LayoutData</code> information to the
393      * <code>ServerComponentUpdate</code>.
394      *
395      * @param child the updated child
396      */

397     public void updateLayoutData(Component child) {
398         if (updatedLayoutDataChildren == null) {
399             updatedLayoutDataChildren = new HashSet JavaDoc();
400         }
401         updatedLayoutDataChildren.add(child);
402     }
403     
404     /**
405      * Adds a description of an update to a property of the parent component
406      * to the <code>ServerComponentUpdate</code>.
407      *
408      * @param propertyName the name of the property
409      * @param oldValue the previous value of the property
410      * @param newValue the current value of the property
411      */

412     public void updateProperty(String JavaDoc propertyName, Object JavaDoc oldValue, Object JavaDoc newValue) {
413         if (propertyUpdates == null) {
414             propertyUpdates = new HashMap JavaDoc();
415         }
416         PropertyUpdate propertyUpdate = new PropertyUpdate(oldValue, newValue);
417         propertyUpdates.put(propertyName, propertyUpdate);
418     }
419 }
420
Popular Tags