View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  /*
    19   * SingleFieldIdentity.java
    20   *
    21   */
    22
    23  package javax.jdo.identity;
    24
    25  import java.io.Externalizable;
    26  import java.io.IOException;
    27  import java.io.ObjectInput;
    28  import java.io.ObjectOutput;
    29
    30  import javax.jdo.JDOFatalInternalException;
    31  import javax.jdo.JDONullIdentityException;
    32
    33  import javax.jdo.spi.I18NHelper;
    34
    35  /** This class is the abstract base class for all single field identity
    36   * classes. A common case of application identity uses exactly one
    37   * persistent field in the class to represent identity. In this case,
    38   * the application can use a standard JDO class instead of creating
    39   * a new user-defined class for the purpose.
    40   * @version 2.0
    41   */
    42  public abstract class SingleFieldIdentity
    43      implements Externalizable, Comparable {
    44
    45      /** The Internationalization message helper.
    46       */
    47      protected static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle"); //NOI18N
    48
    49      /** The class of the target object.
    50       */
    51      transient private Class targetClass;
    52
    53      /** The name of the class of the target object.
    54       */
    55      private String targetClassName;
    56
    57      /** The hashCode.
    58       */
    59      protected int hashCode;
    60
    61      /** The key as an Object.
    62       */
    63      protected Object keyAsObject;
    64
    65      /** Constructor with target class.
    66       * @param pcClass the class of the target
    67       * @since 2.0
    68       */
    69      protected SingleFieldIdentity(Class pcClass) {
    70          if (pcClass == null)
    71              throw new NullPointerException();
    72          targetClass = pcClass;
    73          targetClassName = pcClass.getName();
    74      }
    75
    76      /** Constructor only for Externalizable.
    77       * @since 2.0
    78       */
    79      public SingleFieldIdentity () {
    80      }
    81
    82      /** Set the given key as the key for this instance.
    83       * Compute the hash code for the instance.
    84       * @since 2.0
    85       */
    86      protected void setKeyAsObject(Object key) {
    87          assertKeyNotNull(key);
    88          keyAsObject = key;
    89      }
    90
    91      /** Assert that the key is not null. Throw a JDONullIdentityException
    92       * if the given key is null.
    93       * @since 2.0
    94       */
    95      protected void assertKeyNotNull(Object key) {
    96          if (key == null) {
    97              throw new JDONullIdentityException(
    98                  msg.msg("EXC_SingleFieldIdentityNullParameter")); //NOI18N
    99          }
    100     }
    101
    102     /** Return the target class.
    103      * @return the target class.
    104      * @since 2.0
    105      */
    106     public Class getTargetClass() {
    107         return targetClass;
    108     }
    109
    110     /** Return the target class name.
    111      * @return the target class name.
    112      * @since 2.0
    113      */
    114     public String getTargetClassName() {
    115         return targetClassName;
    116     }
    117
    118     /** Return the key as an Object. The method is synchronized to avoid
    119      * race conditions in multi-threaded environments.
    120      * @return the key as an Object.
    121      * @since 2.0
    122      */
    123     public synchronized Object getKeyAsObject() {
    124         if (keyAsObject == null) {
    125             keyAsObject = createKeyAsObject();
    126         }
    127         return keyAsObject;
    128     }
    129
    130     /** Create the key as an Object.
    131      * @return the key as an Object;
    132      * @since 2.0
    133      */
    134     protected Object createKeyAsObject() {
    135         throw new JDOFatalInternalException
    136                 (msg.msg("EXC_CreateKeyAsObjectMustNotBeCalled"));
    137     }
    138
    139     /** Check the class and class name and object type. If restored
    140      * from serialization, class will be null so compare class name.
    141      * @param obj the other object
    142      * @return true if the class or class name is the same
    143      */
    144     public boolean equals(Object obj) {
    145         if (this == obj) {
    146             return true;
    147         } else if (obj == null || this.getClass() != obj.getClass()) {
    148             return false;
    149         } else {
    150             SingleFieldIdentity other = (SingleFieldIdentity) obj;
    151             if (targetClass != null && targetClass == other.targetClass)
    152                 return true;
    153             return targetClassName.equals (other.targetClassName);
    154         }
    155     }
    156
    157     /** Return the hash code of the class name.
    158      * @return the hash code of the class name
    159      * @since 2.0
    160      */
    161     protected int hashClassName() {
    162         return targetClassName.hashCode();
    163     }
    164
    165     /** Return the cached hash code.
    166      * @return the cached hash code.
    167      */
    168     public int hashCode() {
    169         return hashCode;
    170     }
    171
    172     /** Write to the output stream.
    173      * @param out the stream
    174      */
    175     public void writeExternal(ObjectOutput out) throws IOException {
    176         out.writeObject(targetClassName);
    177         out.writeInt(hashCode);
    178     }
    179
    180     /** Read from the input stream.
    181      * Creates a new instance with the target class name set
    182      */
    183     public void readExternal(ObjectInput in)
    184             throws IOException, ClassNotFoundException {
    185         targetClass = null;
    186         targetClassName = (String)in.readObject();
    187         hashCode = in.readInt();
    188     }
    189
    190     /** Determine the ordering of identity objects. Only the class name
    191      *  is compared. This method is only used by subclasses.
    192      * @param o Other identity
    193      * @return The relative ordering between the objects
    194      * @since 2.2
    195      */
    196     protected int compare(SingleFieldIdentity o) {
    197             return targetClassName.compareTo(o.targetClassName);
    198         }
    199
    200 }