/* * 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.basic; import static com.googlecode.catchexception.CatchException.caughtException; import static com.googlecode.catchexception.CatchException.verifyException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.Set; import com.blazebit.persistence.view.EntityView; import com.blazebit.persistence.view.Mapping; import org.junit.Test; import com.blazebit.persistence.view.EntityViews; import com.blazebit.persistence.view.metamodel.MappingAttribute; import com.blazebit.persistence.view.metamodel.MappingConstructor; import com.blazebit.persistence.view.metamodel.MethodAttribute; import com.blazebit.persistence.view.metamodel.SingularAttribute; import com.blazebit.persistence.view.metamodel.SubqueryAttribute; import com.blazebit.persistence.view.metamodel.ViewMetamodel; import com.blazebit.persistence.view.metamodel.ViewType; import com.blazebit.persistence.view.spi.EntityViewConfiguration; import com.blazebit.persistence.view.testsuite.AbstractEntityViewTest; import com.blazebit.persistence.view.testsuite.basic.model.CircularDocument; import com.blazebit.persistence.view.testsuite.basic.model.CircularPerson; import com.blazebit.persistence.view.testsuite.basic.model.CountSubqueryProvider; import com.blazebit.persistence.view.testsuite.basic.model.DocumentViewAbstractClass; import com.blazebit.persistence.view.testsuite.basic.model.DocumentViewInterface; import com.blazebit.persistence.view.testsuite.basic.model.IdHolderView; import com.blazebit.persistence.view.testsuite.basic.model.PersonView; import com.blazebit.persistence.view.testsuite.basic.model.PersonViewWithSingularMapping; import com.blazebit.persistence.view.testsuite.entity.Document; import com.blazebit.persistence.view.testsuite.entity.Person; /** * * @author Christian Beikov * @since 1.0 */ public class ViewMetamodelTest extends AbstractEntityViewTest { private ViewMetamodel getViewMetamodel() { EntityViewConfiguration cfg = EntityViews.createDefaultConfiguration(); cfg.addEntityView(DocumentViewInterface.class); cfg.addEntityView(DocumentViewAbstractClass.class); cfg.addEntityView(PersonView.class); return cfg.createEntityViewManager(cbf).getMetamodel(); } @Test public void testCircularViews() { EntityViewConfiguration cfg = EntityViews.createDefaultConfiguration(); cfg.addEntityView(CircularDocument.class); cfg.addEntityView(CircularPerson.class); verifyException(cfg, IllegalArgumentException.class).createEntityViewManager(cbf); } @Test public void testGetViewsContainsViews() { EntityViewConfiguration cfg = EntityViews.createDefaultConfiguration(); cfg.addEntityView(DocumentViewInterface.class); cfg.addEntityView(DocumentViewAbstractClass.class); cfg.addEntityView(PersonView.class); ViewMetamodel viewMetamodel = cfg.createEntityViewManager(cbf).getMetamodel(); assertEquals(3, viewMetamodel.getViews().size()); assertTrue(viewMetamodel.getViews().contains(viewMetamodel.view(DocumentViewInterface.class))); assertTrue(viewMetamodel.getViews().contains(viewMetamodel.view(DocumentViewAbstractClass.class))); assertTrue(viewMetamodel.getViews().contains(viewMetamodel.view(PersonView.class))); } @Test public void testMappingSingularView() { EntityViewConfiguration cfg = EntityViews.createDefaultConfiguration(); cfg.addEntityView(PersonViewWithSingularMapping.class); ViewMetamodel viewMetamodel = cfg.createEntityViewManager(cbf).getMetamodel(); ViewType<?> viewType = viewMetamodel.view(PersonViewWithSingularMapping.class); assertNotNull(viewType); MethodAttribute<?, ?> attribute = viewType.getAttribute("ownedDocuments"); assertNotNull(attribute); assertFalse(attribute.isCollection()); assertTrue(attribute instanceof SingularAttribute); } @Test public void testViewReturnsViewTypes() { ViewMetamodel viewMetamodel = getViewMetamodel(); assertNotNull(viewMetamodel.view(DocumentViewInterface.class)); assertNotNull(viewMetamodel.view(DocumentViewAbstractClass.class)); assertNotNull(viewMetamodel.view(PersonView.class)); assertNull(viewMetamodel.view(IdHolderView.class)); } @Test public void testViewTypeDefaults() { ViewMetamodel viewMetamodel = getViewMetamodel(); Class<?> expectedViewClass = DocumentViewInterface.class; Class<?> expectedEntityClass = Document.class; String expectedViewName = expectedViewClass.getSimpleName(); ViewType<?> docView = viewMetamodel.view(expectedViewClass); assertEquals(expectedViewClass, docView.getJavaType()); assertEquals(expectedViewName, docView.getName()); assertEquals(expectedEntityClass, docView.getEntityClass()); } @Test public void testViewTypeOverrides() { ViewMetamodel viewMetamodel = getViewMetamodel(); Class<?> expectedViewClass = PersonView.class; Class<?> expectedEntityClass = Person.class; String expectedViewName = "PersView"; ViewType<?> docView = viewMetamodel.view(expectedViewClass); assertEquals(expectedViewClass, docView.getJavaType()); assertEquals(expectedViewName, docView.getName()); assertEquals(expectedEntityClass, docView.getEntityClass()); } @Test public void testMappingAttributesInterfaceView() { ViewMetamodel viewMetamodel = getViewMetamodel(); Set<MethodAttribute<? super DocumentViewInterface, ?>> attributes = viewMetamodel.view(DocumentViewInterface.class) .getAttributes(); assertEquals(6, attributes.size()); } @Test public void testMappingAttributesClassView() { ViewMetamodel viewMetamodel = getViewMetamodel(); Set<MethodAttribute<? super DocumentViewAbstractClass, ?>> attributes = viewMetamodel.view( DocumentViewAbstractClass.class).getAttributes(); assertEquals(6, attributes.size()); } @Test public void testMappingAttributeInterfaceInheritedInterfaceView() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<?> viewType = viewMetamodel.view(DocumentViewInterface.class); MethodAttribute<?, ?> attribute = viewType.getAttribute("id"); assertNotNull(attribute); assertEquals("id", attribute.getName()); assertFalse(attribute.isSubquery()); assertEquals("id", ((MappingAttribute<?, ?>) attribute).getMapping()); assertFalse(attribute.isCollection()); assertFalse(((SingularAttribute<?, ?>) attribute).isQueryParameter()); assertEquals(Long.class, attribute.getJavaType()); assertEquals(IdHolderView.class.getMethod("getId"), attribute.getJavaMethod()); assertEquals(viewType, attribute.getDeclaringType()); } @Test public void testMappingAttributeInterfaceInheritedClassView() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<?> viewType = viewMetamodel.view(DocumentViewAbstractClass.class); MethodAttribute<?, ?> attribute = viewType.getAttribute("id"); assertNotNull(attribute); assertEquals("id", attribute.getName()); assertFalse(attribute.isSubquery()); assertEquals("id", ((MappingAttribute<?, ?>) attribute).getMapping()); assertFalse(attribute.isCollection()); assertFalse(((SingularAttribute<?, ?>) attribute).isQueryParameter()); assertEquals(Long.class, attribute.getJavaType()); assertEquals(IdHolderView.class.getMethod("getId"), attribute.getJavaMethod()); assertEquals(viewType, attribute.getDeclaringType()); } @Test public void testMappingAttributeImplicitAttributeInterfaceView() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<?> viewType = viewMetamodel.view(DocumentViewInterface.class); MethodAttribute<?, ?> attribute = viewType.getAttribute("name"); assertNotNull(attribute); assertEquals("name", attribute.getName()); assertFalse(attribute.isSubquery()); assertEquals("name", ((MappingAttribute<?, ?>) attribute).getMapping()); assertFalse(attribute.isCollection()); assertFalse(((SingularAttribute<?, ?>) attribute).isQueryParameter()); assertEquals(String.class, attribute.getJavaType()); assertEquals(DocumentViewInterface.class.getMethod("getName"), attribute.getJavaMethod()); assertEquals(viewType, attribute.getDeclaringType()); } @Test public void testMappingAttributeImplicitAttributeClassView() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<?> viewType = viewMetamodel.view(DocumentViewAbstractClass.class); MethodAttribute<?, ?> attribute = viewType.getAttribute("name"); assertNotNull(attribute); assertEquals("name", attribute.getName()); assertFalse(attribute.isSubquery()); assertEquals("name", ((MappingAttribute<?, ?>) attribute).getMapping()); assertFalse(attribute.isCollection()); assertFalse(((SingularAttribute<?, ?>) attribute).isQueryParameter()); assertEquals(String.class, attribute.getJavaType()); assertEquals(DocumentViewInterface.class.getMethod("getName"), attribute.getJavaMethod()); assertEquals(viewType, attribute.getDeclaringType()); } @Test public void testMappingAttributeExplicitAttributeInterfaceView() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<?> viewType = viewMetamodel.view(DocumentViewInterface.class); MethodAttribute<?, ?> attribute = viewType.getAttribute("firstContactPerson"); assertNotNull(attribute); assertEquals("firstContactPerson", attribute.getName()); assertFalse(attribute.isSubquery()); assertEquals("contacts[1]", ((MappingAttribute<?, ?>) attribute).getMapping()); assertFalse(attribute.isCollection()); assertFalse(((SingularAttribute<?, ?>) attribute).isQueryParameter()); assertEquals(Person.class, attribute.getJavaType()); assertEquals(DocumentViewInterface.class.getMethod("getFirstContactPerson"), attribute.getJavaMethod()); assertEquals(viewType, attribute.getDeclaringType()); } @Test public void testMappingAttributeExplicitAttributeClassView() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<?> viewType = viewMetamodel.view(DocumentViewAbstractClass.class); MethodAttribute<?, ?> attribute = viewType.getAttribute("firstContactPerson"); assertNotNull(attribute); assertEquals("firstContactPerson", attribute.getName()); assertFalse(attribute.isSubquery()); assertEquals("contacts[1]", ((MappingAttribute<?, ?>) attribute).getMapping()); assertFalse(attribute.isCollection()); assertFalse(((SingularAttribute<?, ?>) attribute).isQueryParameter()); assertEquals(Person.class, attribute.getJavaType()); assertEquals(DocumentViewInterface.class.getMethod("getFirstContactPerson"), attribute.getJavaMethod()); assertEquals(viewType, attribute.getDeclaringType()); } @Test public void testMappingAttributeWithParameterInterfaceView() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<?> viewType = viewMetamodel.view(DocumentViewInterface.class); MethodAttribute<?, ?> attribute = viewType.getAttribute("myContactPerson"); assertNotNull(attribute); assertEquals("myContactPerson", attribute.getName()); assertFalse(attribute.isSubquery()); assertEquals("contacts2[:contactPersonNumber]", ((MappingAttribute<?, ?>) attribute).getMapping()); assertFalse(attribute.isCollection()); assertFalse(((SingularAttribute<?, ?>) attribute).isQueryParameter()); assertEquals(Person.class, attribute.getJavaType()); assertEquals(DocumentViewInterface.class.getMethod("getMyContactPerson"), attribute.getJavaMethod()); assertEquals(viewType, attribute.getDeclaringType()); } @Test public void testMappingAttributeWithParameterClassView() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<?> viewType = viewMetamodel.view(DocumentViewAbstractClass.class); MethodAttribute<?, ?> attribute = viewType.getAttribute("myContactPerson"); assertNotNull(attribute); assertEquals("myContactPerson", attribute.getName()); assertFalse(attribute.isSubquery()); assertEquals("contacts2[:contactPersonNumber]", ((MappingAttribute<?, ?>) attribute).getMapping()); assertFalse(attribute.isCollection()); assertFalse(((SingularAttribute<?, ?>) attribute).isQueryParameter()); assertEquals(Person.class, attribute.getJavaType()); assertEquals(DocumentViewInterface.class.getMethod("getMyContactPerson"), attribute.getJavaMethod()); assertEquals(viewType, attribute.getDeclaringType()); } @Test public void testMappingParameterInterfaceView() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<?> viewType = viewMetamodel.view(DocumentViewInterface.class); MethodAttribute<?, ?> attribute = viewType.getAttribute("contactPersonNumber2"); assertNotNull(attribute); assertEquals("contactPersonNumber2", attribute.getName()); assertFalse(attribute.isSubquery()); assertEquals("contactPersonNumber", ((MappingAttribute<?, ?>) attribute).getMapping()); assertFalse(attribute.isCollection()); assertTrue(((SingularAttribute<?, ?>) attribute).isQueryParameter()); assertEquals(Integer.class, attribute.getJavaType()); assertEquals(DocumentViewInterface.class.getMethod("getContactPersonNumber2"), attribute.getJavaMethod()); assertEquals(viewType, attribute.getDeclaringType()); } @Test public void testMappingParameterClassView() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<?> viewType = viewMetamodel.view(DocumentViewAbstractClass.class); MethodAttribute<?, ?> attribute = viewType.getAttribute("contactPersonNumber2"); assertNotNull(attribute); assertEquals("contactPersonNumber2", attribute.getName()); assertFalse(attribute.isSubquery()); assertEquals("contactPersonNumber", ((MappingAttribute<?, ?>) attribute).getMapping()); assertFalse(attribute.isCollection()); assertTrue(((SingularAttribute<?, ?>) attribute).isQueryParameter()); assertEquals(Integer.class, attribute.getJavaType()); assertEquals(DocumentViewInterface.class.getMethod("getContactPersonNumber2"), attribute.getJavaMethod()); assertEquals(viewType, attribute.getDeclaringType()); } @Test public void testMappingSubqueryInterfaceView() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<?> viewType = viewMetamodel.view(DocumentViewInterface.class); MethodAttribute<?, ?> attribute = viewType.getAttribute("contactCount"); assertNotNull(attribute); assertEquals("contactCount", attribute.getName()); assertTrue(attribute.isSubquery()); assertEquals(CountSubqueryProvider.class, ((SubqueryAttribute<?, ?>) attribute).getSubqueryProvider()); assertFalse(attribute.isCollection()); assertFalse(((SingularAttribute<?, ?>) attribute).isQueryParameter()); assertEquals(Long.class, attribute.getJavaType()); assertEquals(DocumentViewInterface.class.getMethod("getContactCount"), attribute.getJavaMethod()); assertEquals(viewType, attribute.getDeclaringType()); } @Test public void testMappingSubqueryClassView() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<?> viewType = viewMetamodel.view(DocumentViewAbstractClass.class); MethodAttribute<?, ?> attribute = viewType.getAttribute("contactCount"); assertNotNull(attribute); assertEquals("contactCount", attribute.getName()); assertTrue(attribute.isSubquery()); assertEquals(CountSubqueryProvider.class, ((SubqueryAttribute<?, ?>) attribute).getSubqueryProvider()); assertFalse(attribute.isCollection()); assertFalse(((SingularAttribute<?, ?>) attribute).isQueryParameter()); assertEquals(Long.class, attribute.getJavaType()); assertEquals(DocumentViewInterface.class.getMethod("getContactCount"), attribute.getJavaMethod()); assertEquals(viewType, attribute.getDeclaringType()); } @Test public void testGetConstructorsInterfaceView() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<DocumentViewInterface> viewType = viewMetamodel.view(DocumentViewInterface.class); Set<MappingConstructor<DocumentViewInterface>> constructors = viewType.getConstructors(); assertEquals(0, constructors.size()); } @Test public void testGetConstructorsClassView() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<DocumentViewAbstractClass> viewType = viewMetamodel.view(DocumentViewAbstractClass.class); Set<MappingConstructor<DocumentViewAbstractClass>> constructors = viewType.getConstructors(); assertEquals(1, constructors.size()); assertNotNull(viewType.getConstructor(Long.class, Integer.class, String.class)); assertTrue(constructors.contains(viewType.getConstructor(Long.class, Integer.class, String.class))); } @Test public void testMappingConstructor() throws Exception { ViewMetamodel viewMetamodel = getViewMetamodel(); ViewType<DocumentViewAbstractClass> viewType = viewMetamodel.view(DocumentViewAbstractClass.class); Set<MappingConstructor<DocumentViewAbstractClass>> constructors = viewType.getConstructors(); MappingConstructor<DocumentViewAbstractClass> constructor = constructors.iterator().next(); assertNotNull(constructor); assertEquals(3, constructor.getParameterAttributes().size()); assertEquals(Long.class, constructor.getParameterAttributes().get(0).getJavaType()); assertEquals(constructor, constructor.getParameterAttributes().get(0).getDeclaringConstructor()); assertEquals(viewType, constructor.getParameterAttributes().get(0).getDeclaringType()); assertEquals(0, constructor.getParameterAttributes().get(0).getIndex()); assertFalse(constructor.getParameterAttributes().get(0).isSubquery()); assertEquals("age + 1", ((MappingAttribute<?, ?>) constructor.getParameterAttributes().get(0)).getMapping()); assertFalse(constructor.getParameterAttributes().get(0).isCollection()); assertFalse(((SingularAttribute<?, ?>) constructor.getParameterAttributes().get(0)).isQueryParameter()); assertEquals(Integer.class, constructor.getParameterAttributes().get(1).getJavaType()); assertEquals(constructor, constructor.getParameterAttributes().get(1).getDeclaringConstructor()); assertEquals(viewType, constructor.getParameterAttributes().get(1).getDeclaringType()); assertEquals(1, constructor.getParameterAttributes().get(1).getIndex()); assertFalse(constructor.getParameterAttributes().get(1).isSubquery()); assertEquals("contactPersonNumber", ((MappingAttribute<?, ?>) constructor.getParameterAttributes().get(1)).getMapping()); assertFalse(constructor.getParameterAttributes().get(1).isCollection()); assertTrue(((SingularAttribute<?, ?>) constructor.getParameterAttributes().get(1)).isQueryParameter()); assertEquals(String.class, constructor.getParameterAttributes().get(2).getJavaType()); assertEquals(constructor, constructor.getParameterAttributes().get(2).getDeclaringConstructor()); assertEquals(viewType, constructor.getParameterAttributes().get(2).getDeclaringType()); assertEquals(2, constructor.getParameterAttributes().get(2).getIndex()); assertFalse(constructor.getParameterAttributes().get(2).isSubquery()); assertEquals("optionalParameter", ((MappingAttribute<?, ?>) constructor.getParameterAttributes().get(2)).getMapping()); assertFalse(constructor.getParameterAttributes().get(2).isCollection()); assertTrue(((SingularAttribute<?, ?>) constructor.getParameterAttributes().get(2)).isQueryParameter()); assertEquals(DocumentViewAbstractClass.class.getConstructor(Long.class, Integer.class, String.class), constructor.getJavaConstructor()); assertEquals(viewType, constructor.getDeclaringType()); } @Test public void testConflictingMapping() throws Exception { EntityViewConfiguration cfg = EntityViews.createDefaultConfiguration(); cfg.addEntityView(ConflictingDoc.class); verifyException(cfg, IllegalArgumentException.class).createEntityViewManager(cbf); Throwable t = caughtException(); assertTrue(t.getMessage().contains("'name'")); assertTrue(t.getMessage().contains(ConflictingDoc1.class.getName() + ".getName")); assertTrue(t.getMessage().contains(ConflictingDoc2.class.getName() + ".getName")); } public static interface ConflictingDoc1 extends IdHolderView<Long> { @Mapping("name") public String getName(); } public static interface ConflictingDoc2 extends IdHolderView<Long> { @Mapping("COALESCE(name, '')") public String getName(); } @EntityView(Document.class) public static interface ConflictingDoc extends ConflictingDoc1, ConflictingDoc2 { } @Test public void testResolveConflictingMapping() throws Exception { EntityViewConfiguration cfg = EntityViews.createDefaultConfiguration(); cfg.addEntityView(ResolveConflictingDoc.class); ViewMetamodel metamodel = cfg.createEntityViewManager(cbf).getMetamodel(); MappingAttribute<?, ?> mappingAttribute = (MappingAttribute<?, ?>) metamodel.view(ResolveConflictingDoc.class).getAttribute("name"); assertEquals("UPPER(name)", mappingAttribute.getMapping()); } public static interface ResolveConflictingDoc1 extends IdHolderView<Long> { @Mapping("name") public String getName(); } public static interface ResolveConflictingDoc2 extends IdHolderView<Long> { @Mapping("COALESCE(name, '')") public String getName(); } @EntityView(Document.class) public static interface ResolveConflictingDoc extends ResolveConflictingDoc1, ResolveConflictingDoc2 { @Mapping("UPPER(name)") public String getName(); } @Test public void testInheritancePrecedenceNonConflictingMapping() throws Exception { EntityViewConfiguration cfg = EntityViews.createDefaultConfiguration(); cfg.addEntityView(InheritancePrecedenceNonConflictingDoc.class); ViewMetamodel metamodel = cfg.createEntityViewManager(cbf).getMetamodel(); MappingAttribute<?, ?> mappingAttribute = (MappingAttribute<?, ?>) metamodel.view(InheritancePrecedenceNonConflictingDoc.class).getAttribute("name"); assertEquals("COALESCE(name, '')", mappingAttribute.getMapping()); } public static interface InheritancePrecedenceNonConflictingDoc1 extends IdHolderView<Long> { @Mapping("name") public String getName(); } public static interface InheritancePrecedenceNonConflictingDoc2 extends InheritancePrecedenceNonConflictingDoc1 { @Mapping("COALESCE(name, '')") public String getName(); } @EntityView(Document.class) public static interface InheritancePrecedenceNonConflictingDoc extends InheritancePrecedenceNonConflictingDoc2 { } @Test public void testNoMappingNonConflictingMapping() throws Exception { EntityViewConfiguration cfg = EntityViews.createDefaultConfiguration(); cfg.addEntityView(NoMappingNonConflictingDoc.class); ViewMetamodel metamodel = cfg.createEntityViewManager(cbf).getMetamodel(); MappingAttribute<?, ?> mappingAttribute = (MappingAttribute<?, ?>) metamodel.view(NoMappingNonConflictingDoc.class).getAttribute("name"); assertEquals("COALESCE(name, '')", mappingAttribute.getMapping()); } public static interface NoMappingNonConflictingDoc1 extends IdHolderView<Long> { public String getName(); } public static interface NoMappingNonConflictingDoc2 extends IdHolderView<Long> { @Mapping("COALESCE(name, '')") public String getName(); } @EntityView(Document.class) public static interface NoMappingNonConflictingDoc extends NoMappingNonConflictingDoc1, NoMappingNonConflictingDoc2 { } // TODO: Test filter mapping }