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.db4ounit.common.soda.util;
022:
023: import java.lang.reflect.*;
024: import java.util.*;
025:
026: import com.db4o.internal.*;
027:
028: import db4ounit.extensions.Db4oUnitPlatform;
029:
030: public class TCompare {
031:
032: public static boolean isEqual(Object a_compare, Object a_with) {
033: return isEqual(a_compare, a_with, null, new Vector());
034: }
035:
036: private static boolean isEqual(Object a_compare, Object a_with,
037: String a_path, Vector a_list) {
038:
039: if (a_compare == null) {
040: return a_with == null;
041: }
042: if (a_with == null) {
043: return false;
044: }
045: Class clazz = a_compare.getClass();
046: if (clazz != a_with.getClass()) {
047: return false;
048: }
049:
050: if (Platform4.isSimple(clazz)) {
051: return a_compare.equals(a_with);
052: }
053:
054: // takes care of repeating calls to the same object
055: if (a_list.contains(a_compare)) {
056: return true;
057: }
058: a_list.addElement(a_compare);
059:
060: if (a_compare.getClass().isArray()) {
061: return areArraysEqual(normalizeNArray(a_compare),
062: normalizeNArray(a_with), a_path, a_list);
063: }
064:
065: if (hasPublicConstructor(a_compare.getClass())) {
066: return areFieldsEqual(a_compare, a_with, a_path, a_list);
067: }
068: return a_compare.equals(a_with);
069: }
070:
071: private static boolean areFieldsEqual(final Object a_compare,
072: final Object a_with, final String a_path,
073: final Vector a_list) {
074: String path = getPath(a_compare, a_with, a_path);
075: Field fields[] = a_compare.getClass().getDeclaredFields();
076: for (int i = 0; i < fields.length; i++) {
077: Field field = fields[i];
078: if (Db4oUnitPlatform.isUserField(field)) {
079: Platform4.setAccessible(field);
080: try {
081: if (!isFieldEqual(field, a_compare, a_with, path,
082: a_list)) {
083: return false;
084: }
085: } catch (Exception e) {
086: System.err
087: .println("TCompare failure executing path:"
088: + path);
089: e.printStackTrace();
090: return false;
091: }
092: }
093: }
094: return true;
095: }
096:
097: private static boolean isFieldEqual(Field field,
098: final Object a_compare, final Object a_with, String path,
099: final Vector a_list) {
100: Object compare = getFieldValue(field, a_compare);
101: Object with = getFieldValue(field, a_with);
102: return isEqual(compare, with, path + field.getName() + ":",
103: a_list);
104: }
105:
106: private static Object getFieldValue(Field field, final Object obj) {
107: try {
108: return field.get(obj);
109: } catch (IllegalAccessException ex) {
110: // probably JDK 1
111: // never mind this field
112: return null;
113: }
114: }
115:
116: private static boolean areArraysEqual(Object compare, Object with,
117: String path, Vector a_list) {
118: int len = Array.getLength(compare);
119: if (len != Array.getLength(with)) {
120: return false;
121: } else {
122: for (int j = 0; j < len; j++) {
123: Object elementCompare = Array.get(compare, j);
124: Object elementWith = Array.get(with, j);
125: if (!isEqual(elementCompare, elementWith, path, a_list)) {
126: return false;
127: }
128: }
129: }
130: return true;
131: }
132:
133: private static String getPath(Object a_compare, Object a_with,
134: String a_path) {
135: if (a_path != null && a_path.length() > 0) {
136: return a_path;
137: }
138: if (a_compare != null) {
139: return a_compare.getClass().getName() + ":";
140: }
141: if (a_with != null) {
142: return a_with.getClass().getName() + ":";
143: }
144: return a_path;
145: }
146:
147: static boolean hasPublicConstructor(Class a_class) {
148: if (a_class != String.class) {
149: try {
150: return a_class.newInstance() != null;
151: } catch (Throwable t) {
152: }
153: }
154: return false;
155: }
156:
157: static Object normalizeNArray(Object a_object) {
158: if (Array.getLength(a_object) > 0) {
159: Object first = Array.get(a_object, 0);
160: if (first != null && first.getClass().isArray()) {
161: int dim[] = arrayDimensions(a_object);
162: Object all = new Object[arrayElementCount(dim)];
163: normalizeNArray1(a_object, all, 0, dim, 0);
164: return all;
165: }
166: }
167: return a_object;
168: }
169:
170: static int normalizeNArray1(Object a_object, Object a_all,
171: int a_next, int a_dim[], int a_index) {
172: if (a_index == a_dim.length - 1) {
173: for (int i = 0; i < a_dim[a_index]; i++) {
174: Array.set(a_all, a_next++, Array.get(a_object, i));
175: }
176: } else {
177: for (int i = 0; i < a_dim[a_index]; i++) {
178: a_next = normalizeNArray1(Array.get(a_object, i),
179: a_all, a_next, a_dim, a_index + 1);
180: }
181:
182: }
183: return a_next;
184: }
185:
186: static int[] arrayDimensions(Object a_object) {
187: int count = 0;
188: for (Class clazz = a_object.getClass(); clazz.isArray(); clazz = clazz
189: .getComponentType()) {
190: count++;
191: }
192: int dim[] = new int[count];
193: for (int i = 0; i < count; i++) {
194: dim[i] = Array.getLength(a_object);
195: a_object = Array.get(a_object, 0);
196: }
197: return dim;
198: }
199:
200: static int arrayElementCount(int a_dim[]) {
201: int elements = a_dim[0];
202: for (int i = 1; i < a_dim.length; i++) {
203: elements *= a_dim[i];
204: }
205: return elements;
206: }
207:
208: private TCompare() {
209: }
210: }
|