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.java.ui.nodes.elements;


import java.awt.Component;
import java.io.IOException;
import java.lang.reflect.Modifier; 
import java.util.*;
import java.beans.PropertyEditor;

import org.netbeans.modules.java.ui.nodes.elements.*;
import org.netbeans.modules.java.ui.nodes.editors.ModifierEditor;
import org.netbeans.modules.java.JavaNode;
import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
import org.netbeans.jmi.javamodel.*;
import org.netbeans.jmi.javamodel.Type;
import org.netbeans.api.java.queries.SourceLevelQuery;

import org.openide.*;
import org.openide.explorer.propertysheet.PropertyPanel;
import org.openide.filesystems.FileObject;
import org.openide.util.*;
import org.openide.util.datatransfer.NewType;

import javax.jmi.reflect.JmiException;

/** This class defines utilities for editing source using JMI API,
* e.g. creation new types for class elements, ...
*
* @author Petr Hamernik, Jan Pokorsky
*/
public final class SourceEditSupport {

    static final byte NT_INITIALIZER = 0;
    static final byte NT_FIELD = 1;
    static final byte NT_CONSTRUCTOR = 2;
    static final byte NT_METHOD = 3;
    static final byte NT_INNERCLASS = 4;
    static final byte NT_INNERINTERFACE = 5;
    static final byte NT_INNERENUM = 6;
    static final byte NT_ENUMCONSTANT = 7;
    static final byte NT_CLASS = 8;
    static final byte NT_INTERFACE = 9;
    static final byte NT_ENUM = 10;
    static final byte NT_ANNOTATION_TYPE = 11;
    static final byte NT_INNERANNOTATION_TYPE = 12;
    static final byte NT_ANNOTATION_TYPE_METHOD = 13;
    
    static final String[] MENU_NAMES = {
        getString("MENU_CREATE_BLOCK"), getString("MENU_CREATE_VARIABLE"), // NOI18N
        getString("MENU_CREATE_CONSTRUCTOR"), getString("MENU_CREATE_METHOD"), // NOI18N
        getString("MENU_CREATE_INNERCLASS"), getString("MENU_CREATE_INNERINTERFACE"), // NOI18N
        getString("MENU_CREATE_INNERENUM"), getString("MENU_CREATE_CONSTANT"), // NOI18N
        getString("MENU_CREATE_CLASS"), getString("MENU_CREATE_INTERFACE"), // NOI18N
        getString("MENU_CREATE_ENUM"), getString("MENU_CREATE_ANN_TYPE"), // NOI18N
        getString("MENU_CREATE_INNERANN_TYPE"), getString("MENU_CREATE_ANN_TYPE_METHOD"), // NOI18N
    };

    private static String getString(String key) {
        return NbBundle.getMessage(SourceEditSupport.class, key);
    }
    
    /**
     * creates class new types
     * @param element class
     * @param supportJDK15 support new 1.5 features
     * @return array of new type operations that are allowed
     * @see #isJDK15Supported
     */ 
    public static NewType[] createClassNewTypes(JavaClass element, boolean supportJDK15) {
        NewType[] ntypes;
        if (supportJDK15) { 
            ntypes = new NewType[] {
                new ElementNewType(element, NT_INITIALIZER),
                new ElementNewType(element, NT_FIELD),
                new ElementNewType(element, NT_CONSTRUCTOR),
                new ElementNewType(element, NT_METHOD),
                new ElementNewType(element, NT_INNERCLASS),
                new ElementNewType(element, NT_INNERENUM),
                new ElementNewType(element, NT_INNERINTERFACE),
                new ElementNewType(element, NT_INNERANNOTATION_TYPE),
            };
        } else {
            ntypes = new NewType[] {
                new ElementNewType(element, NT_INITIALIZER),
                new ElementNewType(element, NT_FIELD),
                new ElementNewType(element, NT_CONSTRUCTOR),
                new ElementNewType(element, NT_METHOD),
                new ElementNewType(element, NT_INNERCLASS),
                new ElementNewType(element, NT_INNERINTERFACE),
            };
        }
        return ntypes;
    }
    
    /**
     * creates interface new types
     * @param element interface
     * @param supportJDK15 support new 1.5 features
     * @return array of new type operations that are allowed
     * @see #isJDK15Supported
     */ 
    public static NewType[] createInterfaceNewTypes(JavaClass element, boolean supportJDK15) {
        NewType[] ntypes;
        if (supportJDK15) { 
            ntypes = new NewType[] {
                new ElementNewType(element, NT_FIELD),
                new ElementNewType(element, NT_METHOD),
                new ElementNewType(element, NT_INNERCLASS),
                new ElementNewType(element, NT_INNERENUM),
                new ElementNewType(element, NT_INNERINTERFACE),
                new ElementNewType(element, NT_INNERANNOTATION_TYPE),
            };
        } else {
            ntypes = new NewType[] {
                new ElementNewType(element, NT_FIELD),
                new ElementNewType(element, NT_METHOD),
                new ElementNewType(element, NT_INNERCLASS),
                new ElementNewType(element, NT_INNERINTERFACE),
            };
        }
        return ntypes;
    }
    
    /**
     * creates enum new types
     * @param element enum
     * @return array of new type operations that are allowed
     */ 
    public static NewType[] createEnumNewTypes(JavaEnum element) {
        return new NewType[] {
                new ElementNewType(element, NT_ENUMCONSTANT),
                new ElementNewType(element, NT_INITIALIZER),
                new ElementNewType(element, NT_FIELD),
                new ElementNewType(element, NT_CONSTRUCTOR),
                new ElementNewType(element, NT_METHOD),
                new ElementNewType(element, NT_INNERCLASS),
                new ElementNewType(element, NT_INNERENUM),
                new ElementNewType(element, NT_INNERINTERFACE),
                new ElementNewType(element, NT_INNERANNOTATION_TYPE),
            };
    }
    
    /**
     * creates annotation type new types
     * @param element annotation type
     * @return array of new type operations that are allowed
     */ 
    public static NewType[] createInterfaceNewTypes(AnnotationType element) {
        return new NewType[] {
                   new ElementNewType(element, NT_FIELD),
                   new ElementNewType(element, NT_ANNOTATION_TYPE_METHOD),
                   new ElementNewType(element, NT_INNERCLASS),
                   new ElementNewType(element, NT_INNERENUM),
                   new ElementNewType(element, NT_INNERINTERFACE),
                   new ElementNewType(element, NT_INNERANNOTATION_TYPE),
               };
    }

    /**
     * creates java node new types
     * @param node node
     * @return array of new type operations that are allowed
     */ 
    public static NewType[] createJavaNodeNewTypes(JavaNode node) {
        NewType[] ntypes;
        if (isJDK15Supported(node.getDataObject().getPrimaryFile())) {
            ntypes = new NewType[] {
                new ElementNewType(node, NT_CLASS),
                new ElementNewType(node, NT_ENUM),
                new ElementNewType(node, NT_INTERFACE),
                new ElementNewType(node, NT_ANNOTATION_TYPE),
            };
        } else {
            ntypes = new NewType[] {
                new ElementNewType(node, NT_CLASS),
                new ElementNewType(node, NT_INTERFACE),
            };
        }
        return ntypes;
    }
    
    public static boolean isJDK15Supported(FileObject source) {
        String version = SourceLevelQuery.getSourceLevel(source);
        return version != null && version.startsWith("1.5"); // NOI18N
    }
    
    /** New types for JavaClass */
    static final class ElementNewType extends NewType {
        /** Class element where to create new element */
        private final JavaClass element;
        /** Resource where to create new element */
        private final JavaNode node;

        /** The kind of element to create */
        byte kind;
        private static final String NEW_FIELD_NAME = "newField"; // NOI18N
        private static final String NEW_METHOD_NAME = "newMethod"; // NOI18N
        private static final String NEW_ANN_TYPE_METHOD_NAME = "newMethod"; // NOI18N
        private static final String NEW_INNERCLASS_NAME = "InnerClass"; // NOI18N
        private static final String NEW_INNERINTERFACE_NAME = "InnerInterface"; // NOI18N
        private static final String NEW_INNERENUM_NAME = "InnerEnum"; // NOI18N
        private static final String NEW_INNERANN_TYPE_NAME = "InnerNewAnnotationType"; // NOI18N
        private static final String NEW_CLASS_NAME = "NewClass"; // NOI18N
        private static final String NEW_INTERFACE_NAME = "NewInterface"; // NOI18N
        private static final String NEW_ENUM_NAME = "NewEnum"; // NOI18N
        private static final String NEW_ANN_TYPE_NAME = "NewAnnotationType"; // NOI18N

        /** Creates new type
        * @param element Where to create new element.
        * @param kind The kind of the element to create
        */
        public ElementNewType(JavaClass element, byte kind) {
            this.element = element;
            this.node = null;
            this.kind = kind;
        }

        /** Creates new type
        * @param node resource where to create new element.
        * @param kind The kind of the element to create
        */
        public ElementNewType(JavaNode node, byte kind) {
            this.element = null;
            this.node = node;
            this.kind = kind;
        }

        /** Get the name of the new type.
        * @return localized name.
        */
        public String getName() {
            return MENU_NAMES[kind];
        }

        /** Help context */
        public org.openide.util.HelpCtx getHelpCtx() {
            return new org.openide.util.HelpCtx (SourceEditSupport.class.getName () + ".newElement" + kind); // NOI18N
        }

        /** Creates new element */
        public void create () throws IOException {
            boolean fail = true;
            try {
                JavaMetamodel.getDefaultRepository().beginTrans(true);
                try {
                    createImpl();
                    fail = false;
                } finally {
                    JavaMetamodel.getDefaultRepository().endTrans(fail);
                }
            } catch (JmiException ex) {
                IOException ioe = new IOException();
                ioe.initCause(ex);
                throw ioe;
            }
        }
        
        /**
         * 
         * @throws JmiException
         */ 
        private void createImpl() throws JmiException {
            JavaModelPackage jmodel = getModel();

            switch (kind) {
                case NT_INITIALIZER:
                    createInitializer(jmodel);
                    break;
                case NT_FIELD:
                    createField(jmodel);
                    break;
                case NT_CONSTRUCTOR:
                    createConstructor(jmodel);
                    break;
                case NT_METHOD:
                    createMethod(jmodel);
                    break;
                case NT_INNERCLASS:
                    createInnerClass(jmodel);
                    break;
                case NT_INNERINTERFACE:
                    createInnerInterface(jmodel);
                    break;
                case NT_INNERENUM:
                    createInnerEnum(jmodel);
                    break;
                case NT_ENUMCONSTANT:
                    createConstant(jmodel);
                    break;
                case NT_CLASS:
                    createClass(jmodel);
                    break;
                case NT_INTERFACE:
                    createInterface(jmodel);
                    break;
                case NT_ENUM:
                    createEnum(jmodel);
                    break;
                case NT_ANNOTATION_TYPE:
                    createAnnotationType(jmodel);
                    break;
                case NT_INNERANNOTATION_TYPE:
                    createInnerAnnotationType(jmodel);
                    break;
                case NT_ANNOTATION_TYPE_METHOD:
                    createAnnotationTypeMethod(jmodel);
                    break;
                default:
                    assert true: "Unknown new type: " + kind; // NOI18N
            }
        }

        private void createInnerInterface(JavaModelPackage jmodel) throws JmiException {
            // Adding inner interface
            String name = NEW_INNERINTERFACE_NAME;
            for (int index = 1; element.getInnerClass(name, true) != null; index++) {
                name = NEW_INNERINTERFACE_NAME + '_' + index;
            }
            JavaClass e = jmodel.getJavaClass().createJavaClass(
                    name, null, Modifier.PUBLIC, null, null, null, null, null, null
            );
            e.setInterface(true);
            ClassCustomizer cust = new ClassCustomizer(element, e);
            if (openCustomizer(cust, "TIT_NewInnerInterface") && cust.isOK()) { // NOI18N
                addFeature(e);
            }
        }

        private void createInnerClass(JavaModelPackage jmodel) throws JmiException {
            // Adding inner class
            String name = NEW_INNERCLASS_NAME;
            for (int index = 1; element.getInnerClass(name, true) != null; index++) {
                name = NEW_INNERCLASS_NAME + '_' + index;
            }
            JavaClass e = jmodel.getJavaClass().createJavaClass(
                    name, null, Modifier.PUBLIC | Modifier.FINAL, null, null, null, null, null, null
            );
            e.setInterface(false);
            ClassCustomizer cust = new ClassCustomizer(element, e);
            if (openCustomizer(cust, "TIT_NewInnerClass") && cust.isOK()) { // NOI18N
                addFeature(e);
            }
        }

        private void createInterface(JavaModelPackage jmodel) throws JmiException {
            // Adding inner interface
            String name = NEW_INTERFACE_NAME;
            Resource resource = getResource();
            for (int index = 1; findTopLevelClass(resource, name) != null; index++) {
                name = NEW_INTERFACE_NAME + '_' + index;
            }
            JavaClass e = jmodel.getJavaClass().createJavaClass(
                    name, null, 0, null, null, null, null, null, null
            );
            e.setInterface(true);
            ClassCustomizer cust = new ClassCustomizer(resource, e);
            if (openCustomizer(cust, "TIT_NewInterface") && cust.isOK()) { // NOI18N
                resource.getClassifiers().add(e);
            }
        }

        private void createClass(JavaModelPackage jmodel) throws JmiException {
            // Adding inner class
            String name = NEW_CLASS_NAME;
            Resource resource = getResource();
            
            for (int index = 1; findTopLevelClass(resource, name) != null; index++) {
                name = NEW_CLASS_NAME + '_' + index;
            }
            JavaClass e = jmodel.getJavaClass().createJavaClass(
                    name, null, Modifier.FINAL, null, null, null, null, null, null
            );
            e.setInterface(false);
            ClassCustomizer cust = new ClassCustomizer(resource, e);
            if (openCustomizer(cust, "TIT_NewClass") && cust.isOK()) { // NOI18N
                resource.getClassifiers().add(e);
            }
        }

        private void createMethod(JavaModelPackage jmodel) throws JmiException {
            // Adding method
            Method e = jmodel.getMethod().createMethod();
            Type voidType = jmodel.getType().resolve(PrimitiveTypeKindEnum.VOID.toString());
            e.setType(voidType);

            String name = NEW_METHOD_NAME;
            for (int index = 1; element.getMethod(name, Collections.EMPTY_LIST, true) != null; index++) {
                name = NEW_METHOD_NAME + '_' + index;
            }
            e.setName(name);
                    
            e.setModifiers(Modifier.PUBLIC);
            MethodCustomizer cust = new MethodCustomizer(element, e);
            if (openCustomizer(cust, "TIT_NewMethod") && cust.isOK()) { // NOI18N
                addFeature(e);
            }
        }

        private void createConstructor(JavaModelPackage jmodel) throws JmiException {
            // Adding constructor
            Constructor e = jmodel.getConstructor().createConstructor();
            if (!(this.element instanceof JavaEnum))
                e.setModifiers(Modifier.PUBLIC);
            MethodCustomizer cust = new MethodCustomizer(element, e);
            if (openCustomizer(cust, "TIT_NewConstructor") && cust.isOK()) { // NOI18N
                addFeature(e);
            }
        }

        private void createField(JavaModelPackage jmodel) throws JmiException {
            // Adding field
            Field e = jmodel.getField().createField();
            Type type = jmodel.getType().resolve("int"); // NOI18N
            e.setType(type);

            String name = NEW_FIELD_NAME;
            for (int index = 1; element.getField(name, true) != null; index++) {
                name = NEW_FIELD_NAME + '_' + index;
            }
            e.setName(name);
                    
            boolean outerIsClass = !element.isInterface();
            e.setModifiers(outerIsClass? Modifier.PRIVATE : Modifier.PUBLIC | Modifier.STATIC);
            FieldCustomizer cust = new FieldCustomizer(element, e);
            if (openCustomizer(cust, "TIT_NewField") && cust.isOK()) { // NOI18N
                addFeature(e);
            }
        }

        private void createInitializer(JavaModelPackage jmodel) throws JmiException {
            // Adding initializer
            Initializer e = jmodel.getInitializer().createInitializer();
            e.setModifiers(Modifier.STATIC);
            addFeature(e);
        }

        private void createInnerEnum(JavaModelPackage jmodel) throws JmiException {
            // Adding inner enum
            String name = NEW_INNERENUM_NAME;
            for (int index = 1; element.getInnerClass(name, true) != null; index++) {
                name = NEW_INNERENUM_NAME + '_' + index;
            }
            JavaEnum e = jmodel.getJavaEnum().createJavaEnum(
                    name, null, Modifier.PUBLIC, null, null, null, null, null, null, null
            );
            EnumCustomizer cust = new EnumCustomizer(element, e);
            if (openCustomizer(cust, "TIT_NewInnerEnum") && cust.isOK()) { // NOI18N
                addFeature(e);
            }
        }

        private void createEnum(JavaModelPackage jmodel) throws JmiException {
            // Adding enum
            String name = NEW_ENUM_NAME;
            Resource resource = getResource();
            for (int index = 1; findTopLevelClass(resource, name) != null; index++) {
                name = NEW_ENUM_NAME + '_' + index;
            }
            JavaEnum e = jmodel.getJavaEnum().createJavaEnum(
                    name, null, 0, null, null, null, null, null, null, null
            );
            EnumCustomizer cust = new EnumCustomizer(resource, e);
            if (openCustomizer(cust, "TIT_NewEnum") && cust.isOK()) { // NOI18N
                resource.getClassifiers().add(e);
            }
        }
        
        private void createConstant(JavaModelPackage jmodel) throws JmiException {
            JavaEnum en = (JavaEnum) this.element;
            EnumConstant e = jmodel.getEnumConstant().createEnumConstant();

            final String ENUM_NAME = en.getSimpleName();
            String name = ENUM_NAME;
            for (int index = 1; findConstant(en, name) != null; index++) {
                name = ENUM_NAME + '_' + index;
            }
            e.setName(name);
                    
            EnumConstantCustomizer cust = new EnumConstantCustomizer(en, e);
            if (openCustomizer(cust, "TIT_NewConstant") && cust.isOK()) { // NOI18N
                en.getConstants().add(e);
            }
            return;
        }

        private void createInnerAnnotationType(JavaModelPackage jmodel) throws JmiException {
            // Adding inner annotation type
            String name = NEW_INNERANN_TYPE_NAME;
            for (int index = 1; element.getInnerClass(name, true) != null; index++) {
                name = NEW_INNERANN_TYPE_NAME + '_' + index;
            }
            AnnotationType at = jmodel.getAnnotationType().createAnnotationType(
                    name, null, Modifier.PUBLIC, null, null, null, null, null, null
            );
            AnnotationTypeCustomizer cust = new AnnotationTypeCustomizer(element, at);
            if (openCustomizer(cust, "TIT_NewInnerAnnType") && cust.isOK()) { // NOI18N
                addFeature(at);
            }
        }

        private void createAnnotationType(JavaModelPackage jmodel) throws JmiException {
            // Adding enum
            String name = NEW_ANN_TYPE_NAME;
            Resource resource = getResource();
            for (int index = 1; findTopLevelClass(resource, name) != null; index++) {
                name = NEW_ANN_TYPE_NAME + '_' + index;
            }
            AnnotationType at = jmodel.getAnnotationType().createAnnotationType(
                    name, null, Modifier.PUBLIC, null, null, null, null, null, null
            );
            AnnotationTypeCustomizer cust = new AnnotationTypeCustomizer(resource, at);
            if (openCustomizer(cust, "TIT_NewAnnType") && cust.isOK()) { // NOI18N
                resource.getClassifiers().add(at);
            }
        }

        private void createAnnotationTypeMethod(JavaModelPackage jmodel) throws JmiException {
            // Adding annotation type method
            AnnotationType at = (AnnotationType) this.element;
            String name = NEW_ANN_TYPE_METHOD_NAME;
            for (int index = 1; findAttribute(at, name) != null; index++) {
                name = NEW_ANN_TYPE_METHOD_NAME + '_' + index;
            }
            Type type = jmodel.getType().resolve("java.lang.String"); // NOI18N
            Attribute attr = jmodel.getAttribute().createAttribute(name, null, 0, null, null, null, null, null);
            attr.setType(type);
            AnnotationTypeMethodCustomizer cust = new AnnotationTypeMethodCustomizer(at, attr);
            if (openCustomizer(cust, "TIT_NewAnnTypeMethod") && cust.isOK()) { // NOI18N
                addFeature(attr);
            }
        }
        
        /* This method prevents features to be inserted into gurded blocks.
         * It is a temporal solution - we need to fix the problem in javacore.
         */
        private void addFeature(Feature feature) {
            List features = new ArrayList(element.getFeatures()); // [PENDING] workaround for buggy FeaturesListIterator
            ListIterator iter = features.listIterator(features.size());
            ClassMember f = iter.hasPrevious() ? (ClassMember)iter.previous() : null;
            JavaMetamodel manager = JavaMetamodel.getManager();
            if (f == null || !manager.isElementGuarded(f)) {
                element.getFeatures().add(feature);
                return;
            }
            do {
                f = (ClassMember)iter.previous();
            } while (f != null && manager.isElementGuarded(f));
            iter = element.getFeatures().listIterator();
            if (f != null) {
                for (; iter.next() != f; );
            }
            iter.add(feature);
        }
        
        private Resource getResource() {
            return JavaMetamodel.getManager().getResource(node.getDataObject().getPrimaryFile());
        }
        
        private JavaModelPackage getModel() {
            if (this.element != null) {
                return JavaMetamodel.getManager().getJavaExtent(this.element);
            } else {
                return JavaMetamodel.getManager().getJavaExtent(getResource());
            }
        }
    }
    
    /**
     * finds attribute (annotation type method) in a annotation type
     * @param at annotation type to query
     * @param name name to find
     * @return the attribute or null
     * @throws JmiException
     */ 
    static Attribute findAttribute(AnnotationType at, String name) throws JmiException {
        if (at == null) throw new NullPointerException("at"); // NOI18N
        if (name == null) throw new NullPointerException("name"); // NOI18N
        Iterator it = at.getFeatures().iterator();
        while (it.hasNext()) {
            Object o = it.next();
            if (o instanceof Attribute && name.equals(((Attribute) o).getName())) {
                return (Attribute) o;
            }
        }
        return null;
    }
    
    /**
     * finds constant in an enumeration
     * @param en enumeration to query
     * @param name name to find
     * @return the constant or null
     * @throws JmiException
     */ 
    static EnumConstant findConstant(JavaEnum en, String name) throws JmiException {
        if (en == null) throw new NullPointerException("en"); // NOI18N
        if (name == null) throw new NullPointerException("name"); // NOI18N
        Iterator it = en.getConstants().iterator();
        while (it.hasNext()) {
            EnumConstant ec = (EnumConstant) it.next();
            if (name.equals(ec.getName()))
                return ec;
        }
        return null;
    }
    
    /**
     * finds top level class in java resource
     * @param res a java resource
     * @param name name to find
     * @return the class/interface/enum or null
     * @throws JmiException
     */ 
    static JavaClass findTopLevelClass(Resource res, String name) throws JmiException {
        if (res == null) throw new NullPointerException("res"); // NOI18N
        if (name == null) throw new NullPointerException("name"); // NOI18N
        Iterator it = res.getClassifiers().iterator();
        while (it.hasNext()) {
            JavaClass jc = (JavaClass) it.next();
            if (name.equals(jc.getSimpleName()))
                return jc;
        }
        return null;
    }
    
    /** Show dialog and allow user to modify new element.
    * @param customizer The component to be displayed
    * @param titleKey the key to resource bundle for the title of dialog
    * @return true if user pressed OK button,
    *     otherwise false (for CANCEL)
    */
    static boolean openCustomizer(Component customizer, String titleKey) {
        NotifyDescriptor desriptor = new NotifyDescriptor(
                                         customizer,
                                         ElementNode.getString(titleKey),
                                         NotifyDescriptor.OK_CANCEL_OPTION,
                                         NotifyDescriptor.PLAIN_MESSAGE,
                                         null, null);

        Object ret = DialogDisplayer.getDefault().notify(desriptor);
        return (ret == NotifyDescriptor.OK_OPTION);
    }

    static boolean isWriteable(Element element) {
        boolean w = element.isValid();
        if (w) {
            FileObject fo = JavaMetamodel.getManager().getFileObject(element.getResource());
            w = fo != null && fo.canWrite();
        }
        return w;
    }

    public static PropertyPanel createAccessModifiersPanel(ClassMember element, int mask) {
        PropertyPanel pp = createModifiersPanel(element, mask);
        pp.getProperty().setValue(ModifierEditor.CUSTOM_EDITOR_TYPE, ModifierEditor.ACCESS_MODIFIERS_CUSTOM_EDITOR);
        return pp;
    }

    public static PropertyPanel createOtherModifiersPanel(ClassMember element, int mask) {
        PropertyPanel pp = createModifiersPanel(element, mask);
        pp.getProperty().setValue(ModifierEditor.CUSTOM_EDITOR_TYPE, ModifierEditor.OTHERS_MODIFIERS_CUSTOM_EDITOR);
        return pp;
    }
    
    public static PropertyPanel createModifiersPanel(ClassMember element) {
        return createModifiersPanel(element, getModifiersMask(element));
    }
    
    private static PropertyPanel createModifiersPanel(ClassMember element, int mask) {
        PropertyPanel modifPanel = new PropertyPanel(
                ElementNode.createModifiersProperty(element, true),
                PropertyPanel.PREF_CUSTOM_EDITOR
        );
        PropertyEditor propEdit = modifPanel.getProperty().getPropertyEditor();
        if (propEdit instanceof ModifierEditor) {
            ((ModifierEditor) propEdit).setMask(mask);
        }
        return modifPanel;
    }

    /* Get the possible modifiers for the member.
     * @return the mask of possible modifiers for this class member. */
    public static int getModifiersMask(ClassMember member) throws JmiException {
        int mask = 0;
        if (member instanceof Field) {
            mask = getModifiersMask((Field) member);
        } else if (member instanceof Method) {
            mask = getModifiersMask((Method) member);
        } else if (member instanceof Constructor) {
            mask = getModifiersMask((Constructor) member);
        } else if (member instanceof Attribute) {
            mask = getAttributeModifiersMask();
        } else if (member instanceof JavaClass) {
            mask = getModifiersMask((JavaClass) member);
        } else {
            ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
                    new IllegalStateException("SourceNodes.getModifiersMask: unknown member: " + member)); // NOI18N
        }
        return mask;
    }

    private static int getModifiersMask(Field member) throws JmiException {
        if (isDeclaredInInterface(member)) {
            return Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL;
        }
        else {
            return Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
                   Modifier.STATIC | Modifier.FINAL | Modifier.TRANSIENT |
                   Modifier.VOLATILE;
        }
    }

    private static int getModifiersMask(Method member) throws JmiException {
        if (isDeclaredInInterface(member)) {
            return Modifier.PUBLIC | Modifier.ABSTRACT;
        }
        else {
            return Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
                   Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL |
                   Modifier.NATIVE | Modifier.SYNCHRONIZED;
        }
    }

    private static int getModifiersMask(Constructor member) {
        return Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE;
    }

    private static int getAttributeModifiersMask() {
        return Modifier.PUBLIC | Modifier.ABSTRACT;
    }

    private static int getModifiersMask(JavaClass member) throws JmiException {
        int ret = Modifier.ABSTRACT;

        if (!member.isInterface()) {
            ret |= Modifier.FINAL;
        }

        if (isInner(member)) {
            ret |= Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | Modifier.STATIC;
        }
        return ret;
    }
    
    /** Test if this is an inner class.
    * If so, it has a declaring class.
    * @return true if so
    */
    private static boolean isInner(JavaClass jclass) throws JmiException {
        return (jclass.getDeclaringClass() != null);
    }

    private static boolean isDeclaredInInterface(ClassMember member) throws JmiException {
        ClassDefinition cdef = member.getDeclaringClass();
        return cdef instanceof JavaClass && ((JavaClass) cdef).isInterface();
    }
    
    /**
     * Gets all classes recursively, both top-level and inner.
     * @param res java resource
     * @return all classes
     * @throws JmiException
     */
    public static List/**/ getAllClasses(Resource res) throws JmiException {
        List/**/ l = new LinkedList/**/();
        Iterator/**/ it = res.getClassifiers().iterator();
        while (it.hasNext()) {
            addAllClasses((JavaClass) it.next(), l);
        }
        return l;
    }
    
    private static void addAllClasses(JavaClass jc, List/**/ container) throws JmiException {
        container.add(jc);
        Iterator it = jc.getFeatures().iterator();
        while (it.hasNext()) {
            Object feature = it.next();
            if (feature instanceof JavaClass) {
                addAllClasses((JavaClass) feature, container);
            }
        }
    }

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