001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.test.util;
022:
023: import java.lang.reflect.*;
024: import java.util.*;
025:
026: import com.db4o.internal.*;
027:
028: public class TCompare {
029:
030: public boolean isEqual(Object a_compare, Object a_with) {
031: return isEqual(a_compare, a_with, null, null);
032: }
033:
034: public boolean isEqual(Object a_compare, Object a_with,
035: String a_path, Stack a_stack) {
036: if (a_path == null || a_path.length() < 1) {
037: if (a_compare != null) {
038: a_path = a_compare.getClass().getName() + ":";
039: } else {
040: if (a_with != null) {
041: a_path = a_with.getClass().getName() + ":";
042: }
043: }
044: }
045:
046: String path = a_path;
047:
048: if (a_compare == null) {
049: return a_with == null;
050: }
051: if (a_with == null) {
052: return false;
053: }
054: Class clazz = a_compare.getClass();
055: if (clazz != a_with.getClass()) {
056: return false;
057: }
058:
059: if (Platform4.isSimple(clazz)) {
060: return a_compare.equals(a_with);
061: }
062:
063: if (a_stack == null) {
064: a_stack = new Stack();
065: }
066:
067: // takes care of repeating calls to the same object
068: if (a_stack.contains(a_compare)) {
069: return true;
070: }
071: a_stack.push(a_compare);
072:
073: Field fields[] = clazz.getDeclaredFields();
074: for (int i = 0; i < fields.length; i++) {
075: if (storeableField(clazz, fields[i])) {
076: Platform4.setAccessible(fields[i]);
077: try {
078: path = a_path + fields[i].getName() + ":";
079: Object compare = fields[i].get(a_compare);
080: Object with = fields[i].get(a_with);
081: if (compare == null) {
082: if (with != null) {
083: return false;
084: }
085: } else if (with == null) {
086: return false;
087: } else {
088: if (compare.getClass().isArray()) {
089: if (!with.getClass().isArray()) {
090: return false;
091: } else {
092: compare = normalizeNArray(compare);
093: with = normalizeNArray(with);
094: int len = Array.getLength(compare);
095: if (len != Array.getLength(with)) {
096: return false;
097: } else {
098: for (int j = 0; j < len; j++) {
099: Object elementCompare = Array
100: .get(compare, j);
101: Object elementWith = Array.get(
102: with, j);
103: // if (l_persistentArray)
104: if (!isEqual(elementCompare,
105: elementWith, path,
106: a_stack)) {
107: return false;
108: } else if (elementCompare == null) {
109: if (elementWith != null) {
110: return false;
111: }
112: } else if (elementWith == null) {
113: return false;
114: } else {
115: Class elementCompareClass = elementCompare
116: .getClass();
117: if (elementCompareClass != elementWith
118: .getClass()) {
119: return false;
120: }
121: if (hasPublicConstructor(elementCompareClass)) {
122: if (!isEqual(
123: elementCompare,
124: elementWith,
125: path, a_stack)) {
126: return false;
127:
128: }
129: } else if (!elementCompare
130: .equals(elementWith)) {
131: return false;
132: }
133: }
134:
135: }
136:
137: }
138: }
139: } else if (hasPublicConstructor(fields[i]
140: .getType())) {
141: if (!isEqual(compare, with, path, a_stack)) {
142: return false;
143: }
144: } else {
145: if (!compare.equals(with)) {
146: return false;
147: }
148: }
149: }
150: } catch (IllegalAccessException ex) {
151: // probably JDK 1
152: // never mind this field
153: return true;
154: } catch (Exception e) {
155: System.err
156: .println("TCompare failure executing path:"
157: + path);
158: e.printStackTrace();
159: return false;
160: }
161: }
162: }
163: return true;
164: }
165:
166: boolean hasPublicConstructor(Class a_class) {
167: if (a_class != String.class) {
168: try {
169: return a_class.newInstance() != null;
170: } catch (Throwable t) {
171: }
172: }
173: return false;
174: }
175:
176: Object normalizeNArray(Object a_object) {
177: if (Array.getLength(a_object) > 0) {
178: Object first = Array.get(a_object, 0);
179: if (first != null && first.getClass().isArray()) {
180: int dim[] = arrayDimensions(a_object);
181: Object all = new Object[arrayElementCount(dim)];
182: normalizeNArray1(a_object, all, 0, dim, 0);
183: return all;
184: }
185: }
186: return a_object;
187: }
188:
189: int normalizeNArray1(Object a_object, Object a_all, int a_next,
190: int a_dim[], int a_index) {
191: if (a_index == a_dim.length - 1) {
192: for (int i = 0; i < a_dim[a_index]; i++) {
193: Array.set(a_all, a_next++, Array.get(a_object, i));
194: }
195: } else {
196: for (int i = 0; i < a_dim[a_index]; i++) {
197: a_next = normalizeNArray1(Array.get(a_object, i),
198: a_all, a_next, a_dim, a_index + 1);
199: }
200:
201: }
202: return a_next;
203: }
204:
205: int[] arrayDimensions(Object a_object) {
206: int count = 0;
207: for (Class clazz = a_object.getClass(); clazz.isArray(); clazz = clazz
208: .getComponentType()) {
209: count++;
210: }
211: int dim[] = new int[count];
212: for (int i = 0; i < count; i++) {
213: dim[i] = Array.getLength(a_object);
214: a_object = Array.get(a_object, 0);
215: }
216: return dim;
217: }
218:
219: int arrayElementCount(int a_dim[]) {
220: int elements = a_dim[0];
221: for (int i = 1; i < a_dim.length; i++) {
222: elements *= a_dim[i];
223: }
224: return elements;
225: }
226:
227: public boolean storeableField(Class a_class, Field a_field) {
228: return (!Modifier.isStatic(a_field.getModifiers()))
229: && (!Modifier.isTransient(a_field.getModifiers()) & !(a_field
230: .getName().indexOf("$") > -1));
231: }
232:
233: }
|