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 java.util.AbstractSequentialList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import javax.jmi.reflect.ConstraintViolationException;
import javax.jmi.reflect.RefObject;
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.AttrListWrapper;
import org.netbeans.mdr.storagemodel.StorableObject;
import org.netbeans.mdr.persistence.StorageException;
import org.netbeans.modules.javacore.parser.ASTProvider;
import org.netbeans.modules.javacore.parser.ClassInfo;
import org.netbeans.modules.javacore.parser.ElementInfo;
import org.netbeans.modules.javacore.parser.EnumInfo;
import org.openide.ErrorManager;

/**
 * Implementation of the JavaEnum model element.
 *
 * @author  Martin Matula
 */
public abstract class JavaEnumImpl extends JavaClassImpl implements JavaEnum {
    static final ElementInfo DEFAULT_INFO = new EnumInfo(null, EnumInfo.ENUM_TYPE, null, 0, null, null, null, null);

    public static final boolean DEBUG = false;
    
    public static final String CONSTANTS_ATTR = "constants";

    private LightAttrList constants = null;
    private final MergedFeaturesList features = new MergedFeaturesList();

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

    /**
     * Returns the value of attribute isInterface.
     * @return Value of attribute isInterface.
     */
    public boolean isInterface() {
        return false;
    }

    /**
     * Sets the value of isInterface attribute. See {@link #isInterface} for description
     * on the attribute.
     * @param newValue New value to be set.
     */
    public void setInterface(boolean newValue) {
        if (newValue) {
            throw new ConstraintViolationException(null, null, "Cannot set interface modifier to true for enum."); // NOI18N
        }
    }

    /**
     * Returns the value of reference superClass.
     * @return Value of reference superClass.
     */
    public JavaClass getSuperClass() {
        JavaModelPackage extent = (JavaModelPackage) refImmediatePackage();
        JavaClass enumCls = (JavaClass) extent.getType().resolve("java.lang.Enum"); // NOI18N
        return extent.getParameterizedType().resolveParameterizedType(enumCls, Collections.singletonList(this), null);
    }

    /**
     * Sets the value of reference superClass. See {@link #getSuperClass} for
     * description on the reference.
     * @param newValue New value to be set.
     */
    public void setSuperClass(JavaClass newValue) {
        if (newValue == null || !((ClassInfo) getElementInfo()).superclass.equals(newValue.getName())) {
            throw new ConstraintViolationException(null, null, "Cannot set superclass of an enumeration type to: " + newValue == null ? null : newValue.getName()); // NOI18N
        }
    }

    public List getPersistentConstants() {
        AttrListWrapper list = (AttrListWrapper) super_getConstants();
        list.setAttrName(CONSTANTS_ATTR);
        return list;
    }

    private List getNakedConstants() {
        try {
            return (List) ((StorableObject) _getDelegate()).getAttribute(CONSTANTS_ATTR);
        } catch (StorageException e) {
            throw (GeneralException) ErrorManager.getDefault().annotate(new RuntimeException(e.getMessage()), e);
        }
    }

    public List getConstants() {
        if (constants == null) {
            checkUpToDate();
            constants = createChildrenList(CONSTANTS_ATTR, (AttrListWrapper) super_getConstants(), null, CHANGED_CONSTANTS);
        }
        return constants;
    }
    
    public List getFeatures() {
        return features;
    }

    protected abstract List super_getConstants();

    // ----------------------------------------------------------------------
    // --- Infrastructural methods ------------------------------------------
    // ----------------------------------------------------------------------

    protected ElementInfo getDefaultInfo() {
        return DEFAULT_INFO;
    }
    
    protected void matchPersistent(ElementInfo newInfo) {
        if (!isPersisted()) {
            persistChildren(super_getConstants(), ((EnumInfo) newInfo).constants);
        } else {
            processMembers(getConstants(), ((EnumInfo) newInfo).constants);
        }
        
        super.matchPersistent(newInfo);
    }

    public String toString() {
        return "enum " + getName(); // NOI18N
    }

    protected List getInitedChildren() {
        List list = super.getInitedChildren();
        if (childrenInited)
            list.addAll(getConstants());
        return list;
    }

    public List getChildren() {
        List list = new ArrayList();
        list.addAll(getInterfaceNames());
        list.addAll(getConstants());
        list.addAll(getContents());
        return list;
    }

    /** This method is called when this element is accessed while bypassing
     * parent (e.g. using getByMofId()) and thus its ASTInfo needs to be
     * initialized by its parent.
     *
     * Preciselly: This method is invoked from getElementInfo of a child object
     * if it finds out that ASTInfo was not initialized by its parent (i.e.
     * this object), yet.
     * This method should also be called whenever a getter method
     * for children of this object is called and the children have not
     * been initialized yet.
     */
    protected void initChildren() {
        // initialization of contents requires writable lock
        boolean fail = true;
        _lock(true);
        try {
            childrenInited = false;
            constants = createChildrenList(constants, CONSTANTS_ATTR, (AttrListWrapper) super_getConstants(), ((EnumInfo) getElementInfo()).constants, CHANGED_CONSTANTS);
            super.initChildren();
            fail = false;
        } finally {
            _unlock(fail);
        }
    }

    protected void setData(List annotations, String javadocText, JavaDoc javadoc, List constants, List features, List interfaceNames) {
        this.constants = createChildrenList(CONSTANTS_ATTR, (AttrListWrapper) super_getConstants(), constants, CHANGED_CONSTANTS);
        super.setData(annotations, javadocText, javadoc, features, null, interfaceNames, null);
    }

    // .........................................................................
    // printing and formatting fuctionality
    // .........................................................................

    public String getSourceText() {
        String origElem;
        if ((origElem = checkChange()) != null)
            return origElem;
        StringBuffer buf = new StringBuffer();
        buf.append('\n');
        generateNewJavaDoc(buf);
        buf.append(getIndentation());
        generateNewModifiers(buf);
        buf.append("enum "); // NOI18N
        buf.append(getSimpleName());
        generateNewImplements(buf);
        formatElementPart(CLASS_OPEN_CURLY, buf);
        if (!getConstants().isEmpty())
            buf.append(getInnerIndentation(2));
        for (Iterator it = getConstants().iterator(); it.hasNext();) {
            MetadataElement constant = (MetadataElement) it.next();
            buf.append(constant.getSourceText());
            if (it.hasNext()) formatElementPart(COMMA, buf);
        }
        if (!getContents().isEmpty()) {
            // there isn't any feature, do not put semicolon at the end
            // of constant declaration.
            buf.append(";\n\n"); // NOI18N
        } else {
            if (!getConstants().isEmpty()) {
                buf.append('\n');
            }
        }
        ClassDefinitionImpl.generateNewFeatures(this, buf, false);
        formatElementPart(CLASS_CLOSE_CURLY, buf);
        return buf.toString();
    }

    /**
     *
     */
    public void getDiff(List diffList) {
        EnumInfo astInfo = (EnumInfo) getElementInfo();
        ASTProvider parser = getParser();
        ASTree[] children = getASTree().getSubTrees();

        // javadoc print
        replaceJavaDoc(diffList);
        // print modifiers
        if (isChanged(CHANGED_MODIFIERS)) {
            diffModifiers(diffList, parser.getToken(children[IDENTIFIER].getFirstToken() - 1), parser);
        }
        // print name
        if (isChanged(CHANGED_NAME)) {
            replaceNode(diffList, parser, children[IDENTIFIER], getSimpleName(), 0, null);
        }
        // interfaces
        int startOffset = parser.getToken(children[IDENTIFIER].getLastToken()).getEndOffset();
        String prefix = formatElementPart(IMPLEMENTS_KEYWORD);
        getCollectionDiff(diffList, parser, CHANGED_IMPLEMENTS, getASTree().getSubTrees()[INTERFACES],
                getInterfaceNames(), startOffset, formatElementPart(COMMA), prefix);

        // constants and contents diff
        int endOffset;
        int constEndOffset;
        ASTree body = children[BODY].getSubTrees()[ENUM_BODY_DECLARATIONS];
        {
            Token closeBrace = parser.getToken(getASTree().getLastToken());
            Token[] pad = closeBrace.getPadding();
            constEndOffset = endOffset = pad.length > 0 ? pad[0].getStartOffset() : closeBrace.getStartOffset();
        }
        if (body != null) {
            Token bodyDecls = parser.getToken(body.getFirstToken());
            Token[] pad = bodyDecls.getPadding();
            constEndOffset = pad.length > 0 ? pad[0].getStartOffset() : bodyDecls.getStartOffset();
        }
        getCollectionDiff(diffList, parser, CHANGED_CONSTANTS, astInfo.constants, getConstants(), constEndOffset, ", ", false); // NOI18N
        ASTree constants = children[BODY].getSubTrees()[ENUM_CONSTANTS];
        if (!getContents().isEmpty() && (body == null)) { 
            diffList.add(new DiffElement(constEndOffset, constEndOffset, ";")); // NOI18N
        }
        getCollectionDiff(diffList, parser, CHANGED_FEATURES, astInfo.features, getContents(), endOffset, "\n"); // NOI18N
    }

    protected ASTree getPartTree(ElementPartKind part) {
        if (ElementPartKindEnum.NAME.equals(part)) {
            return getASTree().getSubTrees()[IDENTIFIER];
        }
        throw new IllegalArgumentException("Invalid part for this element: " + part); // NOI18N
    }

    protected ASTree getPartStartTree(ElementPartKind part) {
        if (ElementPartKindEnum.HEADER.equals(part)) {
            return getASTree();
        }
        return super.getPartStartTree(part);
    }

    protected ASTree getPartEndTree(ElementPartKind part) {
        if (ElementPartKindEnum.HEADER.equals(part)) {
            for (int i = 2; true; i--) {
                ASTree result = getASTree().getSubTrees()[i];
                if (result != null) {
                    return result;
                }
            }
        }
        return super.getPartEndTree(part);
    }

    // useful constants
    private static final int IDENTIFIER = 1;
    private static final int INTERFACES = 2;
    private static final int BODY = 3;
    private static final int ENUM_CONSTANTS = 0;
    private static final int ENUM_BODY_DECLARATIONS = 1;

    // ---------------------------------------------------------------------
    // --- Private methods -------------------------------------------------
    // ---------------------------------------------------------------------

    public void replaceChild(Element oldElement, Element newElement) {
        if (isPersisted()) {
            if (replaceObject(getConstants(), oldElement, newElement)) return;
        }
        super.replaceChild(oldElement, newElement);
    }

    protected void _delete() {
        // --- delete components -------------------------------------------
        deleteChildren(CONSTANTS_ATTR, (AttrListWrapper) super_getConstants());
        super._delete();
    }

    public MultipartId getSuperClassName() {
        return null;
    }

    public void setSuperClassName(MultipartId newValue) {
        if (newValue != null) {
            throw new ConstraintViolationException(null, null, "Cannot set superclass name of enum."); // NOI18N
        }
    }
    
    private class MergedFeaturesList extends AbstractSequentialList {
        private void lock() {
            lock(false);
        }

        private void lock(boolean readWrite) {
            repository().beginTrans(readWrite);
        }

        private void unlock() {
            unlock(false);
        }

        private void unlock(boolean fail) {
            repository().endTrans(fail);
        }

        public int size() {
            lock();
            try {
                return getConstants().size() + JavaEnumImpl.super.getFeatures().size();
            } finally {
                unlock();
            }
        }
        
        public ListIterator listIterator(int index) {
            lock();
            try {
                return new It(index);
            } finally {
                unlock();
            }
        }
        
        private class It implements ListIterator {
            private final ListIterator constantsIterator;
            private final ListIterator featuresIterator;
            private ListIterator currIterator;
            
            It(int index) {
                List constants = getConstants();
                int size = constants.size();
                if (index <= size) {
                    constantsIterator = constants.listIterator(index);
                    featuresIterator = JavaEnumImpl.super.getFeatures().listIterator();
                    currIterator = constantsIterator;
                } else {
                    constantsIterator = constants.listIterator(size);
                    featuresIterator = JavaEnumImpl.super.getFeatures().listIterator(index - size);
                    currIterator = featuresIterator;
                }
            }
            
            public void add(Object o) {
                boolean fail = true;
                lock(true);
                try {
                    if (o instanceof EnumConstant) {
                        if (featuresIterator.nextIndex() != 0) {
                            throw new IllegalStateException();
                        }
                        constantsIterator.add(o);
                        currIterator = constantsIterator;
                    } else {
                        if (constantsIterator.nextIndex() != getConstants().size()) {
                            throw new IllegalStateException();
                        }
                        featuresIterator.add(o);
                        currIterator = featuresIterator;
                    }
                    fail = false;
                } finally {
                    unlock(fail);
                }
            }
            
            public boolean hasNext() {
                lock();
                try {
                    return constantsIterator.hasNext() || featuresIterator.hasNext();
                } finally {
                    unlock();
                }
            }
            
            public boolean hasPrevious() {
                lock();
                try {
                    return constantsIterator.hasPrevious() || featuresIterator.hasPrevious();
                } finally {
                    unlock();
                }
            }
            
            public Object next() {
                lock();
                try {
                    if (constantsIterator.hasNext()) {
                        currIterator = constantsIterator;
                        return constantsIterator.next();
                    }
                    currIterator = featuresIterator;
                    return featuresIterator.next();
                } finally {
                    unlock();
                }
            }
            
            public int nextIndex() {
                lock();
                try {
                    return featuresIterator.nextIndex() + constantsIterator.nextIndex();
                } finally {
                    unlock();
                }
            }
            
            public Object previous() {
                lock();
                try {
                    if (featuresIterator.hasPrevious()) {
                        currIterator = featuresIterator;
                        return featuresIterator.previous();
                    }
                    currIterator = constantsIterator;
                    return constantsIterator.previous();
                } finally {
                    unlock();
                }
            }
            
            public int previousIndex() {
                lock();
                try {
                    return featuresIterator.nextIndex() + constantsIterator.previousIndex();
                } finally {
                    unlock();
                }
            }
            
            public void remove() {
                boolean fail = true;
                lock(true);
                try {
                    currIterator.remove();
                    fail = false;
                } finally {
                    unlock(fail);
                }
            }
            
            public void set(Object o) {
                boolean fail = true;
                lock(true);
                try {
                    if (o instanceof EnumConstant) {
                        if (currIterator != constantsIterator) {
                            throw new IllegalStateException();
                        }
                    } else {
                        if (currIterator == constantsIterator) {
                            throw new IllegalStateException();
                        }
                    }
                    currIterator.set(o);
                    fail = false;
                } finally {
                    unlock(fail);
                }
            }
        }
    }
}
... 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.