| /******************************************************************************* |
| * Copyright (c) 2005, 2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.core.commands; |
| |
| import org.eclipse.core.commands.common.HandleObject; |
| import org.eclipse.core.commands.common.NotDefinedException; |
| import org.eclipse.core.internal.commands.util.Util; |
| |
| /** |
| * <p> |
| * Provides information about the type of a command parameter. Clients can use a |
| * parameter type to check if an object matches the type of the parameter with |
| * {@link #isCompatible(Object)} and can get an |
| * {@link AbstractParameterValueConverter} to convert between objects matching |
| * the parameter type and strings that encode the object's identity. |
| * </p> |
| * <p> |
| * A command parameter is not required to declare a type. To determine if a |
| * given parameter has a type, check if an {@link IParameter} implements |
| * {@link ITypedParameter} and if so, use |
| * {@link ITypedParameter#getParameterType()} like this: |
| * </p> |
| * |
| * <pre> |
| * IParameter parameter = // ... get IParameter from Command |
| * if (parameter instanceof ITypedParameter) { |
| * ParameterType type = ((ITypedParameter)parameter).getParameterType(); |
| * if (type != null) { |
| * // this parameter has a ParameterType |
| * } |
| * } |
| * </pre> |
| * |
| * @see IParameter |
| * @see ITypedParameter#getParameterType() |
| * @since 3.2 |
| */ |
| public final class ParameterType extends HandleObject implements Comparable { |
| |
| /** |
| * TODO: this was copied from |
| * org.eclipse.core.internal.expressions.Expressions is there a better place |
| * to reference this? |
| * |
| * @param element |
| * The element to test; may be <code>null</code>. |
| * @param type |
| * The type against which we are testing;may be <code>null</code>. |
| * @return <code>true</code> if the <code>element</code> is an instance |
| * of <code>type</code>; <code>false</code> otherwise. |
| */ |
| private static final boolean isInstanceOf(final Object element, |
| final String type) { |
| // null isn't an instanceof of anything. |
| if (element == null) { |
| return false; |
| } |
| return isSubtype(element.getClass(), type); |
| } |
| |
| /** |
| * TODO: this was copied from |
| * org.eclipse.core.internal.expressions.Expressions is there a better place |
| * to reference this? |
| * |
| * @param clazz |
| * The class to match; may be <code>null</code>. |
| * @param type |
| * The type against which we are testing;may be <code>null</code>. |
| * @return <code>true</code> if the <code>element</code> is an instance |
| * of <code>type</code>; <code>false</code> otherwise. |
| */ |
| private static final boolean isSubtype(final Class clazz, final String type) { |
| if (clazz.getName().equals(type)) { |
| return true; |
| } |
| final Class superClass = clazz.getSuperclass(); |
| if (superClass != null && isSubtype(superClass, type)) { |
| return true; |
| } |
| final Class[] interfaces = clazz.getInterfaces(); |
| for (int i = 0; i < interfaces.length; i++) { |
| if (isSubtype(interfaces[i], type)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * An {@link AbstractParameterValueConverter} for converting parameter |
| * values between objects and strings. This may be <code>null</code>. |
| */ |
| private transient AbstractParameterValueConverter parameterTypeConverter; |
| |
| /** |
| * A string specifying the object type of this parameter type. This will be |
| * <code>null</code> when the parameter type is undefined but never null |
| * when it is defined. |
| */ |
| private transient String type = null; |
| |
| /** |
| * Constructs a new instance based on the given identifier. When a parameter |
| * type is first constructed, it is undefined. Parameter types should only |
| * be constructed by the {@link CommandManager} to ensure that the |
| * identifier remains unique. |
| * |
| * @param id |
| * The identifier for this type. This value must not be |
| * <code>null</code>, and must be unique amongst all parameter |
| * types. |
| */ |
| ParameterType(final String id) { |
| super(id); |
| } |
| |
| /** |
| * Adds a listener to this parameter type that will be notified when its |
| * state changes. |
| * |
| * @param listener |
| * The listener to be added; must not be <code>null</code>. |
| */ |
| public final void addListener(final IParameterTypeListener listener) { |
| addListenerObject(listener); |
| } |
| |
| /** |
| * Compares this parameter type with another object by comparing each of the |
| * non-transient attributes. |
| * |
| * @param object |
| * The object with which to compare; must be an instance of |
| * {@link ParameterType}. |
| * @return A negative integer, zero or a positive integer, if the object is |
| * greater than, equal to or less than this parameter type. |
| */ |
| public final int compareTo(final Object object) { |
| final ParameterType castedObject = (ParameterType) object; |
| int compareTo = Util.compare(defined, castedObject.defined); |
| if (compareTo == 0) { |
| compareTo = Util.compare(id, castedObject.id); |
| } |
| return compareTo; |
| } |
| |
| /** |
| * <p> |
| * Defines this parameter type, setting the defined property to |
| * <code>true</code>. |
| * </p> |
| * <p> |
| * Notification is sent to all listeners that something has changed. |
| * </p> |
| * |
| * @param type |
| * a string identifying the Java object type for this parameter |
| * type; <code>null</code> is interpreted as |
| * <code>"java.lang.Object"</code> |
| * @param parameterTypeConverter |
| * an {@link AbstractParameterValueConverter} to perform |
| * string/object conversions for parameter values; may be |
| * <code>null</code> |
| */ |
| public final void define(final String type, |
| final AbstractParameterValueConverter parameterTypeConverter) { |
| |
| final boolean definedChanged = !this.defined; |
| this.defined = true; |
| |
| this.type = (type == null) ? Object.class.getName() : type; |
| this.parameterTypeConverter = parameterTypeConverter; |
| |
| fireParameterTypeChanged(new ParameterTypeEvent(this, definedChanged)); |
| } |
| |
| /** |
| * Notifies all listeners that this parameter type has changed. This sends |
| * the given event to all of the listeners, if any. |
| * |
| * @param event |
| * The event to send to the listeners; must not be |
| * <code>null</code>. |
| */ |
| private final void fireParameterTypeChanged(final ParameterTypeEvent event) { |
| if (event == null) { |
| throw new NullPointerException( |
| "Cannot send a null event to listeners."); //$NON-NLS-1$ |
| } |
| |
| if (!isListenerAttached()) { |
| return; |
| } |
| |
| final Object[] listeners = getListeners(); |
| for (int i = 0; i < listeners.length; i++) { |
| final IParameterTypeListener listener = (IParameterTypeListener) listeners[i]; |
| listener.parameterTypeChanged(event); |
| } |
| } |
| |
| /** |
| * Returns the value converter associated with this parameter, if any. |
| * |
| * @return The parameter value converter, or <code>null</code> if there is |
| * no value converter for this parameter. |
| * @throws NotDefinedException |
| * if the parameter type is not currently defined |
| */ |
| public final AbstractParameterValueConverter getValueConverter() |
| throws NotDefinedException { |
| if (!isDefined()) { |
| throw new NotDefinedException( |
| "Cannot use getValueConverter() with an undefined ParameterType"); //$NON-NLS-1$ |
| } |
| |
| return parameterTypeConverter; |
| } |
| |
| /** |
| * Returns whether the provided value is compatible with this parameter |
| * type. An object is compatible with a parameter type if the object is an |
| * instance of the class defined as the parameter's type class. |
| * |
| * @param value |
| * an object to check for compatibility with this parameter type; |
| * may be <code>null</code>. |
| * @return <code>true</code> if the value is compatible with this type, |
| * <code>false</code> otherwise |
| * @throws NotDefinedException |
| * if the parameter type is not currently defined |
| */ |
| public boolean isCompatible(Object value) throws NotDefinedException { |
| if (!isDefined()) { |
| throw new NotDefinedException( |
| "Cannot use isCompatible() with an undefined ParameterType"); //$NON-NLS-1$ |
| } |
| return isInstanceOf(value, type); |
| } |
| |
| /** |
| * Unregisters listener for changes to properties of this parameter type. |
| * |
| * @param listener |
| * the instance to unregister. Must not be <code>null</code>. |
| * If an attempt is made to unregister an instance which is not |
| * already registered with this instance, no operation is |
| * performed. |
| */ |
| public final void removeListener(final IParameterTypeListener listener) { |
| removeListenerObject(listener); |
| } |
| |
| /** |
| * The string representation of this parameter type. For debugging purposes |
| * only. This string should not be shown to an end user. |
| * |
| * @return The string representation; never <code>null</code>. |
| */ |
| public final String toString() { |
| if (string == null) { |
| final StringBuffer stringBuffer = new StringBuffer(); |
| stringBuffer.append("ParameterType("); //$NON-NLS-1$ |
| stringBuffer.append(id); |
| stringBuffer.append(','); |
| stringBuffer.append(defined); |
| stringBuffer.append(')'); |
| string = stringBuffer.toString(); |
| } |
| return string; |
| } |
| |
| /** |
| * Makes this parameter type become undefined. Notification is sent to all |
| * listeners. |
| */ |
| public final void undefine() { |
| string = null; |
| |
| final boolean definedChanged = defined; |
| defined = false; |
| |
| type = null; |
| parameterTypeConverter = null; |
| |
| fireParameterTypeChanged(new ParameterTypeEvent(this, definedChanged)); |
| } |
| |
| } |