001: /**
002: * Objective Database Abstraction Layer (ODAL)
003: * Copyright (c) 2004, The ODAL Development Group
004: * All rights reserved.
005: * For definition of the ODAL Development Group please refer to LICENCE.txt file
006: *
007: * Distributable under LGPL license.
008: * See terms of license at gnu.org.
009: */package com.completex.objective.components.persistency.key.impl;
010:
011: import com.completex.objective.components.persistency.OdalRuntimePersistencyException;
012: import com.completex.objective.components.persistency.PersistentObject;
013: import com.completex.objective.components.persistency.key.SimpleNaturalKey;
014:
015: import java.io.Externalizable;
016: import java.io.IOException;
017: import java.io.ObjectInput;
018: import java.io.ObjectOutput;
019: import java.util.Arrays;
020:
021: /**
022: * Descedants of this class can be used as Keys of AbstractPersistentObject
023: * @see com.completex.objective.components.persistency.AbstractPersistentObject#toKey()
024: *
025: * @author Gennady Krizhevsky
026: */
027: public abstract class AbstractSimpleNaturalKey implements
028: SimpleNaturalKey, Externalizable {
029: static final long serialVersionUID = 1L;
030: private String className;
031: private Object[] values;
032: public static final String SEP = "|";
033:
034: protected AbstractSimpleNaturalKey(String className, Object[] values) {
035: this .className = className;
036: this .values = values;
037: }
038:
039: protected AbstractSimpleNaturalKey() {
040: }
041:
042: protected AbstractSimpleNaturalKey(PersistentObject persistent,
043: int[] keyIndeces) {
044: parse(persistent, keyIndeces);
045: }
046:
047: /**
048: * Populate className & values out of input parameters
049: *
050: * @param persistent
051: * @param keyIndeces
052: */
053: protected final void parse(PersistentObject persistent,
054: int[] keyIndeces) {
055: invalidateFlattened(persistent);
056: doParse(persistent, keyIndeces);
057: }
058:
059: /**
060: * Core functionalty of parse - to be overridden in descentants
061: *
062: * @param persistent
063: * @param keyIndeces
064: */
065: protected abstract void doParse(PersistentObject persistent,
066: int[] keyIndeces);
067:
068: /**
069: * @see Object#equals(Object)
070: */
071: public boolean equals(Object o) {
072: if (this == o)
073: return true;
074: if (o == null || getClass() != o.getClass())
075: return false;
076:
077: final AbstractSimpleNaturalKey that = (AbstractSimpleNaturalKey) o;
078:
079: if (className != null ? !className.equals(that.className)
080: : that.className != null)
081: return false;
082: if (!Arrays.equals(values, that.values))
083: return false;
084:
085: return true;
086: }
087:
088: /**
089: * @param values
090: * @return true if values == null || values.length == 0
091: */
092: protected boolean keyEmpty(Object[] values) {
093: return values == null || values.length == 0;
094: }
095:
096: /**
097: * @see Object#hashCode()
098: */
099: public int hashCode() {
100: if (keyEmpty(values)) {
101: return 0;
102: }
103: int result = className.hashCode();
104: for (int i = 0; i < values.length; i++) {
105: Object value = values[i];
106: result = hashCodeFromValue(result, value);
107: }
108: return result;
109: }
110:
111: /**
112: * Compound hash code based on result and value hash code
113: *
114: * @param result
115: * @param value
116: * @return resulting hash code
117: */
118: static int hashCodeFromValue(int result, Object value) {
119: result = 29 * result + (value != null ? value.hashCode() : 0);
120: return result;
121: }
122:
123: protected void invalidateFlattened(PersistentObject persistent) {
124: if (persistent.flattened()) {
125: throw new OdalRuntimePersistencyException(
126: "Cannot use DefaultNaturalKey on flattened objects");
127: }
128: }
129:
130: public String getClassName() {
131: return className;
132: }
133:
134: public void setClassName(String className) {
135: this .className = className;
136: }
137:
138: public Object[] getValues() {
139: return values;
140: }
141:
142: public void setValues(Object[] values) {
143: this .values = values;
144: }
145:
146: public String toString() {
147: if (keyEmpty(values)) {
148: return className;
149: }
150: StringBuffer result = new StringBuffer(className);
151: for (int i = 0; i < values.length; i++) {
152: Object value = values[i];
153: result.append(SEP).append(value);
154: }
155: return result.toString();
156: }
157:
158: public void writeExternal(ObjectOutput out) throws IOException {
159: out.writeObject(className);
160: out.writeObject(values);
161: }
162:
163: public void readExternal(ObjectInput in) throws IOException,
164: ClassNotFoundException {
165: className = (String) in.readObject();
166: values = (Object[]) in.readObject();
167: }
168:
169: }
|