001: /*
002: * Copyright 2002 (C) TJDO.
003: * All rights reserved.
004: *
005: * This software is distributed under the terms of the TJDO License version 1.0.
006: * See the terms of the TJDO License in the documentation provided with this software.
007: *
008: * $Id: OID.java,v 1.4 2004/01/25 22:31:26 jackknifebarber Exp $
009: */
010:
011: package com.triactive.jdo.store;
012:
013: /**
014: * An object identifier. OIDs are normally used as object identifiers for
015: * persistent objects that use data store identity. They're also used for
016: * view objects, which actually use non-data store identity.
017: *
018: * <p>An OID is effectively a long containing a value in the range 0 to
019: * 2<sup>60</sup>-1. The 60 bits encode three unsigned integer ID values; a
020: * 15-bit class ID value, a 30-bit object ID <i>high value</i>, and a 15-bit
021: * object ID <i>low value</i>.
022: *
023: * <p>The object ID value is separated into two parts to facilitate the use of a
024: * particular strategy for efficiently generating unique OID values, called the
025: * <dfn>high/low approach</dfn>. In this approach, the high value is obtained
026: * from a persistent store, and the low value is assigned locally by the
027: * application. The advantage is performance; it avoids the bottleneck of
028: * hitting the persistent store every time an ID needs to be generated.
029: *
030: * @author <a href="mailto:mmartin5@austin.rr.com">Mike Martin</a>
031: * @version $Revision: 1.4 $
032: *
033: * @see StoreManager
034: */
035:
036: public final class OID implements java.io.Serializable {
037: /**
038: * The maximum value of an OID as a <tt>long</tt>. This equals
039: * 2<sup>60</sup> - 1.
040: */
041: public static final long MAX_VALUE = 0xfffffffffffffffL;
042:
043: /**
044: * The maximum class ID value. This equals 2<sup>15</sup> - 1.
045: */
046: public static final int MAX_CLASSID = 0x7fff;
047:
048: /**
049: * The maximum hi portion of an object ID value. This equals
050: * 2<sup>30</sup> - 1.
051: */
052: public static final int MAX_OBJIDHI = 0x3fffffff;
053:
054: /**
055: * The maximum lo portion of an object ID value. This equals
056: * 2<sup>15</sup> - 1.
057: */
058: public static final int MAX_OBJIDLO = 0x7fff;
059:
060: /**
061: * The maximum length of an OID in string form.
062: */
063: public static final int MAX_LENGTH = 14;
064:
065: /**
066: * The OID value as a long.
067: */
068: private long value;
069:
070: /**
071: * Constructs an OID from its long value.
072: *
073: * @param value the long value of the OID.
074: *
075: * @exception IllegalArgumentException
076: * if the argument is not in the range 0 to {@link #MAX_VALUE}.
077: */
078:
079: public OID(long value) throws IllegalArgumentException {
080: if (value < 0 || value > MAX_VALUE)
081: throw new IllegalArgumentException("Invalid OID value: "
082: + value);
083:
084: this .value = value;
085: }
086:
087: /**
088: * Constructs an OID from three integer values. All three arguments must be
089: * between zero and their respective maximums {@link #MAX_CLASSID},
090: * {@link #MAX_OBJIDHI}, and {@link #MAX_OBJIDLO}.
091: *
092: * @param classID the class ID value.
093: * @param objIDHi the hi portion of the object ID value.
094: * @param objIDLo the lo portion of the object ID value.
095: *
096: * @exception IllegalArgumentException
097: * if one of the arguments is out of range.
098: */
099:
100: public OID(int classID, int objIDHi, int objIDLo)
101: throws IllegalArgumentException {
102: if (classID < 0 || classID > MAX_CLASSID)
103: throw new IllegalArgumentException(
104: "Invalid class ID value: " + classID);
105:
106: if (objIDHi < 0 || objIDHi > MAX_OBJIDHI)
107: throw new IllegalArgumentException(
108: "Invalid object ID hi value: " + objIDHi);
109:
110: if (objIDLo < 0 || objIDLo > MAX_OBJIDLO)
111: throw new IllegalArgumentException(
112: "Invalid object ID lo value: " + objIDLo);
113:
114: value = ((long) classID << 45) | ((long) objIDHi << 15)
115: | objIDLo;
116: }
117:
118: /**
119: * Constructs an OID from its string representation.
120: *
121: * @param s the string representation of an OID.
122: *
123: * @exception IllegalArgumentException
124: * if the given string representation is not valid.
125: *
126: * @see #toString
127: */
128:
129: public OID(String s) throws IllegalArgumentException {
130: if (s.length() != 14 || s.charAt(3) != '-'
131: || s.charAt(10) != '-')
132: throw new IllegalArgumentException(
133: "Invalid OID string value: " + s);
134:
135: StringBuffer buf = new StringBuffer(s);
136:
137: buf.deleteCharAt(10).deleteCharAt(3);
138:
139: value = Long.parseLong(buf.toString(), 32);
140:
141: if (value < 0 || value > MAX_VALUE)
142: throw new IllegalArgumentException(
143: "Invalid OID string value: " + s);
144: }
145:
146: /**
147: * Returns the class ID portion of the OID.
148: *
149: * @return the class ID.
150: */
151:
152: public int getClassID() {
153: return (int) (value >> 45);
154: }
155:
156: /**
157: * Returns the value of this OID as a long value.
158: *
159: * @return the value of this OID as a <tt>long</tt>.
160: */
161:
162: public long longValue() {
163: return value;
164: }
165:
166: public boolean equals(Object obj) {
167: if (obj == this )
168: return true;
169:
170: if (!(obj instanceof OID))
171: return false;
172:
173: return (value == ((OID) obj).value);
174: }
175:
176: public int hashCode() {
177: return (int) (value ^ (value >> 32));
178: }
179:
180: /**
181: * Returns the string representation of the OID. The string representation
182: * is all three of the component values in base 32, zero-filled, separated
183: * by a dash '-' character:
184: *
185: * <blockquote><pre>
186: * ccc-hhhhhh-lll
187: * </pre></blockquote>
188: *
189: * @return the string representation of the OID.
190: */
191:
192: public String toString() {
193: StringBuffer s = new StringBuffer("00000000000").append(Long
194: .toString(value, 32));
195:
196: s.delete(0, s.length() - 12).insert(3, '-').insert(10, '-');
197:
198: return s.toString();
199: }
200: }
|