/*
* Copyright 2014 - 2017 Blazebit.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.blazebit.persistence.view.testsuite.inheritance.basic;
import com.blazebit.persistence.CriteriaBuilder;
import com.blazebit.persistence.testsuite.base.category.NoDatanucleus;
import com.blazebit.persistence.testsuite.tx.TxVoidWork;
import com.blazebit.persistence.view.EntityViewManager;
import com.blazebit.persistence.view.EntityViewSetting;
import com.blazebit.persistence.view.EntityViews;
import com.blazebit.persistence.view.metamodel.ManagedViewType;
import com.blazebit.persistence.view.spi.EntityViewConfiguration;
import com.blazebit.persistence.view.testsuite.AbstractEntityViewTest;
import com.blazebit.persistence.view.testsuite.entity.Document;
import com.blazebit.persistence.view.testsuite.entity.Person;
import com.blazebit.persistence.view.testsuite.entity.Version;
import com.blazebit.persistence.view.testsuite.inheritance.basic.model.DocumentBaseView;
import com.blazebit.persistence.view.testsuite.inheritance.basic.model.NewDocumentView;
import com.blazebit.persistence.view.testsuite.inheritance.basic.model.NewSub1DocumentView;
import com.blazebit.persistence.view.testsuite.inheritance.basic.model.NewSub1Sub1DocumentView;
import com.blazebit.persistence.view.testsuite.inheritance.basic.model.NewSub2DocumentView;
import com.blazebit.persistence.view.testsuite.inheritance.basic.model.OldDocumentView;
import com.blazebit.persistence.view.testsuite.inheritance.basic.model.SimplePersonSubView;
import com.blazebit.persistence.view.testsuite.inheritance.basic.model.UnusedOldDocumentView;
import com.blazebit.persistence.view.testsuite.inheritance.basic.model.UsedOldDocumentView;
import com.blazebit.persistence.view.testsuite.inheritance.basic.model.UsedOldSub1DocumentView;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import javax.persistence.EntityManager;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import static org.junit.Assert.*;
/**
*
* @author Christian Beikov
* @since 1.2.0
*/
public class InheritanceTest extends AbstractEntityViewTest {
private Document doc1;
private Document doc2;
private Document doc3;
private Document doc4;
private Document doc5;
private Document doc6;
private EntityViewManager evm;
@Override
public void setUpOnce() {
cleanDatabase();
transactional(new TxVoidWork() {
@Override
public void work(EntityManager em) {
doc1 = new Document("doc1", new Person("owner1"), new Version(), new Version());
doc2 = new Document("doc2", new Person("owner2"));
doc3 = new Document("doc3", new Person("owner3"));
doc4 = new Document("doc4", new Person("owner4"), new Version(), new Version());
doc5 = new Document("doc5", new Person("owner5"));
doc6 = new Document("doc6", new Person("owner6"));
// New
doc1.setAge(1);
doc2.setAge(1);
doc3.setAge(1);
// Base
doc4.setAge(15);
// Old
doc5.setAge(16);
doc6.setAge(16);
// NewSub1
doc1.setDefaultContact(null);
doc2.setDefaultContact(null);
// NewSub2
doc3.setDefaultContact(1);
// Base
doc4.setDefaultContact(1);
doc4.setLastModified(Timestamp.valueOf("2000-01-01 00:00:00"));
// UsedOld
doc5.setLastModified(Timestamp.valueOf("2000-01-01 00:00:00"));
// Old
doc6.setLastModified(null);
Person o1 = new Person("pers1");
Person o2 = new Person("pers2");
Person o3 = new Person("pers3");
Person o4 = new Person("pers4");
Person o5 = new Person("pers5");
Person o6 = new Person("pers6");
doc2.getContacts().put(1, o1);
doc2.getContacts().put(1, o2);
doc5.getContacts().put(1, o3);
doc5.getContacts().put(1, o4);
doc6.getContacts().put(1, o5);
doc6.getContacts().put(1, o6);
em.persist(o1);
em.persist(o2);
em.persist(o3);
em.persist(o4);
em.persist(o5);
em.persist(o6);
o1.setPartnerDocument(doc3);
o2.setPartnerDocument(doc3);
o3.setPartnerDocument(doc4);
o4.setPartnerDocument(doc4);
o5.setPartnerDocument(doc5);
o6.setPartnerDocument(doc5);
doc1.getPersonList().add(o1);
doc2.getPersonList().add(o2);
doc3.getPersonList().add(o3);
doc4.getPersonList().add(o4);
doc5.getPersonList().add(o5);
doc6.getPersonList().add(o6);
em.persist(doc1);
em.persist(doc2);
em.persist(doc3);
em.persist(doc4);
em.persist(doc5);
em.persist(doc6);
}
});
}
@Before
public void setUp() {
doc1 = cbf.create(em, Document.class).where("name").eq("doc1").getSingleResult();
doc2 = cbf.create(em, Document.class).where("name").eq("doc2").getSingleResult();
doc3 = cbf.create(em, Document.class).where("name").eq("doc3").getSingleResult();
doc4 = cbf.create(em, Document.class).where("name").eq("doc4").getSingleResult();
doc5 = cbf.create(em, Document.class).where("name").eq("doc5").getSingleResult();
doc6 = cbf.create(em, Document.class).where("name").eq("doc6").getSingleResult();
EntityViewConfiguration cfg = EntityViews.createDefaultConfiguration();
cfg.addEntityView(SimplePersonSubView.class);
cfg.addEntityView(DocumentBaseView.class);
cfg.addEntityView(NewDocumentView.class);
cfg.addEntityView(NewSub1DocumentView.class);
cfg.addEntityView(NewSub2DocumentView.class);
cfg.addEntityView(OldDocumentView.class);
cfg.addEntityView(UnusedOldDocumentView.class);
cfg.addEntityView(UsedOldDocumentView.class);
cfg.addEntityView(NewSub1Sub1DocumentView.class);
cfg.addEntityView(UsedOldSub1DocumentView.class);
this.evm = cfg.createEntityViewManager(cbf);
}
@Test
public void inheritanceMetamodel() {
ManagedViewType<?> baseViewType = evm.getMetamodel().managedView(DocumentBaseView.class);
ManagedViewType<?> newViewType = evm.getMetamodel().managedView(NewDocumentView.class);
ManagedViewType<?> newSub1ViewType = evm.getMetamodel().managedView(NewSub1DocumentView.class);
ManagedViewType<?> newSub1Sub1ViewType = evm.getMetamodel().managedView(NewSub1Sub1DocumentView.class);
ManagedViewType<?> newSub2ViewType = evm.getMetamodel().managedView(NewSub2DocumentView.class);
ManagedViewType<?> oldViewType = evm.getMetamodel().managedView(OldDocumentView.class);
ManagedViewType<?> usedOldViewType = evm.getMetamodel().managedView(UsedOldDocumentView.class);
ManagedViewType<?> usedOldSubViewType = evm.getMetamodel().managedView(UsedOldSub1DocumentView.class);
ManagedViewType<?> unusedOldViewType = evm.getMetamodel().managedView(UnusedOldDocumentView.class);
assertEquals(null, baseViewType.getInheritanceMapping());
assertEquals(6, baseViewType.getInheritanceSubtypes().size());
assertTrue(baseViewType.getInheritanceSubtypes().contains(baseViewType));
assertTrue(baseViewType.getInheritanceSubtypes().contains(newViewType));
assertTrue(baseViewType.getInheritanceSubtypes().contains(newSub1ViewType));
assertFalse(baseViewType.getInheritanceSubtypes().contains(newSub1Sub1ViewType));
assertTrue(baseViewType.getInheritanceSubtypes().contains(newSub2ViewType));
assertTrue(baseViewType.getInheritanceSubtypes().contains(oldViewType));
assertTrue(baseViewType.getInheritanceSubtypes().contains(usedOldViewType));
assertFalse(baseViewType.getInheritanceSubtypes().contains(usedOldSubViewType));
assertFalse(baseViewType.getInheritanceSubtypes().contains(unusedOldViewType));
assertEquals("age < 15", newViewType.getInheritanceMapping());
assertEquals(3, newViewType.getInheritanceSubtypes().size());
assertTrue(newViewType.getInheritanceSubtypes().contains(newViewType));
assertTrue(newViewType.getInheritanceSubtypes().contains(newSub1ViewType));
assertTrue(newViewType.getInheritanceSubtypes().contains(newSub2ViewType));
assertEquals("defaultContact IS NULL", newSub1ViewType.getInheritanceMapping());
assertEquals(1, newSub1ViewType.getInheritanceSubtypes().size());
assertTrue(newSub1ViewType.getInheritanceSubtypes().contains(newSub1ViewType));
assertEquals("defaultContact IS NOT NULL", newSub2ViewType.getInheritanceMapping());
assertEquals(1, newSub2ViewType.getInheritanceSubtypes().size());
assertTrue(newSub2ViewType.getInheritanceSubtypes().contains(newSub2ViewType));
assertEquals("age > 15", oldViewType.getInheritanceMapping());
assertEquals(2, oldViewType.getInheritanceSubtypes().size());
assertTrue(oldViewType.getInheritanceSubtypes().contains(oldViewType));
assertTrue(oldViewType.getInheritanceSubtypes().contains(usedOldViewType));
assertEquals("lastModified IS NOT NULL", usedOldViewType.getInheritanceMapping());
assertEquals(1, usedOldViewType.getInheritanceSubtypes().size());
assertTrue(usedOldViewType.getInheritanceSubtypes().contains(usedOldViewType));
}
@Test
// TODO: report that datanucleus thinks a NULL literal is of type Integer and normal integral literals are of type Long
@Category({ NoDatanucleus.class })
public void inheritanceQuery() {
CriteriaBuilder<Document> criteria = cbf.create(em, Document.class, "d")
.orderByAsc("id");
CriteriaBuilder<DocumentBaseView> cb = evm.applySetting(EntityViewSetting.create(DocumentBaseView.class), criteria);
List<DocumentBaseView> results = cb.getResultList();
assertEquals(6, results.size());
assertTypeMatches(results.get(0), evm, DocumentBaseView.class, NewSub1DocumentView.class);
assertTypeMatches(results.get(1), evm, DocumentBaseView.class, NewSub1DocumentView.class);
assertTypeMatches(results.get(2), evm, DocumentBaseView.class, NewSub2DocumentView.class);
assertTypeMatches(results.get(3), evm, DocumentBaseView.class, DocumentBaseView.class);
assertTypeMatches(results.get(4), evm, DocumentBaseView.class, UsedOldDocumentView.class);
assertTypeMatches(results.get(5), evm, DocumentBaseView.class, OldDocumentView.class);
NewSub1DocumentView docView1 = (NewSub1DocumentView) results.get(0);
NewSub1DocumentView docView2 = (NewSub1DocumentView) results.get(1);
NewSub2DocumentView docView3 = (NewSub2DocumentView) results.get(2);
DocumentBaseView docView4 = results.get(3);
UsedOldDocumentView docView5 = (UsedOldDocumentView) results.get(4);
OldDocumentView docView6 = (OldDocumentView) results.get(5);
assertDocumentEquals(doc1, docView1);
assertDocumentEquals(doc2, docView2);
assertDocumentEquals(doc3, docView3);
assertDocumentEquals(doc4, docView4);
assertDocumentEquals(doc5, docView5);
assertDocumentEquals(doc6, docView6);
assertSubviewEquals(doc1.getContacts().values(), docView1.getContacts());
assertVersionsEquals(doc1.getVersions(), docView1.getVersionIds());
assertSubviewEquals(doc2.getContacts().values(), docView2.getContacts());
assertVersionsEquals(doc2.getVersions(), docView2.getVersionIds());
assertEquals(doc3.getDefaultContact(), docView3.getDefaultContact());
assertSubviewEquals(doc5.getContacts().values(), docView5.getContacts());
assertSubviewEquals(doc5.getPartners(), docView5.getPartners());
assertSubviewEquals(doc6.getPartners(), docView6.getPartners());
}
public static <T> void assertTypeMatches(T o, EntityViewManager evm, Class<T> baseType, Class<? extends T> subtype) {
int index = 0;
for (ManagedViewType<?> t : evm.getMetamodel().managedView(baseType).getInheritanceSubtypes()) {
if (t.getJavaType() == subtype) {
break;
}
index++;
}
assertEquals(baseType.getName() + "_" + index + "_" + subtype.getSimpleName() + "_$$_javassist_entityview_", o.getClass().getName());
}
public static void assertDocumentEquals(Document doc, DocumentBaseView view) {
assertEquals(doc.getId(), view.getId());
assertEquals(doc.getName(), view.getName());
}
public static void assertVersionsEquals(Set<Version> versions, Set<Long> versionIds) {
if (versions == null) {
assertNull(versionIds);
return;
}
assertNotNull(versionIds);
assertEquals(versions.size(), versionIds.size());
for (Version v : versions) {
if (!versionIds.contains(v.getId())) {
Assert.fail("Could not find a version id: " + v.getId());
}
}
}
public static void assertSubviewEquals(Collection<Person> persons, Set<SimplePersonSubView> personSubviews) {
if (persons == null) {
assertNull(personSubviews);
return;
}
assertNotNull(personSubviews);
assertEquals(persons.size(), personSubviews.size());
for (Person p : persons) {
boolean found = false;
for (SimplePersonSubView pSub : personSubviews) {
if (p.getName().equals(pSub.getName())) {
found = true;
break;
}
}
if (!found) {
Assert.fail("Could not find a SimplePersonSubView with the name: " + p.getName());
}
}
}
}