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.netbeans.modules.java.bridge;

import java.lang.ref.WeakReference;
import java.util.*;
import javax.jmi.reflect.InvalidObjectException;
import javax.jmi.reflect.RefObject;
import org.netbeans.api.mdr.events.AttributeEvent;
import org.netbeans.api.mdr.events.MDRChangeEvent;
import org.netbeans.api.mdr.events.MDRChangeSource;
import org.netbeans.jmi.javamodel.*;
import org.netbeans.modules.javacore.JMManager;
import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
import org.openide.ErrorManager;
import org.openide.src.Element;
import org.openide.src.*;
import org.openide.src.Type;

abstract class ObjectsCollection {
    
    static int POS_VAL_NONE = -1;
    static int POS_VAL_FIELD = 0;
    static int POS_VAL_INITIALIZER = 1;
    static int POS_VAL_CONSTRUCTOR = 2;    
    static int POS_VAL_METHOD = 3;
    static int POS_VAL_CLASS = 4;
    
    static final Type[] NO_TYPES = new Type[0];
    
    private WeakHashMap cache = new WeakHashMap ();
    
    protected FeaturesCollection members;
    
    // ..........................................................................
    
    public ObjectsCollection(FeaturesCollection members) {
        this.members = members;
    }

    public abstract RefObject createFeature (RefObject parent, Element elem);
    
    public abstract Element createElement (RefObject javaElement);
    
    public abstract Element[] getEmptyArray ();
    
    public abstract String getPropertyName ();
    
    public abstract boolean isOfType (RefObject feature);
    
    protected Element cachedElement (RefObject refObject) { // [PENDING] synchronization
        Element elem;
        WeakReference ref = (WeakReference) cache.get (refObject);        

        if (ref != null) {
            elem = (Element) ref.get();
            if (elem != null)
                return elem;
        }
        members.repository.beginTrans (false);
        try {
            members.parentImpl.setClassPath();
            elem = createElement (refObject);
            cache.put (refObject, new WeakReference (elem));
            return elem;
        } finally {
            members.repository.endTrans (false);
        }
    }
    
    public List getFeatures () {
        return members.javaClass.getFeatures ();
    }
    
    public abstract boolean matches (Element elem, RefObject f);

    public int getPositionalValue () {
        return POS_VAL_NONE;
    }
    
    public boolean isClassMember () { // should be abstract
        return true;
    }
    
    public Element [] getElements () {
        ArrayList result = new ArrayList ();
        members.repository.beginTrans (false);
        try {
            members.parentImpl.setClassPath();
            List features = getFeatures ();
            if (features != null) {
                for (Iterator iter = features.iterator (); iter.hasNext ();) {
                    RefObject feature = (RefObject) iter.next ();
                    if (isOfType (feature)) {
                        result.add (cachedElement (feature));
                    }
                }
            }
            return (Element []) result.toArray (getEmptyArray ());
        } catch (InvalidObjectException e) {
            return getEmptyArray ();
        } finally {
            members.repository.endTrans (false);
        }
    }

    private Element [] getMembers () {
        List features = getFeatures ();
        int size = features.size ();
        Element [] result = new Element [size];
        Iterator iter = features.iterator ();
        for (int x = 0; x < size; x++) {
            RefObject feature = (RefObject) iter.next ();
            result [x] = cachedMember (feature);
        }
        return result;
    }

    private Element cachedMember (RefObject f) {
        if (f instanceof JavaClass) {
            return ((ClassElementImpl) members.parentImpl).innerClasses.cachedElement (f);
        } else if (f instanceof Method) {
            return ((ClassElementImpl) members.parentImpl).methods.cachedElement (f);
        } else if (f instanceof Constructor) {
            return ((ClassElementImpl) members.parentImpl).constructors.cachedElement (f);
        } else if (f instanceof Field) {
            return ((ClassElementImpl) members.parentImpl).fields.cachedElement (f);
        } else if (f instanceof Initializer) {
            return ((ClassElementImpl) members.parentImpl).initializers.cachedElement (f);
        }
        throw new RuntimeException ();
    }
    
    public void changeMembers(Element[] items, int operation) throws SourceException {
        
        for (int x = 0; x < items.length; x++)
            if (items [x] == null)
                throw new NullPointerException ("null element in " + items.getClass ().getName ()); // NOI18N
        
        switch (operation) {
            case ClassElementImpl.ADD:
                addMembers(items);
                break;
            case ClassElementImpl.REMOVE:
                removeMembers(items);
                break;
            case ClassElementImpl.SET:
                setMembers(items);
                break;
            default:
                throw new RuntimeException("Unknown/unsupported operation: " + operation); // NOI18N
        }
    }
    
    protected void addMembers (Element[] items) throws SourceException {
        int i;
        if (items.length == 0)
            return;
        
        boolean veto = isClassMember () && (
            members.parentImpl.hasVetoableListeners (getPropertyName ()) ||
            members.parentImpl.hasVetoableListeners (ElementProperties.PROP_MEMBERS));
        Element [] oldElems = null;
        Element [] oldMembers = null;
        
        members.repository.beginTrans (true);
        boolean failed = true;
        try {            
            members.parentImpl.setClassPath();
            
            if (veto) {
                oldElems = getElements ();
                oldMembers = getMembers ();
            }
            
            int index = findAddPosition (getPositionalValue ());            
            ListIterator listIter = getFeatures ().listIterator (index);
            for (i = 0; i < items.length; i++) {
                Object feature = createFeature (members.javaClass, items[i]);                
                listIter.add (feature);
            }

            if (veto) {
                MultiPropertyChangeEvent evt;
                int [] indexes = new int [items.length];
                List added = Arrays.asList (items);
                // PROP_MEMBERS
                Element [] newMembers = getMembers ();
                for (int x = 0; x < items.length; x++) {
                    indexes [x] = x + index;
                }
                evt = new MultiPropertyChangeEvent(
                    members.parentImpl.getElement (), ElementProperties.PROP_MEMBERS, oldMembers, newMembers);
                evt.makeInsertion (added, indexes);
                members.parentImpl.checkVetoablePropertyChange (evt);
                // PROP_XXXS (XXX = feature name)
                Element [] newElems = getElements ();                
                indexes = new int [items.length];
                for (int x = 0; x < items.length; x++) {
                    indexes [x] = x + oldElems.length;
                }
                evt = new MultiPropertyChangeEvent(
                    members.parentImpl.getElement (), getPropertyName(), oldElems, newElems);
                evt.makeInsertion (added, indexes);
                members.parentImpl.checkVetoablePropertyChange (evt);
            }
            
            failed = false;
        } catch (InvalidObjectException e) {
            members.parentImpl.throwIsInvalid ();
        } finally {
            members.repository.endTrans (failed);
        }
    }
    
    protected void removeMembers (Element[] items) throws SourceException {                
        if ((items == null) || (items.length == 0))
            return;
        
        boolean veto = isClassMember () && (
            members.parentImpl.hasVetoableListeners (getPropertyName ()) ||
            members.parentImpl.hasVetoableListeners (ElementProperties.PROP_MEMBERS));
        Element [] oldElems = null;
        Element [] oldMembers = null;
        int elemsCounter, membersCounter, removedCounter;
        int [] elemsIndexes = null;
        int [] membersIndexes = null;
        
        boolean failed = true;
        members.repository.beginTrans (true);
        try {
            members.parentImpl.setClassPath();
            if (veto) {
                oldElems = getElements ();
                oldMembers = getMembers ();
                elemsIndexes = new int [items.length];
                membersIndexes = new int [items.length];
            }
            
            String name;
            List list;
            List features = getFeatures ();
            HashMap map = new HashMap ();
            for (int x = 0; x < items.length; x++) {
                if (items [x] instanceof MemberElement) {
                    name = ((MemberElement) items [x]).getName ().getName ();
                } else if (items [x] instanceof InitializerElement) {
                    name = "initializer"; // NOI18N
                } else { // ImportElement
                    name = ((ImportElement) items[x]).getImport ().getIdentifier ().getFullName ();
                }
                
                list = (List) map.get (name);
                if (list == null) {
                    list = new LinkedList ();
                    map.put (name, list);
                }
                list.add (items [x]);
            }
            ListIterator iter = features.listIterator ();
            membersCounter = elemsCounter = removedCounter = 0;
            while (iter.hasNext ()) {
                RefObject f = (RefObject) iter.next ();
                if (isOfType (f)) {
                    if (f instanceof Constructor) {
                        name = ((JavaClass) ((Constructor) f).getDeclaringClass()).getSimpleName ();
                    } else if (f instanceof Initializer)
                        name = "initializer"; // NOI18N
                    else if (f instanceof org.netbeans.jmi.javamodel.Import) {
                        name = ((org.netbeans.jmi.javamodel.Import) f).getName ();
                        if (name.endsWith (".*")) { // NOI18N
                            name = name.substring (0, name.length() - 2);
                        }
                    } else if (f instanceof JavaClass) {
                        name = ((JavaClass) f).getSimpleName();
                    } else {
                        name = ((Feature) f).getName ();
                    }
                    list = (List) map.get (name);
                    if (list != null) {
                        Iterator iter2 = list.listIterator ();
                        while (iter2.hasNext ()) {
                            Element elem = (Element) iter2.next ();
                            if (matches (elem, f)) {
                                iter2.remove ();
                                iter.remove();
                                f.refDelete ();
                                if (list.size () == 0) {
                                    map.remove (name);
                                }
                                if (veto) {
                                    membersIndexes [removedCounter] = membersCounter;
                                    elemsIndexes [removedCounter] = elemsCounter;
                                }
                                removedCounter ++;
                                break;
                            } // if (matches (...))
                        } // while
                    } // if (list != null)
                    elemsCounter ++;
                } // if (isOfType (f))
                membersCounter ++;
            } // while
            if (map.size () > 0) {
                throw new SourceException ("An element to be removed not found."); // NOI18N
            }
            
            if (veto) {
                MultiPropertyChangeEvent evt;
                List removed = Arrays.asList (items);
                // PROP_MEMBERS
                Element [] newMembers = getMembers ();                
                evt = new MultiPropertyChangeEvent(
                    members.parentImpl.getElement (), ElementProperties.PROP_MEMBERS, oldMembers, newMembers);
                evt.makeRemoval (removed, membersIndexes);
                members.parentImpl.checkVetoablePropertyChange (evt);
                // PROP_XXXS (XXX = feature name)
                Element [] newElems = getElements ();                
                evt = new MultiPropertyChangeEvent(
                    members.parentImpl.getElement (), getPropertyName(), oldElems, newElems);
                evt.makeInsertion (removed, elemsIndexes);
                members.parentImpl.checkVetoablePropertyChange (evt);
            }
            
            failed = false;
        } catch (InvalidObjectException e) {
            members.parentImpl.throwIsInvalid ();
        } finally {
            members.repository.endTrans (failed);
        }
    }
    
    protected void setMembers (Element[] items) throws SourceException {
        boolean veto = isClassMember () && (
            members.parentImpl.hasVetoableListeners (getPropertyName ()) ||
            members.parentImpl.hasVetoableListeners (ElementProperties.PROP_MEMBERS));
        Element [] oldElems = null;
        Element [] oldMembers = null;
        
        boolean failed = true;
        members.repository.beginTrans (true);
        try {
            members.parentImpl.setClassPath();
            if (veto) {
                oldElems = getElements ();
                oldMembers = getMembers ();
            }
            
            int [] pos;
            List features = getFeatures ();        
            int size = features.size ();            
            Iterator iter = features.iterator ();
            List list = new LinkedList ();
            int posValue = getPositionalValue ();
            int maxPrevValue = -1;
            int addIndex = -1;
            List setFeatures = new LinkedList ();
            List removedFeatures = new LinkedList ();
            
            for (int i = 0; i < size; i++) {
                RefObject feature = (RefObject) iter.next ();
                int val = getPositionalValue (feature);
                if ((val <= posValue) && (val > maxPrevValue))
                    maxPrevValue = val;
                if (val == maxPrevValue)
                    addIndex = i;
                if (val == posValue)
                    list.add (new Integer (i));
            } // for

            int size2 = list.size ();            
            pos = new int [size2];
            iter = list.iterator ();
            for (int i = 0; i < size2; i++) {
                pos [i] = ((Integer) iter.next ()).intValue ();
            }
                
            ListIterator listIterator = features.listIterator ();
            int counter = 0;
            int numToBeSet = Math.min (size2, items.length);
            if (numToBeSet == 0) {
                // go to add position
                for (int x = 0; x <= addIndex; x++)
                    listIterator.next ();
            } else {
                // do SET
                for (int x = 0; x <= pos[numToBeSet-1]; x++) {
                    RefObject refObj = (RefObject) listIterator.next ();
                    if (pos[counter] == x) {
                        listIterator.set (
                            createFeature (members.javaClass, items[counter])
                        );
                        refObj.refDelete ();
                        if (veto) {
                            setFeatures.add (cachedElement (refObj));
                        }
                        counter++;
                    }
                    addIndex++;
                } // for
            }            
            if (numToBeSet < items.length) {
                // do ADD
                for (int x = numToBeSet; x < items.length; x++)
                    listIterator.add (createFeature (members.javaClass, items[x]));
            } else if (numToBeSet < size2) {
                // do REMOVE
                for (int x = pos[numToBeSet-1] + 1; x <= pos[size2-1]; x++) {
                    RefObject refObj = (RefObject) listIterator.next ();
                    if (pos[counter] == x) {
                        listIterator.remove ();
                        refObj.refDelete ();
                        if (veto) {
                            removedFeatures.add (cachedElement (refObj));
                        }
                        counter++;
                    }
                } // for                
            }

            if (veto) {
                MultiPropertyChangeEvent evt;
                int [] indexes;
                int [] setIndexes, removeIndexes, addIndexes = null;
                setIndexes = removeIndexes = addIndexes = new int [0];
                List affectedIndexes = new LinkedList ();
                Element source = members.parentImpl.getElement ();
                List evtElems = new LinkedList ();
                List evtMembers = new LinkedList ();
                Element [] newMembers = getMembers ();
                Element [] newElems = getElements ();                
                                
                if (numToBeSet > 0) {
                    List curr = new LinkedList ();
                    setIndexes = new int [numToBeSet];
                    indexes = new int [numToBeSet];
                    for (int x = 0; x < numToBeSet; x++) {
                        curr.add (items [x]);
                        setIndexes [x] = pos [x];
                    }
                    evt = new MultiPropertyChangeEvent(
                        source, ElementProperties.PROP_MEMBERS, oldMembers, newMembers);
                    evt.makeReplacement (setFeatures, curr, setIndexes);
                    evtMembers.add (evt);
                    for (int x = 0; x < numToBeSet; x++) {
                        indexes [x] = x;
                    }
                    evt = new MultiPropertyChangeEvent(
                        source, getPropertyName (), oldElems, newElems);
                    evt.makeReplacement (setFeatures, curr, indexes);
                    evtElems.add (evt);
                }
                
                addIndex = addIndex + 1;
                if (numToBeSet < items.length) {
                    List inserted = new LinkedList ();
                    indexes = new int [items.length - numToBeSet];
                    addIndexes = new int [items.length - numToBeSet];
                    for (int x = numToBeSet; x < items.length; x++) {
                        inserted.add (items [x]);
                        addIndexes [x - numToBeSet] = addIndex + x - numToBeSet;
                    }
                    evt = new MultiPropertyChangeEvent(
                        source, ElementProperties.PROP_MEMBERS, oldMembers, newMembers);
                    evt.makeInsertion (inserted, addIndexes);
                    evtMembers.add (evt);
                    for (int x = 0; x < items.length - numToBeSet; x++) {
                        indexes [x] = x;
                    }
                    evt = new MultiPropertyChangeEvent(
                        source, getPropertyName (), oldElems, newElems);
                    evt.makeInsertion (inserted, indexes);
                    evtElems.add (evt);
                } else if (numToBeSet < size2) {
                    indexes = new int [size2 - numToBeSet];
                    removeIndexes = new int [size2 - numToBeSet];
                    for (int x = 0; x < size2 - numToBeSet; x++) {
                        removeIndexes [x] = pos [numToBeSet + x];
                    }
                    evt = new MultiPropertyChangeEvent(
                        source, ElementProperties.PROP_MEMBERS, oldMembers, newMembers);
                    evt.makeRemoval (removedFeatures, removeIndexes);
                    evtMembers.add (evt);
                    for (int x = 0; x < size2 - numToBeSet; x++) {
                        indexes [x] = numToBeSet + x;
                    }
                    evt = new MultiPropertyChangeEvent(
                        source, getPropertyName (), oldElems, newElems);
                    evt.makeRemoval (removedFeatures, indexes);
                    evtElems.add (evt);
                }
                
                indexes = new int [setIndexes.length + addIndexes.length + removeIndexes.length];
                int i = 0;                
                for (int x = 0; x < setIndexes.length; x++) {
                    indexes [i] = setIndexes [x];
                    i++;
                }
                for (int x = 0; x < addIndexes.length; x++) {
                    indexes [i] = addIndexes [x];
                    i++;
                }
                for (int x = 0; x < removeIndexes.length; x++) {
                    indexes [i] = removeIndexes [x];
                    i++;
                }                
                evt = new MultiPropertyChangeEvent(
                    source, ElementProperties.PROP_MEMBERS, oldMembers, newMembers);
                evt.makeCompound (evtMembers, indexes);
                members.parentImpl.checkVetoablePropertyChange (evt);
                
                for (int x = 0; x < indexes.length; x++)
                    indexes [x] = 0;
                evt = new MultiPropertyChangeEvent(
                    source, getPropertyName (), oldElems, newElems);
                evt.makeCompound (evtElems, indexes);
                members.parentImpl.checkVetoablePropertyChange (evt);
            }
            
            failed = false;
        } catch (InvalidObjectException e) {
            members.parentImpl.throwIsInvalid ();
        } finally {
            members.repository.endTrans (failed);
        }
    }

    private int findAddPosition (int posValue) {
        List features = getFeatures ();        
        int size = features.size ();
        if (size == 0)
            return 0;
        
        org.netbeans.jmi.javamodel.Element elems[] = new org.netbeans.jmi.javamodel.Element[size];
        Iterator iter = features.iterator ();
        int maxPrevValue = -1;
        int index = -1;
        for (int i = 0; i < size; i++) {
            org.netbeans.jmi.javamodel.Element feature = (org.netbeans.jmi.javamodel.Element) iter.next ();
            elems[i] = feature;
            int val = getPositionalValue (feature);
            if ((val <= posValue) && (val > maxPrevValue))
                maxPrevValue = val;
            if (val == maxPrevValue)
                index = i;
        } // for
        
//        JavaMetamodel manager = JavaMetamodel.getManager();
//        while (index >= 0 && manager.isElementGuarded(elems[index])) {
//            index--;
//        }
        
        return index + 1;
    }
    
    private int getPositionalValue (RefObject feature) { 
        if (feature instanceof JavaClass) {
            return POS_VAL_CLASS;
        } else if (feature instanceof Method) {
            return POS_VAL_METHOD;
        } else if (feature instanceof Constructor) {
            return POS_VAL_CONSTRUCTOR;
        } else if (feature instanceof Field) {
            return POS_VAL_FIELD;
        } else if (feature instanceof Initializer) {
            return POS_VAL_INITIALIZER;
        }
        return POS_VAL_NONE;        
    }
    
    // ..........................................................................
    // ..........................................................................

    static class FeaturesListener extends ElementImpl.ElementListener {
    
        static Element [] NO_ELEMENTS = new Element [0];
        
        protected ArrayList features;
        protected boolean fireMembers = true;
        
        FeaturesListener (ElementImpl impl) {
            super (impl);
        }

        public void connect () {
            if (REGISTER_LISTENER) {
                try {
                    ((MDRChangeSource) javaElement).addListener (this);
                    features = new ArrayList ();
                    List classFeatures = ((JavaClass) javaElement).getFeatures ();
                    if (classFeatures != null) {
                        features.addAll (classFeatures);
                    }
                } catch (InvalidObjectException e) {
                    // [PENDING]
                }
            }
        }                
        
        private String elemName (RefObject elem) {
            if (elem == null)
                return "null"; // NOI18N
            try {
                return ((org.netbeans.jmi.javamodel.NamedElement) elem).getName ();
            } catch (Exception e) {
                return "deleted"; // NOI18N
            }
        }

        protected boolean isWatchedAttribute (AttributeEvent ev) {
            return ev.getAttributeName ().equals ("contents"); // NOI18N
        }
        
        public void doChange(MDRChangeEvent event) {
            super.doChange (event);
            if ((event instanceof AttributeEvent) && (isWatchedAttribute((AttributeEvent) event))) {
                AttributeEvent attribEvent = (AttributeEvent) event;

                RefObject prev = (RefObject) attribEvent.getOldElement ();
                RefObject curr = (RefObject) attribEvent.getNewElement ();
        
                //System.out.println("FeaturesListener: " + assocEvent.getPosition () + " " + assocEvent.getEndName () + " " + 
                    //elemName (fixed) + " " + elemName (prev) + " " + elemName (curr) + " " + hashCode ());
                
                if (event.isOfType (AttributeEvent.EVENT_ATTRIBUTE_SET)) {
                    doSet (prev, curr);
                } else if (event.isOfType (AttributeEvent.EVENT_ATTRIBUTE_REMOVE)) {                        
                    doRemove (prev);
                } else { // EVENT_ASSOCIATION_ADD
                    doAdd (attribEvent.getPosition (), curr);
                }

            } // if
        }

        public void doSet (RefObject oldFeature, RefObject feature) {            
            // System.out.println("doSet: " + elemName (feature));            
            
            ObjectsCollection coll = getFeatureCollection (feature);
            if (coll == null)
                return;
            int position = -1;
            ArrayList temp = new ArrayList ();
            ArrayList allTemp = new ArrayList ();
            Iterator iter = features.iterator ();
            int size = features.size ();
            int index = -1;
            for (int x = 0; x < size; x++) {
                RefObject f = (RefObject) iter.next ();
                Element elem = cachedElement (f);
                if (elem != null) {
                    allTemp.add (elem);
                    if (coll.isOfType (f)) {
                        temp.add (elem);
                    }                
                }
                if (f.equals (oldFeature)) {
                    index = temp.size () - 1;
                    position = x;
                }
            }
            
            if (index == -1) {
                JMManager.getLog().log(ErrorManager.INFORMATIONAL, "Bad index: " + elemName (feature)); // NOI18N
            }
            
            Element oldElem = coll.cachedElement ((RefObject) features.set (position, feature));
            Element newElem = (Element) coll.cachedElement (feature);
            
            if ((oldElem == null) || (newElem == null)) {
                // can occure in case of TopClassesCollection when related classifiers contain a non JavaClass element
                return;
            }
            
            Object old = temp.toArray (NO_ELEMENTS);
            List orig = new LinkedList ();
            List replacement = new LinkedList ();
            orig.add (oldElem);
            replacement.add (newElem);
            temp.set (index, newElem);
            Object now = temp.toArray (NO_ELEMENTS);
            
            if (fireMembers) {
                Element [] allOld = (Element []) allTemp.toArray (NO_ELEMENTS);
                allTemp.set (position, newElem);
                Element [] allNew = (Element []) allTemp.toArray (NO_ELEMENTS);
                MultiPropertyChangeEvent mEvt = new MultiPropertyChangeEvent(
                    impl.getElement (), ElementProperties.PROP_MEMBERS, allOld, allNew);
                mEvt.makeReplacement(orig, replacement, new int [] {position});
                
                impl.fireOwnPropertyChange (mEvt);
            }
            
            MultiPropertyChangeEvent evt = new MultiPropertyChangeEvent(
                impl.getElement (), coll.getPropertyName(), old, now);
            evt.makeReplacement(orig, replacement, new int [] {index});
            impl.fireOwnPropertyChange (evt);
            impl.notifyConnectionSet (oldElem, newElem);
        }
        
        public void doAdd (int position, RefObject feature) {
            
            // System.out.println("doAdd: " + elemName (feature) + " " + position);
            
            // [PENDING]
            if (position == -1)
                position = features.size ();
            ObjectsCollection coll = getFeatureCollection (feature);
            if (coll == null)
                return;
            ArrayList temp = new ArrayList ();
            ArrayList allTemp = new ArrayList ();
            Iterator iter = features.iterator ();
            int size = features.size ();
            int index = -1;
            for (int x = 0; x < size; x++) {
                RefObject f = (RefObject) iter.next ();
                Element elem = cachedElement (f);
                if (elem != null) {
                    allTemp.add (elem);
                    if (coll.isOfType (f)) {
                        temp.add (elem);
                    }
                }
                if (x == position) {
                    index = temp.size ();
                }
            }
            if (index == -1)
                index = temp.size ();
            
            features.add (position, feature);
            Element addedElem = (Element) coll.cachedElement (feature);
            
            if (addedElem == null) {
                // can occure in case of TopClassesCollection when related classifiers contain a non JavaClass element
                return;
            }
            
            Object old = temp.toArray (NO_ELEMENTS);
            List added = new LinkedList ();
            added.add (addedElem);
            temp.add (index, addedElem);
            Object newElems = temp.toArray (NO_ELEMENTS);
            
            if (fireMembers) {
                Element [] allOld = (Element []) allTemp.toArray (NO_ELEMENTS);
                allTemp.add (position, addedElem);
                Element [] allNew = (Element []) allTemp.toArray (NO_ELEMENTS);
                MultiPropertyChangeEvent mEvt = new MultiPropertyChangeEvent(
                    impl.getElement (), ElementProperties.PROP_MEMBERS, allOld, allNew);
                mEvt.makeInsertion(added, new int [] {position});
                
                impl.fireOwnPropertyChange (mEvt);
            }
            
            MultiPropertyChangeEvent evt = new MultiPropertyChangeEvent(
                impl.getElement (), coll.getPropertyName(), old, newElems);
            evt.makeInsertion(added, new int [] {index});
            impl.fireOwnPropertyChange (evt);
            impl.notifyConnectionAdd (addedElem);
        }
        
        public void doRemove (RefObject member) {
            // System.out.println("doRemove: " + elemName (member) + hashCode ());
            
            int position = -1;
            ObjectsCollection coll = getFeatureCollection (member);
            if (coll == null)
                return;
            ArrayList temp = new ArrayList ();
            ArrayList allTemp = new ArrayList ();
            
            Iterator iter = features.iterator ();
            int size = features.size ();
            int index = -1;
            for (int x = 0; x < size; x++) {
                RefObject feature = (RefObject) iter.next ();
                Element elem = cachedElement (feature);
                if (elem != null) {
                    allTemp.add (elem);
                    if (coll.isOfType (feature)) {
                        temp.add (elem);
                    }
                }
                if (member.equals (feature)) {
                    index = temp.size () - 1;
                    position = x;
                }
            }
            
            if (position == -1) {
                JMManager.getLog().log(ErrorManager.INFORMATIONAL, "Bad index: " + elemName (member)); // NOI18N
                return; // [PENDING]
            }
            
            features.remove (position);
            
            if (cachedElement(member) == null) {
                // can occure in case of TopClassesCollection when related classifiers contain a non JavaClass element
                return;
            }
            
            Element [] old = (Element []) temp.toArray (NO_ELEMENTS);
            Element o = (Element) temp.remove (index);
            List removed = new LinkedList ();
            removed.add (o);
            Element [] newElems = (Element []) temp.toArray (NO_ELEMENTS);
              
            //System.out.println("\t" + old.length);
            //System.out.print("\t");
            //for (int x = 0; x < newElems.length; x++)
                //System.out.print(((MemberElement) newElems[x]).getName () + "  ");
            //System.out.println("");
            //System.out.println("\t" + index);
            
            if (fireMembers) {
                Element [] allOld = (Element []) allTemp.toArray (NO_ELEMENTS);
                allTemp.remove (position);
                Element [] allNew = (Element []) allTemp.toArray (NO_ELEMENTS);
                MultiPropertyChangeEvent mEvt = new MultiPropertyChangeEvent(
                    impl.getElement (), ElementProperties.PROP_MEMBERS, allOld, allNew);
                mEvt.makeRemoval(removed, new int [] {position});
                
                impl.fireOwnPropertyChange (mEvt);
            }
            
            MultiPropertyChangeEvent evt = new MultiPropertyChangeEvent(
                impl.getElement (), coll.getPropertyName(), old, newElems);
            evt.makeRemoval(removed, new int [] {index});

            impl.fireOwnPropertyChange (evt);
            impl.notifyConnectionRemove (o);
        }                
        
        public ObjectsCollection getFeatureCollection (RefObject feature) {
            if (feature instanceof JavaClass) {
                return ((ClassElementImpl) impl).innerClasses;
            } else if (feature instanceof Method) {
                return ((ClassElementImpl) impl).methods;
            } else if (feature instanceof Constructor) {
                return ((ClassElementImpl) impl).constructors;
            } else if (feature instanceof Field) {
                return ((ClassElementImpl) impl).fields;
            } else if (feature instanceof Initializer) {
                return ((ClassElementImpl) impl).initializers;
            }
            return null;
        }
        
        public Element cachedElement (RefObject f) {
            if (f instanceof JavaClass) {
                return ((ClassElementImpl) impl).innerClasses.cachedElement (f);
            } else if (f instanceof Method) {
                return ((ClassElementImpl) impl).methods.cachedElement (f);
            } else if (f instanceof Constructor) {
                return ((ClassElementImpl) impl).constructors.cachedElement (f);
            } else if (f instanceof Field) {
                return ((ClassElementImpl) impl).fields.cachedElement (f);
            } else if (f instanceof Initializer) {
                return ((ClassElementImpl) impl).initializers.cachedElement (f);
            }
            return null;
        }
    }
}
... 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.