001    /*
002     * This file is part of muCommander, http://www.mucommander.com
003     * Copyright (C) 2002-2008 Maxence Bernard
004     *
005     * muCommander is free software; you can redistribute it and/or modify
006     * it under the terms of the GNU General Public License as published by
007     * the Free Software Foundation; either version 3 of the License, or
008     * (at your option) any later version.
009     *
010     * muCommander is distributed in the hope that it will be useful,
011     * but WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013     * GNU General Public License for more details.
014     *
015     * You should have received a copy of the GNU General Public License
016     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017     */
018    
019    package com.mucommander.ui.action;
020    
021    import java.util.Hashtable;
022    
023    /**
024     * A descriptor class for {@link MuAction} instances. An ActionDescriptor is the combination of a MuAction
025     * class (a class extending MuAction and following its conventions) and a set of properties used for instanciation.
026     * Thus, it not only identifies an action class but also the way it is instanciated.
027     *
028     * <p>Two ActionDescriptor instances are equal only if:
029     * <ul>
030     *  <li>they refer to the same MuAction class
031     *  <li>both sets of initialization properties are equal, i.e. they contain the same key/value pairs (deep equality)
032     * </ul>
033     * This means that two ActionDescriptor instances referring to the same MuAction class but with a different set of
034     * initialization properties will not be equal.
035     *
036     * <p>This class is used by ActionManager to instance MuAction and allow several instances to live in memory only if
037     * they have different initialization properties, which translated into action speak means a different appearance
038     * and/or behavior.
039     *
040     * @see ActionManager
041     * @see MuAction
042     *
043     * @author Maxence Bernard
044     */
045    public class ActionDescriptor {
046    
047        /** MuAction class descriptor */
048        private Class actionClass;
049    
050        /** Intialization properties, null if there are no initialization properties */
051        private Hashtable properties;
052    
053    
054        /**
055         * Convenience constructor which has the same effect as calling {@link #ActionDescriptor(Class, Hashtable)}
056         * with a null value for the <code>properties</code> parameter.
057         *
058         * @param actionClass a MuAction Class descriptor
059         */
060        public ActionDescriptor(Class actionClass) {
061            this(actionClass, null);
062        }
063    
064        /**
065         * Creates a new ActionDescriptor which identifies the specified combination of MuAction class and initialization
066         * properties. The <code>properties</code> parameter may be <code>null</code> if the action class is to be
067         * instanciated without any initialization properties.
068         *
069         * <p>The specified Class *must* denote a class that extends {@link MuAction} and follows its conventions
070         * (provide the proper constructor), otherwise {@link ActionManager} will fail to instanciate it. However,
071         * ActionDescriptor does not check if the specified Class is valid or not.
072         * 
073         * @param muActionClass a MuAction Class descriptor
074         * @param initProperties a Hashtable containing the properties that will be used to instanciate the specified MuAction class
075         */
076        public ActionDescriptor(Class muActionClass, Hashtable initProperties) {
077            this.actionClass = muActionClass;
078            this.properties = initProperties;
079        }
080    
081        /**
082         * Returns a Class instance referring to a class that extends MuAction.
083         */
084        public Class getActionClass() {
085            return actionClass;
086        }
087    
088        /**
089         * Returns the list of properties that are to be used to instanciate the MuAction class, or <code>null</code> if
090         * there are none.
091         */
092        public Hashtable getInitProperties() {
093            return properties;
094        }
095    
096    
097        /**
098         * Returns <code>true</code> if the given object is an ActionDescriptor that is equal to this one.
099         * ActionDescriptor instances are considered equal if they refer to the same {@link MuAction} class and
100         * set of initialization properties.
101         */
102        public boolean equals(Object o) {
103            if(!(o instanceof ActionDescriptor))
104                return false;
105    
106            ActionDescriptor ad = (ActionDescriptor)o;
107    
108            return actionClass.getName().equals(ad.actionClass.getName())
109                && (((properties==null || properties.isEmpty()) && (ad.properties==null || ad.properties.isEmpty()))
110                    || (properties!=null && ad.properties!=null && properties.equals(ad.properties)));
111        }
112    
113    
114        /**
115         * Returns a hash code value for this ActionDescriptor, making this class suitable for use as a key in a Hashtable.
116         */
117        public int hashCode() {
118            return actionClass.hashCode() + 27*(properties==null?0:properties.hashCode());
119        }
120    
121        /**
122         * Returns a String representation of this ActionDescriptor. 
123         */
124        public String toString() {
125            return super.toString()+" class="+actionClass.getName()+" properties="+properties;
126        }
127    }