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: BinaryWidget.java,v 1.4 2004/03/22 04:58:12 jackknifebarber Exp $
009: */
010:
011: package com.triactive.jdo.model.test.widgets;
012:
013: import com.triactive.jdo.model.*;
014: import java.util.Arrays;
015: import java.util.Random;
016: import junit.framework.Assert;
017:
018: /**
019: * An object used to test persistence of binary fields, in addition to those
020: * in {@link Widget}.
021: *
022: * @author <a href="mailto:mmartin5@austin.rr.com">Mike Martin</a>
023: * @version $Revision: 1.4 $
024: */
025:
026: public class BinaryWidget extends Widget {
027: private byte[] fixedLengthBinary;
028: private byte[] varLengthBinary;
029: private byte[] hugeBinary;
030:
031: /**
032: * Constructs an empty test object.
033: */
034:
035: public BinaryWidget() {
036: super ();
037: }
038:
039: private static Random r = new Random(0);
040:
041: /**
042: * Fills all of the object's fields with random data values. Any non-
043: * primitive fields will also be assigned <code>null</code> on a random
044: * basis.
045: */
046:
047: public void fillRandom() {
048: super .fillRandom();
049:
050: fixedLengthBinary = r.nextBoolean() ? null : new byte[20];
051: varLengthBinary = r.nextBoolean() ? null : new byte[r
052: .nextInt(20) + 1];
053: hugeBinary = r.nextBoolean() ? null
054: : new byte[r.nextInt(128) + 1];
055:
056: if (fixedLengthBinary != null)
057: r.nextBytes(fixedLengthBinary);
058:
059: if (varLengthBinary != null)
060: r.nextBytes(varLengthBinary);
061:
062: if (hugeBinary != null)
063: r.nextBytes(hugeBinary);
064: }
065:
066: /**
067: * Indicates whether some other object is "equal to" this one. By comparing
068: * against an original copy of the object, <code>equals()</code> can be
069: * used to verify that the object has been written to a database and read
070: * back correctly.
071: *
072: * @param obj the reference object with which to compare
073: *
074: * @return <code>true</code> if this object is equal to the obj argument;
075: * <code>false</code> otherwise.
076: */
077:
078: public boolean equals(Object obj) {
079: if (this == obj)
080: return true;
081:
082: if (!(obj instanceof BinaryWidget) || !super .equals(obj))
083: return false;
084:
085: BinaryWidget w = (BinaryWidget) obj;
086:
087: return Arrays.equals(fixedLengthBinary, w.fixedLengthBinary)
088: && Arrays.equals(varLengthBinary, w.varLengthBinary)
089: && Arrays.equals(hugeBinary, w.hugeBinary);
090: }
091:
092: /**
093: * Returns a hash code value for this object.
094: *
095: * @return a hash code value for this object.
096: */
097:
098: public int hashCode() {
099: return (fixedLengthBinary == null ? 0
100: : hashCode(fixedLengthBinary))
101: ^ (varLengthBinary == null ? 0
102: : hashCode(varLengthBinary))
103: ^ (hugeBinary == null ? 0 : hashCode(hugeBinary));
104: }
105:
106: /**
107: * Computes a suitable hash code from an array of bytes.
108: *
109: * @param bytes The array of bytes on which to compute the hash code.
110: *
111: * @return The computed hash code.
112: */
113:
114: private int hashCode(byte[] bytes) {
115: int hc = 0;
116: int leftShift = 0;
117:
118: for (int i = 0; i < bytes.length; ++i) {
119: hc ^= bytes[i] << leftShift;
120:
121: if ((leftShift += 8) > 24)
122: leftShift = 0;
123: }
124:
125: return hc;
126: }
127:
128: /**
129: * Returns a string representation for this object. All of the field
130: * values are included in the string for debugging purposes.
131: *
132: * @return a string representation for this object.
133: */
134:
135: public String toString() {
136: StringBuffer s = new StringBuffer(super .toString());
137:
138: s.append(" fixedLengthBinary = binary");
139:
140: if (fixedLengthBinary != null)
141: s.append(", hashCode = ").append(
142: hashCode(fixedLengthBinary)).append(", bytes = ")
143: .append(toHexString(fixedLengthBinary));
144: else
145: s.append(" (null)");
146:
147: s.append("\n varLengthBinary = binary");
148:
149: if (varLengthBinary != null)
150: s.append(", length = ").append(varLengthBinary.length)
151: .append(", hashCode = ").append(
152: hashCode(varLengthBinary)).append(
153: ", bytes = ").append(
154: toHexString(varLengthBinary));
155: else
156: s.append(" (null)");
157:
158: s.append("\n hugeBinary = binary");
159:
160: if (hugeBinary != null)
161: s.append(", length = ").append(hugeBinary.length).append(
162: ", hashCode = ").append(hashCode(hugeBinary))
163: .append(", bytes = ").append(
164: toHexString(hugeBinary));
165: else
166: s.append(" (null)");
167:
168: s.append('\n');
169:
170: return s.toString();
171: }
172:
173: /**
174: * Returns a hex string representation of a given byte array.
175: *
176: * @param bytes the byte array to convert to string.
177: *
178: * @return a hex string representation of the given byte array.
179: */
180:
181: private static String toHexString(byte[] bytes) {
182: StringBuffer s = new StringBuffer();
183:
184: for (int i = 0; i < bytes.length; ++i)
185: s.append(Integer.toHexString((int) bytes[i] & 0xff));
186:
187: return s.toString();
188: }
189:
190: /**
191: * Asserts that the given metadata is correct for an object of this class.
192: *
193: * @param cmd the class metadata to be tested.
194: * @param test the test to be used to call assert methods.
195: */
196:
197: public static void assertValidMetaData(ClassMetaData cmd,
198: Assert test) {
199: test.assertNotNull("Metadata", cmd);
200: test.assertEquals(BinaryWidget.class, cmd.getPCClass());
201: test.assertEquals("com.triactive.jdo.model.test.widgets", cmd
202: .getPackageName());
203: test.assertTrue("Source URL", cmd.getSourceURL().toString()
204: .indexOf("BinaryWidget.jdo") >= 0);
205: test.assertEquals("Superclass", Widget.class, cmd
206: .getPCSuperclass());
207: test
208: .assertEquals("Identity type",
209: ClassMetaData.DATASTORE_IDENTITY, cmd
210: .getIdentityType());
211: test.assertNull("Identity class", cmd.getIdentityClass());
212:
213: String[] sortedFieldNames = new String[] { "fixedLengthBinary",
214: "hugeBinary", "varLengthBinary" };
215:
216: String[] lengthExtensions = new String[] { "20", "unlimited",
217: "max 20" };
218:
219: test.assertEquals("Field count", sortedFieldNames.length, cmd
220: .getFieldCount());
221:
222: for (int i = 0; i < sortedFieldNames.length; ++i) {
223: FieldMetaData fmd = cmd.getFieldRelative(i);
224: ArrayMetaData amd = fmd.getArrayMetaData();
225: String s = sortedFieldNames[i];
226:
227: test.assertEquals(s, fmd.getName());
228: test.assertEquals(s + " persistence modifier",
229: FieldMetaData.PERSISTENCE_MODIFIER_PERSISTENT, fmd
230: .getPersistenceModifier());
231: test.assertEquals(s + " primary key", false, fmd
232: .isPrimaryKeyPart());
233: test.assertEquals(s + " null value handling",
234: FieldMetaData.NULL_VALUE_NONE, fmd
235: .getNullValueHandling());
236: test.assertEquals(s + " default fetch group", false, fmd
237: .isInDefaultFetchGroup());
238: test.assertEquals(s + " array metadata element type",
239: byte.class, amd.getElementType());
240: test.assertTrue(s + " array metadata embedded flag", amd
241: .isEmbeddedElement());
242: test.assertNull(s + " collection metadata", fmd
243: .getCollectionMetaData());
244: test.assertNull(s + " map metadata", fmd.getMapMetaData());
245: test.assertEquals(s + " length extension",
246: lengthExtensions[i], fmd.getLength());
247: }
248: }
249: }
|