Package com.nexirius.framework.command

Source Code of com.nexirius.framework.command.AbstractCommand

//{HEADER
/**
* This class is part of jnex 'Nexirius Application Framework for Java'
* Copyright (C) Nexirius GmbH, CH-4450 Sissach, Switzerland (www.nexirius.ch)
*
* <p>This library is free software; you can redistribute it and/or<br>
* modify it under the terms of the GNU Lesser General Public<br>
* License as published by the Free Software Foundation; either<br>
* version 2.1 of the License, or (at your option) any later version.</p>
*
* <p>This library is distributed in the hope that it will be useful,<br>
* but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU<br>
* Lesser General Public License for more details.</p>
*
* <p>You should have received a copy of the GNU Lesser General Public<br>
* License along with this library; if not, write to the Free Software<br>
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA</p>
* </blockquote>
*
* <p>
* Nexirius GmbH, hereby disclaims all copyright interest in<br>
* the library jnex' 'Nexirius Application Framework for Java' written<br>
* by Marcel Baumann.</p>
*/
//}HEADER
package com.nexirius.framework.command;

import com.nexirius.framework.FWLog;
import com.nexirius.framework.application.DialogManager;
import com.nexirius.util.ClassUtil;
import com.nexirius.util.EventMulticaster;
import com.nexirius.util.assertion.Assert;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.lang.ref.SoftReference;
import java.util.Hashtable;

/**
* This class provides a basic implementation of the Command interface.
* In some ways it is analagous to the javax.swing.AbstractAction class
* which implements the javax.swing.Action interface.
* An important difference is that Command/AbstractCommand is not coupled
* to any particular GUI API.
*
* @author Marcel Baumann
*         Date      Author      Changes/Enhancements
*         1998.11.16  MB        Created
*         1999.02.27  MB        Bugfix: Precondition in setTimeout corrected
*         2003.05.30  MB        introduce EventMulticaster with soft references (PropertyChangeListener instances) to avoid memory leaks
*/
public abstract class AbstractCommand
        implements Command, Serializable {
    // A command can maintain an arbitrary list of properties
    private Hashtable keyTable = new Hashtable(2);

    // If any PropertyChangeListeners have been registered, the
    // propertyChangeListenerList field describes them.
    Object propertyChangeListenerList = null;

    // This is the name of the command. The name remains fixed throughout the
    // lifetime of the command
    private String commandName;

    // This determines how much time in milliseconds should be allowed
    // for a command to execute.
    private long timeoutValue = 0;

    // Signal to command processor that execution should not continue
    // after timeout has occurred
    private boolean abortAfterTimeout = false;

    // Signal to command processor that execution should be synchronous
    // otherwise asynchronous
    private boolean synchronous = false;

    // This flag indicates whether or not the command is enabled
    private boolean enabled = true;

    private boolean visible = true;

    private boolean defaultButton = false;

    private String resourceKey = null;


    /**
     * Constructor for AbstractCommand. The class's name will be used as a
     * default command name.
     */
    public AbstractCommand() {
        super();

        this.commandName = ClassUtil.getShortClassName(this);

        init();
    }

    /**
     * Constructor for AbstractCommand
     *
     * @param commandName the name of the command
     */
    public AbstractCommand(String commandName) {
        super();

        Assert.pre(commandName != null, "Parameter commandName is not null");

        this.commandName = commandName;

        init();
    }

    private void init() {
        setTimeout(timeoutValue);
        setAbortAfterTimeout(abortAfterTimeout);
        setSynchronous(synchronous);
        setEnabled(enabled);
        setVisible(visible);
        setDefaultButton(defaultButton);
        setResourceKey(commandName);
    }

    public Hashtable getProperties() {
        return this.keyTable;
    }

    /**
     * Add a PropertyChangeListener to the listener list.
     * The listener is registered for all properties.
     * <p/>
     * A PropertyChangeEvent will get fired in response to setting
     * a bound property, e.g. setEnabled
     * <p/>
     * The listener is attached as a SoftReference (make sure that the garbage collector does not
     * remove your listener by attaching the listener reference to another instance preferably the GUI component)
     *
     * @param listener The PropertyChangeListener to be added
     */
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeListenerList = EventMulticaster.addEventListener(propertyChangeListenerList, new SoftReference(listener));
    }

    /**
     * Action to be performed in case an exception was thrown during command
     * execution
     *
     * @param e Throwable
     */
    public void exceptionAction(Throwable e) {
        Assert.pre(e != null, "Throwable e is not null");

        FWLog.log("AbstractCommand: An exception in command  '" +
                getCommandName() + "' during command execution");
        e.printStackTrace();
        DialogManager.error(e);
    }


    /**
     * This method is called before doAction. Override this method if something
     * should be performed in initialiseAction.
     * <p/>
     * The object passed as a parameter may used to pass initialising info
     * to the command.  If the command was invoked from a button or menu status
     * then the object may correspond to the action event (the application
     * programmer has to know).
     */
    public void initialiseAction(Object parameter) {
    }


    /**
     * This method is called after doAction. Override this method
     * if something should be performed in finaliseAction
     */
    public void finaliseAction() {
    }

    /**
     * This action is performed if a command times out.  Override this
     * if some specific action is required.
     * <p/>
     * The default behaviour is to write a message to the logger
     */
    public void timeoutAction() {
        FWLog.log("AbstractCommand: Command '" + getCommandName() + "' timed out");
    }

    /**
     * A flag to a command processor that the command should be aborted
     * following a timeout. The value of abortAfterTimeout is typically
     * set by calling setAbortAfterTimeout() from within the timeoutAction()
     * method.
     */
    public boolean getAbortAfterTimeout() {
        return this.abortAfterTimeout;
    }

    /**
     * Return the command name
     */
    public String getCommandName() {
        return this.commandName;
    }

    public void setCommandName(String commandName) {
        this.commandName = commandName;
    }

    /**
     * Return the timeout period i.e. the amount of time (in milliseconds)
     * permitted for the execution of this command. A return value of zero
     * indicates that no timeout period has been specified.
     *
     * @return long
     */
    public long getTimeout() {
        return this.timeoutValue;
    }

    /**
     * Gets the Object associated with key (standard Properties stuff)
     */
    public Object getValue(String key) {
        return keyTable.get(key);
    }

    /**
     * This method was created for jnex
     */
    public boolean isEnabled() {
        return enabled;
    }

    public boolean isVisible() {
        return visible;
    }

    public boolean isDefaultButton() {
        return defaultButton;
    }

    /**
     * This method was created in VisualAge
     */
    public boolean isSynchronous() {
        return this.synchronous;
    }

    /**
     * Sets the Value associated with key. Standard Properties stuff.
     *
     * @param key      the key of the property
     * @param newValue the value to be associated with the property
     */
    public synchronized void putValue(String key, Object newValue) {
        if (key.equals(Command.ABORT_AFTER_TIMEOUT)) {
            abortAfterTimeout = ((Boolean) newValue).booleanValue();
        } else if (key.equals(Command.ENABLED)) {
            enabled = ((Boolean) newValue).booleanValue();
        } else if (key.equals(Command.VISIBLE)) {
            visible = ((Boolean) newValue).booleanValue();
        } else if (key.equals(Command.DEFAULT_BUTTON)) {
            defaultButton = ((Boolean) newValue).booleanValue();
        } else if (key.equals(Command.RESOURCE_KEY)) {
            resourceKey = (String) newValue;
        } else if (key.equals(Command.SYNCHRONOUS)) {
            synchronous = ((Boolean) newValue).booleanValue();
        } else if (key.equals(Command.TIMEOUT)) {
            timeoutValue = ((Long) newValue).longValue();
        }

        Object oldValue = null;

        if (keyTable.containsKey(key)) {
            oldValue = keyTable.get(key);
        }

        if (newValue != null) {
            keyTable.put(key, newValue);
        } else {
            keyTable.remove(key);
        }

        firePropertyChange(key, oldValue, newValue);
    }


    /**
     * Remove a PropertyChangeListener from the listener list.
     * This removes a PropertyChangeListener that was registered
     * for all properties.
     *
     * @param listener The PropertyChangeListener to be removed
     */
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeListenerList = EventMulticaster.removeEventListener(propertyChangeListenerList, listener);
    }

    /**
     * Modify the bound property 'abortAfterTimeout'
     *
     * @param abortAfterTimeout boolean
     */
    public void setAbortAfterTimeout(boolean abortAfterTimeout) {
        putValue(Command.ABORT_AFTER_TIMEOUT, new Boolean(abortAfterTimeout));
    }

    /**
     * Modify bound propery 'enabled'.
     * <p/>
     * GUI widgets listening for property changes typically modify their
     * 'enabled' status to correspond to that of the command
     *
     * @param enabled the value if 'enabled'
     */
    public synchronized void setEnabled(boolean enabled) {
        putValue(Command.ENABLED, new Boolean(enabled));
    }

    public synchronized void setVisible(boolean on) {
        putValue(Command.VISIBLE, new Boolean(on));
    }

    public synchronized void setDefaultButton(boolean on) {
        putValue(Command.DEFAULT_BUTTON, new Boolean(on));
    }

    /**
     * Modify bound property 'synchronous'.
     *
     * @param synchronous true if the command should be executed synchronously
     * @see com.nexirius.framework.command.Command
     */
    public void setSynchronous(boolean synchronous) {
        putValue(Command.SYNCHRONOUS, new Boolean(synchronous));
    }


    /**
     * Modify the bound property 'timeout'.
     * This sets the amount of time before the command times out.
     * By setting a value of 0, the command will not timeout.
     *
     * @param timeoutValue long
     */
    public void setTimeout(long timeoutValue) {
        putValue(Command.TIMEOUT, new Long(timeoutValue));
    }

    public void setResourceKey(String resourceKey) {
        putValue(Command.RESOURCE_KEY, resourceKey);
    }

    public String getResourceKey() {
        return (resourceKey == null ? getCommandName() : resourceKey);
    }

    /**
     * Support for reporting bound property changes.  This method can be called
     * when a bound property has changed and it will send the appropriate
     * PropertyChangeEvent to any registered PropertyChangeListeners.
     */
    private void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
        if (propertyChangeListenerList == null) {
            return;
        }
        firePropertyChange(new PropertyChangeEvent(this, propertyName, oldValue, newValue));
    }

    public void firePropertyChange(PropertyChangeEvent event) {
        Object listeners[] = EventMulticaster.getArray(propertyChangeListenerList);
        boolean needGarbageCollect = false;

        for (int i = 0; listeners != null && i < listeners.length; ++i) {
            PropertyChangeListener listener = (PropertyChangeListener) listeners[i];

            if (listener == null) {
                needGarbageCollect = true;
            } else {
                listener.propertyChange(event);
            }
        }

        if (needGarbageCollect) {
            propertyChangeListenerList = EventMulticaster.garbageCollect(propertyChangeListenerList);
        }
    }
}
TOP

Related Classes of com.nexirius.framework.command.AbstractCommand

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.