alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

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

 

new blog posts

 

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.