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-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.netbeans.modules.javacore.jmiimpl.javamodel;

import java.lang.reflect.Modifier;
import java.util.*;
import org.netbeans.jmi.javamodel.*;
import org.netbeans.lib.java.parser.ASTree;
import org.netbeans.mdr.handlers.AttrListWrapper;
import org.netbeans.mdr.storagemodel.StorableObject;
import org.netbeans.modules.javacore.JMManager;
import org.netbeans.modules.javacore.parser.ElementInfo;
import org.netbeans.modules.javacore.parser.MethodInfo;
import org.netbeans.modules.javacore.parser.MDRParser;
import org.netbeans.modules.javacore.parser.TypeParamRef;
import org.netbeans.modules.javacore.parser.TypeRef;
import org.openide.util.Utilities;


/**
 * Superclass for the MethodImpl and ConstructorImpl classes.
 *
 * @author  Martin Matula
 * @author  Vladimir Hudec
 * @author  Pavel Flaska
 */
public abstract class CallableFeatureImpl extends BehavioralFeatureImpl implements CallableFeature {
    public static final String PARAMETERS_ATTR = "parameters";
    
    protected boolean elementsInited = false;

    protected LightAttrList parameters;

    /** List of exceptions */
    protected ReferenceListWrapper exceptions = null;
    /** List of exception names */
    private LightAttrList excNames = null;
    private LightAttrList typeParameters = null;

    /** Creates a new instance of ConstructorImpl */
    public CallableFeatureImpl(StorableObject s) {
        super(s);
    }

    protected void matchPersistent(ElementInfo newInfo) {
        super.matchPersistent(newInfo);
        
        MethodInfo info = (MethodInfo) newInfo;
        
        if (!isPersisted()) {
            setPersisted(true);
            persist();
            setTypeRef(info.type);
            setExceptionRefs(Arrays.asList(info.exceptions));
            persistChildren(super_getParameters(), info.parameters);
            persistChildren(super_getTypeParameters(), info.typeParams);
        } else {
            if (!Utilities.compareObjects(info.type, getTypeRef())) {
                setType(resolveType(info.type));
            }
            processMembers(getExceptions(), info.exceptions);
            processMembers(getParameters(), info.parameters);
            processMembers(getTypeParameters(), info.typeParams);
        }
    }
    
    /** The method has to make sure that the AST infos of children are also updated.
     */
    protected void matchElementInfo(ElementInfo newInfo) {
        super.matchElementInfo(newInfo);
        resetASTElements();
    }

    protected void resetChildren() {
        if (parameters != null) parameters.setInnerList(getPersistentList(PARAMETERS_ATTR, super_getParameters()));
        if (typeParameters != null) typeParameters.setInnerList(getPersistentList(TYPE_PARAMETERS_ATTR, super_getTypeParameters()));
        if (childrenInited) {
            resetASTElements();
            initChildren();
        }
        if (exceptions != null) {
            initExceptions();
        }
    }

    protected void resetASTElements() {
        if (elementsInited) {
            if (excNames != null) {
                deleteChildren(excNames);
                excNames = null;
            }
            elementsInited = false;
        }
    }

    protected void initASTElements() {
        elementsInited = false;
        if (!childrenInited) {
            initChildren();
        }
        MethodInfo info = (MethodInfo) getElementInfo();
        ASTree[] namesAST = info.getExceptionsAST(this);
        excNames = createChildrenList(excNames, "exceptionNames", namesAST, CHANGED_THROWS, false); // NOI18N
        elementsInited = true;
    }

    protected ASTree getBodyAST() {
        return getASTree().getSubTrees()[5];
    }

    /**
     * Returns the value of attribute parameters.
     * @return Value of parameters attribute.
     */
    public List getParameters() {
        if (parameters == null) {
            checkUpToDate();
            parameters = createChildrenList(PARAMETERS_ATTR, (AttrListWrapper) super_getParameters(), null, CHANGED_PARAMETERS);
        }
        return parameters;
    }

    public List getTypeParameters() {
        if (typeParameters == null) {
            checkUpToDate();
            typeParameters = createChildrenList(TYPE_PARAMETERS_ATTR, (AttrListWrapper) super_getTypeParameters(), null, CHANGED_TYPE_PARAMETERS);
        }
        return typeParameters;
    }

    protected void initChildren() {
        childrenInited = false;
        parameters = createChildrenList(parameters, PARAMETERS_ATTR, (AttrListWrapper) super_getParameters(), ((MethodInfo) getElementInfo()).parameters, CHANGED_PARAMETERS);
        typeParameters = createChildrenList(typeParameters, TYPE_PARAMETERS_ATTR, (AttrListWrapper) super_getTypeParameters(), ((MethodInfo) getElementInfo()).typeParams, CHANGED_TYPE_PARAMETERS);
        super.initChildren();
        childrenInited = true;
        
        if (elementsInited) {
            initASTElements();
        }

        StatementBlock body = retrieveBody();
        if (bodyInited) {
            JMManager.getTransactionMutex().addBFeatureToInitQueue(this);
        }
    }
    
    protected abstract List super_getParameters();
    protected abstract List super_getTypeParameters();

    protected void setData(List annotations, String javadocText, JavaDoc javadoc, StatementBlock body, String bodyText, List typeParameters, List parameters, List exceptionNames) {
        super.setData(annotations, javadocText, javadoc, body, bodyText);
        this.typeParameters = createChildrenList(TYPE_PARAMETERS_ATTR, (AttrListWrapper) super_getTypeParameters(), typeParameters, CHANGED_TYPE_PARAMETERS); // NOI18N
        this.parameters = createChildrenList(PARAMETERS_ATTR, (AttrListWrapper) super_getParameters(), parameters, CHANGED_PARAMETERS); // NOI18N
        this.excNames = createChildrenList("exceptionNames", exceptionNames, CHANGED_THROWS); // NOI18N
        elementsInited = true;
    }

    /**
     * Returns the value of reference exceptions.
     * @return Value of reference exceptions.
     */
    public List getExceptions() {
        if (exceptions == null) {            
            initExceptions();
        }
        return exceptions;
    }

    public List getExceptionNames() {
        if (!elementsInited) {
            initASTElements();
        }
        return excNames;
    }

    public List getChildren() {
        List list = super.getChildren();
        list.addAll(getTypeParameters());
        list.addAll(getParameters());
        list.addAll(getExceptionNames());
        return list;
    }

    protected List getInitedChildren() {
        List list = super.getInitedChildren();
        if (childrenInited) {
            list.addAll(typeParameters);
            list.addAll(parameters);
        }
        if (elementsInited) {
            list.addAll(excNames);
        }
        return list;
    }
    
    public void replaceChild(Element oldElement, Element newElement) {
        if (replaceObject(getParameters(), oldElement, newElement)) return;
        if (replaceObject(getTypeParameters(), oldElement, newElement)) return;
        if (elementsInited) {
            if (replaceObject(excNames, oldElement, newElement)) return;
        }
        super.replaceChild(oldElement, newElement);
    }
    
    public Collection findDependencies(boolean findUsages, boolean fromBaseClass, boolean findOverridingMethods) {
        Resource[] res = findReferencedResources();
        
        if (!fromBaseClass || (fromBaseClass && !isOverriden())) {
            Element cd = getDeclaringClass();
            while (!((cd instanceof JavaClass) && !((JavaClass) cd).isInner())) {
                cd = (Element) cd.refImmediateComposite();
            }
            int modifiers = ((JavaClass) cd).getModifiers();
            if (!(Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers))) {
                res = filterResourcesFromThisPackage(res);
            }
        }

        UsageFinder finder = new UsageFinder(this, findUsages, fromBaseClass, findOverridingMethods); 
        return finder.getUsers(res);
    }
    
    private boolean isOverriden() {
        if (!(this instanceof Method))
            return false;
        
        ClassDefinition declaringClass = getDeclaringClass();
        
        List params = new ArrayList();
        for (Iterator i = getParameters().iterator(); i.hasNext(); params.add(((Parameter)i.next()).getType()));
        
        ClassDefinition parent = declaringClass.getSuperClass();
        Method m = parent.getMethod(getName(), params, true);
        if (m!=null) {
            return true;
        }
        Iterator i = declaringClass.getInterfaces().iterator();
        while (i.hasNext()) {
            ClassDefinition jc = (ClassDefinition) i.next();
            m = jc.getMethod(getName(), params, true);
            if (m!=null) {
                return true;
            }
        }
        return false;
    }
    
    private void initExceptions() {
        checkUpToDate();
        List exceptionNames = getExceptionRefs();
        if (exceptionNames == null) {
            exceptionNames = new ArrayList();
        } else if (!(exceptionNames instanceof ArrayList)) {
            exceptionNames = new ArrayList(exceptionNames);
        }
        TypeList innerExceptions = new TypeList(this, (ArrayList) exceptionNames) {
            protected void updateParent() {
                setExceptionRefs(innerList);
            }
        };
        if (exceptions == null) {
            ThrowsImpl throwsImpl = (ThrowsImpl)(((JavaModelPackage) refImmediatePackage()).getThrows());
            exceptions = new ReferenceListWrapper(_getDelegate().getMdrStorage(), throwsImpl, this, "exceptions", this, CHANGED_THROWS, innerExceptions); // NOI18N
        } else {
            exceptions.setInnerList(innerExceptions);
        }
    }

    // .........................................................................
    // printing and formatting functionality
    // .........................................................................

    /**
     * Generates callable feature header, i.e. Constructor or Method. Subclasses
     * have to provide generateTypeAndName() method.
     *
     * @param  buf  buffer to append header to
     */
    void generateHeader(StringBuffer buf) {
        buf.append('\n'); // todo (#pf): use options for leaving empty line before the element
        generateNewJavaDoc(buf);
        buf.append(getIndentation());
        generateNewModifiers(buf);
        generateNewTypeParameters(buf);
        generateTypeAndName(buf);
        generateNewParameters(buf);
        generateNewExceptions(buf);
    }

    /**
     * Provided by constructor and method elements.
     *
     * @param  buf  buffer to append type and name to
     */
    abstract void generateTypeAndName(StringBuffer buf);

    /**
     * Method is used by subclasses to generate 'parameters' part of the
     * element.
     *
     * @param  buf  append parameters to this parameter
     */
    void generateNewParameters(StringBuffer buf) {
        formatElementPart(PAR_OPEN_BRACKET, buf);
        List parameters = getParameters();
        if (!parameters.isEmpty()) {
            Iterator it = parameters.iterator();
            ParameterImpl impl = (ParameterImpl) it.next();
            buf.append(impl.getSourceText());
            while (it.hasNext()) {
                formatElementPart(COMMA, buf);
                impl = (ParameterImpl) it.next();
                buf.append(impl.getSourceText());
            }
        }
        formatElementPart(PAR_CLOSE_BRACKET, buf);
    }

    /**
     * Method is used by subclasses to generate 'throws clause' of the
     * element.
     *
     * @param  buf  append throws clause to this param
     */
    void generateNewExceptions(StringBuffer buf) {
        Collection exceptions = getExceptionNames();
        if (!exceptions.isEmpty()) {
            formatElementPart(THROWS_KEYWORD, buf);
            Iterator it = exceptions.iterator();
            MultipartIdImpl id = (MultipartIdImpl) it.next();
            buf.append(id.getSourceText());
            while (it.hasNext()) {
                formatElementPart(COMMA, buf);
                id = (MultipartIdImpl) it.next();
                buf.append(id.getSourceText());
            }
        }
    }

    private void generateNewTypeParameters(StringBuffer buf) {
        Collection typeParameters = getTypeParameters();
        if (!typeParameters.isEmpty()) {
            buf.append('<');
            Iterator it = typeParameters.iterator();
            while (it.hasNext()) {
                buf.append(((TypeParameterImpl) it.next()).getSourceText());
                if (it.hasNext()) {
                    formatElementPart(COMMA, buf);
                }
            }
            buf.append('>');
        }
    }

    protected void getTypeParamsDiff(List diffList) {
        MethodInfo astInfo = (MethodInfo) getElementInfo();
        MDRParser parser = getParser();
        ASTree[] children = getASTree().getSubTrees();
        if (astInfo.typeParams.length == 0) {
            if (isChanged(CHANGED_TYPE_PARAMETERS)) {
                StringBuffer buf = new StringBuffer();
                generateNewTypeParameters(buf);
                int endOffset = getStartOffset(parser, children[2], false);
                diffList.add(new DiffElement(endOffset, endOffset, buf.toString() + ' '));
            }
        } else if (getTypeParameters().isEmpty()) {
            if (isChanged(CHANGED_TYPE_PARAMETERS)) {
                int endOffset = getStartOffset(parser, children[2], true);
                int startOffset = getStartOffset(parser, children[1], true);
                diffList.add(new DiffElement(startOffset, endOffset, ""));
            }
        } else {
            getCollectionDiff(diffList, parser, CHANGED_TYPE_PARAMETERS, astInfo.typeParams, getTypeParameters(), parser.getToken(children[1].getLastToken()).getStartOffset(), ", "); // NOI18N
        }
    }

    protected void _delete() {
        // --- delete components -------------------------------------------
        if (elementsInited) {
            deleteChildren(getExceptionNames());
        }
        // delete all parameters (if initialized)
        deleteChildren(PARAMETERS_ATTR, (AttrListWrapper) super_getParameters());
        deleteChildren(TYPE_PARAMETERS_ATTR, (AttrListWrapper) super_getTypeParameters());
        // --- delete links -----------------------------------------------
        // no links to delete
        // [TODO] should Throws association be notified?
        // --- call super -------------------------------------------------
        super._delete();
    }
    
    protected void setExceptionRefs(List excs) {
        _getDelegate().setSlot2(excs);
    }
    
    public List getExceptionRefs() {
        return (List) _getDelegate().getSlot2();
    }
}
... 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.