/**
* Speedo: an implementation of JDO compliant personality on top of JORM generic
* I/O sub-system.
* Copyright (C) 2001-2004 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
*
* Contact: speedo@objectweb.org
*
*/
package org.objectweb.speedo.runtime.detach;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.jdo.Extent;
import javax.jdo.JDOException;
import javax.jdo.JDOUserException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import junit.framework.Assert;
import org.objectweb.speedo.SpeedoTestHelper;
import org.objectweb.speedo.api.ExceptionHelper;
import org.objectweb.speedo.mim.jdo.api.JDOPersistentObjectItf;
import org.objectweb.speedo.pobjects.detach.Car;
import org.objectweb.speedo.pobjects.detach.Coach;
import org.objectweb.speedo.pobjects.detach.FormulaOne;
import org.objectweb.speedo.pobjects.detach.Player;
import org.objectweb.speedo.pobjects.detach.Team;
import org.objectweb.speedo.pobjects.detach.Vehicle;
import org.objectweb.speedo.pobjects.map.C;
import org.objectweb.speedo.pobjects.map.D;
import org.objectweb.util.monolog.api.BasicLevel;
/**
* @author Y.Bersihand
*/
public class TestDetach extends SpeedoTestHelper {
public TestDetach(String s) {
super(s);
}
protected String getLoggerName() {
return LOG_NAME + ".rt.detach.TestDetach";
}
/**
* Test the deatch on an object which references a map.
*/
public void testDetachMap() {
logger.log(BasicLevel.DEBUG, "***************testDetachMap*****************");
int MAP_SIZE = 10;
String F1_PREFIX = "f1_";
PersistenceManager pm = pmf.getPersistenceManager();
//Create instances
pm.currentTransaction().begin();
C c = new C(1);
ArrayList ds = new ArrayList(MAP_SIZE * 2);
for(int i=0; i<MAP_SIZE; i++) {
String f1 = F1_PREFIX + i;
ds.add(new D(i, f1));
}
pm.makePersistent(c);
pm.makePersistentAll(ds);
pm.currentTransaction().commit();
//Add into the map
pm.currentTransaction().begin();
Map m = c.getDkey2d();
for(int i=0; i<MAP_SIZE; i++) {
D d = (D) ds.get(i);
m.put(d.getF1(), d);
}
pm.currentTransaction().commit();
pm.getFetchPlan().addGroup("all").removeGroup("default");
C copyOfC = (C) pm.detachCopy(c);
assertEquals("Not the same id for c and its detached copy", c.getMyid(), copyOfC.getMyid());
Map mC = c.getDkey2d();
Map mCopyOfC = copyOfC.getDkey2d();
assertEquals("The maps' size should be the same.",mC.size(), mCopyOfC.size());
Iterator itC = mC.values().iterator();
Collection col = mCopyOfC.values();
while(itC.hasNext()) {
D dC = (D) itC.next();
boolean contained = false;
Iterator it = col.iterator();
while (it.hasNext() && !contained) {
D dCopy = (D) it.next();
if (dC.getMyid()==dCopy.getMyid() && dC.getF1().equals(dCopy.getF1()))
contained = true;
}
assertTrue("The element " + dC.getMyid() + " is not contained", contained);
}
}
/**
* Test the detach method: make an object persistent, and detach it out of an active transaction.
*/
public void testDetachCopy() {
logger.log(BasicLevel.DEBUG, "***************testDetachCopy*****************");
Team t = new Team("Bordeaux",null,null);
Collection players = new ArrayList();
Player p1 = new Player("p1", t, 25);
players.add(p1);
Player p2 = new Player("p2", t, 32);
players.add(p2);
t.setPlayers(players);
Coach c = new Coach("c1", 5, t);
t.setCoach(c);
PersistenceManager pm = pmf.getPersistenceManager();
pm.currentTransaction().begin();
logger.log(BasicLevel.DEBUG, "make persistent the team " + t.toString());
pm.makePersistent(t);
pm.currentTransaction().commit();
t = null;
p1 = null;
p2 = null;
c = null;
pm.evictAll();
pm.close();
pm = pmf.getPersistenceManager();
Query query = pm.newQuery(Team.class, "players.contains(player) & player.age<12");
query.declareVariables("Player player");
Collection results = (Collection)query.execute();
assertTrue("The result of the query should be empty.", results.isEmpty());
query.closeAll();
query = pm.newQuery(Team.class, "players.contains(player) & player.age>12");
query.declareVariables("Player player");
results = (Collection)query.execute();
assertTrue("The result of the query shouldn't be empty.", !results.isEmpty());
Team res = (Team) results.iterator().next();
Collection cpl = res.getPlayers();
Iterator itPlayer = cpl.iterator();
while(itPlayer.hasNext()) {
Player pl = (Player) itPlayer.next();
assertTrue("The age of the player should be over 12. It is " + pl.getAge() + ".", pl.getAge()>12);
}
query.closeAll();
query = pm.newQuery(Team.class, "town==\"Bordeaux\"");
results = (Collection)query.execute();
assertEquals("The result of the query shouldn't be empty.", false, results.isEmpty());
Team toDetach = (Team) results.iterator().next();
query.closeAll();
//detach the team t
Team copyOfT = (Team) pm.detachCopy(toDetach);
try {
assertNotNull(copyOfT);
assertEquals("Town of team and detached team are not the same", toDetach.getTown(), copyOfT.getTown());
assertEquals("Coach experience of team and detached team are not the same",toDetach.getCoach().getExperience(), copyOfT.getCoach().getExperience());
assertEquals("Coach name of team and detached team are not the same",toDetach.getCoach().getName(), copyOfT.getCoach().getName());
//print the team out
logger.log(BasicLevel.DEBUG, copyOfT.toString());
} catch (Exception e) {
fail(e.getMessage());
} finally {
if (pm.currentTransaction().isActive())
pm.currentTransaction().rollback();
pm.close();
}
}
/**
* Test the detach method with a non persistent object: the object is made persistent before being detached.
*/
public void testDetachNonPersistentCopy() {
logger.log(BasicLevel.DEBUG, "*************testDetachNonPersistentCopy*****************");
Team t = new Team("Marseille",null,null);
Coach c = new Coach("c2", 5, t);
t.setCoach(c);
Player p = new Player("p3", t, 25);
t.addPlayer(p);
PersistenceManager pm = pmf.getPersistenceManager();
pm.currentTransaction().begin();
//detach the team t while it is not persistent
Team copyOfT = (Team) pm.detachCopy(t);
pm.currentTransaction().commit();
try {
assertNotNull(copyOfT);
assertTrue(((JDOPersistentObjectItf )t).jdoIsPersistent());
// print the team out
logger.log(BasicLevel.DEBUG, copyOfT.toString());
} catch(Exception e) {
fail(e.getMessage());
} finally {
if (pm.currentTransaction().isActive())
pm.currentTransaction().rollback();
pm.close();
}
}
/**
* Test the detach method with a persistent-new object: the object is flushed before being detached.
*/
public void testDetachPersistentNew() {
logger.log(BasicLevel.DEBUG, "******************testDetachPersistentNew****************");
Team t = new Team("Monaco",null,null);
Coach c = new Coach("c3", 5, t);
t.setCoach(c);
Player p = new Player("p4", t, 25);
t.addPlayer(p);
PersistenceManager pm = pmf.getPersistenceManager();
pm.currentTransaction().begin();
pm.makePersistent(c);
//detach the team while it is persistent-new: the object must be flushed before being detached
Team copyOfT = (Team) pm.detachCopy(t);
try {
assertNotNull(copyOfT);
assertEquals("Town of team and detached team are not the same", t.getTown(), copyOfT.getTown());
assertEquals("Coach experience of team and detached team are not the same",t.getCoach().getExperience(), copyOfT.getCoach().getExperience());
assertEquals("Coach name of team and detached team are not the same",t.getCoach().getName(), copyOfT.getCoach().getName());
pm.currentTransaction().commit();
// print the team out
logger.log(BasicLevel.DEBUG, copyOfT.toString());
} catch(Exception e) {
fail(e.getMessage());
} finally {
if (pm.currentTransaction().isActive())
pm.currentTransaction().rollback();
pm.close();
}
}
/**
* Test the detach method with a persistent-dirty object: the object is flushed before being detached.
*/
public void testDetachPersistentDirty() {
logger.log(BasicLevel.DEBUG, "******************testDetachPersistentDirty****************");
Team t = new Team("Nantes",null,null);
Coach c = new Coach("c4", 5, t);
t.setCoach(c);
Player p = new Player("p5", t, 28);
t.addPlayer(p);
PersistenceManager pm = pmf.getPersistenceManager();
//make persistent
pm.currentTransaction().begin();
pm.makePersistent(c);
pm.currentTransaction().commit();
//update and detach
pm.currentTransaction().begin();
c.setExperience(10);
//detach the team while it is persistent-dirty: the object must be flushed before being detached
Team copyOfT = (Team) pm.detachCopy(t);
pm.currentTransaction().commit();
try {
assertEquals(10, copyOfT.getCoach().getExperience());
logger.log(BasicLevel.DEBUG, copyOfT.toString());
} catch(Exception e) {
fail(e.getMessage());
} finally {
if (pm.currentTransaction().isActive())
pm.currentTransaction().rollback();
pm.close();
}
}
/**
* Test the detach method with a persistent-deleted object: an exception must be thrown.
*/
public void testDetachPersistentDeleted() {
logger.log(BasicLevel.DEBUG, "******************testDetachPersistentDeleted****************");
Team t = new Team("Paris",null, null);
Coach c = new Coach("c5", 5, t);
t.setCoach(c);
Player p = new Player("p6", t, 28);
t.addPlayer(p);
PersistenceManager pm = pmf.getPersistenceManager();
//make persistent
pm.currentTransaction().begin();
pm.makePersistent(c);
pm.currentTransaction().commit();
//delete
pm.currentTransaction().begin();
pm.deletePersistent(c);
try {
//detach the coach c while it is persistent-deleted: an exception must be thrown
pm.detachCopy(c);
pm.currentTransaction().commit();
} catch (Exception e) {
assertEquals("Wrong exception thrown: " + e.getMessage(),
JDOUserException.class, e.getClass());
} finally {
if (pm.currentTransaction().isActive()) {
pm.currentTransaction().commit();
}
pm.close();
}
}
/**
* Test the detach method with a persistent-deleted object within a collection: an exception must be thrown.
*/
public void testDetachPersistentDeletedCollection() {
logger.log(BasicLevel.DEBUG, "******************testDetachPersistentDeletedCollection****************");
Team t = new Team("Auxerre",null, null);
Coach c = new Coach("c6", 10, t);
t.setCoach(c);
Player p = new Player("p7", t, 28);
t.addPlayer(p);
PersistenceManager pm = pmf.getPersistenceManager();
//make persistent
pm.currentTransaction().begin();
pm.makePersistent(c);
pm.currentTransaction().commit();
//delete
pm.currentTransaction().begin();
pm.deletePersistent(p);
try{
// detach the coach c while it is persistent-deleted:
// an exception must be thrown
pm.detachCopy(c);
pm.currentTransaction().commit();
} catch (Exception e) {
assertEquals("Wrong exception thrown: " + e.getMessage(),
JDOUserException.class, e.getClass());
} finally {
if (pm.currentTransaction().isActive()) {
pm.currentTransaction().commit();
}
pm.close();
}
}
/**
* Test the detach method: make an object persistent with a null refrence, and detach it out of an active transaction.
*/
public void testDetachNullReference() {
logger.log(BasicLevel.DEBUG, "***************testDetachNullReference*****************");
Team t = new Team("Niort",null,null);
Collection players = new ArrayList();
Player p1 = new Player("p8", t, 25);
players.add(p1);
Player p2 = new Player("p9", t, 32);
players.add(p2);
t.setPlayers(players);
PersistenceManager pm = pmf.getPersistenceManager();
pm.currentTransaction().begin();
logger.log(BasicLevel.DEBUG, "make persistent the team " + t.toString());
pm.makePersistent(t);
pm.currentTransaction().commit();
try {
Extent extent = pm.getExtent(Team.class, false);
Query query = pm.newQuery(extent, "town == townName");
query.declareParameters("String townName");
Collection collection = (Collection) query.execute(t.getTown());
assertTrue("The result should not be empty", !collection.isEmpty());
Iterator itr = collection.iterator();
Team copyOfT = null;
while (itr.hasNext()) {
Team team = (Team) itr.next();
assertEquals("The town should be " + t.getTown(), t.getTown(), team.getTown());
//detach the team t
copyOfT = (Team) pm.detachCopy(team);
}
query.close(collection);
extent.closeAll();
assertNotNull(copyOfT);
assertEquals("Town of team and detached team are not the same", t.getTown(), copyOfT.getTown());
assertNull("The coach reference is supposed to be null", copyOfT.getCoach());
} catch (Exception e) {
fail(e.getMessage());
} finally {
if (pm.currentTransaction().isActive())
pm.currentTransaction().rollback();
pm.close();
}
}
/**
* Test the makePersistent on an object referencing a detached one
*/
public void testNewReferencingDetached() {
PersistenceManager pm = pmf.getPersistenceManager();
try {
logger.log(BasicLevel.DEBUG, "******************testNewReferencingDetached****************");
Coach c = new Coach("cXX", 10, null);
//make persistent the coach
pm.currentTransaction().begin();
pm.makePersistent(c);
pm.currentTransaction().commit();
//detach a copy
Coach copyOfC = (Coach) pm.detachCopy(c);
//create a team referencing the detached coach
Team t = new Team("LeMans",null, null);
t.setCoach(copyOfC);
//make persistent the team
pm.currentTransaction().begin();
pm.makePersistent(t);
pm.currentTransaction().commit();
assertNotNull(t.getCoach());
assertEquals(t.getCoach().getName(), c.getName());
} catch(Exception e) {
fail(e.getMessage());
} finally {
if (pm.currentTransaction().isActive())
pm.currentTransaction().rollback();
pm.close();
}
}
/**
* Test the detach method with inheritance.
*/
public void testDetachInherited() {
logger.log(BasicLevel.DEBUG, "***************testDetachInherited*****************");
Car c = new Car("r5", 4, "red");
FormulaOne f = new FormulaOne("williams", 4, "green", 262);
PersistenceManager pm = pmf.getPersistenceManager();
pm.currentTransaction().begin();
logger.log(BasicLevel.DEBUG, "make persistent the car " + c.toString() +
" and the formula one " + f.toString());
pm.makePersistent(c);
pm.makePersistent(f);
pm.currentTransaction().commit();
try {
//detach the car c
Car copyOfC = (Car) pm.detachCopy(c);
assertNotNull(copyOfC);
assertEquals(c.getName(), copyOfC.getName());
assertEquals(c.getColor(), copyOfC.getColor());
assertEquals(c.getNbOfWheels(), copyOfC.getNbOfWheels());
assertEquals(c.getType(), copyOfC.getType());
// print the car out
logger.log(BasicLevel.DEBUG, copyOfC.toString());
//detach the formula one f
FormulaOne copyOfF = (FormulaOne) pm.detachCopy(f);
assertNotNull(copyOfF);
assertEquals(f.getName(), copyOfF.getName());
assertEquals(f.getColor(), copyOfF.getColor());
assertEquals(f.getNbOfWheels(), copyOfF.getNbOfWheels());
assertEquals(f.getType(), copyOfF.getType());
assertEquals(f.getSpeedMax(), copyOfF.getSpeedMax());
//print the formula one out
logger.log(BasicLevel.DEBUG, copyOfF.toString());
} catch(Exception e) {
fail(e.getMessage());
} finally {
if (pm.currentTransaction().isActive())
pm.currentTransaction().rollback();
pm.close();
}
}
/**
* Test the detach method with a non persistent object which is inherited from a super class: the object is made persistent before being detached.
*/
public void testDetachNonPersistentInherited() {
logger.log(BasicLevel.DEBUG, "*************testDetachNonPersistentInherited*****************");
FormulaOne f = new FormulaOne("sauber", 4, "blue", 274);
PersistenceManager pm = pmf.getPersistenceManager();
pm.currentTransaction().begin();
// detach the formula one f while it is not persistent
FormulaOne copyOfF = (FormulaOne) pm.detachCopy(f);
assertTrue(((JDOPersistentObjectItf) f).jdoIsPersistent());
pm.currentTransaction().commit();
try {
assertNotNull(copyOfF);
assertEquals(f.getName(), copyOfF.getName());
assertEquals(f.getColor(), copyOfF.getColor());
assertEquals(f.getNbOfWheels(), copyOfF.getNbOfWheels());
assertEquals(f.getType(), copyOfF.getType());
assertEquals(f.getSpeedMax(), copyOfF.getSpeedMax());
//print the team out
logger.log(BasicLevel.DEBUG, copyOfF.toString());
} catch(Exception e) {
fail(e.getMessage());
} finally {
if (pm.currentTransaction().isActive())
pm.currentTransaction().rollback();
pm.close();
}
}
/**
* Test the detach method with a persistent-deleted inherited object: an exception must be thrown.
*/
public void testDetachPersistentDeletedInherited() {
logger.log(BasicLevel.DEBUG, "******************testDetachPersistentDeletedInherited****************");
FormulaOne f = new FormulaOne("honda", 4, "yellow", 240);
PersistenceManager pm = pmf.getPersistenceManager();
//make persistent
pm.currentTransaction().begin();
pm.makePersistent(f);
pm.currentTransaction().commit();
//delete
pm.currentTransaction().begin();
pm.deletePersistent(f);
try{
//detach the coach c while it is persistent-deleted: an exception must be thrown
pm.detachCopy(f);
} catch(Exception e){
assertEquals("Wrong exception thrown: ",JDOUserException.class, e.getClass());
} finally {
if (pm.currentTransaction().isActive())
pm.currentTransaction().rollback();
pm.close();
}
}
/**
* Test the detach method with a persistent-dirty inherited object: the object is flushed before being detached.
*/
public void testDetachPersistentDirtyInherited() {
logger.log(BasicLevel.DEBUG, "******************testDetachPersistentDirtyInherited****************");
FormulaOne f = new FormulaOne("ferrari", 4, "yellow", 240);
PersistenceManager pm = pmf.getPersistenceManager();
//make persistent
pm.currentTransaction().begin();
pm.makePersistent(f);
pm.currentTransaction().commit();
//update and detach
pm.currentTransaction().begin();
f.setNbOfWheels(3);
f.setSpeedMax(300);
pm.currentTransaction().commit();
try {
//detach the formula one while it is persistent-dirty: the object must be flushed before being detached
FormulaOne copyOfF = (FormulaOne) pm.detachCopy(f);
assertEquals(f.getName(), copyOfF.getName());
assertEquals(f.getColor(), copyOfF.getColor());
assertEquals(3, copyOfF.getNbOfWheels());
assertEquals(f.getType(), copyOfF.getType());
assertEquals(300, copyOfF.getSpeedMax());
//print the formula one out
logger.log(BasicLevel.DEBUG, copyOfF.toString());
} catch(Exception e) {
fail(e.getMessage());
} finally {
if (pm.currentTransaction().isActive())
pm.currentTransaction().rollback();
pm.close();
}
}
/**
* Test the detach method with a persistent-new inherited object: the object is flushed before being detached.
*/
public void testDetachPersistentNewInherited() {
logger.log(BasicLevel.DEBUG, "******************testDetachPersistentNewInherited****************");
FormulaOne f = new FormulaOne("renault", 4, "yellow", 260);
PersistenceManager pm = pmf.getPersistenceManager();
pm.currentTransaction().begin();
pm.makePersistent(f);
pm.currentTransaction().commit();
try {
//detach the formula one while it is persistent-new: the object must be flushed before being detached
FormulaOne copyOfF = (FormulaOne) pm.detachCopy(f);
assertEquals(f.getName(), copyOfF.getName());
assertEquals(f.getColor(), copyOfF.getColor());
assertEquals(f.getNbOfWheels(), copyOfF.getNbOfWheels());
assertEquals(f.getType(), copyOfF.getType());
assertEquals(f.getSpeedMax(), copyOfF.getSpeedMax());
// print the formula one out
logger.log(BasicLevel.DEBUG, copyOfF.toString());
} catch(Exception e) {
fail(e.getMessage());
} finally {
if (pm.currentTransaction().isActive())
pm.currentTransaction().rollback();
pm.close();
}
}
public void testRemovingOfPersistentObject() {
PersistenceManager pm = pmf.getPersistenceManager();
try {
Class[] cs = new Class[]{Coach.class, Player.class, Team.class, Vehicle.class};
pm.currentTransaction().begin();
for(int i=0; i<cs.length; i++) {
Query query = pm.newQuery(cs[i]);
Collection col = (Collection) query.execute();
Iterator it = col.iterator();
while(it.hasNext()) {
Object o = it.next();
Assert.assertNotNull("null object in the query result"
+ cs[i].getName(), o);
pm.deletePersistent(o);
}
query.close(col);
}
pm.currentTransaction().commit();
} catch (JDOException e) {
Exception ie = ExceptionHelper.getNested(e);
logger.log(BasicLevel.ERROR, "", ie);
fail(ie.getMessage());
} finally {
if (pm.currentTransaction().isActive())
pm.currentTransaction().rollback();
pm.close();
}
}
}