KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > src > MemoryCollection


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.openide.src;
21
22 import java.io.Serializable JavaDoc;
23 import java.util.*;
24
25 /** Support class that manages set of objects and fires events
26 * about its changes.
27 *
28 * @author Jaroslav Tulach
29 */

30 abstract class MemoryCollection extends Object JavaDoc implements Serializable JavaDoc {
31     /** array of objects */
32     LinkedList array;
33
34     /** Object to fire info about changes to */
35     ClassElement.Memory memory;
36
37     /** If set, new elements will be inserted before or after this one, depending on {@link #insertAfter }
38     */

39     private Element insertionMark;
40
41   /** Determines, if new elements are inserted before (false) or after (true) the insertionMark. If insertionMark
42       is null elements are inserted at the end (true) or at the beginning (false) of the collection.
43   */

44   private boolean insertAfter;
45
46     /** name of property to fire */
47     private String JavaDoc propertyName;
48
49     /** array template to return */
50     private Object JavaDoc[] template;
51
52     static final long serialVersionUID =-9215370960397120952L;
53
54     /**
55     * @param memory memory element to fire changes to
56     * @param propertyName name of property to fire when array changes
57     * @param emptyArray emptyArray instance that provides the type of arrays
58     * that should be returned by toArray method
59     */

60     public MemoryCollection(
61         ClassElement.Memory memory, String JavaDoc propertyName, Object JavaDoc[] emptyArray
62     ) {
63         this.memory = memory;
64         this.propertyName = propertyName;
65         this.template = emptyArray;
66     }
67     
68     Collection makeClones(Object JavaDoc[] els) {
69         Collection contents = array == null ? Collections.EMPTY_LIST : array;
70         
71         Set hashContents = new HashSet(contents.size() * 4 / 3 + 1);
72         for (Iterator it = contents.iterator(); it.hasNext(); ) {
73         Object JavaDoc e = it.next();
74             hashContents.add(e);
75         }
76         Collection result = new ArrayList(els.length);
77         for (int i = 0; i < els.length; i++) {
78             Object JavaDoc el = els[i];
79             if (!hashContents.contains(el)) {
80                 result.add(clone(el));
81             } else {
82                 result.add(el);
83         }
84         }
85         return result;
86     }
87     
88     Collection cloneElements(Object JavaDoc[] els) {
89         Collection n = new ArrayList(els.length);
90         for (int i = 0; i < els.length; i++) {
91             n.add(clone(els[i]));
92         }
93         return n;
94     }
95     
96     protected abstract Object JavaDoc clone(Object JavaDoc el);
97
98     /** Changes the content of this object.
99     * @param arr array of objects to change
100     * @param action the action to do
101     */

102     public void change (Object JavaDoc[] arr, int action) {
103         Collection data;
104         
105         switch (action) {
106             case ClassElement.Impl.ADD:
107                 data = cloneElements(arr);
108                 break;
109             case ClassElement.Impl.REMOVE:
110                 data = Arrays.asList(arr);
111                 break;
112             case ClassElement.Impl.SET:
113                 data = makeClones(arr);
114                 break;
115             default:
116                 return;
117         }
118         change (data, action);
119     }
120     /** Changes the content of this object.
121     * @param c collection of objects to change
122     * @param action the action to do
123     */

124     protected void change (Collection c, int action) {
125         boolean anChange;
126         switch (action) {
127         case ClassElement.Impl.ADD:
128             anChange = c.size () > 0;
129             if (array != null) {
130                 if (insertionMark != null) {
131                     int index = array.indexOf(insertionMark);
132                     if (index == -1) {
133                         insertionMark = null;
134                         index = array.size();
135                     } else if (insertAfter) {
136                         index++;
137                     }
138                     array.addAll(index, c);
139                 } else {
140                     array.addAll (c);
141                 }
142                 break;
143             }
144             // fall thru to initialize the array
145
case ClassElement.Impl.SET:
146             // PENDING: better change detection; currently any SET operation will fire change.
147
anChange = c.size () > 0 || (array != null && array.size () > 0);
148             array = new LinkedList (c);
149             insertionMark = null;
150             break;
151         case ClassElement.Impl.REMOVE:
152         {
153             Element newMark = null;
154             if (insertionMark != null && c.contains(insertionMark)) {
155                 Set removing = new HashSet(c.size() * 4 / 3);
156                 removing.addAll(c);
157                 int markIndex = array.indexOf(insertionMark);
158                 if (markIndex == -1) {
159                     insertionMark = null;
160                 } else {
161                     ListIterator it = array.listIterator(markIndex);
162                     while (it.hasNext()) {
163                         Object JavaDoc x = it.next();
164                         if (!removing.contains(x)) {
165                             newMark = (Element)x;
166                             insertAfter = false;
167                             break;
168                         }
169                     }
170                     if (newMark == null) {
171                         it = array.listIterator(markIndex);
172                         while (it.hasPrevious()) {
173                             Object JavaDoc x = it.previous();
174                             if (!removing.contains(x)) {
175                                 newMark = (Element)x;
176                                 insertAfter = true;
177                                 break;
178                             }
179                         }
180                     }
181                 }
182                 insertionMark = newMark;
183             }
184             anChange = array != null && array.removeAll (c);
185             break;
186         }
187         default:
188             // illegal argument in internal implementation
189
throw new InternalError JavaDoc ();
190         }
191
192         if (anChange) {
193             // do not construct array values if not necessary
194
memory.firePropertyChange (propertyName, null, null);
195         }
196     }
197
198     /** Access to the array.
199     * @return array of objects contained here
200     */

201     public Object JavaDoc[] toArray () {
202         if (array == null) {
203             return template;
204         } else {
205             return array.toArray (template);
206         }
207     }
208   
209     void markCurrent(Element el, boolean after) {
210         insertionMark = el;
211         insertAfter = after;
212     }
213
214     static final class Interface extends MemoryCollection {
215         Interface(ClassElement.Memory memory) {
216             super(memory, ElementProperties.PROP_INTERFACES, new Identifier[0]);
217         }
218         
219         Collection makeClones(Object JavaDoc[] arr) {
220             return Arrays.asList(arr);
221         }
222
223         Collection cloneElements(Object JavaDoc[] arr) {
224             return Arrays.asList(arr);
225         }
226
227         protected Object JavaDoc clone(Object JavaDoc o) {
228             // interfaces are immutable...
229
return o;
230         }
231     }
232
233     /** Special collection for initializers. Provides declaringClass field.
234     */

235     static final class Initializer extends MemoryCollection {
236         private static final InitializerElement[] EMPTY = new InitializerElement[0];
237
238         static final long serialVersionUID =5715072242254795093L;
239         /**
240         * @param memory memory element to fire changes to
241         * @param propertyName name of property to fire when array changes
242         * @param emptyArray emptyArray instance that provides the type of arrays
243         * that should be returned by toArray method
244         */

245         public Initializer (
246             ClassElement.Memory memory
247         ) {
248             super (memory, ElementProperties.PROP_INITIALIZERS, EMPTY);
249         }
250
251         protected Object JavaDoc clone(Object JavaDoc el) {
252             return new InitializerElement(
253                 new InitializerElement.Memory((InitializerElement)el),
254                 memory.getClassElement());
255         }
256     }
257
258     /** Collection for members. Assignes to each class its
259     * members.
260     */

261     static abstract class Member extends MemoryCollection {
262         static final long serialVersionUID =7875426480834524238L;
263         /**
264         * @param memory memory element to fire changes to
265         * @param propertyName name of property to fire when array changes
266         * @param emptyArray emptyArray instance that provides the type of arrays
267         * that should be returned by toArray method
268         */

269         public Member (
270             ClassElement.Memory memory, String JavaDoc propertyName, Object JavaDoc[] emptyArray
271         ) {
272             super (memory, propertyName, emptyArray);
273         }
274
275         /** Find method that looks in member elements
276         * @param id the indetifier (or null)
277         * @param types array of types to test (or null)
278         * @return the element or null
279         */

280         public MemberElement find (Identifier id, Type[] types) {
281             if (array == null)
282                 return null;
283
284             Iterator it = array.iterator ();
285             while (it.hasNext ()) {
286                 MemberElement me = (MemberElement)it.next ();
287                 if (
288                     (id == null || id.equals(me.getName ()))
289                     &&
290                     // types can be non-null only for Method or Constructor Elements
291
(types == null || equalTypes (types, me))
292                 ) {
293                     // found element
294
return me;
295                 }
296             }
297             // nothing found
298
return null;
299         }
300
301         /** Copares given types to types of the element.
302         * The element must be ConstructorElement
303         *
304         * @param types the types
305         * @param el the element
306         * @return true if types are equal
307         */

308         private static boolean equalTypes (Type[] types, MemberElement el) {
309             // can be called only for ConstructorElement
310
MethodParameter[] test = ((ConstructorElement)el).getParameters ();
311
312             // number
313
if (test.length != types.length) return false;
314
315             int l = test.length;
316             for (int i = 0; i < l; i++) {
317                 if (!test[i].getType().equals(types[i]))
318                     return false;
319             }
320             return true;
321         }
322     }
323
324     /** Collection for members. Assignes to each class its
325     * members.
326     */

327     static class Constructor extends Member {
328         private static final ConstructorElement[] EMPTY = new ConstructorElement[0];
329
330         static final long serialVersionUID =4314343816469864217L;
331         /** @param ce class element memory impl to work in
332         */

333         public Constructor (ClassElement.Memory ce) {
334             super (ce, ElementProperties.PROP_CONSTRUCTORS, EMPTY);
335         }
336
337         /** Clones the object.
338         * @param obj object to clone
339         * @return cloned object
340         */

341         protected Object JavaDoc clone (Object JavaDoc obj) {
342         ConstructorElement.Memory m = new ConstructorElement.Memory ((ConstructorElement)obj);
343         Identifier id = memory.getName();
344         if (id != null) {
345         m.setName(Identifier.create(id.getName()));
346         }
347             return new ConstructorElement(m, memory.getClassElement());
348         }
349     }
350
351     /** Collection for methods.
352     */

353     static class Method extends Member {
354         private static final MethodElement[] EMPTY = new MethodElement[0];
355
356         static final long serialVersionUID =-745714645316747109L;
357         /** @param ce class element memory impl to work in
358         */

359         public Method (ClassElement.Memory ce) {
360             super (ce, ElementProperties.PROP_METHODS, EMPTY);
361         }
362
363         /** Clones the object.
364         * @param obj object to clone
365         * @return cloned object
366         */

367         protected Object JavaDoc clone (Object JavaDoc obj) {
368             return new MethodElement (new MethodElement.Memory (
369                                           (MethodElement)obj
370                                       ), memory.getClassElement ());
371         }
372     }
373
374     /** Collection of fields.
375     */

376     static class Field extends Member {
377         private static final FieldElement[] EMPTY = new FieldElement[0];
378
379         static final long serialVersionUID =5747776340409139399L;
380         /** @param ce class element memory impl to work in
381         */

382         public Field (ClassElement.Memory ce) {
383             super (ce, ElementProperties.PROP_FIELDS, EMPTY);
384         }
385
386         /** Clones the object.
387         * @param obj object to clone
388         * @return cloned object
389         */

390         protected Object JavaDoc clone (Object JavaDoc obj) {
391             return new FieldElement (new FieldElement.Memory (
392                                          (FieldElement)obj
393                                      ), memory.getClassElement ());
394         }
395     }
396
397     /** Collection of class.
398     */

399     static class Class extends Member {
400         private static final ClassElement[] EMPTY = new ClassElement[0];
401
402         static final long serialVersionUID =3206093459760846163L;
403         /** @param ce class element memory impl to work in
404         */

405         public Class (ClassElement.Memory ce) {
406             super (ce, ElementProperties.PROP_CLASSES, EMPTY);
407         }
408         
409         public MemberElement find(Identifier name, Type[] types) {
410             if (array == null)
411                 return null;
412
413             Iterator it = array.iterator ();
414             while (it.hasNext ()) {
415                 ClassElement ce = (ClassElement)it.next ();
416                 Identifier cname = ce.getName();
417                 if (name.getFullName().equals(cname.getFullName())) {
418                     return ce;
419                 } else if (name.getName().equals(cname.getName())) {
420                     String JavaDoc fname = name.getFullName();
421                     if (fname.equals(name.getName()))
422                         return ce;
423                 }
424             }
425             // nothing found
426
return null;
427         }
428
429         /** Clones the object.
430         * @param obj object to clone
431         * @return cloned object
432         */

433         protected Object JavaDoc clone (Object JavaDoc obj) {
434             ClassElement.Memory ceMem = new ClassElement.Memory (
435                                             (ClassElement)obj
436                                         );
437             MemberElement newElement = new ClassElement(ceMem, memory.getClassElement());
438             ceMem.initialize((ClassElement)obj);
439             return newElement;
440         }
441     }
442
443 }
444
Popular Tags