package sk.nociar.jpacloner;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.transaction.annotation.Transactional;
import sk.nociar.jpacloner.entities.Bar;
import sk.nociar.jpacloner.entities.BaseEntity;
import sk.nociar.jpacloner.entities.Baz;
import sk.nociar.jpacloner.entities.Baz_;
import sk.nociar.jpacloner.entities.Edge;
import sk.nociar.jpacloner.entities.Edge_;
import sk.nociar.jpacloner.entities.Foo;
import sk.nociar.jpacloner.entities.Foo_;
import sk.nociar.jpacloner.entities.Node;
import sk.nociar.jpacloner.entities.Node_;
import sk.nociar.jpacloner.entities.Point;
import sk.nociar.jpacloner.selectors.Selector;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class,
classes = { AppConfig.class, DataConfig.class })
public class JpaClonerTest {
@PersistenceContext
EntityManager em;
private void persist(List<? extends BaseEntity> list) {
for (BaseEntity e : list) {
em.persist(e);
}
em.flush();
}
private JpaClonerTestSupport support;
private List<Node> nodeList;
private List<Edge> edgeList;
private List<Foo> fooList;
private List<Baz> bazList;
private List<Bar> barList;
@Before
@Transactional
public void setUp() {
nodeList = new ArrayList<Node>();
edgeList = new ArrayList<Edge>();
fooList = new ArrayList<Foo>();
bazList = new ArrayList<Baz>();
barList = new ArrayList<Bar>();
support = new JpaClonerTestSupport() {
@Override
protected Node createNode() {
Node entity = new Node();
nodeList.add(entity);
return entity;
}
@Override
protected Edge createEdge() {
Edge entity = new Edge();
edgeList.add(entity);
return entity;
}
@Override
protected Point createPoint() {
return new Point(1, 2);
}
@Override
protected Foo createFoo() {
Foo entity = new Foo();
fooList.add(entity);
return entity;
}
@Override
protected Bar createBar() {
Bar entity = new Bar();
barList.add(entity);
return entity;
}
@Override
protected Baz createBaz() {
Baz entity = new Baz();
bazList.add(entity);
return entity;
}
@Override
protected Node getOriginal() {
TypedQuery<Node> q = em.createQuery("select n from Node n where n.name='1'", Node.class);
return q.getSingleResult();
}
};
support.initialize();
persist(barList);
persist(bazList);
persist(fooList);
persist(nodeList);
persist(edgeList);
// detach all entities from persistence ctx
em.clear();
}
@Test
@Transactional
public void testClone1() {
support.testClone1();
}
@Test
@Transactional
public void testClone2() {
support.testClone2();
}
@Test
@Transactional
public void testClone3() {
support.testClone3();
}
@Test
@Transactional
public void testClone4() {
support.testClone4();
}
@Test
@Transactional
public void testClone5() {
support.testClone5();
}
@Test
@Transactional
public void testExplore() {
support.testExplore();
}
@Test
@Transactional
public void testSelector() {
Selector<Node> s = Selector.get(Node.class);
s.join(Node_.point);
s.join(Node_.foo).join(Foo_.bar);
s.join(Node_.baz).join(Baz_.bar);
s.join(Node_.children).join(Edge_.bar);
Node cloned = JpaCloner.clone(support.getOriginal(), s.toString());
JpaExplorer e = JpaExplorer.doExplore(cloned, "*+");
JpaClonerTestSupport.assertCloned(e, Node.class, 1);
JpaClonerTestSupport.assertCloned(e, Point.class, 1);
JpaClonerTestSupport.assertCloned(e, Foo.class, 1);
JpaClonerTestSupport.assertCloned(e, Baz.class, 1);
JpaClonerTestSupport.assertCloned(e, Bar.class, 2);
JpaClonerTestSupport.assertCloned(e, Edge.class, 2);
}
@Test
@Transactional
public void testCloneList() {
TypedQuery<Node> q = em.createQuery("select n from Node n", Node.class);
List<Node> nodes = JpaCloner.clone(q.getResultList(), "point", "(foo|baz).bar");
// assert that the same objects are correctly cloned/references
Map<Object, Object> instances = new HashMap<Object, Object>();
for (Node node : nodes) {
if (node.getBaz() != null) {
assertSingleInstance(node.getBaz(), instances);
assertSingleInstance(node.getBaz().getBar(), instances);
}
if (node.getFoo() != null) {
assertSingleInstance(node.getFoo(), instances);
assertSingleInstance(node.getFoo().getBar(), instances);
}
}
}
private void assertSingleInstance(Object object, Map<Object, Object> instances) {
Object instance = instances.get(object);
if (instance == null) {
instances.put(object, object);
} else {
Assert.assertSame(instance, object);
}
}
}