Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/virtuosotechnologies/lib/basiccommand/builder/AbstractBranchBuilderNode.java


1   /*
2   ================================================================================
3   
4     FILE:  AbstractBranchBuilderNode.java
5     
6     PROJECT:
7     
8       Virtuoso Utilities
9     
10    CONTENTS:
11    
12      A skeletal implementation for builder nodes with children.
13    
14    PROGRAMMERS:
15    
16      Daniel Azuma (DA)  <dazuma@kagi.com>
17    
18    COPYRIGHT:
19    
20      Copyright (C) 2003  Daniel Azuma  (dazuma@kagi.com)
21      
22      This program is free software; you can redistribute it and/or
23      modify it under the terms of the GNU General Public License as
24      published by the Free Software Foundation; either version 2
25      of the License, or (at your option) any later version.
26      
27      This program is distributed in the hope that it will be useful,
28      but WITHOUT ANY WARRANTY; without even the implied warranty of
29      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30      GNU General Public License for more details.
31      
32      You should have received a copy of the GNU General Public
33      License along with this program; if not, write to
34        Free Software Foundation, Inc.
35        59 Temple Place, Suite 330
36        Boston, MA 02111-1307 USA
37  
38  ================================================================================
39  */
40  
41  
42  package com.virtuosotechnologies.lib.basiccommand.builder;
43  
44  
45  import java.util.List;
46  import java.util.ArrayList;
47  import java.util.Collections;
48  import java.util.Iterator;
49  
50  import com.virtuosotechnologies.lib.command.CommandNode;
51  import com.virtuosotechnologies.lib.command.CommandNodeListener;
52  import com.virtuosotechnologies.lib.command.ChildAddedEvent;
53  import com.virtuosotechnologies.lib.command.ChildRemovedEvent;
54  import com.virtuosotechnologies.lib.command.AllChildrenRemovedEvent;
55  
56  
57  /**
58   * A skeletal implementation for builder nodes with children. Provides
59   * accessors for children as well as position finding. Subclasses need
60   * to implement createChildNode() to create child nodes corresponding
61   * to child CommandNodes. Subclasses also need to implement the
62   * add/set/removeElements methods, as well as getCardinality().
63   */
64  public abstract class AbstractBranchBuilderNode
65  extends AbstractBuilderNode
66  implements
67    CommandNodeListener
68  {
69    private List children_;
70    
71    
72    /**
73     * Used only by AbstractBuilderNode
74     */
75    final void internalAddChild(
76      AbstractBuilderNode node)
77    {
78      children_.add(node);
79    }
80    
81    
82    /**
83     * Used only by AbstractBuilderNode
84     */
85    final void internalAddChild(
86      int index,
87      AbstractBuilderNode node)
88    {
89      children_.add(index, node);
90    }
91    
92    
93    /**
94     * Constructor
95     */
96    protected AbstractBranchBuilderNode(
97      CommandNode commandNode,
98      AbstractBranchBuilderNode parent,
99      int index)
100   {
101     super(commandNode, parent, index);
102     children_ = new ArrayList();
103     commandNode.addNodeListener(this);
104   }
105   
106   
107   /**
108    * Build children. Call this from the constructor of nodes that
109    * can have children. Assumes that the node has no children to start off.
110    */
111   protected final void buildChildren()
112   {
113     CommandNode cn = getCommandNode();
114     int numChildren = cn.getNumChildren();
115     for (int i=0; i<numChildren; ++i)
116     {
117       CommandNode child = cn.getNthChild(i);
118       createChildNode(child, END_POSITION);
119     }
120   }
121   
122   
123   /**
124    * Get the starting position of a particular child
125    */
126   protected final int getPosition(
127     AbstractBuilderNode child)
128   {
129     int ret = 0;
130     for (Iterator iter = children_.iterator(); iter.hasNext(); )
131     {
132       AbstractBuilderNode node = (AbstractBuilderNode)iter.next();
133       if (node == child)
134       {
135         return ret;
136       }
137       else if (node != null)
138       {
139         ret += node.getCardinality();
140       }
141     }
142     return END_POSITION;
143   }
144   
145   
146   /**
147    * Get the starting position at a particular index
148    */
149   protected final int getPosition(
150     int index)
151   {
152     if (index == END_POSITION)
153     {
154       return END_POSITION;
155     }
156     int ret = 0;
157     for (int i=0; i<index; ++i)
158     {
159       AbstractBuilderNode node = (AbstractBuilderNode)children_.get(i);
160       if (node != null)
161       {
162         ret += node.getCardinality();
163       }
164     }
165     return ret;
166   }
167   
168   
169   /**
170    * Get a child given an index
171    */
172   protected final AbstractBuilderNode getChild(
173     int index)
174   {
175     return (AbstractBuilderNode)children_.get(index);
176   }
177   
178   
179   /**
180    * Get a child given a CommandNode
181    */
182   protected final AbstractBuilderNode getChild(
183     CommandNode cn)
184   {
185     for (int i=0; i<children_.size(); ++i)
186     {
187       AbstractBuilderNode node = (AbstractBuilderNode)children_.get(i);
188       if (node != null && node.getCommandNode() == cn)
189       {
190         return node;
191       }
192     }
193     return null;
194   }
195   
196   
197   /**
198    * Get number of children
199    */
200   protected final int getNumChildren()
201   {
202     return children_.size();
203   }
204   
205   
206   /**
207    * Get an unmodifiable view of the list of children
208    */
209   protected final List getChildren()
210   {
211     return Collections.unmodifiableList(children_);
212   }
213   
214   
215   /**
216    * Helper method that removes elements within the specified
217    * child's area of influence (position and cardinality)
218    */
219   protected final void removeChildElements(
220     AbstractBuilderNode child)
221   {
222     if (children_.size() > 0)
223     {
224       int pos = getPosition(child);
225       if (pos != END_POSITION)
226       {
227         int num = child.getCardinality();
228         for (int i=0; i<num; ++i)
229         {
230           removeElementAt(pos);
231         }
232       }
233     }
234   }
235   
236   
237   /**
238    * Create a child node. Return null if no child is to be created.
239    */
240   protected abstract AbstractBuilderNode createChildNode(
241     CommandNode cn,
242     int index);
243   
244   
245   /**
246    * Override this to insert a element at a position.
247    */
248   protected abstract void addElementAt(
249     int pos,
250     Object element);
251   
252   
253   /**
254    * Override this to set the element at a position. Default
255    * implementation calls removeElementAt followed by addElementAt.
256    */
257   protected void setElementAt(
258     int pos,
259     Object element)
260   {
261     removeElementAt(pos);
262     addElementAt(pos, element);
263   }
264   
265   
266   /**
267    * Override this to remove an indexed element.
268    */
269   protected abstract void removeElementAt(
270     int pos);
271   
272   
273   /**
274    * Override this to remove all child elements.
275    */
276   protected abstract void removeAllElements();
277   
278   
279   /**
280    * Child added.
281    * Default method creates a child node, which may result in elements
282    * being added.
283    */
284   public void childAdded(
285     ChildAddedEvent ev)
286   {
287     createChildNode(ev.getChildNode(), ev.getChildIndex());
288   }
289   
290   
291   /**
292    * Child removed.
293    * Default method removes the child node and removes the elements
294    * within the child's area of influence.
295    */
296   public void childRemoved(
297     ChildRemovedEvent ev)
298   {
299     int index = ev.getChildIndex();
300     AbstractBuilderNode child = (AbstractBuilderNode)children_.get(index);
301     if (child != null)
302     {
303       removeChildElements(child);
304     }
305     children_.remove(index);
306   }
307   
308   
309   /**
310    * All children removed.
311    * Default method removes all children and all elements under this node.
312    */
313   public void allChildrenRemoved(
314     AllChildrenRemovedEvent ev)
315   {
316     removeAllElements();
317     children_.clear();
318   }
319 }