/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.common.namedobject;
import java.io.Serializable;
import org.teiid.core.designer.TeiidDesignerRuntimeException;
import org.teiid.designer.common.util.ErrorMessageKeys;
/**
* This class represents the basic implementation of MetadataObject, which is the foundation for all classes that are used to
* capture metadata. This abstract class is immutable, although it is intended that subclasses are mutable. Additionally, although
* this class is thread safe, subclasses do not have to be thread safe, since the framework for update and modifying these objects
* must guarantee proper concurrent access.
* <p>
* These classes are shipped between the client and Metadata Service, so this class is serializable.
* <p>
* Also, the <code>hashCode</code>, <code>equals</code> and <code>compareTo</code> methods are all consistent and optimized for
* fast performance. This is in part accomplished by caching the hash code value which identifies quickly that two objects are
* <i>not</i> equal.
* <p>
* This class and all of its subclasses are designed to be publicly immutable. That is, no component outside of the Configuration
* Service changes these objects once they are created.
*
* @since 8.0
*/
public abstract class BasicObject implements BaseObject, Serializable {
// To accomplish the public immutability, the BasicObject class has
// <code>setXXX</code> methods that visible to this package (where the
// {@link com.metamatrix.common.config.model.BasicConfigurationObjectEditor }
// class exists). Finally, a protected <code>updateHashCode</code> method that can be invoked
// by subclasses within the <code>setXXX</code> methods and that in-turn invokes the
// specialized <code>computeHashCode</code> method overridden by each subclass, obtains
// the new hash code value, and sets the internal hash code value. This framework
// provides a relatively simply template that simplifies the responsibility of
// developers as they provide new subclasses.
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* The ID for this object. Never null.
*
* @label ID
* @supplierCardinality 1
*/
private BaseID id;
/**
* Create a new instance with the specified ID.
*
* @param id the ID for this object (may not be null).
* @throws IllegalArgumentException if either the ID or data source ID is null.
*/
protected BasicObject( BaseID id ) {
if (id == null) {
throw new IllegalArgumentException(ErrorMessageKeys.NAMEDOBJECT_ERR_0004);
}
this.id = id;
}
/**
* Get the ID for this metadata object. The ID can never change in an object, so it is an immutable field.
*
* @return the identifier for this metadata object.
*/
@Override
public BaseID getID() {
return this.id;
}
/**
* Returns the name for this instance of the object. If you are using the dot notation for a naming conventions, this will
* return the last node in name.
*
* @return the name
* @see #getFullName
*/
@Override
public String getName() {
return getID().getName();
}
/**
* Returns the full name for this instance of the object.
*
* @return the name
*/
@Override
public String getFullName() {
return getID().getFullName();
}
/**
* Sets the id for this objects
*
* @param newID is of type BaseID
*/
protected void setID( BaseID newID ) {
this.id = newID;
}
/**
* Overrides Object hashCode method. Note that the hash code is computed purely from the ID, so two distinct instances that
* have the same identifier (i.e., full name) will have the same hash code value.
* <p>
* This hash code must be consistent with the <code>equals</code> method. defined by subclasses.
*
* @return the hash code value for this metadata object.
*/
@Override
public int hashCode() {
return this.id.hashCode();
}
/**
* Returns true if the specified object is semantically equal to this instance. Note: this method is consistent with
* <code>compareTo()</code>.
* <p>
*
* @param obj the object that this instance is to be compared to.
* @return whether the object is equal to this object.
*/
@Override
public boolean equals( Object obj ) {
// Check if instances are identical ...
if (this == obj) {
return true;
}
// Check if object can be compared to this one
// (this includes checking for null ) ...
if (this.getClass().isInstance(obj)) {
// Do quick hash code check first
if (this.hashCode() != obj.hashCode()) {
return false;
}
BasicObject that = (BasicObject)obj;
return this.getID().equals(that.getID());
}
// Otherwise not comparable ...
return false;
}
/**
* Compares this object to another. If the specified object is an instance of the same class, then this method compares the
* name; otherwise, it throws a ClassCastException (as instances are comparable only to instances of the same class). Note:
* this method is consistent with <code>equals()</code>.
* <p>
*
* @param obj the object that this instance is to be compared to.
* @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the
* specified object, respectively.
* @throws IllegalArgumentException if the specified object reference is null
* @throws ClassCastException if the specified object's type prevents it from being compared to this instance.
*/
@Override
public int compareTo( Object obj ) {
// Check if instances are identical...
if (this == obj) {
return 0;
}
// Check if object can be compared to this one...
// (this includes checking for null ) ...
if (this.getClass().isInstance(obj)) {
BasicObject that = (BasicObject)obj;
return this.getID().compareTo(that.getID());
}
// Otherwise not comparable ...
throw new ClassCastException(ErrorMessageKeys.NAMEDOBJECT_ERR_0005);
}
/**
* Returns a string representing the current state of the object.
*
* @return the string representation of this instance.
*/
@Override
public String toString() {
return this.id.toString();
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new TeiidDesignerRuntimeException(e);
}
}
}