PageRenderTime 55ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/com/google/appengine/datanucleus/jdo/JDOOneToManyPolymorphicTestCase.java

http://datanucleus-appengine.googlecode.com/
Java | 1766 lines | 1488 code | 233 blank | 45 comment | 71 complexity | 89e8a951a15e466707cf5781702462f5 MD5 | raw file
Possible License(s): Apache-2.0
  1. /**********************************************************************
  2. Copyright (c) 2011 Google Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. **********************************************************************/
  13. package com.google.appengine.datanucleus.jdo;
  14. import com.google.appengine.api.datastore.DatastoreService;
  15. import com.google.appengine.api.datastore.DatastoreServiceConfig;
  16. import com.google.appengine.api.datastore.Entity;
  17. import com.google.appengine.api.datastore.EntityNotFoundException;
  18. import com.google.appengine.api.datastore.Key;
  19. import com.google.appengine.api.datastore.KeyFactory;
  20. import com.google.appengine.api.datastore.Query;
  21. import com.google.appengine.api.datastore.Transaction;
  22. import com.google.appengine.api.datastore.TransactionOptions;
  23. import com.google.appengine.datanucleus.DatastoreServiceFactoryInternal;
  24. import com.google.appengine.datanucleus.DatastoreServiceInterceptor;
  25. import com.google.appengine.datanucleus.PolymorphicTestUtils;
  26. import com.google.appengine.datanucleus.StorageVersion;
  27. import com.google.appengine.datanucleus.Utils;
  28. import com.google.appengine.datanucleus.Utils.Function;
  29. import com.google.appengine.datanucleus.test.jdo.BidirectionalSuperclassTableChildJDO;
  30. import com.google.appengine.datanucleus.test.jdo.UnidirectionalSuperclassTableChildJDO;
  31. import com.google.appengine.datanucleus.test.jdo.BidirectionalSuperclassTableChildJDO.BidirTop;
  32. import com.google.appengine.datanucleus.test.jdo.BidirectionalSuperclassTableChildJDO.BidirTopLongPk;
  33. import com.google.appengine.datanucleus.test.jdo.BidirectionalSuperclassTableChildJDO.BidirTopUnencodedStringPkJDO;
  34. import com.google.appengine.datanucleus.test.jdo.HasPolymorphicRelationsJDO.HasOneToManyJDO;
  35. import com.google.appengine.datanucleus.test.jdo.HasPolymorphicRelationsJDO.HasOneToManyKeyPkJDO;
  36. import com.google.appengine.datanucleus.test.jdo.HasPolymorphicRelationsJDO.HasOneToManyLongPkJDO;
  37. import com.google.appengine.datanucleus.test.jdo.HasPolymorphicRelationsJDO.HasOneToManyUnencodedStringPkJDO;
  38. import com.google.appengine.datanucleus.test.jdo.HasPolymorphicRelationsJDO.HasOneToManyWithOrderByJDO;
  39. import com.google.appengine.datanucleus.test.jdo.UnidirectionalSuperclassTableChildJDO.UnidirBottom;
  40. import com.google.appengine.datanucleus.test.jdo.UnidirectionalSuperclassTableChildJDO.UnidirMiddle;
  41. import com.google.appengine.datanucleus.test.jdo.UnidirectionalSuperclassTableChildJDO.UnidirTop;
  42. import com.google.appengine.datanucleus.test.jdo.UnidirectionalSuperclassTableChildJDO.UnidirTopWithIndexColumn;
  43. import org.easymock.EasyMock;
  44. import java.lang.reflect.Method;
  45. import java.util.Collection;
  46. import java.util.Collections;
  47. import java.util.ConcurrentModificationException;
  48. import java.util.Date;
  49. import java.util.Iterator;
  50. import java.util.List;
  51. import java.util.Set;
  52. import javax.jdo.JDOFatalUserException;
  53. import javax.jdo.PersistenceManager;
  54. import static com.google.appengine.datanucleus.PolymorphicTestUtils.getEntityKind;
  55. abstract class JDOOneToManyPolymorphicTestCase extends JDOTestCase {
  56. public enum UnidirLevel {
  57. Top(UnidirectionalSuperclassTableChildJDO.DISCRIMINATOR_TOP, UnidirTop.class),
  58. Middle(UnidirectionalSuperclassTableChildJDO.DISCRIMINATOR_MIDDLE, UnidirMiddle.class),
  59. Bottom(UnidirectionalSuperclassTableChildJDO.DISCRIMINATOR_BOTTOM, UnidirBottom.class);
  60. final String discriminator;
  61. final Class<?> clazz;
  62. UnidirLevel(String discriminator, Class<?> clazz) {
  63. this.discriminator = discriminator;
  64. this.clazz = clazz;
  65. }
  66. }
  67. public final StartEnd NEW_PM_DETACH_ON_CLOSE_START_END = new StartEnd() {
  68. public void start() {
  69. if (pm.isClosed()) {
  70. pm = pmf.getPersistenceManager();
  71. getExecutionContext().setProperty(PROP_DETACH_ON_CLOSE, true);
  72. }
  73. }
  74. public void end() {
  75. pm.close();
  76. }
  77. public PersistenceManagerFactoryName getPmfName() {
  78. return PersistenceManagerFactoryName.nontransactional;
  79. }
  80. };
  81. protected boolean hasIndexPropertyInChild(PersistenceManager pm) {
  82. return getStorageVersion(pm).ordinal() < StorageVersion.READ_OWNED_CHILD_KEYS_FROM_PARENTS.ordinal();
  83. }
  84. @Override
  85. protected void tearDown() throws Exception {
  86. try {
  87. if (!pm.isClosed() && pm.currentTransaction().isActive()) {
  88. pm.currentTransaction().rollback();
  89. }
  90. pmf.close();
  91. } finally {
  92. super.tearDown();
  93. }
  94. }
  95. void testInsert_NewParentAndChild(HasOneToManyJDO parent,
  96. BidirTop bidirChild, StartEnd startEnd, UnidirLevel unidirLevel,
  97. String expectedBidirKind, String expectedUnidirKind,
  98. int expectedParent, int expectedChildren) throws EntityNotFoundException {
  99. bidirChild.setChildVal("yam");
  100. UnidirTop unidirChild = newUnidir(unidirLevel);
  101. String expectedStr = unidirChild.getStr();
  102. parent.addBidirChild(bidirChild);
  103. bidirChild.setParent(parent);
  104. parent.addUnidirChild(unidirChild);
  105. parent.setVal("yar");
  106. startEnd.start();
  107. pm.makePersistent(parent);
  108. startEnd.end();
  109. assertNotNull(bidirChild.getId());
  110. assertNotNull(unidirChild.getId());
  111. Entity bidirChildEntity = ds.get(KeyFactory.stringToKey(bidirChild.getId()));
  112. assertEquals(expectedBidirKind, bidirChildEntity.getKind());
  113. assertNotNull(bidirChildEntity);
  114. assertEquals(bidirChild.getClass().getName(), bidirChildEntity.getProperty("DISCRIMINATOR"));
  115. int numProps = bidirChild.getPropertyCount();
  116. if (hasIndexPropertyInChild(pm)) {
  117. numProps += getIndexPropertyCount();
  118. }
  119. assertEquals(numProps, bidirChildEntity.getProperties().size());
  120. assertEquals("yam", bidirChildEntity.getProperty("childVal"));
  121. assertEquals(KeyFactory.stringToKey(bidirChild.getId()), bidirChildEntity.getKey());
  122. PolymorphicTestUtils.assertKeyParentEquals(parent.getId(), bidirChildEntity, bidirChild.getId());
  123. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  124. assertEquals(0L, bidirChildEntity.getProperty("bidirChildren_INTEGER_IDX"));
  125. }
  126. Entity unidirEntity = ds.get(KeyFactory.stringToKey(unidirChild.getId()));
  127. assertEquals(expectedUnidirKind, unidirEntity.getKind());
  128. assertNotNull(unidirEntity);
  129. assertEquals(unidirLevel.discriminator, unidirEntity.getProperty("TYPE"));
  130. numProps = unidirChild.getPropertyCount();
  131. if (hasIndexPropertyInChild(pm)) {
  132. numProps += getIndexPropertyCount();
  133. }
  134. assertEquals(numProps, unidirEntity.getProperties().size());
  135. assertEquals(expectedStr, unidirEntity.getProperty("str"));
  136. assertEquals(KeyFactory.stringToKey(unidirChild.getId()), unidirEntity.getKey());
  137. PolymorphicTestUtils.assertKeyParentEquals(parent.getId(), unidirEntity, unidirChild.getId());
  138. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  139. assertEquals(0L, unidirEntity.getProperty("unidirChildren_INTEGER_IDX"));
  140. }
  141. Entity parentEntity = ds.get(KeyFactory.stringToKey(parent.getId()));
  142. assertNotNull(parentEntity);
  143. assertEquals(3, parentEntity.getProperties().size());
  144. assertEquals("yar", parentEntity.getProperty("val"));
  145. assertEquals(Utils.newArrayList(bidirChildEntity.getKey()), parentEntity.getProperty("bidirChildren"));
  146. assertEquals(Utils.newArrayList(unidirEntity.getKey()), parentEntity.getProperty("unidirChildren"));
  147. assertCountsInDatastore(parent.getClass(), bidirChild.getClass(), expectedParent, expectedChildren);
  148. }
  149. void testInsert_ExistingParentNewChild(HasOneToManyJDO pojo,
  150. BidirectionalSuperclassTableChildJDO.BidirTop bidirChild, StartEnd startEnd, UnidirLevel unidirLevel,
  151. String expectedBidirKind, String expectedUnidirKind,
  152. int expectedParent, int expectedChildren) throws EntityNotFoundException {
  153. pojo.setVal("yar");
  154. startEnd.start();
  155. pm.makePersistent(pojo);
  156. startEnd.end();
  157. startEnd.start();
  158. assertNotNull(pojo.getId());
  159. assertTrue(pojo.getUnidirChildren().isEmpty());
  160. assertTrue(pojo.getBidirChildren().isEmpty());
  161. Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
  162. assertNotNull(pojoEntity);
  163. assertEquals(3, pojoEntity.getProperties().size());
  164. assertEquals("yar", pojoEntity.getProperty("val"));
  165. assertTrue(pojoEntity.hasProperty("bidirChildren"));
  166. assertNull(pojoEntity.getProperty("bidirChildren"));
  167. assertTrue(pojoEntity.hasProperty("unidirChildren"));
  168. assertNull(pojoEntity.getProperty("unidirChildren"));
  169. startEnd.end();
  170. startEnd.start();
  171. pojo = pm.makePersistent(pojo);
  172. assertEquals("yar", pojo.getVal());
  173. UnidirTop unidirChild = newUnidir(unidirLevel);
  174. String exepectedStr = unidirChild.getStr();
  175. pojo.addUnidirChild(unidirChild);
  176. bidirChild.setChildVal("yam");
  177. pojo.addBidirChild(bidirChild);
  178. startEnd.end();
  179. startEnd.start();
  180. assertNotNull(bidirChild.getId());
  181. assertNotNull(bidirChild.getParent());
  182. assertNotNull(unidirChild.getId());
  183. startEnd.end();
  184. Entity bidirChildEntity = ds.get(KeyFactory.stringToKey(bidirChild.getId()));
  185. assertNotNull(bidirChildEntity);
  186. assertEquals(expectedBidirKind, bidirChildEntity.getKind());
  187. int numProps = bidirChild.getPropertyCount();
  188. if (hasIndexPropertyInChild(pm)) {
  189. numProps += getIndexPropertyCount();
  190. }
  191. assertEquals(numProps, bidirChildEntity.getProperties().size());
  192. assertEquals(bidirChild.getClass().getName(), bidirChildEntity.getProperty("DISCRIMINATOR"));
  193. assertEquals("yam", bidirChildEntity.getProperty("childVal"));
  194. assertEquals(KeyFactory.stringToKey(bidirChild.getId()), bidirChildEntity.getKey());
  195. PolymorphicTestUtils.assertKeyParentEquals(pojo.getId(), bidirChildEntity, bidirChild.getId());
  196. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  197. assertEquals(0L, bidirChildEntity.getProperty("bidirChildren_INTEGER_IDX"));
  198. }
  199. Entity unidirChildEntity = ds.get(KeyFactory.stringToKey(unidirChild.getId()));
  200. assertNotNull(unidirChildEntity);
  201. assertEquals(expectedUnidirKind, unidirChildEntity.getKind());
  202. numProps = unidirChild.getPropertyCount();
  203. if (hasIndexPropertyInChild(pm)) {
  204. numProps += getIndexPropertyCount();
  205. }
  206. assertEquals(numProps, unidirChildEntity.getProperties().size());
  207. assertEquals(unidirLevel.discriminator, unidirChildEntity.getProperty("TYPE"));
  208. assertEquals(exepectedStr, unidirChildEntity.getProperty("str"));
  209. assertEquals(KeyFactory.stringToKey(unidirChild.getId()), unidirChildEntity.getKey());
  210. PolymorphicTestUtils.assertKeyParentEquals(pojo.getId(), unidirChildEntity, unidirChild.getId());
  211. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  212. assertEquals(0L, unidirChildEntity.getProperty("unidirChildren_INTEGER_IDX"));
  213. }
  214. Entity parentEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
  215. assertNotNull(parentEntity);
  216. assertEquals(3, parentEntity.getProperties().size());
  217. assertEquals("yar", parentEntity.getProperty("val"));
  218. assertEquals(Utils.newArrayList(bidirChildEntity.getKey()), parentEntity.getProperty("bidirChildren"));
  219. assertEquals(Utils.newArrayList(unidirChildEntity.getKey()), parentEntity.getProperty("unidirChildren"));
  220. assertCountsInDatastore(pojo.getClass(), bidirChild.getClass(), expectedParent, expectedChildren);
  221. }
  222. void testSwapAtPosition(HasOneToManyJDO pojo,
  223. BidirectionalSuperclassTableChildJDO.BidirTop bidir1,
  224. BidirectionalSuperclassTableChildJDO.BidirTop bidir2, StartEnd startEnd,
  225. String expectedBidirKind, String expectedUnidirKind,
  226. int expectedParent, int expectedChildren) throws EntityNotFoundException {
  227. pojo.setVal("yar");
  228. bidir2.setChildVal("yam");
  229. UnidirTop unidir = newUnidir(UnidirLevel.Middle);
  230. pojo.addUnidirChild(unidir);
  231. pojo.addBidirChild(bidir1);
  232. bidir1.setParent(pojo);
  233. startEnd.start();
  234. pm.makePersistent(pojo);
  235. startEnd.end();
  236. assertCountsInDatastore(pojo.getClass(), bidir1.getClass(), expectedParent, expectedChildren);
  237. startEnd.start();
  238. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  239. String bidir1Id = pojo.getBidirChildren().iterator().next().getId();
  240. String unidir1Id = pojo.getUnidirChildren().iterator().next().getId();
  241. pojo.addBidirChildAtPosition(bidir2, 0);
  242. UnidirTop unidir2 = newUnidir(UnidirLevel.Top);
  243. unidir2.setStr("another str");
  244. pojo.addUnidirAtPosition(unidir2, 0);
  245. startEnd.end();
  246. startEnd.start();
  247. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  248. assertNotNull(pojo.getId());
  249. assertEquals(1, pojo.getUnidirChildren().size());
  250. assertEquals(1, pojo.getBidirChildren().size());
  251. assertNotNull(bidir2.getId());
  252. assertNotNull(bidir2.getParent());
  253. assertNotNull(unidir2.getId());
  254. Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
  255. assertNotNull(pojoEntity);
  256. assertEquals(3, pojoEntity.getProperties().size());
  257. assertEquals(Utils.newArrayList(KeyFactory.stringToKey(bidir2.getId())), pojoEntity.getProperty("bidirChildren"));
  258. assertEquals(Utils.newArrayList(KeyFactory.stringToKey(unidir2.getId())), pojoEntity.getProperty("unidirChildren"));
  259. startEnd.end();
  260. try {
  261. ds.get(KeyFactory.stringToKey(bidir1Id));
  262. fail("expected EntityNotFoundException");
  263. } catch (EntityNotFoundException enfe) {
  264. // good
  265. }
  266. try {
  267. ds.get(KeyFactory.stringToKey(unidir1Id));
  268. fail("expected EntityNotFoundException");
  269. } catch (EntityNotFoundException enfe) {
  270. // good
  271. }
  272. Entity bidirChildEntity = ds.get(KeyFactory.stringToKey(bidir2.getId()));
  273. assertNotNull(bidirChildEntity);
  274. assertEquals(expectedBidirKind, bidirChildEntity.getKind());
  275. int numProps = bidir2.getPropertyCount();
  276. if (hasIndexPropertyInChild(pm)) {
  277. numProps += getIndexPropertyCount();
  278. }
  279. assertEquals(numProps, bidirChildEntity.getProperties().size());
  280. assertEquals(bidir2.getClass().getName(), bidirChildEntity.getProperty("DISCRIMINATOR"));
  281. assertEquals("yam", bidirChildEntity.getProperty("childVal"));
  282. assertEquals(KeyFactory.stringToKey(bidir2.getId()), bidirChildEntity.getKey());
  283. PolymorphicTestUtils.assertKeyParentEquals(pojo.getId(), bidirChildEntity, bidir2.getId());
  284. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  285. assertEquals(0L, bidirChildEntity.getProperty("bidirChildren_INTEGER_IDX"));
  286. }
  287. Entity unidirChildEntity = ds.get(KeyFactory.stringToKey(unidir2.getId()));
  288. assertNotNull(unidirChildEntity);
  289. assertEquals(expectedUnidirKind, unidirChildEntity.getKind());
  290. numProps = unidir2.getPropertyCount();
  291. if (hasIndexPropertyInChild(pm)) {
  292. numProps += getIndexPropertyCount();
  293. }
  294. assertEquals(numProps, unidirChildEntity.getProperties().size());
  295. assertEquals(UnidirLevel.Top.discriminator, unidirChildEntity.getProperty("TYPE"));
  296. assertEquals("another str", unidirChildEntity.getProperty("str"));
  297. assertEquals(KeyFactory.stringToKey(unidir2.getId()), unidirChildEntity.getKey());
  298. PolymorphicTestUtils.assertKeyParentEquals(pojo.getId(), unidirChildEntity, unidir2.getId());
  299. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  300. assertEquals(0L, unidirChildEntity.getProperty("unidirChildren_INTEGER_IDX"));
  301. }
  302. Entity parentEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
  303. assertNotNull(parentEntity);
  304. assertEquals(3, parentEntity.getProperties().size());
  305. assertEquals("yar", parentEntity.getProperty("val"));
  306. assertEquals(Utils.newArrayList(bidirChildEntity.getKey()), parentEntity.getProperty("bidirChildren"));
  307. assertEquals(Utils.newArrayList(unidirChildEntity.getKey()), parentEntity.getProperty("unidirChildren"));
  308. assertCountsInDatastore(pojo.getClass(), bidir2.getClass(), expectedParent, expectedChildren);
  309. }
  310. void testRemoveAtPosition(HasOneToManyJDO pojo,
  311. BidirectionalSuperclassTableChildJDO.BidirTop bidir1,
  312. BidirectionalSuperclassTableChildJDO.BidirTop bidir2,
  313. BidirectionalSuperclassTableChildJDO.BidirTop bidir3, StartEnd startEnd,
  314. String expectedBidirKind, String expectedUnidirKind,
  315. int count) throws EntityNotFoundException {
  316. pojo.setVal("yar");
  317. bidir2.setChildVal("another yam");
  318. bidir3.setChildVal("yet another yam");
  319. UnidirTop unidir = newUnidir(UnidirLevel.Top);
  320. UnidirTop unidir2 = newUnidir(UnidirLevel.Bottom);
  321. UnidirTop unidir3 = newUnidir(UnidirLevel.Middle);
  322. unidir2.setStr("another str");
  323. unidir3.setStr("yet another str");
  324. pojo.addUnidirChild(unidir);
  325. pojo.addUnidirChild(unidir2);
  326. pojo.addUnidirChild(unidir3);
  327. pojo.addBidirChild(bidir1);
  328. pojo.addBidirChild(bidir2);
  329. pojo.addBidirChild(bidir3);
  330. startEnd.start();
  331. pm.makePersistent(pojo);
  332. startEnd.end();
  333. assertCountsInDatastore(pojo.getClass(), bidir1.getClass(), count, (count-1) * 2 + 3);
  334. startEnd.start();
  335. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  336. String bidir1Id = pojo.getBidirChildren().iterator().next().getId();
  337. String unidir1Id = pojo.getUnidirChildren().iterator().next().getId();
  338. pojo.removeBidirChildAtPosition(0);
  339. pojo.removeUnidirChildAtPosition(0);
  340. startEnd.end();
  341. startEnd.start();
  342. assertNotNull(pojo.getId());
  343. assertEquals(2, pojo.getUnidirChildren().size());
  344. assertEquals(2, pojo.getBidirChildren().size());
  345. Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
  346. assertNotNull(pojoEntity);
  347. assertEquals(3, pojoEntity.getProperties().size());
  348. assertEquals(Utils.newArrayList(
  349. KeyFactory.stringToKey(bidir2.getId()),
  350. KeyFactory.stringToKey(bidir3.getId())), pojoEntity.getProperty("bidirChildren"));
  351. assertEquals(Utils.newArrayList(
  352. KeyFactory.stringToKey(unidir2.getId()),
  353. KeyFactory.stringToKey(unidir3.getId())), pojoEntity.getProperty("unidirChildren"));
  354. startEnd.end();
  355. try {
  356. ds.get(KeyFactory.stringToKey(bidir1Id));
  357. fail("expected EntityNotFoundException");
  358. } catch (EntityNotFoundException enfe) {
  359. // good
  360. }
  361. try {
  362. ds.get(KeyFactory.stringToKey(unidir1Id));
  363. fail("expected EntityNotFoundException");
  364. } catch (EntityNotFoundException enfe) {
  365. // good
  366. }
  367. Entity bidirChildEntity = ds.get(KeyFactory.stringToKey(bidir2.getId()));
  368. assertNotNull(bidirChildEntity);
  369. assertEquals(expectedBidirKind, bidirChildEntity.getKind());
  370. int numProps = bidir2.getPropertyCount();
  371. if (hasIndexPropertyInChild(pm)) {
  372. numProps += getIndexPropertyCount();
  373. }
  374. assertEquals(numProps, bidirChildEntity.getProperties().size());
  375. assertEquals(bidir2.getClass().getName(), bidirChildEntity.getProperty("DISCRIMINATOR"));
  376. assertEquals("another yam", bidirChildEntity.getProperty("childVal"));
  377. assertEquals(KeyFactory.stringToKey(bidir2.getId()), bidirChildEntity.getKey());
  378. PolymorphicTestUtils.assertKeyParentEquals(pojo.getId(), bidirChildEntity, bidir2.getId());
  379. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  380. assertEquals(0L, bidirChildEntity.getProperty("bidirChildren_INTEGER_IDX"));
  381. }
  382. bidirChildEntity = ds.get(KeyFactory.stringToKey(bidir3.getId()));
  383. assertNotNull(bidirChildEntity);
  384. assertEquals(expectedBidirKind, bidirChildEntity.getKind());
  385. numProps = bidir3.getPropertyCount();
  386. if (hasIndexPropertyInChild(pm)) {
  387. numProps += getIndexPropertyCount();
  388. }
  389. assertEquals(numProps, bidirChildEntity.getProperties().size());
  390. assertEquals(bidir3.getClass().getName(), bidirChildEntity.getProperty("DISCRIMINATOR"));
  391. assertEquals("yet another yam", bidirChildEntity.getProperty("childVal"));
  392. assertEquals(KeyFactory.stringToKey(bidir3.getId()), bidirChildEntity.getKey());
  393. PolymorphicTestUtils.assertKeyParentEquals(pojo.getId(), bidirChildEntity, bidir2.getId());
  394. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  395. assertEquals(1L, bidirChildEntity.getProperty("bidirChildren_INTEGER_IDX"));
  396. }
  397. Entity unidirChildEntity = ds.get(KeyFactory.stringToKey(unidir2.getId()));
  398. assertNotNull(unidirChildEntity);
  399. assertEquals(expectedUnidirKind, unidirChildEntity.getKind());
  400. numProps = unidir2.getPropertyCount();
  401. if (hasIndexPropertyInChild(pm)) {
  402. numProps += getIndexPropertyCount();
  403. }
  404. assertEquals(numProps, unidirChildEntity.getProperties().size());
  405. assertEquals(UnidirLevel.Bottom.discriminator, unidirChildEntity.getProperty("TYPE"));
  406. assertEquals("another str", unidirChildEntity.getProperty("str"));
  407. assertEquals(KeyFactory.stringToKey(unidir2.getId()), unidirChildEntity.getKey());
  408. PolymorphicTestUtils.assertKeyParentEquals(pojo.getId(), unidirChildEntity, unidir2.getId());
  409. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  410. assertEquals(0L, unidirChildEntity.getProperty("unidirChildren_INTEGER_IDX"));
  411. }
  412. unidirChildEntity = ds.get(KeyFactory.stringToKey(unidir3.getId()));
  413. assertNotNull(unidirChildEntity);
  414. assertEquals(expectedUnidirKind, unidirChildEntity.getKind());
  415. assertEquals(UnidirLevel.Middle.discriminator, unidirChildEntity.getProperty("TYPE"));
  416. assertEquals("yet another str", unidirChildEntity.getProperty("str"));
  417. assertEquals(KeyFactory.stringToKey(unidir3.getId()), unidirChildEntity.getKey());
  418. PolymorphicTestUtils.assertKeyParentEquals(pojo.getId(), unidirChildEntity, unidir2.getId());
  419. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  420. assertEquals(1L, unidirChildEntity.getProperty("unidirChildren_INTEGER_IDX"));
  421. }
  422. Entity parentEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
  423. assertNotNull(parentEntity);
  424. assertEquals(3, parentEntity.getProperties().size());
  425. assertEquals("yar", parentEntity.getProperty("val"));
  426. assertEquals(Utils.newArrayList(
  427. KeyFactory.stringToKey(bidir2.getId()),
  428. KeyFactory.stringToKey(bidir3.getId())), parentEntity.getProperty("bidirChildren"));
  429. assertEquals(Utils.newArrayList(
  430. KeyFactory.stringToKey(unidir2.getId()),
  431. KeyFactory.stringToKey(unidir3.getId())), parentEntity.getProperty("unidirChildren"));
  432. assertCountsInDatastore(pojo.getClass(), bidir2.getClass(), count, 2 * count);
  433. }
  434. void testAddAtPosition(HasOneToManyJDO pojo,
  435. BidirectionalSuperclassTableChildJDO.BidirTop bidir1,
  436. BidirectionalSuperclassTableChildJDO.BidirTop bidir2, StartEnd startEnd,
  437. String expectedBidirKind, String expectedUnidirKind, int count) throws EntityNotFoundException {
  438. pojo.setVal("yar");
  439. bidir2.setChildVal("yam");
  440. UnidirTop unidir = newUnidir(UnidirLevel.Middle);
  441. UnidirTop unidir2 = newUnidir(UnidirLevel.Bottom);
  442. unidir2.setStr("another str");
  443. pojo.addUnidirChild(unidir);
  444. pojo.addBidirChild(bidir1);
  445. startEnd.start();
  446. pm.makePersistent(pojo);
  447. startEnd.end();
  448. assertCountsInDatastore(pojo.getClass(), bidir1.getClass(), count, 2 *(count-1) + 1);
  449. startEnd.start();
  450. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  451. String bidir1Id = pojo.getBidirChildren().iterator().next().getId();
  452. String unidir1Id = pojo.getUnidirChildren().iterator().next().getId();
  453. pojo.addAtPosition(0, bidir2);
  454. pojo.addAtPosition(0, unidir2);
  455. startEnd.end();
  456. startEnd.start();
  457. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  458. assertNotNull(pojo.getId());
  459. assertEquals(2, pojo.getUnidirChildren().size());
  460. assertEquals(2, pojo.getBidirChildren().size());
  461. assertNotNull(bidir2.getId());
  462. assertNotNull(bidir2.getParent());
  463. assertNotNull(unidir2.getId());
  464. Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
  465. assertNotNull(pojoEntity);
  466. assertEquals(3, pojoEntity.getProperties().size());
  467. assertEquals(Utils.newArrayList(
  468. KeyFactory.stringToKey(bidir2.getId()),
  469. KeyFactory.stringToKey(bidir1.getId())), pojoEntity.getProperty("bidirChildren"));
  470. assertEquals(Utils.newArrayList(
  471. KeyFactory.stringToKey(unidir2.getId()),
  472. KeyFactory.stringToKey(unidir.getId())), pojoEntity.getProperty("unidirChildren"));
  473. startEnd.end();
  474. ds.get(KeyFactory.stringToKey(bidir1Id));
  475. ds.get(KeyFactory.stringToKey(unidir1Id));
  476. Entity bidirChildEntity = ds.get(KeyFactory.stringToKey(bidir2.getId()));
  477. assertNotNull(bidirChildEntity);
  478. assertEquals(expectedBidirKind, bidirChildEntity.getKind());
  479. int numProps = bidir2.getPropertyCount();
  480. if (hasIndexPropertyInChild(pm)) {
  481. numProps += getIndexPropertyCount();
  482. }
  483. assertEquals(numProps, bidirChildEntity.getProperties().size());
  484. assertEquals(bidir2.getClass().getName(), bidirChildEntity.getProperty("DISCRIMINATOR"));
  485. assertEquals("yam", bidirChildEntity.getProperty("childVal"));
  486. assertEquals(KeyFactory.stringToKey(bidir2.getId()), bidirChildEntity.getKey());
  487. PolymorphicTestUtils.assertKeyParentEquals(pojo.getId(), bidirChildEntity, bidir2.getId());
  488. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  489. assertEquals(0L, bidirChildEntity.getProperty("bidirChildren_INTEGER_IDX"));
  490. }
  491. Entity unidirChildEntity = ds.get(KeyFactory.stringToKey(unidir2.getId()));
  492. assertNotNull(unidirChildEntity);
  493. assertEquals(expectedUnidirKind, unidirChildEntity.getKind());
  494. numProps = unidir2.getPropertyCount();
  495. if (hasIndexPropertyInChild(pm)) {
  496. numProps += getIndexPropertyCount();
  497. }
  498. assertEquals(numProps, unidirChildEntity.getProperties().size());
  499. assertEquals(UnidirLevel.Bottom.discriminator, unidirChildEntity.getProperty("TYPE"));
  500. assertEquals("another str", unidirChildEntity.getProperty("str"));
  501. assertEquals(KeyFactory.stringToKey(unidir2.getId()), unidirChildEntity.getKey());
  502. PolymorphicTestUtils.assertKeyParentEquals(pojo.getId(), unidirChildEntity, unidir2.getId());
  503. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  504. assertEquals(0L, unidirChildEntity.getProperty("unidirChildren_INTEGER_IDX"));
  505. }
  506. Entity parentEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
  507. assertNotNull(parentEntity);
  508. assertEquals(3, parentEntity.getProperties().size());
  509. assertEquals("yar", parentEntity.getProperty("val"));
  510. assertEquals(Utils.newArrayList(
  511. KeyFactory.stringToKey(bidir2.getId()),
  512. KeyFactory.stringToKey(bidir1.getId())), parentEntity.getProperty("bidirChildren"));
  513. assertEquals(Utils.newArrayList(
  514. KeyFactory.stringToKey(unidir2.getId()),
  515. KeyFactory.stringToKey(unidir.getId())), parentEntity.getProperty("unidirChildren"));
  516. assertCountsInDatastore(pojo.getClass(), bidir2.getClass(), count, 2 * count);
  517. }
  518. void testUpdate_UpdateChildWithMerge(HasOneToManyJDO pojo,
  519. BidirectionalSuperclassTableChildJDO.BidirTop bidir, StartEnd startEnd,
  520. String expectedBidirKind, String expectedUnidirKind,
  521. UnidirLevel unidirLevel, int count) throws EntityNotFoundException {
  522. UnidirTop unidir = newUnidir(unidirLevel);
  523. pojo.addUnidirChild(unidir);
  524. pojo.addBidirChild(bidir);
  525. bidir.setParent(pojo);
  526. startEnd.start();
  527. pm.makePersistent(pojo);
  528. startEnd.end();
  529. assertNotNull(unidir.getId());
  530. assertNotNull(bidir.getId());
  531. assertNotNull(pojo.getId());
  532. startEnd.start();
  533. unidir.setStr("yam");
  534. bidir.setChildVal("yap");
  535. pm.makePersistent(pojo);
  536. startEnd.end();
  537. Entity unidirChildEntity = ds.get(KeyFactory.stringToKey(unidir.getId()));
  538. assertNotNull(unidirChildEntity);
  539. assertEquals(expectedUnidirKind, unidirChildEntity.getKind());
  540. int numProps = unidir.getPropertyCount();
  541. if (hasIndexPropertyInChild(pm)) {
  542. numProps += getIndexPropertyCount();
  543. }
  544. assertEquals(numProps, unidirChildEntity.getProperties().size());
  545. assertEquals(unidirLevel.discriminator, unidirChildEntity.getProperty("TYPE"));
  546. assertEquals("yam", unidirChildEntity.getProperty("str"));
  547. PolymorphicTestUtils.assertKeyParentEquals(pojo.getId(), unidirChildEntity, unidir.getId());
  548. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  549. assertEquals(0L, unidirChildEntity.getProperty("unidirChildren_INTEGER_IDX"));
  550. }
  551. Entity bidirEntity = ds.get(KeyFactory.stringToKey(bidir.getId()));
  552. assertNotNull(bidirEntity);
  553. assertEquals(expectedBidirKind, bidirEntity.getKind());
  554. numProps = bidir.getPropertyCount();
  555. if (hasIndexPropertyInChild(pm)) {
  556. numProps += getIndexPropertyCount();
  557. }
  558. assertEquals(numProps, bidirEntity.getProperties().size());
  559. assertEquals(bidir.getClass().getName(), bidirEntity.getProperty("DISCRIMINATOR"));
  560. assertEquals("yap", bidirEntity.getProperty("childVal"));
  561. PolymorphicTestUtils.assertKeyParentEquals(pojo.getId(), bidirEntity, bidir.getId());
  562. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  563. assertEquals(0L, bidirEntity.getProperty("bidirChildren_INTEGER_IDX"));
  564. }
  565. assertCountsInDatastore(pojo.getClass(), bidir.getClass(), count, count);
  566. }
  567. void testUpdate_UpdateChild(HasOneToManyJDO pojo,
  568. BidirectionalSuperclassTableChildJDO.BidirTop bidir, StartEnd startEnd,
  569. String expectedBidirKind, String expectedUnidirKind,
  570. UnidirLevel unidirLevel, int count) throws EntityNotFoundException {
  571. UnidirTop unidir = newUnidir(unidirLevel);
  572. pojo.addUnidirChild(unidir);
  573. pojo.addBidirChild(bidir);
  574. bidir.setParent(pojo);
  575. startEnd.start();
  576. pm.makePersistent(pojo);
  577. startEnd.end();
  578. assertNotNull(unidir.getId());
  579. assertNotNull(bidir.getId());
  580. assertNotNull(pojo.getId());
  581. startEnd.start();
  582. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  583. pojo.getUnidirChildren().iterator().next().setStr("yam");
  584. pojo.getBidirChildren().iterator().next().setChildVal("yap");
  585. startEnd.end();
  586. Entity unidirChildEntity = ds.get(KeyFactory.stringToKey(unidir.getId()));
  587. assertNotNull(unidirChildEntity);
  588. assertEquals(expectedUnidirKind, unidirChildEntity.getKind());
  589. int numProps = unidir.getPropertyCount();
  590. if (hasIndexPropertyInChild(pm)) {
  591. numProps += getIndexPropertyCount();
  592. }
  593. assertEquals(numProps, unidirChildEntity.getProperties().size());
  594. assertEquals(unidirLevel.discriminator, unidirChildEntity.getProperty("TYPE"));
  595. assertEquals("yam", unidirChildEntity.getProperty("str"));
  596. PolymorphicTestUtils.assertKeyParentEquals(pojo.getId(), unidirChildEntity, unidir.getId());
  597. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  598. assertEquals(0L, unidirChildEntity.getProperty("unidirChildren_INTEGER_IDX"));
  599. }
  600. Entity bidirEntity = ds.get(KeyFactory.stringToKey(bidir.getId()));
  601. assertNotNull(bidirEntity);
  602. assertEquals(expectedBidirKind, bidirEntity.getKind());
  603. numProps = bidir.getPropertyCount();
  604. if (hasIndexPropertyInChild(pm)) {
  605. numProps += getIndexPropertyCount();
  606. }
  607. assertEquals(numProps, bidirEntity.getProperties().size());
  608. assertEquals(bidir.getClass().getName(), bidirEntity.getProperty("DISCRIMINATOR"));
  609. assertEquals("yap", bidirEntity.getProperty("childVal"));
  610. PolymorphicTestUtils.assertKeyParentEquals(pojo.getId(), bidirEntity, bidir.getId());
  611. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  612. assertEquals(0L, bidirEntity.getProperty("bidirChildren_INTEGER_IDX"));
  613. }
  614. assertCountsInDatastore(pojo.getClass(), bidir.getClass(), count, count);
  615. }
  616. void testUpdate_NullOutChildren(HasOneToManyJDO pojo,
  617. BidirectionalSuperclassTableChildJDO.BidirTop bidir, StartEnd startEnd,
  618. UnidirLevel unidirLevel, int count) throws EntityNotFoundException {
  619. UnidirTop unidir = newUnidir(unidirLevel);
  620. pojo.addUnidirChild(unidir);
  621. pojo.addBidirChild(bidir);
  622. bidir.setParent(pojo);
  623. startEnd.start();
  624. pm.makePersistent(pojo);
  625. startEnd.end();
  626. assertCountsInDatastore(pojo.getClass(), bidir.getClass(), count, 1);
  627. startEnd.start();
  628. String unidirId = unidir.getId();
  629. String bidirChildId = bidir.getId();
  630. pojo.nullUnidirChildren();
  631. pojo.nullBidirChildren();
  632. pm.makePersistent(pojo);
  633. startEnd.end();
  634. try {
  635. ds.get(KeyFactory.stringToKey(unidirId));
  636. fail("expected enfe");
  637. } catch (EntityNotFoundException enfe) {
  638. // good
  639. }
  640. try {
  641. ds.get(KeyFactory.stringToKey(bidirChildId));
  642. fail("expected enfe");
  643. } catch (EntityNotFoundException enfe) {
  644. // good
  645. }
  646. Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
  647. assertEquals(3, pojoEntity.getProperties().size());
  648. assertTrue(pojoEntity.hasProperty("bidirChildren"));
  649. assertNull(pojoEntity.getProperty("bidirChildren"));
  650. assertTrue(pojoEntity.hasProperty("unidirChildren"));
  651. assertNull(pojoEntity.getProperty("unidirChildren"));
  652. assertCountsInDatastore(pojo.getClass(), bidir.getClass(), count, 0);
  653. }
  654. void testUpdate_ClearOutChildren(HasOneToManyJDO pojo,
  655. BidirectionalSuperclassTableChildJDO.BidirTop bidir, StartEnd startEnd,
  656. UnidirLevel unidirLevel, int count) throws EntityNotFoundException {
  657. UnidirTop unidir = newUnidir(unidirLevel);
  658. pojo.addUnidirChild(unidir);
  659. pojo.addBidirChild(bidir);
  660. bidir.setParent(pojo);
  661. startEnd.start();
  662. pm.makePersistent(pojo);
  663. startEnd.end();
  664. String unidirId = unidir.getId();
  665. String bidirChildId = bidir.getId();
  666. assertCountsInDatastore(pojo.getClass(), bidir.getClass(), count, 1);
  667. startEnd.start();
  668. pojo = pm.makePersistent(pojo);
  669. pojo.clearUnidirChildren();
  670. pojo.clearBidirChildren();
  671. startEnd.end();
  672. try {
  673. ds.get(KeyFactory.stringToKey(unidirId));
  674. fail("expected enfe");
  675. } catch (EntityNotFoundException enfe) {
  676. // good
  677. }
  678. try {
  679. ds.get(KeyFactory.stringToKey(bidirChildId));
  680. fail("expected enfe");
  681. } catch (EntityNotFoundException enfe) {
  682. // good
  683. }
  684. Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
  685. assertEquals(3, pojoEntity.getProperties().size());
  686. assertTrue(pojoEntity.hasProperty("bidirChildren"));
  687. assertNull(pojoEntity.getProperty("bidirChildren"));
  688. assertTrue(pojoEntity.hasProperty("unidirChildren"));
  689. assertNull(pojoEntity.getProperty("unidirChildren"));
  690. assertCountsInDatastore(pojo.getClass(), bidir.getClass(), count, 0);
  691. }
  692. void testFindWithOrderBy(Class<? extends HasOneToManyWithOrderByJDO> pojoClass, StartEnd startEnd)
  693. throws EntityNotFoundException {
  694. getExecutionContext().getNucleusContext().getPersistenceConfiguration().setProperty(
  695. "datanucleus.appengine.allowMultipleRelationsOfSameType", true);
  696. Entity pojoEntity = new Entity(getEntityKind(pojoClass));
  697. ds.put(pojoEntity);
  698. Entity unidirChildEntity1 = newUnidir(UnidirLevel.Bottom, pojoEntity.getKey(), "str1", "name 1", new Date(), 1);
  699. unidirChildEntity1.setProperty("unidirByStrAndName_INTEGER_IDX", 0);
  700. unidirChildEntity1.setProperty("unidirByIdAndStr_INTEGER_IDX", 0);
  701. unidirChildEntity1.setProperty("unidirByStrAndId_INTEGER_IDX", 0);
  702. ds.put(unidirChildEntity1);
  703. Entity unidirChildEntity2 = newUnidir(UnidirLevel.Top, pojoEntity.getKey(), "str2", "name 2", null, null);
  704. unidirChildEntity2.setProperty("unidirByStrAndName_INTEGER_IDX", 1);
  705. unidirChildEntity2.setProperty("unidirByIdAndStr_INTEGER_IDX", 1);
  706. unidirChildEntity2.setProperty("unidirByStrAndId_INTEGER_IDX", 1);
  707. ds.put(unidirChildEntity2);
  708. Entity unidirChildEntity3 = newUnidir(UnidirLevel.Middle, pojoEntity.getKey(), "str1", "name 0", new Date(), null);
  709. unidirChildEntity3.setProperty("unidirByStrAndName_INTEGER_IDX", 2);
  710. unidirChildEntity3.setProperty("unidirByIdAndStr_INTEGER_IDX", 2);
  711. unidirChildEntity3.setProperty("unidirByStrAndId_INTEGER_IDX", 2);
  712. ds.put(unidirChildEntity3);
  713. Entity explicitIndexEntity1 =
  714. new Entity(getEntityKind(UnidirTopWithIndexColumn.class), pojoEntity.getKey());
  715. explicitIndexEntity1.setProperty("index", 3);
  716. ds.put(explicitIndexEntity1);
  717. Entity explicitIndexEntity2 =
  718. new Entity(getEntityKind(UnidirTopWithIndexColumn.class), pojoEntity.getKey());
  719. explicitIndexEntity2.setProperty("index", 2);
  720. ds.put(explicitIndexEntity2);
  721. Entity explicitIndexEntity3 =
  722. new Entity(getEntityKind(UnidirTopWithIndexColumn.class), pojoEntity.getKey());
  723. explicitIndexEntity3.setProperty("index", 1);
  724. ds.put(explicitIndexEntity3);
  725. pojoEntity.setProperty("unidirByStrAndName", Utils.newArrayList(unidirChildEntity2.getKey(), unidirChildEntity3.getKey(), unidirChildEntity1.getKey()));
  726. pojoEntity.setProperty("unidirByIdAndStr", Utils.newArrayList(unidirChildEntity3.getKey(), unidirChildEntity2.getKey(), unidirChildEntity1.getKey()));
  727. pojoEntity.setProperty("unidirByStrAndId", Utils.newArrayList(unidirChildEntity2.getKey(), unidirChildEntity1.getKey(), unidirChildEntity3.getKey()));
  728. pojoEntity.setProperty("unidirWithIndexColumn", Utils.newArrayList(explicitIndexEntity3.getKey(), explicitIndexEntity2.getKey(), explicitIndexEntity1.getKey()));
  729. ds.put(pojoEntity);
  730. startEnd.start();
  731. registerSubclasses();
  732. HasOneToManyWithOrderByJDO pojo = pm.getObjectById(
  733. pojoClass, KeyFactory.keyToString(pojoEntity.getKey()));
  734. assertNotNull(pojo);
  735. assertNotNull(pojo.getUndirByStrAndName());
  736. assertEquals(3, pojo.getUndirByStrAndName().size());
  737. assertEquals("name 2", pojo.getUndirByStrAndName().get(0).getName());
  738. assertTrue(pojo.getUndirByStrAndName().get(0) instanceof UnidirTop);
  739. assertEquals("name 0", pojo.getUndirByStrAndName().get(1).getName());
  740. assertTrue(pojo.getUndirByStrAndName().get(1) instanceof UnidirMiddle);
  741. assertEquals("name 1", pojo.getUndirByStrAndName().get(2).getName());
  742. assertTrue(pojo.getUndirByStrAndName().get(2) instanceof UnidirBottom);
  743. assertNotNull(pojo.getUnidirByIdAndStr());
  744. assertEquals(3, pojo.getUnidirByIdAndStr().size());
  745. assertEquals("name 0", pojo.getUnidirByIdAndStr().get(0).getName());
  746. assertTrue(pojo.getUnidirByIdAndStr().get(0) instanceof UnidirMiddle);
  747. assertEquals("name 2", pojo.getUnidirByIdAndStr().get(1).getName());
  748. assertTrue(pojo.getUnidirByIdAndStr().get(1) instanceof UnidirTop);
  749. assertEquals("name 1", pojo.getUnidirByIdAndStr().get(2).getName());
  750. assertTrue(pojo.getUnidirByIdAndStr().get(2) instanceof UnidirBottom);
  751. assertNotNull(pojo.getUnidirByStrAndId());
  752. assertEquals(3, pojo.getUnidirByStrAndId().size());
  753. assertEquals("name 2", pojo.getUnidirByStrAndId().get(0).getName());
  754. assertTrue(pojo.getUnidirByStrAndId().get(0) instanceof UnidirTop);
  755. assertEquals("name 1", pojo.getUnidirByStrAndId().get(1).getName());
  756. assertTrue(pojo.getUnidirByStrAndId().get(1) instanceof UnidirBottom);
  757. assertEquals("name 0", pojo.getUnidirByStrAndId().get(2).getName());
  758. assertTrue(pojo.getUnidirByStrAndId().get(2) instanceof UnidirMiddle);
  759. assertNotNull(pojo.getUnidirWithIndexColumn());
  760. assertEquals(3, pojo.getUnidirWithIndexColumn().size());
  761. assertEquals(explicitIndexEntity3.getKey(), KeyFactory.stringToKey(pojo.getUnidirWithIndexColumn().get(0).getId()));
  762. assertEquals(explicitIndexEntity2.getKey(), KeyFactory.stringToKey(pojo.getUnidirWithIndexColumn().get(1).getId()));
  763. assertEquals(explicitIndexEntity1.getKey(), KeyFactory.stringToKey(pojo.getUnidirWithIndexColumn().get(2).getId()));
  764. startEnd.end();
  765. }
  766. void testSaveWithOrderBy(HasOneToManyWithOrderByJDO pojo,
  767. StartEnd startEnd) throws EntityNotFoundException {
  768. getExecutionContext().getNucleusContext().getPersistenceConfiguration()
  769. .setProperty("datanucleus.appengine.allowMultipleRelationsOfSameType",
  770. true);
  771. startEnd.start();
  772. pm.makePersistent(pojo);
  773. startEnd.end();
  774. startEnd.start();
  775. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  776. UnidirTop unidir = newUnidir(UnidirLevel.Bottom);
  777. unidir.setStr("str1");
  778. unidir.setName("name 1");
  779. pojo.getUndirByStrAndName().add(unidir);
  780. unidir = newUnidir(UnidirLevel.Top);
  781. unidir.setStr("str2");
  782. unidir.setName("name 2");
  783. pojo.getUndirByStrAndName().add(unidir);
  784. unidir = newUnidir(UnidirLevel.Bottom);
  785. unidir.setStr("str1");
  786. unidir.setName("name 0");
  787. pojo.getUndirByStrAndName().add(unidir);
  788. startEnd.end();
  789. startEnd.start();
  790. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  791. assertNotNull(pojo);
  792. assertNotNull(pojo.getUndirByStrAndName());
  793. assertEquals(3, pojo.getUndirByStrAndName().size());
  794. assertEquals("name 2", pojo.getUndirByStrAndName().get(0).getName());
  795. assertTrue(pojo.getUndirByStrAndName().get(0) instanceof UnidirTop);
  796. assertEquals("name 0", pojo.getUndirByStrAndName().get(1).getName());
  797. assertTrue(pojo.getUndirByStrAndName().get(1) instanceof UnidirMiddle);
  798. assertEquals("name 1", pojo.getUndirByStrAndName().get(2).getName());
  799. assertTrue(pojo.getUndirByStrAndName().get(2) instanceof UnidirBottom);
  800. assertNotNull(pojo.getUnidirByIdAndStr());
  801. assertEquals(3, pojo.getUnidirByIdAndStr().size());
  802. assertEquals("name 0", pojo.getUnidirByIdAndStr().get(0).getName());
  803. assertTrue(pojo.getUnidirByIdAndStr().get(0) instanceof UnidirMiddle);
  804. assertEquals("name 2", pojo.getUnidirByIdAndStr().get(1).getName());
  805. assertTrue(pojo.getUnidirByIdAndStr().get(1) instanceof UnidirTop);
  806. assertEquals("name 1", pojo.getUnidirByIdAndStr().get(2).getName());
  807. assertTrue(pojo.getUnidirByIdAndStr().get(2) instanceof UnidirBottom);
  808. assertNotNull(pojo.getUnidirByStrAndId());
  809. assertEquals(3, pojo.getUnidirByStrAndId().size());
  810. assertEquals("name 2", pojo.getUnidirByStrAndId().get(0).getName());
  811. assertTrue(pojo.getUnidirByStrAndId().get(0) instanceof UnidirTop);
  812. assertEquals("name 1", pojo.getUnidirByStrAndId().get(1).getName());
  813. assertTrue(pojo.getUnidirByStrAndId().get(1) instanceof UnidirBottom);
  814. assertEquals("name 0", pojo.getUnidirByStrAndId().get(2).getName());
  815. assertTrue(pojo.getUnidirByStrAndId().get(2) instanceof UnidirMiddle);
  816. startEnd.end();
  817. }
  818. void testFind(Class<? extends HasOneToManyJDO> pojoClass,
  819. Class<? extends BidirectionalSuperclassTableChildJDO.BidirTop> bidirClass, StartEnd startEnd,
  820. String bidirKind, UnidirLevel unidirLevel) throws EntityNotFoundException {
  821. Entity pojoEntity = new Entity(getEntityKind(pojoClass));
  822. ds.put(pojoEntity);
  823. Entity unidirChildEntity = newUnidir(unidirLevel, pojoEntity.getKey(), "str1", "name 1", null, null);
  824. ds.put(unidirChildEntity);
  825. Entity bidirEntity = new Entity(bidirKind, pojoEntity.getKey());
  826. bidirEntity.setProperty("childVal", "yap");
  827. bidirEntity.setProperty("DISCRIMINATOR", bidirClass.getName());
  828. bidirEntity.setProperty("bidirChildren_INTEGER_IDX", 1);
  829. ds.put(bidirEntity);
  830. pojoEntity.setProperty("bidirChildren", Utils.newArrayList(bidirEntity.getKey()));
  831. pojoEntity.setProperty("unidirChildren", Utils.newArrayList(unidirChildEntity.getKey()));
  832. ds.put(pojoEntity);
  833. startEnd.start();
  834. registerSubclasses();
  835. HasOneToManyJDO pojo =
  836. pm.getObjectById(pojoClass, KeyFactory.keyToString(pojoEntity.getKey()));
  837. assertNotNull(pojo);
  838. assertNotNull(pojo.getUnidirChildren());
  839. assertEquals(1, pojo.getUnidirChildren().size());
  840. assertEquals("str1", pojo.getUnidirChildren().iterator().next().getStr());
  841. assertEquals(unidirLevel.clazz, pojo.getUnidirChildren().iterator().next().getClass());
  842. assertNotNull(pojo.getBidirChildren());
  843. assertEquals(1, pojo.getBidirChildren().size());
  844. assertEquals("yap", pojo.getBidirChildren().iterator().next().getChildVal());
  845. assertEquals(pojo, pojo.getBidirChildren().iterator().next().getParent());
  846. assertEquals(bidirClass, pojo.getBidirChildren().iterator().next().getClass());
  847. startEnd.end();
  848. }
  849. void testQuery(Class<? extends HasOneToManyJDO> pojoClass,
  850. Class<? extends BidirectionalSuperclassTableChildJDO.BidirTop> bidirClass, StartEnd startEnd,
  851. String bidirKind, UnidirLevel unidirLevel) throws EntityNotFoundException {
  852. Entity pojoEntity = new Entity(getEntityKind(pojoClass));
  853. ds.put(pojoEntity);
  854. Entity unidirEntity = newUnidir(unidirLevel, pojoEntity.getKey(), "str", "name", null, null);
  855. ds.put(unidirEntity);
  856. Entity bidirEntity = new Entity(bidirKind, pojoEntity.getKey());
  857. bidirEntity.setProperty("DISCRIMINATOR", bidirClass.getName());
  858. bidirEntity.setProperty("childVal", "yap");
  859. bidirEntity.setProperty("bidirChildren_INTEGER_IDX", 1);
  860. ds.put(bidirEntity);
  861. pojoEntity.setProperty("bidirChildren", Utils.newArrayList(bidirEntity.getKey()));
  862. pojoEntity.setProperty("unidirChildren", Utils.newArrayList(unidirEntity.getKey()));
  863. ds.put(pojoEntity);
  864. startEnd.start();
  865. registerSubclasses();
  866. javax.jdo.Query q = pm.newQuery(
  867. "select from " + pojoClass.getName() + " where id == key parameters String key");
  868. @SuppressWarnings("unchecked")
  869. List<HasOneToManyJDO> result =
  870. (List<HasOneToManyJDO>) q.execute(KeyFactory.keyToString(pojoEntity.getKey()));
  871. assertEquals(1, result.size());
  872. HasOneToManyJDO pojo = result.get(0);
  873. assertNotNull(pojo.getUnidirChildren());
  874. assertEquals(1, pojo.getUnidirChildren().size());
  875. assertEquals("str", pojo.getUnidirChildren().iterator().next().getStr());
  876. assertEquals("name", pojo.getUnidirChildren().iterator().next().getName());
  877. assertEquals(unidirLevel.clazz, pojo.getUnidirChildren().iterator().next().getClass());
  878. assertEquals(1, pojo.getUnidirChildren().size());
  879. assertNotNull(pojo.getBidirChildren());
  880. assertEquals(1, pojo.getBidirChildren().size());
  881. assertEquals("yap", pojo.getBidirChildren().iterator().next().getChildVal());
  882. assertEquals(pojo, pojo.getBidirChildren().iterator().next().getParent());
  883. assertEquals(bidirClass, pojo.getBidirChildren().iterator().next().getClass());
  884. startEnd.end();
  885. }
  886. void testChildFetchedLazily(Class<? extends HasOneToManyJDO> pojoClass,
  887. Class<? extends BidirectionalSuperclassTableChildJDO.BidirTop> bidirClass) throws Exception {
  888. DatastoreServiceConfig config = getStoreManager().getDefaultDatastoreServiceConfigForReads();
  889. tearDown();
  890. DatastoreService mockDatastore = EasyMock.createMock(DatastoreService.class);
  891. DatastoreService original = DatastoreServiceFactoryInternal.getDatastoreService(config);
  892. DatastoreServiceFactoryInternal.setDatastoreService(mockDatastore);
  893. try {
  894. setUp();
  895. Entity pojoEntity = new Entity(getEntityKind(pojoClass));
  896. ds.put(pojoEntity);
  897. Entity unidirEntity = newUnidir(UnidirLevel.Top, pojoEntity.getKey(), "str", "name", null, null);
  898. ds.put(unidirEntity);
  899. Entity bidirEntity = new Entity(bidirClass.getSimpleName(), pojoEntity.getKey());
  900. bidirEntity.setProperty("childVal", "yap");
  901. ds.put(bidirEntity);
  902. Transaction txn = EasyMock.createMock(Transaction.class);
  903. EasyMock.expect(txn.getId()).andReturn("1").times(2);
  904. txn.commit();
  905. EasyMock.expectLastCall();
  906. EasyMock.replay(txn);
  907. EasyMock.expect(mockDatastore.beginTransaction(EasyMock.isA(TransactionOptions.class))).andReturn(txn);
  908. // the only get we're going to perform is for the pojo
  909. EasyMock.expect(mockDatastore.get(txn, pojoEntity.getKey())).andReturn(pojoEntity);
  910. EasyMock.replay(mockDatastore);
  911. beginTxn();
  912. HasOneToManyJDO pojo =
  913. pm.getObjectById(pojoClass, KeyFactory.keyToString(pojoEntity.getKey()));
  914. assertNotNull(pojo);
  915. pojo.getId();
  916. commitTxn();
  917. } finally {
  918. DatastoreServiceFactoryInternal.setDatastoreService(original);
  919. }
  920. EasyMock.verify(mockDatastore);
  921. }
  922. void testDeleteParentDeletesChild(Class<? extends HasOneToManyJDO> pojoClass,
  923. Class<? extends BidirectionalSuperclassTableChildJDO.BidirTop> bidirClass, StartEnd startEnd,
  924. String bidirKind, UnidirLevel unidirLevel) throws Exception {
  925. Entity pojoEntity = new Entity(getEntityKind(pojoClass));
  926. ds.put(pojoEntity);
  927. Entity unidirEntity = newUnidir(unidirLevel, pojoEntity.getKey(), "str", "name", null, null);
  928. ds.put(unidirEntity);
  929. Entity bidirEntity = new Entity(bidirKind, pojoEntity.getKey());
  930. bidirEntity.setProperty("childVal", "yap");
  931. bidirEntity.setProperty("bidirChildren_INTEGER_IDX", 1);
  932. bidirEntity.setProperty("DISCRIMINATOR", bidirClass.getName());
  933. ds.put(bidirEntity);
  934. pojoEntity.setProperty("bidirChildren", Utils.newArrayList(bidirEntity.getKey()));
  935. pojoEntity.setProperty("unidirChildren", Utils.newArrayList(unidirEntity.getKey()));
  936. ds.put(pojoEntity);
  937. startEnd.start();
  938. registerSubclasses();
  939. HasOneToManyJDO pojo = pm.getObjectById(pojoClass, KeyFactory.keyToString(pojoEntity.getKey()));
  940. pm.deletePersistent(pojo);
  941. startEnd.end();
  942. assertCountsInDatastore(pojoClass, bidirClass, 0, 0);
  943. }
  944. void testRemoveAll(HasOneToManyJDO pojo, BidirectionalSuperclassTableChildJDO.BidirTop bidir1,
  945. BidirectionalSuperclassTableChildJDO.BidirTop bidir2, BidirectionalSuperclassTableChildJDO.BidirTop bidir3, StartEnd startEnd)
  946. throws EntityNotFoundException {
  947. UnidirTop unidir1 = new UnidirTop();
  948. UnidirTop unidir2 = new UnidirMiddle();
  949. UnidirTop unidir3 = new UnidirBottom();
  950. pojo.addUnidirChild(unidir1);
  951. pojo.addUnidirChild(unidir2);
  952. pojo.addUnidirChild(unidir3);
  953. pojo.addBidirChild(bidir1);
  954. pojo.addBidirChild(bidir2);
  955. pojo.addBidirChild(bidir3);
  956. startEnd.start();
  957. pm.makePersistent(pojo);
  958. startEnd.end();
  959. startEnd.start();
  960. pojo = pm.makePersistent(pojo);
  961. String unidir2Id = unidir2.getId();
  962. String bidir2Id = bidir2.getId();
  963. pojo.removeUnidirChildren(Collections.singleton(unidir2));
  964. pojo.removeBidirChildren(Collections.singleton(bidir2));
  965. startEnd.end();
  966. startEnd.start();
  967. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  968. assertEquals(2, pojo.getUnidirChildren().size());
  969. Set<String> unidirIds = Utils.newHashSet(unidir1.getId(), unidir2.getId(), unidir3.getId());
  970. for (UnidirTop unidir : pojo.getUnidirChildren()) {
  971. unidirIds.remove(unidir.getId());
  972. }
  973. assertEquals(1, unidirIds.size());
  974. assertEquals(unidir2.getId(), unidirIds.iterator().next());
  975. assertEquals(2, pojo.getBidirChildren().size());
  976. Set<String> bidirIds = Utils.newHashSet(bidir1.getId(), bidir2.getId(), bidir3.getId());
  977. for (BidirectionalSuperclassTableChildJDO.BidirTop b : pojo.getBidirChildren()) {
  978. bidirIds.remove(b.getId());
  979. }
  980. assertEquals(1, bidirIds.size());
  981. assertEquals(bidir2.getId(), bidirIds.iterator().next());
  982. startEnd.end();
  983. Entity unidirEntity1 = ds.get(KeyFactory.stringToKey(unidir1.getId()));
  984. Entity unidirEntity3 = ds.get(KeyFactory.stringToKey(unidir3.getId()));
  985. Entity bidirEntity1 = ds.get(KeyFactory.stringToKey(bidir1.getId()));
  986. Entity bidirEntity3 = ds.get(KeyFactory.stringToKey(bidir3.getId()));
  987. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  988. // Only have index property when using older storageVersions
  989. assertEquals(0L, unidirEntity1.getProperty("unidirChildren_INTEGER_IDX"));
  990. assertEquals(1L, unidirEntity3.getProperty("unidirChildren_INTEGER_IDX"));
  991. assertEquals(0L, bidirEntity1.getProperty("bidirChildren_INTEGER_IDX"));
  992. assertEquals(1L, bidirEntity3.getProperty("bidirChildren_INTEGER_IDX"));
  993. }
  994. try {
  995. ds.get(KeyFactory.stringToKey(unidir2Id));
  996. fail("expected enfe");
  997. } catch (EntityNotFoundException enfe) {
  998. // good
  999. }
  1000. try {
  1001. ds.get(KeyFactory.stringToKey(bidir2Id));
  1002. fail("expected enfe");
  1003. } catch (EntityNotFoundException enfe) {
  1004. // good
  1005. }
  1006. }
  1007. void testRemoveAll_LongPkOnParent(HasOneToManyLongPkJDO pojo, BidirTopLongPk bidir1,
  1008. BidirTopLongPk bidir2, BidirTopLongPk bidir3, StartEnd startEnd)
  1009. throws EntityNotFoundException {
  1010. UnidirTop unidir1 = new UnidirBottom();
  1011. UnidirTop unidir2 = new UnidirMiddle();
  1012. UnidirTop unidir3 = new UnidirTop();
  1013. pojo.addUnidirChild(unidir1);
  1014. pojo.addUnidirChild(unidir2);
  1015. pojo.addUnidirChild(unidir3);
  1016. pojo.addBidirChild(bidir1);
  1017. pojo.addBidirChild(bidir2);
  1018. pojo.addBidirChild(bidir3);
  1019. startEnd.start();
  1020. pm.makePersistent(pojo);
  1021. startEnd.end();
  1022. startEnd.start();
  1023. pojo = pm.makePersistent(pojo);
  1024. String f2Id = unidir2.getId();
  1025. String bidir2Id = bidir2.getId();
  1026. pojo.removeUnidirChildren(Collections.singleton(unidir2));
  1027. pojo.removeBidirChildren(Collections.singleton(bidir2));
  1028. startEnd.end();
  1029. startEnd.start();
  1030. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  1031. assertEquals(2, pojo.getUnidirChildren().size());
  1032. Set<String> unidirIds = Utils.newHashSet(unidir1.getId(), unidir2.getId(), unidir3.getId());
  1033. for (UnidirTop f : pojo.getUnidirChildren()) {
  1034. unidirIds.remove(f.getId());
  1035. }
  1036. assertEquals(1, unidirIds.size());
  1037. assertEquals(unidir2.getId(), unidirIds.iterator().next());
  1038. assertEquals(2, pojo.getBidirChildren().size());
  1039. Set<String> bidirIds = Utils.newHashSet(bidir1.getId(), bidir2.getId(), bidir3.getId());
  1040. for (BidirTopLongPk b : pojo.getBidirChildren()) {
  1041. bidirIds.remove(b.getId());
  1042. }
  1043. assertEquals(1, bidirIds.size());
  1044. assertEquals(bidir2.getId(), bidirIds.iterator().next());
  1045. startEnd.end();
  1046. Entity unidirEntity1 = ds.get(KeyFactory.stringToKey(unidir1.getId()));
  1047. Entity unidirEntity3 = ds.get(KeyFactory.stringToKey(unidir3.getId()));
  1048. Entity bidirEntity1 = ds.get(KeyFactory.stringToKey(bidir1.getId()));
  1049. Entity bidirEntity3 = ds.get(KeyFactory.stringToKey(bidir3.getId()));
  1050. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  1051. // Only have index property when using older storageVersions
  1052. assertEquals(0L, unidirEntity1.getProperty("unidirChildren_INTEGER_IDX_longpk"));
  1053. assertEquals(1L, unidirEntity3.getProperty("unidirChildren_INTEGER_IDX_longpk"));
  1054. assertEquals(0L, bidirEntity1.getProperty("bidirChildren_INTEGER_IDX"));
  1055. assertEquals(1L, bidirEntity3.getProperty("bidirChildren_INTEGER_IDX"));
  1056. }
  1057. try {
  1058. ds.get(KeyFactory.stringToKey(f2Id));
  1059. fail("expected enfe");
  1060. } catch (EntityNotFoundException enfe) {
  1061. // good
  1062. }
  1063. try {
  1064. ds.get(KeyFactory.stringToKey(bidir2Id));
  1065. fail("expected enfe");
  1066. } catch (EntityNotFoundException enfe) {
  1067. // good
  1068. }
  1069. }
  1070. void testRemoveAll_UnencodedStringPkOnParent(HasOneToManyUnencodedStringPkJDO pojo, BidirTopUnencodedStringPkJDO bidir1,
  1071. BidirTopUnencodedStringPkJDO bidir2,
  1072. BidirTopUnencodedStringPkJDO bidir3, StartEnd startEnd)
  1073. throws EntityNotFoundException {
  1074. UnidirTop unidir1 = new UnidirBottom();
  1075. UnidirTop unidir2 = new UnidirTop();
  1076. UnidirTop unidir3 = new UnidirMiddle();
  1077. pojo.addUnidirChild(unidir1);
  1078. pojo.addUnidirChild(unidir2);
  1079. pojo.addUnidirChild(unidir3);
  1080. pojo.addBidirChild(bidir1);
  1081. pojo.addBidirChild(bidir2);
  1082. pojo.addBidirChild(bidir3);
  1083. startEnd.start();
  1084. pm.makePersistent(pojo);
  1085. startEnd.end();
  1086. startEnd.start();
  1087. pojo = pm.makePersistent(pojo);
  1088. String f2Id = unidir2.getId();
  1089. String bidir2Id = bidir2.getId();
  1090. pojo.removeUnidirChildren(Collections.singleton(unidir2));
  1091. pojo.removeBidirChildren(Collections.singleton(bidir2));
  1092. startEnd.end();
  1093. startEnd.start();
  1094. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  1095. assertEquals(2, pojo.getUnidirChildren().size());
  1096. Set<String> unidirIds = Utils.newHashSet(unidir1.getId(), unidir2.getId(), unidir3.getId());
  1097. for (UnidirTop f : pojo.getUnidirChildren()) {
  1098. unidirIds.remove(f.getId());
  1099. }
  1100. assertEquals(1, unidirIds.size());
  1101. assertEquals(unidir2.getId(), unidirIds.iterator().next());
  1102. assertEquals(2, pojo.getBidirChildren().size());
  1103. Set<String> bidirIds = Utils.newHashSet(bidir1.getId(), bidir2.getId(), bidir3.getId());
  1104. for (BidirTopUnencodedStringPkJDO b : pojo.getBidirChildren()) {
  1105. bidirIds.remove(b.getId());
  1106. }
  1107. assertEquals(1, bidirIds.size());
  1108. assertEquals(bidir2.getId(), bidirIds.iterator().next());
  1109. startEnd.end();
  1110. Entity unidirEntity1 = ds.get(KeyFactory.stringToKey(unidir1.getId()));
  1111. Entity unidirEntity3 = ds.get(KeyFactory.stringToKey(unidir3.getId()));
  1112. Entity bidirEntity1 = ds.get(KeyFactory.stringToKey(bidir1.getId()));
  1113. bidirEntity1.setProperty("DISCRIMINATOR", "B");
  1114. Entity bidirEntity3 = ds.get(KeyFactory.stringToKey(bidir3.getId()));
  1115. bidirEntity3.setProperty("DISCRIMINATOR", "M");
  1116. if (isIndexed() && hasIndexPropertyInChild(pm)) {
  1117. // Only have index property when using older storageVersions
  1118. assertEquals(0L, unidirEntity1.getProperty("unidirChildren_INTEGER_IDX_unencodedstringpk"));
  1119. assertEquals(1L, unidirEntity3.getProperty("unidirChildren_INTEGER_IDX_unencodedstringpk"));
  1120. assertEquals(0L, bidirEntity1.getProperty("bidirChildren_INTEGER_IDX"));
  1121. assertEquals(1L, bidirEntity3.getProperty("bidirChildren_INTEGER_IDX"));
  1122. }
  1123. try {
  1124. ds.get(KeyFactory.stringToKey(f2Id));
  1125. fail("expected enfe");
  1126. } catch (EntityNotFoundException enfe) {
  1127. // good
  1128. }
  1129. try {
  1130. ds.get(KeyFactory.stringToKey(bidir2Id));
  1131. fail("expected enfe");
  1132. } catch (EntityNotFoundException enfe) {
  1133. // good
  1134. }
  1135. }
  1136. void testChangeParent(HasOneToManyJDO pojo, HasOneToManyJDO pojo2,
  1137. StartEnd startEnd, UnidirLevel unidirLevel) {
  1138. switchDatasource(PersistenceManagerFactoryName.nontransactional);
  1139. UnidirTop unidir1 = newUnidir(unidirLevel);
  1140. pojo.addUnidirChild(unidir1);
  1141. startEnd.start();
  1142. pm.makePersistent(pojo);
  1143. startEnd.end();
  1144. startEnd.start();
  1145. pojo2.addUnidirChild(unidir1);
  1146. try {
  1147. pm.makePersistent(pojo2);
  1148. fail("expected exception");
  1149. } catch (JDOFatalUserException e) {
  1150. if (pm.currentTransaction().isActive()) {
  1151. rollbackTxn();
  1152. }
  1153. }
  1154. }
  1155. void testNewParentNewChild_NamedKeyOnChild(HasOneToManyJDO pojo, StartEnd startEnd,
  1156. UnidirLevel unidirLevel) throws EntityNotFoundException {
  1157. UnidirTop unidir1 = newUnidir(unidirLevel);
  1158. pojo.addUnidirChild(unidir1);
  1159. unidir1.setId(KeyFactory.keyToString(
  1160. KeyFactory.createKey(getEntityKind(UnidirTop.class), "named key")));
  1161. startEnd.start();
  1162. pm.makePersistent(pojo);
  1163. startEnd.end();
  1164. Entity unidirEntity = ds.get(KeyFactory.stringToKey(unidir1.getId()));
  1165. assertEquals("named key", unidirEntity.getKey().getName());
  1166. }
  1167. void testAddAlreadyPersistedChildToParent_NoTxnSamePm(HasOneToManyJDO pojo,
  1168. UnidirLevel unidirLevel, int count) {
  1169. switchDatasource(PersistenceManagerFactoryName.nontransactional);
  1170. UnidirTop unidir = newUnidir(unidirLevel);
  1171. pm.makePersistent(unidir);
  1172. pojo.addUnidirChild(unidir);
  1173. try {
  1174. pm.makePersistent(pojo);
  1175. fail("expected exception");
  1176. } catch (JDOFatalUserException e) {
  1177. // good
  1178. }
  1179. pm.close();
  1180. assertEquals(0, countForClass(pojo.getClass()));
  1181. assertEquals(count, countForClass(UnidirTop.class));
  1182. }
  1183. void testAddAlreadyPersistedChildToParent_NoTxnDifferentPm(HasOneToManyJDO pojo,
  1184. UnidirLevel unidirLevel, int count) {
  1185. switchDatasource(PersistenceManagerFactoryName.nontransactional);
  1186. UnidirTop unidir1 = newUnidir(unidirLevel);
  1187. pm.makePersistent(unidir1);
  1188. unidir1 = pm.detachCopy(unidir1);
  1189. pm.close();
  1190. pm = pmf.getPersistenceManager();
  1191. unidir1 = pm.makePersistent(unidir1);
  1192. pojo.addUnidirChild(unidir1);
  1193. try {
  1194. pm.makePersistent(pojo);
  1195. fail("expected exception");
  1196. } catch (JDOFatalUserException e) {
  1197. // good
  1198. }
  1199. pm.close();
  1200. assertEquals(0, countForClass(pojo.getClass()));
  1201. assertEquals(count, countForClass(UnidirTop.class));
  1202. }
  1203. void testFetchOfOneToManyParentWithKeyPk(HasOneToManyKeyPkJDO pojo, StartEnd startEnd) {
  1204. startEnd.start();
  1205. pm.makePersistent(pojo);
  1206. startEnd.end();
  1207. startEnd.start();
  1208. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  1209. assertEquals(0, pojo.getUnidirChildren().size());
  1210. startEnd.end();
  1211. }
  1212. void testFetchOfOneToManyParentWithLongPk(HasOneToManyLongPkJDO pojo, StartEnd startEnd) {
  1213. startEnd.start();
  1214. pm.makePersistent(pojo);
  1215. startEnd.end();
  1216. startEnd.start();
  1217. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  1218. assertEquals(0, pojo.getUnidirChildren().size());
  1219. startEnd.end();
  1220. }
  1221. void testFetchOfOneToManyParentWithUnencodedStringPk(HasOneToManyUnencodedStringPkJDO pojo, StartEnd startEnd) {
  1222. pojo.setId("yar");
  1223. startEnd.start();
  1224. pm.makePersistent(pojo);
  1225. startEnd.end();
  1226. startEnd.start();
  1227. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  1228. assertEquals(0, pojo.getUnidirChildren().size());
  1229. startEnd.end();
  1230. }
  1231. void testAddChildToOneToManyParentWithLongPk(
  1232. HasOneToManyLongPkJDO pojo, BidirTopLongPk bidirChild, StartEnd startEnd,
  1233. UnidirLevel unidirLevel) throws EntityNotFoundException {
  1234. startEnd.start();
  1235. pm.makePersistent(pojo);
  1236. startEnd.end();
  1237. startEnd.start();
  1238. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  1239. UnidirTop unidir = newUnidir(unidirLevel);
  1240. pojo.addUnidirChild(unidir);
  1241. pojo.addBidirChild(bidirChild);
  1242. startEnd.end();
  1243. Entity unidirEntity = ds.get(KeyFactory.stringToKey(unidir.getId()));
  1244. Entity bidirEntity = ds.get(KeyFactory.stringToKey(bidirChild.getId()));
  1245. Entity pojoEntity = ds.get(KeyFactory.createKey(getEntityKind(pojo.getClass()), pojo.getId()));
  1246. assertEquals(pojoEntity.getKey(), unidirEntity.getParent());
  1247. assertEquals(pojoEntity.getKey(), bidirEntity.getParent());
  1248. }
  1249. void testAddChildToOneToManyParentWithUnencodedStringPk(
  1250. HasOneToManyUnencodedStringPkJDO pojo, BidirTopUnencodedStringPkJDO bidirChild,
  1251. StartEnd startEnd, UnidirLevel unidirLevel, String id) throws EntityNotFoundException {
  1252. pojo.setId(id);
  1253. startEnd.start();
  1254. pm.makePersistent(pojo);
  1255. startEnd.end();
  1256. startEnd.start();
  1257. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  1258. UnidirTop unidir = newUnidir(unidirLevel);
  1259. pojo.addUnidirChild(unidir);
  1260. pojo.addBidirChild(bidirChild);
  1261. startEnd.end();
  1262. Entity unidirEntity = ds.get(KeyFactory.stringToKey(unidir.getId()));
  1263. Entity bidirEntity = ds.get(KeyFactory.stringToKey(bidirChild.getId()));
  1264. Entity pojoEntity = ds.get(KeyFactory.createKey(getEntityKind(pojo.getClass()), pojo.getId()));
  1265. assertEquals(pojoEntity.getKey(), unidirEntity.getParent());
  1266. assertEquals(pojoEntity.getKey(), bidirEntity.getParent());
  1267. }
  1268. void testAddQueriedParentToBidirChild(HasOneToManyJDO pojo, BidirectionalSuperclassTableChildJDO.BidirTop bidir,
  1269. StartEnd startEnd, String bidirKind) throws EntityNotFoundException {
  1270. deleteAll(bidirKind);
  1271. deleteAll(getEntityKind(pojo.getClass()));
  1272. startEnd.start();
  1273. pm.makePersistent(pojo);
  1274. startEnd.end();
  1275. startEnd.start();
  1276. pojo = (HasOneToManyJDO) ((List<?>)pm.newQuery(pojo.getClass()).execute()).get(0);
  1277. bidir.setParent(pojo);
  1278. pojo.addBidirChild(bidir);
  1279. pm.makePersistent(bidir);
  1280. startEnd.end();
  1281. assertEquals(1, countForClass(bidir.getClass()));
  1282. Entity e = ds.prepare(new Query(bidirKind)).asSingleEntity();
  1283. assertNotNull(e.getParent());
  1284. startEnd.start();
  1285. pojo = (HasOneToManyJDO) ((List<?>)pm.newQuery(pojo.getClass()).execute()).get(0);
  1286. assertEquals(1, pojo.getBidirChildren().size());
  1287. startEnd.end();
  1288. Entity bidirEntity = ds.get(KeyFactory.stringToKey(bidir.getId()));
  1289. Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
  1290. assertEquals(pojoEntity.getKey(), bidirEntity.getParent());
  1291. }
  1292. void testAddFetchedParentToBidirChild(HasOneToManyJDO pojo, BidirectionalSuperclassTableChildJDO.BidirTop bidir,
  1293. StartEnd startEnd, String bidirKind) throws EntityNotFoundException {
  1294. deleteAll(bidirKind);
  1295. deleteAll(getEntityKind(pojo.getClass()));
  1296. startEnd.start();
  1297. pm.makePersistent(pojo);
  1298. startEnd.end();
  1299. startEnd.start();
  1300. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  1301. bidir.setParent(pojo);
  1302. pm.makePersistent(bidir);
  1303. pojo.addBidirChild(bidir);
  1304. startEnd.end();
  1305. assertEquals(1, countForClass(bidir.getClass()));
  1306. Entity e = ds.prepare(new Query(bidirKind)).asSingleEntity();
  1307. assertNotNull(e.getParent());
  1308. startEnd.start();
  1309. pojo = (HasOneToManyJDO) ((List<?>)pm.newQuery(pojo.getClass()).execute()).get(0);
  1310. assertEquals(1, pojo.getBidirChildren().size());
  1311. startEnd.end();
  1312. Entity bidirEntity = ds.get(KeyFactory.stringToKey(bidir.getId()));
  1313. Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
  1314. assertEquals(pojoEntity.getKey(), bidirEntity.getParent());
  1315. }
  1316. void testReplaceBidirColl(HasOneToManyJDO parent,
  1317. BidirectionalSuperclassTableChildJDO.BidirTop bidir1,
  1318. Collection<? extends BidirectionalSuperclassTableChildJDO.BidirTop> newColl, StartEnd startEnd) {
  1319. bidir1.setParent(parent);
  1320. parent.addBidirChild(bidir1);
  1321. startEnd.start();
  1322. pm.makePersistent(parent);
  1323. startEnd.end();
  1324. String childKey = bidir1.getId();
  1325. startEnd.start();
  1326. parent = pm.getObjectById(parent.getClass(), KeyFactory.stringToKey(parent.getId()));
  1327. parent.setBidirChildren(newColl);
  1328. startEnd.end();
  1329. startEnd.start();
  1330. parent = pm.getObjectById(parent.getClass(), KeyFactory.stringToKey(parent.getId()));
  1331. assertEquals(2, parent.getBidirChildren().size());
  1332. Iterator<? extends BidirectionalSuperclassTableChildJDO.BidirTop> childIter = parent.getBidirChildren().iterator();
  1333. assertFalse(childKey.equals(childIter.next().getId()));
  1334. assertFalse(childKey.equals(childIter.next().getId()));
  1335. startEnd.end();
  1336. assertEquals(2, countForClass(newColl.iterator().next().getClass()));
  1337. }
  1338. private static final class PutPolicy implements DatastoreServiceInterceptor.Policy {
  1339. private final List<Object[]> putParamList = Utils.newArrayList();
  1340. public void intercept(Object o, Method method, Object[] params) {
  1341. if (method.getName().equals("put")) {
  1342. putParamList.add(params);
  1343. }
  1344. }
  1345. }
  1346. PutPolicy setupPutPolicy(HasOneToManyJDO pojo, BidirectionalSuperclassTableChildJDO.BidirTop bidir, StartEnd startEnd)
  1347. throws Throwable {
  1348. PutPolicy policy = new PutPolicy();
  1349. DatastoreServiceInterceptor.install(getStoreManager(), policy);
  1350. try {
  1351. pmf.close();
  1352. switchDatasource(startEnd.getPmfName());
  1353. UnidirTop unidir = new UnidirTop();
  1354. pojo.addUnidirChild(unidir);
  1355. pojo.addBidirChild(bidir);
  1356. startEnd.start();
  1357. pm.makePersistent(pojo);
  1358. startEnd.end();
  1359. // 1 put for the parent, 2 puts for the children, 1 more put
  1360. // to add the child keys back on the parent
  1361. assertEquals(4, policy.putParamList.size());
  1362. policy.putParamList.clear();
  1363. return policy;
  1364. } catch (Throwable t) {
  1365. DatastoreServiceInterceptor.uninstall();
  1366. throw t;
  1367. }
  1368. }
  1369. void testOnlyOnePutOnChildUpdate(HasOneToManyJDO pojo, BidirectionalSuperclassTableChildJDO.BidirTop bidir, StartEnd startEnd)
  1370. throws Throwable {
  1371. PutPolicy policy = setupPutPolicy(pojo, bidir, startEnd);
  1372. try {
  1373. startEnd.start();
  1374. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  1375. pojo.getUnidirChildren().iterator().next().setStr("str");
  1376. pojo.getBidirChildren().iterator().next().setChildVal("blarg");
  1377. startEnd.end();
  1378. } finally {
  1379. DatastoreServiceInterceptor.uninstall();
  1380. }
  1381. // 1 put for each child update
  1382. assertEquals(2, policy.putParamList.size());
  1383. }
  1384. void testOnlyOneParentPutOnParentAndChildUpdate(HasOneToManyJDO pojo, BidirectionalSuperclassTableChildJDO.BidirTop bidir, StartEnd startEnd)
  1385. throws Throwable {
  1386. PutPolicy policy = setupPutPolicy(pojo, bidir, startEnd);
  1387. try {
  1388. startEnd.start();
  1389. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  1390. pojo.setVal("another val");
  1391. pojo.getUnidirChildren().iterator().next().setStr("str");
  1392. pojo.getBidirChildren().iterator().next().setChildVal("blarg");
  1393. startEnd.end();
  1394. } finally {
  1395. DatastoreServiceInterceptor.uninstall();
  1396. }
  1397. // 1 put for the parent update, 1 put for each child update
  1398. assertEquals(3, policy.putParamList.size());
  1399. }
  1400. void testOnlyOneParentPutOnChildDelete(HasOneToManyJDO pojo, BidirectionalSuperclassTableChildJDO.BidirTop bidir, StartEnd startEnd)
  1401. throws Throwable {
  1402. PutPolicy policy = setupPutPolicy(pojo, bidir, startEnd);
  1403. try {
  1404. startEnd.start();
  1405. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  1406. pojo.setVal("another val");
  1407. pojo.nullUnidirChildren();
  1408. pojo.nullBidirChildren();
  1409. startEnd.end();
  1410. } finally {
  1411. DatastoreServiceInterceptor.uninstall();
  1412. }
  1413. if (startEnd == TXN_START_END) {
  1414. // transactional, so 1 put for all updates
  1415. assertEquals(1, policy.putParamList.size());
  1416. } else {
  1417. // non-transactional, so 1 for each update
  1418. assertEquals(3, policy.putParamList.size());
  1419. }
  1420. }
  1421. void testNonTxnAddOfChildToParentFailsPartwayThrough(HasOneToManyJDO pojo)
  1422. throws Throwable {
  1423. UnidirTop unidir1 = new UnidirTop();
  1424. pojo.addUnidirChild(unidir1);
  1425. beginTxn();
  1426. pm.makePersistent(pojo);
  1427. commitTxn();
  1428. final String kind = kindForObject(pojo);
  1429. DatastoreServiceInterceptor.Policy policy = new DatastoreServiceInterceptor.Policy() {
  1430. public void intercept(Object o, Method method, Object[] params) {
  1431. if (method.getName().equals("put") && ((Entity) params[0]).getKind().equals(kind)) {
  1432. throw new ConcurrentModificationException("kaboom");
  1433. }
  1434. }
  1435. };
  1436. DatastoreServiceInterceptor.install(getStoreManager(), policy);
  1437. UnidirTop unidir2 = new UnidirBottom();
  1438. try {
  1439. pmf.close();
  1440. switchDatasource(PersistenceManagerFactoryName.nontransactional);
  1441. pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
  1442. pojo.addUnidirChild(unidir2);
  1443. pm.close();
  1444. fail("expected exception");
  1445. } catch (ConcurrentModificationException cme) {
  1446. // good
  1447. } finally {
  1448. DatastoreServiceInterceptor.uninstall();
  1449. }
  1450. // prove that the book entity exists
  1451. ds.get(KeyFactory.stringToKey(unidir2.getId()));
  1452. Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
  1453. // the parent has a reference to the first book that was already there
  1454. // but no reference to the second book
  1455. assertEquals(
  1456. Collections.singletonList(KeyFactory.stringToKey(unidir1.getId())),
  1457. pojoEntity.getProperty("unidirChildren"));
  1458. }
  1459. void assertCountsInDatastore(Class<? extends HasOneToManyJDO> parentClass,
  1460. Class<? extends BidirectionalSuperclassTableChildJDO.BidirTop> bidirClass,
  1461. int expectedParent, int expectedChildren) {
  1462. assertEquals(parentClass.getName(), expectedParent, countForClass(parentClass));
  1463. assertEquals(bidirClass.getName(), expectedChildren, countForClass(bidirClass));
  1464. assertEquals(UnidirTop.class.getName(), expectedChildren, countForClass(UnidirTop.class));
  1465. }
  1466. UnidirTop newUnidir(UnidirLevel level) {
  1467. switch (level) {
  1468. case Top:
  1469. UnidirTop top = new UnidirTop();
  1470. top.setStr("top");
  1471. top.setName("top name");
  1472. return top;
  1473. case Middle:
  1474. UnidirMiddle middle = new UnidirMiddle();
  1475. middle.setStr("middle");
  1476. middle.setName("middle name");
  1477. return middle;
  1478. case Bottom:
  1479. UnidirBottom bottom = new UnidirBottom();
  1480. bottom.setStr("bottom");
  1481. bottom.setName("bottom name");
  1482. return bottom;
  1483. default:
  1484. return null;
  1485. }
  1486. }
  1487. Entity newUnidir(UnidirLevel level, Key parentKey, String str, String name, Date date, Integer integer) {
  1488. switch (level) {
  1489. case Top:
  1490. Entity topEntity = new Entity(getEntityKind(UnidirTop.class), parentKey);
  1491. topEntity.setProperty("str", str);
  1492. topEntity.setProperty("name", name);
  1493. topEntity.setProperty("unidirChildren_INTEGER_IDX", 1);
  1494. topEntity.setProperty("TYPE", UnidirectionalSuperclassTableChildJDO.DISCRIMINATOR_TOP);
  1495. return topEntity;
  1496. case Middle:
  1497. Entity middleEntity = new Entity(getEntityKind(UnidirTop.class), parentKey);
  1498. middleEntity.setProperty("str", str);
  1499. middleEntity.setProperty("name", name);
  1500. middleEntity.setProperty("date", date);
  1501. middleEntity.setProperty("unidirChildren_INTEGER_IDX", 1);
  1502. middleEntity.setProperty("TYPE", UnidirectionalSuperclassTableChildJDO.DISCRIMINATOR_MIDDLE);
  1503. return middleEntity;
  1504. case Bottom:
  1505. Entity bottomEntity = new Entity(getEntityKind(UnidirTop.class), parentKey);
  1506. bottomEntity.setProperty("str", str);
  1507. bottomEntity.setProperty("name", name);
  1508. bottomEntity.setProperty("date", date);
  1509. bottomEntity.setProperty("integer", integer);
  1510. bottomEntity.setProperty("unidirChildren_INTEGER_IDX", 1);
  1511. bottomEntity.setProperty("TYPE", UnidirectionalSuperclassTableChildJDO.DISCRIMINATOR_BOTTOM);
  1512. return bottomEntity;
  1513. default:
  1514. return null;
  1515. }
  1516. }
  1517. protected int getIndexPropertyCount() {
  1518. return isIndexed() ? 1 : 0;
  1519. }
  1520. private void deleteAll(String kind) {
  1521. Query q = new Query(kind);
  1522. q.setKeysOnly();
  1523. ds.delete(Utils.transform(ds.prepare(q).asIterable(), new Function<Entity, Key>() {
  1524. public Key apply(Entity from) {
  1525. return from.getKey();
  1526. }}));
  1527. }
  1528. protected abstract void registerSubclasses();
  1529. abstract boolean isIndexed();
  1530. }