I've continued to work on this issue. After some googling, I found an example from this forum on how to apply the scope-class attribute in the reveng file. See below.
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-reverse-engineering PUBLIC "-//Hibernate/Hibernate Reverse Engineering DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-reverse-engineering-3.0.dtd">
<hibernate-reverse-engineering>
<schema-selection match-catalog="mmerch"/>
<table-filter match-name="a_p_i_keys">
<!-- force abstract scope for generated classes -->
<meta attribute="scope-class">public abstract</meta>
</table-filter>
</hibernate-reverse-engineering>
That allowed me to create an abstract class. However, I wanted to prefix the classname with "Abstract", so I could use the base classname as my implementation class. So I wrote a reverse strategy to attempt to do this.
Code:
package tribal.tool;
import org.hibernate.cfg.reveng.DelegatingReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.ReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.TableIdentifier;
/**
*
* @author Ezward
*/
public class TribalDomainStrategy extends DelegatingReverseEngineeringStrategy
{
public TribalDomainStrategy(ReverseEngineeringStrategy delegate)
{
//
// remember our delegate. We will override some methods and
// allow delegate to handle the rest.
//
super(delegate);
}
/**
* return the class name given the table name
*
* Our strategy produces abstract classes, so prefix the standard
* name with 'Abstract'
*
* @param tableIdentifier name of the table
* @return name of the corresponding domain class
*/
@Override
public String tableToClassName(TableIdentifier tableIdentifier) {
String theClassName = super.tableToClassName(tableIdentifier);
//
// theClassName has form package.ClassName, so make it package.AbstractClassName
int index = theClassName.lastIndexOf('.');
return theClassName.substring(0, index) + "Abstract" + theClassName.substring(index + 1);
}
/*@Override
public Map tableToMetaAttributes(TableIdentifier tableIdentifier) {
Map theMetaAttributes = super.tableToMetaAttributes( tableIdentifier );
if( theMetaAttributes == null ) theMetaAttributes = new HashMap<String, MetaAttribute>();
//
// force abstract meta attribute unless there is already a class scope
//
if( ! theMetaAttributes.containsKey("scope-class"))
{
theMetaAttributes.put("scope-class", new MetaAttribute("public abstract"));
}
return theMetaAttributes;
}*/
}
Note that the tableToMetaAttributes() method is commented out; more on that later.
When I changed my build file to use this, it did not seem to get called. here is the relavent build section;
Code:
<!-- let ant know about the hibernatetool task -->
<taskdef name="hibernatetool"
classname="org.hibernate.tool.ant.HibernateToolTask" />
<!-- pre-compile task to regenrate domain classes and mapping files -->
<target name="-pre-compile">
</target>
<!-- generate the domain classes and mapping files -->
<target name="generate-domain-from-db"
description="run the hibernate task to generate domain classes and mapping files" >
<!-- run the hibernate task to generate domain classes and mapping files -->
<hibernatetool destdir="src">
<!-- classpath to hibernate mappings and reveng files -->
<classpath>
<path location="src/tribal/domain"/>
</classpath>
<!-- we are using jdbc to read configuration from database -->
<jdbcconfiguration
propertyfile="src/tribal/domain/hibernate.properties"
revengfile="src/tribal/domain/hibernate.reveng.xml"
packagename="tribal.domain"
detectmanytomany="true"
reversestrategy="tribal.tool.TribalDomainStrategy"
/>
<!-- order of generators is important -->
<!-- we are generating the hbm.xml files -->
<hbm2hbmxml destdir="src" />
<!-- we are generating the java files -->
<hbm2java jdk5="true" />
<!-- we are generating the hibernate config file -->
<hbm2cfgxml destdir="src/tribal/domain" />
</hibernatetool>
</target>
When I took out the meta tag from the table-filter in the reveng file, then the strategy seemed to get called, but it created an error. here is the updated reveng file, followed by the resulting error when the build is attempted:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-reverse-engineering PUBLIC "-//Hibernate/Hibernate Reverse Engineering DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-reverse-engineering-3.0.dtd">
<hibernate-reverse-engineering>
<schema-selection match-catalog="mmerch"/>
<table-filter match-name="a_p_i_keys">
</table-filter>
</hibernate-reverse-engineering>
The errors:
Code:
generate-domain-from-db:
Executing Hibernate Tool with a JDBC Configuration (for reverse engineering)
1. task: hbm2hbmxml (Generates a set of hbm.xml files)
An exception occurred while running exporter #2:hbm2hbmxml (Generates a set of hbm.xml files)
To get the full stack trace run ant with -verbose
org.hibernate.tool.hbm2x.ExporterException: Error while processing Entity: Abstracttribal.domain.APIKeys with template hbm/hibernate-mapping.hbm.ftl
freemarker.core.InvalidReferenceException: Expression metaattributable.getMetaAttributes().get(key).values is undefined on line 3, column 9 in hbm/meta.hbm.ftl.
org.hibernate.tool.hbm2x.ExporterException: Error while processing Entity: Abstracttribal.domain.APIKeys with template hbm/hibernate-mapping.hbm.ftl
at org.hibernate.tool.hbm2x.TemplateHelper.processTemplate(TemplateHelper.java:261)
at org.hibernate.tool.hbm2x.TemplateProducer.produceToString(TemplateProducer.java:67)
at org.hibernate.tool.hbm2x.TemplateProducer.produce(TemplateProducer.java:28)
at org.hibernate.tool.hbm2x.TemplateProducer.produce(TemplateProducer.java:103)
at org.hibernate.tool.hbm2x.GenericExporter.exportPOJO(GenericExporter.java:148)
at org.hibernate.tool.hbm2x.GenericExporter.exportPersistentClass(GenericExporter.java:137)
at org.hibernate.tool.hbm2x.GenericExporter$2.process(GenericExporter.java:43)
... snip ...
So, if I have the meta tag in the reveng file, it generates without error and I get an abstract class, but the name is not changed. If I remove the meta tag, I get the error. Any clues?
Note that the error refers to the entity "Abstracttribal.domain.APIKeys". I'm not sure what is up there. It seems to have prefixed the class with "Abstract", so that is why it can't process it.
Back to the tableToMetaAttributes() that is commented out. I thought this was the problem, so i commented it out. I'm not sure if I am allocating the correct kind of map. It would be great if someone could point me to a good example of implementing this method. I could use this rather than add the meta mapping to every file in the reveng file. Also, it seems like I may have to add this if I don't have it in the reveng file (is that the error?)
Thank you for your help.
[/code]