/** * Copyright 2013 the original author or authors. * * 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 io.neba.core.resourcemodels.metadata; import io.neba.core.resourcemodels.mapping.testmodels.*; import org.apache.sling.api.resource.Resource; import org.junit.Test; import java.lang.reflect.Field; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.util.ReflectionUtils.findField; import static org.springframework.util.ReflectionUtils.setField; /** * @author Olaf Otto */ public class MappedFieldMetaDataTest { private Class<?> modelType = TestResourceModel.class; private MappedFieldMetaData testee; @Test(expected = IllegalArgumentException.class) public void testHandlingOfNullField() throws Exception { createMetadataForTestModelFieldWithName("this.field.does.not.exist"); } @Test public void testPathAnnotationUsageOnPropertyField() throws Exception { createMetadataForTestModelFieldWithName("stringFieldWithRelativePathAnnotation"); assertFieldHasPathAnnotation(); assertFieldIsPropertyType(); assertFieldIsNotCollectionType(); assertFieldIsNotReference(); assertFieldIsNotThisReference(); } @Test public void testPathAnnotationOnComplexReferenceField() throws Exception { createMetadataForTestModelFieldWithName("referencedResource"); assertFieldHasPathAnnotation(); assertFieldIsReference(); assertFieldIsPropertyType(); assertFieldIsNotCollectionType(); assertFieldIsNotThisReference(); } @Test public void testPathAnnotationOnComplexReferenceFieldWithMetaAnnotation() throws Exception { createMetadataForTestModelFieldWithName("referencedResourceWithMetaAnnotation"); assertFieldHasPathAnnotation(); assertFieldIsReference(); assertFieldIsPropertyType(); assertFieldIsNotCollectionType(); assertFieldIsNotThisReference(); } @Test public void testAppendAbsolutePathOnReference() throws Exception { createMetadataForTestModelFieldWithName("referencedResourceModelWithAbsoluteAppendedReferencePath"); assertReferenceHasAppendPath(); assertReferenceAppendPathIs("/jcr:content"); } @Test public void testAppendRelativePathOnReference() throws Exception { createMetadataForTestModelFieldWithName("referencedResourceModelWithRelativeAppendedReferencePath"); assertReferenceHasAppendPath(); assertReferenceAppendPathIs("/jcr:content"); } @Test public void testNoAppendPathOnReference() throws Exception { createMetadataForTestModelFieldWithName("referencedResource"); assertNoAppendPathIsPresentOnReference(); } @Test public void testResolveBelowEveryChildOnChildren() throws Exception { createMetadataForTestModelFieldWithName("childContentResourcesAsResources"); assertChildrenHasResolveBelowEveryChildPath(); assertChildrenResolveBelowEveryChildPathIs("jcr:content"); } @Test public void testNoResolveBelowEveryChildOnChildren() throws Exception { createMetadataForTestModelFieldWithName("childrenAsResources"); assertChildrenDoesNotHaveResolveBelowEveryChildPath(); } @Test public void testTypeParameterDetection() throws Exception { createMetadataForTestModelFieldWithName("referencedResourcesListWithSimpleTypeParameter"); assertFieldIsPropertyType(); assertFieldIsCollectionType(); assertTypeParameterIs(Resource.class); } @Test public void testThisReferenceDetection() throws Exception { createMetadataForTestModelFieldWithName("thisResource"); assertFieldIsThisReference(); assertFieldIsNotPropertyType(); assertFieldIsNotCollectionType(); assertFieldIsNotReference(); assertFieldHasNoPathAnnotation(); } @Test public void testThisReferenceDetectionWithMetaAnnotation() throws Exception { createMetadataForTestModelFieldWithName("thisResourceWithMetaAnnotation"); assertFieldIsThisReference(); assertFieldIsNotPropertyType(); assertFieldIsNotCollectionType(); assertFieldIsNotReference(); assertFieldHasNoPathAnnotation(); } @Test public void testPathRetrievalFromPathAnnotation() throws Exception { createMetadataForTestModelFieldWithName("stringFieldWithAbsolutePathAnnotation"); assertFieldHasPathAnnotation(); assertFieldHasPath("/absolute/path"); } @Test public void testPathRetrievalFromPathMetaAnnotation() throws Exception { createMetadataForTestModelFieldWithName("stringFieldWithPathMetaAnnotation"); assertFieldHasPathAnnotation(); assertFieldHasPath("/absolute/path"); } @Test(expected = IllegalArgumentException.class) public void testTreatmentOfInvalidGenericsUsage() throws Exception { withModelType(TestResourceModelWithInvalidGenericFieldDeclaration.class); createMetadataForTestModelFieldWithName("readOnlyList"); } @Test(expected = IllegalArgumentException.class) public void testTreatmentOfInvalidPathAnnotation() throws Exception { withModelType(TestResourceModelWithInvalidPathDeclaration.class); createMetadataForTestModelFieldWithName("fieldWithInvalidPathAnnotation"); } @Test(expected = IllegalArgumentException.class) public void testTreatmentOfUnsupportedCollectionTypes() throws Exception { withModelType(TestResourceModelWithUnsupportedCollectionTypes.class); createMetadataForTestModelFieldWithName("hashSetField"); } @Test public void testChildrenAsResources() throws Exception { createMetadataForTestModelFieldWithName("childrenAsResources"); assertThat(this.testee.isChildrenAnnotationPresent()).isTrue(); } @Test public void testChildrenAsResourcesWithMetaAnnotation() throws Exception { createMetadataForTestModelFieldWithName("childrenAsResourcesWithMetaAnnotation"); assertThat(this.testee.isChildrenAnnotationPresent()).isTrue(); } @Test(expected = IllegalArgumentException.class) public void testChildrenAnnotationOnInvalidFieldType() { withModelType(TestResourceModelWithUnsupportedCollectionTypes.class); createMetadataForTestModelFieldWithName("hashMapField"); } @Test public void testDetectionOfPropertyTypedFields() throws Exception { createMetadataForTestModelFieldWithName("stringField"); assertFieldIsPropertyType(); createMetadataForTestModelFieldWithName("primitiveIntField"); assertFieldIsPropertyType(); createMetadataForTestModelFieldWithName("primitiveBooleanField"); assertFieldIsPropertyType(); createMetadataForTestModelFieldWithName("primitiveLongField"); assertFieldIsPropertyType(); createMetadataForTestModelFieldWithName("primitiveFloatField"); assertFieldIsPropertyType(); createMetadataForTestModelFieldWithName("primitiveDoubleField"); assertFieldIsPropertyType(); createMetadataForTestModelFieldWithName("primitiveShortField"); assertFieldIsPropertyType(); createMetadataForTestModelFieldWithName("dateField"); assertFieldIsPropertyType(); createMetadataForTestModelFieldWithName("calendarField"); assertFieldIsPropertyType(); } @Test public void testDetectionOfCollectionTypedPropertyFields() throws Exception { createMetadataForTestModelFieldWithName("collectionOfStrings"); assertFieldIsPropertyType(); assertFieldIsCollectionType(); assertFieldIsInstantiableCollectionType(); } @Test public void testDetectionOfPathExpression() throws Exception { createMetadataForTestModelFieldWithName("stringFieldWithPlaceholder"); assertFieldHasPathExpression(); } @Test public void testDetectionOfOptionalFieldWithReferenceAnnotation() throws Exception { createMetadataForTestModelFieldWithName("lazyReferenceToOtherModel"); assertOptionalFieldIsDetected(); assertFieldTypeIs(OtherTestResourceModel.class); } @Test public void testDetectionOfOptionalFieldWithPointingToChildResource() throws Exception { createMetadataForTestModelFieldWithName("lazyReferenceToChildAsOtherModel"); assertOptionalFieldIsDetected(); assertFieldTypeIs(OtherTestResourceModel.class); } @Test public void testProvisioningOfLazyLoadingFactoryForChildrenCollection() throws Exception { createMetadataForTestModelFieldWithName("childrenAsResources"); assertLazyLoadingCollectionFactoryIsCreated(); } @Test public void testProvisioningOfLazyLoadingFactoryForReferenceCollection() throws Exception { createMetadataForTestModelFieldWithName("referencedResourcesListWithSimpleTypeParameter"); assertLazyLoadingCollectionFactoryIsCreated(); } @Test public void testResolutionOfArrayComponentType() throws Exception { createMetadataForTestModelFieldWithName("collectionOfStrings"); assertArrayTypeOfComponentTypeIs(String[].class); } @Test public void testOptionalFieldsAreTransparentlyTreatedLikeTheirTargetType() throws Exception { createMetadataForTestModelFieldWithName("optionalChildContentResourcesAsResources"); assertFieldIsInstantiableCollectionType(); assertFieldTypeIs(List.class); assertTypeParameterIs(Resource.class); } @Test public void testMetadataMakesFieldAccessible() throws Exception { TestResourceModel testResourceModel = new TestResourceModel(); createMetadataForTestModelFieldWithName("stringField"); setField(this.testee.getField(), testResourceModel, "JunitTest"); assertThat(testResourceModel.getStringField()).isEqualTo("JunitTest"); } private void assertFieldTypeIs(Class<?> type) { assertThat(this.testee.getType()).isEqualTo(type); } private void assertLazyLoadingCollectionFactoryIsCreated() { assertThat(this.testee.getCollectionProxyFactory()).isNotNull(); } private void assertOptionalFieldIsDetected() { assertThat(this.testee.isOptional()).isTrue(); } private void assertChildrenHasResolveBelowEveryChildPath() { assertThat(this.testee.isResolveBelowEveryChildPathPresentOnChildren()).isTrue(); } private void assertChildrenDoesNotHaveResolveBelowEveryChildPath() { assertThat(this.testee.isResolveBelowEveryChildPathPresentOnChildren()).isFalse(); } private void assertChildrenResolveBelowEveryChildPathIs(String path) { assertThat(this.testee.getResolveBelowEveryChildPathOnChildren()).isEqualTo(path); } private void assertFieldHasPathExpression() { assertThat(this.testee.isPathExpressionPresent()).isTrue(); } private void assertFieldIsInstantiableCollectionType() { assertThat(this.testee.isInstantiableCollectionType()).isTrue(); } private void assertFieldHasPath(String path) { assertThat(this.testee.getPath()).isEqualTo(path); } private void assertFieldHasPathAnnotation() { assertThat(this.testee.isPathAnnotationPresent()).isTrue(); } private void assertFieldHasNoPathAnnotation() { assertThat(this.testee.isPathAnnotationPresent()).isFalse(); } private void assertFieldIsThisReference() { assertThat(this.testee.isThisReference()).isTrue(); } private void assertFieldIsNotThisReference() { assertThat(this.testee.isThisReference()).isFalse(); } private void assertTypeParameterIs(Class<?> type) { assertThat(this.testee.getTypeParameter()).isEqualTo(type); } private void assertArrayTypeOfComponentTypeIs(Class<?> type) { assertThat(this.testee.getArrayTypeOfTypeParameter()).isEqualTo(type); } private void assertFieldIsCollectionType() { assertThat(this.testee.isCollectionType()).isTrue(); } private void assertFieldIsNotCollectionType() { assertThat(this.testee.isCollectionType()).isFalse(); } private void assertFieldIsReference() { assertThat(this.testee.isReference()).isTrue(); } private void assertFieldIsNotReference() { assertThat(this.testee.isReference()).isFalse(); } private void assertNoAppendPathIsPresentOnReference() { assertThat(this.testee.isAppendPathPresentOnReference()).isFalse(); } private void assertReferenceHasAppendPath() { assertThat(this.testee.isAppendPathPresentOnReference()).isTrue(); } private void assertReferenceAppendPathIs(String path) { assertThat(this.testee.getAppendPathOnReference()).isEqualTo(path); } private void assertFieldIsPropertyType() { assertThat(this.testee.isPropertyType()).isTrue(); } private void assertFieldIsNotPropertyType() { assertThat(this.testee.isPropertyType()).isFalse(); } private void createMetadataForTestModelFieldWithName(String fieldName) { Field field = findField(this.modelType, fieldName); this.testee = new MappedFieldMetaData(field, this.modelType); } private void withModelType(Class<?> type) { modelType = type; } }