diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaAttributeGenerationVisitor.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaAttributeGenerationVisitor.java index 4adf7695d3..f031a2bee3 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaAttributeGenerationVisitor.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaAttributeGenerationVisitor.java @@ -138,14 +138,20 @@ public class MetaAttributeGenerationVisitor extends SimpleTypeVisitor6 COLLECTIONS = new HashMap(); diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CollectionAsBasicTypeTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CollectionAsBasicTypeTest.java new file mode 100644 index 0000000000..10b436c510 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CollectionAsBasicTypeTest.java @@ -0,0 +1,89 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.jpamodelgen.test.collectionbasictype; + +import org.hibernate.jpamodelgen.test.util.CompilationTest; +import org.hibernate.jpamodelgen.test.util.TestForIssue; +import org.hibernate.jpamodelgen.test.util.WithClasses; + +import org.junit.Test; + +import static org.hibernate.jpamodelgen.test.util.TestUtil.assertAttributeTypeInMetaModelFor; +import static org.hibernate.jpamodelgen.test.util.TestUtil.assertListAttributeTypeInMetaModelFor; +import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMetamodelClassGeneratedFor; + +/** + * @author helloztt + */ +public class CollectionAsBasicTypeTest extends CompilationTest { + + @Test + @TestForIssue(jiraKey = "HHH-12338") + @WithClasses({Goods.class, Product.class}) + public void testConvert() throws ClassNotFoundException, NoSuchFieldException { + assertMetamodelClassGeneratedFor(Product.class); + assertMetamodelClassGeneratedFor(Goods.class); + assertListAttributeTypeInMetaModelFor( + Goods.class, + "productList", + Product.class, + "ListAttribute generic type should be Product" + ); + assertAttributeTypeInMetaModelFor( + Goods.class, + "tags", + Goods.class.getDeclaredField("tags").getGenericType(), + "Wrong meta model type" + ); + + } + + @Test + @TestForIssue(jiraKey = "HHH-12338") + @WithClasses({Person.class}) + public void testListType() throws ClassNotFoundException, NoSuchFieldException { + assertMetamodelClassGeneratedFor(Person.class); + + assertAttributeTypeInMetaModelFor( + Person.class, + "phones", + Person.class.getDeclaredField("phones").getGenericType(), + "Wrong meta model type" + ); + + } + + @Test + @TestForIssue(jiraKey = "HHH-12338") + @WithClasses({PersonPhone.class}) + public void testListTypeWithImport() throws ClassNotFoundException, NoSuchFieldException { + assertMetamodelClassGeneratedFor(PersonPhone.class); + + assertAttributeTypeInMetaModelFor( + PersonPhone.class, + "phones", + PersonPhone.class.getDeclaredField("phones").getGenericType(), + "Wrong meta model type" + ); + + } + + @Test + @TestForIssue(jiraKey = "HHH-12338") + @WithClasses({PhoneBook.class}) + public void testMapType() throws ClassNotFoundException, NoSuchFieldException { + assertMetamodelClassGeneratedFor(PhoneBook.class); + + assertAttributeTypeInMetaModelFor( + PhoneBook.class, + "phones", + PhoneBook.class.getDeclaredField("phones").getGenericType(), + "Wrong meta model type" + ); + + } +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CommaDelimitedStringMapJavaTypeDescriptor.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CommaDelimitedStringMapJavaTypeDescriptor.java new file mode 100644 index 0000000000..040292922d --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CommaDelimitedStringMapJavaTypeDescriptor.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.jpamodelgen.test.collectionbasictype; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.java.AbstractTypeDescriptor; +import org.hibernate.type.descriptor.java.MutableMutabilityPlan; + +/** + * @author Vlad Mihalcea + */ +public class CommaDelimitedStringMapJavaTypeDescriptor extends AbstractTypeDescriptor { + + public static final String DELIMITER = ","; + + public CommaDelimitedStringMapJavaTypeDescriptor() { + super( + Map.class, + new MutableMutabilityPlan() { + @Override + protected Map deepCopyNotNull(Map value) { + return new HashMap( value ); + } + } + ); + } + + @Override + public String toString(Map value) { + return null; + } + + @Override + public Map fromString(String string) { + return null; + } + + @Override + public X unwrap(Map value, Class type, WrapperOptions options) { + return (X) toString( value ); + } + + @Override + public Map wrap(X value, WrapperOptions options) { + return fromString( (String) value ); + } +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CommaDelimitedStringsJavaTypeDescriptor.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CommaDelimitedStringsJavaTypeDescriptor.java new file mode 100644 index 0000000000..a09fad55f6 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CommaDelimitedStringsJavaTypeDescriptor.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.jpamodelgen.test.collectionbasictype; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.java.AbstractTypeDescriptor; +import org.hibernate.type.descriptor.java.MutableMutabilityPlan; + +/** + * @author Vlad Mihalcea + */ +public class CommaDelimitedStringsJavaTypeDescriptor extends AbstractTypeDescriptor { + + public static final String DELIMITER = ","; + + public CommaDelimitedStringsJavaTypeDescriptor() { + super( + List.class, + new MutableMutabilityPlan() { + @Override + protected List deepCopyNotNull(List value) { + return new ArrayList( value ); + } + } + ); + } + + @Override + public String toString(List value) { + return ( (List) value ).stream().collect( Collectors.joining( DELIMITER ) ); + } + + @Override + public List fromString(String string) { + List values = new ArrayList<>(); + Collections.addAll( values, string.split( DELIMITER ) ); + return values; + } + + @Override + public X unwrap(List value, Class type, WrapperOptions options) { + return (X) toString( value ); + } + + @Override + public List wrap(X value, WrapperOptions options) { + return fromString( (String) value ); + } +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CommaDelimitedStringsMapType.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CommaDelimitedStringsMapType.java new file mode 100644 index 0000000000..28eb1ad601 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CommaDelimitedStringsMapType.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.jpamodelgen.test.collectionbasictype; + +import java.util.List; +import java.util.Map; + +import org.hibernate.type.AbstractSingleColumnStandardBasicType; +import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor; + +/** + * @author Vlad Mihalcea + */ +public class CommaDelimitedStringsMapType extends AbstractSingleColumnStandardBasicType { + + public CommaDelimitedStringsMapType() { + super( + VarcharTypeDescriptor.INSTANCE, + new CommaDelimitedStringMapJavaTypeDescriptor() + ); + } + + @Override + public String getName() { + return "comma_delimited_string_map"; + } +} \ No newline at end of file diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CommaDelimitedStringsType.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CommaDelimitedStringsType.java new file mode 100644 index 0000000000..c15ac474d0 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/CommaDelimitedStringsType.java @@ -0,0 +1,30 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.jpamodelgen.test.collectionbasictype; + +import java.util.List; + +import org.hibernate.type.AbstractSingleColumnStandardBasicType; +import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor; + +/** + * @author Vlad Mihalcea + */ +public class CommaDelimitedStringsType extends AbstractSingleColumnStandardBasicType { + + public CommaDelimitedStringsType() { + super( + VarcharTypeDescriptor.INSTANCE, + new CommaDelimitedStringsJavaTypeDescriptor() + ); + } + + @Override + public String getName() { + return "comma_delimited_strings"; + } +} \ No newline at end of file diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/Goods.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/Goods.java new file mode 100644 index 0000000000..b494b62fe0 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/Goods.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.jpamodelgen.test.collectionbasictype; + +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import java.util.List; + +/** + * @author helloztt + */ +@Entity +public class Goods { + private Long id; + private List productList; + private List tags; + + @Id + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @OneToMany + public List getProductList() { + return productList; + } + + public void setProductList(List productList) { + this.productList = productList; + } + + @Convert(converter = StringToListConverter.class) + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/Person.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/Person.java new file mode 100644 index 0000000000..c648f25e8d --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/Person.java @@ -0,0 +1,27 @@ +package org.hibernate.jpamodelgen.test.collectionbasictype; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; + +/** + * @author Vlad Mihalcea + */ +@Entity(name = "Person") +@TypeDef( name = "comma_delimited_strings", typeClass = CommaDelimitedStringsType.class) +public class Person { + + @Id + private Long id; + + @Type(type = "comma_delimited_strings") + private List phones = new ArrayList<>(); + + public List getPhones() { + return phones; + } +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/PersonPhone.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/PersonPhone.java new file mode 100644 index 0000000000..7d4c05417b --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/PersonPhone.java @@ -0,0 +1,28 @@ +package org.hibernate.jpamodelgen.test.collectionbasictype; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; +import org.hibernate.jpamodelgen.test.collectionbasictype.extras.Phone; + +/** + * @author Vlad Mihalcea + */ +@Entity(name = "Person") +@TypeDef( name = "comma_delimited_strings", typeClass = CommaDelimitedStringsType.class) +public class PersonPhone { + + @Id + private Long id; + + @Type(type = "comma_delimited_strings") + private List phones = new ArrayList<>(); + + public List getPhones() { + return phones; + } +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/PhoneBook.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/PhoneBook.java new file mode 100644 index 0000000000..4ea42b0439 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/PhoneBook.java @@ -0,0 +1,27 @@ +package org.hibernate.jpamodelgen.test.collectionbasictype; + +import java.util.HashMap; +import java.util.Map; +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; + +/** + * @author Vlad Mihalcea + */ +@Entity(name = "Person") +@TypeDef( name = "comma_delimited_string_map", typeClass = CommaDelimitedStringsMapType.class) +public class PhoneBook { + + @Id + private Long id; + + @Type(type = "comma_delimited_string_map") + private Map phones = new HashMap<>(); + + public Map getPhones() { + return phones; + } +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/Product.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/Product.java new file mode 100644 index 0000000000..275c509254 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/Product.java @@ -0,0 +1,36 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.jpamodelgen.test.collectionbasictype; + +import javax.persistence.Entity; +import javax.persistence.Id; + +/** + * @author helloztt + */ +@Entity +public class Product { + private int proId; + private String proName; + + @Id + public int getProId() { + return proId; + } + + public void setProId(int proId) { + this.proId = proId; + } + + public String getProName() { + return proName; + } + + public void setProName(String proName) { + this.proName = proName; + } +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/StringToListConverter.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/StringToListConverter.java new file mode 100644 index 0000000000..41b96aacf0 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/StringToListConverter.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.jpamodelgen.test.collectionbasictype; + +import javax.persistence.AttributeConverter; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author helloztt + */ +public class StringToListConverter implements AttributeConverter, String> { + private static final String COMMA = ","; + + @Override + public String convertToDatabaseColumn(List attribute) { + if (attribute == null || attribute.size() == 0) { + return null; + } + return attribute.stream().collect(Collectors.joining(COMMA)); + } + + @Override + public List convertToEntityAttribute(String dbData) { + if (dbData == null || dbData.length() == 0) { + return null; + } + return Arrays.asList(dbData.split(COMMA)); + } +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/extras/Phone.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/extras/Phone.java new file mode 100644 index 0000000000..ad0f4b393e --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/collectionbasictype/extras/Phone.java @@ -0,0 +1,19 @@ +package org.hibernate.jpamodelgen.test.collectionbasictype.extras; + +import java.io.Serializable; + +/** + * @author Vlad Mihalcea + */ +public class Phone implements Serializable { + + private String phoneNumber; + + public String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/TestUtil.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/TestUtil.java index 863aa8415d..f8ebe99512 100644 --- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/TestUtil.java +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/TestUtil.java @@ -101,6 +101,18 @@ public class TestUtil { ); } + public static void assertAttributeTypeInMetaModelFor(Class clazz, String fieldName, Type expectedType, String errorString) { + Field field = getFieldFromMetamodelFor( clazz, fieldName ); + assertNotNull( "Cannot find field '" + fieldName + "' in " + clazz.getName(), field ); + ParameterizedType type = (ParameterizedType) field.getGenericType(); + Type actualType = type.getActualTypeArguments()[1]; + assertEquals( + "Types do not match: " + buildErrorString( errorString, clazz ), + expectedType, + actualType + ); + } + public static void assertListAttributeTypeInMetaModelFor(Class clazz, String fieldName, Class expectedType, String errorString) { Field field = getFieldFromMetamodelFor( clazz, fieldName ); assertNotNull( "Cannot find field '" + fieldName + "' in " + clazz.getName(), field );