0001: /*-
0002: * See the file LICENSE for redistribution information.
0003: *
0004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
0005: *
0006: * $Id: BindingTest.java,v 1.28.2.3 2008/01/07 15:14:35 cwl Exp $
0007: */
0008:
0009: package com.sleepycat.persist.test;
0010:
0011: import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
0012: import static com.sleepycat.persist.model.Relationship.ONE_TO_MANY;
0013: import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE;
0014:
0015: import java.io.File;
0016: import java.io.IOException;
0017: import java.lang.reflect.Array;
0018: import java.lang.reflect.Field;
0019: import java.math.BigInteger;
0020: import java.util.ArrayList;
0021: import java.util.Arrays;
0022: import java.util.Collection;
0023: import java.util.Comparator;
0024: import java.util.Date;
0025: import java.util.HashMap;
0026: import java.util.HashSet;
0027: import java.util.Iterator;
0028: import java.util.LinkedList;
0029: import java.util.List;
0030: import java.util.Locale;
0031: import java.util.Map;
0032: import java.util.Set;
0033: import java.util.TreeMap;
0034: import java.util.TreeSet;
0035:
0036: import junit.framework.TestCase;
0037:
0038: import com.sleepycat.bind.EntryBinding;
0039: import com.sleepycat.je.DatabaseConfig;
0040: import com.sleepycat.je.DatabaseEntry;
0041: import com.sleepycat.je.DatabaseException;
0042: import com.sleepycat.je.Environment;
0043: import com.sleepycat.je.EnvironmentConfig;
0044: import com.sleepycat.je.ForeignMultiKeyNullifier;
0045: import com.sleepycat.je.SecondaryKeyCreator;
0046: import com.sleepycat.je.SecondaryMultiKeyCreator;
0047: import com.sleepycat.je.util.TestUtils;
0048: import com.sleepycat.persist.impl.PersistCatalog;
0049: import com.sleepycat.persist.impl.PersistComparator;
0050: import com.sleepycat.persist.impl.PersistEntityBinding;
0051: import com.sleepycat.persist.impl.PersistKeyBinding;
0052: import com.sleepycat.persist.impl.PersistKeyCreator;
0053: import com.sleepycat.persist.impl.SimpleCatalog;
0054: import com.sleepycat.persist.model.AnnotationModel;
0055: import com.sleepycat.persist.model.ClassMetadata;
0056: import com.sleepycat.persist.model.Entity;
0057: import com.sleepycat.persist.model.EntityMetadata;
0058: import com.sleepycat.persist.model.EntityModel;
0059: import com.sleepycat.persist.model.KeyField;
0060: import com.sleepycat.persist.model.Persistent;
0061: import com.sleepycat.persist.model.PersistentProxy;
0062: import com.sleepycat.persist.model.PrimaryKey;
0063: import com.sleepycat.persist.model.PrimaryKeyMetadata;
0064: import com.sleepycat.persist.model.SecondaryKey;
0065: import com.sleepycat.persist.model.SecondaryKeyMetadata;
0066: import com.sleepycat.persist.raw.RawField;
0067: import com.sleepycat.persist.raw.RawObject;
0068: import com.sleepycat.persist.raw.RawType;
0069:
0070: /**
0071: * @author Mark Hayes
0072: */
0073: public class BindingTest extends TestCase {
0074:
0075: private static final String STORE_PREFIX = "persist#foo#";
0076:
0077: private File envHome;
0078: private Environment env;
0079: private EntityModel model;
0080: private PersistCatalog catalog;
0081: private DatabaseEntry keyEntry;
0082: private DatabaseEntry dataEntry;
0083:
0084: public void setUp() throws IOException {
0085:
0086: envHome = new File(System.getProperty(TestUtils.DEST_DIR));
0087: keyEntry = new DatabaseEntry();
0088: dataEntry = new DatabaseEntry();
0089: TestUtils.removeLogFiles("Setup", envHome, false);
0090: }
0091:
0092: public void tearDown() throws IOException {
0093:
0094: if (env != null) {
0095: try {
0096: env.close();
0097: } catch (DatabaseException e) {
0098: System.out.println("During tearDown: " + e);
0099: }
0100: }
0101: try {
0102: TestUtils.removeLogFiles("TearDown", envHome, false);
0103: } catch (Error e) {
0104: System.out.println("During tearDown: " + e);
0105: }
0106: envHome = null;
0107: env = null;
0108: catalog = null;
0109: keyEntry = null;
0110: dataEntry = null;
0111: }
0112:
0113: private void open() throws DatabaseException {
0114:
0115: EnvironmentConfig envConfig = new EnvironmentConfig();
0116: envConfig.setAllowCreate(true);
0117: env = new Environment(envHome, envConfig);
0118:
0119: openCatalog();
0120: }
0121:
0122: private void openCatalog() throws DatabaseException {
0123:
0124: model = new AnnotationModel();
0125: model.registerClass(LocalizedTextProxy.class);
0126: model.registerClass(LocaleProxy.class);
0127:
0128: DatabaseConfig dbConfig = new DatabaseConfig();
0129: dbConfig.setAllowCreate(true);
0130: catalog = new PersistCatalog(null, env, STORE_PREFIX,
0131: "catalog", dbConfig, model, null, false /*rawAccess*/,
0132: null /*Store*/);
0133: }
0134:
0135: private void close() throws DatabaseException {
0136:
0137: /* Close/open/close catalog to test checks for class evolution. */
0138: catalog.close();
0139: PersistCatalog.expectNoClassChanges = true;
0140: try {
0141: openCatalog();
0142: } finally {
0143: PersistCatalog.expectNoClassChanges = false;
0144: }
0145: catalog.close();
0146: catalog = null;
0147:
0148: env.close();
0149: env = null;
0150: }
0151:
0152: public void testBasic() throws DatabaseException {
0153:
0154: open();
0155:
0156: checkEntity(Basic.class, new Basic(1, "one", 2.2, "three"));
0157: checkEntity(Basic.class, new Basic(0, null, 0, null));
0158: checkEntity(Basic.class, new Basic(-1, "xxx", -2, "xxx"));
0159:
0160: checkMetadata(Basic.class.getName(),
0161: new String[][] { { "id", "long" },
0162: { "one", "java.lang.String" },
0163: { "two", "double" },
0164: { "three", "java.lang.String" }, },
0165: 0 /*priKeyIndex*/, null);
0166:
0167: close();
0168: }
0169:
0170: @Entity
0171: static class Basic implements MyEntity {
0172:
0173: @PrimaryKey
0174: private long id;
0175: private String one;
0176: private double two;
0177: private String three;
0178:
0179: private Basic() {
0180: }
0181:
0182: private Basic(long id, String one, double two, String three) {
0183: this .id = id;
0184: this .one = one;
0185: this .two = two;
0186: this .three = three;
0187: }
0188:
0189: public String getBasicOne() {
0190: return one;
0191: }
0192:
0193: public Object getPriKeyObject() {
0194: return id;
0195: }
0196:
0197: public void validate(Object other) {
0198: Basic o = (Basic) other;
0199: TestCase.assertEquals(id, o.id);
0200: TestCase.assertTrue(nullOrEqual(one, o.one));
0201: TestCase.assertEquals(two, o.two);
0202: TestCase.assertTrue(nullOrEqual(three, o.three));
0203: if (one == three) {
0204: TestCase.assertSame(o.one, o.three);
0205: }
0206: }
0207:
0208: @Override
0209: public String toString() {
0210: return "" + id + ' ' + one + ' ' + two;
0211: }
0212: }
0213:
0214: public void testSimpleTypes() throws DatabaseException {
0215:
0216: open();
0217:
0218: checkEntity(SimpleTypes.class, new SimpleTypes());
0219:
0220: checkMetadata(SimpleTypes.class.getName(), new String[][] {
0221: { "f0", "boolean" },
0222: { "f1", "char" },
0223: { "f2", "byte" },
0224: { "f3", "short" },
0225: { "f4", "int" },
0226: { "f5", "long" },
0227: { "f6", "float" },
0228: { "f7", "double" },
0229: { "f8", "java.lang.String" },
0230: { "f9", "java.math.BigInteger" },
0231: //{"f10", "java.math.BigDecimal"},
0232: { "f11", "java.util.Date" },
0233: { "f12", "java.lang.Boolean" },
0234: { "f13", "java.lang.Character" },
0235: { "f14", "java.lang.Byte" },
0236: { "f15", "java.lang.Short" },
0237: { "f16", "java.lang.Integer" },
0238: { "f17", "java.lang.Long" },
0239: { "f18", "java.lang.Float" },
0240: { "f19", "java.lang.Double" }, }, 0 /*priKeyIndex*/,
0241: null);
0242:
0243: close();
0244: }
0245:
0246: @Entity
0247: static class SimpleTypes implements MyEntity {
0248:
0249: @PrimaryKey
0250: private boolean f0 = true;
0251: private char f1 = 'a';
0252: private byte f2 = 123;
0253: private short f3 = 123;
0254: private int f4 = 123;
0255: private long f5 = 123;
0256: private float f6 = 123.4f;
0257: private double f7 = 123.4;
0258: private String f8 = "xxx";
0259: private BigInteger f9 = BigInteger.valueOf(123);
0260: //private BigDecimal f10 = BigDecimal.valueOf(123.4);
0261: private Date f11 = new Date();
0262: private Boolean f12 = true;
0263: private Character f13 = 'a';
0264: private Byte f14 = 123;
0265: private Short f15 = 123;
0266: private Integer f16 = 123;
0267: private Long f17 = 123L;
0268: private Float f18 = 123.4f;
0269: private Double f19 = 123.4;
0270:
0271: SimpleTypes() {
0272: }
0273:
0274: public Object getPriKeyObject() {
0275: return f0;
0276: }
0277:
0278: public void validate(Object other) {
0279: SimpleTypes o = (SimpleTypes) other;
0280: TestCase.assertEquals(f0, o.f0);
0281: TestCase.assertEquals(f1, o.f1);
0282: TestCase.assertEquals(f2, o.f2);
0283: TestCase.assertEquals(f3, o.f3);
0284: TestCase.assertEquals(f4, o.f4);
0285: TestCase.assertEquals(f5, o.f5);
0286: TestCase.assertEquals(f6, o.f6);
0287: TestCase.assertEquals(f7, o.f7);
0288: TestCase.assertEquals(f8, o.f8);
0289: TestCase.assertEquals(f9, o.f9);
0290: //TestCase.assertEquals(f10, o.f10);
0291: TestCase.assertEquals(f11, o.f11);
0292: TestCase.assertEquals(f12, o.f12);
0293: TestCase.assertEquals(f13, o.f13);
0294: TestCase.assertEquals(f14, o.f14);
0295: TestCase.assertEquals(f15, o.f15);
0296: TestCase.assertEquals(f16, o.f16);
0297: TestCase.assertEquals(f17, o.f17);
0298: TestCase.assertEquals(f18, o.f18);
0299: TestCase.assertEquals(f19, o.f19);
0300: }
0301: }
0302:
0303: public void testArrayTypes() throws DatabaseException {
0304:
0305: open();
0306:
0307: checkEntity(ArrayTypes.class, new ArrayTypes());
0308:
0309: checkMetadata(ArrayTypes.class.getName(), new String[][] {
0310: { "id", "int" }, { "f0", boolean[].class.getName() },
0311: { "f1", char[].class.getName() },
0312: { "f2", byte[].class.getName() },
0313: { "f3", short[].class.getName() },
0314: { "f4", int[].class.getName() },
0315: { "f5", long[].class.getName() },
0316: { "f6", float[].class.getName() },
0317: { "f7", double[].class.getName() },
0318: { "f8", String[].class.getName() },
0319: { "f9", Address[].class.getName() },
0320: { "f10", boolean[][][].class.getName() },
0321: { "f11", String[][][].class.getName() }, },
0322: 0 /*priKeyIndex*/, null);
0323:
0324: close();
0325: }
0326:
0327: @Entity
0328: static class ArrayTypes implements MyEntity {
0329:
0330: @PrimaryKey
0331: private int id = 1;
0332: private boolean[] f0 = { false, true };
0333: private char[] f1 = { 'a', 'b' };
0334: private byte[] f2 = { 1, 2 };
0335: private short[] f3 = { 1, 2 };
0336: private int[] f4 = { 1, 2 };
0337: private long[] f5 = { 1, 2 };
0338: private float[] f6 = { 1.1f, 2.2f };
0339: private double[] f7 = { 1.1, 2, 2 };
0340: private String[] f8 = { "xxx", null, "yyy" };
0341: private Address[] f9 = { new Address("city", "state", 123),
0342: null, new Address("x", "y", 444) };
0343: private boolean[][][] f10 = {
0344: { { false, true }, { false, true }, }, null,
0345: { { false, true }, { false, true }, }, };
0346: private String[][][] f11 = {
0347: { { "xxx", null, "yyy" }, null, { "xxx", null, "yyy" }, },
0348: null,
0349: { { "xxx", null, "yyy" }, null, { "xxx", null, "yyy" }, }, };
0350:
0351: ArrayTypes() {
0352: }
0353:
0354: public Object getPriKeyObject() {
0355: return id;
0356: }
0357:
0358: public void validate(Object other) {
0359: ArrayTypes o = (ArrayTypes) other;
0360: TestCase.assertEquals(id, o.id);
0361: TestCase.assertTrue(Arrays.equals(f0, o.f0));
0362: TestCase.assertTrue(Arrays.equals(f1, o.f1));
0363: TestCase.assertTrue(Arrays.equals(f2, o.f2));
0364: TestCase.assertTrue(Arrays.equals(f3, o.f3));
0365: TestCase.assertTrue(Arrays.equals(f4, o.f4));
0366: TestCase.assertTrue(Arrays.equals(f5, o.f5));
0367: TestCase.assertTrue(Arrays.equals(f6, o.f6));
0368: TestCase.assertTrue(Arrays.equals(f7, o.f7));
0369: TestCase.assertTrue(Arrays.equals(f8, o.f8));
0370: TestCase.assertTrue(Arrays.deepEquals(f9, o.f9));
0371: TestCase.assertTrue(Arrays.deepEquals(f10, o.f10));
0372: TestCase.assertTrue(Arrays.deepEquals(f11, o.f11));
0373: }
0374: }
0375:
0376: public void testEnumTypes() throws DatabaseException {
0377:
0378: open();
0379:
0380: checkEntity(EnumTypes.class, new EnumTypes());
0381:
0382: checkMetadata(EnumTypes.class.getName(), new String[][] {
0383: { "f0", "int" },
0384: { "f1", Thread.State.class.getName() },
0385: { "f2", EnumTypes.MyEnum.class.getName() },
0386: { "f3", Object.class.getName() }, },
0387: 0 /*priKeyIndex*/, null);
0388:
0389: close();
0390: }
0391:
0392: @Entity
0393: static class EnumTypes implements MyEntity {
0394:
0395: private static enum MyEnum {
0396: ONE, TWO
0397: };
0398:
0399: @PrimaryKey
0400: private int f0 = 1;
0401: private Thread.State f1 = Thread.State.RUNNABLE;
0402: private MyEnum f2 = MyEnum.ONE;
0403: private Object f3 = MyEnum.TWO;
0404:
0405: EnumTypes() {
0406: }
0407:
0408: public Object getPriKeyObject() {
0409: return f0;
0410: }
0411:
0412: public void validate(Object other) {
0413: EnumTypes o = (EnumTypes) other;
0414: TestCase.assertEquals(f0, o.f0);
0415: TestCase.assertSame(f1, o.f1);
0416: TestCase.assertSame(f2, o.f2);
0417: TestCase.assertSame(f3, o.f3);
0418: }
0419: }
0420:
0421: public void testProxyTypes() throws DatabaseException {
0422:
0423: open();
0424:
0425: checkEntity(ProxyTypes.class, new ProxyTypes());
0426:
0427: checkMetadata(ProxyTypes.class.getName(), new String[][] {
0428: { "f0", "int" }, { "f1", Locale.class.getName() },
0429: { "f2", Set.class.getName() },
0430: { "f3", Set.class.getName() },
0431: { "f4", Object.class.getName() },
0432: { "f5", HashMap.class.getName() },
0433: { "f6", TreeMap.class.getName() },
0434: { "f7", List.class.getName() },
0435: { "f8", LinkedList.class.getName() },
0436: { "f9", LocalizedText.class.getName() }, },
0437: 0 /*priKeyIndex*/, null);
0438:
0439: close();
0440: }
0441:
0442: @Entity
0443: static class ProxyTypes implements MyEntity {
0444:
0445: @PrimaryKey
0446: private int f0 = 1;
0447: private Locale f1 = Locale.getDefault();
0448: private Set<Integer> f2 = new HashSet<Integer>();
0449: private Set<Integer> f3 = new TreeSet<Integer>();
0450: private Object f4 = new HashSet<Address>();
0451: private HashMap<String, Integer> f5 = new HashMap<String, Integer>();
0452: private TreeMap<String, Address> f6 = new TreeMap<String, Address>();
0453: private List<Integer> f7 = new ArrayList<Integer>();
0454: private LinkedList<Integer> f8 = new LinkedList<Integer>();
0455: private LocalizedText f9 = new LocalizedText(f1, "xyz");
0456:
0457: ProxyTypes() {
0458: f2.add(123);
0459: f2.add(456);
0460: f3.add(456);
0461: f3.add(123);
0462: HashSet<Address> s = (HashSet) f4;
0463: s.add(new Address("city", "state", 11111));
0464: s.add(new Address("city2", "state2", 22222));
0465: s.add(new Address("city3", "state3", 33333));
0466: f5.put("one", 111);
0467: f5.put("two", 222);
0468: f5.put("three", 333);
0469: f6.put("one", new Address("city", "state", 11111));
0470: f6.put("two", new Address("city2", "state2", 22222));
0471: f6.put("three", new Address("city3", "state3", 33333));
0472: f7.add(123);
0473: f7.add(456);
0474: f8.add(123);
0475: f8.add(456);
0476: }
0477:
0478: public Object getPriKeyObject() {
0479: return f0;
0480: }
0481:
0482: public void validate(Object other) {
0483: ProxyTypes o = (ProxyTypes) other;
0484: TestCase.assertEquals(f0, o.f0);
0485: TestCase.assertEquals(f1, o.f1);
0486: TestCase.assertEquals(f2, o.f2);
0487: TestCase.assertEquals(f3, o.f3);
0488: TestCase.assertEquals(f4, o.f4);
0489: TestCase.assertEquals(f5, o.f5);
0490: TestCase.assertEquals(f6, o.f6);
0491: TestCase.assertEquals(f7, o.f7);
0492: TestCase.assertEquals(f8, o.f8);
0493: TestCase.assertEquals(f9, o.f9);
0494: }
0495: }
0496:
0497: @Persistent(proxyFor=Locale.class)
0498: static class LocaleProxy implements PersistentProxy<Locale> {
0499:
0500: String language;
0501: String country;
0502: String variant;
0503:
0504: private LocaleProxy() {
0505: }
0506:
0507: public void initializeProxy(Locale object) {
0508: language = object.getLanguage();
0509: country = object.getCountry();
0510: variant = object.getVariant();
0511: }
0512:
0513: public Locale convertProxy() {
0514: return new Locale(language, country, variant);
0515: }
0516: }
0517:
0518: static class LocalizedText {
0519:
0520: Locale locale;
0521: String text;
0522:
0523: LocalizedText(Locale locale, String text) {
0524: this .locale = locale;
0525: this .text = text;
0526: }
0527:
0528: @Override
0529: public boolean equals(Object other) {
0530: LocalizedText o = (LocalizedText) other;
0531: return text.equals(o.text) && locale.equals(o.locale);
0532: }
0533: }
0534:
0535: @Persistent(proxyFor=LocalizedText.class)
0536: static class LocalizedTextProxy implements
0537: PersistentProxy<LocalizedText> {
0538:
0539: Locale locale;
0540: String text;
0541:
0542: private LocalizedTextProxy() {
0543: }
0544:
0545: public void initializeProxy(LocalizedText object) {
0546: locale = object.locale;
0547: text = object.text;
0548: }
0549:
0550: public LocalizedText convertProxy() {
0551: return new LocalizedText(locale, text);
0552: }
0553: }
0554:
0555: public void testEmbedded() throws DatabaseException {
0556:
0557: open();
0558:
0559: Address a1 = new Address("city", "state", 123);
0560: Address a2 = new Address("Wikieup", "AZ", 85360);
0561:
0562: checkEntity(Embedded.class, new Embedded("x", a1, a2));
0563: checkEntity(Embedded.class, new Embedded("y", a1, null));
0564: checkEntity(Embedded.class, new Embedded("", a2, a2));
0565:
0566: checkMetadata(Embedded.class.getName(), new String[][] {
0567: { "id", "java.lang.String" },
0568: { "idShadow", "java.lang.String" },
0569: { "one", Address.class.getName() },
0570: { "two", Address.class.getName() }, },
0571: 0 /*priKeyIndex*/, null);
0572:
0573: checkMetadata(Address.class.getName(), new String[][] {
0574: { "street", "java.lang.String" },
0575: { "city", "java.lang.String" }, { "zip", "int" }, },
0576: -1 /*priKeyIndex*/, null);
0577:
0578: close();
0579: }
0580:
0581: @Entity
0582: static class Embedded implements MyEntity {
0583:
0584: @PrimaryKey
0585: private String id;
0586: private String idShadow;
0587: private Address one;
0588: private Address two;
0589:
0590: private Embedded() {
0591: }
0592:
0593: private Embedded(String id, Address one, Address two) {
0594: this .id = id;
0595: idShadow = id;
0596: this .one = one;
0597: this .two = two;
0598: }
0599:
0600: public Object getPriKeyObject() {
0601: return id;
0602: }
0603:
0604: public void validate(Object other) {
0605: Embedded o = (Embedded) other;
0606: TestCase.assertEquals(id, o.id);
0607: if (one != null) {
0608: one.validate(o.one);
0609: } else {
0610: assertNull(o.one);
0611: }
0612: if (two != null) {
0613: two.validate(o.two);
0614: } else {
0615: assertNull(o.two);
0616: }
0617: TestCase.assertSame(o.id, o.idShadow);
0618: if (one == two) {
0619: TestCase.assertSame(o.one, o.two);
0620: }
0621: }
0622:
0623: @Override
0624: public String toString() {
0625: return "" + id + ' ' + one + ' ' + two;
0626: }
0627: }
0628:
0629: @Persistent
0630: static class Address {
0631:
0632: private String street;
0633: private String city;
0634: private int zip;
0635:
0636: private Address() {
0637: }
0638:
0639: Address(String street, String city, int zip) {
0640: this .street = street;
0641: this .city = city;
0642: this .zip = zip;
0643: }
0644:
0645: void validate(Address o) {
0646: TestCase.assertTrue(nullOrEqual(street, o.street));
0647: TestCase.assertTrue(nullOrEqual(city, o.city));
0648: TestCase.assertEquals(zip, o.zip);
0649: }
0650:
0651: @Override
0652: public String toString() {
0653: return "" + street + ' ' + city + ' ' + zip;
0654: }
0655:
0656: @Override
0657: public boolean equals(Object other) {
0658: if (other == null) {
0659: return false;
0660: }
0661: Address o = (Address) other;
0662: return nullOrEqual(street, o.street)
0663: && nullOrEqual(city, o.city)
0664: && nullOrEqual(zip, o.zip);
0665: }
0666:
0667: @Override
0668: public int hashCode() {
0669: return zip;
0670: }
0671: }
0672:
0673: public void testSubclass() throws DatabaseException {
0674:
0675: open();
0676:
0677: checkEntity(Basic.class, new Subclass(-1, "xxx", -2, "xxx",
0678: "xxx", true));
0679:
0680: checkMetadata(Basic.class.getName(),
0681: new String[][] { { "id", "long" },
0682: { "one", "java.lang.String" },
0683: { "two", "double" },
0684: { "three", "java.lang.String" }, },
0685: 0 /*priKeyIndex*/, null);
0686: checkMetadata(Subclass.class.getName(), new String[][] {
0687: { "one", "java.lang.String" }, { "two", "boolean" }, },
0688: -1 /*priKeyIndex*/, Basic.class.getName());
0689:
0690: close();
0691: }
0692:
0693: @Persistent
0694: static class Subclass extends Basic {
0695:
0696: private String one;
0697: private boolean two;
0698:
0699: private Subclass() {
0700: }
0701:
0702: private Subclass(long id, String one, double two, String three,
0703: String subOne, boolean subTwo) {
0704: super (id, one, two, three);
0705: this .one = subOne;
0706: this .two = subTwo;
0707: }
0708:
0709: public void validate(Object other) {
0710: super .validate(other);
0711: Subclass o = (Subclass) other;
0712: TestCase.assertTrue(nullOrEqual(one, o.one));
0713: TestCase.assertEquals(two, o.two);
0714: if (one == getBasicOne()) {
0715: TestCase.assertSame(o.one, o.getBasicOne());
0716: }
0717: }
0718: }
0719:
0720: public void testSuperclass() throws DatabaseException {
0721:
0722: open();
0723:
0724: checkEntity(UseSuperclass.class, new UseSuperclass(33, "xxx"));
0725:
0726: checkMetadata(Superclass.class.getName(), new String[][] {
0727: { "id", "int" }, { "one", "java.lang.String" }, },
0728: 0 /*priKeyIndex*/, null);
0729: checkMetadata(UseSuperclass.class.getName(), new String[][] {},
0730: -1 /*priKeyIndex*/, Superclass.class.getName());
0731:
0732: close();
0733: }
0734:
0735: @Persistent
0736: static class Superclass implements MyEntity {
0737:
0738: @PrimaryKey
0739: private int id;
0740: private String one;
0741:
0742: private Superclass() {
0743: }
0744:
0745: private Superclass(int id, String one) {
0746: this .id = id;
0747: this .one = one;
0748: }
0749:
0750: public Object getPriKeyObject() {
0751: return id;
0752: }
0753:
0754: public void validate(Object other) {
0755: Superclass o = (Superclass) other;
0756: TestCase.assertEquals(id, o.id);
0757: TestCase.assertTrue(nullOrEqual(one, o.one));
0758: }
0759: }
0760:
0761: @Entity
0762: static class UseSuperclass extends Superclass {
0763:
0764: private UseSuperclass() {
0765: }
0766:
0767: private UseSuperclass(int id, String one) {
0768: super (id, one);
0769: }
0770: }
0771:
0772: public void testAbstract() throws DatabaseException {
0773:
0774: open();
0775:
0776: checkEntity(EntityUseAbstract.class, new EntityUseAbstract(33,
0777: "xxx"));
0778:
0779: checkMetadata(Abstract.class.getName(), new String[][] { {
0780: "one", "java.lang.String" }, }, -1 /*priKeyIndex*/,
0781: null);
0782: checkMetadata(EmbeddedUseAbstract.class.getName(),
0783: new String[][] { { "two", "java.lang.String" }, },
0784: -1 /*priKeyIndex*/, Abstract.class.getName());
0785: checkMetadata(
0786: EntityUseAbstract.class.getName(),
0787: new String[][] {
0788: { "id", "int" },
0789: { "f1", EmbeddedUseAbstract.class.getName() },
0790: { "f2", Abstract.class.getName() },
0791: { "f3", Object.class.getName() },
0792: { "f4", Interface.class.getName() },
0793: { "a1", EmbeddedUseAbstract[].class.getName() },
0794: { "a2", Abstract[].class.getName() },
0795: { "a3", Abstract[].class.getName() },
0796: { "a4", Object[].class.getName() },
0797: { "a5", Interface[].class.getName() },
0798: { "a6", Interface[].class.getName() },
0799: { "a7", Interface[].class.getName() }, },
0800: 0 /*priKeyIndex*/, Abstract.class.getName());
0801:
0802: close();
0803: }
0804:
0805: @Persistent
0806: static abstract class Abstract implements Interface {
0807:
0808: String one;
0809:
0810: private Abstract() {
0811: }
0812:
0813: private Abstract(String one) {
0814: this .one = one;
0815: }
0816:
0817: public void validate(Object other) {
0818: Abstract o = (Abstract) other;
0819: TestCase.assertTrue(nullOrEqual(one, o.one));
0820: }
0821:
0822: @Override
0823: public boolean equals(Object other) {
0824: Abstract o = (Abstract) other;
0825: return nullOrEqual(one, o.one);
0826: }
0827: }
0828:
0829: interface Interface {
0830: void validate(Object other);
0831: }
0832:
0833: @Persistent
0834: static class EmbeddedUseAbstract extends Abstract {
0835:
0836: private String two;
0837:
0838: private EmbeddedUseAbstract() {
0839: }
0840:
0841: private EmbeddedUseAbstract(String one, String two) {
0842: super (one);
0843: this .two = two;
0844: }
0845:
0846: @Override
0847: public void validate(Object other) {
0848: super .validate(other);
0849: EmbeddedUseAbstract o = (EmbeddedUseAbstract) other;
0850: TestCase.assertTrue(nullOrEqual(two, o.two));
0851: }
0852:
0853: @Override
0854: public boolean equals(Object other) {
0855: if (!super .equals(other)) {
0856: return false;
0857: }
0858: EmbeddedUseAbstract o = (EmbeddedUseAbstract) other;
0859: return nullOrEqual(two, o.two);
0860: }
0861: }
0862:
0863: @Entity
0864: static class EntityUseAbstract extends Abstract implements MyEntity {
0865:
0866: @PrimaryKey
0867: private int id;
0868:
0869: private EmbeddedUseAbstract f1;
0870: private Abstract f2;
0871: private Object f3;
0872: private Interface f4;
0873: private EmbeddedUseAbstract[] a1;
0874: private Abstract[] a2;
0875: private Abstract[] a3;
0876: private Object[] a4;
0877: private Interface[] a5;
0878: private Interface[] a6;
0879: private Interface[] a7;
0880:
0881: private EntityUseAbstract() {
0882: }
0883:
0884: private EntityUseAbstract(int id, String one) {
0885: super (one);
0886: this .id = id;
0887: f1 = new EmbeddedUseAbstract(one, one);
0888: f2 = new EmbeddedUseAbstract(one + "x", one + "y");
0889: f3 = new EmbeddedUseAbstract(null, null);
0890: f4 = new EmbeddedUseAbstract(null, null);
0891: a1 = new EmbeddedUseAbstract[3];
0892: a2 = new EmbeddedUseAbstract[3];
0893: a3 = new Abstract[3];
0894: a4 = new Object[3];
0895: a5 = new EmbeddedUseAbstract[3];
0896: a6 = new Abstract[3];
0897: a7 = new Interface[3];
0898: for (int i = 0; i < 3; i += 1) {
0899: a1[i] = new EmbeddedUseAbstract("1" + i, null);
0900: a2[i] = new EmbeddedUseAbstract("2" + i, null);
0901: a3[i] = new EmbeddedUseAbstract("3" + i, null);
0902: a4[i] = new EmbeddedUseAbstract("4" + i, null);
0903: a5[i] = new EmbeddedUseAbstract("5" + i, null);
0904: a6[i] = new EmbeddedUseAbstract("6" + i, null);
0905: a7[i] = new EmbeddedUseAbstract("7" + i, null);
0906: }
0907: }
0908:
0909: public Object getPriKeyObject() {
0910: return id;
0911: }
0912:
0913: @Override
0914: public void validate(Object other) {
0915: super .validate(other);
0916: EntityUseAbstract o = (EntityUseAbstract) other;
0917: TestCase.assertEquals(id, o.id);
0918: f1.validate(o.f1);
0919: assertSame(o.one, o.f1.one);
0920: assertSame(o.f1.one, o.f1.two);
0921: f2.validate(o.f2);
0922: ((Abstract) f3).validate(o.f3);
0923: f4.validate(o.f4);
0924: assertTrue(arrayToString(a1) + ' ' + arrayToString(o.a1),
0925: Arrays.equals(a1, o.a1));
0926: assertTrue(Arrays.equals(a2, o.a2));
0927: assertTrue(Arrays.equals(a3, o.a3));
0928: assertTrue(Arrays.equals(a4, o.a4));
0929: assertTrue(Arrays.equals(a5, o.a5));
0930: assertTrue(Arrays.equals(a6, o.a6));
0931: assertTrue(Arrays.equals(a7, o.a7));
0932: assertSame(EmbeddedUseAbstract.class, f2.getClass());
0933: assertSame(EmbeddedUseAbstract.class, f3.getClass());
0934: assertSame(EmbeddedUseAbstract[].class, a1.getClass());
0935: assertSame(EmbeddedUseAbstract[].class, a2.getClass());
0936: assertSame(Abstract[].class, a3.getClass());
0937: assertSame(Object[].class, a4.getClass());
0938: assertSame(EmbeddedUseAbstract[].class, a5.getClass());
0939: assertSame(Abstract[].class, a6.getClass());
0940: assertSame(Interface[].class, a7.getClass());
0941: }
0942: }
0943:
0944: public void testCompositeKey() throws DatabaseException {
0945:
0946: open();
0947:
0948: CompositeKey key = new CompositeKey(123, 456L, "xyz",
0949: BigInteger.valueOf(789));
0950: checkEntity(UseCompositeKey.class, new UseCompositeKey(key,
0951: "one"));
0952:
0953: checkMetadata(UseCompositeKey.class.getName(), new String[][] {
0954: { "key", CompositeKey.class.getName() },
0955: { "one", "java.lang.String" }, }, 0 /*priKeyIndex*/,
0956: null);
0957:
0958: checkMetadata(CompositeKey.class.getName(), new String[][] {
0959: { "f1", "int" }, { "f2", "java.lang.Long" },
0960: { "f3", "java.lang.String" },
0961: { "f4", "java.math.BigInteger" }, },
0962: -1 /*priKeyIndex*/, null);
0963:
0964: close();
0965: }
0966:
0967: @Persistent
0968: static class CompositeKey {
0969: @KeyField(3)
0970: private int f1;
0971: @KeyField(2)
0972: private Long f2;
0973: @KeyField(1)
0974: private String f3;
0975: @KeyField(4)
0976: private BigInteger f4;
0977:
0978: private CompositeKey() {
0979: }
0980:
0981: CompositeKey(int f1, Long f2, String f3, BigInteger f4) {
0982: this .f1 = f1;
0983: this .f2 = f2;
0984: this .f3 = f3;
0985: this .f4 = f4;
0986: }
0987:
0988: void validate(CompositeKey o) {
0989: TestCase.assertEquals(f1, o.f1);
0990: TestCase.assertTrue(nullOrEqual(f2, o.f2));
0991: TestCase.assertTrue(nullOrEqual(f3, o.f3));
0992: TestCase.assertTrue(nullOrEqual(f4, o.f4));
0993: }
0994:
0995: @Override
0996: public boolean equals(Object other) {
0997: CompositeKey o = (CompositeKey) other;
0998: return f1 == o.f1 && nullOrEqual(f2, o.f2)
0999: && nullOrEqual(f3, o.f3) && nullOrEqual(f4, o.f4);
1000: }
1001:
1002: @Override
1003: public int hashCode() {
1004: return f1;
1005: }
1006:
1007: @Override
1008: public String toString() {
1009: return "" + f1 + ' ' + f2 + ' ' + f3 + ' ' + f4;
1010: }
1011: }
1012:
1013: @Entity
1014: static class UseCompositeKey implements MyEntity {
1015:
1016: @PrimaryKey
1017: private CompositeKey key;
1018: private String one;
1019:
1020: private UseCompositeKey() {
1021: }
1022:
1023: private UseCompositeKey(CompositeKey key, String one) {
1024: this .key = key;
1025: this .one = one;
1026: }
1027:
1028: public Object getPriKeyObject() {
1029: return key;
1030: }
1031:
1032: public void validate(Object other) {
1033: UseCompositeKey o = (UseCompositeKey) other;
1034: TestCase.assertNotNull(key);
1035: TestCase.assertNotNull(o.key);
1036: key.validate(o.key);
1037: TestCase.assertTrue(nullOrEqual(one, o.one));
1038: }
1039: }
1040:
1041: public void testComparableKey() throws DatabaseException {
1042:
1043: open();
1044:
1045: ComparableKey key = new ComparableKey(123, 456);
1046: checkEntity(UseComparableKey.class, new UseComparableKey(key,
1047: "one"));
1048:
1049: checkMetadata(UseComparableKey.class.getName(), new String[][] {
1050: { "key", ComparableKey.class.getName() },
1051: { "one", "java.lang.String" }, }, 0 /*priKeyIndex*/,
1052: null);
1053:
1054: checkMetadata(ComparableKey.class.getName(), new String[][] {
1055: { "f1", "int" }, { "f2", "int" }, },
1056: -1 /*priKeyIndex*/, null);
1057:
1058: ClassMetadata classMeta = model
1059: .getClassMetadata(UseComparableKey.class.getName());
1060: assertNotNull(classMeta);
1061:
1062: PersistKeyBinding binding = new PersistKeyBinding(catalog,
1063: ComparableKey.class.getName(), false);
1064:
1065: PersistComparator comparator = new PersistComparator(
1066: ComparableKey.class.getName(), classMeta
1067: .getCompositeKeyFields(), binding);
1068:
1069: compareKeys(comparator, binding, new ComparableKey(1, 1),
1070: new ComparableKey(1, 1), 0);
1071: compareKeys(comparator, binding, new ComparableKey(1, 2),
1072: new ComparableKey(1, 1), -1);
1073: compareKeys(comparator, binding, new ComparableKey(2, 1),
1074: new ComparableKey(1, 1), -1);
1075: compareKeys(comparator, binding, new ComparableKey(2, 1),
1076: new ComparableKey(3, 1), 1);
1077:
1078: close();
1079: }
1080:
1081: private void compareKeys(Comparator<Object> comparator,
1082: EntryBinding binding, Object key1, Object key2,
1083: int expectResult) {
1084: DatabaseEntry entry1 = new DatabaseEntry();
1085: DatabaseEntry entry2 = new DatabaseEntry();
1086: binding.objectToEntry(key1, entry1);
1087: binding.objectToEntry(key2, entry2);
1088: int result = comparator.compare(entry1.getData(), entry2
1089: .getData());
1090: assertEquals(expectResult, result);
1091: }
1092:
1093: @Persistent
1094: static class ComparableKey implements Comparable<ComparableKey> {
1095: @KeyField(2)
1096: private int f1;
1097: @KeyField(1)
1098: private int f2;
1099:
1100: private ComparableKey() {
1101: }
1102:
1103: ComparableKey(int f1, int f2) {
1104: this .f1 = f1;
1105: this .f2 = f2;
1106: }
1107:
1108: void validate(ComparableKey o) {
1109: TestCase.assertEquals(f1, o.f1);
1110: TestCase.assertEquals(f2, o.f2);
1111: }
1112:
1113: @Override
1114: public boolean equals(Object other) {
1115: ComparableKey o = (ComparableKey) other;
1116: return f1 == o.f1 && f2 == o.f2;
1117: }
1118:
1119: @Override
1120: public int hashCode() {
1121: return f1 + f2;
1122: }
1123:
1124: @Override
1125: public String toString() {
1126: return "" + f1 + ' ' + f2;
1127: }
1128:
1129: /** Compare f1 then f2, in reverse integer order. */
1130: public int compareTo(ComparableKey o) {
1131: if (f1 != o.f1) {
1132: return o.f1 - f1;
1133: } else {
1134: return o.f2 - f2;
1135: }
1136: }
1137: }
1138:
1139: @Entity
1140: static class UseComparableKey implements MyEntity {
1141:
1142: @PrimaryKey
1143: private ComparableKey key;
1144: private String one;
1145:
1146: private UseComparableKey() {
1147: }
1148:
1149: private UseComparableKey(ComparableKey key, String one) {
1150: this .key = key;
1151: this .one = one;
1152: }
1153:
1154: public Object getPriKeyObject() {
1155: return key;
1156: }
1157:
1158: public void validate(Object other) {
1159: UseComparableKey o = (UseComparableKey) other;
1160: TestCase.assertNotNull(key);
1161: TestCase.assertNotNull(o.key);
1162: key.validate(o.key);
1163: TestCase.assertTrue(nullOrEqual(one, o.one));
1164: }
1165: }
1166:
1167: public void testSecKeys() throws DatabaseException {
1168:
1169: open();
1170:
1171: SecKeys obj = new SecKeys();
1172: checkEntity(SecKeys.class, obj);
1173:
1174: checkMetadata(SecKeys.class.getName(), new String[][] {
1175: { "id", "long" },
1176: { "f0", "boolean" },
1177: { "g0", "boolean" },
1178: { "f1", "char" },
1179: { "g1", "char" },
1180: { "f2", "byte" },
1181: { "g2", "byte" },
1182: { "f3", "short" },
1183: { "g3", "short" },
1184: { "f4", "int" },
1185: { "g4", "int" },
1186: { "f5", "long" },
1187: { "g5", "long" },
1188: { "f6", "float" },
1189: { "g6", "float" },
1190: { "f7", "double" },
1191: { "g7", "double" },
1192: { "f8", "java.lang.String" },
1193: { "g8", "java.lang.String" },
1194: { "f9", "java.math.BigInteger" },
1195: { "g9", "java.math.BigInteger" },
1196: //{"f10", "java.math.BigDecimal"},
1197: //{"g10", "java.math.BigDecimal"},
1198: { "f11", "java.util.Date" },
1199: { "g11", "java.util.Date" },
1200: { "f12", "java.lang.Boolean" },
1201: { "g12", "java.lang.Boolean" },
1202: { "f13", "java.lang.Character" },
1203: { "g13", "java.lang.Character" },
1204: { "f14", "java.lang.Byte" },
1205: { "g14", "java.lang.Byte" },
1206: { "f15", "java.lang.Short" },
1207: { "g15", "java.lang.Short" },
1208: { "f16", "java.lang.Integer" },
1209: { "g16", "java.lang.Integer" },
1210: { "f17", "java.lang.Long" },
1211: { "g17", "java.lang.Long" },
1212: { "f18", "java.lang.Float" },
1213: { "g18", "java.lang.Float" },
1214: { "f19", "java.lang.Double" },
1215: { "g19", "java.lang.Double" },
1216: { "f20", CompositeKey.class.getName() },
1217: { "g20", CompositeKey.class.getName() },
1218: { "f21", int[].class.getName() },
1219: { "g21", int[].class.getName() },
1220: { "f22", Integer[].class.getName() },
1221: { "g22", Integer[].class.getName() },
1222: { "f23", Set.class.getName() },
1223: { "g23", Set.class.getName() },
1224: { "f24", CompositeKey[].class.getName() },
1225: { "g24", CompositeKey[].class.getName() },
1226: { "f25", Set.class.getName() },
1227: { "g25", Set.class.getName() },
1228: { "f31", "java.util.Date" },
1229: { "f32", "java.lang.Boolean" },
1230: { "f33", "java.lang.Character" },
1231: { "f34", "java.lang.Byte" },
1232: { "f35", "java.lang.Short" },
1233: { "f36", "java.lang.Integer" },
1234: { "f37", "java.lang.Long" },
1235: { "f38", "java.lang.Float" },
1236: { "f39", "java.lang.Double" },
1237: { "f40", CompositeKey.class.getName() }, },
1238: 0 /*priKeyIndex*/, null);
1239:
1240: checkSecKey(obj, "f0", obj.f0, Boolean.class);
1241: checkSecKey(obj, "f1", obj.f1, Character.class);
1242: checkSecKey(obj, "f2", obj.f2, Byte.class);
1243: checkSecKey(obj, "f3", obj.f3, Short.class);
1244: checkSecKey(obj, "f4", obj.f4, Integer.class);
1245: checkSecKey(obj, "f5", obj.f5, Long.class);
1246: checkSecKey(obj, "f6", obj.f6, Float.class);
1247: checkSecKey(obj, "f7", obj.f7, Double.class);
1248: checkSecKey(obj, "f8", obj.f8, String.class);
1249: checkSecKey(obj, "f9", obj.f9, BigInteger.class);
1250: //checkSecKey(obj, "f10", obj.f10, BigDecimal.class);
1251: checkSecKey(obj, "f11", obj.f11, Date.class);
1252: checkSecKey(obj, "f12", obj.f12, Boolean.class);
1253: checkSecKey(obj, "f13", obj.f13, Character.class);
1254: checkSecKey(obj, "f14", obj.f14, Byte.class);
1255: checkSecKey(obj, "f15", obj.f15, Short.class);
1256: checkSecKey(obj, "f16", obj.f16, Integer.class);
1257: checkSecKey(obj, "f17", obj.f17, Long.class);
1258: checkSecKey(obj, "f18", obj.f18, Float.class);
1259: checkSecKey(obj, "f19", obj.f19, Double.class);
1260: checkSecKey(obj, "f20", obj.f20, CompositeKey.class);
1261:
1262: checkSecMultiKey(obj, "f21", toSet(obj.f21), Integer.class);
1263: checkSecMultiKey(obj, "f22", toSet(obj.f22), Integer.class);
1264: checkSecMultiKey(obj, "f23", toSet(obj.f23), Integer.class);
1265: checkSecMultiKey(obj, "f24", toSet(obj.f24), CompositeKey.class);
1266: checkSecMultiKey(obj, "f25", toSet(obj.f25), CompositeKey.class);
1267:
1268: nullifySecKey(obj, "f8", obj.f8, String.class);
1269: nullifySecKey(obj, "f9", obj.f9, BigInteger.class);
1270: //nullifySecKey(obj, "f10", obj.f10, BigDecimal.class);
1271: nullifySecKey(obj, "f11", obj.f11, Date.class);
1272: nullifySecKey(obj, "f12", obj.f12, Boolean.class);
1273: nullifySecKey(obj, "f13", obj.f13, Character.class);
1274: nullifySecKey(obj, "f14", obj.f14, Byte.class);
1275: nullifySecKey(obj, "f15", obj.f15, Short.class);
1276: nullifySecKey(obj, "f16", obj.f16, Integer.class);
1277: nullifySecKey(obj, "f17", obj.f17, Long.class);
1278: nullifySecKey(obj, "f18", obj.f18, Float.class);
1279: nullifySecKey(obj, "f19", obj.f19, Double.class);
1280: nullifySecKey(obj, "f20", obj.f20, CompositeKey.class);
1281:
1282: nullifySecMultiKey(obj, "f21", obj.f21, Integer.class);
1283: nullifySecMultiKey(obj, "f22", obj.f22, Integer.class);
1284: nullifySecMultiKey(obj, "f23", obj.f23, Integer.class);
1285: nullifySecMultiKey(obj, "f24", obj.f24, CompositeKey.class);
1286: nullifySecMultiKey(obj, "f25", obj.f25, CompositeKey.class);
1287:
1288: nullifySecKey(obj, "f31", obj.f31, Date.class);
1289: nullifySecKey(obj, "f32", obj.f32, Boolean.class);
1290: nullifySecKey(obj, "f33", obj.f33, Character.class);
1291: nullifySecKey(obj, "f34", obj.f34, Byte.class);
1292: nullifySecKey(obj, "f35", obj.f35, Short.class);
1293: nullifySecKey(obj, "f36", obj.f36, Integer.class);
1294: nullifySecKey(obj, "f37", obj.f37, Long.class);
1295: nullifySecKey(obj, "f38", obj.f38, Float.class);
1296: nullifySecKey(obj, "f39", obj.f39, Double.class);
1297: nullifySecKey(obj, "f40", obj.f40, CompositeKey.class);
1298:
1299: close();
1300: }
1301:
1302: static Set toSet(int[] a) {
1303: Set set = new HashSet();
1304: for (int i : a) {
1305: set.add(i);
1306: }
1307: return set;
1308: }
1309:
1310: static Set toSet(Object[] a) {
1311: return new HashSet(Arrays.asList(a));
1312: }
1313:
1314: static Set toSet(Set s) {
1315: return s;
1316: }
1317:
1318: @Entity
1319: static class SecKeys implements MyEntity {
1320:
1321: @PrimaryKey
1322: long id;
1323:
1324: @SecondaryKey(relate=MANY_TO_ONE)
1325: private boolean f0 = false;
1326: private boolean g0 = false;
1327:
1328: @SecondaryKey(relate=MANY_TO_ONE)
1329: private char f1 = '1';
1330: private char g1 = '1';
1331:
1332: @SecondaryKey(relate=MANY_TO_ONE)
1333: private byte f2 = 2;
1334: private byte g2 = 2;
1335:
1336: @SecondaryKey(relate=MANY_TO_ONE)
1337: private short f3 = 3;
1338: private short g3 = 3;
1339:
1340: @SecondaryKey(relate=MANY_TO_ONE)
1341: private int f4 = 4;
1342: private int g4 = 4;
1343:
1344: @SecondaryKey(relate=MANY_TO_ONE)
1345: private long f5 = 5;
1346: private long g5 = 5;
1347:
1348: @SecondaryKey(relate=MANY_TO_ONE)
1349: private float f6 = 6.6f;
1350: private float g6 = 6.6f;
1351:
1352: @SecondaryKey(relate=MANY_TO_ONE)
1353: private double f7 = 7.7;
1354: private double g7 = 7.7;
1355:
1356: @SecondaryKey(relate=MANY_TO_ONE)
1357: private String f8 = "8";
1358: private String g8 = "8";
1359:
1360: @SecondaryKey(relate=MANY_TO_ONE)
1361: private BigInteger f9;
1362: private BigInteger g9;
1363:
1364: //@SecondaryKey(relate=MANY_TO_ONE)
1365: //private BigDecimal f10;
1366: //private BigDecimal g10;
1367:
1368: @SecondaryKey(relate=MANY_TO_ONE)
1369: private Date f11 = new Date(11);
1370: private Date g11 = new Date(11);
1371:
1372: @SecondaryKey(relate=MANY_TO_ONE)
1373: private Boolean f12 = true;
1374: private Boolean g12 = true;
1375:
1376: @SecondaryKey(relate=MANY_TO_ONE)
1377: private Character f13 = '3';
1378: private Character g13 = '3';
1379:
1380: @SecondaryKey(relate=MANY_TO_ONE)
1381: private Byte f14 = 14;
1382: private Byte g14 = 14;
1383:
1384: @SecondaryKey(relate=MANY_TO_ONE)
1385: private Short f15 = 15;
1386: private Short g15 = 15;
1387:
1388: @SecondaryKey(relate=MANY_TO_ONE)
1389: private Integer f16 = 16;
1390: private Integer g16 = 16;
1391:
1392: @SecondaryKey(relate=MANY_TO_ONE)
1393: private Long f17 = 17L;
1394: private Long g17 = 17L;
1395:
1396: @SecondaryKey(relate=MANY_TO_ONE)
1397: private Float f18 = 18.18f;
1398: private Float g18 = 18.18f;
1399:
1400: @SecondaryKey(relate=MANY_TO_ONE)
1401: private Double f19 = 19.19;
1402: private Double g19 = 19.19;
1403:
1404: @SecondaryKey(relate=MANY_TO_ONE)
1405: private CompositeKey f20 = new CompositeKey(20, 20L, "20",
1406: BigInteger.valueOf(20));
1407: private CompositeKey g20 = new CompositeKey(20, 20L, "20",
1408: BigInteger.valueOf(20));
1409:
1410: private static int[] arrayOfInt = { 100, 101, 102 };
1411:
1412: private static Integer[] arrayOfInteger = { 100, 101, 102 };
1413:
1414: private static CompositeKey[] arrayOfCompositeKey = {
1415: new CompositeKey(100, 100L, "100", BigInteger
1416: .valueOf(100)),
1417: new CompositeKey(101, 101L, "101", BigInteger
1418: .valueOf(101)),
1419: new CompositeKey(102, 102L, "102", BigInteger
1420: .valueOf(102)), };
1421:
1422: @SecondaryKey(relate=ONE_TO_MANY)
1423: private int[] f21 = arrayOfInt;
1424: private int[] g21 = f21;
1425:
1426: @SecondaryKey(relate=ONE_TO_MANY)
1427: private Integer[] f22 = arrayOfInteger;
1428: private Integer[] g22 = f22;
1429:
1430: @SecondaryKey(relate=ONE_TO_MANY)
1431: private Set<Integer> f23 = toSet(arrayOfInteger);
1432: private Set<Integer> g23 = f23;
1433:
1434: @SecondaryKey(relate=ONE_TO_MANY)
1435: private CompositeKey[] f24 = arrayOfCompositeKey;
1436: private CompositeKey[] g24 = f24;
1437:
1438: @SecondaryKey(relate=ONE_TO_MANY)
1439: private Set<CompositeKey> f25 = toSet(arrayOfCompositeKey);
1440: private Set<CompositeKey> g25 = f25;
1441:
1442: /* Repeated key values to test shared references. */
1443:
1444: @SecondaryKey(relate=MANY_TO_ONE)
1445: private Date f31 = f11;
1446:
1447: @SecondaryKey(relate=MANY_TO_ONE)
1448: private Boolean f32 = f12;
1449:
1450: @SecondaryKey(relate=MANY_TO_ONE)
1451: private Character f33 = f13;
1452:
1453: @SecondaryKey(relate=MANY_TO_ONE)
1454: private Byte f34 = f14;
1455:
1456: @SecondaryKey(relate=MANY_TO_ONE)
1457: private Short f35 = f15;
1458:
1459: @SecondaryKey(relate=MANY_TO_ONE)
1460: private Integer f36 = f16;
1461:
1462: @SecondaryKey(relate=MANY_TO_ONE)
1463: private Long f37 = f17;
1464:
1465: @SecondaryKey(relate=MANY_TO_ONE)
1466: private Float f38 = f18;
1467:
1468: @SecondaryKey(relate=MANY_TO_ONE)
1469: private Double f39 = f19;
1470:
1471: @SecondaryKey(relate=MANY_TO_ONE)
1472: private CompositeKey f40 = f20;
1473:
1474: public Object getPriKeyObject() {
1475: return id;
1476: }
1477:
1478: public void validate(Object other) {
1479: SecKeys o = (SecKeys) other;
1480: TestCase.assertEquals(id, o.id);
1481:
1482: TestCase.assertEquals(f0, o.f0);
1483: TestCase.assertEquals(f1, o.f1);
1484: TestCase.assertEquals(f2, o.f2);
1485: TestCase.assertEquals(f3, o.f3);
1486: TestCase.assertEquals(f4, o.f4);
1487: TestCase.assertEquals(f5, o.f5);
1488: TestCase.assertEquals(f6, o.f6);
1489: TestCase.assertEquals(f7, o.f7);
1490: TestCase.assertEquals(f8, o.f8);
1491: TestCase.assertEquals(f9, o.f9);
1492: //TestCase.assertEquals(f10, o.f10);
1493: TestCase.assertEquals(f11, o.f11);
1494: TestCase.assertEquals(f12, o.f12);
1495: TestCase.assertEquals(f13, o.f13);
1496: TestCase.assertEquals(f14, o.f14);
1497: TestCase.assertEquals(f15, o.f15);
1498: TestCase.assertEquals(f16, o.f16);
1499: TestCase.assertEquals(f17, o.f17);
1500: TestCase.assertEquals(f18, o.f18);
1501: TestCase.assertEquals(f19, o.f19);
1502: TestCase.assertEquals(f20, o.f20);
1503: TestCase.assertTrue(Arrays.equals(f21, o.f21));
1504: TestCase.assertTrue(Arrays.equals(f22, o.f22));
1505: TestCase.assertEquals(f23, o.f23);
1506: TestCase.assertTrue(Arrays.equals(f24, o.f24));
1507: TestCase.assertEquals(f25, o.f25);
1508:
1509: TestCase.assertEquals(g0, o.g0);
1510: TestCase.assertEquals(g1, o.g1);
1511: TestCase.assertEquals(g2, o.g2);
1512: TestCase.assertEquals(g3, o.g3);
1513: TestCase.assertEquals(g4, o.g4);
1514: TestCase.assertEquals(g5, o.g5);
1515: TestCase.assertEquals(g6, o.g6);
1516: TestCase.assertEquals(g7, o.g7);
1517: TestCase.assertEquals(g8, o.g8);
1518: TestCase.assertEquals(g9, o.g9);
1519: //TestCase.assertEquals(g10, o.g10);
1520: TestCase.assertEquals(g11, o.g11);
1521: TestCase.assertEquals(g12, o.g12);
1522: TestCase.assertEquals(g13, o.g13);
1523: TestCase.assertEquals(g14, o.g14);
1524: TestCase.assertEquals(g15, o.g15);
1525: TestCase.assertEquals(g16, o.g16);
1526: TestCase.assertEquals(g17, o.g17);
1527: TestCase.assertEquals(g18, o.g18);
1528: TestCase.assertEquals(g19, o.g19);
1529: TestCase.assertEquals(g20, o.g20);
1530: TestCase.assertTrue(Arrays.equals(g21, o.g21));
1531: TestCase.assertTrue(Arrays.equals(g22, o.g22));
1532: TestCase.assertEquals(g23, o.g23);
1533: TestCase.assertTrue(Arrays.equals(g24, o.g24));
1534: TestCase.assertEquals(g25, o.g25);
1535:
1536: TestCase.assertEquals(f31, o.f31);
1537: TestCase.assertEquals(f32, o.f32);
1538: TestCase.assertEquals(f33, o.f33);
1539: TestCase.assertEquals(f34, o.f34);
1540: TestCase.assertEquals(f35, o.f35);
1541: TestCase.assertEquals(f36, o.f36);
1542: TestCase.assertEquals(f37, o.f37);
1543: TestCase.assertEquals(f38, o.f38);
1544: TestCase.assertEquals(f39, o.f39);
1545: TestCase.assertEquals(f40, o.f40);
1546:
1547: checkSameIfNonNull(o.f31, o.f11);
1548: checkSameIfNonNull(o.f32, o.f12);
1549: checkSameIfNonNull(o.f33, o.f13);
1550: checkSameIfNonNull(o.f34, o.f14);
1551: checkSameIfNonNull(o.f35, o.f15);
1552: checkSameIfNonNull(o.f36, o.f16);
1553: checkSameIfNonNull(o.f37, o.f17);
1554: checkSameIfNonNull(o.f38, o.f18);
1555: checkSameIfNonNull(o.f39, o.f19);
1556: checkSameIfNonNull(o.f40, o.f20);
1557: }
1558: }
1559:
1560: public void testSecKeyRefToPriKey() throws DatabaseException {
1561:
1562: open();
1563:
1564: SecKeyRefToPriKey obj = new SecKeyRefToPriKey();
1565: checkEntity(SecKeyRefToPriKey.class, obj);
1566:
1567: checkMetadata(SecKeyRefToPriKey.class.getName(),
1568: new String[][] { { "priKey", "java.lang.String" },
1569: { "secKey1", "java.lang.String" },
1570: { "secKey2", String[].class.getName() },
1571: { "secKey3", Set.class.getName() }, },
1572: 0 /*priKeyIndex*/, null);
1573:
1574: checkSecKey(obj, "secKey1", obj.secKey1, String.class);
1575: checkSecMultiKey(obj, "secKey2", toSet(obj.secKey2),
1576: String.class);
1577: checkSecMultiKey(obj, "secKey3", toSet(obj.secKey3),
1578: String.class);
1579:
1580: close();
1581: }
1582:
1583: @Entity
1584: static class SecKeyRefToPriKey implements MyEntity {
1585:
1586: @PrimaryKey
1587: private String priKey;
1588:
1589: @SecondaryKey(relate=ONE_TO_ONE)
1590: private String secKey1;
1591:
1592: @SecondaryKey(relate=ONE_TO_MANY)
1593: private String[] secKey2;
1594:
1595: @SecondaryKey(relate=ONE_TO_MANY)
1596: private Set<String> secKey3 = new HashSet<String>();
1597:
1598: private SecKeyRefToPriKey() {
1599: priKey = "sharedValue";
1600: secKey1 = priKey;
1601: secKey2 = new String[] { priKey };
1602: secKey3.add(priKey);
1603: }
1604:
1605: public Object getPriKeyObject() {
1606: return priKey;
1607: }
1608:
1609: public void validate(Object other) {
1610: SecKeyRefToPriKey o = (SecKeyRefToPriKey) other;
1611: TestCase.assertEquals(priKey, o.priKey);
1612: TestCase.assertNotNull(o.secKey1);
1613: TestCase.assertEquals(1, o.secKey2.length);
1614: TestCase.assertEquals(1, o.secKey3.size());
1615: TestCase.assertSame(o.secKey1, o.priKey);
1616: TestCase.assertSame(o.secKey2[0], o.priKey);
1617: TestCase.assertSame(o.secKey3.iterator().next(), o.priKey);
1618: }
1619: }
1620:
1621: public void testSecKeyInSuperclass() throws DatabaseException {
1622:
1623: open();
1624:
1625: SecKeyInSuperclassEntity obj = new SecKeyInSuperclassEntity();
1626: checkEntity(SecKeyInSuperclassEntity.class, obj);
1627:
1628: checkMetadata(SecKeyInSuperclass.class.getName(),
1629: new String[][] { { "priKey", "java.lang.String" },
1630: { "secKey1", String.class.getName() }, },
1631: 0/*priKeyIndex*/, null);
1632:
1633: checkMetadata(SecKeyInSuperclassEntity.class.getName(),
1634: new String[][] { { "secKey2", "java.lang.String" }, },
1635: -1 /*priKeyIndex*/, SecKeyInSuperclass.class.getName());
1636:
1637: checkSecKey(obj, SecKeyInSuperclassEntity.class, "secKey1",
1638: obj.secKey1, String.class);
1639: checkSecKey(obj, SecKeyInSuperclassEntity.class, "secKey2",
1640: obj.secKey2, String.class);
1641:
1642: close();
1643: }
1644:
1645: @Persistent
1646: static class SecKeyInSuperclass implements MyEntity {
1647:
1648: @PrimaryKey
1649: String priKey = "1";
1650:
1651: @SecondaryKey(relate=ONE_TO_ONE)
1652: String secKey1 = "1";
1653:
1654: public Object getPriKeyObject() {
1655: return priKey;
1656: }
1657:
1658: public void validate(Object other) {
1659: SecKeyInSuperclass o = (SecKeyInSuperclass) other;
1660: TestCase.assertEquals(secKey1, o.secKey1);
1661: }
1662: }
1663:
1664: @Entity
1665: static class SecKeyInSuperclassEntity extends SecKeyInSuperclass {
1666:
1667: @SecondaryKey(relate=ONE_TO_ONE)
1668: String secKey2 = "2";
1669:
1670: public void validate(Object other) {
1671: super .validate(other);
1672: SecKeyInSuperclassEntity o = (SecKeyInSuperclassEntity) other;
1673: TestCase.assertEquals(priKey, o.priKey);
1674: TestCase.assertEquals(secKey2, o.secKey2);
1675: }
1676: }
1677:
1678: public void testSecKeyInSubclass() throws DatabaseException {
1679:
1680: open();
1681:
1682: SecKeyInSubclass obj = new SecKeyInSubclass();
1683: checkEntity(SecKeyInSubclassEntity.class, obj);
1684:
1685: checkMetadata(SecKeyInSubclassEntity.class.getName(),
1686: new String[][] { { "priKey", "java.lang.String" },
1687: { "secKey1", "java.lang.String" }, },
1688: 0 /*priKeyIndex*/, null);
1689:
1690: checkMetadata(
1691: SecKeyInSubclass.class.getName(),
1692: new String[][] { { "secKey2", String.class.getName() }, },
1693: -1 /*priKeyIndex*/, SecKeyInSubclassEntity.class
1694: .getName());
1695:
1696: checkSecKey(obj, SecKeyInSubclassEntity.class, "secKey1",
1697: obj.secKey1, String.class);
1698: checkSecKey(obj, SecKeyInSubclassEntity.class, "secKey2",
1699: obj.secKey2, String.class);
1700:
1701: close();
1702: }
1703:
1704: @Entity
1705: static class SecKeyInSubclassEntity implements MyEntity {
1706:
1707: @PrimaryKey
1708: String priKey = "1";
1709:
1710: @SecondaryKey(relate=ONE_TO_ONE)
1711: String secKey1;
1712:
1713: public Object getPriKeyObject() {
1714: return priKey;
1715: }
1716:
1717: public void validate(Object other) {
1718: SecKeyInSubclassEntity o = (SecKeyInSubclassEntity) other;
1719: TestCase.assertEquals(priKey, o.priKey);
1720: TestCase.assertEquals(secKey1, o.secKey1);
1721: }
1722: }
1723:
1724: @Persistent
1725: static class SecKeyInSubclass extends SecKeyInSubclassEntity {
1726:
1727: @SecondaryKey(relate=ONE_TO_ONE)
1728: String secKey2 = "2";
1729:
1730: public void validate(Object other) {
1731: super .validate(other);
1732: SecKeyInSubclass o = (SecKeyInSubclass) other;
1733: TestCase.assertEquals(secKey2, o.secKey2);
1734: }
1735: }
1736:
1737: private static void checkSameIfNonNull(Object o1, Object o2) {
1738: if (o1 != null && o2 != null) {
1739: assertSame(o1, o2);
1740: }
1741: }
1742:
1743: private void checkEntity(Class entityCls, MyEntity entity)
1744: throws DatabaseException {
1745:
1746: Object priKey = entity.getPriKeyObject();
1747: Class keyCls = priKey.getClass();
1748: DatabaseEntry keyEntry2 = new DatabaseEntry();
1749: DatabaseEntry dataEntry2 = new DatabaseEntry();
1750:
1751: /* Write object, read it back and validate (compare) it. */
1752: PersistEntityBinding entityBinding = new PersistEntityBinding(
1753: catalog, entityCls.getName(), false);
1754: entityBinding.objectToData(entity, dataEntry);
1755: entityBinding.objectToKey(entity, keyEntry);
1756: Object entity2 = entityBinding.entryToObject(keyEntry,
1757: dataEntry);
1758: entity.validate(entity2);
1759:
1760: /* Read back the primary key and validate it. */
1761: PersistKeyBinding keyBinding = new PersistKeyBinding(catalog,
1762: keyCls.getName(), false);
1763: Object priKey2 = keyBinding.entryToObject(keyEntry);
1764: assertEquals(priKey, priKey2);
1765: keyBinding.objectToEntry(priKey2, keyEntry2);
1766: assertEquals(keyEntry, keyEntry2);
1767:
1768: /* Check raw entity binding. */
1769: PersistEntityBinding rawEntityBinding = new PersistEntityBinding(
1770: catalog, entityCls.getName(), true);
1771: RawObject rawEntity = (RawObject) rawEntityBinding
1772: .entryToObject(keyEntry, dataEntry);
1773: rawEntityBinding.objectToKey(rawEntity, keyEntry2);
1774: rawEntityBinding.objectToData(rawEntity, dataEntry2);
1775: entity2 = entityBinding.entryToObject(keyEntry2, dataEntry2);
1776: entity.validate(entity2);
1777: RawObject rawEntity2 = (RawObject) rawEntityBinding
1778: .entryToObject(keyEntry2, dataEntry2);
1779: assertEquals(rawEntity, rawEntity2);
1780: assertEquals(dataEntry, dataEntry2);
1781: assertEquals(keyEntry, keyEntry2);
1782:
1783: /* Check that raw entity can be converted to a regular entity. */
1784: entity2 = catalog.convertRawObject(rawEntity, null);
1785: entity.validate(entity2);
1786:
1787: /* Check raw key binding. */
1788: PersistKeyBinding rawKeyBinding = new PersistKeyBinding(
1789: catalog, keyCls.getName(), true);
1790: Object rawKey = rawKeyBinding.entryToObject(keyEntry);
1791: rawKeyBinding.objectToEntry(rawKey, keyEntry2);
1792: priKey2 = keyBinding.entryToObject(keyEntry2);
1793: assertEquals(priKey, priKey2);
1794: assertEquals(keyEntry, keyEntry2);
1795: }
1796:
1797: private void checkSecKey(MyEntity entity, String keyName,
1798: Object keyValue, Class keyCls) throws DatabaseException {
1799:
1800: checkSecKey(entity, entity.getClass(), keyName, keyValue,
1801: keyCls);
1802: }
1803:
1804: private void checkSecKey(MyEntity entity, Class entityCls,
1805: String keyName, Object keyValue, Class keyCls)
1806: throws DatabaseException {
1807:
1808: /* Get entity metadata. */
1809: EntityMetadata entityMeta = model.getEntityMetadata(entityCls
1810: .getName());
1811: assertNotNull(entityMeta);
1812:
1813: /* Get secondary key metadata. */
1814: SecondaryKeyMetadata secKeyMeta = entityMeta.getSecondaryKeys()
1815: .get(keyName);
1816: assertNotNull(secKeyMeta);
1817:
1818: /* Create key creator/nullifier. */
1819: SecondaryKeyCreator keyCreator = new PersistKeyCreator(catalog,
1820: entityMeta, keyCls.getName(), secKeyMeta);
1821:
1822: /* Convert entity to bytes. */
1823: PersistEntityBinding entityBinding = new PersistEntityBinding(
1824: catalog, entityCls.getName(), false);
1825: entityBinding.objectToData(entity, dataEntry);
1826: entityBinding.objectToKey(entity, keyEntry);
1827:
1828: /* Extract secondary key bytes from entity bytes. */
1829: DatabaseEntry secKeyEntry = new DatabaseEntry();
1830: boolean isKeyPresent = keyCreator.createSecondaryKey(null,
1831: keyEntry, dataEntry, secKeyEntry);
1832: assertEquals(keyValue != null, isKeyPresent);
1833:
1834: /* Convert secondary key bytes back to an object. */
1835: PersistKeyBinding keyBinding = new PersistKeyBinding(catalog,
1836: keyCls.getName(), false);
1837: if (isKeyPresent) {
1838: Object keyValue2 = keyBinding.entryToObject(secKeyEntry);
1839: assertEquals(keyValue, keyValue2);
1840: DatabaseEntry secKeyEntry2 = new DatabaseEntry();
1841: keyBinding.objectToEntry(keyValue2, secKeyEntry2);
1842: assertEquals(secKeyEntry, secKeyEntry2);
1843: }
1844: }
1845:
1846: private void checkSecMultiKey(MyEntity entity, String keyName,
1847: Set keyValues, Class keyCls) throws DatabaseException {
1848:
1849: /* Get entity metadata. */
1850: Class entityCls = entity.getClass();
1851: EntityMetadata entityMeta = model.getEntityMetadata(entityCls
1852: .getName());
1853: assertNotNull(entityMeta);
1854:
1855: /* Get secondary key metadata. */
1856: SecondaryKeyMetadata secKeyMeta = entityMeta.getSecondaryKeys()
1857: .get(keyName);
1858: assertNotNull(secKeyMeta);
1859:
1860: /* Create key creator/nullifier. */
1861: SecondaryMultiKeyCreator keyCreator = new PersistKeyCreator(
1862: catalog, entityMeta, keyCls.getName(), secKeyMeta);
1863:
1864: /* Convert entity to bytes. */
1865: PersistEntityBinding entityBinding = new PersistEntityBinding(
1866: catalog, entityCls.getName(), false);
1867: entityBinding.objectToData(entity, dataEntry);
1868: entityBinding.objectToKey(entity, keyEntry);
1869:
1870: /* Extract secondary key bytes from entity bytes. */
1871: Set<DatabaseEntry> results = new HashSet<DatabaseEntry>();
1872: keyCreator.createSecondaryKeys(null, keyEntry, dataEntry,
1873: results);
1874: assertEquals(keyValues.size(), results.size());
1875:
1876: /* Convert secondary key bytes back to objects. */
1877: PersistKeyBinding keyBinding = new PersistKeyBinding(catalog,
1878: keyCls.getName(), false);
1879: Set keyValues2 = new HashSet();
1880: for (DatabaseEntry secKeyEntry : results) {
1881: Object keyValue2 = keyBinding.entryToObject(secKeyEntry);
1882: keyValues2.add(keyValue2);
1883: }
1884: assertEquals(keyValues, keyValues2);
1885: }
1886:
1887: private void nullifySecKey(MyEntity entity, String keyName,
1888: Object keyValue, Class keyCls) throws DatabaseException {
1889:
1890: /* Get entity metadata. */
1891: Class entityCls = entity.getClass();
1892: EntityMetadata entityMeta = model.getEntityMetadata(entityCls
1893: .getName());
1894: assertNotNull(entityMeta);
1895:
1896: /* Get secondary key metadata. */
1897: SecondaryKeyMetadata secKeyMeta = entityMeta.getSecondaryKeys()
1898: .get(keyName);
1899: assertNotNull(secKeyMeta);
1900:
1901: /* Create key creator/nullifier. */
1902: ForeignMultiKeyNullifier keyNullifier = new PersistKeyCreator(
1903: catalog, entityMeta, keyCls.getName(), secKeyMeta);
1904:
1905: /* Convert entity to bytes. */
1906: PersistEntityBinding entityBinding = new PersistEntityBinding(
1907: catalog, entityCls.getName(), false);
1908: entityBinding.objectToData(entity, dataEntry);
1909: entityBinding.objectToKey(entity, keyEntry);
1910:
1911: /* Convert secondary key to bytes. */
1912: PersistKeyBinding keyBinding = new PersistKeyBinding(catalog,
1913: keyCls.getName(), false);
1914: DatabaseEntry secKeyEntry = new DatabaseEntry();
1915: if (keyValue != null) {
1916: keyBinding.objectToEntry(keyValue, secKeyEntry);
1917: }
1918:
1919: /* Nullify secondary key bytes within entity bytes. */
1920: boolean isKeyPresent = keyNullifier.nullifyForeignKey(null,
1921: keyEntry, dataEntry, secKeyEntry);
1922: assertEquals(keyValue != null, isKeyPresent);
1923:
1924: /* Convert modified entity bytes back to an entity. */
1925: Object entity2 = entityBinding.entryToObject(keyEntry,
1926: dataEntry);
1927: setFieldToNull(entity, keyName);
1928: entity.validate(entity2);
1929:
1930: /* Do a full check after nullifying it. */
1931: checkSecKey(entity, keyName, null, keyCls);
1932: }
1933:
1934: private void nullifySecMultiKey(MyEntity entity, String keyName,
1935: Object keyValue, Class keyCls) throws DatabaseException {
1936:
1937: /* Get entity metadata. */
1938: Class entityCls = entity.getClass();
1939: EntityMetadata entityMeta = model.getEntityMetadata(entityCls
1940: .getName());
1941: assertNotNull(entityMeta);
1942:
1943: /* Get secondary key metadata. */
1944: SecondaryKeyMetadata secKeyMeta = entityMeta.getSecondaryKeys()
1945: .get(keyName);
1946: assertNotNull(secKeyMeta);
1947:
1948: /* Create key creator/nullifier. */
1949: ForeignMultiKeyNullifier keyNullifier = new PersistKeyCreator(
1950: catalog, entityMeta, keyCls.getName(), secKeyMeta);
1951:
1952: /* Convert entity to bytes. */
1953: PersistEntityBinding entityBinding = new PersistEntityBinding(
1954: catalog, entityCls.getName(), false);
1955: entityBinding.objectToData(entity, dataEntry);
1956: entityBinding.objectToKey(entity, keyEntry);
1957:
1958: /* Get secondary key binding. */
1959: PersistKeyBinding keyBinding = new PersistKeyBinding(catalog,
1960: keyCls.getName(), false);
1961: DatabaseEntry secKeyEntry = new DatabaseEntry();
1962:
1963: /* Nullify one key value at a time until all of them are gone. */
1964: while (true) {
1965: Object fieldObj = getField(entity, keyName);
1966: fieldObj = nullifyFirstElement(fieldObj, keyBinding,
1967: secKeyEntry);
1968: if (fieldObj == null) {
1969: break;
1970: }
1971: setField(entity, keyName, fieldObj);
1972:
1973: /* Nullify secondary key bytes within entity bytes. */
1974: boolean isKeyPresent = keyNullifier.nullifyForeignKey(null,
1975: keyEntry, dataEntry, secKeyEntry);
1976: assertEquals(keyValue != null, isKeyPresent);
1977:
1978: /* Convert modified entity bytes back to an entity. */
1979: Object entity2 = entityBinding.entryToObject(keyEntry,
1980: dataEntry);
1981: entity.validate(entity2);
1982:
1983: /* Do a full check after nullifying it. */
1984: Set keyValues;
1985: if (fieldObj instanceof Set) {
1986: keyValues = (Set) fieldObj;
1987: } else if (fieldObj instanceof Object[]) {
1988: keyValues = toSet((Object[]) fieldObj);
1989: } else if (fieldObj instanceof int[]) {
1990: keyValues = toSet((int[]) fieldObj);
1991: } else {
1992: throw new IllegalStateException(fieldObj.getClass()
1993: .getName());
1994: }
1995: checkSecMultiKey(entity, keyName, keyValues, keyCls);
1996: }
1997: }
1998:
1999: /**
2000: * Nullifies the first element of an array or collection object by removing
2001: * it from the array or collection. Returns the resulting array or
2002: * collection. Also outputs the removed element to the keyEntry using the
2003: * keyBinding.
2004: */
2005: private Object nullifyFirstElement(Object obj,
2006: EntryBinding keyBinding, DatabaseEntry keyEntry) {
2007: if (obj instanceof Collection) {
2008: Iterator i = ((Collection) obj).iterator();
2009: if (i.hasNext()) {
2010: Object elem = i.next();
2011: i.remove();
2012: keyBinding.objectToEntry(elem, keyEntry);
2013: return obj;
2014: } else {
2015: return null;
2016: }
2017: } else if (obj instanceof Object[]) {
2018: Object[] a1 = (Object[]) obj;
2019: if (a1.length > 0) {
2020: Object[] a2 = (Object[]) Array.newInstance(obj
2021: .getClass().getComponentType(), a1.length - 1);
2022: System.arraycopy(a1, 1, a2, 0, a2.length);
2023: keyBinding.objectToEntry(a1[0], keyEntry);
2024: return a2;
2025: } else {
2026: return null;
2027: }
2028: } else if (obj instanceof int[]) {
2029: int[] a1 = (int[]) obj;
2030: if (a1.length > 0) {
2031: int[] a2 = new int[a1.length - 1];
2032: System.arraycopy(a1, 1, a2, 0, a2.length);
2033: keyBinding.objectToEntry(a1[0], keyEntry);
2034: return a2;
2035: } else {
2036: return null;
2037: }
2038: } else {
2039: throw new IllegalStateException(obj.getClass().getName());
2040: }
2041: }
2042:
2043: private void checkMetadata(String clsName,
2044: String[][] nameTypePairs, int priKeyIndex,
2045: String super ClsName) throws DatabaseException {
2046:
2047: /* Check metadata/types against the live model. */
2048: checkMetadata(catalog, model, clsName, nameTypePairs,
2049: priKeyIndex, super ClsName);
2050:
2051: /*
2052: * Open a catalog that uses the stored model.
2053: */
2054: PersistCatalog storedCatalog = new PersistCatalog(null, env,
2055: STORE_PREFIX, "catalog", null, null, null,
2056: false /*useCurrentModel*/, null /*Store*/);
2057: EntityModel storedModel = storedCatalog.getResolvedModel();
2058:
2059: /* Check metadata/types against the stored catalog/model. */
2060: checkMetadata(storedCatalog, storedModel, clsName,
2061: nameTypePairs, priKeyIndex, super ClsName);
2062:
2063: storedCatalog.close();
2064: }
2065:
2066: private void checkMetadata(PersistCatalog checkCatalog,
2067: EntityModel checkModel, String clsName,
2068: String[][] nameTypePairs, int priKeyIndex,
2069: String super ClsName) throws DatabaseException {
2070:
2071: ClassMetadata classMeta = checkModel.getClassMetadata(clsName);
2072: assertNotNull(clsName, classMeta);
2073:
2074: PrimaryKeyMetadata priKeyMeta = classMeta.getPrimaryKey();
2075: if (priKeyIndex >= 0) {
2076: assertNotNull(priKeyMeta);
2077: String fieldName = nameTypePairs[priKeyIndex][0];
2078: String fieldType = nameTypePairs[priKeyIndex][1];
2079: assertEquals(priKeyMeta.getName(), fieldName);
2080: assertEquals(priKeyMeta.getClassName(), fieldType);
2081: assertEquals(priKeyMeta.getDeclaringClassName(), clsName);
2082: assertNull(priKeyMeta.getSequenceName());
2083: } else {
2084: assertNull(priKeyMeta);
2085: }
2086:
2087: RawType type = checkCatalog.getFormat(clsName);
2088: assertNotNull(type);
2089: assertEquals(clsName, type.getClassName());
2090: assertEquals(0, type.getVersion());
2091: assertTrue(!type.isSimple());
2092: assertTrue(!type.isPrimitive());
2093: assertTrue(!type.isEnum());
2094: assertNull(type.getEnumConstants());
2095: assertTrue(!type.isArray());
2096: assertEquals(0, type.getDimensions());
2097: assertNull(type.getComponentType());
2098: RawType super Type = type.getSuperType();
2099: if (super ClsName != null) {
2100: assertNotNull(super Type);
2101: assertEquals(super ClsName, super Type.getClassName());
2102: } else {
2103: assertNull(super Type);
2104: }
2105:
2106: Map<String, RawField> fields = type.getFields();
2107: assertNotNull(fields);
2108:
2109: int nFields = nameTypePairs.length;
2110: assertEquals(nFields, fields.size());
2111:
2112: for (String[] pair : nameTypePairs) {
2113: String fieldName = pair[0];
2114: String fieldType = pair[1];
2115: Class fieldCls;
2116: try {
2117: fieldCls = SimpleCatalog.classForName(fieldType);
2118: } catch (ClassNotFoundException e) {
2119: fail(e.toString());
2120: return; /* For compiler */
2121: }
2122: RawField field = fields.get(fieldName);
2123: assertNotNull(field);
2124: assertEquals(fieldName, field.getName());
2125: type = field.getType();
2126: assertNotNull(type);
2127: int dim = getArrayDimensions(fieldType);
2128: while (dim > 0) {
2129: assertEquals(dim, type.getDimensions());
2130: assertEquals(dim, getArrayDimensions(fieldType));
2131: assertEquals(true, type.isArray());
2132: assertEquals(fieldType, type.getClassName());
2133: assertEquals(0, type.getVersion());
2134: assertTrue(!type.isSimple());
2135: assertTrue(!type.isPrimitive());
2136: assertTrue(!type.isEnum());
2137: assertNull(type.getEnumConstants());
2138: fieldType = getArrayComponent(fieldType, dim);
2139: type = type.getComponentType();
2140: assertNotNull(fieldType, type);
2141: dim -= 1;
2142: }
2143: assertEquals(fieldType, type.getClassName());
2144: List<String> enums = getEnumConstants(fieldType);
2145: assertEquals(isSimpleType(fieldType), type.isSimple());
2146: assertEquals(isPrimitiveType(fieldType), type.isPrimitive());
2147: assertNull(type.getComponentType());
2148: assertTrue(!type.isArray());
2149: assertEquals(0, type.getDimensions());
2150: if (enums != null) {
2151: assertTrue(type.isEnum());
2152: assertEquals(enums, type.getEnumConstants());
2153: assertNull(type.getSuperType());
2154: } else {
2155: assertTrue(!type.isEnum());
2156: assertNull(type.getEnumConstants());
2157: }
2158: }
2159: }
2160:
2161: private List<String> getEnumConstants(String clsName) {
2162: if (isPrimitiveType(clsName)) {
2163: return null;
2164: }
2165: Class cls;
2166: try {
2167: cls = Class.forName(clsName);
2168: } catch (ClassNotFoundException e) {
2169: fail(e.toString());
2170: return null; /* Never happens. */
2171: }
2172: if (!cls.isEnum()) {
2173: return null;
2174: }
2175: List<String> enums = new ArrayList<String>();
2176: Object[] vals = cls.getEnumConstants();
2177: for (Object val : vals) {
2178: enums.add(val.toString());
2179: }
2180: return enums;
2181: }
2182:
2183: private String getArrayComponent(String clsName, int dim) {
2184: clsName = clsName.substring(1);
2185: if (dim > 1) {
2186: return clsName;
2187: }
2188: if (clsName.charAt(0) == 'L'
2189: && clsName.charAt(clsName.length() - 1) == ';') {
2190: return clsName.substring(1, clsName.length() - 1);
2191: }
2192: if (clsName.length() != 1) {
2193: fail();
2194: }
2195: switch (clsName.charAt(0)) {
2196: case 'Z':
2197: return "boolean";
2198: case 'B':
2199: return "byte";
2200: case 'C':
2201: return "char";
2202: case 'D':
2203: return "double";
2204: case 'F':
2205: return "float";
2206: case 'I':
2207: return "int";
2208: case 'J':
2209: return "long";
2210: case 'S':
2211: return "short";
2212: default:
2213: fail();
2214: }
2215: return null; /* Should never happen. */
2216: }
2217:
2218: private static int getArrayDimensions(String clsName) {
2219: int i = 0;
2220: while (clsName.charAt(i) == '[') {
2221: i += 1;
2222: }
2223: return i;
2224: }
2225:
2226: private static boolean isSimpleType(String clsName) {
2227: return isPrimitiveType(clsName)
2228: || clsName.equals("java.lang.Boolean")
2229: || clsName.equals("java.lang.Character")
2230: || clsName.equals("java.lang.Byte")
2231: || clsName.equals("java.lang.Short")
2232: || clsName.equals("java.lang.Integer")
2233: || clsName.equals("java.lang.Long")
2234: || clsName.equals("java.lang.Float")
2235: || clsName.equals("java.lang.Double")
2236: || clsName.equals("java.lang.String")
2237: || clsName.equals("java.math.BigInteger") ||
2238: //clsName.equals("java.math.BigDecimal") ||
2239: clsName.equals("java.util.Date");
2240: }
2241:
2242: private static boolean isPrimitiveType(String clsName) {
2243: return clsName.equals("boolean") || clsName.equals("char")
2244: || clsName.equals("byte") || clsName.equals("short")
2245: || clsName.equals("int") || clsName.equals("long")
2246: || clsName.equals("float") || clsName.equals("double");
2247: }
2248:
2249: interface MyEntity {
2250: Object getPriKeyObject();
2251:
2252: void validate(Object other);
2253: }
2254:
2255: private static boolean nullOrEqual(Object o1, Object o2) {
2256: return (o1 != null) ? o1.equals(o2) : (o2 == null);
2257: }
2258:
2259: private static String arrayToString(Object[] array) {
2260: StringBuffer buf = new StringBuffer();
2261: buf.append('[');
2262: for (Object o : array) {
2263: if (o instanceof Object[]) {
2264: buf.append(arrayToString((Object[]) o));
2265: } else {
2266: buf.append(o);
2267: }
2268: buf.append(',');
2269: }
2270: buf.append(']');
2271: return buf.toString();
2272: }
2273:
2274: private void setFieldToNull(Object obj, String fieldName) {
2275: try {
2276: Field field = obj.getClass().getDeclaredField(fieldName);
2277: field.setAccessible(true);
2278: field.set(obj, null);
2279: } catch (NoSuchFieldException e) {
2280: fail(e.toString());
2281: } catch (IllegalAccessException e) {
2282: fail(e.toString());
2283: }
2284: }
2285:
2286: private void setField(Object obj, String fieldName,
2287: Object fieldValue) {
2288: try {
2289: Field field = obj.getClass().getDeclaredField(fieldName);
2290: field.setAccessible(true);
2291: field.set(obj, fieldValue);
2292: } catch (NoSuchFieldException e) {
2293: throw new IllegalStateException(e.toString());
2294: } catch (IllegalAccessException e) {
2295: throw new IllegalStateException(e.toString());
2296: }
2297: }
2298:
2299: private Object getField(Object obj, String fieldName) {
2300: try {
2301: Field field = obj.getClass().getDeclaredField(fieldName);
2302: field.setAccessible(true);
2303: return field.get(obj);
2304: } catch (NoSuchFieldException e) {
2305: throw new IllegalStateException(e.toString());
2306: } catch (IllegalAccessException e) {
2307: throw new IllegalStateException(e.toString());
2308: }
2309: }
2310: }
|