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.beans;

import java.beans.Introspector;
import java.beans.IntrospectionException;
import java.text.MessageFormat;
import java.util.ResourceBundle;
import java.lang.reflect.Modifier;
import org.openide.DialogDisplayer;

import org.openide.src.ClassElement;
import org.openide.src.MethodElement;
import org.openide.src.MethodParameter;
import org.openide.src.Type;
import org.openide.src.Identifier;
import org.openide.src.SourceException;
import org.openide.nodes.Node;
import org.openide.NotifyDescriptor;
import org.openide.util.Utilities;
import org.openide.util.NbBundle;

/** EventSetPattern: This class holds the information about used event set pattern
 * in code.
 * @author Petr Hrebejk
 *
 * 
 *  PENDING: Add Pattern class hierarchy (abstract classes || interfaces )
 */
public class EventSetPattern extends Pattern {

    static final String[] WELL_KNOWN_LISTENERS =  new String[] {
                "java.awt.event.ActionListener", // NOI18N
                "java.awt.event.ContainerListener", // NOI18N
                "java.awt.event.FocusListener", // NOI18N
                "java.awt.event.ItemListener", // NOI18N
                "java.awt.event.KeyListener", // NOI18N
                "java.awt.event.MouseListener", // NOI18N
                "java.awt.event.MouseMotionListener", // NOI18N
                "java.awt.event.WindowListener", // NOI18N
                "java.beans.PropertyChangeListener", // NOI18N
                "java.beans.VetoableChangeListener", // NOI18N
                "javax.swing.event.CaretListener", // NOI18N
                "javax.swing.event.ChangeListener", // NOI18N
                "javax.swing.event.DocumentListener", // NOI18N
                "javax.swing.event.HyperlinkListener", // NOI18N
                "javax.swing.event.MenuListener", // NOI18N
                "javax.swing.event.MouseInputListener", // NOI18N
                "javax.swing.event.PopupMenuListener", // NOI18N
                "javax.swing.event.TableColumnModelListener", // NOI18N
                "javax.swing.event.TableModelListener", // NOI18N
                "javax.swing.event.TreeModelListener", // NOI18N
                "javax.swing.event.UndoableEditListener" // NOI18N
            };


    protected MethodElement addListenerMethod = null;
    protected MethodElement removeListenerMethod = null;

    private Type type;
    private boolean isUnicast = false;
    private ClassElement typeElement;

    /** holds the decapitalized name */
    protected String name;

    /** Creates new PropertyPattern one of the methods may be null */
    public EventSetPattern( PatternAnalyser patternAnalyser,
                            MethodElement addListenerMethod, MethodElement removeListenerMethod )
    throws IntrospectionException {
        super( patternAnalyser );

        if ( addListenerMethod == null || removeListenerMethod == null  )
            throw new InternalError();

        this.addListenerMethod = addListenerMethod;
        this.removeListenerMethod = removeListenerMethod;

        isUnicast = testUnicast();
        findEventSetType();
        name = findEventSetName();

        typeElement = patternAnalyser.findClassElement( type.getClassName().getFullName() ) ;


    }

    private EventSetPattern( PatternAnalyser patternAnalyser ) {
        super( patternAnalyser );
    }

    static EventSetPattern create( PatternAnalyser patternAnalyser,
                                   String name, String type, boolean isUnicast ) throws SourceException {

        EventSetPattern esp = new EventSetPattern( patternAnalyser );

        esp.name = name;
        esp.type = Type.parse( type );
        esp.isUnicast = isUnicast;

        esp.generateAddListenerMethod();
        esp.generateRemoveListenerMethod();

        return esp;
    }

    /** Creates new pattern from result of dialog */

    static EventSetPattern create( PatternAnalyser patternAnalyser,
                                   String type,
                                   int implementation,
                                   boolean fire,
                                   boolean passEvent,
                                   boolean isUnicast ) throws SourceException {

        EventSetPattern esp = new EventSetPattern( patternAnalyser );

        esp.type = Type.parse( type );

        if ( esp.type == null || !esp.type.isClass() ) {
            return null;
        }

        //System.out.println( "Type " + esp.type.toString() ); // NOI18N


        esp.name = Introspector.decapitalize( esp.type.getClassName().getName() );
        esp.isUnicast = isUnicast;

        String listenerList = null;

        if ( implementation == 1 ) {
            if ( isUnicast )
                BeanPatternGenerator.unicastListenerField( esp.getDeclaringClass(), esp.type );
            else
                BeanPatternGenerator.listenersArrayListField( esp.getDeclaringClass(), esp.type );
        }
        else if ( implementation == 2 && !isUnicast ) {
            listenerList = BeanPatternGenerator.eventListenerListField( esp.getDeclaringClass(), esp.type );
        }


        if ( isUnicast ) {
            esp.generateAddListenerMethod( BeanPatternGenerator.ucAddBody( esp.type, implementation ), true );
            esp.generateRemoveListenerMethod( BeanPatternGenerator.ucRemoveBody( esp.type, implementation ), true );
        }
        else {
            esp.generateAddListenerMethod( BeanPatternGenerator.mcAddBody( esp.type, implementation, listenerList ), true );
            esp.generateRemoveListenerMethod( BeanPatternGenerator.mcRemoveBody( esp.type, implementation, listenerList ), true );
        }

        if ( fire ) {
            ClassElement listener = patternAnalyser.findClassElement( type.toString() );


            if ( listener != null ) {
                MethodElement methods[] = listener.getMethods();
                boolean isInterface = !listener.isClassOrInterface();
                for( int i = 0; i < methods.length; i++ ) {
                    if ( ((methods[i].getModifiers() & Modifier.PUBLIC) != 0 ) ||
                         (isInterface && (methods[i].getModifiers() & (Modifier.PROTECTED | Modifier.PRIVATE)) == 0)
                       ) {
                        if ( isUnicast )
                            BeanPatternGenerator.unicastFireMethod( esp.getDeclaringClass(), esp.type,
                                                                    methods[i], implementation, passEvent );
                        else
                            BeanPatternGenerator.fireMethod( esp.getDeclaringClass(), esp.type,
                                                             methods[i], implementation, listenerList, passEvent );
                    }
                }

            }
        }


        return esp;
    }


    public ClassElement getTypeElement() {
        return typeElement;
    }

    /** Gets the name of PropertyPattern */
    public String getName() {
        return name;
    }

    /** Sets the name of PropertyPattern */
    public void setName( String name ) throws SourceException {

        if ( !Utilities.isJavaIdentifier( name ) || name.indexOf( "Listener" ) <= 0 ) // NOI18N
            throw new SourceException( "Invalid event source name" ); // NOI18N

        name = capitalizeFirstLetter( name );

        Identifier addMethodID = Identifier.create( "add" + name ); //+ "Listener" ); // NOI18N
        Identifier removeMethodID = Identifier.create( "remove" + name ); //+ "Listener" ); // NOI18N

        addListenerMethod.setName( addMethodID );
        removeListenerMethod.setName( removeMethodID );

        this.name = Introspector.decapitalize( name );
    }

    /** Test if the name is valid for given pattern */
    protected static boolean isValidName( String str ) {
        if ( Utilities.isJavaIdentifier(str) == false )
            return false;

        if (str.indexOf( "Listener" ) <= 0 ) // NOI18N
            return false;

        return true;
    }

    /** Returns the mode of the property READ_WRITE, READ_ONLY or WRITE_ONLY */
    public boolean isUnicast() {
        return isUnicast;
    }

    /** Sets the property to be unicast or multicast */
    public void setIsUnicast( boolean b ) throws SourceException {
        if ( b != isUnicast) {
            Identifier tooMany = Identifier.create( "java.util.TooManyListenersException" ); // NOI18N
            Identifier[] exs = addListenerMethod.getExceptions();

            if (b) {
                Identifier[] nexs = new Identifier[exs.length + 1];
                System.arraycopy( exs, 0, nexs, 0, exs.length );
                nexs[ exs.length ] = tooMany;
                addListenerMethod.setExceptions( nexs );
            }
            else {
                Identifier[] nexs = new Identifier[exs.length -1];
                int found = 0;
                for( int i = 0; i < exs.length; i++ ) {
                    if ( !exs[i].compareTo( tooMany, false ) )
                        nexs[i-found] = exs[i];
                    else
                        found = 1;
                }
                addListenerMethod.setExceptions( nexs );
            }
        }
        this.isUnicast = b;
    }

    /** Returns the getter method */
    public MethodElement getAddListenerMethod() {
        return addListenerMethod;
    }

    /** Returns the setter method */
    public MethodElement getRemoveListenerMethod() {
        return removeListenerMethod;
    }

    /** Gets the type of property */
    public Type getType() {
        return type;
    }

    /** Sets the type of property */
    public void setType( Type newType ) throws SourceException {

        if ( newType.compareTo(type, true))
            return;

        //try {

        //if (!java.util.EventListener.class.isAssignableFrom( newType.toClass() ) ) {
        if ( !PatternAnalyser.isSubclass(
                    patternAnalyser.findClassElement( newType.getClassName().getFullName() ),
                    patternAnalyser.findClassElement( "java.util.EventListener" ) ) ) { // NOI18N

            DialogDisplayer.getDefault().notify(
                new NotifyDescriptor.Message(PatternNode.getString("MSG_InvalidListenerInterface"),
                                             NotifyDescriptor.ERROR_MESSAGE) );
            return;
        }
        /*
    }
        catch ( java.lang.ClassNotFoundException ex ) {
         TopManager.getDefault().notify(
             new NotifyDescriptor.Message(PatternNode.getString("MSG_ListenerInterfaceNotFound"),
                                          NotifyDescriptor.ERROR_MESSAGE) );
             
         return;
    }
          */ 
        MethodParameter[] params = addListenerMethod.getParameters();
        if ( params.length > 0 ) {
            params[0].setType( newType );
            addListenerMethod.setParameters( params );
        }

        params = removeListenerMethod.getParameters();
        if ( params.length > 0 ) {
            params[0].setType( newType );
            removeListenerMethod.setParameters( params );
        }

        // Ask if we have to change the bame of the methods
        String mssg = MessageFormat.format( PatternNode.getString( "FMT_ChangeEventSourceName" ),
                                            new Object[] { capitalizeFirstLetter( newType.getClassName().getName() ) } );
        //new Object[] { "Blah Blah !" } ); // NOI18N
        NotifyDescriptor nd = new NotifyDescriptor.Confirmation ( mssg, NotifyDescriptor.YES_NO_OPTION );
        if ( DialogDisplayer.getDefault().notify( nd ).equals( NotifyDescriptor.YES_OPTION ) ) {
            setName( newType.getClassName().getName() );
        }

        this.type = newType;
    }

    /** Gets the cookie of the first available method */

    public Node.Cookie getCookie( Class cookieType ) {
        if ( addListenerMethod != null )
            return addListenerMethod.getCookie( cookieType );

        if ( removeListenerMethod != null )
            return removeListenerMethod.getCookie( cookieType );

        return null;
    }

    public void destroy() throws SourceException {
        ClassElement declaringClass;

        // Remove addListener method

        if ( addListenerMethod != null ) {
            declaringClass = addListenerMethod.getDeclaringClass();
            if ( declaringClass == null ) {
                throw new SourceException();
            }
            else {
                declaringClass.removeMethod( addListenerMethod );
            }
        }

        // Remove removeListener method

        if ( removeListenerMethod != null ) {
            declaringClass = removeListenerMethod.getDeclaringClass();

            if ( declaringClass == null ) {
                throw new SourceException();
            }
            else {
                declaringClass.removeMethod( removeListenerMethod );
            }
        }
        
        //** BOB - Matula
        
        // delete associated "fire" methods
        declaringClass = getDeclaringClass();
        ClassElement listener = patternAnalyser.findClassElement( type.toString() );
        boolean canDelete = false;

        if ( listener != null ) {
            MethodElement methods[] = listener.getMethods();
            MethodElement sourceMethods[] = declaringClass.getMethods();
            String method;
            
            for( int i = 0; i < methods.length; i++ ) {
                method = "fire" + // NOI18N
                    Pattern.capitalizeFirstLetter( type.getClassName().getName() ) +
                    Pattern.capitalizeFirstLetter( methods[i].getName().getName() );
                if ( (methods[i].getModifiers() & Modifier.PUBLIC) != 0 ) {
                    for ( int j = 0; j < sourceMethods.length; j++ ) {
                        if (sourceMethods[j].getName().getName().equals(method)) {
                            if (!canDelete) {
                                // Ask, if the fire methods can be deleted
                                String mssg = MessageFormat.format( PatternNode.getString( "FMT_DeleteFire" ),
                                                                    new Object[] { } );
                                NotifyDescriptor nd = new NotifyDescriptor.Confirmation ( mssg, NotifyDescriptor.YES_NO_OPTION );
                                if ( DialogDisplayer.getDefault().notify( nd ).equals( NotifyDescriptor.NO_OPTION ) ) {
                                    return;
                                } else {
                                      canDelete = true;
                                }
                            }
                            declaringClass.removeMethod(sourceMethods[j]);
                        }
                    }
                }
            }
        }
        //** EOB - Matula
    }

    // Utility methods --------------------------------------------------------------------

    /*
    * Package-private constructor
    * Merge two event set descriptors.  Where they conflict, give the
    * second argument (y) priority over the first argument (x).
    *
    * @param x  The first (lower priority) EventSetDescriptor
    * @param y  The second (higher priority) EventSetDescriptor
    */

    EventSetPattern( EventSetPattern x, EventSetPattern y) {
        super( y.patternAnalyser );
        //super(x,y);

        /*
        listenerMethodDescriptors = x.listenerMethodDescriptors;
        if (y.listenerMethodDescriptors != null) {
         listenerMethodDescriptors = y.listenerMethodDescriptors;
    }
        if (listenerMethodDescriptors == null) {
         listenerMethods = y.listenerMethods;
    }
        */
        addListenerMethod = y.addListenerMethod;
        removeListenerMethod = y.removeListenerMethod;
        isUnicast = y.isUnicast;
        type = y.type;
        name = y.name;

        /*
        if (!x.inDefaultEventSet || !y.inDefaultEventSet) {
         inDefaultEventSet = false;
    }
        */
    }


    /** Finds the Type of property.
     * @throws IntrospectionException if the property doesnt folow the design patterns
     */

    private void findEventSetType() throws IntrospectionException {
        if ( addListenerMethod == null )
            throw new InternalError( "add method == nul in event set pattern"); // NOI18N

        type = addListenerMethod.getParameters()[0].getType();
    }

    /** Decides about the name of the event set from names of the methods */

    private String findEventSetName() {

        String compound = addListenerMethod.getName().getName().substring(3);
        return name = Introspector.decapitalize( compound );
    }


    /** Test if this EventSet pattern is unicast */
    private boolean testUnicast() {
        if (findTooManyListenersException() != null)
            return true;
        else
            return false;
    }

    /** @return The identifier for java.util.TooManyListenersException if the addListener
     * method throws it or null if not. 
     */

    Identifier findTooManyListenersException() {
        Identifier tooMany = Identifier.create( "java.util.TooManyListenersException" ); // NOI18N

        Identifier[] exs = addListenerMethod.getExceptions();


        for ( int i = 0; i < exs.length; i++ ) {
            if ( exs[i].compareTo( tooMany, false ) ) {
                return exs[i];
            }
        }
        return null;
    }

    void generateAddListenerMethod () throws SourceException {
        generateAddListenerMethod( null, false );
    }

    void generateAddListenerMethod ( String body, boolean javadoc ) throws SourceException {
        ClassElement declaringClass = getDeclaringClass();
        MethodElement newMethod = new MethodElement();

        MethodParameter[] newParameters = { new MethodParameter( "listener", type, false ) }; // NOI18N

        newMethod.setName( Identifier.create( "add" + capitalizeFirstLetter( getName() ) ) ); // NOI18N
        newMethod.setReturn( Type.VOID );
        newMethod.setModifiers( Modifier.PUBLIC | Modifier.SYNCHRONIZED );
        newMethod.setParameters( newParameters );

        if ( declaringClass.isInterface() )
            newMethod.setBody( null );
        else if ( body != null )
            newMethod.setBody( body );

        if ( isUnicast )
            newMethod.setExceptions( new Identifier[] { Identifier.create( "java.util.TooManyListenersException" ) } ); // NOI18N
        if ( javadoc ) {
            String comment = MessageFormat.format( PatternNode.getString( "COMMENT_AddListenerMethod" ),
                                                   new Object[] { type.getClassName().getName() } );
            newMethod.getJavaDoc().setRawText( comment );
        }

        if ( declaringClass == null )
            throw new SourceException();
        else {
            declaringClass.addMethod( newMethod );
            addListenerMethod = newMethod;
        }
    }

    void generateRemoveListenerMethod() throws SourceException {
        generateRemoveListenerMethod( null, false );
    }

    void generateRemoveListenerMethod( String body, boolean javadoc ) throws SourceException {
        ClassElement declaringClass = getDeclaringClass();
        MethodElement newMethod = new MethodElement();

        MethodParameter[] newParameters = { new MethodParameter( "listener", type, false ) }; // NOI18N

        newMethod.setName( Identifier.create( "remove" + capitalizeFirstLetter( getName() ) ) ); // NOI18N
        newMethod.setReturn( Type.VOID );
        newMethod.setModifiers( Modifier.PUBLIC | Modifier.SYNCHRONIZED );
        newMethod.setParameters( newParameters );

        if ( declaringClass.isInterface() )
            newMethod.setBody( null );
        else if ( body != null )
            newMethod.setBody( body );

        if ( javadoc ) {
            String comment = MessageFormat.format( PatternNode.getString( "COMMENT_RemoveListenerMethod" ),
                                                   new Object[] { type.getClassName().getName() } );
            newMethod.getJavaDoc().setRawText( comment );
        }

        if ( declaringClass == null )
            throw new SourceException();
        else {
            declaringClass.addMethod( newMethod );
            removeListenerMethod = newMethod;
        }
    }

    // Property change support -------------------------------------------------------------------------

    void copyProperties( EventSetPattern src ) {

        boolean changed = !src.getType().equals( getType() ) ||
                          !src.getName().equals( getName() ) ||
                          !(src.isUnicast() == isUnicast());

        if ( src.getAddListenerMethod() != addListenerMethod )
            addListenerMethod = src.getAddListenerMethod();
        if ( src.getRemoveListenerMethod() != removeListenerMethod )
            removeListenerMethod = src.getRemoveListenerMethod();

        if ( changed ) {

            isUnicast = testUnicast();

            try {
                findEventSetType();
            }
            catch ( java.beans.IntrospectionException e ) {
                // Nothing happens
            }
            isUnicast = testUnicast();
            name = findEventSetName();

            firePropertyChange( new java.beans.PropertyChangeEvent( this, null, null, null ) );
        }

    }

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