|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun * Microsystems, Inc. All Rights Reserved. */ package org.openide.src; import java.io.Serializable; import java.util.*; /** Support class that manages set of objects and fires events * about its changes. * * @author Jaroslav Tulach */ abstract class MemoryCollection extends Object implements Serializable { /** array of objects */ LinkedList array; /** Object to fire info about changes to */ ClassElement.Memory memory; /** If set, new elements will be inserted before or after this one, depending on {@link #insertAfter } */ private Element insertionMark; /** Determines, if new elements are inserted before (false) or after (true) the insertionMark. If insertionMark is null elements are inserted at the end (true) or at the beginning (false) of the collection. */ private boolean insertAfter; /** name of property to fire */ private String propertyName; /** array template to return */ private Object[] template; static final long serialVersionUID =-9215370960397120952L; /** * @param memory memory element to fire changes to * @param propertyName name of property to fire when array changes * @param emptyArray emptyArray instance that provides the type of arrays * that should be returned by toArray method */ public MemoryCollection( ClassElement.Memory memory, String propertyName, Object[] emptyArray ) { this.memory = memory; this.propertyName = propertyName; this.template = emptyArray; } Collection makeClones(Object[] els) { Collection contents = array == null ? Collections.EMPTY_LIST : array; Set hashContents = new HashSet(contents.size() * 4 / 3 + 1); for (Iterator it = contents.iterator(); it.hasNext(); ) { Object e = it.next(); hashContents.add(e); } Collection result = new ArrayList(els.length); for (int i = 0; i < els.length; i++) { Object el = els[i]; if (!hashContents.contains(el)) { result.add(clone(el)); } else { result.add(el); } } return result; } Collection cloneElements(Object[] els) { Collection n = new ArrayList(els.length); for (int i = 0; i < els.length; i++) { n.add(clone(els[i])); } return n; } protected abstract Object clone(Object el); /** Changes the content of this object. * @param arr array of objects to change * @param action the action to do */ public void change (Object[] arr, int action) { Collection data; switch (action) { case ClassElement.Impl.ADD: data = cloneElements(arr); break; case ClassElement.Impl.REMOVE: data = Arrays.asList(arr); break; case ClassElement.Impl.SET: data = makeClones(arr); break; default: return; } change (data, action); } /** Changes the content of this object. * @param c collection of objects to change * @param action the action to do */ protected void change (Collection c, int action) { boolean anChange; switch (action) { case ClassElement.Impl.ADD: anChange = c.size () > 0; if (array != null) { if (insertionMark != null) { int index = array.indexOf(insertionMark); if (index == -1) { insertionMark = null; index = array.size(); } else if (insertAfter) { index++; } array.addAll(index, c); } else { array.addAll (c); } break; } // fall thru to initialize the array case ClassElement.Impl.SET: // PENDING: better change detection; currently any SET operation will fire change. anChange = c.size () > 0 || (array != null && array.size () > 0); array = new LinkedList (c); insertionMark = null; break; case ClassElement.Impl.REMOVE: { Element newMark = null; if (insertionMark != null && c.contains(insertionMark)) { Set removing = new HashSet(c.size() * 4 / 3); removing.addAll(c); int markIndex = array.indexOf(insertionMark); if (markIndex == -1) { insertionMark = null; } else { ListIterator it = array.listIterator(markIndex); while (it.hasNext()) { Object x = it.next(); if (!removing.contains(x)) { newMark = (Element)x; insertAfter = false; break; } } if (newMark == null) { it = array.listIterator(markIndex); while (it.hasPrevious()) { Object x = it.previous(); if (!removing.contains(x)) { newMark = (Element)x; insertAfter = true; break; } } } } insertionMark = newMark; } anChange = array != null && array.removeAll (c); break; } default: // illegal argument in internal implementation throw new InternalError (); } if (anChange) { // do not construct array values if not necessary memory.firePropertyChange (propertyName, null, null); } } /** Access to the array. * @return array of objects contained here */ public Object[] toArray () { if (array == null) { return template; } else { return array.toArray (template); } } void markCurrent(Element el, boolean after) { insertionMark = el; insertAfter = after; } static final class Interface extends MemoryCollection { Interface(ClassElement.Memory memory) { super(memory, ElementProperties.PROP_INTERFACES, new Identifier[0]); } Collection makeClones(Object[] arr) { return Arrays.asList(arr); } Collection cloneElements(Object[] arr) { return Arrays.asList(arr); } protected Object clone(Object o) { // interfaces are immutable... return o; } } /** Special collection for initializers. Provides declaringClass field. */ static final class Initializer extends MemoryCollection { private static final InitializerElement[] EMPTY = new InitializerElement[0]; static final long serialVersionUID =5715072242254795093L; /** * @param memory memory element to fire changes to * @param propertyName name of property to fire when array changes * @param emptyArray emptyArray instance that provides the type of arrays * that should be returned by toArray method */ public Initializer ( ClassElement.Memory memory ) { super (memory, ElementProperties.PROP_INITIALIZERS, EMPTY); } protected Object clone(Object el) { return new InitializerElement( new InitializerElement.Memory((InitializerElement)el), memory.getClassElement()); } } /** Collection for members. Assignes to each class its * members. */ static abstract class Member extends MemoryCollection { static final long serialVersionUID =7875426480834524238L; /** * @param memory memory element to fire changes to * @param propertyName name of property to fire when array changes * @param emptyArray emptyArray instance that provides the type of arrays * that should be returned by toArray method */ public Member ( ClassElement.Memory memory, String propertyName, Object[] emptyArray ) { super (memory, propertyName, emptyArray); } /** Find method that looks in member elements * @param id the indetifier (or null) * @param types array of types to test (or null) * @return the element or null */ public MemberElement find (Identifier id, Type[] types) { if (array == null) return null; Iterator it = array.iterator (); while (it.hasNext ()) { MemberElement me = (MemberElement)it.next (); if ( (id == null || id.equals(me.getName ())) && // types can be non-null only for Method or Constructor Elements (types == null || equalTypes (types, me)) ) { // found element return me; } } // nothing found return null; } /** Copares given types to types of the element. * The element must be ConstructorElement * * @param types the types * @param el the element * @return true if types are equal */ private static boolean equalTypes (Type[] types, MemberElement el) { // can be called only for ConstructorElement MethodParameter[] test = ((ConstructorElement)el).getParameters (); // number if (test.length != types.length) return false; int l = test.length; for (int i = 0; i < l; i++) { if (!test[i].getType().equals(types[i])) return false; } return true; } } /** Collection for members. Assignes to each class its * members. */ static class Constructor extends Member { private static final ConstructorElement[] EMPTY = new ConstructorElement[0]; static final long serialVersionUID =4314343816469864217L; /** @param ce class element memory impl to work in */ public Constructor (ClassElement.Memory ce) { super (ce, ElementProperties.PROP_CONSTRUCTORS, EMPTY); } /** Clones the object. * @param obj object to clone * @return cloned object */ protected Object clone (Object obj) { ConstructorElement.Memory m = new ConstructorElement.Memory ((ConstructorElement)obj); Identifier id = memory.getName(); if (id != null) { m.setName(Identifier.create(id.getName())); } return new ConstructorElement(m, memory.getClassElement()); } } /** Collection for methods. */ static class Method extends Member { private static final MethodElement[] EMPTY = new MethodElement[0]; static final long serialVersionUID =-745714645316747109L; /** @param ce class element memory impl to work in */ public Method (ClassElement.Memory ce) { super (ce, ElementProperties.PROP_METHODS, EMPTY); } /** Clones the object. * @param obj object to clone * @return cloned object */ protected Object clone (Object obj) { return new MethodElement (new MethodElement.Memory ( (MethodElement)obj ), memory.getClassElement ()); } } /** Collection of fields. */ static class Field extends Member { private static final FieldElement[] EMPTY = new FieldElement[0]; static final long serialVersionUID =5747776340409139399L; /** @param ce class element memory impl to work in */ public Field (ClassElement.Memory ce) { super (ce, ElementProperties.PROP_FIELDS, EMPTY); } /** Clones the object. * @param obj object to clone * @return cloned object */ protected Object clone (Object obj) { return new FieldElement (new FieldElement.Memory ( (FieldElement)obj ), memory.getClassElement ()); } } /** Collection of class. */ static class Class extends Member { private static final ClassElement[] EMPTY = new ClassElement[0]; static final long serialVersionUID =3206093459760846163L; /** @param ce class element memory impl to work in */ public Class (ClassElement.Memory ce) { super (ce, ElementProperties.PROP_CLASSES, EMPTY); } public MemberElement find(Identifier name, Type[] types) { if (array == null) return null; Iterator it = array.iterator (); while (it.hasNext ()) { ClassElement ce = (ClassElement)it.next (); Identifier cname = ce.getName(); if (name.getFullName().equals(cname.getFullName())) { return ce; } else if (name.getName().equals(cname.getName())) { String fname = name.getFullName(); if (fname.equals(name.getName())) return ce; } } // nothing found return null; } /** Clones the object. * @param obj object to clone * @return cloned object */ protected Object clone (Object obj) { ClassElement.Memory ceMem = new ClassElement.Memory ( (ClassElement)obj ); MemberElement newElement = new ClassElement(ceMem, memory.getClassElement()); ceMem.initialize((ClassElement)obj); return newElement; } } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.