Package nexj.core.persistence

Source Code of nexj.core.persistence.OID

// Copyright 2010 NexJ Systems Inc. This software is licensed under the terms of the Eclipse Public License 1.0
package nexj.core.persistence;

import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.math.BigDecimal;
import java.util.Date;

import nexj.core.meta.Primitive;
import nexj.core.meta.TypeConversionException;
import nexj.core.util.Binary;
import nexj.core.util.BinaryUtil;
import nexj.core.util.IOUtil;
import nexj.core.util.ObjUtil;

/**
* Object Identifier - a value object used to match the copies of an object
* instance across process boundaries. Usually, they contain the primary
* key and can be compared based on its values, including for total
* ordering.
*/
public final class OID implements OIDHolder, Comparable, Externalizable
{
   // constants

   /**
    * The Java stream unique identifier for the class.
    */
   private final static long serialVersionUID = 1875795639836903377L;

   // attributes

   /**
    * Stores the primary key values.
    */
   private Object[] m_valueArray;

   /**
    * The cached hash code.
    */
   private int m_nHashCode = 0;

   // constructors

   /**
    * Creates an OID.
    * @param valueArray The OID components.
    */
   public OID(Object[] valueArray)
   {
      m_valueArray = valueArray;
   }

   /**
    * Creates an OID.
    * This constructor is for INTERNAL USE ONLY.
    */
   public OID()
   {
   }

   // operations

   /**
    * Sets the value array.
    * OIDs are immutable - this method is for INTERNAL USE ONLY.
    * @param valueArray The value array to set.
    */
   public void setValueArray(Object[] valueArray)
   {
      if (m_valueArray != null)
      {
         throw new IllegalStateException("Attempt to reset the state on OID");
      }

      m_valueArray = valueArray;
   }

   /**
    * @return The value array. This method is for INTERNAL USE ONLY.
    */
   public Object[] getValueArray()
   {
      return m_valueArray;
   }

   /**
    * Returns an OID component value by ordinal number.
    * @param nOrdinal The OID component ordinal (0-based).
    * @return The OID component value.
    */
   public Object getValue(int nOrdinal)
   {
      return m_valueArray[nOrdinal];
   }

   /**
    * Returns the OID component count.
    * @return The OID component count.
    */
   public int getCount()
   {
      return m_valueArray.length;
   }

   /**
    * @see java.lang.Comparable#compareTo(java.lang.Object)
    */
   public int compareTo(Object o)
   {
      return compareTo((OID)o);
   }

   /**
    * Typed version of compareTo(Object).
    * @see java.lang.Comparable#compareTo(java.lang.Object)
    */
   public int compareTo(OID oid)
   {
      if (oid == null)
      {
         return 1;
      }

      if (oid == this)
      {
         return 0;
      }

      int nCount = m_valueArray.length;

      if (nCount != oid.m_valueArray.length)
      {
         throw new ClassCastException("OID value array length mismatch");
      }

      int nCmp = 0;

      for (int i = 0; nCmp == 0 && i < nCount; ++i)
      {
         nCmp = ObjUtil.compare((Comparable)m_valueArray[i], oid.m_valueArray[i]);
      }

      return nCmp;
   }

   /**
    * @see java.lang.Object#equals(java.lang.Object)
    */
   public boolean equals(Object obj)
   {
      if (!(obj instanceof OID))
      {
         return false;
      }

      if (this == obj)
      {
         return true;
      }

      OID oid = (OID)obj;

      if (m_nHashCode != oid.m_nHashCode &&
         m_nHashCode != 0 &&
         oid.m_nHashCode != 0)
      {
         return false;
      }

      int nCount = m_valueArray.length;

      if (nCount != oid.m_valueArray.length)
      {
         return false;
      }

      for (int i = 0; i != nCount; ++i)
      {
         Object left = m_valueArray[i];
         Object right = oid.m_valueArray[i];

         if (left == null)
         {
            if (right != null)
            {
               return false;
            }
         }
         else
         {
            if (!left.equals(right))
            {
               return false;
            }
         }
      }

      return true;
   }

   /**
    * @see java.lang.Object#hashCode()
    */
   public int hashCode()
   {
      if (m_nHashCode == 0)
      {
         int n = 0;

         for (int i = 0; i < m_valueArray.length; ++i)
         {
            if (m_valueArray[i] != null)
            {
               n ^= m_valueArray[i].hashCode();
            }
         }

         m_nHashCode = (n == 0) ? 1 : n;
      }

      return m_nHashCode;
   }

   /**
    * Serializes the OID to a string.
    * @return The stringified OID.
    */
   public String toString()
   {
      StringBuilder buf = new StringBuilder(32);

      buf.append("OID:");
      buf.append(m_valueArray.length);

      for (int i = 0; i < m_valueArray.length; ++i)
      {
         Object value = m_valueArray[i];
         String s;

         buf.append(':');

         if (value != null)
         {
            if (value instanceof String)
            {
               buf.append('S');
               s = (String)value;
            }
            else if (value instanceof Number)
            {
               if (value instanceof Integer)
               {
                  buf.append('I');
               }
               else if (value instanceof Long)
               {
                  buf.append('L');
               }
               else if (value instanceof Float)
               {
                  buf.append('F');
               }
               else if (value instanceof Double)
               {
                  buf.append('D');
               }
               else if (value instanceof BigDecimal)
               {
                  buf.append('N');
               }
               else
               {
                  buf.append('?');
               }

               s = value.toString();
            }
            else if (value instanceof Date)
            {
               buf.append('T');
               s = Long.toString(((Date)value).getTime());
            }
            else if (value instanceof Boolean)
            {
               buf.append('B');
               buf.append((((Boolean)value).booleanValue()) ? 'T' : 'F');
               s = null;
            }
            else if (value instanceof Binary)
            {
               buf.append('V');
               s = value.toString();
            }
            else
            {
               buf.append('?');
               s = "";
            }

            if (s != null)
            {
               buf.append(s.length());
               buf.append(':');
               buf.append(s);
            }
         }
      }

      return buf.toString();
   }

   /**
    * Returns this object.
    * @see nexj.core.persistence.OIDHolder#getOID()
    */
   public OID getOID()
   {
      return this;
   }

   /**
    * This is not supported, as OIDs are immutable.
    * @throws UnsupportedOperationException
    * @see nexj.core.persistence.OIDHolder#setOID(nexj.core.meta.OID)
    */
   public void setOID(OID oid)
   {
      throw new UnsupportedOperationException("Attempt to invoke OID.setOID(OID)");
   }

   /**
    * Writes the OID to a data output stream.
    * @param os The output stream, to which to write the data.
    * @throws IOException if an error occurs.
    */
   public void write(DataOutput os) throws IOException
   {
      for (int i = 0; i < m_valueArray.length; ++i)
      {
         BinaryUtil.write(os, m_valueArray[i]);
      }
   }

   /**
    * Reads the contents of the OID from a data input stream.
    * This method is for INTERNAL USE ONLY.
    * @param is The input stream.
    * @param nValueCount The number of components to read, or -1 to read until the end of the stream.
    */
   public void read(DataInput is, int nValueCount) throws IOException
   {
      int nCount = 0;
      m_valueArray =  new Object[(nValueCount < 0) ? 1 : nValueCount];

      while (nCount != nValueCount)
      {
         Object value;

         try
         {
            value = BinaryUtil.read(is);
         }
         catch (EOFException e)
         {
            if (nValueCount > 0)
            {
               throw e;
            }

            break;
         }

         if (nCount == m_valueArray.length)
         {
            Object[] values = new Object[nCount << 1];

            System.arraycopy(m_valueArray, 0, values, 0, nCount);
            m_valueArray = values;
         }

         m_valueArray[nCount++] = value;
      }

      if (nCount != m_valueArray.length)
      {
         Object[] values = new Object[nCount];

         System.arraycopy(m_valueArray, 0, values, 0, nCount);
         m_valueArray = values;
      }
   }

   /**
    * @return The OID serialized as a binary value.
    */
   public Binary toBinary()
   {
      ByteArrayOutputStream bos = new ByteArrayOutputStream(17);
      DataOutputStream dos = new DataOutputStream(bos);

      try
      {
         write(dos);
         dos.close();

         return new Binary(bos.toByteArray());
      }
      catch (IOException e)
      {
         throw new TypeConversionException(Primitive.ANY, e);
      }
   }

   /**
    * Converts a binary value to OID.
    * @param binary The binary value.
    * @return The converted OID.
    */
   public static OID fromBinary(Binary binary)
   {
      DataInputStream is = new DataInputStream(binary.getInputStream());
      OID oid = new OID();

      try
      {
         oid.read(is, -1);
      }
      catch (IOException e)
      {
         throw new TypeConversionException(Primitive.ANY, e);
      }
      finally
      {
         IOUtil.close(is);
      }

      return oid;
   }

   /**
    * @see java.io.Externalizable#readExternal(java.io.ObjectInput)
    */
   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
   {
      read(in, in.readUnsignedByte());
   }

   /**
    * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
    */
   public void writeExternal(ObjectOutput out) throws IOException
   {
      out.writeByte(m_valueArray.length);
      write(out);
   }
}
TOP

Related Classes of nexj.core.persistence.OID

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.