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

package org.netbeans.modules.java.bridge;

/*
 *                 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.
 */

import java.beans.*;
import java.util.*;
import java.lang.reflect.Modifier;
import org.netbeans.api.mdr.events.AssociationEvent;
import org.netbeans.jmi.javamodel.ParameterizedType;

import org.openide.nodes.Node;
import org.openide.src.*;

import org.netbeans.api.mdr.events.*;

import javax.jmi.reflect.RefObject;
import javax.jmi.reflect.RefBaseObject;
import javax.jmi.reflect.InvalidObjectException;
import org.netbeans.jmi.javamodel.AnnotationType;

import org.netbeans.jmi.javamodel.JavaClass;
import org.netbeans.jmi.javamodel.ClassDefinition;
import org.netbeans.jmi.javamodel.Method;
import org.netbeans.jmi.javamodel.Constructor;
import org.netbeans.jmi.javamodel.Feature;
import org.netbeans.jmi.javamodel.Field;
import org.netbeans.jmi.javamodel.Initializer;
import org.netbeans.jmi.javamodel.Extends;
import org.netbeans.jmi.javamodel.Implements;
import org.netbeans.jmi.javamodel.MultipartId;
import org.netbeans.jmi.javamodel.TypeReference;
import org.netbeans.jmi.javamodel.JavaEnum;

/**
 * Models a class in a source - either a nested/local class, top-level class or an inner class.
 *
 * @author  Svatopluk Dedic
 * @version 0.1
 * @since 24/11/2000
 */
class ClassElementImpl extends MemberElementImpl implements ClassElement.Impl, ElementOrder {
    /** Uplink to the implementation of the source element. The link is made during
     * attaching the abstract Element to the implementation.
     */
    private SourceElementImpl       sourceImpl;
    
    /**
     * Reference to the enclosing element's implementation; the reference is identical
     * to getDeclaringImpl() if the class is an inner class, but it is different, if
     * the class is a nested or local class.
     */
    private ElementImpl             parentImpl;
        
    transient FieldsCollection        fields;
    
    transient MethodsCollection       methods;
    
    transient ConstructorsCollection  constructors;
    
    transient InitializersCollection  initializers;
    
    transient ClassesCollection       innerClasses;
    
    transient FeaturesCollection      members;    

    private static IdentifierArrayProperty    identSupport;
    
    private IdentContextSupport     identSupp;

    private static final long serialVersionUID = -7718381719188756697L;
    
    private ElementImpl.ElementListener classListener, featuresListener;
    
    // Construction
    ///////////////////////////////////////////////////////////////////////////////////
    
    static {
        // initialize flyweight property support.
        identSupport = new InterfaceSupport();
    }        
    
    ClassElementImpl(DefaultLangModel model, JavaClass javaClass) {                        
        super(model, javaClass);        
        init ();
    }
    
    public void connectListener () {
        classListener = new ClassListener (this);
        classListener.connect ();
        featuresListener = new ObjectsCollection.FeaturesListener (this);
        featuresListener.connect ();
    }
        
    private void init () {
        identSupp = new IdentContextSupport(37);        
        javadoc = new JavaDocImpl.Class(null, this);

        members = new FeaturesCollection (this);
        fields = new FieldsCollection (members);
        methods = new MethodsCollection (members);
        constructors = new ConstructorsCollection (members);
        initializers = new InitializersCollection (members);
        innerClasses = new ClassesCollection (members);
    }
    
    protected Identifier createName(String fullName) {
        String simpleName = fullName;
        int index = simpleName.lastIndexOf('.');
        
        if (index!=-1) {
            simpleName=simpleName.substring(index+1);
        }
        return Identifier.create(fullName,simpleName,Identifier.RESOLVED);
    }
    
    protected void createFromModel(Element model) throws SourceException {
        ClassElement c = (ClassElement)model;

        // PENDING: set these directly.
        super.createFromModel(model);
        setClassOrInterface(c.isClassOrInterface());
        setSuperclass(c.getSuperclass());

        // member elements need the Element already.
        changeInterfaces(c.getInterfaces(), ClassElement.Impl.ADD);
        changeInitializers(c.getInitializers(), ClassElement.Impl.ADD);
        
        changeFields(c.getFields(), ClassElement.Impl.ADD);
        changeConstructors(c.getConstructors(), ClassElement.Impl.ADD);
        changeMethods(c.getMethods(), ClassElement.Impl.ADD);
        changeClasses(c.getClasses(), ClassElement.Impl.ADD);
        
        setJavaDocText(c.getJavaDoc().getRawText(), true);
    }
    
    public JavaDoc.Class getJavaDoc() {
        updateJavadoc();
        return (JavaDoc.Class)javadoc;
    }
    
    public final void setParent(ElementImpl impl) {
        super.setParent(impl);
        if (impl instanceof SourceElementImpl) {
            sourceImpl = (SourceElementImpl)impl;
        }
    }
            
    // Public operations
    ///////////////////////////////////////////////////////////////////////////////////
    /*
    public final Node.Cookie getCookie(Class clazz) {
        Node.Cookie ret = super.getCookie(clazz);
        if (ret != null || sourceImpl == null)
            return ret;
        return sourceImpl.getCookie(clazz);
    }
     */

    // Getters
    ///////////////////////////////////////////////////////////////////////////////////
    /**
     * Returns true, iff the class is a proper class. False, if the element represents
     * an interface.
     * @return true, if representing a class.
     */
    public boolean isClassOrInterface() {
        try {
            return !((JavaClass) javaElement).isInterface ();
        } catch (InvalidObjectException e) {
            return false;
        }
    }
    
    public Identifier getName() {
        repository.beginTrans(false);
        try {
            setClassPath();
            return createName (typeToFullName((JavaClass) javaElement));
        } catch (InvalidObjectException e) {            
            return cachedName != null ? cachedName : Identifier.create ("");
        } finally {
            repository.endTrans(false);
        }
    }
    
    public int getModifiers () {
        repository.beginTrans(false);
        try {
            return super.getModifiers () & ~Modifier.INTERFACE;
        } catch (InvalidObjectException e) {
            return 0;
        } finally {
            repository.endTrans(false);
        }
    }
    
    public Identifier getSuperclass() {
        repository.beginTrans(false);
        try {
            setClassPath();
            JavaClass sup = ((JavaClass) javaElement).getSuperClass ();
            return sup != null ? createClassIdentifier (typeToFullName(sup)) : null;
        } catch (InvalidObjectException e) {
            return Identifier.create ("");
        } finally {
            repository.endTrans(false);
        }
    }
    
    public Identifier[] getInterfaces() {
        repository.beginTrans (false);
        try {
            setClassPath();
            Collection list = ((JavaClass) javaElement).getInterfaceNames ();
            Identifier [] superinterfaces = new Identifier [list.size ()];
            Iterator iter = list.iterator ();
            for (int x = 0; iter.hasNext (); x++) {
                superinterfaces [x] = createClassIdentifier ((MultipartId) iter.next ());
            }
            return superinterfaces;
        } catch (InvalidObjectException e) {
            return new Identifier[0];
        } finally {
            repository.endTrans (false);
        }
    }
    
    // Setters/changers
    ///////////////////////////////////////////////////////////////////////////////////

    /**
     * Sets the desired superclass. The implementation will attempt to check the
     * passed identifier and will attempt to preserve the semantic meaning of the
     * Identifier when updating the model.
     * @param superclass the identifier of the new superclass.
     * @throw SourceException if the source cannot be locked, veto on the property change is
     * issued, the superclass' identifier is not reachable or there's some I/O or race error
     * during the operation.
     */
    public void setSuperclass(Identifier superclass) throws SourceException {
        checkWritable();
        checkDocument();
        boolean failed = false;
        repository.beginTrans (true);
        try {
            setClassPath();
            superclass = resolveIdent(superclass);
            Identifier old = getSuperclass ();
            PropertyChangeEvent evt;
            
            if (superclass == old ||
                (superclass != null && old != null &&
                compareSourceIdentifiers(old, superclass))) {
                // no change at all.
                checkIsValid ();
                return;
            }
            evt = new PropertyChangeEvent(getElement(), PROP_SUPERCLASS,
                old, superclass
            );
            checkVetoablePropertyChange(evt);
            
            JavaClass superClass = null;
            if (superclass!=null)
                superClass=getClassDescriptor(superclass.getFullName());
            else
                superClass=getClassDescriptor(JAVA_LANG_OBJECT);
            ((JavaClass) javaElement).setSuperClass(superClass);
            failed = false;
        } catch (InvalidObjectException e) {
            throwIsInvalid ();
        } finally {
            repository.endTrans (failed);
        }
    } 
    
    public void fireSuperclassChange (Identifier oldValue, Identifier newValue) {
        if ((oldValue == newValue) ||
            (oldValue != null && newValue != null &&
            compareSourceIdentifiers(oldValue, newValue)))
            return;
        PropertyChangeEvent evt = new PropertyChangeEvent(getElement(), PROP_SUPERCLASS, oldValue, newValue);
        fireOwnPropertyChange(evt);
        
        ClassElement old = (ClassElement) cloneSelf ();
        try {
            old.setSuperclass (oldValue);
        } catch (SourceException e) {
            e.printStackTrace ();
        }
        notifyConnectionChange (old);
    }
    
    Identifier[] filterInterfaces(Identifier[] its) {
        if (its.length == 0)
            return its;
        Identifier[] oldIts = getInterfaces();
        Collection newState = null;
        for (int i = 0; i < its.length; i++) {
            boolean matches = false;
            for (int j = 0; j < oldIts.length; j++) {
                if (its[i].getSourceName().equals(oldIts[j].getSourceName())) {
                    matches = true;
                    break;
                }
            }
            if (!matches) {
                if (newState != null)
                    newState.add(its[i]);
            } else if (newState == null) {
                newState = new ArrayList(its.length);
                for (int k = 0; k < i; k++)
                    newState.add(its[k]);
            }
        }
        if (newState == null)
            return its;
        else
            return (Identifier[])newState.toArray(new Identifier[newState.size()]);
    }
        
    /**
     * Sets the interfaces implemented by the class.
     * @param interfaces collection of affected interfaces. If added, the values are
     * appended at the end of the interface property.
     * @param operation ADD, REMOVE or SET depending on the operation being performed.
     */
    public void changeInterfaces(Identifier[] interfaces, int operation) throws SourceException {
        checkWritable();
        checkDocument();
        boolean failed = true;
        repository.beginTrans (true);
        try {
            setClassPath();
            Identifier[] newValue;
            PropertyChangeEvent evt;

            // TODO: resolve interface identifiers, one by one, to preserve the semantic
            // meaning and create a suitable representation.
            switch (operation) {
                case ADD:
                    evt = identSupport.add(this, filterInterfaces(interfaces));
                    if (evt == null) {
                        failed = false;
                        return;
                    }
                    newValue = (Identifier[])evt.getNewValue();
                    break;
                case REMOVE:
                    evt = identSupport.remove(this, interfaces);
                    if (evt == null) {
                        failed = false;
                        return;
                    }
                    newValue = (Identifier[])evt.getNewValue();
                    break;
                // ugly generic case:
                case SET:
                    newValue = interfaces;
                    evt = identSupport.createChangeEvent(getElement(),
                        getInterfaces (), interfaces);
                    if (evt == null) {
                        failed = false;
                        return;
                    }
                    break;
                default:
                    throw new IllegalArgumentException("Unknown operation: " + operation); // NOI18N
            }

            checkVetoablePropertyChange(evt);

            List inters = ((JavaClass)javaElement).getInterfaceNames ();
            
            if (operation == REMOVE) {
                for (int x = 0; x < interfaces.length; x++) {
                    String fqn = interfaces[x].getSourceName();
                    ListIterator iter = inters.listIterator ();
                    while (iter.hasNext ()) {
                        MultipartId id = (MultipartId) iter.next ();
                        if (fqn.equals(multipartIdToName(id))) {
                            iter.remove ();
                            break;
                        }
                    } // while
                } // for
            } else { // SET or ADD                
                Collection oldInters = new LinkedList ();
                Collection temp = new LinkedList ();
                for (int x = 0; x < interfaces.length; x++) {
                    temp.add(javaModelPackage.getMultipartId().createMultipartId(interfaces[x].getFullName(), null, null));
                }
                if (operation == SET)
                    inters.clear();
                inters.addAll (temp);
            }    
            failed = false;
        } catch (InvalidObjectException e) {
            throwIsInvalid ();
        } finally {
            repository.endTrans (failed);
        }
    }

    public void fireInterfacesChange (Identifier[] oldValue, Identifier[] newValue) {
        // [PENDING] an interfaces change is always translated as SET operation
        PropertyChangeEvent evt = identSupport.createChangeEvent(getElement(),
                        oldValue, newValue);
        
        /*
        System.out.println("## fireInterfacesChange ##");
        System.out.print("old: ");
        for (int x = 0; x < oldValue.length; x++) {
            System.out.print(oldValue [x].getName () + " ");
        }
        System.out.println("");
        System.out.print("new: ");
        for (int x = 0; x < newValue.length; x++) {
            System.out.print(newValue [x].getName () + " ");
        }
        System.out.println("");
         */
        
        if (evt == null)
            return;
        fireOwnPropertyChange(evt);
        
        ClassElement old = (ClassElement) cloneSelf ();
        try {
            old.setInterfaces (oldValue);
        } catch (SourceException e) {
            e.printStackTrace ();
        }
        notifyConnectionChange (old);
    }
    
    public void setModifiers(int mod) throws SourceException {
        checkWritable();
        checkDocument();
        super.setModifiers ((mod & ~Modifier.INTERFACE) | (getModifiers () & Modifier.INTERFACE));
    }
    
    /**
     * Converts a class into an interface or vice-versa.
     * @param classFlag true, if the element should turn itself into a class def,
     * false if it should become an interface.
     */
    public void setClassOrInterface(boolean classFlag) throws SourceException {
        checkWritable();
        checkDocument();
        boolean failed = true;
        repository.beginTrans (true);
        try {
            PropertyChangeEvent evt;
            setClassPath();
            if (isClassOrInterface () == classFlag) {
                failed = false;
                checkIsValid ();
                return;
            }
                
            evt = new PropertyChangeEvent(getElement(), PROP_CLASS_OR_INTERFACE,
                classFlag ? Boolean.FALSE : Boolean.TRUE,
                classFlag ? Boolean.TRUE : Boolean.FALSE);

            // TODO: constraint the class -> interface change so that methods cannot
            // contain bodies.
            checkVetoablePropertyChange(evt);
            // perform the change in the source.
            
            ((JavaClass) javaElement).setInterface (!classFlag);
            failed = false;
        } catch (InvalidObjectException e) {
            throwIsInvalid ();
        } finally {
            repository.endTrans (failed);
        }
    }

    public void fireModifiersChange (Integer oldValue, Integer newValue) {
        int oldInt = oldValue.intValue ();
        int newInt = newValue.intValue ();
        boolean oldIsClass = (oldInt & Modifier.INTERFACE) == 0;
        boolean newIsClass = (newInt & Modifier.INTERFACE) == 0;
        if (oldIsClass != newIsClass) {
            fireIsClassChange (oldIsClass, newIsClass);
        }
        
        oldInt = oldInt & ~Modifier.INTERFACE;
        newInt = newInt & ~Modifier.INTERFACE;
        if (oldInt == newInt)
            return;
        
        PropertyChangeEvent evt = new PropertyChangeEvent(
            getElement(), 
            PROP_MODIFIERS, 
            new Integer (oldInt), 
            new Integer (newInt)
        );
        fireOwnPropertyChange(evt);
        
        MemberElement old = (MemberElement) cloneSelf ();
        try {
            old.setModifiers (oldInt);
        } catch (SourceException e) {
            e.printStackTrace ();
        }
        notifyConnectionChange (old);
    }
    
    public void fireIsClassChange (boolean oldValue, boolean newValue) {        
        PropertyChangeEvent evt = new PropertyChangeEvent(
            getElement(), 
            PROP_CLASS_OR_INTERFACE, 
            oldValue ? Boolean.TRUE : Boolean.FALSE, 
            newValue ? Boolean.TRUE : Boolean.FALSE
        );
        fireOwnPropertyChange(evt);
        
        ClassElement old = (ClassElement) cloneSelf ();
        try {
            old.setClassOrInterface (oldValue);
        } catch (SourceException e) {
            e.printStackTrace ();
        }
        notifyConnectionChange (old);
    }
        
    // Member management methods
    // - will delegate to collection helpers.
    ///////////////////////////////////////////////////////////////////////////////////
    public FieldElement[] getFields() {        
        return (FieldElement[]) fields.getFields().clone ();
    }
    
    public FieldElement getField(Identifier name) {
        return fields.getField (name);
    }
    
    public void changeFields(FieldElement[] flds, int operation) throws SourceException {
        checkWritable();
        checkDocument();
        fields.changeMembers(flds, operation);
    }
    
    public MethodElement[] getMethods() {        
        return (MethodElement[]) methods.getMethods().clone();
    }
    
    public MethodElement getMethod(Identifier id, Type[] argtypes) {        
        return methods.getMethod (id, argtypes);
    }
    
    public void changeMethods(MethodElement[] m, int operation) throws SourceException {
        checkWritable();
        checkDocument();
        methods.changeMembers(m, operation);
    }
    
    public ConstructorElement[] getConstructors() {
        return (ConstructorElement[]) constructors.getConstructors ().clone ();
    }
    
    public ConstructorElement getConstructor(Type[] argtypes) {
        return constructors.getConstructor (argtypes);
    }
    
    public void changeConstructors(ConstructorElement[] cons, int operation) throws SourceException {
        checkWritable();
        checkDocument();
        constructors.changeMembers(cons, operation);
    }
    
    public ClassElement[] getClasses() {
        return (ClassElement[]) innerClasses.getClasses ().clone ();
    }
    
    public ClassElement getClass(Identifier id) {        
        return innerClasses.getClass (id);
    }
    
    public void changeClasses(ClassElement[] classes, int operation) throws SourceException {
        checkWritable();
        checkDocument();
        innerClasses.changeMembers(classes, operation);
    }
    
    public InitializerElement[] getInitializers() {        
        return (InitializerElement[]) initializers.getInitializers ().clone ();
    }
    
    public void changeInitializers(InitializerElement[] el, int operation) throws SourceException {
        checkWritable();
        checkDocument();
        initializers.changeMembers(el, operation);
    }
    
    // Local element management
    ///////////////////////////////////////////////////////////////////////////////////
    
    /**
     * Local classes of a class are its inner classes.
     */
    public ClassElement[] getLocalClasses() {
        return getClasses();
    }
    
    // Utility methods
    ///////////////////////////////////////////////////////////////////////////////////
    
    protected void checkWritable() throws SourceException {        
        if (javaElement instanceof JavaEnum) {
            throw new SourceException.IO("Enumeration cannot be modified: " + getName().getFullName()); // NOI18N
        } else if (javaElement instanceof AnnotationType) {
            throw new SourceException.IO("Annotation type cannot be modified: " + getName().getFullName()); // NOI18N
        }
        super.checkWritable();
    }
    
    /** Return the implementation for the SourceElement - directly, since all classes
     * have a link to the source.
     */
    protected final SourceElementImpl findSourceImpl() {
        return this.sourceImpl;
    }        
    
    protected SourceElementImpl findSource() {
        if (sourceImpl != null)
            return sourceImpl;
        else {
            ClassElementImpl declClass = getDeclaringImpl();
            if (declClass != null)
                return declClass.findSource();
        }
        return null;
    }
    
    public void updateMembers(String propName, Element[] els, int[] indices, int[] optMap) {
        if (propName == ElementProperties.PROP_INITIALIZERS) {
            // initializers.updateMembers(els, indices, optMap);
        } else if (propName == ElementProperties.PROP_FIELDS) {            
            // fields.updateMembers(els, indices, optMap);
        } else if (propName == ElementProperties.PROP_CONSTRUCTORS) {            
            // constructors.updateMembers(els, indices, optMap);
        } else if (propName == ElementProperties.PROP_METHODS) {            
            // methods.updateMembers(els, indices, optMap);
        } else if (propName == ElementProperties.PROP_CLASSES) {            
            // innerClasses.updateMembers(els, indices, optMap);
        }    
    }
    
    public void updateMemberOrder(Element[] ordered) {
        // members.updateOrder(ordered);
    }
            
    protected final void createAfter(Binding.Container cb, Binding refBinding) throws SourceException {
        /*
        Element[] els = members.getElements();
        ElementImpl impl;
        Binding ref = null;
        
        for (int i = 0; i < els.length; i++) {
            impl = members.getElementImpl(els[i]);
            // impl.createAfter(getClassBinding(), ref);
            ref = impl.getBinding();
        }
         */
    }
    
    // Serialization support
    ///////////////////////////////////////////////////////////////////////////////////
    public Object readResolve() {
        return null;
    }
    
    // Support classes
    ///////////////////////////////////////////////////////////////////////////////////
    private static final class InterfaceSupport extends IdentifierArrayProperty {
        InterfaceSupport() {
            super(PROP_INTERFACES);
        }
        
        public Object[] getValue(ElementImpl bean) {
            return ((ClassElementImpl)bean).getInterfaces ();
        }
        
        public PropertyChangeEvent add(ClassElementImpl beanImpl, Identifier[] adding) 
            throws SourceException {
            Identifier[] cur = (Identifier[])getValue(beanImpl);
            Collection remains = null;
            
            for (int i = 0; i < adding.length; i++) {
                for (int j = 0; j < cur.length; j++) {
                    if (adding[i].getSourceName().equals(cur[j].getSourceName())) {
                        if (remains == null)
                            remains = new ArrayList(adding.length - 1);
                        for (int k = 0; k < i; k++) {
                            remains.add(adding[k]);
                        }
                        break;
                    }
                }
            }
            if (remains == null) {
                return super.add(beanImpl, adding);
            } else {
                // PENDING: throw an exception under different mode ??
                return super.add(beanImpl, remains.toArray(new Identifier[remains.size()]));
            }
        }
        
        public boolean compareValues(Object o1, Object o2) {
            return compareSourceIdentifiers((Identifier)o1, (Identifier)o2);
        }
    }
    
    public String toString() {
        StringBuffer sb = new StringBuffer();
        
        sb.append("ClassElement["); // NOI18N
        sb.append(getName().getFullName());
        sb.append("/"); // NOI18N
        sb.append(getName().getSourceName());
        sb.append("]"); // NOI18N
        return sb.toString();
    }
    
    /**
     * This implementation only clones the class element itself, not its subitems.
     */
    protected Element cloneSelf() {
        ClassElement clone = new ClassElement();
        try {
            clone.setClassOrInterface(isClassOrInterface());
            clone.setName(getName());
            clone.setSuperclass(getSuperclass());
            clone.setInterfaces(getInterfaces());
            clone.setModifiers(getModifiers());
        } catch (SourceException ex) {
        }
        return clone;
    }
    
    /**
     * Called by outer classes during their rename operation. The inner classes
     * should fire Property Change on their name property, but without Vetoable change.
     * And, of course, change their names.
     */
    protected void updateName(String outerPrefix) throws SourceException {
        Identifier curName = getName();
        if (curName.getQualifier().equals(outerPrefix))
            return;
        StringBuffer sb = new StringBuffer();
        if (outerPrefix != null && !"".equals(outerPrefix)) {
            sb.append(outerPrefix);
            sb.append('.');
        }
        String simpleName = curName.getName();
        sb.append(simpleName);
        String fullName = sb.toString();
        Identifier newName = Identifier.create(fullName, simpleName);
        setName(newName);
        updateInnerClasses(fullName);
    }
    
    private void updateInnerClasses(String fullName) throws SourceException {
        ClassElement[] cls = getClasses();
        for (int i = 0; i < cls.length; i++) {
            ClassElementImpl impl = (ClassElementImpl)cls[i].getCookie(ClassElementImpl.class);
            impl.updateName(fullName);
        }
    }
    
    protected Element getParent() {
        Element p = super.getParent();
        if (p == null)
            return ((ClassElement)getElement()).getSource();
        else 
            return p;
    }
    
    protected Identifier createLocalIdentifier(Identifier id, int status) {
        return identSupp.create(id, status);
    }
    
    protected boolean checkIdentifierContext(Identifier id) {
        return identSupp.checkContext(id);
    }
    
    protected void checkRemove() throws SourceException {
        super.checkRemove();
    }
    
    protected void notifyRemove() {
        super.notifyRemove();
    }
    
    protected void notifyCreate() {
        /*
        Element[] allElems = members.getElements();
        for (int i = 0; i < allElems.length; i++) {
            ElementImpl impl = members.getElementImpl(allElems[i]);
            impl.notifyCreate();
        }
        super.notifyCreate();
        members.sanityCheck();
        if (innerClasses != null)
            innerClasses.sanityCheck();
        if (fields != null)
            fields.sanityCheck();
        if (methods != null)
            methods.sanityCheck();
        if (constructors != null)
            constructors.sanityCheck();
        if (initializers != null)
            initializers.sanityCheck();
         */
    }
    
    protected boolean parentValid() {
        return declaringClassImpl == null ? 
            sourceImpl.isValid() : declaringClassImpl.isValid();
    }
    
    public Element[] getElements() {
        repository.beginTrans (false);
        try {
            setClassPath();
            Collection coll = ((JavaClass) javaElement).getFeatures();
            int size = coll.size ();
            Iterator iter = coll.iterator();
            ArrayList list = new ArrayList();
            
            while (iter.hasNext()) {
                Feature f = (Feature)iter.next();
                if (f instanceof Method) {
                    list.add(methods.cachedElement(f));
                } else if (f instanceof Constructor) {
                    list.add(constructors.cachedElement(f));
                } else if (f instanceof Field) {
                    list.add(fields.cachedElement(f));
                } else if (f instanceof Initializer) {
                    list.add(initializers.cachedElement(f));
                } else if (f instanceof JavaClass) {
                    list.add(innerClasses.cachedElement(f));
                }
            }
            Element[] res = new Element[list.size()];
            list.toArray(res);
            return res;
        } catch (InvalidObjectException e) {
            return new Element [0];
        } finally {
            repository.endTrans (false);
        }
    }
    
    // ..........................................................................

    static class ClassListener extends MemberElementImpl.MemberElementListener implements MDRPreChangeListener {
        
        private static final Identifier[] NO_INTERFACES = new Identifier[0];
        private InterfacesListener interfaces = new InterfacesListener (this);
        private Identifier superClass;
        private Map eventsMap = new HashMap();
        
        ClassListener (ClassElementImpl impl) {
            super (impl);
        }
                
        public void connect () {
            if (REGISTER_LISTENER) {
                super.connect ();
                impl = (ElementImpl) ref.get();
                if (impl != null) {
                    interfaces.initElements ();
                    
                    JavaClass superCls = ((ClassDefinition) javaElement).getSuperClass();
                    if (superCls != null) {
                        superClass = Identifier.create(superCls.getName());
                    } else {
                        superClass = null;
                    }
                }
                impl = null;
            }
        }

        public void remove () {
            super.remove ();
            interfaces.removeAll ();
        }

        public void doChange(MDRChangeEvent event) {
            super.doChange (event);
            if (source instanceof Extends) {
                AssociationEvent assocEvent = (AssociationEvent) event;
                if ("subClasses".equals(assocEvent.getEndName())) {
                    EventInfo info = (EventInfo) eventsMap.get(event);
                    Identifier oldSuperClass = superClass;
                    superClass = info.newName != null ? Identifier.create(info.newName) : null;
                    ((ClassElementImpl) impl).fireSuperclassChange(oldSuperClass, superClass);                    
                }
                /*
                System.out.println("end name: " + assocEvent.getEndName());
                System.out.println("fixed: " + assocEvent.getFixedElement());
                System.out.println("new: " + assocEvent.getNewElement());
                 */
            }
        }
                
        public void changeCancelled(MDRChangeEvent e) {
            eventsMap.remove(e);
        }
        
        public void plannedChange(MDRChangeEvent event) {
            RefBaseObject source = (RefBaseObject) event.getSource ();
            if (source instanceof Extends) {
                AssociationEvent assocEvent = (AssociationEvent) event;
                if ("subClasses".equals(assocEvent.getEndName())) {
                    JavaClass jc = (JavaClass) assocEvent.getNewElement();
                    EventInfo info = new EventInfo();
                    info.newName = jc != null ? jc.getName() : null;
                    eventsMap.put(event, info);
                }
            }
        }
        
        class EventInfo {            
            String newName;            
        }
        
    } // ClassListener ..........................................................
    
    static class InterfacesListener extends CallableImpl.ExceptionsListener {

        InterfacesListener(ElementImpl.ElementListener parentListener) {
            super(parentListener);
        }

        public List getElements() {
            return ((JavaClass) javaElement).getInterfaces();
        }
        
        public String getEndName() {
            return "interfaces"; // NOI18N
        }
        
        public void fireChange (ElementImpl impl, ArrayList oldValues, ArrayList newValues) {
            Identifier [] oldPars = (Identifier []) oldValues.toArray (ClassListener.NO_INTERFACES);
            Identifier [] newPars = (Identifier []) newValues.toArray (ClassListener.NO_INTERFACES);
            ((ClassElementImpl) impl).fireInterfacesChange (oldPars, newPars);
        }

    } // InterfacesListener .....................................................

}
... 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.