blob: e248a093a1c8d530bb8e456dd4c6887f3aea739e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
<<<<<<< Updated upstream
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
=======
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
>>>>>>> Stashed changes
* limitations under the License.
*/
/*
* SingleFieldIdentity.java
*
*/
package javax.jdo.identity;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import javax.jdo.JDOFatalInternalException;
import javax.jdo.JDONullIdentityException;
import javax.jdo.spi.I18NHelper;
/**
* This class is the abstract base class for all single field identity classes. A common case of
* application identity uses exactly one persistent field in the class to represent identity. In
* this case, the application can use a standard JDO class instead of creating a new user-defined
* class for the purpose.
*
* @version 2.0
*/
public abstract class SingleFieldIdentity<SUBCLASS extends SingleFieldIdentity<SUBCLASS>>
implements Externalizable, Comparable<SUBCLASS> {
private static final long serialVersionUID = 1L;
/** The Internationalization message helper. */
protected static final I18NHelper MSG = I18NHelper.getInstance("javax.jdo.Bundle"); // NOI18N
/** The class of the target object. */
private transient Class<?> targetClass;
/** The name of the class of the target object. */
private String targetClassName;
/** The hashCode. */
protected int hashCode;
/** The key as an Object. */
protected Object keyAsObject;
/**
* Constructor with target class.
*
* @param pcClass the class of the target
* @since 2.0
*/
protected SingleFieldIdentity(Class<?> pcClass) {
if (pcClass == null) throw new NullPointerException();
targetClass = pcClass;
targetClassName = pcClass.getName();
}
/**
* Constructor only for Externalizable.
*
* @since 2.0
*/
public SingleFieldIdentity() {}
/**
* Set the given key as the key for this instance. Compute the hash code for the instance.
*
* @param key The key to use
* @since 2.0
*/
protected void setKeyAsObject(Object key) {
assertKeyNotNull(key);
keyAsObject = key;
}
/**
* Assert that the key is not null. Throw a JDONullIdentityException if the given key is null.
*
* @param key The key to check
* @since 2.0
*/
protected void assertKeyNotNull(Object key) {
if (key == null) {
throw new JDONullIdentityException(MSG.msg("EXC_SingleFieldIdentityNullParameter")); // NOI18N
}
}
/**
* Return the target class.
*
* @return the target class.
* @since 2.0
*/
public Class<?> getTargetClass() {
return targetClass;
}
/**
* Return the target class name.
*
* @return the target class name.
* @since 2.0
*/
public String getTargetClassName() {
return targetClassName;
}
/**
* Return the key as an Object. The method is synchronized to avoid race conditions in
* multi-threaded environments.
*
* @return the key as an Object.
* @since 2.0
*/
public synchronized Object getKeyAsObject() {
if (keyAsObject == null) {
keyAsObject = createKeyAsObject();
}
return keyAsObject;
}
/**
* Create the key as an Object.
*
* @return the key as an Object;
* @since 2.0
*/
protected Object createKeyAsObject() {
throw new JDOFatalInternalException(MSG.msg("EXC_CreateKeyAsObjectMustNotBeCalled"));
}
/**
* Check the class and class name and object type. If restored from serialization, class will be
* null so compare class name.
*
* @param obj the other object
* @return true if the class or class name is the same
*/
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (obj == null || this.getClass() != obj.getClass()) {
return false;
} else {
SingleFieldIdentity<?> other = (SingleFieldIdentity<?>) obj;
if (targetClass != null && targetClass == other.targetClass) return true;
return targetClassName.equals(other.targetClassName);
}
}
/**
* Return the hash code of the class name.
*
* @return the hash code of the class name
* @since 2.0
*/
protected int hashClassName() {
return targetClassName.hashCode();
}
/**
* Return the cached hash code.
*
* @return the cached hash code.
*/
public int hashCode() {
return hashCode;
}
/**
* Write to the output stream.
*
* @param out the stream
*/
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(targetClassName);
out.writeInt(hashCode);
}
/** Read from the input stream. Creates a new instance with the target class name set */
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
targetClass = null;
targetClassName = (String) in.readObject();
hashCode = in.readInt();
}
/**
* Determine the ordering of identity objects. Only the class name is compared. This method is
* only used by subclasses.
*
* @param o Other identity
* @return The relative ordering between the objects
* @since 2.2
*/
protected int compare(SingleFieldIdentity<?> o) {
return targetClassName.compareTo(o.targetClassName);
}
}