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-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.javacore.jmiimpl.javamodel;

import org.netbeans.jmi.javamodel.*;
import org.netbeans.lib.java.parser.ASTree;
import org.netbeans.lib.java.parser.ParserTokens;
import org.netbeans.lib.java.parser.Token;
import org.netbeans.mdr.handlers.BaseObjectHandler;
import org.netbeans.mdr.persistence.StorageException;
import org.netbeans.mdr.storagemodel.StorableObject;
import org.netbeans.modules.javacore.ClassIndex;
import org.netbeans.modules.javacore.JMManager;
import org.netbeans.modules.javacore.parser.ASTProvider;
import org.netbeans.modules.javacore.parser.ElementInfo;
import org.netbeans.modules.javacore.parser.FeatureInfo;
import org.netbeans.modules.javacore.parser.JavaDocParser;
import org.openide.ErrorManager;
import org.openide.util.Utilities;
import javax.jmi.model.MofClass;
import javax.jmi.reflect.ConstraintViolationException;
import javax.jmi.reflect.RefFeatured;
import javax.jmi.reflect.RefObject;
import java.lang.reflect.Modifier;
import java.util.*;
import org.netbeans.api.mdr.MDRepository;
import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
import org.netbeans.modules.javacore.parser.MDRParser;
import org.netbeans.modules.javacore.parser.TypeRef;
import org.openide.text.PositionBounds;


/** Implementation of Feature object instance interface.
 *
 * @author Vladimir Hudec
 * @author Pavel Flaska
 */
public abstract class FeatureImpl extends SemiPersistentElement {
    
    public static final int DEPRECATED = 0x80000000;
    
    public static final String TYPE_PARAMETERS_ATTR = "typeParameters"; // NOI18N
    
    protected String javadocText = null;
    protected JavaDoc javadoc = null;
    protected LightAttrList annotations = null;
    
    /** Creates a new instance of FeatureImpl */
    public FeatureImpl(StorableObject s) {
        super(s);
    }
    
    protected void initChildren() {
        annotations = createChildrenList(annotations, "annotations", // NOI18N
            ((FeatureInfo) getElementInfo()).annotations, 
            CHANGED_ANNOTATION, false);
    }
    
    protected void resetChildren() {
        if (childrenInited) {
            if (annotations != null) {
                createChildrenList(annotations, "annotations", ((FeatureInfo) getElementInfo()).annotations, CHANGED_ANNOTATION, true); // NOI18N
            }
        }
    }

    /**
     * Returns the value of attribute annotations.
     * @return Value of annotations attribute.
     */
    public List getAnnotations() {
        if (!childrenInited) {
            initChildren();
        }
        return annotations != null ? annotations : Collections.EMPTY_LIST;
    }

    protected abstract void super_setModifiers(int modifiers);
    protected abstract int super_getModifiers();

    /**
     * Returns the value of attribute modifiers.
     * @return Value of attribute modifiers.
     */
    public int getModifiers() {
        int mods = super_getModifiers();
        ClassDefinition cd = getDeclaringClass();
        if (cd instanceof JavaClass) {
            JavaClass jc = (JavaClass)cd;
            if ((jc.getModifiers() & Modifier.STRICT) != 0) {
                mods = mods | Modifier.STRICT;
            }
            if (jc.isInterface()) {
                mods = mods | Modifier.PUBLIC;
                if (this instanceof Method) {
                    mods |= Modifier.ABSTRACT;
                }
            } else {
                if (this instanceof Method && ((jc.getModifiers() & Modifier.FINAL) != 0)) {
                    mods |= Modifier.FINAL;
                }
            }
        }
        return ~DEPRECATED & mods;
    }

    public int getSourceModifiers() {
        int mods = super_getModifiers();
        return ~DEPRECATED & mods;
    }
    
    /**
     * Sets the value of modifiers attribute. See {@link #getModifiers} for description
     * on the attribute.
     * @param newValue New value to be set.
     */
    public void setModifiers(int newValue) {
        boolean isDeprecated = isDeprecated();
        objectChanged(CHANGED_MODIFIERS);
        super_setModifiers((newValue & ~DEPRECATED) | (isDeprecated ? DEPRECATED : 0));
    }

    public boolean isDeprecated() {
        int mods = super_getModifiers();
        return (mods & DEPRECATED) != 0;
    }
    
    public void setDeprecated(boolean deprecated) {
        throw new UnsupportedOperationException();
    }
    
    /**
     * Returns the value of attribute javadocText.
     *
     * IT'S POSSIBLE TO USE SIMPLE IMPLEMENTATION JavaDocParser.surroundWithJavaDocStars()
     *
     * @return Value of attribute javadocText.
     */
    public java.lang.String getJavadocText() {
        if (isChanged(CHANGED_JAVADOC) && javadoc != null) {
            List tags = javadoc.getTags();
            JavaDocParser.JavaDocTag[] javaDocTags = null;
            if (tags != null) {
                javaDocTags = new JavaDocParser.JavaDocTag[tags.size()];
                int i = 0;
                for (Iterator it = tags.iterator(); it.hasNext(); ) {
                    TagValue tagValue = (TagValue) it.next();
                    javaDocTags[i++] = new JavaDocParser.JavaDocTag(tagValue.getDefinition().getName(), tagValue.getValue());
                }
            }
            JavaDocParser parser = new JavaDocParser(javadoc.getText(), javaDocTags);
            return parser.getRawText(true); // reorder tags
        }

        else if (isChanged(CHANGED_JAVADOC))
            return javadocText;
        else {
            MDRParser parser = getParser();
            if (parser != null) {
                String s = parser.getJavaDoc(getASTree());
                if (s == null) // there is no javadoc
                    return null;
                if (s.startsWith("\n")) {
                    return s.substring(1);
                }
                if (s.startsWith("\r\n")) { // to be sure that it works on Win too
                    return s.substring(2);
                }
                return s;
            }
        }
        return null;
    }
    /**
     * Sets the value of javadocText attribute. See {@link #getJavadocText} for
     * description on the attribute.
     * @param newValue New value to be set.
     */
    public void setJavadocText(java.lang.String newValue) {
        objectChanged(CHANGED_JAVADOC);
        javadoc = null;
        javadocText = newValue;
        if (Utilities.compareObjects(getParser().getJavaDoc(getASTree()), newValue)) {
            resetChange(CHANGED_JAVADOC);
        }
    }

    /**
     * Returns the value of attribute javadoc.
     * @return Value of attribute javadoc.
     */
    public JavaDoc getJavadoc() {
        if (isChanged(CHANGED_JAVADOC) && javadoc != null)
            return javadoc;
        String javaDocText = getJavadocText();
        if (javaDocText == null)
            return null;

        JavaModelPackage pkg = (JavaModelPackage) refImmediatePackage();
        TagValueClassImpl tagValueClass = (TagValueClassImpl) pkg.getTagValue();
        JavaDocClassImpl javaDocClass = (JavaDocClassImpl) pkg.getJavaDoc();

        JavaDocParser parser = new JavaDocParser(javaDocText);
        JavaDocParser.JavaDocTag[] tags = parser.getTags();

        List tagsList = new ArrayList();
        String text = null;

        if (tags != null && tags.length > 0) {
            for (int i = 0; i < tags.length; i++) {
                JavaDocParser.JavaDocTag tag = tags[i];
                if (tag.isText()) {
                    text = tag.getValue();
                    continue;
                }
                String tagName = tag.getName();
                String tagText = tag.getValue();
                tagsList.add(tagValueClass.create(tagName, tagText));
            }
        }

        JavaDocImpl javaDoc = (JavaDocImpl) javaDocClass.createJavaDoc(text, tagsList);

        if (javadocText != null)
            this.javadocText = null;
        changeChild(this.javadoc, javaDoc);
        return this.javadoc = javaDoc;
    }

    /**
     * Sets the value of javadoc attribute. See {@link #getJavadoc} for description
     * on the attribute.
     * @param newValue New value to be set.
     */
    public void setJavadoc(JavaDoc newValue) {
        if (javadocText != null)
            throw new ConstraintViolationException(this, getNameAttr("javadoc"), "Can't set both JavaDoc as a text and as an object."); // NOI18N
        objectChanged(CHANGED_JAVADOC);
        changeChild(this.javadoc, newValue);
        this.javadoc = newValue;
    }

    /** Helper class
     */
    public ClassDefinition getDeclaringClass() {
        RefFeatured obj = refImmediateComposite();

        if (obj instanceof ClassDefinition) {
            return (ClassDefinition) obj;
        } else if (this instanceof Field && obj instanceof FieldGroup) {
            return ((FieldGroup) obj).getDeclaringClass();
        }
        return null;
    }

    public PositionBounds getPosition() {
        ResourceImpl resource = (ResourceImpl)getResource();
        PositionBounds result = resource.getFeaturePosition(this);
        if (result != null)
            return result;
        else {
            MDRepository repository = repository();
            repository.beginTrans(false);
            try {
                if (((JMManager) JavaMetamodel.getManager()).getTransactionMutex().getClassPath() == null) {
                    JavaMetamodel.getManager().setClassPath(resource);
                }
                return super.getPosition();
            } finally {
                repository.endTrans(false);
            }    
        }
    }
    
    /** Helper method
     */
    protected RefObject getNameAttr(String name) {
        try {
            return ((MofClass) refMetaObject()).lookupElementExtended(name);
        }
        catch (javax.jmi.model.NameNotFoundException e) {
            return null;
        }
    }

    /**
     * Adds the new diff item to the list if the javaDoc is changed in element,
     * otherwise it does nothing.
     * todo (#pf): currently, we use only javadocText. 
     *
     * @param  diff  list of collected differences where the new element is added
     */
    protected void replaceJavaDoc(List diff) {
        if (isChanged(CHANGED_JAVADOC)) {
            ASTree tree = getASTree();
            Token docToken = getParser().getComment(tree);
            // todo (#pf): now we only handle javaDoc text, we ignore
            // settings from model -- (For the time being it is enough 
            // to provide information for compatability bridge.)
            String newContent = JavaDocParser.surroundWithJavaDocStars(javadocText);
            if (docToken.getType() == ParserTokens.DOC_COMMENT && javadocText != null) {
                // replace the original javaDoc if exists already
                diff.add(new DiffElement(docToken.getStartOffset(),
                                         docToken.getEndOffset(),
                                         indentJavaDoc(newContent).trim()
                                        )
                        );
                // We cannot use general replaceNode method because it
                // doesn't work on padding token. (Method getFirstToken()
                // and getLastToken() cannot return token indexes because they
                // aren't in the token list.)
                //
                // replaceNode(diff, 
                //            getParser(),
                //            docToken,
                //            , 
                //            docToken.getStartOffset(),
                //            null);
            } else {
                // we have to reset original javadoc
                if (javadocText == null) {
                    int startOffset = docToken.getStartOffset();
                    int endOffset = docToken.getEndOffset();
                    if (getParser().getSourceText().length() > endOffset) {
                        int temp = getParser().getSourceText().indexOf('\n', endOffset);
                        if (temp > -1) {
                            endOffset = temp + 1;
                        }
                    }
                    diff.add(new DiffElement(startOffset, endOffset, ""));
                } else {
                    // create new javaDoc in case it didn't exist yet
                    // we will look for the last new line before the element. The
                    // comment will be put before this new line. If the new line
                    // does not exist before the element, we will put the javadoc
                    // comment directly before the first char of the element.
                    int startOffset = getLastNewLineOffset(docToken) + 1;
                    if (startOffset < 0) {
                        startOffset = docToken.getStartOffset();
                    }
                    diff.add(new DiffElement(startOffset,
                                             startOffset,
                                             indentJavaDoc(newContent + '\n')
                                            )
                            );
                }
            }
        }
    }

    /**
     * Looks for the last new line before the token in its paddings.
     * 
     * @param   token  token to look for the new line before
     * @return  offset of the last new line in the token's paddings
     */
    private int getLastNewLineOffset(Token token) {
        Token[] pad = token.getPadding();
        // previously, empty array was returned - with gjast.jar, it is possible
        // to get null value. We have to check it.
        if (pad == null) return -1; 
        for (int i = pad.length; i > 0; i--) {
            if (pad[i-1].getType() == ParserTokens.EOL) {
                String value = getParser().getText(pad[i-1]);
                return pad[i-1].getStartOffset() + value.lastIndexOf('\n');
            }
        }
        return -1;
    }
    
    /**
     * Replaces JavaDoc, leaves the paddings for the token as they
     * were.
     *
     * @param javadoc      javadoc to be printed
     * @param token        first element token
     * @param buf          add doc to the buf
     * @param lastPrinted  lastPrinted character
     *
     * @return  index of the last printed character
     */
    protected int printJavaDoc(String javadoc, Token token, StringBuffer buf, int lastPrinted) {
        ASTProvider parser = getParser();
        String origSrc = parser.getSourceText();
        Token comment = parser.getComment(getASTree());
        String newJavadoc = indentJavaDoc(JavaDocParser.surroundWithJavaDocStars(getJavadocText()));
        if (comment.getType() == ParserTokens.DOC_COMMENT) {
            int startOffset = comment.getStartOffset();
            if (lastPrinted < startOffset)
                buf.append(origSrc.substring(lastPrinted, startOffset));
            buf.append(newJavadoc.trim());
            lastPrinted = token.getStartOffset();
            buf.append(origSrc.substring(comment.getEndOffset(), lastPrinted));
        }
        else {
            int startOffset = getBeginIndex();
            lastPrinted = token.getStartOffset();
            String paddings = origSrc.substring(startOffset, lastPrinted);
            StringTokenizer tokenizer = new StringTokenizer(paddings, "\n", true); // NOI18N
            String toPrint = "";
            while (tokenizer.hasMoreTokens()) {
                buf.append(toPrint);
                toPrint = tokenizer.nextToken();
            }
            if (toPrint.length() == 0) {
                buf.append(newJavadoc);
                buf.append('\n'); buf.append(getIndentation());
            }
            else {
                buf.append(newJavadoc);
                if (!toPrint.equals("\n")) // NOI18N
                    buf.append('\n');
                buf.append(toPrint);
            }
        }
        return lastPrinted;
    }

    protected void diffModifiers(List diffList, ASTree nextNode, ASTProvider parser) {
        String text = Modifier.toString(getSourceModifiers());
        int nextToken = nextNode.getFirstToken();
        int startOffset, endOffset;
        int startToken;
        endOffset = parser.getToken(nextToken).getStartOffset();
        ASTree modifiers = getASTree().getSubTrees()[0];
        if (modifiers != null) {
            startToken = modifiers.getFirstToken();
            startOffset = parser.getToken(startToken).getStartOffset();
            if (text.length() != 0) {
                int endToken = modifiers.getLastToken();
                endOffset = parser.getToken(endToken).getEndOffset();
            }
        } else {
            startOffset = endOffset;
            text += ' ';
        }
        for (Iterator annIt = getAnnotations().iterator(); annIt.hasNext(); ) {
            AnnotationImpl ann = (AnnotationImpl) annIt.next();
            text = ann.getSourceText() + ' ' + text;
        }
        diffList.add(new DiffElement(startOffset, endOffset, text));
    }

    /**
     * Generates element's javadoc and appends it to the buffer.
     *
     * @param  buf  buffer to append javadoc to
     * @return true, if there is JavaDoc, otherwise false
     */
    public boolean generateNewJavaDoc(StringBuffer buf) {
        String javadoc = getJavadocText();
        if (javadoc != null) {
            buf.append(indentJavaDoc(JavaDocParser.surroundWithJavaDocStars(javadoc)));
            buf.append('\n');
            return true;
        }
        else
            return false;
    }

    /**
     * Generates element's modifiers and append them to the buffer.
     * Moreover, it appends also annotation for this feature.
     *
     * @param  buf  append modifiers to the buffer
     * @return      true if there is any modifier, otherwise false
     */
    public boolean generateNewModifiers(StringBuffer buf) {
        for (Iterator annIt = getAnnotations().iterator(); annIt.hasNext(); ) {
            AnnotationImpl ann = (AnnotationImpl) annIt.next();
            buf.append(ann.getSourceText()).append(' ');
        }
        String modString = Modifier.toString(getSourceModifiers());
        if (modString.length() > 0) {
            buf.append(modString);
            buf.append(' ');
            return true;
        }
        else
            return false;
    }

    /**
     * Find referenced resources using ClassIndex.findResourcesForIdentifier().
     * Modifiers are considered to reduce number of resources
     */
    Resource[] findReferencedResources() {
        return findReferencedResources(false);
    }
    
    /**
     * Find referenced resources using ClassIndex.findResourcesForIdentifier().
     * Modifiers are considered to reduce number of resources
     */
    Resource[] findReferencedResources(boolean includeLibraries) {
        int modifiers=getModifiers();
        String name;
        Resource[] res;

        if (Modifier.isPrivate(modifiers)) {
            return new Resource[] {getResource()};
        }
        if (this instanceof JavaClass) {
            name=((JavaClass)this).getSimpleName();
        } else if (this instanceof Constructor) {
            name=((JavaClass)getDeclaringClass()).getSimpleName();
        } else {
            name=getName();
        }
        res=ClassIndex.findResourcesForIdentifier(name, includeLibraries);
        
        if (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) {
            if (this instanceof Field) {
                Element cd = getDeclaringClass();
                while (!((cd instanceof JavaClass) && !((JavaClass) cd).isInner())) {
                    cd = (Element) cd.refImmediateComposite();
                }
                int mods = ((JavaClass) cd).getModifiers();
                if (!(Modifier.isPublic(mods) || Modifier.isProtected(mods))) {
                    return filterResourcesFromThisPackage(res);
                }
            }
            return res;
        }
        return  filterResourcesFromThisPackage(res);
    }
    
    Resource[] filterResourcesFromThisPackage(Resource[] res) {
        List filteredResources=new ArrayList(res.length);
        String packageName=getResource().getPackageName();
        for (int i=0;i
... 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.