/* * Copyright 2009-2016 Tilmann Zaeschke. All rights reserved. * * This file is part of ZooDB. * * ZooDB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ZooDB is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ZooDB. If not, see <http://www.gnu.org/licenses/>. * * See the README and COPYING files for further information. */ package org.zoodb.test.jdo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import javax.jdo.JDOHelper; import javax.jdo.JDOUserException; import javax.jdo.PersistenceManager; import javax.jdo.PersistenceManagerFactory; import javax.jdo.listener.ClearLifecycleListener; import javax.jdo.listener.CreateLifecycleListener; import javax.jdo.listener.DeleteLifecycleListener; import javax.jdo.listener.DirtyLifecycleListener; import javax.jdo.listener.InstanceLifecycleEvent; import javax.jdo.listener.LoadLifecycleListener; import javax.jdo.listener.StoreLifecycleListener; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.zoodb.api.ZooInstanceEvent; import org.zoodb.jdo.ZooJdoProperties; import org.zoodb.test.testutil.TestTools; public class Test_046_TransactionsLifecycleListener { private static final ArrayList<Pair> calls = new ArrayList<Pair>(); private static final class Pair { final ZooInstanceEvent type; final InstanceLifecycleEvent e; public Pair(InstanceLifecycleEvent e, ZooInstanceEvent type) { this.e = e; this.type = type; } } @BeforeClass public static void setUp() { TestTools.createDb(); TestTools.defineSchema(TestClass.class); } @Before public void before() { TestTools.dropInstances(TestClass.class); calls.clear(); } private static class ListenerLoad implements LoadLifecycleListener { @Override public void postLoad(InstanceLifecycleEvent arg0) { registerCall(arg0, ZooInstanceEvent.LOAD); } } private static class ListenerStore implements StoreLifecycleListener { @Override public void postStore(InstanceLifecycleEvent arg0) { registerCall(arg0, ZooInstanceEvent.POST_STORE); } @Override public void preStore(InstanceLifecycleEvent arg0) { registerCall(arg0, ZooInstanceEvent.PRE_STORE); } } private static class ListenerClear implements ClearLifecycleListener { @Override public void postClear(InstanceLifecycleEvent arg0) { registerCall(arg0, ZooInstanceEvent.POST_CLEAR); } @Override public void preClear(InstanceLifecycleEvent arg0) { registerCall(arg0, ZooInstanceEvent.PRE_CLEAR); } } private static class ListenerDelete implements DeleteLifecycleListener { @Override public void postDelete(InstanceLifecycleEvent arg0) { registerCall(arg0, ZooInstanceEvent.POST_DELETE); } @Override public void preDelete(InstanceLifecycleEvent arg0) { registerCall(arg0, ZooInstanceEvent.PRE_DELETE); } } private static class ListenerCreate implements CreateLifecycleListener { @Override public void postCreate(InstanceLifecycleEvent arg0) { registerCall(arg0, ZooInstanceEvent.CREATE); } } private static class ListenerDirty implements DirtyLifecycleListener { @Override public void postDirty(InstanceLifecycleEvent arg0) { registerCall(arg0, ZooInstanceEvent.POST_DIRTY); } @Override public void preDirty(InstanceLifecycleEvent arg0) { registerCall(arg0, ZooInstanceEvent.PRE_DIRTY); } } @Test public void testLifecycleListenerFail() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); try { pm.addInstanceLifecycleListener(new ListenerClear(), TestClassTinyClone.class); } catch (JDOUserException e) { //good, this should NOT throw a NPE. } try { pm.addInstanceLifecycleListener(new ListenerClear(), (Class<?>)null); } catch (JDOUserException e) { //good, this should NOT throw a NPE. } try { pm.addInstanceLifecycleListener(new ListenerClear(), (Class<?>[])null); } catch (JDOUserException e) { //good, this should NOT throw a NPE. } TestTools.closePM(); } @Test public void testLifecycleListener() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); pm.addInstanceLifecycleListener(new ListenerClear(), TestClass.class); pm.addInstanceLifecycleListener(new ListenerCreate(), TestClass.class); pm.addInstanceLifecycleListener(new ListenerDelete(), TestClass.class); pm.addInstanceLifecycleListener(new ListenerDirty(), TestClass.class); pm.addInstanceLifecycleListener(new ListenerLoad(), TestClass.class); pm.addInstanceLifecycleListener(new ListenerStore(), TestClass.class); internalTest(pm); TestTools.closePM(); } @Test public void testLifecycleListenerNull() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); pm.addInstanceLifecycleListener(new ListenerClear(), (Class<?>)null); pm.addInstanceLifecycleListener(new ListenerCreate(), (Class<?>)null); pm.addInstanceLifecycleListener(new ListenerDelete(), (Class<?>)null); pm.addInstanceLifecycleListener(new ListenerDirty(), (Class<?>)null); pm.addInstanceLifecycleListener(new ListenerLoad(), (Class<?>)null); pm.addInstanceLifecycleListener(new ListenerStore(), (Class<?>)null); internalTest(pm); TestTools.closePM(); } @Test public void testLifecycleListenerPMF() { ZooJdoProperties props = new ZooJdoProperties(TestTools.getDbName()); PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props); Class<?>[] clsA = new Class[]{TestClass.class}; pmf.addInstanceLifecycleListener(new ListenerClear(), clsA); pmf.addInstanceLifecycleListener(new ListenerCreate(), clsA); pmf.addInstanceLifecycleListener(new ListenerDelete(), clsA); pmf.addInstanceLifecycleListener(new ListenerDirty(), clsA); pmf.addInstanceLifecycleListener(new ListenerLoad(), clsA); pmf.addInstanceLifecycleListener(new ListenerStore(), clsA); PersistenceManager pm = pmf.getPersistenceManager(); pm.currentTransaction().begin(); internalTest(pm); TestTools.closePM(pm); } @Test public void testLifecycleListenerPmfNull() { ZooJdoProperties props = new ZooJdoProperties(TestTools.getDbName()); PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props); pmf.addInstanceLifecycleListener(new ListenerClear(), null); pmf.addInstanceLifecycleListener(new ListenerCreate(), null); pmf.addInstanceLifecycleListener(new ListenerDelete(), null); pmf.addInstanceLifecycleListener(new ListenerDirty(), null); pmf.addInstanceLifecycleListener(new ListenerLoad(), null); pmf.addInstanceLifecycleListener(new ListenerStore(), null); PersistenceManager pm = pmf.getPersistenceManager(); pm.currentTransaction().begin(); internalTest(pm); TestTools.closePM(pm); } private void internalTest(PersistenceManager pm) { TestClass t1 = new TestClass(); //to check clear() t1.setRef2(t1); assertTrue(calls.isEmpty()); //check CREATE pm.makePersistent(t1); checkCall(ZooInstanceEvent.CREATE, t1); assertTrue(calls.isEmpty()); //check STORE pm.currentTransaction().commit(); checkCall(ZooInstanceEvent.PRE_STORE, t1); //preStore checkCall(ZooInstanceEvent.PRE_CLEAR, t1); checkCall(ZooInstanceEvent.POST_CLEAR, t1); checkCall(ZooInstanceEvent.POST_STORE, t1); //postStore assertTrue(calls.isEmpty()); pm.currentTransaction().begin(); // check LOAD assertNotNull(t1.getRef2()); checkCall(ZooInstanceEvent.LOAD, t1); assertTrue(calls.isEmpty()); // check modify t1.setRef2(null); checkCall(ZooInstanceEvent.PRE_DIRTY, t1); checkCall(ZooInstanceEvent.POST_DIRTY, t1); System.err.println("WARNING InstanceLifecycles are currently not correct. " + "PRE_DIRTY and POST_DIRTY should be triggered BEFORE/AFTER a field is modified."); assertTrue(calls.isEmpty()); //check refresh-LOAD pm.refresh(t1); checkCall(ZooInstanceEvent.LOAD, t1); assertTrue(calls.isEmpty()); //check DELETE pm.deletePersistent(t1); assertTrue(calls.isEmpty()); pm.currentTransaction().commit(); checkCall(ZooInstanceEvent.PRE_DELETE, t1); checkCall(ZooInstanceEvent.POST_DELETE, t1); assertTrue(calls.isEmpty()); } @Test public void testLifecycleListenerRemoval() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ListenerCreate lc = new ListenerCreate(); pm.addInstanceLifecycleListener(lc, TestClass.class); TestClass t1 = new TestClass(); assertTrue(calls.isEmpty()); //check CREATE pm.makePersistent(t1); checkCall(ZooInstanceEvent.CREATE, t1); assertTrue(calls.isEmpty()); //remove listener pm.removeInstanceLifecycleListener(lc); TestClass t2 = new TestClass(); pm.makePersistent(t2); assertTrue(calls.isEmpty()); pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testLifecycleListenerRemovalPmf() { ZooJdoProperties props = new ZooJdoProperties(TestTools.getDbName()); PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props); ListenerCreate lc = new ListenerCreate(); pmf.addInstanceLifecycleListener(lc, new Class[]{TestClass.class}); pmf.removeInstanceLifecycleListener(lc); PersistenceManager pm = pmf.getPersistenceManager(); pm.currentTransaction().begin(); TestClass t1 = new TestClass(); assertTrue(calls.isEmpty()); //check CREATE pm.makePersistent(t1); assertTrue(calls.isEmpty()); //remove listener TestClass t2 = new TestClass(); pm.makePersistent(t2); assertTrue(calls.isEmpty()); pm.currentTransaction().rollback(); TestTools.closePM(pm); } private void checkCall(ZooInstanceEvent expected, Object pc) { assertTrue(calls.size() > 0); Pair p = calls.get(0); //System.out.println("calls:" + calls.size() + " " + p.e.getPersistentInstance()); //System.out.println("calls:" + p.type + " " + p.e.getPersistentInstance().getClass()); assertEquals(expected, p.type); assertEquals(TestClass.class, p.e.getSource().getClass()); assertTrue(pc == p.e.getPersistentInstance()); calls.remove(0); } private static void registerCall(InstanceLifecycleEvent e, ZooInstanceEvent type) { calls.add(new Pair(e, type)); } @Test public void testDirtyOnlyOnFirstCall() { ZooJdoProperties props = new ZooJdoProperties(TestTools.getDbName()); PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props); pmf.addInstanceLifecycleListener(new ListenerDirty(), new Class[]{TestClass.class}); PersistenceManager pm = pmf.getPersistenceManager(); pm.currentTransaction().begin(); TestClass t1 = new TestClass(); pm.makePersistent(t1); assertTrue(calls.isEmpty()); //should do nothing, is already dirty! t1.setInt(3); assertTrue(calls.isEmpty()); //should do nothing, is already dirty! JDOHelper.makeDirty(t1, "_int"); assertTrue(calls.isEmpty()); //check STORE pm.currentTransaction().commit(); pm.currentTransaction().begin(); // check modify t1.setInt(3); checkCall(ZooInstanceEvent.PRE_DIRTY, t1); checkCall(ZooInstanceEvent.POST_DIRTY, t1); assertTrue(calls.isEmpty()); // check modify again does nothing t1.setInt(5); assertTrue(calls.isEmpty()); //should do nothing, is already dirty! JDOHelper.makeDirty(t1, "_int"); assertTrue(calls.isEmpty()); pm.currentTransaction().commit(); TestTools.closePM(pm); } @After public void afterTest() { TestTools.closePM(); } @AfterClass public static void tearDown() { TestTools.removeDb(); } }