| /******************************************************************************* |
| * Copyright (c) 2004 Composent, Inc. 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: Composent, Inc. - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.ecf.core.identity; |
| |
| import java.io.Serializable; |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.ecf.internal.core.identity.Activator; |
| |
| /** |
| * Namespace base class. |
| * <p> |
| * This class and subclasses define a namespace for the creation and management |
| * of ID instances. Creation of ID instances is accomplished via the |
| * {@link #createInstance(Object[])} method, implemented by subclasses of this |
| * Namespace superclass. |
| * <p> |
| * All Namespace instances must have a unique name passed to the Namespace upon |
| * construction. |
| * <p> |
| * Typically Namespace instances are created via plugins that define extensions |
| * of the org.eclipse.ecf.namespace extension point. For example, to define a |
| * new Namespace subclass XMPPNamespace with name "ecf.xmpp" and add it to the |
| * ECF extension registry: |
| * |
| * <pre> |
| * <extension |
| * point="org.eclipse.ecf.namespace"> |
| * <namespace |
| * class="XMPPNamespace" |
| * name="ecf.xmpp"/> |
| * </extension> |
| * </pre> |
| * |
| * @see ID |
| */ |
| public abstract class Namespace implements Serializable, IAdaptable { |
| |
| private static final long serialVersionUID = 3976740272094720312L; |
| |
| public static final String SCHEME_SEPARATOR = ":"; //$NON-NLS-1$ |
| |
| private String name; |
| |
| private String description; |
| |
| private transient int hashCode; |
| |
| private transient boolean isInitialized = false; |
| |
| public Namespace() { |
| // public null constructor |
| } |
| |
| public final boolean initialize(String n, String desc) { |
| Assert.isNotNull(n, "Namespace<init> name cannot be null"); //$NON-NLS-1$ |
| if (!isInitialized) { |
| this.name = n; |
| this.description = desc; |
| this.hashCode = name.hashCode(); |
| this.isInitialized = true; |
| return true; |
| } |
| return false; |
| } |
| |
| public Namespace(String name, String desc) { |
| initialize(name, desc); |
| } |
| |
| /** |
| * Override of Object.equals. This equals method returns true if the provided |
| * Object is also a Namespace instance, and the names of the two instances |
| * match. |
| * |
| * @param other |
| * the Object to test for equality |
| */ |
| public boolean equals(Object other) { |
| if (!(other instanceof Namespace)) |
| return false; |
| return ((Namespace) other).name.equals(name); |
| } |
| |
| /** |
| * Hashcode implementation. Subclasses should not override. |
| * |
| * @return int hashCode for this Namespace. Should be unique. |
| */ |
| public int hashCode() { |
| return hashCode; |
| } |
| |
| /** |
| * Test whether two IDs are equal to one another. |
| * |
| * @param first |
| * the first ID. Must not be <code>null</code>. |
| * @param second |
| * the second ID. Must not be <code>null</code>. |
| * @return <code>true</code> if this ID is equal to the given ID. |
| * <code>false</code> otherwise. |
| */ |
| protected boolean testIDEquals(BaseID first, BaseID second) { |
| // First check that namespaces are the same and non-null |
| Namespace sn = second.getNamespace(); |
| if (sn == null || !this.equals(sn)) |
| return false; |
| return first.namespaceEquals(second); |
| } |
| |
| /** |
| * The default implementation of this method is to call id.namespaceGetName(). |
| * Subclasses may override. |
| * |
| * @param id |
| * the ID to get the name for. Must not be <code>null</code>. |
| * @return String that is the unique name for the given id within this |
| * Namespace. |
| */ |
| protected String getNameForID(BaseID id) { |
| return id.namespaceGetName(); |
| } |
| |
| /** |
| * The default implementation of this method is to call |
| * first.namespaceCompareTo(second). Subclasses may override. |
| * |
| * @param first |
| * the first id to compare. Must not be <code>null</code>. |
| * @param second |
| * the second id to compare. Must not be <code>null</code>. |
| * @return int as specified by {@link Comparable}. |
| */ |
| protected int getCompareToForObject(BaseID first, BaseID second) { |
| return first.namespaceCompareTo(second); |
| } |
| |
| /** |
| * The default implementation of this method is to call id.namespaceHashCode(). |
| * Subclasses may override. |
| * |
| * @param id |
| * the id in this Namespace to get the hashcode for. Must not be |
| * <code>null</code>. |
| * @return the hashcode for the given id. Returned value must be unique within |
| * this process. |
| */ |
| protected int getHashCodeForID(BaseID id) { |
| return id.namespaceHashCode(); |
| } |
| |
| /** |
| * The default implementation of this method is to call |
| * id.namespaceToExternalForm(). Subclasses may override. |
| * |
| * @param id |
| * the id in this Namespace to convert to external form. |
| * @return String that represents the given id in an external form. Note that |
| * this external form may at some later time be passed to |
| * {@link #createInstance(Object[])} as a single String parameter, and |
| * should result in a valid ID instance of the appropriate Namespace. |
| */ |
| protected String toExternalForm(BaseID id) { |
| return id.namespaceToExternalForm(); |
| } |
| |
| /** |
| * Get the name of this namespace. Must not return <code>null</code>. |
| * |
| * @return String name of Namespace instance. Must not return <code>null</code>, |
| * and the returned value should be a globally unique name for this |
| * Namespace subclass. |
| * |
| */ |
| public String getName() { |
| return name; |
| } |
| |
| /** |
| * Get the description, associated with this Namespace. The returned value may |
| * be <code>null</code>. |
| * |
| * @return the description associated with this Namespace. May be |
| * <code>null</code>. |
| */ |
| public String getDescription() { |
| return description; |
| } |
| |
| /** |
| * Make an instance of this namespace. Namespace subclasses, provided by plugins |
| * must implement this method to construct ID instances for the given namespace. |
| * <p> |
| * </p> |
| * See {@link #getSupportedParameterTypes()} to get information relevant to |
| * deciding what parameter types are expected by this method. |
| * <p> |
| * </p> |
| * |
| * @param parameters |
| * an Object[] of parameters for creating ID instances. May be null. |
| * |
| * @return a non-null ID instance. The class used may extend BaseID or may |
| * implement the ID interface directly |
| * @throws IDCreateException |
| * if construction fails |
| */ |
| public abstract ID createInstance(Object[] parameters) throws IDCreateException; |
| |
| /** |
| * Get the primary scheme associated with this namespace. Subclasses must |
| * provide an implementation that returns a non-<code>null</code> scheme |
| * identifier. Note that the returned scheme should <b>not</b> contain the |
| * Namespace.SCHEME_SEPARATOR (\":\"). |
| * |
| * @return a String scheme identifier. Must not be <code>null</code>. |
| */ |
| public abstract String getScheme(); |
| |
| /** |
| * Get an array of schemes supported by this Namespace instance. Subclasses may |
| * override to support multiple schemes. |
| * |
| * @return String[] of schemes supported by this Namespace. Will not be |
| * <code>null</code>, but returned array may be of length 0. |
| */ |
| public String[] getSupportedSchemes() { |
| return new String[0]; |
| } |
| |
| /** |
| * Get the supported parameter types for IDs created via subsequent calls to |
| * {@link #createInstance(Object[])}. Callers may use this method to determine |
| * the available parameter types, and then create and pass in conforming Object |
| * arrays to to {@link #createInstance(Object[])}. |
| * <p> |
| * </p> |
| * An empty two-dimensional array (new Class[0][0]) is the default returned by |
| * this abstract superclass. This means that the Object [] passed to |
| * {@link #createInstance(Object[])} will be ignored. |
| * <p> |
| * </p> |
| * Subsclasses should override this method to specify the parameters that they |
| * will accept in calls to {@link #createInstance(Object[])}. The rows of the |
| * returned Class array are the acceptable types for a given invocation of |
| * createInstance. |
| * <p> |
| * </p> |
| * Consider the following example: |
| * <p> |
| * </p> |
| * |
| * <pre> |
| * public Class[][] getSupportedParameterTypes() { |
| * return new Class[][] { { String.class }, { String.class, String.class } }; |
| * } |
| * </pre> |
| * |
| * The above means that there are two acceptable values for the Object [] passed |
| * into {@link #createInstance(Object[])}: 1) a single String, and 2) two |
| * Strings. These would therefore be acceptable as input to createInstance: |
| * |
| * <pre> |
| * ID newID1 = namespace.createInstance(new Object[] { "Hello" }); |
| * ID newID2 = namespace.createInstance(new Object[] { "Hello", "There"}}; |
| * </pre> |
| * |
| * @return Class [][] an array of class []s. Rows of the returned |
| * two-dimensional array define the acceptable parameter types for a |
| * single call to {@link #createInstance(Object[])}. If zero-length |
| * Class arrays are returned (i.e. Class[0][0]), then Object [] |
| * parameters to {@link #createInstance(Object[])} will be ignored. |
| */ |
| public Class<?>[][] getSupportedParameterTypes() { |
| return new Class[][] { {} }; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) |
| */ |
| @SuppressWarnings("unchecked") |
| public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { |
| if (adapter.isInstance(this)) { |
| return this; |
| } |
| IAdapterManager manager = Activator.getDefault().getAdapterManager(); |
| if (manager == null) |
| return null; |
| return manager.loadAdapter(this, adapter.getName()); |
| } |
| |
| /** |
| * @since 3.1 |
| */ |
| protected String getInitStringFromExternalForm(Object[] args) { |
| if (args == null || args.length < 1 || args[0] == null) |
| return null; |
| if (args[0] instanceof String) { |
| final String arg = (String) args[0]; |
| if (arg.startsWith(getScheme() + SCHEME_SEPARATOR)) { |
| final int index = arg.indexOf(SCHEME_SEPARATOR); |
| if (index >= arg.length()) |
| return null; |
| return arg.substring(index + 1); |
| } |
| } |
| return null; |
| } |
| |
| public String toString() { |
| StringBuffer b = new StringBuffer("Namespace["); //$NON-NLS-1$ |
| b.append("name=").append(name).append(";"); //$NON-NLS-1$ //$NON-NLS-2$ |
| b.append("scheme=").append(getScheme()).append(";"); //$NON-NLS-1$ //$NON-NLS-2$ |
| b.append("description=").append("]"); //$NON-NLS-1$ //$NON-NLS-2$ |
| return b.toString(); |
| } |
| } |