/** * *************************************************************************** * Copyright (c) 2010 Qcadoo Limited * Project: Qcadoo Framework * Version: 1.4 * * This file is part of Qcadoo. * * Qcadoo is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation; either version 3 of the License, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *************************************************************************** */ package com.qcadoo.model.internal.classconverter; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import java.beans.PropertyDescriptor; import java.math.BigDecimal; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Set; import junit.framework.Assert; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.beanutils.PropertyUtils; import org.junit.BeforeClass; import org.junit.Test; import com.google.common.collect.Sets; import com.qcadoo.model.Utils; import com.qcadoo.model.internal.utils.ClassNameUtils; public class ModelXmlToClassConverterTest { private static final ModelXmlToClassConverterImpl MODEL_XML_TO_CLASSCONVERTER = new ModelXmlToClassConverterImpl(); private static Map<String, Class<?>> classes = new HashMap<String, Class<?>>(); private static Map<String, PropertyDescriptor> propertyDescriptors = new HashMap<String, PropertyDescriptor>(); @BeforeClass public static void init() throws Exception { MODEL_XML_TO_CLASSCONVERTER.setBeanClassLoader(ClassLoader.getSystemClassLoader()); for (Class<?> clazz : MODEL_XML_TO_CLASSCONVERTER.convert(Utils.FULL_FIRST_ENTITY_XML_RESOURCE, Utils.FULL_SECOND_ENTITY_XML_RESOURCE, Utils.FULL_THIRD_ENTITY_XML_RESOURCE, Utils.OTHER_FIRST_ENTITY_XML_RESOURCE, Utils.OTHER_SECOND_ENTITY_XML_RESOURCE)) { classes.put(clazz.getCanonicalName(), clazz); } for (PropertyDescriptor propertyDescriptor : PropertyUtils.getPropertyDescriptors(classes.get(ClassNameUtils .getFullyQualifiedClassName("full", "firstEntity")))) { propertyDescriptors.put(propertyDescriptor.getName(), propertyDescriptor); } } @Test public void shouldDefineClasses() throws Exception { assertEquals(5, classes.size()); } @Test public void shouldHaveProperName() throws Exception { assertNotNull(classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "firstEntity"))); assertNotNull(classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "secondEntity"))); assertNotNull(classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "thirdEntity"))); assertNotNull(classes.get(ClassNameUtils.getFullyQualifiedClassName("other", "firstEntity"))); assertNotNull(classes.get(ClassNameUtils.getFullyQualifiedClassName("other", "secondEntity"))); } @Test public void shouldDefineIdentifier() { verifyField(propertyDescriptors.get("id"), Long.class); } @Test public void shouldDefineSimpleFields() throws Exception { verifyField(propertyDescriptors.get("fieldInteger"), Integer.class); verifyField(propertyDescriptors.get("fieldString"), String.class); verifyField(propertyDescriptors.get("fieldText"), String.class); verifyField(propertyDescriptors.get("fieldDecimal"), BigDecimal.class); verifyField(propertyDescriptors.get("fieldDecimalOnlyWithScale"), BigDecimal.class); verifyField(propertyDescriptors.get("fieldDecimalWithoutValidators"), BigDecimal.class); verifyField(propertyDescriptors.get("fieldDatetime"), Date.class); verifyField(propertyDescriptors.get("fieldDate"), Date.class); verifyField(propertyDescriptors.get("fieldBoolean"), Boolean.class); verifyField(propertyDescriptors.get("fieldDictionary"), String.class); verifyField(propertyDescriptors.get("fieldOtherDictionary"), String.class); verifyField(propertyDescriptors.get("fieldEnum"), String.class); verifyField(propertyDescriptors.get("fieldPassword"), String.class); verifyField(propertyDescriptors.get("fieldPriority"), Integer.class); } @Test public void shouldDefineActivableField() throws Exception { verifyField(propertyDescriptors.get("active"), Boolean.class); } @Test public void shouldDefineBelongsToFields() throws Exception { verifyField(propertyDescriptors.get("fieldSecondEntity"), classes.get(ClassNameUtils.getFullyQualifiedClassName("other", "secondEntity"))); verifyField(propertyDescriptors.get("fieldSecondEntity2"), classes.get(ClassNameUtils.getFullyQualifiedClassName("other", "secondEntity"))); } @Test public void shouldDefineManyToManyFields() throws Exception { verifyField(propertyDescriptors.get("fieldManyToMany"), Set.class); } @Test public void shouldDefineHasManyFields() throws Exception { verifyField(propertyDescriptors.get("fieldTree"), Set.class); verifyField(propertyDescriptors.get("fieldHasMany"), Set.class); } @Test public void shouldHaveAuditableFields() throws Exception { verifyField(propertyDescriptors.get("createDate"), Date.class); verifyField(propertyDescriptors.get("updateDate"), Date.class); verifyField(propertyDescriptors.get("createUser"), String.class); verifyField(propertyDescriptors.get("updateUser"), String.class); } @Test public void shouldHaveToStringMethod() throws Exception { // given Object entity = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "firstEntity")).newInstance(); BeanUtils.setProperty(entity, "fieldInteger", 13); BeanUtils.setProperty(entity, "fieldString", "Xxx"); // when String string = entity.toString(); // then assertTrue(string.contains("fieldInteger=13")); assertTrue(string.contains("fieldString=Xxx")); assertTrue(string.contains(ClassNameUtils.getFullyQualifiedClassName("full", "firstEntity"))); } @Test public void shouldHaveHashCodeMethod() throws Exception { Object entity1 = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "firstEntity")).newInstance(); Object entity2 = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "firstEntity")).newInstance(); BeanUtils.setProperty(entity1, "fieldInteger", 13); BeanUtils.setProperty(entity2, "fieldInteger", 13); BeanUtils.setProperty(entity1, "fieldString", "Xxx"); BeanUtils.setProperty(entity2, "fieldString", "Xxx"); assertTrue(entity1.hashCode() == entity1.hashCode()); assertTrue(entity1.hashCode() == entity2.hashCode()); BeanUtils.setProperty(entity2, "fieldString", "Xxz"); assertFalse(entity1.hashCode() == entity2.hashCode()); } @Test public void shouldHaveEqualsMethod() throws Exception { Object entity1 = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "firstEntity")).newInstance(); Object entity2 = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "firstEntity")).newInstance(); Object entity3 = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "secondEntity")).newInstance(); BeanUtils.setProperty(entity1, "fieldInteger", 13); BeanUtils.setProperty(entity2, "fieldInteger", 13); BeanUtils.setProperty(entity1, "fieldString", "Xxx"); BeanUtils.setProperty(entity2, "fieldString", "Xxx"); assertTrue(entity1.equals(entity1)); assertTrue(entity1.equals(entity2)); assertTrue(entity2.equals(entity1)); BeanUtils.setProperty(entity2, "fieldString", "Xxz"); assertFalse(entity1.equals(entity2)); assertFalse(entity2.equals(entity1)); assertFalse(entity1.equals(null)); assertFalse(entity1.equals(entity3)); } @Test public void shouldHashCodeDoNotHaveCycleWithBelongsToFields() throws Exception { // given Object firstEntity = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "firstEntity")).newInstance(); Object thirdEntity = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "thirdEntity")).newInstance(); BeanUtils.setProperty(firstEntity, "fieldThirdEntity", thirdEntity); BeanUtils.setProperty(thirdEntity, "fieldFirstEntity", firstEntity); // when & then try { firstEntity.hashCode(); thirdEntity.hashCode(); } catch (StackOverflowError t) { Assert.fail(); } } @Test public void shouldHashCodeDoNotHaveCycleWithHasManyFields() throws Exception { // given Object firstEntity = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "firstEntity")).newInstance(); Object thirdEntity = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "thirdEntity")).newInstance(); BeanUtils.setProperty(firstEntity, "fieldHasMany", Sets.newHashSet(thirdEntity)); BeanUtils.setProperty(thirdEntity, "fieldFirstEntity", firstEntity); // when & then try { firstEntity.hashCode(); thirdEntity.hashCode(); } catch (StackOverflowError t) { Assert.fail(); } } @Test public void shouldHashCodeDoNotHaveCycleWithManyToManyFields() throws Exception { // given Object firstEntity = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "firstEntity")).newInstance(); Object thirdEntity = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "thirdEntity")).newInstance(); BeanUtils.setProperty(firstEntity, "fieldManyToMany", Sets.newHashSet(thirdEntity)); BeanUtils.setProperty(thirdEntity, "fieldManyToMany", Sets.newHashSet(firstEntity)); // when & then try { firstEntity.hashCode(); thirdEntity.hashCode(); } catch (StackOverflowError t) { Assert.fail(); } } @Test public void shouldHashCodeDoNotHaveCycleWithBelongsToAndManyToManyFields() throws Exception { // given Object firstEntity = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "firstEntity")).newInstance(); Object thirdEntity = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "thirdEntity")).newInstance(); BeanUtils.setProperty(firstEntity, "fieldThirdEntity", thirdEntity); BeanUtils.setProperty(thirdEntity, "fieldManyToMany", Sets.newHashSet(firstEntity)); // when & then try { firstEntity.hashCode(); thirdEntity.hashCode(); } catch (StackOverflowError t) { Assert.fail(); } } @Test public final void shouldReturnDifferentHashCodesIfRelatedEntitiesAreDifferent() throws Exception { // given Object firstEntityA = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "firstEntity")).newInstance(); Object firstEntityB = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "firstEntity")).newInstance(); Object thirdEntityA = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "thirdEntity")).newInstance(); Object thirdEntityB = classes.get(ClassNameUtils.getFullyQualifiedClassName("full", "thirdEntity")).newInstance(); BeanUtils.setProperty(firstEntityA, "fieldInteger", 13); BeanUtils.setProperty(firstEntityA, "fieldString", "Xxx"); BeanUtils.setProperty(firstEntityA, "fieldManyToMany", Sets.newHashSet(thirdEntityA)); BeanUtils.setProperty(thirdEntityA, "fieldString", "Aaa"); BeanUtils.setProperty(thirdEntityA, "fieldManyToMany", Sets.newHashSet(firstEntityA)); BeanUtils.setProperty(firstEntityB, "fieldInteger", 13); BeanUtils.setProperty(firstEntityB, "fieldString", "Xxx"); BeanUtils.setProperty(firstEntityB, "fieldManyToMany", Sets.newHashSet(thirdEntityB)); BeanUtils.setProperty(thirdEntityB, "fieldString", "Bbb"); BeanUtils.setProperty(thirdEntityB, "fieldManyToMany", Sets.newHashSet(firstEntityB)); // when int hashCodeFirstB = firstEntityB.hashCode(); assertFalse(firstEntityA.hashCode() == firstEntityB.hashCode()); BeanUtils.setProperty(thirdEntityB, "fieldString", "Aaa"); assertFalse(hashCodeFirstB == firstEntityB.hashCode()); BeanUtils.setProperty(firstEntityB, "fieldManyToMany", Sets.newHashSet(thirdEntityA)); assertTrue(firstEntityA.hashCode() == firstEntityB.hashCode()); } private void verifyField(final PropertyDescriptor propertyDescriptor, final Class<?> type) { verifyField(propertyDescriptor, type, true, true); } private void verifyField(final PropertyDescriptor propertyDescriptor, final Class<?> type, final boolean readable, final boolean writable) { assertEquals(type, propertyDescriptor.getPropertyType()); if (writable) { assertNotNull(propertyDescriptor.getWriteMethod()); } else { assertNull(propertyDescriptor.getWriteMethod()); } if (readable) { assertNotNull(propertyDescriptor.getReadMethod()); } else { assertNull(propertyDescriptor.getReadMethod()); } } }