1 /*- 2 * Copyright (c) 2002, 2020 Oracle and/or its affiliates. All rights reserved. 3 * 4 * See the file LICENSE for license information. 5 * 6 */ 7 8 package com.sleepycat.persist.test; 9 10 import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE; 11 import static com.sleepycat.persist.model.Relationship.ONE_TO_MANY; 12 import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE; 13 import static org.junit.Assert.assertEquals; 14 import static org.junit.Assert.assertNotNull; 15 import static org.junit.Assert.assertNull; 16 import static org.junit.Assert.assertSame; 17 import static org.junit.Assert.assertTrue; 18 import static org.junit.Assert.fail; 19 20 import java.io.File; 21 import java.io.FileNotFoundException; 22 import java.lang.reflect.Array; 23 import java.lang.reflect.Field; 24 import java.math.BigDecimal; 25 import java.math.BigInteger; 26 import java.util.ArrayList; 27 import java.util.Arrays; 28 import java.util.Collection; 29 import java.util.Comparator; 30 import java.util.Date; 31 import java.util.HashMap; 32 import java.util.HashSet; 33 import java.util.Iterator; 34 import java.util.LinkedHashMap; 35 import java.util.LinkedList; 36 import java.util.List; 37 import java.util.Locale; 38 import java.util.Map; 39 import java.util.Set; 40 import java.util.TreeMap; 41 import java.util.TreeSet; 42 43 import junit.framework.TestCase; 44 45 import org.junit.After; 46 import org.junit.Before; 47 import org.junit.Test; 48 49 import com.sleepycat.bind.EntryBinding; 50 import com.sleepycat.compat.DbCompat; 51 import com.sleepycat.db.DatabaseConfig; 52 import com.sleepycat.db.DatabaseEntry; 53 import com.sleepycat.db.DatabaseException; 54 import com.sleepycat.db.Environment; 55 import com.sleepycat.db.EnvironmentConfig; 56 import com.sleepycat.db.ForeignMultiKeyNullifier; 57 import com.sleepycat.db.SecondaryKeyCreator; 58 import com.sleepycat.db.SecondaryMultiKeyCreator; 59 import com.sleepycat.persist.impl.PersistCatalog; 60 import com.sleepycat.persist.impl.PersistComparator; 61 import com.sleepycat.persist.impl.PersistEntityBinding; 62 import com.sleepycat.persist.impl.PersistKeyBinding; 63 import com.sleepycat.persist.impl.PersistKeyCreator; 64 import com.sleepycat.persist.impl.RefreshException; 65 import com.sleepycat.persist.model.AnnotationModel; 66 import com.sleepycat.persist.model.ClassMetadata; 67 import com.sleepycat.persist.model.Entity; 68 import com.sleepycat.persist.model.EntityMetadata; 69 import com.sleepycat.persist.model.EntityModel; 70 import com.sleepycat.persist.model.KeyField; 71 import com.sleepycat.persist.model.Persistent; 72 import com.sleepycat.persist.model.PersistentProxy; 73 import com.sleepycat.persist.model.PrimaryKey; 74 import com.sleepycat.persist.model.PrimaryKeyMetadata; 75 import com.sleepycat.persist.model.SecondaryKey; 76 import com.sleepycat.persist.model.SecondaryKeyMetadata; 77 import com.sleepycat.persist.raw.RawField; 78 import com.sleepycat.persist.raw.RawObject; 79 import com.sleepycat.persist.raw.RawType; 80 import com.sleepycat.util.test.SharedTestUtils; 81 import com.sleepycat.util.test.TestBase; 82 import com.sleepycat.util.test.TestEnv; 83 84 /** 85 * @author Mark Hayes 86 */ 87 public class BindingTest extends TestBase { 88 89 private static final String STORE_PREFIX = "persist#foo#"; 90 91 private File envHome; 92 private Environment env; 93 private EntityModel model; 94 private PersistCatalog catalog; 95 private DatabaseEntry keyEntry; 96 private DatabaseEntry dataEntry; 97 98 @Before setUp()99 public void setUp() 100 throws Exception { 101 102 envHome = SharedTestUtils.getTestDir(); 103 super.setUp(); 104 105 keyEntry = new DatabaseEntry(); 106 dataEntry = new DatabaseEntry(); 107 } 108 109 @After tearDown()110 public void tearDown() { 111 if (env != null) { 112 try { 113 env.close(); 114 } catch (Exception e) { 115 System.out.println("During tearDown: " + e); 116 } 117 } 118 envHome = null; 119 env = null; 120 catalog = null; 121 keyEntry = null; 122 dataEntry = null; 123 } 124 125 /** 126 * @throws FileNotFoundException from DB core. 127 */ open()128 private void open() 129 throws FileNotFoundException, DatabaseException { 130 131 EnvironmentConfig envConfig = TestEnv.BDB.getConfig(); 132 envConfig.setAllowCreate(true); 133 env = new Environment(envHome, envConfig); 134 openCatalog(); 135 } 136 openCatalog()137 private void openCatalog() 138 throws DatabaseException { 139 140 model = new AnnotationModel(); 141 model.registerClass(LocalizedTextProxy.class); 142 model.registerClass(LocaleProxy.class); 143 144 DatabaseConfig dbConfig = new DatabaseConfig(); 145 dbConfig.setAllowCreate(true); 146 DbCompat.setTypeBtree(dbConfig); 147 catalog = new PersistCatalog 148 (env, STORE_PREFIX, STORE_PREFIX + "catalog", dbConfig, model, 149 null, false /*rawAccess*/, null /*Store*/); 150 } 151 close()152 private void close() 153 throws DatabaseException { 154 155 /* Close/open/close catalog to test checks for class evolution. */ 156 catalog.close(); 157 PersistCatalog.expectNoClassChanges = true; 158 try { 159 openCatalog(); 160 } finally { 161 PersistCatalog.expectNoClassChanges = false; 162 } 163 catalog.close(); 164 catalog = null; 165 166 env.close(); 167 env = null; 168 } 169 170 @Test testBasic()171 public void testBasic() 172 throws FileNotFoundException, DatabaseException { 173 174 open(); 175 176 checkEntity(Basic.class, 177 new Basic(1, "one", 2.2, "three")); 178 checkEntity(Basic.class, 179 new Basic(0, null, 0, null)); 180 checkEntity(Basic.class, 181 new Basic(-1, "xxx", -2, "xxx")); 182 183 checkMetadata(Basic.class.getName(), new String[][] { 184 {"id", "long"}, 185 {"one", "java.lang.String"}, 186 {"two", "double"}, 187 {"three", "java.lang.String"}, 188 }, 189 0 /*priKeyIndex*/, null); 190 191 close(); 192 } 193 194 @Entity 195 static class Basic implements MyEntity { 196 197 @PrimaryKey 198 private long id; 199 private String one; 200 private double two; 201 private String three; 202 Basic()203 private Basic() { } 204 Basic(long id, String one, double two, String three)205 private Basic(long id, String one, double two, String three) { 206 this.id = id; 207 this.one = one; 208 this.two = two; 209 this.three = three; 210 } 211 getBasicOne()212 public String getBasicOne() { 213 return one; 214 } 215 getPriKeyObject()216 public Object getPriKeyObject() { 217 return id; 218 } 219 validate(Object other)220 public void validate(Object other) { 221 Basic o = (Basic) other; 222 TestCase.assertEquals(id, o.id); 223 TestCase.assertTrue(nullOrEqual(one, o.one)); 224 TestCase.assertEquals(two, o.two); 225 TestCase.assertTrue(nullOrEqual(three, o.three)); 226 } 227 228 @Override toString()229 public String toString() { 230 return "" + id + ' ' + one + ' ' + two; 231 } 232 } 233 234 @Test testSimpleTypes()235 public void testSimpleTypes() 236 throws FileNotFoundException, DatabaseException { 237 238 open(); 239 240 checkEntity(SimpleTypes.class, new SimpleTypes()); 241 242 checkMetadata(SimpleTypes.class.getName(), new String[][] { 243 {"f0", "boolean"}, 244 {"f1", "char"}, 245 {"f2", "byte"}, 246 {"f3", "short"}, 247 {"f4", "int"}, 248 {"f5", "long"}, 249 {"f6", "float"}, 250 {"f7", "double"}, 251 {"f8", "java.lang.String"}, 252 {"f9", "java.math.BigInteger"}, 253 {"f10", "java.math.BigDecimal"}, 254 {"f11", "java.util.Date"}, 255 {"f12", "java.lang.Boolean"}, 256 {"f13", "java.lang.Character"}, 257 {"f14", "java.lang.Byte"}, 258 {"f15", "java.lang.Short"}, 259 {"f16", "java.lang.Integer"}, 260 {"f17", "java.lang.Long"}, 261 {"f18", "java.lang.Float"}, 262 {"f19", "java.lang.Double"}, 263 }, 264 0 /*priKeyIndex*/, null); 265 266 close(); 267 } 268 269 @Entity 270 static class SimpleTypes implements MyEntity { 271 272 @PrimaryKey 273 private final boolean f0 = true; 274 private final char f1 = 'a'; 275 private final byte f2 = 123; 276 private final short f3 = 123; 277 private final int f4 = 123; 278 private final long f5 = 123; 279 private final float f6 = 123.4f; 280 private final double f7 = 123.4; 281 private final String f8 = "xxx"; 282 private final BigInteger f9 = BigInteger.valueOf(123); 283 private BigDecimal f10 = new BigDecimal("123.1234000"); 284 private final Date f11 = new Date(); 285 private final Boolean f12 = true; 286 private final Character f13 = 'a'; 287 private final Byte f14 = 123; 288 private final Short f15 = 123; 289 private final Integer f16 = 123; 290 private final Long f17 = 123L; 291 private final Float f18 = 123.4f; 292 private final Double f19 = 123.4; 293 SimpleTypes()294 SimpleTypes() { } 295 getPriKeyObject()296 public Object getPriKeyObject() { 297 return f0; 298 } 299 validate(Object other)300 public void validate(Object other) { 301 SimpleTypes o = (SimpleTypes) other; 302 TestCase.assertEquals(f0, o.f0); 303 TestCase.assertEquals(f1, o.f1); 304 TestCase.assertEquals(f2, o.f2); 305 TestCase.assertEquals(f3, o.f3); 306 TestCase.assertEquals(f4, o.f4); 307 TestCase.assertEquals(f5, o.f5); 308 TestCase.assertEquals(f6, o.f6); 309 TestCase.assertEquals(f7, o.f7); 310 TestCase.assertEquals(f8, o.f8); 311 TestCase.assertEquals(f9, o.f9); 312 /* The sorted BigDecimal cannot preserve the precision. */ 313 TestCase.assertTrue(!f10.equals(o.f10)); 314 TestCase.assertEquals(f10.compareTo(o.f10), 0); 315 TestCase.assertEquals(f10.stripTrailingZeros(), o.f10); 316 TestCase.assertEquals(f11, o.f11); 317 TestCase.assertEquals(f12, o.f12); 318 TestCase.assertEquals(f13, o.f13); 319 TestCase.assertEquals(f14, o.f14); 320 TestCase.assertEquals(f15, o.f15); 321 TestCase.assertEquals(f16, o.f16); 322 TestCase.assertEquals(f17, o.f17); 323 TestCase.assertEquals(f18, o.f18); 324 TestCase.assertEquals(f19, o.f19); 325 } 326 } 327 328 @Test testArrayTypes()329 public void testArrayTypes() 330 throws FileNotFoundException, DatabaseException { 331 332 open(); 333 334 checkEntity(ArrayTypes.class, new ArrayTypes()); 335 336 checkMetadata(ArrayTypes.class.getName(), new String[][] { 337 {"id", "int"}, 338 {"f0", boolean[].class.getName()}, 339 {"f1", char[].class.getName()}, 340 {"f2", byte[].class.getName()}, 341 {"f3", short[].class.getName()}, 342 {"f4", int[].class.getName()}, 343 {"f5", long[].class.getName()}, 344 {"f6", float[].class.getName()}, 345 {"f7", double[].class.getName()}, 346 {"f8", String[].class.getName()}, 347 {"f9", Address[].class.getName()}, 348 {"f10", boolean[][][].class.getName()}, 349 {"f11", String[][][].class.getName()}, 350 }, 351 0 /*priKeyIndex*/, null); 352 353 close(); 354 } 355 356 @Entity 357 static class ArrayTypes implements MyEntity { 358 359 @PrimaryKey 360 private final int id = 1; 361 private final boolean[] f0 = {false, true}; 362 private final char[] f1 = {'a', 'b'}; 363 private final byte[] f2 = {1, 2}; 364 private final short[] f3 = {1, 2}; 365 private final int[] f4 = {1, 2}; 366 private final long[] f5 = {1, 2}; 367 private final float[] f6 = {1.1f, 2.2f}; 368 private final double[] f7 = {1.1, 2,2}; 369 private final String[] f8 = {"xxx", null, "yyy"}; 370 private final Address[] f9 = {new Address("city", "state", 123), 371 null, 372 new Address("x", "y", 444)}; 373 private final boolean[][][] f10 = 374 { 375 { 376 {false, true}, 377 {false, true}, 378 }, 379 null, 380 { 381 {false, true}, 382 {false, true}, 383 }, 384 }; 385 private final String[][][] f11 = 386 { 387 { 388 {"xxx", null, "yyy"}, 389 null, 390 {"xxx", null, "yyy"}, 391 }, 392 null, 393 { 394 {"xxx", null, "yyy"}, 395 null, 396 {"xxx", null, "yyy"}, 397 }, 398 }; 399 ArrayTypes()400 ArrayTypes() { } 401 getPriKeyObject()402 public Object getPriKeyObject() { 403 return id; 404 } 405 validate(Object other)406 public void validate(Object other) { 407 ArrayTypes o = (ArrayTypes) other; 408 TestCase.assertEquals(id, o.id); 409 TestCase.assertTrue(Arrays.equals(f0, o.f0)); 410 TestCase.assertTrue(Arrays.equals(f1, o.f1)); 411 TestCase.assertTrue(Arrays.equals(f2, o.f2)); 412 TestCase.assertTrue(Arrays.equals(f3, o.f3)); 413 TestCase.assertTrue(Arrays.equals(f4, o.f4)); 414 TestCase.assertTrue(Arrays.equals(f5, o.f5)); 415 TestCase.assertTrue(Arrays.equals(f6, o.f6)); 416 TestCase.assertTrue(Arrays.equals(f7, o.f7)); 417 TestCase.assertTrue(Arrays.equals(f8, o.f8)); 418 TestCase.assertTrue(Arrays.deepEquals(f9, o.f9)); 419 TestCase.assertTrue(Arrays.deepEquals(f10, o.f10)); 420 TestCase.assertTrue(Arrays.deepEquals(f11, o.f11)); 421 } 422 } 423 424 @Test testEnumTypes()425 public void testEnumTypes() 426 throws FileNotFoundException, DatabaseException { 427 428 open(); 429 430 checkEntity(EnumTypes.class, new EnumTypes()); 431 432 checkMetadata(EnumTypes.class.getName(), new String[][] { 433 {"f0", "int"}, 434 {"f1", Thread.State.class.getName()}, 435 {"f2", MyEnum.class.getName()}, 436 {"f3", Object.class.getName()}, 437 {"f4", MyEnumCSM.class.getName()}, 438 {"f5", Object.class.getName()}, 439 }, 440 0 /*priKeyIndex*/, null); 441 442 close(); 443 } 444 445 enum MyEnum { ONE, TWO }; 446 447 enum MyEnumCSM { 448 449 A { Foo()450 void Foo() { 451 System.out.println("This is A!"); 452 } 453 }, 454 B(true)455 B(true) { 456 void Foo() { 457 System.out.println("This is B!"); 458 } 459 }; 460 461 private boolean b; 462 MyEnumCSM()463 MyEnumCSM() { 464 this(false); 465 } 466 MyEnumCSM(boolean b)467 MyEnumCSM(boolean b) { 468 this.b = b; 469 } 470 Foo()471 abstract void Foo(); 472 }; 473 474 @Entity 475 static class EnumTypes implements MyEntity { 476 477 @PrimaryKey 478 private final int f0 = 1; 479 private final Thread.State f1 = Thread.State.RUNNABLE; 480 private final MyEnum f2 = MyEnum.ONE; 481 private final Object f3 = MyEnum.TWO; 482 private final MyEnumCSM f4 = MyEnumCSM.A; 483 private final Object f5 = MyEnumCSM.B; 484 EnumTypes()485 EnumTypes() { } 486 getPriKeyObject()487 public Object getPriKeyObject() { 488 return f0; 489 } 490 validate(Object other)491 public void validate(Object other) { 492 EnumTypes o = (EnumTypes) other; 493 TestCase.assertEquals(f0, o.f0); 494 TestCase.assertSame(f1, o.f1); 495 TestCase.assertSame(f2, o.f2); 496 TestCase.assertSame(f3, o.f3); 497 TestCase.assertSame(f4, o.f4); 498 TestCase.assertSame(f5, o.f5); 499 } 500 } 501 502 @Test testEnumObjectTypes()503 public void testEnumObjectTypes() 504 throws FileNotFoundException, DatabaseException { 505 506 open(); 507 508 checkEntity(EnumObjectTypes.class, new EnumObjectTypes()); 509 510 checkMetadata(EnumObjectTypes.class.getName(), new String[][] { 511 {"f0", "int"}, 512 {"f1", Object.class.getName()}, 513 {"f2", Object.class.getName()}, 514 }, 515 0 /*priKeyIndex*/, null); 516 517 close(); 518 } 519 520 @Entity 521 static class EnumObjectTypes implements MyEntity { 522 523 @PrimaryKey 524 private final int f0 = 1; 525 private final Object f1 = MyEnum.ONE; 526 private final Object f2 = MyEnumCSM.A; 527 EnumObjectTypes()528 EnumObjectTypes() { } 529 getPriKeyObject()530 public Object getPriKeyObject() { 531 return f0; 532 } 533 validate(Object other)534 public void validate(Object other) { 535 EnumObjectTypes o = (EnumObjectTypes) other; 536 TestCase.assertEquals(f0, o.f0); 537 TestCase.assertSame(f1, o.f1); 538 TestCase.assertSame(f2, o.f2); 539 } 540 } 541 542 @Test testProxyTypes()543 public void testProxyTypes() 544 throws FileNotFoundException, DatabaseException { 545 546 open(); 547 548 checkEntity(ProxyTypes.class, new ProxyTypes()); 549 550 checkMetadata(ProxyTypes.class.getName(), new String[][] { 551 {"f0", "int"}, 552 {"f1", Locale.class.getName()}, 553 {"f2", Set.class.getName()}, 554 {"f3", Set.class.getName()}, 555 {"f4", Object.class.getName()}, 556 {"f5", HashMap.class.getName()}, 557 {"f6", TreeMap.class.getName()}, 558 {"f7", List.class.getName()}, 559 {"f8", LinkedList.class.getName()}, 560 {"f9", LocalizedText.class.getName()}, 561 {"f10", LinkedHashMap.class.getName()}, 562 }, 563 0 /*priKeyIndex*/, null); 564 565 close(); 566 } 567 568 @Entity 569 static class ProxyTypes implements MyEntity { 570 571 @PrimaryKey 572 private final int f0 = 1; 573 private final Locale f1 = Locale.getDefault(); 574 private final Set<Integer> f2 = new HashSet<Integer>(); 575 private final Set<Integer> f3 = new TreeSet<Integer>(); 576 private final Object f4 = new HashSet<Address>(); 577 private final HashMap<String, Integer> f5 = 578 new HashMap<String, Integer>(); 579 private final TreeMap<String, Address> f6 = 580 new TreeMap<String, Address>(); 581 private final List<Integer> f7 = new ArrayList<Integer>(); 582 private final LinkedList<Integer> f8 = new LinkedList<Integer>(); 583 private final LocalizedText f9 = new LocalizedText(f1, "xyz"); 584 private final LinkedHashMap<String, Integer> f10 = 585 new LinkedHashMap<String, Integer>(); 586 ProxyTypes()587 ProxyTypes() { 588 f2.add(123); 589 f2.add(456); 590 f3.add(456); 591 f3.add(123); 592 HashSet<Address> s = (HashSet) f4; 593 s.add(new Address("city", "state", 11111)); 594 s.add(new Address("city2", "state2", 22222)); 595 s.add(new Address("city3", "state3", 33333)); 596 f5.put("one", 111); 597 f5.put("two", 222); 598 f5.put("three", 333); 599 f6.put("one", new Address("city", "state", 11111)); 600 f6.put("two", new Address("city2", "state2", 22222)); 601 f6.put("three", new Address("city3", "state3", 33333)); 602 f7.add(123); 603 f7.add(456); 604 f8.add(123); 605 f8.add(456); 606 f10.put("one", 111); 607 f10.put("two", 222); 608 f10.put("three", 333); 609 } 610 getPriKeyObject()611 public Object getPriKeyObject() { 612 return f0; 613 } 614 validate(Object other)615 public void validate(Object other) { 616 ProxyTypes o = (ProxyTypes) other; 617 TestCase.assertEquals(f0, o.f0); 618 TestCase.assertEquals(f1, o.f1); 619 TestCase.assertEquals(f2, o.f2); 620 TestCase.assertEquals(f3, o.f3); 621 TestCase.assertEquals(f4, o.f4); 622 TestCase.assertEquals(f5, o.f5); 623 TestCase.assertEquals(f6, o.f6); 624 TestCase.assertEquals(f7, o.f7); 625 TestCase.assertEquals(f8, o.f8); 626 TestCase.assertEquals(f9, o.f9); 627 TestCase.assertEquals(f10, o.f10); 628 } 629 } 630 631 @Persistent(proxyFor=Locale.class) 632 static class LocaleProxy implements PersistentProxy<Locale> { 633 634 String language; 635 String country; 636 String variant; 637 LocaleProxy()638 private LocaleProxy() {} 639 initializeProxy(Locale object)640 public void initializeProxy(Locale object) { 641 language = object.getLanguage(); 642 country = object.getCountry(); 643 variant = object.getVariant(); 644 } 645 convertProxy()646 public Locale convertProxy() { 647 return new Locale(language, country, variant); 648 } 649 } 650 651 static class LocalizedText { 652 653 Locale locale; 654 String text; 655 LocalizedText(Locale locale, String text)656 LocalizedText(Locale locale, String text) { 657 this.locale = locale; 658 this.text = text; 659 } 660 661 @Override equals(Object other)662 public boolean equals(Object other) { 663 LocalizedText o = (LocalizedText) other; 664 return text.equals(o.text) && 665 locale.equals(o.locale); 666 } 667 } 668 669 @Persistent(proxyFor=LocalizedText.class) 670 static class LocalizedTextProxy implements PersistentProxy<LocalizedText> { 671 672 Locale locale; 673 String text; 674 LocalizedTextProxy()675 private LocalizedTextProxy() {} 676 initializeProxy(LocalizedText object)677 public void initializeProxy(LocalizedText object) { 678 locale = object.locale; 679 text = object.text; 680 } 681 convertProxy()682 public LocalizedText convertProxy() { 683 return new LocalizedText(locale, text); 684 } 685 } 686 687 @Test testEmbedded()688 public void testEmbedded() 689 throws FileNotFoundException, DatabaseException { 690 691 open(); 692 693 Address a1 = new Address("city", "state", 123); 694 Address a2 = new Address("Wikieup", "AZ", 85360); 695 696 checkEntity(Embedded.class, 697 new Embedded("x", a1, a2)); 698 checkEntity(Embedded.class, 699 new Embedded("y", a1, null)); 700 checkEntity(Embedded.class, 701 new Embedded("", a2, a2)); 702 703 checkMetadata(Embedded.class.getName(), new String[][] { 704 {"id", "java.lang.String"}, 705 {"idShadow", "java.lang.String"}, 706 {"one", Address.class.getName()}, 707 {"two", Address.class.getName()}, 708 }, 709 0 /*priKeyIndex*/, null); 710 711 checkMetadata(Address.class.getName(), new String[][] { 712 {"street", "java.lang.String"}, 713 {"city", "java.lang.String"}, 714 {"zip", "int"}, 715 }, 716 -1 /*priKeyIndex*/, null); 717 718 close(); 719 } 720 721 @Entity 722 static class Embedded implements MyEntity { 723 724 @PrimaryKey 725 private String id; 726 private String idShadow; 727 private Address one; 728 private Address two; 729 Embedded()730 private Embedded() { } 731 Embedded(String id, Address one, Address two)732 private Embedded(String id, Address one, Address two) { 733 this.id = id; 734 idShadow = id; 735 this.one = one; 736 this.two = two; 737 } 738 getPriKeyObject()739 public Object getPriKeyObject() { 740 return id; 741 } 742 validate(Object other)743 public void validate(Object other) { 744 Embedded o = (Embedded) other; 745 TestCase.assertEquals(id, o.id); 746 if (one != null) { 747 one.validate(o.one); 748 } else { 749 assertNull(o.one); 750 } 751 if (two != null) { 752 two.validate(o.two); 753 } else { 754 assertNull(o.two); 755 } 756 if (one == two) { 757 TestCase.assertSame(o.one, o.two); 758 } 759 } 760 761 @Override toString()762 public String toString() { 763 return "" + id + ' ' + one + ' ' + two; 764 } 765 } 766 767 @Persistent 768 static class Address { 769 770 private String street; 771 private String city; 772 private int zip; 773 Address()774 private Address() {} 775 Address(String street, String city, int zip)776 Address(String street, String city, int zip) { 777 this.street = street; 778 this.city = city; 779 this.zip = zip; 780 } 781 validate(Address o)782 void validate(Address o) { 783 TestCase.assertTrue(nullOrEqual(street, o.street)); 784 TestCase.assertTrue(nullOrEqual(city, o.city)); 785 TestCase.assertEquals(zip, o.zip); 786 } 787 788 @Override toString()789 public String toString() { 790 return "" + street + ' ' + city + ' ' + zip; 791 } 792 793 @Override equals(Object other)794 public boolean equals(Object other) { 795 if (other == null) { 796 return false; 797 } 798 Address o = (Address) other; 799 return nullOrEqual(street, o.street) && 800 nullOrEqual(city, o.city) && 801 nullOrEqual(zip, o.zip); 802 } 803 804 @Override hashCode()805 public int hashCode() { 806 return zip; 807 } 808 } 809 810 @Test testSubclass()811 public void testSubclass() 812 throws FileNotFoundException, DatabaseException { 813 814 open(); 815 816 checkEntity(Basic.class, 817 new Subclass(-1, "xxx", -2, "xxx", "xxx", true)); 818 819 checkMetadata(Basic.class.getName(), new String[][] { 820 {"id", "long"}, 821 {"one", "java.lang.String"}, 822 {"two", "double"}, 823 {"three", "java.lang.String"}, 824 }, 825 0 /*priKeyIndex*/, null); 826 checkMetadata(Subclass.class.getName(), new String[][] { 827 {"one", "java.lang.String"}, 828 {"two", "boolean"}, 829 }, 830 -1 /*priKeyIndex*/, Basic.class.getName()); 831 832 close(); 833 } 834 835 @Persistent 836 static class Subclass extends Basic { 837 838 private String one; 839 private boolean two; 840 Subclass()841 private Subclass() { 842 } 843 Subclass(long id, String one, double two, String three, String subOne, boolean subTwo)844 private Subclass(long id, String one, double two, String three, 845 String subOne, boolean subTwo) { 846 super(id, one, two, three); 847 this.one = subOne; 848 this.two = subTwo; 849 } 850 851 @Override validate(Object other)852 public void validate(Object other) { 853 super.validate(other); 854 Subclass o = (Subclass) other; 855 TestCase.assertTrue(nullOrEqual(one, o.one)); 856 TestCase.assertEquals(two, o.two); 857 } 858 } 859 860 @Test testSuperclass()861 public void testSuperclass() 862 throws FileNotFoundException, DatabaseException { 863 864 open(); 865 866 checkEntity(UseSuperclass.class, 867 new UseSuperclass(33, "xxx")); 868 869 checkMetadata(Superclass.class.getName(), new String[][] { 870 {"id", "int"}, 871 {"one", "java.lang.String"}, 872 }, 873 0 /*priKeyIndex*/, null); 874 checkMetadata(UseSuperclass.class.getName(), new String[][] { 875 }, 876 -1 /*priKeyIndex*/, Superclass.class.getName()); 877 878 close(); 879 } 880 881 @Persistent 882 static class Superclass implements MyEntity { 883 884 @PrimaryKey 885 private int id; 886 private String one; 887 Superclass()888 private Superclass() { } 889 Superclass(int id, String one)890 private Superclass(int id, String one) { 891 this.id = id; 892 this.one = one; 893 } 894 getPriKeyObject()895 public Object getPriKeyObject() { 896 return id; 897 } 898 validate(Object other)899 public void validate(Object other) { 900 Superclass o = (Superclass) other; 901 TestCase.assertEquals(id, o.id); 902 TestCase.assertTrue(nullOrEqual(one, o.one)); 903 } 904 } 905 906 @Entity 907 static class UseSuperclass extends Superclass { 908 UseSuperclass()909 private UseSuperclass() { } 910 UseSuperclass(int id, String one)911 private UseSuperclass(int id, String one) { 912 super(id, one); 913 } 914 } 915 916 @Test testAbstract()917 public void testAbstract() 918 throws FileNotFoundException, DatabaseException { 919 920 open(); 921 922 checkEntity(EntityUseAbstract.class, 923 new EntityUseAbstract(33, "xxx")); 924 925 checkMetadata(Abstract.class.getName(), new String[][] { 926 {"one", "java.lang.String"}, 927 }, 928 -1 /*priKeyIndex*/, null); 929 checkMetadata(EmbeddedUseAbstract.class.getName(), new String[][] { 930 {"two", "java.lang.String"}, 931 }, 932 -1 /*priKeyIndex*/, Abstract.class.getName()); 933 checkMetadata(EntityUseAbstract.class.getName(), new String[][] { 934 {"id", "int"}, 935 {"f1", EmbeddedUseAbstract.class.getName()}, 936 {"f2", Abstract.class.getName()}, 937 {"f3", Object.class.getName()}, 938 {"f4", Interface.class.getName()}, 939 {"a1", EmbeddedUseAbstract[].class.getName()}, 940 {"a2", Abstract[].class.getName()}, 941 {"a3", Abstract[].class.getName()}, 942 {"a4", Object[].class.getName()}, 943 {"a5", Interface[].class.getName()}, 944 {"a6", Interface[].class.getName()}, 945 {"a7", Interface[].class.getName()}, 946 }, 947 0 /*priKeyIndex*/, Abstract.class.getName()); 948 949 close(); 950 } 951 952 @Persistent 953 static abstract class Abstract implements Interface { 954 955 String one; 956 Abstract()957 private Abstract() { } 958 Abstract(String one)959 private Abstract(String one) { 960 this.one = one; 961 } 962 validate(Object other)963 public void validate(Object other) { 964 Abstract o = (Abstract) other; 965 TestCase.assertTrue(nullOrEqual(one, o.one)); 966 } 967 968 @Override equals(Object other)969 public boolean equals(Object other) { 970 Abstract o = (Abstract) other; 971 return nullOrEqual(one, o.one); 972 } 973 } 974 975 interface Interface { validate(Object other)976 void validate(Object other); 977 } 978 979 @Persistent 980 static class EmbeddedUseAbstract extends Abstract { 981 982 private String two; 983 EmbeddedUseAbstract()984 private EmbeddedUseAbstract() { } 985 EmbeddedUseAbstract(String one, String two)986 private EmbeddedUseAbstract(String one, String two) { 987 super(one); 988 this.two = two; 989 } 990 991 @Override validate(Object other)992 public void validate(Object other) { 993 super.validate(other); 994 EmbeddedUseAbstract o = (EmbeddedUseAbstract) other; 995 TestCase.assertTrue(nullOrEqual(two, o.two)); 996 } 997 998 @Override equals(Object other)999 public boolean equals(Object other) { 1000 if (!super.equals(other)) { 1001 return false; 1002 } 1003 EmbeddedUseAbstract o = (EmbeddedUseAbstract) other; 1004 return nullOrEqual(two, o.two); 1005 } 1006 } 1007 1008 @Entity 1009 static class EntityUseAbstract extends Abstract implements MyEntity { 1010 1011 @PrimaryKey 1012 private int id; 1013 1014 private EmbeddedUseAbstract f1; 1015 private Abstract f2; 1016 private Object f3; 1017 private Interface f4; 1018 private EmbeddedUseAbstract[] a1; 1019 private Abstract[] a2; 1020 private Abstract[] a3; 1021 private Object[] a4; 1022 private Interface[] a5; 1023 private Interface[] a6; 1024 private Interface[] a7; 1025 EntityUseAbstract()1026 private EntityUseAbstract() { } 1027 EntityUseAbstract(int id, String one)1028 private EntityUseAbstract(int id, String one) { 1029 super(one); 1030 this.id = id; 1031 f1 = new EmbeddedUseAbstract(one, one); 1032 f2 = new EmbeddedUseAbstract(one + "x", one + "y"); 1033 f3 = new EmbeddedUseAbstract(null, null); 1034 f4 = new EmbeddedUseAbstract(null, null); 1035 a1 = new EmbeddedUseAbstract[3]; 1036 a2 = new EmbeddedUseAbstract[3]; 1037 a3 = new Abstract[3]; 1038 a4 = new Object[3]; 1039 a5 = new EmbeddedUseAbstract[3]; 1040 a6 = new Abstract[3]; 1041 a7 = new Interface[3]; 1042 for (int i = 0; i < 3; i += 1) { 1043 a1[i] = new EmbeddedUseAbstract("1" + i, null); 1044 a2[i] = new EmbeddedUseAbstract("2" + i, null); 1045 a3[i] = new EmbeddedUseAbstract("3" + i, null); 1046 a4[i] = new EmbeddedUseAbstract("4" + i, null); 1047 a5[i] = new EmbeddedUseAbstract("5" + i, null); 1048 a6[i] = new EmbeddedUseAbstract("6" + i, null); 1049 a7[i] = new EmbeddedUseAbstract("7" + i, null); 1050 } 1051 } 1052 getPriKeyObject()1053 public Object getPriKeyObject() { 1054 return id; 1055 } 1056 1057 @Override validate(Object other)1058 public void validate(Object other) { 1059 super.validate(other); 1060 EntityUseAbstract o = (EntityUseAbstract) other; 1061 TestCase.assertEquals(id, o.id); 1062 f1.validate(o.f1); 1063 f2.validate(o.f2); 1064 ((Abstract) f3).validate(o.f3); 1065 f4.validate(o.f4); 1066 assertTrue(arrayToString(a1) + ' ' + arrayToString(o.a1), 1067 Arrays.equals(a1, o.a1)); 1068 assertTrue(Arrays.equals(a2, o.a2)); 1069 assertTrue(Arrays.equals(a3, o.a3)); 1070 assertTrue(Arrays.equals(a4, o.a4)); 1071 assertTrue(Arrays.equals(a5, o.a5)); 1072 assertTrue(Arrays.equals(a6, o.a6)); 1073 assertTrue(Arrays.equals(a7, o.a7)); 1074 assertSame(EmbeddedUseAbstract.class, f2.getClass()); 1075 assertSame(EmbeddedUseAbstract.class, f3.getClass()); 1076 assertSame(EmbeddedUseAbstract[].class, a1.getClass()); 1077 assertSame(EmbeddedUseAbstract[].class, a2.getClass()); 1078 assertSame(Abstract[].class, a3.getClass()); 1079 assertSame(Object[].class, a4.getClass()); 1080 assertSame(EmbeddedUseAbstract[].class, a5.getClass()); 1081 assertSame(Abstract[].class, a6.getClass()); 1082 assertSame(Interface[].class, a7.getClass()); 1083 } 1084 } 1085 1086 @Test testCompositeKey()1087 public void testCompositeKey() 1088 throws FileNotFoundException, DatabaseException { 1089 1090 open(); 1091 1092 CompositeKey key = 1093 new CompositeKey(123, 456L, "xyz", BigInteger.valueOf(789), 1094 MyEnum.ONE, MyEnumCSM.A, 1095 BigDecimal.valueOf(123.123)); 1096 checkEntity(UseCompositeKey.class, 1097 new UseCompositeKey(key, "one")); 1098 1099 checkMetadata(UseCompositeKey.class.getName(), new String[][] { 1100 {"key", CompositeKey.class.getName()}, 1101 {"one", "java.lang.String"}, 1102 }, 1103 0 /*priKeyIndex*/, null); 1104 1105 checkMetadata(CompositeKey.class.getName(), new String[][] { 1106 {"f1", "int"}, 1107 {"f2", "java.lang.Long"}, 1108 {"f3", "java.lang.String"}, 1109 {"f4", "java.math.BigInteger"}, 1110 {"f5", MyEnum.class.getName()}, 1111 {"f6", MyEnumCSM.class.getName()}, 1112 {"f7", BigDecimal.class.getName()}, 1113 }, 1114 -1 /*priKeyIndex*/, null); 1115 1116 close(); 1117 } 1118 1119 @Persistent 1120 static class CompositeKey { 1121 @KeyField(3) 1122 private int f1; 1123 @KeyField(2) 1124 private Long f2; 1125 @KeyField(1) 1126 private String f3; 1127 @KeyField(4) 1128 private BigInteger f4; 1129 @KeyField(5) 1130 private MyEnum f5; 1131 @KeyField(6) 1132 private MyEnumCSM f6; 1133 @KeyField(7) 1134 private BigDecimal f7; 1135 CompositeKey()1136 private CompositeKey() {} 1137 CompositeKey(int f1, Long f2, String f3, BigInteger f4, MyEnum f5, MyEnumCSM f6, BigDecimal f7)1138 CompositeKey(int f1, 1139 Long f2, 1140 String f3, 1141 BigInteger f4, 1142 MyEnum f5, 1143 MyEnumCSM f6, 1144 BigDecimal f7) { 1145 this.f1 = f1; 1146 this.f2 = f2; 1147 this.f3 = f3; 1148 this.f4 = f4; 1149 this.f5 = f5; 1150 this.f6 = f6; 1151 this.f7 = f7; 1152 } 1153 validate(CompositeKey o)1154 void validate(CompositeKey o) { 1155 TestCase.assertEquals(f1, o.f1); 1156 TestCase.assertTrue(nullOrEqual(f2, o.f2)); 1157 TestCase.assertTrue(nullOrEqual(f3, o.f3)); 1158 TestCase.assertTrue(nullOrEqual(f4, o.f4)); 1159 TestCase.assertEquals(f5, o.f5); 1160 TestCase.assertTrue(nullOrEqual(f5, o.f5)); 1161 TestCase.assertEquals(f5, o.f5); 1162 TestCase.assertTrue(nullOrEqual(f6, o.f6)); 1163 TestCase.assertTrue(nullOrEqual(f7, o.f7)); 1164 } 1165 1166 @Override equals(Object other)1167 public boolean equals(Object other) { 1168 CompositeKey o = (CompositeKey) other; 1169 return f1 == o.f1 && 1170 nullOrEqual(f2, o.f2) && 1171 nullOrEqual(f3, o.f3) && 1172 nullOrEqual(f4, o.f4) && 1173 nullOrEqual(f5, o.f5) && 1174 nullOrEqual(f6, o.f6) && 1175 nullOrEqual(f7, o.f7); 1176 } 1177 1178 @Override hashCode()1179 public int hashCode() { 1180 return f1; 1181 } 1182 1183 @Override toString()1184 public String toString() { 1185 return "" + f1 + ' ' + f2 + ' ' + f3 + ' ' + f4 + ' ' + f5 + ' ' + 1186 f6 + ' ' + f7; 1187 } 1188 } 1189 1190 @Entity 1191 static class UseCompositeKey implements MyEntity { 1192 1193 @PrimaryKey 1194 private CompositeKey key; 1195 private String one; 1196 UseCompositeKey()1197 private UseCompositeKey() { } 1198 UseCompositeKey(CompositeKey key, String one)1199 private UseCompositeKey(CompositeKey key, String one) { 1200 this.key = key; 1201 this.one = one; 1202 } 1203 getPriKeyObject()1204 public Object getPriKeyObject() { 1205 return key; 1206 } 1207 validate(Object other)1208 public void validate(Object other) { 1209 UseCompositeKey o = (UseCompositeKey) other; 1210 TestCase.assertNotNull(key); 1211 TestCase.assertNotNull(o.key); 1212 key.validate(o.key); 1213 TestCase.assertTrue(nullOrEqual(one, o.one)); 1214 } 1215 } 1216 1217 @Test testComparableKey()1218 public void testComparableKey() 1219 throws FileNotFoundException, DatabaseException { 1220 1221 open(); 1222 1223 ComparableKey key = new ComparableKey(123, 456); 1224 checkEntity(UseComparableKey.class, 1225 new UseComparableKey(key, "one")); 1226 1227 checkMetadata(UseComparableKey.class.getName(), new String[][] { 1228 {"key", ComparableKey.class.getName()}, 1229 {"one", "java.lang.String"}, 1230 }, 1231 0 /*priKeyIndex*/, null); 1232 1233 checkMetadata(ComparableKey.class.getName(), new String[][] { 1234 {"f1", "int"}, 1235 {"f2", "int"}, 1236 }, 1237 -1 /*priKeyIndex*/, null); 1238 1239 ClassMetadata classMeta = 1240 model.getClassMetadata(UseComparableKey.class.getName()); 1241 assertNotNull(classMeta); 1242 1243 PersistKeyBinding binding = new PersistKeyBinding 1244 (catalog, ComparableKey.class.getName(), false); 1245 1246 PersistComparator comparator = new PersistComparator(binding); 1247 1248 compareKeys(comparator, binding, new ComparableKey(1, 1), 1249 new ComparableKey(1, 1), 0); 1250 compareKeys(comparator, binding, new ComparableKey(1, 2), 1251 new ComparableKey(1, 1), -1); 1252 compareKeys(comparator, binding, new ComparableKey(2, 1), 1253 new ComparableKey(1, 1), -1); 1254 compareKeys(comparator, binding, new ComparableKey(2, 1), 1255 new ComparableKey(3, 1), 1); 1256 1257 close(); 1258 } 1259 compareKeys(Comparator<byte[]> comparator, EntryBinding binding, Object key1, Object key2, int expectResult)1260 private void compareKeys(Comparator<byte[]> comparator, 1261 EntryBinding binding, 1262 Object key1, 1263 Object key2, 1264 int expectResult) { 1265 DatabaseEntry entry1 = new DatabaseEntry(); 1266 DatabaseEntry entry2 = new DatabaseEntry(); 1267 binding.objectToEntry(key1, entry1); 1268 binding.objectToEntry(key2, entry2); 1269 int result = comparator.compare(entry1.getData(), entry2.getData()); 1270 assertEquals(expectResult, result); 1271 } 1272 1273 @Persistent 1274 static class ComparableKey implements Comparable<ComparableKey> { 1275 @KeyField(2) 1276 private int f1; 1277 @KeyField(1) 1278 private int f2; 1279 ComparableKey()1280 private ComparableKey() {} 1281 ComparableKey(int f1, int f2)1282 ComparableKey(int f1, int f2) { 1283 this.f1 = f1; 1284 this.f2 = f2; 1285 } 1286 validate(ComparableKey o)1287 void validate(ComparableKey o) { 1288 TestCase.assertEquals(f1, o.f1); 1289 TestCase.assertEquals(f2, o.f2); 1290 } 1291 1292 @Override equals(Object other)1293 public boolean equals(Object other) { 1294 ComparableKey o = (ComparableKey) other; 1295 return f1 == o.f1 && f2 == o.f2; 1296 } 1297 1298 @Override hashCode()1299 public int hashCode() { 1300 return f1 + f2; 1301 } 1302 1303 @Override toString()1304 public String toString() { 1305 return "" + f1 + ' ' + f2; 1306 } 1307 1308 /** Compare f1 then f2, in reverse integer order. */ compareTo(ComparableKey o)1309 public int compareTo(ComparableKey o) { 1310 if (f1 != o.f1) { 1311 return o.f1 - f1; 1312 } else { 1313 return o.f2 - f2; 1314 } 1315 } 1316 } 1317 1318 @Entity 1319 static class UseComparableKey implements MyEntity { 1320 1321 @PrimaryKey 1322 private ComparableKey key; 1323 private String one; 1324 UseComparableKey()1325 private UseComparableKey() { } 1326 UseComparableKey(ComparableKey key, String one)1327 private UseComparableKey(ComparableKey key, String one) { 1328 this.key = key; 1329 this.one = one; 1330 } 1331 getPriKeyObject()1332 public Object getPriKeyObject() { 1333 return key; 1334 } 1335 validate(Object other)1336 public void validate(Object other) { 1337 UseComparableKey o = (UseComparableKey) other; 1338 TestCase.assertNotNull(key); 1339 TestCase.assertNotNull(o.key); 1340 key.validate(o.key); 1341 TestCase.assertTrue(nullOrEqual(one, o.one)); 1342 } 1343 } 1344 1345 @Test testSecKeys()1346 public void testSecKeys() 1347 throws FileNotFoundException, DatabaseException { 1348 1349 open(); 1350 1351 SecKeys obj = new SecKeys(); 1352 checkEntity(SecKeys.class, obj); 1353 1354 checkMetadata(SecKeys.class.getName(), new String[][] { 1355 {"id", "long"}, 1356 {"f0", "boolean"}, 1357 {"g0", "boolean"}, 1358 {"f1", "char"}, 1359 {"g1", "char"}, 1360 {"f2", "byte"}, 1361 {"g2", "byte"}, 1362 {"f3", "short"}, 1363 {"g3", "short"}, 1364 {"f4", "int"}, 1365 {"g4", "int"}, 1366 {"f5", "long"}, 1367 {"g5", "long"}, 1368 {"f6", "float"}, 1369 {"g6", "float"}, 1370 {"f7", "double"}, 1371 {"g7", "double"}, 1372 {"f8", "java.lang.String"}, 1373 {"g8", "java.lang.String"}, 1374 {"f9", "java.math.BigInteger"}, 1375 {"g9", "java.math.BigInteger"}, 1376 {"f10", "java.math.BigDecimal"}, 1377 {"g10", "java.math.BigDecimal"}, 1378 {"f11", "java.util.Date"}, 1379 {"g11", "java.util.Date"}, 1380 {"f12", "java.lang.Boolean"}, 1381 {"g12", "java.lang.Boolean"}, 1382 {"f13", "java.lang.Character"}, 1383 {"g13", "java.lang.Character"}, 1384 {"f14", "java.lang.Byte"}, 1385 {"g14", "java.lang.Byte"}, 1386 {"f15", "java.lang.Short"}, 1387 {"g15", "java.lang.Short"}, 1388 {"f16", "java.lang.Integer"}, 1389 {"g16", "java.lang.Integer"}, 1390 {"f17", "java.lang.Long"}, 1391 {"g17", "java.lang.Long"}, 1392 {"f18", "java.lang.Float"}, 1393 {"g18", "java.lang.Float"}, 1394 {"f19", "java.lang.Double"}, 1395 {"g19", "java.lang.Double"}, 1396 {"f20", CompositeKey.class.getName()}, 1397 {"g20", CompositeKey.class.getName()}, 1398 {"f21", int[].class.getName()}, 1399 {"g21", int[].class.getName()}, 1400 {"f22", Integer[].class.getName()}, 1401 {"g22", Integer[].class.getName()}, 1402 {"f23", Set.class.getName()}, 1403 {"g23", Set.class.getName()}, 1404 {"f24", CompositeKey[].class.getName()}, 1405 {"g24", CompositeKey[].class.getName()}, 1406 {"f25", Set.class.getName()}, 1407 {"g25", Set.class.getName()}, 1408 {"f26", MyEnum.class.getName()}, 1409 {"g26", MyEnum.class.getName()}, 1410 {"f27", MyEnum[].class.getName()}, 1411 {"g27", MyEnum[].class.getName()}, 1412 {"f28", Set.class.getName()}, 1413 {"g28", Set.class.getName()}, 1414 {"f31", "java.util.Date"}, 1415 {"f32", "java.lang.Boolean"}, 1416 {"f33", "java.lang.Character"}, 1417 {"f34", "java.lang.Byte"}, 1418 {"f35", "java.lang.Short"}, 1419 {"f36", "java.lang.Integer"}, 1420 {"f37", "java.lang.Long"}, 1421 {"f38", "java.lang.Float"}, 1422 {"f39", "java.lang.Double"}, 1423 {"f40", CompositeKey.class.getName()}, 1424 {"f41", MyEnumCSM.class.getName()}, 1425 {"g41", MyEnumCSM.class.getName()}, 1426 {"f42", MyEnumCSM[].class.getName()}, 1427 {"g42", MyEnumCSM[].class.getName()}, 1428 {"f43", Set.class.getName()}, 1429 {"g43", Set.class.getName()}, 1430 }, 1431 0 /*priKeyIndex*/, null); 1432 1433 checkSecKey(obj, "f0", obj.f0, Boolean.class); 1434 checkSecKey(obj, "f1", obj.f1, Character.class); 1435 checkSecKey(obj, "f2", obj.f2, Byte.class); 1436 checkSecKey(obj, "f3", obj.f3, Short.class); 1437 checkSecKey(obj, "f4", obj.f4, Integer.class); 1438 checkSecKey(obj, "f5", obj.f5, Long.class); 1439 checkSecKey(obj, "f6", obj.f6, Float.class); 1440 checkSecKey(obj, "f7", obj.f7, Double.class); 1441 checkSecKey(obj, "f8", obj.f8, String.class); 1442 checkSecKey(obj, "f9", obj.f9, BigInteger.class); 1443 checkSecKey(obj, "f10", obj.f10, BigDecimal.class); 1444 checkSecKey(obj, "f11", obj.f11, Date.class); 1445 checkSecKey(obj, "f12", obj.f12, Boolean.class); 1446 checkSecKey(obj, "f13", obj.f13, Character.class); 1447 checkSecKey(obj, "f14", obj.f14, Byte.class); 1448 checkSecKey(obj, "f15", obj.f15, Short.class); 1449 checkSecKey(obj, "f16", obj.f16, Integer.class); 1450 checkSecKey(obj, "f17", obj.f17, Long.class); 1451 checkSecKey(obj, "f18", obj.f18, Float.class); 1452 checkSecKey(obj, "f19", obj.f19, Double.class); 1453 checkSecKey(obj, "f20", obj.f20, CompositeKey.class); 1454 checkSecKey(obj, "f26", obj.f26, MyEnum.class); 1455 checkSecKey(obj, "f41", obj.f41, MyEnumCSM.class); 1456 1457 checkSecMultiKey(obj, "f21", toSet(obj.f21), Integer.class); 1458 checkSecMultiKey(obj, "f22", toSet(obj.f22), Integer.class); 1459 checkSecMultiKey(obj, "f23", toSet(obj.f23), Integer.class); 1460 checkSecMultiKey(obj, "f24", toSet(obj.f24), CompositeKey.class); 1461 checkSecMultiKey(obj, "f25", toSet(obj.f25), CompositeKey.class); 1462 checkSecMultiKey(obj, "f27", toSet(obj.f27), MyEnum.class); 1463 checkSecMultiKey(obj, "f28", toSet(obj.f28), MyEnum.class); 1464 checkSecMultiKey(obj, "f42", toSet(obj.f42), MyEnumCSM.class); 1465 checkSecMultiKey(obj, "f43", toSet(obj.f43), MyEnumCSM.class); 1466 1467 nullifySecKey(obj, "f8", obj.f8, String.class); 1468 nullifySecKey(obj, "f9", obj.f9, BigInteger.class); 1469 nullifySecKey(obj, "f10", obj.f10, BigDecimal.class); 1470 nullifySecKey(obj, "f11", obj.f11, Date.class); 1471 nullifySecKey(obj, "f12", obj.f12, Boolean.class); 1472 nullifySecKey(obj, "f13", obj.f13, Character.class); 1473 nullifySecKey(obj, "f14", obj.f14, Byte.class); 1474 nullifySecKey(obj, "f15", obj.f15, Short.class); 1475 nullifySecKey(obj, "f16", obj.f16, Integer.class); 1476 nullifySecKey(obj, "f17", obj.f17, Long.class); 1477 nullifySecKey(obj, "f18", obj.f18, Float.class); 1478 nullifySecKey(obj, "f19", obj.f19, Double.class); 1479 nullifySecKey(obj, "f20", obj.f20, CompositeKey.class); 1480 nullifySecKey(obj, "f26", obj.f26, MyEnum.class); 1481 nullifySecKey(obj, "f41", obj.f41, MyEnumCSM.class); 1482 1483 nullifySecMultiKey(obj, "f21", obj.f21, Integer.class); 1484 nullifySecMultiKey(obj, "f22", obj.f22, Integer.class); 1485 nullifySecMultiKey(obj, "f23", obj.f23, Integer.class); 1486 nullifySecMultiKey(obj, "f24", obj.f24, CompositeKey.class); 1487 nullifySecMultiKey(obj, "f25", obj.f25, CompositeKey.class); 1488 nullifySecMultiKey(obj, "f27", obj.f27, MyEnum.class); 1489 nullifySecMultiKey(obj, "f28", obj.f28, MyEnum.class); 1490 nullifySecMultiKey(obj, "f42", obj.f42, MyEnumCSM.class); 1491 nullifySecMultiKey(obj, "f43", obj.f43, MyEnumCSM.class); 1492 1493 nullifySecKey(obj, "f31", obj.f31, Date.class); 1494 nullifySecKey(obj, "f32", obj.f32, Boolean.class); 1495 nullifySecKey(obj, "f33", obj.f33, Character.class); 1496 nullifySecKey(obj, "f34", obj.f34, Byte.class); 1497 nullifySecKey(obj, "f35", obj.f35, Short.class); 1498 nullifySecKey(obj, "f36", obj.f36, Integer.class); 1499 nullifySecKey(obj, "f37", obj.f37, Long.class); 1500 nullifySecKey(obj, "f38", obj.f38, Float.class); 1501 nullifySecKey(obj, "f39", obj.f39, Double.class); 1502 nullifySecKey(obj, "f40", obj.f40, CompositeKey.class); 1503 1504 close(); 1505 } 1506 toSet(int[] a)1507 static Set toSet(int[] a) { 1508 Set set = new HashSet(); 1509 for (int i : a) { 1510 set.add(i); 1511 } 1512 return set; 1513 } 1514 toSet(Object[] a)1515 static Set toSet(Object[] a) { 1516 return new HashSet(Arrays.asList(a)); 1517 } 1518 toSet(Set s)1519 static Set toSet(Set s) { 1520 return s; 1521 } 1522 1523 @Entity 1524 static class SecKeys implements MyEntity { 1525 1526 @PrimaryKey 1527 long id; 1528 1529 @SecondaryKey(relate=MANY_TO_ONE) 1530 private final boolean f0 = false; 1531 private final boolean g0 = false; 1532 1533 @SecondaryKey(relate=MANY_TO_ONE) 1534 private final char f1 = '1'; 1535 private final char g1 = '1'; 1536 1537 @SecondaryKey(relate=MANY_TO_ONE) 1538 private final byte f2 = 2; 1539 private final byte g2 = 2; 1540 1541 @SecondaryKey(relate=MANY_TO_ONE) 1542 private final short f3 = 3; 1543 private final short g3 = 3; 1544 1545 @SecondaryKey(relate=MANY_TO_ONE) 1546 private final int f4 = 4; 1547 private final int g4 = 4; 1548 1549 @SecondaryKey(relate=MANY_TO_ONE) 1550 private final long f5 = 5; 1551 private final long g5 = 5; 1552 1553 @SecondaryKey(relate=MANY_TO_ONE) 1554 private final float f6 = 6.6f; 1555 private final float g6 = 6.6f; 1556 1557 @SecondaryKey(relate=MANY_TO_ONE) 1558 private final double f7 = 7.7; 1559 private final double g7 = 7.7; 1560 1561 @SecondaryKey(relate=MANY_TO_ONE) 1562 private final String f8 = "8"; 1563 private final String g8 = "8"; 1564 1565 @SecondaryKey(relate=MANY_TO_ONE) 1566 private BigInteger f9; 1567 private BigInteger g9; 1568 1569 @SecondaryKey(relate=MANY_TO_ONE) 1570 private BigDecimal f10; 1571 private BigDecimal g10; 1572 1573 @SecondaryKey(relate=MANY_TO_ONE) 1574 private final Date f11 = new Date(11); 1575 private final Date g11 = new Date(11); 1576 1577 @SecondaryKey(relate=MANY_TO_ONE) 1578 private final Boolean f12 = true; 1579 private final Boolean g12 = true; 1580 1581 @SecondaryKey(relate=MANY_TO_ONE) 1582 private final Character f13 = '3'; 1583 private final Character g13 = '3'; 1584 1585 @SecondaryKey(relate=MANY_TO_ONE) 1586 private final Byte f14 = 14; 1587 private final Byte g14 = 14; 1588 1589 @SecondaryKey(relate=MANY_TO_ONE) 1590 private final Short f15 = 15; 1591 private final Short g15 = 15; 1592 1593 @SecondaryKey(relate=MANY_TO_ONE) 1594 private final Integer f16 = 16; 1595 private final Integer g16 = 16; 1596 1597 @SecondaryKey(relate=MANY_TO_ONE) 1598 private final Long f17= 17L; 1599 private final Long g17= 17L; 1600 1601 @SecondaryKey(relate=MANY_TO_ONE) 1602 private final Float f18 = 18.18f; 1603 private final Float g18 = 18.18f; 1604 1605 @SecondaryKey(relate=MANY_TO_ONE) 1606 private final Double f19 = 19.19; 1607 private final Double g19 = 19.19; 1608 1609 @SecondaryKey(relate=MANY_TO_ONE) 1610 private final CompositeKey f20 = 1611 new CompositeKey(20, 20L, "20", BigInteger.valueOf(20), 1612 MyEnum.ONE, MyEnumCSM.A, 1613 BigDecimal.valueOf(123.123)); 1614 private final CompositeKey g20 = 1615 new CompositeKey(20, 20L, "20", BigInteger.valueOf(20), 1616 MyEnum.TWO, MyEnumCSM.B, 1617 BigDecimal.valueOf(123.123)); 1618 1619 private static int[] arrayOfInt = { 100, 101, 102 }; 1620 1621 private static Integer[] arrayOfInteger = { 100, 101, 102 }; 1622 1623 private static CompositeKey[] arrayOfCompositeKey = { 1624 new CompositeKey(100, 100L, "100", BigInteger.valueOf(100), 1625 MyEnum.ONE, MyEnumCSM.A, 1626 BigDecimal.valueOf(123.123)), 1627 new CompositeKey(101, 101L, "101", BigInteger.valueOf(101), 1628 MyEnum.TWO, MyEnumCSM.B, 1629 BigDecimal.valueOf(123.123)), 1630 new CompositeKey(102, 102L, "102", BigInteger.valueOf(102), 1631 MyEnum.TWO, MyEnumCSM.B, 1632 BigDecimal.valueOf(123.123)), 1633 }; 1634 1635 private static MyEnum[] arrayOfEnum = 1636 new MyEnum[] { MyEnum.ONE, MyEnum.TWO }; 1637 1638 private static MyEnumCSM[] arrayOfEnumCSM = 1639 new MyEnumCSM[] { MyEnumCSM.A, MyEnumCSM.B }; 1640 1641 @SecondaryKey(relate=ONE_TO_MANY) 1642 private final int[] f21 = arrayOfInt; 1643 private final int[] g21 = f21; 1644 1645 @SecondaryKey(relate=ONE_TO_MANY) 1646 private final Integer[] f22 = arrayOfInteger; 1647 private final Integer[] g22 = f22; 1648 1649 @SecondaryKey(relate=ONE_TO_MANY) 1650 private final Set<Integer> f23 = toSet(arrayOfInteger); 1651 private final Set<Integer> g23 = f23; 1652 1653 @SecondaryKey(relate=ONE_TO_MANY) 1654 private final CompositeKey[] f24 = arrayOfCompositeKey; 1655 private final CompositeKey[] g24 = f24; 1656 1657 @SecondaryKey(relate=ONE_TO_MANY) 1658 private final Set<CompositeKey> f25 = toSet(arrayOfCompositeKey); 1659 private final Set<CompositeKey> g25 = f25; 1660 1661 @SecondaryKey(relate=MANY_TO_ONE) 1662 private final MyEnum f26 = MyEnum.TWO; 1663 private final MyEnum g26 = f26; 1664 1665 @SecondaryKey(relate=ONE_TO_MANY) 1666 private final MyEnum[] f27 = arrayOfEnum; 1667 private final MyEnum[] g27 = f27; 1668 1669 @SecondaryKey(relate=ONE_TO_MANY) 1670 private final Set<MyEnum> f28 = toSet(arrayOfEnum); 1671 private final Set<MyEnum> g28 = f28; 1672 1673 @SecondaryKey(relate=MANY_TO_ONE) 1674 private final MyEnumCSM f41 = MyEnumCSM.B; 1675 private final MyEnumCSM g41 = f41; 1676 1677 @SecondaryKey(relate=ONE_TO_MANY) 1678 private final MyEnumCSM[] f42 = arrayOfEnumCSM; 1679 private final MyEnumCSM[] g42 = f42; 1680 1681 @SecondaryKey(relate=ONE_TO_MANY) 1682 private final Set<MyEnumCSM> f43 = toSet(arrayOfEnumCSM); 1683 private final Set<MyEnumCSM> g43 = f43; 1684 1685 /* Repeated key values to test shared references. */ 1686 1687 @SecondaryKey(relate=MANY_TO_ONE) 1688 private final Date f31 = f11; 1689 1690 @SecondaryKey(relate=MANY_TO_ONE) 1691 private final Boolean f32 = f12; 1692 1693 @SecondaryKey(relate=MANY_TO_ONE) 1694 private final Character f33 = f13; 1695 1696 @SecondaryKey(relate=MANY_TO_ONE) 1697 private final Byte f34 = f14; 1698 1699 @SecondaryKey(relate=MANY_TO_ONE) 1700 private final Short f35 = f15; 1701 1702 @SecondaryKey(relate=MANY_TO_ONE) 1703 private final Integer f36 = f16; 1704 1705 @SecondaryKey(relate=MANY_TO_ONE) 1706 private final Long f37= f17; 1707 1708 @SecondaryKey(relate=MANY_TO_ONE) 1709 private final Float f38 = f18; 1710 1711 @SecondaryKey(relate=MANY_TO_ONE) 1712 private final Double f39 = f19; 1713 1714 @SecondaryKey(relate=MANY_TO_ONE) 1715 private final CompositeKey f40 = f20; 1716 getPriKeyObject()1717 public Object getPriKeyObject() { 1718 return id; 1719 } 1720 validate(Object other)1721 public void validate(Object other) { 1722 SecKeys o = (SecKeys) other; 1723 TestCase.assertEquals(id, o.id); 1724 1725 TestCase.assertEquals(f0, o.f0); 1726 TestCase.assertEquals(f1, o.f1); 1727 TestCase.assertEquals(f2, o.f2); 1728 TestCase.assertEquals(f3, o.f3); 1729 TestCase.assertEquals(f4, o.f4); 1730 TestCase.assertEquals(f5, o.f5); 1731 TestCase.assertEquals(f6, o.f6); 1732 TestCase.assertEquals(f7, o.f7); 1733 TestCase.assertEquals(f8, o.f8); 1734 TestCase.assertEquals(f9, o.f9); 1735 TestCase.assertEquals(f10, o.f10); 1736 TestCase.assertEquals(f11, o.f11); 1737 TestCase.assertEquals(f12, o.f12); 1738 TestCase.assertEquals(f13, o.f13); 1739 TestCase.assertEquals(f14, o.f14); 1740 TestCase.assertEquals(f15, o.f15); 1741 TestCase.assertEquals(f16, o.f16); 1742 TestCase.assertEquals(f17, o.f17); 1743 TestCase.assertEquals(f18, o.f18); 1744 TestCase.assertEquals(f19, o.f19); 1745 TestCase.assertEquals(f20, o.f20); 1746 TestCase.assertTrue(Arrays.equals(f21, o.f21)); 1747 TestCase.assertTrue(Arrays.equals(f22, o.f22)); 1748 TestCase.assertEquals(f23, o.f23); 1749 TestCase.assertTrue(Arrays.equals(f24, o.f24)); 1750 TestCase.assertEquals(f25, o.f25); 1751 TestCase.assertEquals(f26, o.f26); 1752 TestCase.assertTrue(Arrays.equals(f27, o.f27)); 1753 TestCase.assertEquals(f28, o.f28); 1754 TestCase.assertEquals(f41, o.f41); 1755 TestCase.assertTrue(Arrays.equals(f42, o.f42)); 1756 TestCase.assertEquals(f43, o.f43); 1757 1758 TestCase.assertEquals(g0, o.g0); 1759 TestCase.assertEquals(g1, o.g1); 1760 TestCase.assertEquals(g2, o.g2); 1761 TestCase.assertEquals(g3, o.g3); 1762 TestCase.assertEquals(g4, o.g4); 1763 TestCase.assertEquals(g5, o.g5); 1764 TestCase.assertEquals(g6, o.g6); 1765 TestCase.assertEquals(g7, o.g7); 1766 TestCase.assertEquals(g8, o.g8); 1767 TestCase.assertEquals(g9, o.g9); 1768 TestCase.assertEquals(g10, o.g10); 1769 TestCase.assertEquals(g11, o.g11); 1770 TestCase.assertEquals(g12, o.g12); 1771 TestCase.assertEquals(g13, o.g13); 1772 TestCase.assertEquals(g14, o.g14); 1773 TestCase.assertEquals(g15, o.g15); 1774 TestCase.assertEquals(g16, o.g16); 1775 TestCase.assertEquals(g17, o.g17); 1776 TestCase.assertEquals(g18, o.g18); 1777 TestCase.assertEquals(g19, o.g19); 1778 TestCase.assertEquals(g20, o.g20); 1779 TestCase.assertTrue(Arrays.equals(g21, o.g21)); 1780 TestCase.assertTrue(Arrays.equals(g22, o.g22)); 1781 TestCase.assertEquals(g23, o.g23); 1782 TestCase.assertTrue(Arrays.equals(g24, o.g24)); 1783 TestCase.assertEquals(g25, o.g25); 1784 TestCase.assertEquals(g26, o.g26); 1785 TestCase.assertTrue(Arrays.equals(g27, o.g27)); 1786 TestCase.assertEquals(g28, o.g28); 1787 TestCase.assertEquals(g41, o.g41); 1788 TestCase.assertTrue(Arrays.equals(g42, o.g42)); 1789 TestCase.assertEquals(g43, o.g43); 1790 1791 TestCase.assertEquals(f31, o.f31); 1792 TestCase.assertEquals(f32, o.f32); 1793 TestCase.assertEquals(f33, o.f33); 1794 TestCase.assertEquals(f34, o.f34); 1795 TestCase.assertEquals(f35, o.f35); 1796 TestCase.assertEquals(f36, o.f36); 1797 TestCase.assertEquals(f37, o.f37); 1798 TestCase.assertEquals(f38, o.f38); 1799 TestCase.assertEquals(f39, o.f39); 1800 TestCase.assertEquals(f40, o.f40); 1801 1802 checkSameIfNonNull(o.f31, o.f11); 1803 checkSameIfNonNull(o.f32, o.f12); 1804 checkSameIfNonNull(o.f33, o.f13); 1805 checkSameIfNonNull(o.f34, o.f14); 1806 checkSameIfNonNull(o.f35, o.f15); 1807 checkSameIfNonNull(o.f36, o.f16); 1808 checkSameIfNonNull(o.f37, o.f17); 1809 checkSameIfNonNull(o.f38, o.f18); 1810 checkSameIfNonNull(o.f39, o.f19); 1811 checkSameIfNonNull(o.f40, o.f20); 1812 } 1813 } 1814 1815 @Test testSecKeyRefToPriKey()1816 public void testSecKeyRefToPriKey() 1817 throws FileNotFoundException, DatabaseException { 1818 1819 open(); 1820 1821 SecKeyRefToPriKey obj = new SecKeyRefToPriKey(); 1822 checkEntity(SecKeyRefToPriKey.class, obj); 1823 1824 checkMetadata(SecKeyRefToPriKey.class.getName(), new String[][] { 1825 {"priKey", "java.lang.String"}, 1826 {"secKey1", "java.lang.String"}, 1827 {"secKey2", String[].class.getName()}, 1828 {"secKey3", Set.class.getName()}, 1829 }, 1830 0 /*priKeyIndex*/, null); 1831 1832 checkSecKey(obj, "secKey1", obj.secKey1, String.class); 1833 checkSecMultiKey(obj, "secKey2", toSet(obj.secKey2), String.class); 1834 checkSecMultiKey(obj, "secKey3", toSet(obj.secKey3), String.class); 1835 1836 close(); 1837 } 1838 1839 @Entity 1840 static class SecKeyRefToPriKey implements MyEntity { 1841 1842 @PrimaryKey 1843 private final String priKey; 1844 1845 @SecondaryKey(relate=ONE_TO_ONE) 1846 private final String secKey1; 1847 1848 @SecondaryKey(relate=ONE_TO_MANY) 1849 private final String[] secKey2; 1850 1851 @SecondaryKey(relate=ONE_TO_MANY) 1852 private final Set<String> secKey3 = new HashSet<String>(); 1853 SecKeyRefToPriKey()1854 private SecKeyRefToPriKey() { 1855 priKey = "sharedValue"; 1856 secKey1 = priKey; 1857 secKey2 = new String[] { priKey }; 1858 secKey3.add(priKey); 1859 } 1860 getPriKeyObject()1861 public Object getPriKeyObject() { 1862 return priKey; 1863 } 1864 validate(Object other)1865 public void validate(Object other) { 1866 SecKeyRefToPriKey o = (SecKeyRefToPriKey) other; 1867 TestCase.assertEquals(priKey, o.priKey); 1868 TestCase.assertNotNull(o.secKey1); 1869 TestCase.assertEquals(1, o.secKey2.length); 1870 TestCase.assertEquals(1, o.secKey3.size()); 1871 } 1872 } 1873 1874 @Test testSecKeyInSuperclass()1875 public void testSecKeyInSuperclass() 1876 throws FileNotFoundException, DatabaseException { 1877 1878 open(); 1879 1880 SecKeyInSuperclassEntity obj = new SecKeyInSuperclassEntity(); 1881 checkEntity(SecKeyInSuperclassEntity.class, obj); 1882 1883 checkMetadata(SecKeyInSuperclass.class.getName(), 1884 new String[][] { 1885 {"priKey", "java.lang.String"}, 1886 {"secKey1", String.class.getName()}, 1887 }, 1888 0/*priKeyIndex*/, null); 1889 1890 checkMetadata(SecKeyInSuperclassEntity.class.getName(), 1891 new String[][] { 1892 {"secKey2", "java.lang.String"}, 1893 }, 1894 -1 /*priKeyIndex*/, SecKeyInSuperclass.class.getName()); 1895 1896 checkSecKey 1897 (obj, SecKeyInSuperclassEntity.class, "secKey1", obj.secKey1, 1898 String.class); 1899 checkSecKey 1900 (obj, SecKeyInSuperclassEntity.class, "secKey2", obj.secKey2, 1901 String.class); 1902 1903 close(); 1904 } 1905 1906 @Persistent 1907 static class SecKeyInSuperclass implements MyEntity { 1908 1909 @PrimaryKey 1910 String priKey = "1"; 1911 1912 @SecondaryKey(relate=ONE_TO_ONE) 1913 String secKey1 = "1"; 1914 getPriKeyObject()1915 public Object getPriKeyObject() { 1916 return priKey; 1917 } 1918 validate(Object other)1919 public void validate(Object other) { 1920 SecKeyInSuperclass o = (SecKeyInSuperclass) other; 1921 TestCase.assertEquals(secKey1, o.secKey1); 1922 } 1923 } 1924 1925 @Entity 1926 static class SecKeyInSuperclassEntity extends SecKeyInSuperclass { 1927 1928 @SecondaryKey(relate=ONE_TO_ONE) 1929 String secKey2 = "2"; 1930 1931 @Override validate(Object other)1932 public void validate(Object other) { 1933 super.validate(other); 1934 SecKeyInSuperclassEntity o = (SecKeyInSuperclassEntity) other; 1935 TestCase.assertEquals(priKey, o.priKey); 1936 TestCase.assertEquals(secKey2, o.secKey2); 1937 } 1938 } 1939 1940 @Test testSecKeyInSubclass()1941 public void testSecKeyInSubclass() 1942 throws FileNotFoundException, DatabaseException { 1943 1944 open(); 1945 1946 SecKeyInSubclass obj = new SecKeyInSubclass(); 1947 checkEntity(SecKeyInSubclassEntity.class, obj); 1948 1949 checkMetadata(SecKeyInSubclassEntity.class.getName(), new String[][] { 1950 {"priKey", "java.lang.String"}, 1951 {"secKey1", "java.lang.String"}, 1952 }, 1953 0 /*priKeyIndex*/, null); 1954 1955 checkMetadata(SecKeyInSubclass.class.getName(), new String[][] { 1956 {"secKey2", String.class.getName()}, 1957 }, 1958 -1 /*priKeyIndex*/, 1959 SecKeyInSubclassEntity.class.getName()); 1960 1961 checkSecKey 1962 (obj, SecKeyInSubclassEntity.class, "secKey1", obj.secKey1, 1963 String.class); 1964 checkSecKey 1965 (obj, SecKeyInSubclassEntity.class, "secKey2", obj.secKey2, 1966 String.class); 1967 1968 close(); 1969 } 1970 1971 @Entity 1972 static class SecKeyInSubclassEntity implements MyEntity { 1973 1974 @PrimaryKey 1975 String priKey = "1"; 1976 1977 @SecondaryKey(relate=ONE_TO_ONE) 1978 String secKey1; 1979 getPriKeyObject()1980 public Object getPriKeyObject() { 1981 return priKey; 1982 } 1983 validate(Object other)1984 public void validate(Object other) { 1985 SecKeyInSubclassEntity o = (SecKeyInSubclassEntity) other; 1986 TestCase.assertEquals(priKey, o.priKey); 1987 TestCase.assertEquals(secKey1, o.secKey1); 1988 } 1989 } 1990 1991 @Persistent 1992 static class SecKeyInSubclass extends SecKeyInSubclassEntity { 1993 1994 @SecondaryKey(relate=ONE_TO_ONE) 1995 String secKey2 = "2"; 1996 1997 @Override validate(Object other)1998 public void validate(Object other) { 1999 super.validate(other); 2000 SecKeyInSubclass o = (SecKeyInSubclass) other; 2001 TestCase.assertEquals(secKey2, o.secKey2); 2002 } 2003 } 2004 checkSameIfNonNull(Object o1, Object o2)2005 private static void checkSameIfNonNull(Object o1, Object o2) { 2006 if (o1 != null && o2 != null) { 2007 assertSame(o1, o2); 2008 } 2009 } 2010 checkEntity(Class entityCls, MyEntity entity)2011 private void checkEntity(Class entityCls, MyEntity entity) { 2012 Object priKey = entity.getPriKeyObject(); 2013 Class keyCls = priKey.getClass(); 2014 DatabaseEntry keyEntry2 = new DatabaseEntry(); 2015 DatabaseEntry dataEntry2 = new DatabaseEntry(); 2016 2017 /* Write object, read it back and validate (compare) it. */ 2018 PersistEntityBinding entityBinding = 2019 new PersistEntityBinding(catalog, entityCls.getName(), false); 2020 entityBinding.objectToData(entity, dataEntry); 2021 entityBinding.objectToKey(entity, keyEntry); 2022 Object entity2 = entityBinding.entryToObject(keyEntry, dataEntry); 2023 entity.validate(entity2); 2024 2025 /* Read back the primary key and validate it. */ 2026 PersistKeyBinding keyBinding = 2027 new PersistKeyBinding(catalog, keyCls.getName(), false); 2028 Object priKey2 = keyBinding.entryToObject(keyEntry); 2029 assertEquals(priKey, priKey2); 2030 keyBinding.objectToEntry(priKey2, keyEntry2); 2031 assertEquals(keyEntry, keyEntry2); 2032 2033 /* Check raw entity binding. */ 2034 PersistEntityBinding rawEntityBinding = 2035 new PersistEntityBinding(catalog, entityCls.getName(), true); 2036 RawObject rawEntity = 2037 (RawObject) rawEntityBinding.entryToObject(keyEntry, dataEntry); 2038 rawEntityBinding.objectToKey(rawEntity, keyEntry2); 2039 rawEntityBinding.objectToData(rawEntity, dataEntry2); 2040 entity2 = entityBinding.entryToObject(keyEntry2, dataEntry2); 2041 entity.validate(entity2); 2042 RawObject rawEntity2 = 2043 (RawObject) rawEntityBinding.entryToObject(keyEntry2, dataEntry2); 2044 assertEquals(rawEntity, rawEntity2); 2045 assertEquals(dataEntry, dataEntry2); 2046 assertEquals(keyEntry, keyEntry2); 2047 2048 /* Check that raw entity can be converted to a regular entity. */ 2049 try { 2050 entity2 = catalog.convertRawObject(rawEntity, null); 2051 } catch (RefreshException e) { 2052 fail(e.toString()); 2053 } 2054 entity.validate(entity2); 2055 2056 /* Check raw key binding. */ 2057 PersistKeyBinding rawKeyBinding = 2058 new PersistKeyBinding(catalog, keyCls.getName(), true); 2059 Object rawKey = rawKeyBinding.entryToObject(keyEntry); 2060 rawKeyBinding.objectToEntry(rawKey, keyEntry2); 2061 priKey2 = keyBinding.entryToObject(keyEntry2); 2062 assertEquals(priKey, priKey2); 2063 assertEquals(keyEntry, keyEntry2); 2064 } 2065 checkSecKey(MyEntity entity, String keyName, Object keyValue, Class keyCls)2066 private void checkSecKey(MyEntity entity, 2067 String keyName, 2068 Object keyValue, 2069 Class keyCls) 2070 throws DatabaseException { 2071 2072 checkSecKey(entity, entity.getClass(), keyName, keyValue, keyCls); 2073 } 2074 checkSecKey(MyEntity entity, Class entityCls, String keyName, Object keyValue, Class keyCls)2075 private void checkSecKey(MyEntity entity, 2076 Class entityCls, 2077 String keyName, 2078 Object keyValue, 2079 Class keyCls) 2080 throws DatabaseException { 2081 2082 /* Get entity metadata. */ 2083 EntityMetadata entityMeta = 2084 model.getEntityMetadata(entityCls.getName()); 2085 assertNotNull(entityMeta); 2086 2087 /* Get secondary key metadata. */ 2088 SecondaryKeyMetadata secKeyMeta = 2089 entityMeta.getSecondaryKeys().get(keyName); 2090 assertNotNull(secKeyMeta); 2091 2092 /* Create key creator/nullifier. */ 2093 SecondaryKeyCreator keyCreator = new PersistKeyCreator 2094 (catalog, entityMeta, keyCls.getName(), secKeyMeta, 2095 false /*rawAcess*/); 2096 2097 /* Convert entity to bytes. */ 2098 PersistEntityBinding entityBinding = 2099 new PersistEntityBinding(catalog, entityCls.getName(), false); 2100 entityBinding.objectToData(entity, dataEntry); 2101 entityBinding.objectToKey(entity, keyEntry); 2102 2103 /* Extract secondary key bytes from entity bytes. */ 2104 DatabaseEntry secKeyEntry = new DatabaseEntry(); 2105 boolean isKeyPresent = keyCreator.createSecondaryKey 2106 (null, keyEntry, dataEntry, secKeyEntry); 2107 assertEquals(keyValue != null, isKeyPresent); 2108 2109 /* Convert secondary key bytes back to an object. */ 2110 PersistKeyBinding keyBinding = 2111 new PersistKeyBinding(catalog, keyCls.getName(), false); 2112 if (isKeyPresent) { 2113 Object keyValue2 = keyBinding.entryToObject(secKeyEntry); 2114 assertEquals(keyValue, keyValue2); 2115 DatabaseEntry secKeyEntry2 = new DatabaseEntry(); 2116 keyBinding.objectToEntry(keyValue2, secKeyEntry2); 2117 assertEquals(secKeyEntry, secKeyEntry2); 2118 } 2119 } 2120 checkSecMultiKey(MyEntity entity, String keyName, Set keyValues, Class keyCls)2121 private void checkSecMultiKey(MyEntity entity, 2122 String keyName, 2123 Set keyValues, 2124 Class keyCls) 2125 throws DatabaseException { 2126 2127 /* Get entity metadata. */ 2128 Class entityCls = entity.getClass(); 2129 EntityMetadata entityMeta = 2130 model.getEntityMetadata(entityCls.getName()); 2131 assertNotNull(entityMeta); 2132 2133 /* Get secondary key metadata. */ 2134 SecondaryKeyMetadata secKeyMeta = 2135 entityMeta.getSecondaryKeys().get(keyName); 2136 assertNotNull(secKeyMeta); 2137 2138 /* Create key creator/nullifier. */ 2139 SecondaryMultiKeyCreator keyCreator = new PersistKeyCreator 2140 (catalog, entityMeta, keyCls.getName(), secKeyMeta, 2141 false /*rawAcess*/); 2142 2143 /* Convert entity to bytes. */ 2144 PersistEntityBinding entityBinding = 2145 new PersistEntityBinding(catalog, entityCls.getName(), false); 2146 entityBinding.objectToData(entity, dataEntry); 2147 entityBinding.objectToKey(entity, keyEntry); 2148 2149 /* Extract secondary key bytes from entity bytes. */ 2150 Set<DatabaseEntry> results = new HashSet<DatabaseEntry>(); 2151 keyCreator.createSecondaryKeys 2152 (null, keyEntry, dataEntry, results); 2153 assertEquals(keyValues.size(), results.size()); 2154 2155 /* Convert secondary key bytes back to objects. */ 2156 PersistKeyBinding keyBinding = 2157 new PersistKeyBinding(catalog, keyCls.getName(), false); 2158 Set keyValues2 = new HashSet(); 2159 for (DatabaseEntry secKeyEntry : results) { 2160 Object keyValue2 = keyBinding.entryToObject(secKeyEntry); 2161 keyValues2.add(keyValue2); 2162 } 2163 assertEquals(keyValues, keyValues2); 2164 } 2165 nullifySecKey(MyEntity entity, String keyName, Object keyValue, Class keyCls)2166 private void nullifySecKey(MyEntity entity, 2167 String keyName, 2168 Object keyValue, 2169 Class keyCls) 2170 throws DatabaseException { 2171 2172 /* Get entity metadata. */ 2173 Class entityCls = entity.getClass(); 2174 EntityMetadata entityMeta = 2175 model.getEntityMetadata(entityCls.getName()); 2176 assertNotNull(entityMeta); 2177 2178 /* Get secondary key metadata. */ 2179 SecondaryKeyMetadata secKeyMeta = 2180 entityMeta.getSecondaryKeys().get(keyName); 2181 assertNotNull(secKeyMeta); 2182 2183 /* Create key creator/nullifier. */ 2184 ForeignMultiKeyNullifier keyNullifier = new PersistKeyCreator 2185 (catalog, entityMeta, keyCls.getName(), secKeyMeta, 2186 false /*rawAcess*/); 2187 2188 /* Convert entity to bytes. */ 2189 PersistEntityBinding entityBinding = 2190 new PersistEntityBinding(catalog, entityCls.getName(), false); 2191 entityBinding.objectToData(entity, dataEntry); 2192 entityBinding.objectToKey(entity, keyEntry); 2193 2194 /* Convert secondary key to bytes. */ 2195 PersistKeyBinding keyBinding = 2196 new PersistKeyBinding(catalog, keyCls.getName(), false); 2197 DatabaseEntry secKeyEntry = new DatabaseEntry(); 2198 if (keyValue != null) { 2199 keyBinding.objectToEntry(keyValue, secKeyEntry); 2200 } 2201 2202 /* Nullify secondary key bytes within entity bytes. */ 2203 boolean isKeyPresent = keyNullifier.nullifyForeignKey 2204 (null, keyEntry, dataEntry, secKeyEntry); 2205 assertEquals(keyValue != null, isKeyPresent); 2206 2207 /* Convert modified entity bytes back to an entity. */ 2208 Object entity2 = entityBinding.entryToObject(keyEntry, dataEntry); 2209 setFieldToNull(entity, keyName); 2210 entity.validate(entity2); 2211 2212 /* Do a full check after nullifying it. */ 2213 checkSecKey(entity, keyName, null, keyCls); 2214 } 2215 nullifySecMultiKey(MyEntity entity, String keyName, Object keyValue, Class keyCls)2216 private void nullifySecMultiKey(MyEntity entity, 2217 String keyName, 2218 Object keyValue, 2219 Class keyCls) 2220 throws DatabaseException { 2221 2222 /* Get entity metadata. */ 2223 Class entityCls = entity.getClass(); 2224 EntityMetadata entityMeta = 2225 model.getEntityMetadata(entityCls.getName()); 2226 assertNotNull(entityMeta); 2227 2228 /* Get secondary key metadata. */ 2229 SecondaryKeyMetadata secKeyMeta = 2230 entityMeta.getSecondaryKeys().get(keyName); 2231 assertNotNull(secKeyMeta); 2232 2233 /* Create key creator/nullifier. */ 2234 ForeignMultiKeyNullifier keyNullifier = new PersistKeyCreator 2235 (catalog, entityMeta, keyCls.getName(), secKeyMeta, 2236 false /*rawAcess*/); 2237 2238 /* Convert entity to bytes. */ 2239 PersistEntityBinding entityBinding = 2240 new PersistEntityBinding(catalog, entityCls.getName(), false); 2241 entityBinding.objectToData(entity, dataEntry); 2242 entityBinding.objectToKey(entity, keyEntry); 2243 2244 /* Get secondary key binding. */ 2245 PersistKeyBinding keyBinding = 2246 new PersistKeyBinding(catalog, keyCls.getName(), false); 2247 DatabaseEntry secKeyEntry = new DatabaseEntry(); 2248 2249 /* Nullify one key value at a time until all of them are gone. */ 2250 while (true) { 2251 Object fieldObj = getField(entity, keyName); 2252 fieldObj = nullifyFirstElement(fieldObj, keyBinding, secKeyEntry); 2253 if (fieldObj == null) { 2254 break; 2255 } 2256 setField(entity, keyName, fieldObj); 2257 2258 /* Nullify secondary key bytes within entity bytes. */ 2259 boolean isKeyPresent = keyNullifier.nullifyForeignKey 2260 (null, keyEntry, dataEntry, secKeyEntry); 2261 assertEquals(keyValue != null, isKeyPresent); 2262 2263 /* Convert modified entity bytes back to an entity. */ 2264 Object entity2 = entityBinding.entryToObject(keyEntry, dataEntry); 2265 entity.validate(entity2); 2266 2267 /* Do a full check after nullifying it. */ 2268 Set keyValues; 2269 if (fieldObj instanceof Set) { 2270 keyValues = (Set) fieldObj; 2271 } else if (fieldObj instanceof Object[]) { 2272 keyValues = toSet((Object[]) fieldObj); 2273 } else if (fieldObj instanceof int[]) { 2274 keyValues = toSet((int[]) fieldObj); 2275 } else { 2276 throw new IllegalStateException(fieldObj.getClass().getName()); 2277 } 2278 checkSecMultiKey(entity, keyName, keyValues, keyCls); 2279 } 2280 } 2281 2282 /** 2283 * Nullifies the first element of an array or collection object by removing 2284 * it from the array or collection. Returns the resulting array or 2285 * collection. Also outputs the removed element to the keyEntry using the 2286 * keyBinding. 2287 */ nullifyFirstElement(Object obj, EntryBinding keyBinding, DatabaseEntry keyEntry)2288 private Object nullifyFirstElement(Object obj, 2289 EntryBinding keyBinding, 2290 DatabaseEntry keyEntry) { 2291 if (obj instanceof Collection) { 2292 Iterator i = ((Collection) obj).iterator(); 2293 if (i.hasNext()) { 2294 Object elem = i.next(); 2295 i.remove(); 2296 keyBinding.objectToEntry(elem, keyEntry); 2297 return obj; 2298 } else { 2299 return null; 2300 } 2301 } else if (obj instanceof Object[]) { 2302 Object[] a1 = (Object[]) obj; 2303 if (a1.length > 0) { 2304 Object[] a2 = (Object[]) Array.newInstance 2305 (obj.getClass().getComponentType(), a1.length - 1); 2306 System.arraycopy(a1, 1, a2, 0, a2.length); 2307 keyBinding.objectToEntry(a1[0], keyEntry); 2308 return a2; 2309 } else { 2310 return null; 2311 } 2312 } else if (obj instanceof int[]) { 2313 int[] a1 = (int[]) obj; 2314 if (a1.length > 0) { 2315 int[] a2 = new int[a1.length - 1]; 2316 System.arraycopy(a1, 1, a2, 0, a2.length); 2317 keyBinding.objectToEntry(a1[0], keyEntry); 2318 return a2; 2319 } else { 2320 return null; 2321 } 2322 } else { 2323 throw new IllegalStateException(obj.getClass().getName()); 2324 } 2325 } 2326 checkMetadata(String clsName, String[][] nameTypePairs, int priKeyIndex, String superClsName)2327 private void checkMetadata(String clsName, 2328 String[][] nameTypePairs, 2329 int priKeyIndex, 2330 String superClsName) 2331 throws DatabaseException { 2332 2333 /* Check metadata/types against the live model. */ 2334 checkMetadata 2335 (catalog, model, clsName, nameTypePairs, priKeyIndex, 2336 superClsName); 2337 2338 /* 2339 * Open a catalog that uses the stored model. 2340 */ 2341 PersistCatalog storedCatalog = null; 2342 storedCatalog = new PersistCatalog 2343 (env, STORE_PREFIX, STORE_PREFIX + "catalog", new DatabaseConfig(), 2344 null, null, false /*useCurrentModel*/, null /*Store*/); 2345 EntityModel storedModel = storedCatalog.getResolvedModel(); 2346 2347 /* Check metadata/types against the stored catalog/model. */ 2348 checkMetadata 2349 (storedCatalog, storedModel, clsName, nameTypePairs, priKeyIndex, 2350 superClsName); 2351 2352 storedCatalog.close(); 2353 } 2354 checkMetadata(PersistCatalog checkCatalog, EntityModel checkModel, String clsName, String[][] nameTypePairs, int priKeyIndex, String superClsName)2355 private void checkMetadata(PersistCatalog checkCatalog, 2356 EntityModel checkModel, 2357 String clsName, 2358 String[][] nameTypePairs, 2359 int priKeyIndex, 2360 String superClsName) { 2361 ClassMetadata classMeta = checkModel.getClassMetadata(clsName); 2362 assertNotNull(clsName, classMeta); 2363 2364 PrimaryKeyMetadata priKeyMeta = classMeta.getPrimaryKey(); 2365 if (priKeyIndex >= 0) { 2366 assertNotNull(priKeyMeta); 2367 String fieldName = nameTypePairs[priKeyIndex][0]; 2368 String fieldType = nameTypePairs[priKeyIndex][1]; 2369 assertEquals(priKeyMeta.getName(), fieldName); 2370 assertEquals(priKeyMeta.getClassName(), fieldType); 2371 assertEquals(priKeyMeta.getDeclaringClassName(), clsName); 2372 assertNull(priKeyMeta.getSequenceName()); 2373 } else { 2374 assertNull(priKeyMeta); 2375 } 2376 2377 RawType type = checkCatalog.getFormat(clsName); 2378 assertNotNull(type); 2379 assertEquals(clsName, type.getClassName()); 2380 assertEquals(0, type.getVersion()); 2381 assertTrue(!type.isSimple()); 2382 assertTrue(!type.isPrimitive()); 2383 assertTrue(!type.isEnum()); 2384 assertNull(type.getEnumConstants()); 2385 assertTrue(!type.isArray()); 2386 assertEquals(0, type.getDimensions()); 2387 assertNull(type.getComponentType()); 2388 RawType superType = type.getSuperType(); 2389 if (superClsName != null) { 2390 assertNotNull(superType); 2391 assertEquals(superClsName, superType.getClassName()); 2392 } else { 2393 assertNull(superType); 2394 } 2395 2396 Map<String, RawField> fields = type.getFields(); 2397 assertNotNull(fields); 2398 2399 int nFields = nameTypePairs.length; 2400 assertEquals(nFields, fields.size()); 2401 2402 for (String[] pair : nameTypePairs) { 2403 String fieldName = pair[0]; 2404 String fieldType = pair[1]; 2405 Class fieldCls; 2406 try { 2407 fieldCls = checkCatalog.resolveClass(fieldType); 2408 } catch (ClassNotFoundException e) { 2409 fail(e.toString()); 2410 return; /* For compiler */ 2411 } 2412 RawField field = fields.get(fieldName); 2413 assertNotNull(field); 2414 assertEquals(fieldName, field.getName()); 2415 type = field.getType(); 2416 assertNotNull(type); 2417 int dim = getArrayDimensions(fieldType); 2418 while (dim > 0) { 2419 assertEquals(dim, type.getDimensions()); 2420 assertEquals(dim, getArrayDimensions(fieldType)); 2421 assertEquals(true, type.isArray()); 2422 assertEquals(fieldType, type.getClassName()); 2423 assertEquals(0, type.getVersion()); 2424 assertTrue(!type.isSimple()); 2425 assertTrue(!type.isPrimitive()); 2426 assertTrue(!type.isEnum()); 2427 assertNull(type.getEnumConstants()); 2428 fieldType = getArrayComponent(fieldType, dim); 2429 type = type.getComponentType(); 2430 assertNotNull(fieldType, type); 2431 dim -= 1; 2432 } 2433 assertEquals(fieldType, type.getClassName()); 2434 List<String> enums = getEnumConstants(fieldType); 2435 assertEquals(isSimpleType(fieldType), type.isSimple()); 2436 assertEquals(isPrimitiveType(fieldType), type.isPrimitive()); 2437 assertNull(type.getComponentType()); 2438 assertTrue(!type.isArray()); 2439 assertEquals(0, type.getDimensions()); 2440 if (enums != null) { 2441 assertTrue(type.isEnum()); 2442 assertEquals(enums, type.getEnumConstants()); 2443 assertNull(type.getSuperType()); 2444 } else { 2445 assertTrue(!type.isEnum()); 2446 assertNull(type.getEnumConstants()); 2447 } 2448 } 2449 } 2450 getEnumConstants(String clsName)2451 private List<String> getEnumConstants(String clsName) { 2452 if (isPrimitiveType(clsName)) { 2453 return null; 2454 } 2455 Class cls; 2456 try { 2457 cls = Class.forName(clsName); 2458 } catch (ClassNotFoundException e) { 2459 fail(e.toString()); 2460 return null; /* Never happens. */ 2461 } 2462 if (!cls.isEnum()) { 2463 return null; 2464 } 2465 List<String> enums = new ArrayList<String>(); 2466 Object[] vals = cls.getEnumConstants(); 2467 for (Object val : vals) { 2468 enums.add(val.toString()); 2469 } 2470 return enums; 2471 } 2472 getArrayComponent(String clsName, int dim)2473 private String getArrayComponent(String clsName, int dim) { 2474 clsName = clsName.substring(1); 2475 if (dim > 1) { 2476 return clsName; 2477 } 2478 if (clsName.charAt(0) == 'L' && 2479 clsName.charAt(clsName.length() - 1) == ';') { 2480 return clsName.substring(1, clsName.length() - 1); 2481 } 2482 if (clsName.length() != 1) { 2483 fail(); 2484 } 2485 switch (clsName.charAt(0)) { 2486 case 'Z': return "boolean"; 2487 case 'B': return "byte"; 2488 case 'C': return "char"; 2489 case 'D': return "double"; 2490 case 'F': return "float"; 2491 case 'I': return "int"; 2492 case 'J': return "long"; 2493 case 'S': return "short"; 2494 default: fail(); 2495 } 2496 return null; /* Should never happen. */ 2497 } 2498 getArrayDimensions(String clsName)2499 private static int getArrayDimensions(String clsName) { 2500 int i = 0; 2501 while (clsName.charAt(i) == '[') { 2502 i += 1; 2503 } 2504 return i; 2505 } 2506 isSimpleType(String clsName)2507 private static boolean isSimpleType(String clsName) { 2508 return isPrimitiveType(clsName) || 2509 clsName.equals("java.lang.Boolean") || 2510 clsName.equals("java.lang.Character") || 2511 clsName.equals("java.lang.Byte") || 2512 clsName.equals("java.lang.Short") || 2513 clsName.equals("java.lang.Integer") || 2514 clsName.equals("java.lang.Long") || 2515 clsName.equals("java.lang.Float") || 2516 clsName.equals("java.lang.Double") || 2517 clsName.equals("java.lang.String") || 2518 clsName.equals("java.math.BigInteger") || 2519 clsName.equals("java.math.BigDecimal") || 2520 clsName.equals("java.util.Date"); 2521 } 2522 isPrimitiveType(String clsName)2523 private static boolean isPrimitiveType(String clsName) { 2524 return clsName.equals("boolean") || 2525 clsName.equals("char") || 2526 clsName.equals("byte") || 2527 clsName.equals("short") || 2528 clsName.equals("int") || 2529 clsName.equals("long") || 2530 clsName.equals("float") || 2531 clsName.equals("double"); 2532 } 2533 2534 interface MyEntity { getPriKeyObject()2535 Object getPriKeyObject(); validate(Object other)2536 void validate(Object other); 2537 } 2538 nullOrEqual(Object o1, Object o2)2539 private static boolean nullOrEqual(Object o1, Object o2) { 2540 return (o1 != null) ? o1.equals(o2) : (o2 == null); 2541 } 2542 arrayToString(Object[] array)2543 private static String arrayToString(Object[] array) { 2544 StringBuilder buf = new StringBuilder(); 2545 buf.append('['); 2546 for (Object o : array) { 2547 if (o instanceof Object[]) { 2548 buf.append(arrayToString((Object[]) o)); 2549 } else { 2550 buf.append(o); 2551 } 2552 buf.append(','); 2553 } 2554 buf.append(']'); 2555 return buf.toString(); 2556 } 2557 setFieldToNull(Object obj, String fieldName)2558 private void setFieldToNull(Object obj, String fieldName) { 2559 try { 2560 Field field = obj.getClass().getDeclaredField(fieldName); 2561 field.setAccessible(true); 2562 field.set(obj, null); 2563 } catch (NoSuchFieldException e) { 2564 fail(e.toString()); 2565 } catch (IllegalAccessException e) { 2566 fail(e.toString()); 2567 } 2568 } 2569 setField(Object obj, String fieldName, Object fieldValue)2570 private void setField(Object obj, String fieldName, Object fieldValue) { 2571 try { 2572 Field field = obj.getClass().getDeclaredField(fieldName); 2573 field.setAccessible(true); 2574 field.set(obj, fieldValue); 2575 } catch (NoSuchFieldException e) { 2576 throw new IllegalStateException(e.toString()); 2577 } catch (IllegalAccessException e) { 2578 throw new IllegalStateException(e.toString()); 2579 } 2580 } 2581 getField(Object obj, String fieldName)2582 private Object getField(Object obj, String fieldName) { 2583 try { 2584 Field field = obj.getClass().getDeclaredField(fieldName); 2585 field.setAccessible(true); 2586 return field.get(obj); 2587 } catch (NoSuchFieldException e) { 2588 throw new IllegalStateException(e.toString()); 2589 } catch (IllegalAccessException e) { 2590 throw new IllegalStateException(e.toString()); 2591 } 2592 } 2593 } 2594