From 85a3d7062b4d905c31eafbbeb474cad5d9c6525a Mon Sep 17 00:00:00 2001 From: Daren Isaacs Date: Wed, 29 Jan 2025 14:44:15 +1000 Subject: [PATCH] HBX-2931 Pojo template cleanup. Adjust freemarker pojo templates for uniform whitespace usage. ImportContextImpl - normalise line separators: remove carriage return char. Add a template for field annotations. Allow selection of field annotations over default property annotations by configuration of a toolclass property "hibernatetool.annotateField.toolclass". The class allocated to this property is not important only the name "annotateField". Tweak existing h2 database EntityNamingTest for testing of: -field annotations -optimistic lock @Version annotation -extra class code generation using MetaAttribute logic. --- .../export/java/ImportContextImpl.java | 4 +- .../resources/pojo/Ejb3FieldGetAnnotation.ftl | 23 ++++ .../pojo/Ejb3PropertyGetAnnotation.ftl | 35 +++--- orm/src/main/resources/pojo/Pojo.ftl | 10 -- .../main/resources/pojo/PojoConstructors.ftl | 33 +++--- .../resources/pojo/PojoEqualsHashcode.ftl | 35 +++--- .../resources/pojo/PojoExtraClassCode.ftl | 8 +- orm/src/main/resources/pojo/PojoFields.ftl | 13 ++- .../pojo/PojoInterfacePropertyAccessors.ftl | 17 ++- .../resources/pojo/PojoPropertyAccessors.ftl | 15 +-- orm/src/main/resources/pojo/PojoToString.ftl | 24 ++-- .../tool/entitynaming/EntityNamingTest.java | 110 +++++++++++++++++- .../tool/entitynaming/FieldAnnotation.java | 9 ++ .../RevengStrategyEntityNaming.java | 106 ++++++++++++++++- .../hibernate/tool/entitynaming/create.sql | 2 +- .../hibernate/tool/entitynaming/shape.hbm.xml | 15 +++ 16 files changed, 362 insertions(+), 97 deletions(-) create mode 100644 orm/src/main/resources/pojo/Ejb3FieldGetAnnotation.ftl create mode 100644 test/h2/src/test/java/org/hibernate/tool/entitynaming/FieldAnnotation.java create mode 100644 test/h2/src/test/resources/org/hibernate/tool/entitynaming/shape.hbm.xml diff --git a/orm/src/main/java/org/hibernate/tool/internal/export/java/ImportContextImpl.java b/orm/src/main/java/org/hibernate/tool/internal/export/java/ImportContextImpl.java index 85879c7647..80e5af4ad4 100644 --- a/orm/src/main/java/org/hibernate/tool/internal/export/java/ImportContextImpl.java +++ b/orm/src/main/java/org/hibernate/tool/internal/export/java/ImportContextImpl.java @@ -136,9 +136,9 @@ public String generateImports() { // dont add automatically "imported" stuff } else { if(staticImports.contains(next)) { - buf.append("import static " + next + ";\r\n"); + buf.append("import static " + next + ";\n"); } else { - buf.append("import " + next + ";\r\n"); + buf.append("import " + next + ";\n"); } } } diff --git a/orm/src/main/resources/pojo/Ejb3FieldGetAnnotation.ftl b/orm/src/main/resources/pojo/Ejb3FieldGetAnnotation.ftl new file mode 100644 index 0000000000..5da85dccef --- /dev/null +++ b/orm/src/main/resources/pojo/Ejb3FieldGetAnnotation.ftl @@ -0,0 +1,23 @@ +<#if ejb3> + <#if pojo.hasIdentifierProperty()> + <#if field.equals(clazz.identifierProperty)> +${pojo.generateAnnIdGenerator()}<#--has space prepended--> + + + <#if c2h.isOneToOne(field)> + ${pojo.generateOneToOneAnnotation(field, md)} + <#elseif c2h.isManyToOne(field)> + ${pojo.generateManyToOneAnnotation(field)} + <#--TODO support optional and targetEntity--> +${pojo.generateJoinColumnsAnnotation(field, md)} + <#elseif c2h.isCollection(field)> + ${pojo.generateCollectionAnnotation(field, md)} + <#else> + <#if pojo.generateBasicAnnotation(field)?has_content > + <#if pojo.generateBasicAnnotation(field)?trim?length gt 0 > +${(pojo.generateBasicAnnotation(field))}<#--has space prepended--> + + +${pojo.generateAnnColumnAnnotation(field)}<#--has space prepended--> + + diff --git a/orm/src/main/resources/pojo/Ejb3PropertyGetAnnotation.ftl b/orm/src/main/resources/pojo/Ejb3PropertyGetAnnotation.ftl index fb2cac7512..5c631051bb 100644 --- a/orm/src/main/resources/pojo/Ejb3PropertyGetAnnotation.ftl +++ b/orm/src/main/resources/pojo/Ejb3PropertyGetAnnotation.ftl @@ -1,22 +1,23 @@ <#if ejb3> -<#if pojo.hasIdentifierProperty()> -<#if property.equals(clazz.identifierProperty)> - ${pojo.generateAnnIdGenerator()} -<#-- if this is the id property (getter)--> -<#-- explicitly set the column name for this property--> - - - -<#if c2h.isOneToOne(property)> -${pojo.generateOneToOneAnnotation(property, md)} -<#elseif c2h.isManyToOne(property)> -${pojo.generateManyToOneAnnotation(property)} -<#--TODO support optional and targetEntity--> + <#if pojo.hasIdentifierProperty()> + <#if property.equals(clazz.identifierProperty)> +${pojo.generateAnnIdGenerator()} + <#-- if this is the id property (getter)--> + <#-- explicitly set the column name for this property--> + + + <#if c2h.isOneToOne(property)> + ${pojo.generateOneToOneAnnotation(property, md)} + <#elseif c2h.isManyToOne(property)> + ${pojo.generateManyToOneAnnotation(property)} + <#--TODO support optional and targetEntity--> ${pojo.generateJoinColumnsAnnotation(property, md)} -<#elseif c2h.isCollection(property)> -${pojo.generateCollectionAnnotation(property, md)} -<#else> + <#elseif c2h.isCollection(property)> + ${pojo.generateCollectionAnnotation(property, md)} + <#else> + <#if pojo.generateBasicAnnotation(property) != " " > ${pojo.generateBasicAnnotation(property)} + ${pojo.generateAnnColumnAnnotation(property)} + - \ No newline at end of file diff --git a/orm/src/main/resources/pojo/Pojo.ftl b/orm/src/main/resources/pojo/Pojo.ftl index 84ff76a5b2..cb9b2cfb68 100644 --- a/orm/src/main/resources/pojo/Pojo.ftl +++ b/orm/src/main/resources/pojo/Pojo.ftl @@ -3,27 +3,17 @@ ${pojo.getPackageDeclaration()} <#assign classbody> <#include "PojoTypeDeclaration.ftl"/> { - <#if !pojo.isInterface()> <#include "PojoFields.ftl"/> - <#include "PojoConstructors.ftl"/> - <#include "PojoPropertyAccessors.ftl"/> - <#include "PojoToString.ftl"/> - <#include "PojoEqualsHashcode.ftl"/> - <#else> <#include "PojoInterfacePropertyAccessors.ftl"/> - <#include "PojoExtraClassCode.ftl"/> - } - ${pojo.generateImports()} ${classbody} - diff --git a/orm/src/main/resources/pojo/PojoConstructors.ftl b/orm/src/main/resources/pojo/PojoConstructors.ftl index eec96f2f20..b08c409a49 100644 --- a/orm/src/main/resources/pojo/PojoConstructors.ftl +++ b/orm/src/main/resources/pojo/PojoConstructors.ftl @@ -1,26 +1,25 @@ - <#-- /** default constructor */ --> public ${pojo.getDeclarationName()}() { } +<#if pojo.needsMinimalConstructor()><#-- /** minimal constructor */ --> -<#if pojo.needsMinimalConstructor()> <#-- /** minimal constructor */ --> public ${pojo.getDeclarationName()}(${c2j.asParameterList(pojo.getPropertyClosureForMinimalConstructor(), jdk5, pojo)}) { -<#if pojo.isSubclass() && !pojo.getPropertyClosureForSuperclassMinimalConstructor().isEmpty()> - super(${c2j.asArgumentList(pojo.getPropertyClosureForSuperclassMinimalConstructor())}); - -<#list pojo.getPropertiesForMinimalConstructor() as field> + <#if pojo.isSubclass() && !pojo.getPropertyClosureForSuperclassMinimalConstructor().isEmpty()> + super(${c2j.asArgumentList(pojo.getPropertyClosureForSuperclassMinimalConstructor())}); + + <#list pojo.getPropertiesForMinimalConstructor() as field> this.${c2j.keyWordCheck(field.name)} = ${c2j.keyWordCheck(field.name)}; - + } - -<#if pojo.needsFullConstructor()> -<#-- /** full constructor */ --> - public ${pojo.getDeclarationName()}(${c2j.asParameterList(pojo.getPropertyClosureForFullConstructor(), jdk5, pojo)}) { -<#if pojo.isSubclass() && !pojo.getPropertyClosureForSuperclassFullConstructor().isEmpty()> - super(${c2j.asArgumentList(pojo.getPropertyClosureForSuperclassFullConstructor())}); -<#list pojo.getPropertiesForFullConstructor() as field> - this.${c2j.keyWordCheck(field.name)} = ${c2j.keyWordCheck(field.name)}; - +<#if pojo.needsFullConstructor()><#-- /** full constructor */ --> + + public ${pojo.getDeclarationName()}(${c2j.asParameterList(pojo.getPropertyClosureForFullConstructor(), jdk5, pojo)}) { + <#if pojo.isSubclass() && !pojo.getPropertyClosureForSuperclassFullConstructor().isEmpty()> + super(${c2j.asArgumentList(pojo.getPropertyClosureForSuperclassFullConstructor())}); + + <#list pojo.getPropertiesForFullConstructor() as field> + this.${c2j.keyWordCheck(field.name)} = ${c2j.keyWordCheck(field.name)}; + } - + diff --git a/orm/src/main/resources/pojo/PojoEqualsHashcode.ftl b/orm/src/main/resources/pojo/PojoEqualsHashcode.ftl index 92fa70ee21..af81cbafbe 100644 --- a/orm/src/main/resources/pojo/PojoEqualsHashcode.ftl +++ b/orm/src/main/resources/pojo/PojoEqualsHashcode.ftl @@ -1,18 +1,21 @@ <#if pojo.needsEqualsHashCode() && !clazz.superclass?exists> <#assign classNameToCastTo><#if clazz.getProxyInterfaceName?exists>${clazz.getProxyInterfaceName()}<#else>${pojo.getDeclarationName()} - public boolean equals(Object other) { - if ( (this == other ) ) return true; - if ( (other == null ) ) return false; - if ( !(other instanceof ${classNameToCastTo}) ) return false; - ${classNameToCastTo} castOther = ( ${classNameToCastTo} ) other; - - return ${pojo.generateEquals("this", "castOther", jdk5)}; - } - - public int hashCode() { - int result = 17; - -<#list pojo.getAllPropertiesIterator() as property> ${pojo.generateHashCode(property, "result", "this", jdk5)} - return result; - } - \ No newline at end of file + + public boolean equals(Object other) { + if ( (this == other ) ) return true; + if ( (other == null ) ) return false; + if ( !(other instanceof ${classNameToCastTo}) ) return false; + ${classNameToCastTo} castOther = ( ${classNameToCastTo} ) other; + return ${pojo.generateEquals("this", "castOther", jdk5)}; + } + + public int hashCode() { + int result = 17; + <#list pojo.getAllPropertiesIterator() as property> + <#if pojo.generateHashCode(property, "result", "this", jdk5)?trim?length gt 0 > + ${pojo.generateHashCode(property, "result", "this", jdk5)} + + + return result; + } + diff --git a/orm/src/main/resources/pojo/PojoExtraClassCode.ftl b/orm/src/main/resources/pojo/PojoExtraClassCode.ftl index 17ae88a243..c784d7d388 100644 --- a/orm/src/main/resources/pojo/PojoExtraClassCode.ftl +++ b/orm/src/main/resources/pojo/PojoExtraClassCode.ftl @@ -1,4 +1,6 @@ -<#if pojo.hasMetaAttribute("class-code")> // The following is extra code specified in the hbm.xml files +<#if pojo.hasMetaAttribute("class-code")> + + // Extra-code via hbm.xml/RevengStrategy config. ${pojo.getExtraClassCode()} - // end of extra code specified in the hbm.xml files - \ No newline at end of file + // Extra-code end. + diff --git a/orm/src/main/resources/pojo/PojoFields.ftl b/orm/src/main/resources/pojo/PojoFields.ftl index 205da1e929..d5a7daffc0 100644 --- a/orm/src/main/resources/pojo/PojoFields.ftl +++ b/orm/src/main/resources/pojo/PojoFields.ftl @@ -1,8 +1,13 @@ <#-- // Fields --> - -<#list pojo.getAllPropertiesIterator() as field><#if pojo.getMetaAttribAsBool(field, "gen-property", true)> <#if pojo.hasMetaAttribute(field, "field-description")> /** +<#list pojo.getAllPropertiesIterator() as field> + <#if pojo.getMetaAttribAsBool(field, "gen-property", true)> + <#if pojo.hasMetaAttribute(field, "field-description")> + /** ${pojo.getFieldJavaDoc(field, 0)} */ - ${pojo.getFieldModifiers(field)} ${pojo.getJavaTypeName(field, jdk5)} ${c2j.keyWordCheck(field.name)}<#if pojo.hasFieldInitializor(field, jdk5)> = ${pojo.getFieldInitialization(field, jdk5)}; - + + <#if annotateField??><#include "Ejb3FieldGetAnnotation.ftl"/><#--an alternative to property annotation, configured in PojoPropertyAccessors.ftl--> + ${pojo.getFieldModifiers(field)} ${pojo.getJavaTypeName(field, jdk5)} ${c2j.keyWordCheck(field.name)}<#if pojo.hasFieldInitializor(field, jdk5)> = ${pojo.getFieldInitialization(field, jdk5)}; + + diff --git a/orm/src/main/resources/pojo/PojoInterfacePropertyAccessors.ftl b/orm/src/main/resources/pojo/PojoInterfacePropertyAccessors.ftl index fba5487098..eb0e803880 100644 --- a/orm/src/main/resources/pojo/PojoInterfacePropertyAccessors.ftl +++ b/orm/src/main/resources/pojo/PojoInterfacePropertyAccessors.ftl @@ -1,8 +1,15 @@ <#-- if interface --> <#-- Property accessors for interface --> -<#list pojo.getAllPropertiesIterator() as property><#if pojo.getMetaAttribAsBool(property, "gen-property", true)> /** - ${c2j.toJavaDoc(c2j.getMetaAsString(property, "field-description"), 4)} */ - ${pojo.getPropertyGetModifiers(property)} ${pojo.getJavaTypeName(property, jdk5)} ${pojo.getGetterSignature(property)}(); +<#list pojo.getAllPropertiesIterator() as property> + <#if pojo.getMetaAttribAsBool(property, "gen-property", true)> + + <#if c2j.getMetaAsString(property, "field-description")?trim?length gt 0> + /** + ${c2j.toJavaDoc(c2j.getMetaAsString(property, "field-description"), 0)} + */ + + ${pojo.getPropertyGetModifiers(property)} ${pojo.getJavaTypeName(property, jdk5)} ${pojo.getGetterSignature(property)}(); - ${pojo.getPropertySetModifiers(property)} void set${pojo.getPropertyName(property)}(${pojo.getJavaTypeName(property, jdk5)} ${property.name}); - \ No newline at end of file + ${pojo.getPropertySetModifiers(property)} void set${pojo.getPropertyName(property)}(${pojo.getJavaTypeName(property, jdk5)} ${property.name}); + + diff --git a/orm/src/main/resources/pojo/PojoPropertyAccessors.ftl b/orm/src/main/resources/pojo/PojoPropertyAccessors.ftl index b166786237..3bde3be3f4 100644 --- a/orm/src/main/resources/pojo/PojoPropertyAccessors.ftl +++ b/orm/src/main/resources/pojo/PojoPropertyAccessors.ftl @@ -1,18 +1,19 @@ <#-- // Property accessors --> <#list pojo.getAllPropertiesIterator() as property> -<#if pojo.getMetaAttribAsBool(property, "gen-property", true)> - <#if pojo.hasFieldJavaDoc(property)> - /** + <#if pojo.getMetaAttribAsBool(property, "gen-property", true)> + <#if pojo.hasFieldJavaDoc(property)> + /** * ${pojo.getFieldJavaDoc(property, 4)} */ - - <#include "GetPropertyAnnotation.ftl"/> + + + <#if !annotateField??><#include "GetPropertyAnnotation.ftl"/><#-- Property annotations. Field annotation configured in PojoFields.ftl --> ${pojo.getPropertyGetModifiers(property)} ${pojo.getJavaTypeName(property, jdk5)} ${pojo.getGetterSignature(property)}() { return this.${c2j.keyWordCheck(property.name)}; } - + ${pojo.getPropertySetModifiers(property)} void set${pojo.getPropertyName(property)}(${pojo.getJavaTypeName(property, jdk5)} ${c2j.keyWordCheck(property.name)}) { this.${c2j.keyWordCheck(property.name)} = ${c2j.keyWordCheck(property.name)}; } - + diff --git a/orm/src/main/resources/pojo/PojoToString.ftl b/orm/src/main/resources/pojo/PojoToString.ftl index e60628e79c..e0920ff4d4 100644 --- a/orm/src/main/resources/pojo/PojoToString.ftl +++ b/orm/src/main/resources/pojo/PojoToString.ftl @@ -1,14 +1,16 @@ -<#if pojo.needsToString()> /** +<#if pojo.needsToString()> + + /** * toString * @return String */ - public String toString() { - StringBuffer buffer = new StringBuffer(); - - buffer.append(getClass().getName()).append("@").append(Integer.toHexString(hashCode())).append(" ["); -<#list pojo.getToStringPropertiesIterator() as property> buffer.append("${property.getName()}").append("='").append(${pojo.getGetterSignature(property)}()).append("' "); - buffer.append("]"); - - return buffer.toString(); - } - \ No newline at end of file + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append(getClass().getName()).append("@").append(Integer.toHexString(hashCode())).append(" ["); + <#list pojo.getToStringPropertiesIterator() as property> + buffer.append("${property.getName()}").append("='").append(${pojo.getGetterSignature(property)}()).append("' "); + + buffer.append("]"); + return buffer.toString(); + } + diff --git a/test/h2/src/test/java/org/hibernate/tool/entitynaming/EntityNamingTest.java b/test/h2/src/test/java/org/hibernate/tool/entitynaming/EntityNamingTest.java index 9c4a27363d..685a93e18a 100644 --- a/test/h2/src/test/java/org/hibernate/tool/entitynaming/EntityNamingTest.java +++ b/test/h2/src/test/java/org/hibernate/tool/entitynaming/EntityNamingTest.java @@ -19,6 +19,7 @@ */ package org.hibernate.tool.entitynaming; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; @@ -39,6 +40,7 @@ import org.hibernate.tools.test.util.ResourceUtil; import org.jboss.logging.Logger; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; @@ -67,6 +69,7 @@ public class EntityNamingTest { public File outputDir = new File("output"); static final String packageName = "com.entity"; + static final String SHAPE_HBM_FILE= "shape.hbm.xml"; Properties hibernateProperties = new Properties(); @@ -98,8 +101,8 @@ public void testGenerateJava() throws IOException { reveng = new RevengStrategyEntityNaming(reveng); - //Necessary to set the root strategy. - RevengSettings revengSettings + //Necessary to set the root strategy. + RevengSettings revengSettings = new RevengSettings(reveng).setDefaultPackageName(packageName) .setDetectManyToMany(true) .setDetectOneToOne(true) @@ -118,12 +121,113 @@ public void testGenerateJava() throws IOException { + packageName.replace(".", File.separator); File dummy = new File(packageDir, "Dummy.java"); assertTrue(dummy.exists()); + + //Check @Version annotation preceeds the method + String str = new String(Files.readAllBytes(dummy.toPath())); + int stringPos = str.indexOf("@Version"); + String versionMatch = "@Version\n @Column(name=\"duVersion\", nullable=false)\n public byte getDuVersion() {"; + String versionInFile = str.substring(stringPos, stringPos + versionMatch.length()); + Assertions.assertEquals(versionMatch,versionInFile ); + //Check addition of code via class-code MetaAttribute in PojoExtraClassCode.ftl + assertTrue(str.contains("specialProc()")); + File order = new File(packageDir, "Order.java"); assertTrue(order.exists()); File orderItem = new File(packageDir, "OrderItem.java"); assertTrue(orderItem.exists()); - String str = new String(Files.readAllBytes(orderItem.toPath())); + str = new String(Files.readAllBytes(orderItem.toPath())); assertTrue(str.contains("private Integer oiId;")); assertTrue(str.contains("private Order order;")); + //specialProc only added to dummy table. + assertFalse(str.contains("specialProc()")); + + //Check @Version annotation preceeds the field. + //Many hibernatetool.xxxName.toolclass may be loaded into the freemarker context as hibernate properties. + //The toolclass methods are accessable by xxxName in the template ie {$xxxName.methodName() + exporter.getProperties().put("hibernatetool.annotateField.toolclass", "org.hibernate.tool.entitynaming.FieldAnnotation"); + exporter.start(); + dummy = new File(packageDir, "Dummy.java"); + assertTrue(dummy.exists()); + str = new String(Files.readAllBytes(dummy.toPath())); + stringPos = str.indexOf("@Version"); + versionMatch = "@Version\n @Column(name=\"duVersion\", nullable=false)\n private byte duVersion;"; + versionInFile = str.substring(stringPos, stringPos + versionMatch.length()); + Assertions.assertEquals(versionMatch,versionInFile ); + + //Check toString() + stringPos = str.indexOf(" * toString"); + String toStringMatch = " * toString\n" + + " * @return String\n" + + " */\n" + + " public String toString() {\n" + + " StringBuffer buffer = new StringBuffer();\n" + + " buffer.append(getClass().getName()).append(\"@\").append(Integer." + + "toHexString(hashCode())).append(\" [\");\n" + + " buffer.append(\"duData\").append(\"='\").append(getDuData()).append(\"' \");\n" + + " buffer.append(\"]\");\n" + + " return buffer.toString();\n" + + " }\n"; + String toStringInFile = str.substring(stringPos, stringPos + toStringMatch.length()); + Assertions.assertEquals(toStringMatch,toStringInFile ); + + //Check equals() + stringPos = str.indexOf(" public boolean"); + String equalsMatch = " public boolean equals(Object other) {\n" + + " if ( (this == other ) ) return true;\n" + + " if ( (other == null ) ) return false;\n" + + " if ( !(other instanceof com.entity.Dummy) ) return false;\n" + + " com.entity.Dummy castOther = ( com.entity.Dummy ) other;\n" + + " return ( (this.getDuId()==castOther.getDuId()) || ( this.getDuId()!=null" + + " && castOther.getDuId()!=null && this.getDuId().equals(castOther.getDuId()) ) )\n" + + " && ( (this.getDuData()==castOther.getDuData()) || ( this.getDuData()!=null " + + "&& castOther.getDuData()!=null && this.getDuData().equals(castOther.getDuData()) ) );\n" + + " }\n"; + String equalsInFile = str.substring(stringPos, stringPos + equalsMatch.length()); + Assertions.assertEquals(equalsMatch, equalsInFile); + + //Check hashcode() + stringPos = str.indexOf(" public int hashCode()"); + String hashMatch = " public int hashCode() {\n" + + " int result = 17;\n" + + " result = 37 * result + ( getDuId() == null ? 0 : this.getDuId().hashCode() );\n" + + " result = 37 * result + ( getDuData() == null ? 0 : this.getDuData().hashCode() );\n" + + " return result;\n" + + " }\n"; + String hashInFile = str.substring(stringPos, stringPos + hashMatch.length()); + Assertions.assertEquals(hashMatch, hashInFile); + + //Check class description + stringPos = str.indexOf(" * Long description"); + String descMatch = " * Long description\n" + + " * for javadoc\n" + + " * of a particular entity.\n" + + " */\n"; + String descFile = str.substring(stringPos, stringPos + descMatch.length()); + Assertions.assertEquals(descMatch, descFile); + + //The only untested template is for interfaces. For completeness I will add a test + // for it here, even though it probably won't be used in reverse engineering. + File[] hbmFiles = new File[]{ + ResourceUtil.resolveResourceFile(this.getClass(), SHAPE_HBM_FILE)}; + MetadataDescriptor nativeMetadataDesc= MetadataDescriptorFactory.createNativeDescriptor( + null, hbmFiles, hibernateProperties); + exporter = ExporterFactory.createExporter(ExporterType.JAVA); + exporter.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, nativeMetadataDesc); + exporter.getProperties().put(ExporterConstants.DESTINATION_FOLDER, outputDir); + exporter.getProperties().setProperty("ejb3", "true"); + exporter.start(); + + File shape = new File(outputDir, "Shape.java"); + assertTrue(shape.exists()); + str = new String(Files.readAllBytes(shape.toPath())); + stringPos = str.indexOf("public interface Shape"); + String interfaceMatch = "public interface Shape {\n" + + "\n" + + " /**\n" + + " * Test Field Description\n" + + " */\n" + + " public long getId();\n"; + String interfaceFile = str.substring(stringPos, stringPos + interfaceMatch.length()); + Assertions.assertEquals(interfaceMatch, interfaceFile); } } diff --git a/test/h2/src/test/java/org/hibernate/tool/entitynaming/FieldAnnotation.java b/test/h2/src/test/java/org/hibernate/tool/entitynaming/FieldAnnotation.java new file mode 100644 index 0000000000..5e23960e38 --- /dev/null +++ b/test/h2/src/test/java/org/hibernate/tool/entitynaming/FieldAnnotation.java @@ -0,0 +1,9 @@ +package org.hibernate.tool.entitynaming; + +/** + * Marker class used to turn on field annotations. + * + * @author Daren + */ +public class FieldAnnotation { +} diff --git a/test/h2/src/test/java/org/hibernate/tool/entitynaming/RevengStrategyEntityNaming.java b/test/h2/src/test/java/org/hibernate/tool/entitynaming/RevengStrategyEntityNaming.java index 0a9f8e678a..d5fe96f673 100644 --- a/test/h2/src/test/java/org/hibernate/tool/entitynaming/RevengStrategyEntityNaming.java +++ b/test/h2/src/test/java/org/hibernate/tool/entitynaming/RevengStrategyEntityNaming.java @@ -18,12 +18,18 @@ */ package org.hibernate.tool.entitynaming; +import org.hibernate.mapping.MetaAttribute; + import java.util.ArrayList; import java.util.List; import org.hibernate.tool.api.reveng.RevengStrategy; +import org.hibernate.tool.api.reveng.TableIdentifier; import org.hibernate.tool.internal.reveng.strategy.DelegatingStrategy; +import java.util.HashMap; +import java.util.Map; + /** * * @author Daren @@ -35,7 +41,7 @@ public class RevengStrategyEntityNaming extends DelegatingStrategy { public RevengStrategyEntityNaming(RevengStrategy delegate) { super(delegate); this.schemas = new ArrayList<>(); - schemas.add(new SchemaSelection(){ + schemas.add(new SchemaSelection() { @Override public String getMatchCatalog() { /* no h2 pattern matching on catalog*/ @@ -58,4 +64,102 @@ public List getSchemaSelections() { return schemas; } + /** + * Selection of entity field for Version annotation. + */ + @Override + public boolean useColumnForOptimisticLock(TableIdentifier identifier, + String column) { + return column.matches(".*Version$"); + } + + @Override + public Map tableToMetaAttributes(TableIdentifier tableIdentifier) { + HashMap metaData = new HashMap<>(); + getClassCode(tableIdentifier, metaData); + getClassDesc(tableIdentifier, metaData); + return metaData; + } + + @Override + public Map columnToMetaAttributes(TableIdentifier identifier, String column) { + HashMap metaData = new HashMap<>(); + useInToString(identifier, column, metaData); + useInEquals(identifier, column, metaData); + return metaData; + } + + private void getClassCode(TableIdentifier tableIdentifier, HashMap metaData) { + String tableName = tableIdentifier.getName(); + String code = ""; + switch (tableName) { + case "dummy": + code = "\n" + + " public void specialProc() {\n" + + " }\n"; + break; + default: + } + if (code.length() > 0) { + MetaAttribute ma = new MetaAttribute("class-code"); + ma.addValue(code); + metaData.put("class-code", ma); + } + } + + private void getClassDesc(TableIdentifier tableIdentifier, HashMap metaData) { + String tableName = tableIdentifier.getName(); + String desc = ""; + switch (tableName) { + case "dummy": + desc = "Long description\n" + + "for javadoc\n" + + "of a particular entity.\n"; + break; + default: } + if (desc.length() > 0) { + MetaAttribute ma = new MetaAttribute("class-description"); + ma.addValue(desc); + metaData.put("class-description", ma); + } + } + + private void useInToString(TableIdentifier tableIdentifier, String column, HashMap metaData) { + String tableName = tableIdentifier.getName(); + String value= ""; + switch (tableName) { + case "dummy": + if( column.contentEquals("duData")) { + value = "true"; + } + break; + default: + } + if (value.length() > 0) { + MetaAttribute ma = new MetaAttribute("use-in-tostring"); + ma.addValue(value); + metaData.put("use-in-tostring", ma); + } + } + + private void useInEquals(TableIdentifier tableIdentifier, String column, HashMap metaData) { + String tableName = tableIdentifier.getName(); + String value= ""; + switch (tableName) { + case "dummy": + if( column.contentEquals("duData")) { + value = "true"; + } else if( column.contentEquals("duId")) { + value = "true"; + } + break; + default: + } + if (value.length() > 0) { + MetaAttribute ma = new MetaAttribute("use-in-equals"); + ma.addValue(value); + metaData.put("use-in-equals", ma); + } + } +} diff --git a/test/h2/src/test/resources/org/hibernate/tool/entitynaming/create.sql b/test/h2/src/test/resources/org/hibernate/tool/entitynaming/create.sql index 392e700d39..3918bccb2e 100644 --- a/test/h2/src/test/resources/org/hibernate/tool/entitynaming/create.sql +++ b/test/h2/src/test/resources/org/hibernate/tool/entitynaming/create.sql @@ -1,4 +1,4 @@ CREATE TABLE "orders" ( "ordId" INT generated by default as identity (start with 1) NOT NULL, "ordDesc" VARCHAR(10), "ordVersion" TINYINT DEFAULT 0 NOT NULL, PRIMARY KEY ("ordId")) CREATE TABLE "orderItems" ( "oiId" INT generated by default as identity (start with 1) NOT NULL, "oiOrdId" INT NOT NULL, "oiDesc" VARCHAR(10), "oiVersion" TINYINT DEFAULT 0 NOT NULL, PRIMARY KEY ("oiId")) ALTER TABLE "orderItems" ADD CONSTRAINT "orderorderitemfk" FOREIGN KEY ("oiOrdId") REFERENCES "orders" ("ordId") ON DELETE CASCADE ON UPDATE CASCADE -CREATE TABLE "dummy" ( "duId" INT generated by default as identity (start with 1) NOT NULL, "duVersion" TINYINT DEFAULT 0 NOT NULL, PRIMARY KEY ("duId")) \ No newline at end of file +CREATE TABLE "dummy" ( "duId" INT generated by default as identity (start with 1) NOT NULL, "duData" VARCHAR(10), "duVersion" TINYINT DEFAULT 0 NOT NULL, PRIMARY KEY ("duId")) \ No newline at end of file diff --git a/test/h2/src/test/resources/org/hibernate/tool/entitynaming/shape.hbm.xml b/test/h2/src/test/resources/org/hibernate/tool/entitynaming/shape.hbm.xml new file mode 100644 index 0000000000..e70af29860 --- /dev/null +++ b/test/h2/src/test/resources/org/hibernate/tool/entitynaming/shape.hbm.xml @@ -0,0 +1,15 @@ + + + + + + true + + + Test Field Description + + + + \ No newline at end of file