/*
* 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.embedded;
import com.blazebit.persistence.CriteriaBuilder;
import com.blazebit.persistence.testsuite.base.category.NoDatanucleus;
import com.blazebit.persistence.testsuite.base.category.NoEclipselink;
import com.blazebit.persistence.testsuite.treat.entity.IntIdEntity;
import com.blazebit.persistence.testsuite.treat.entity.IntValueEmbeddable;
import com.blazebit.persistence.testsuite.treat.entity.SingleTableBase;
import com.blazebit.persistence.testsuite.treat.entity.SingleTableEmbeddable;
import com.blazebit.persistence.testsuite.treat.entity.SingleTableEmbeddableSub1;
import com.blazebit.persistence.testsuite.treat.entity.SingleTableEmbeddableSub2;
import com.blazebit.persistence.testsuite.treat.entity.SingleTableSub1;
import com.blazebit.persistence.testsuite.treat.entity.SingleTableSub2;
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.metamodel.SingularAttribute;
import com.blazebit.persistence.view.spi.EntityViewConfiguration;
import com.blazebit.persistence.view.testsuite.AbstractEntityViewTest;
import com.blazebit.persistence.view.testsuite.inheritance.embedded.model.IntIdEntityView;
import com.blazebit.persistence.view.testsuite.inheritance.embedded.model.SingleTableDetailsView;
import com.blazebit.persistence.view.testsuite.inheritance.embedded.model.SingleTableSub1DetailsView;
import com.blazebit.persistence.view.testsuite.inheritance.embedded.model.SingleTableSub2DetailsView;
import com.blazebit.persistence.view.testsuite.inheritance.embedded.model.SingleTableView;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import javax.persistence.EntityManager;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
*
* @author Christian Beikov
* @since 1.2.0
*/
// NOTE: Eclipselink and Datanucleus have no real support for subtype property access
@Category({ NoEclipselink.class, NoDatanucleus.class })
public class EmbeddedInheritanceTest extends AbstractEntityViewTest {
private SingleTableSub1 base1;
private SingleTableSub2 base2;
private EntityViewManager evm;
@Override
protected Class<?>[] getEntityClasses() {
return new Class[] {
IntIdEntity.class,
IntValueEmbeddable.class,
SingleTableBase.class,
SingleTableSub1.class,
SingleTableSub2.class,
SingleTableEmbeddable.class,
SingleTableEmbeddableSub1.class,
SingleTableEmbeddableSub2.class
};
}
@Override
public void setUpOnce() {
cleanDatabase();
transactional(new TxVoidWork() {
@Override
public void work(EntityManager em) {
IntIdEntity i1 = new IntIdEntity("i1", 1);
base1 = new SingleTableSub1("st1");
base2 = new SingleTableSub2("st2");
base1.setSub1Value(123);
base2.setSub2Value(456);
base2.setRelation2(i1);
em.persist(i1);
em.persist(base1);
em.persist(base2);
base1.setParent(base2);
base2.setParent(base1);
}
});
}
@Before
public void setUp() {
base1 = cbf.create(em, SingleTableSub1.class).where("name").eq("st1").getSingleResult();
base2 = cbf.create(em, SingleTableSub2.class).where("name").eq("st2").getSingleResult();
EntityViewConfiguration cfg = EntityViews.createDefaultConfiguration();
cfg.addEntityView(IntIdEntityView.class);
cfg.addEntityView(SingleTableView.class);
cfg.addEntityView(SingleTableDetailsView.class);
cfg.addEntityView(SingleTableSub1DetailsView.class);
cfg.addEntityView(SingleTableSub2DetailsView.class);
this.evm = cfg.createEntityViewManager(cbf);
}
@Test
public void inheritanceMetamodel() {
ManagedViewType<?> baseViewType = evm.getMetamodel().managedView(SingleTableView.class);
ManagedViewType<?> detailsViewType = evm.getMetamodel().managedView(SingleTableDetailsView.class);
ManagedViewType<?> detailsViewType1 = evm.getMetamodel().managedView(SingleTableSub1DetailsView.class);
ManagedViewType<?> detailsViewType2 = evm.getMetamodel().managedView(SingleTableSub2DetailsView.class);
SingularAttribute<?, ?> detailsAttribute = (SingularAttribute<?, ?>) baseViewType.getAttribute("details");
assertEquals(3, detailsViewType.getInheritanceSubtypes().size());
assertTrue(detailsViewType.getInheritanceSubtypes().contains(detailsViewType));
assertTrue(detailsViewType.getInheritanceSubtypes().contains(detailsViewType1));
assertTrue(detailsViewType.getInheritanceSubtypes().contains(detailsViewType2));
assertEquals("", detailsAttribute.getInheritanceSubtypeMappings().get(detailsViewType));
assertEquals("TYPE(this) = " + SingleTableSub1.class.getSimpleName(), detailsAttribute.getInheritanceSubtypeMappings().get(detailsViewType1));
assertEquals("TYPE(this) = " + SingleTableSub2.class.getSimpleName(), detailsAttribute.getInheritanceSubtypeMappings().get(detailsViewType2));
}
@Test
public void inheritanceQuery() {
CriteriaBuilder<SingleTableBase> criteria = cbf.create(em, SingleTableBase.class, "d")
.orderByAsc("id");
CriteriaBuilder<SingleTableView> cb = evm.applySetting(EntityViewSetting.create(SingleTableView.class), criteria);
List<SingleTableView> results = cb.getResultList();
assertEquals(2, results.size());
assertTypeMatches(results.get(0).getDetails(), evm, SingleTableDetailsView.class, SingleTableSub1DetailsView.class);
assertTypeMatches(results.get(1).getDetails(), evm, SingleTableDetailsView.class, SingleTableSub2DetailsView.class);
assertViewEquals(base1, results.get(0));
assertViewEquals(base2, results.get(1));
SingleTableSub1DetailsView view1 = (SingleTableSub1DetailsView) results.get(0).getDetails();
SingleTableSub2DetailsView view2 = (SingleTableSub2DetailsView) results.get(1).getDetails();
assertViewEquals(base1, view1);
assertViewEquals(base2, view2);
assertEquals(base1.getSub1Value(), view1.getSub1Value());
assertViewEquals(base2.getRelation2(), view2.getRelation2());
}
public static void assertViewEquals(SingleTableBase doc, SingleTableView view) {
assertEquals(doc.getId(), view.getId());
}
public static void assertViewEquals(SingleTableBase doc, SingleTableDetailsView view) {
assertEquals(doc.getName(), view.getName());
}
public static void assertViewEquals(IntIdEntity intIdEntity, IntIdEntityView view) {
assertEquals(intIdEntity.getId(), view.getId());
assertEquals(intIdEntity.getName(), view.getName());
}
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());
}
}