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: FloatWidget.java,v 1.5 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.math.BigDecimal;
015: import java.math.BigInteger;
016: import java.util.Random;
017: import junit.framework.Assert;
018:
019: /**
020: * An object used to test persistence of floating-point and decimal fields,
021: * in addition to those in {@link BinaryWidget}.
022: *
023: * @author <a href="mailto:mmartin5@austin.rr.com">Mike Martin</a>
024: * @version $Revision: 1.5 $
025: */
026:
027: public class FloatWidget extends BinaryWidget {
028: private float floatField;
029: private double doubleField;
030: private Float floatObjField;
031: private Double doubleObjField;
032: private BigDecimal bigDecimalField;
033: private BigInteger bigIntegerField;
034:
035: /**
036: * Constructs an empty test object.
037: */
038:
039: public FloatWidget() {
040: super ();
041: }
042:
043: private static Random r = new Random(0);
044:
045: /**
046: * Fills all of the object's fields with random data values. Any non-
047: * primitive fields will also be assigned <code>null</code> on a random
048: * basis.
049: */
050:
051: public void fillRandom() {
052: super .fillRandom();
053:
054: floatField = r.nextFloat();
055: doubleField = r.nextDouble();
056: floatObjField = r.nextBoolean() ? null : new Float(r
057: .nextFloat());
058: doubleObjField = r.nextBoolean() ? null : new Double(r
059: .nextDouble());
060: bigDecimalField = r.nextBoolean() ? null : BigDecimal.valueOf(
061: (long) r.nextInt(), 2);
062: bigIntegerField = r.nextBoolean() ? null : BigInteger
063: .valueOf((long) r.nextInt());
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 FloatWidget) || !super .equals(obj))
083: return false;
084:
085: FloatWidget w = (FloatWidget) obj;
086:
087: /*
088: * Expecting that we may lose some precision (or experience rounding)
089: * as a floating value is transferred to the database and back, we
090: * define equality as being at least 6 decimal digits of accuracy for
091: * float types and 15 decimal digits for double types.
092: *
093: * Note that the comparisons used below only work if the values in
094: * question are in the range 0.0 <= x < 1.0.
095: */
096:
097: if (Math.abs(floatField - w.floatField) >= 1e-6)
098: return false;
099: if (Math.abs(doubleField - w.doubleField) >= 1e-15)
100: return false;
101:
102: if (floatObjField == null) {
103: if (w.floatObjField != null)
104: return false;
105: } else if (Math.abs(floatObjField.floatValue()
106: - w.floatObjField.floatValue()) >= 1e-6)
107: return false;
108:
109: if (doubleObjField == null) {
110: if (w.doubleObjField != null)
111: return false;
112: } else if (Math.abs(doubleObjField.doubleValue()
113: - w.doubleObjField.doubleValue()) >= 1e-15)
114: return false;
115:
116: /*
117: * BigDecimals and BigIntegers can be compared normally -- they're
118: * required to be exact at all times.
119: */
120:
121: if (bigDecimalField == null) {
122: if (w.bigDecimalField != null)
123: return false;
124: } else if (!bigDecimalField.equals(w.bigDecimalField))
125: return false;
126:
127: if (bigIntegerField == null) {
128: if (w.bigIntegerField != null)
129: return false;
130: } else if (!bigIntegerField.equals(w.bigIntegerField))
131: return false;
132:
133: return true;
134: }
135:
136: /**
137: * Returns a hash code value for this object.
138: *
139: * @return a hash code value for this object.
140: */
141:
142: public int hashCode() {
143: /*
144: * Note that, like equals() above, the technique used below for
145: * computing a hash code on the floating fields only works if the
146: * values in question are in the range 0.0 <= x < 1.0.
147: */
148:
149: return (int) (floatField * 1e6)
150: ^ (int) (doubleField * 1e9)
151: ^ (floatObjField == null ? 0 : (int) (floatObjField
152: .floatValue() * 1e6))
153: ^ (doubleObjField == null ? 0 : (int) (doubleObjField
154: .doubleValue() * 1e9))
155: ^ (bigDecimalField == null ? 0 : bigDecimalField
156: .hashCode())
157: ^ (bigIntegerField == null ? 0 : bigIntegerField
158: .hashCode());
159: }
160:
161: /**
162: * Returns a string representation for this object. All of the field
163: * values are included in the string for debugging purposes.
164: *
165: * @return a string representation for this object.
166: */
167:
168: public String toString() {
169: StringBuffer s = new StringBuffer(super .toString());
170:
171: s.append(" floatField = ").append(floatField);
172: s.append("\n doubleField = ").append(doubleField);
173: s.append("\n bigDecimalField = ").append(bigDecimalField);
174: s.append("\n bigIntegerField = ").append(bigIntegerField);
175: s.append('\n');
176:
177: return s.toString();
178: }
179:
180: /**
181: * Asserts that the given metadata is correct for an object of this class.
182: *
183: * @param cmd the class metadata to be tested.
184: * @param test the test to be used to call assert methods.
185: */
186:
187: public static void assertValidMetaData(ClassMetaData cmd,
188: Assert test) {
189: test.assertNotNull("Metadata", cmd);
190: test.assertEquals(FloatWidget.class, cmd.getPCClass());
191: test.assertEquals("com.triactive.jdo.model.test.widgets", cmd
192: .getPackageName());
193: test.assertTrue("Source URL", cmd.getSourceURL().toString()
194: .indexOf("package.jdo") >= 0);
195: test.assertEquals("Superclass", BinaryWidget.class, cmd
196: .getPCSuperclass());
197: test
198: .assertEquals("Identity type",
199: ClassMetaData.DATASTORE_IDENTITY, cmd
200: .getIdentityType());
201: test.assertNull("Identity class", cmd.getIdentityClass());
202:
203: String[] sortedFieldNames = new String[] { "bigDecimalField",
204: "bigIntegerField", "doubleField", "doubleObjField",
205: "floatField", "floatObjField" };
206:
207: int[] nullValueHandlings = new int[] {
208: FieldMetaData.NULL_VALUE_NONE,
209: FieldMetaData.NULL_VALUE_NONE,
210: FieldMetaData.NULL_VALUE_EXCEPTION,
211: FieldMetaData.NULL_VALUE_NONE,
212: FieldMetaData.NULL_VALUE_EXCEPTION,
213: FieldMetaData.NULL_VALUE_NONE };
214:
215: test.assertEquals("Field count", sortedFieldNames.length, cmd
216: .getFieldCount());
217:
218: for (int i = 0; i < sortedFieldNames.length; ++i) {
219: FieldMetaData fmd = cmd.getFieldRelative(i);
220: String s = sortedFieldNames[i];
221:
222: test.assertEquals(s, fmd.getName());
223: test.assertEquals(s + " persistence modifier",
224: FieldMetaData.PERSISTENCE_MODIFIER_PERSISTENT, fmd
225: .getPersistenceModifier());
226: test.assertEquals(s + " primary key", false, fmd
227: .isPrimaryKeyPart());
228: test.assertEquals(s + " null value handling",
229: nullValueHandlings[i], fmd.getNullValueHandling());
230: test.assertEquals(s + " default fetch group", true, fmd
231: .isInDefaultFetchGroup());
232: test.assertNull(s + " array metadata", fmd
233: .getArrayMetaData());
234: test.assertNull(s + " collection metadata", fmd
235: .getCollectionMetaData());
236: test.assertNull(s + " map metadata", fmd.getMapMetaData());
237: }
238: }
239: }
|