It is very easy to add a new code generator into castor. The code
for registering and starting a code generator is easy to understand see
TemplateJClassPrinter.java and TemplateJClassPrinterFactory.java in:
castor-1.3\codegen\src\main\java\org\exolab\castor\builder\printing.
The velocity example is nice in that it is very concise - the main
thing one has to understand is the representation of an XSD
in castor-1.3\codegen\src\main\java\org\exolab\javasource (e.g.
JClass.java).
downside with velocity is that I have never seen quite so many #s :-)
James
----- Original Message -----
From: "Alex Thieme" <[email protected]>
To: <[email protected]>
Sent: Thursday, September 10, 2009 3:32 PM
Subject: Re: [castor-user] How to generate other types of code, besides
POJOs
Thanks for the pointers. In fact, what James describes in the end of his
email, is no unlike what I will need. That is, the company I am at has a
homegrown code generator (not using castor or velocity) of any arbitrary
code starting from a Manifest.xsd, XSDs within that and Java code (not
velocity templates) which are called from Maven; but, I'd just as soon
not have to maintain that, which is why I'm looking for alternatives.
Alex
On Sep 10, 2009, at 5:16 AM, James Cowan wrote:
Hi Werner
I made one change to library vm to add a macro called annotate:
#macro (annotate $comment $shift)
#if($comment && $comment.getComment().indexOf("@")>=0)
${shift} ${comment.getComment().substring($comment.getComment
().indexOf("@"))}
#end
#end
This macro looks inside a comment (JClass holds the xsd:annotation in
this property). If there
is an @ character it spits out the java annotation otherwise not.
In main.vm I made a few changes to use the annotate macro:
In class enum where there will typically be a @Entity or
@MappedSuperclass annotation.
## CLASS/ENUM DEFINITION *#
#javadoc( $jClass.getJDocComment() "" )
#annotate( $jClass.getJDocComment() " " ) ## THIS WILL TYPICALLY copy
a JPA @Entity annotation
#foreach( $annotation in $jClass.getAnnotations() )
#annotation( $annotation " ")
#end
#if( $helper.isEnum($jClass) )
#enumDefinition( $jClass "") { ##
#{else}
#classDefinition( $jClass "") { ##
#{end}
and in the methods to generate other annotations like @ID or @ManyToOne
etc:
## METHODS *#
#if( $jClass.getMethodCount() > 0)
#foreach( $method in $jClass.getMethods() )
#javadoc( $method.getJDocComment() " " )
#annotate( $method.getJDocComment() " " )
#foreach( $annotation in $method.getAnnotations() )
#annotation( $annotation " ")
#end
#method( $method " " )
#end
#end
Here is a sample bit of xsd that contains use of annotations:
<!-- *************************************** -->
<!-- User -->
<complexType name="User">
<annotation>
<documentation>User Entity @Entity</documentation>
</annotation>
<sequence>
</sequence>
<attribute name="email" type="string" default="">
<annotation>
<documentation>@Column(name="email", nullable = false)</ documentation>
</annotation>
</attribute>
<attribute name="userId" type="long" >
<annotation>
<documentation>
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "userId", unique = true, nullable = false)
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string" default="">
<annotation>
<documentation>@Column(name="name", nullable = false)</ documentation>
</annotation>
</attribute>
<attribute name="password" type="string" default="">
<annotation>
<documentation>@Column(name="password", nullable = false)</
documentation>
</annotation>
</attribute>
<attribute name="role" type="string" default="">
<annotation>
<documentation>@Column(name="role", nullable = false)</ documentation>
</annotation>
</attribute>
</complexType>
There are somethings things that I would like to improve. For example I
would prefer the annotations
to appear in an appinfo rather than documentation sub element of
annotation. I was going to take a look at what is needed in JClass.java
to support this.
The other hack that I had to implement was to output import
javax.persistence.*; - not sure how to generate this neatly from an xsd.
I have attached the vm files.
I use xsd to model domains (often without xml marshalling) and the
schema compiler saves me loads ot time.
Generating the model into different coding environments other than
standard java would be very useful. It would be nice if one could get
the xsd compiler to generate java classes that can be compiled with GWT
compiler without switching off xml marshalling; I have posted on
the list about these problems before. I am also planning to generate
actionscript3 code so that I can use the same xsd for flex/java
projects.
Being able to generate json or google protobuf marshalling would also be
very useful. Manipulating xml can be hard work in jscript - json is much
easier.
James
----- Original Message ----- From: "Werner Guttmann"
<[email protected]
>
To: <[email protected]>
Sent: Thursday, September 10, 2009 9:21 AM
Subject: Re: [castor-user] How to generate other types of code, besides
POJOs
Hi James,
I think you are right with your assessment. If the
TemplateJClassPrinter
loads from the classpath, the approach highlighted should be fine.
Werner
PS I wonder, though, whether you'd be willing to allow us having a look
at your extensions, to get an idea whether what you have done could and
should be integrated with Castor.
James Cowan wrote:
Hi Alex
Thanks for the answers. Perhaps this is what you mean by not having
any
"entry points"; but, is there any way to change the velocity
templates
that are in use?
Not currently. But it should not be too hard to have this
configurable.
Why not raise a feature request, and we will look into to.
It is possible to take a copy of the the 2 velocity templates
library.vm
and main.vm and
modify them. TemplateJClassPrinter.java looks for the velocity
templates
on the classpath here:
public static final String TEMPLATE_PACKAGE =
"/org/exolab/castor/builder/printing/templates/";
I modified the velocity templates so that JPA annotations added to xsd
annotations can be
generated in the output.
The only thing you need to do apart from telling the source generator
to
use velocity is to
put your templates in the classpath before the default ones.
In a maven environment put your modified velocity templates in
src\main\resources\org\exolab\castor\builder\printing\templates.
The castor source generator shoudl pick these up instead of the ones
embedded in the jar.
James
----- Original Message ----- From: "Alex Thieme" <[email protected]>
To: <[email protected]>
Sent: Wednesday, September 09, 2009 1:20 PM
Subject: Re: [castor-user] How to generate other types of code,
besides
POJOs
Unless instructed otherwise, I will create an enhancement through
JIRA
(http://jira.codehaus.org/browse/CASTOR). Any particular "component"
in mind? I'm thinking either Unknown, Core or General.
Also, and I guess this is to be understood if you don't want to give
pointers to competitors, did you have any thoughts on my last point
about other projects that provide this out of the box?
Alex
On Sep 9, 2009, at 6:12 AM, Werner Guttmann wrote:
Hi Alex,
Alex Thieme wrote:
Werner,
Thanks for the answers. Perhaps this is what you mean by not having
any
"entry points"; but, is there any way to change the velocity
templates
that are in use?
Not currently. But it should not be too hard to have this
configurable.
Why not raise a feature request, and we will look into to.
Cheers
Werner
I'm guessing not. And, with that said, do you know of
any well maintain open source projects that might be applicable
(ones
that you think are worthy)?
Alex
On Sep 6, 2009, at 3:30 PM, Werner Guttmann wrote:
Hi Alex,
that is a hard question to answer, as the answer i snot a simpe
yes
and/or no. But let me try .....
Regards
Werner
Alex Thieme wrote:
I know that castor can generate Java classes (what I would
consider
POJOs); but, is there an option to generate a file or files from
any
arbitrary template and XSD? I'll provide examples in case my
explanation
is not clear.
In the example below, there's an Adjustment.xsd, containing three
attributes. The generator writes out a class header (package and
import
statements of my choosing), then writes a statement representing
the
"singleton" instance. Then, a "format" method is generated.
Again,
AdjustmentNativeFormatter (below) is the result of applying the
Adjustment.xsd to a generator, say "FormatterGenerator" because
this
generator generates "Formatter" objects.
What I can't find in castor is the piece of code that I could
write,
either in XML or more likely Java code, which has access to the
metadata
in the XSD (the root elements, nested elements, attributes,
whether
something is a simple type or complex type, XML Schema type,
etc). From
that, I would write code to iterate over the elements and
attributes,
write out statements that will be written to a file on disk.
It's not as easy as you think. Internally, Castor converts your
XML
schemas and the types/elements defined therein into a set of in-
memory
Java objects that represent your XML schema definitions.
It's those object instances that classes such as Source-/
MemberFactory
will use to traverse these schema objects and build J* instances
from;
eventually, the Castor XML code generator will serialize those J*
instances (such as JClass, JField, .....) to files on your file
system.
In other words, most of what you need is in place; but on the
other
hand, none of these classes expose any entry points fro you to use
to
implement your own code fragments.
Does this answer your question ?
As you can see, this is different from generating simply POJOs.
I'd like
to be able to generate any arbitrary code from XSD.
I do appreciate your needs here, but Castor's code generator will
generate POJOs only and the corresponding descriptor classes for
XML
data binding and JDO persistence.
And, dare I ask, if castor does not have this feature, can you
recommend
other open source projects that do have this feature?
Thanks in advance,
Alex
Generated code:
package com.athieme.KToW.formatters;
import org.apache.log4j.Logger;
import java.math.BigInteger;
import java.util.Calendar;
import com.athieme.AbstractFormatter;
import com.athieme.interfaces.IAdjustment;
public class AdjustmentFormatter extends
AbstractFormatter<IAdjustment> {
public static final AdjustmentFormatter singleton = new
AdjustmentFormatter();
public String format(final IAdjustment obj) {
final StringBuffer sb = new StringBuffer();
sb.append(obj.company());
sb.append(obj.userId());
sb.append(obj.dateStamp());
sb.append(obj.timeStamp());
return sb.toString();
}
}
XSD:
<?xml version="1.0" encoding="iso-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fd="http://athieme/FieldDef"
xmlns:common="http://athieme/Common"
targetNamespace="http://athieme/KToW"
elementFormDefault="qualified">
<xs:import namespace="http://athieme/FieldDef"
schemaLocation="../
FieldDef.xsd"/>
<xs:import namespace="http://athieme/Common" schemaLocation="../
Common.xsd"/>
<xs:complexType name="Adjustment">
<xs:attribute name="company"
type="fd:fixedString10"
fd:externalName="LDCO"
fd:internalName="Company"/>
<xs:attribute name="userId"
type="fd:fixedString10"
fd:externalName="PLUSER"
fd:internalName="user_id"/>
<xs:attribute name="dateStamp"
type="fd:fixedInt8"
fd:externalName="DateStamp"
fd:internalName="DateStamp"
fd:fieldDefType="int"/>
</xs:complexType>
</xs:schema>
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
< main.vm
>
< library.vm
>---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email