Starting with GraniteDS 2.2, Gas3 may also replicate validation annotations in order to use the Flex side validation framework (see Bean Validation (JSR-303))
and may also be configured to generate Long
, BigInteger
and BigDecimal
variable for their Java equivalents (see Big Number Implementations).
The generator (named GAS3) is implemented as an Eclipse plugin and as an Ant task. This Ant task is packaged as an Eclipse 3.2+ Ant plugin but may also be used outside of Eclipse for command line Ant calls. It is also included in the Maven plugin.
The next sections introduce both the Eclipse plugin and Ant task configurations and usages. You may also have a look at the Eclipse Plugins Installation section and at the Hello World revisited tutorial for a sample Eclipse Builder usage.
package org.test;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Welcome implements Serializable {
private static final long serialVersionUID = 1L;
@Id @GeneratedValue
private Integer id;
@Basic
private String name;
public Welcome() {
}
public Welcome(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/** * Generated by Gas3 v2.2.0 (Granite Data Services). * * NOTE: this file is only generated if it does not exist. You may safely put * your custom code here. */ package org.test { [Bindable] [RemoteClass(alias="org.test.Welcome")] public class Welcome extends WelcomeBase { } }
/** * Generated by Gas3 v2.2.0 (Granite Data Services). * * WARNING: DO NOT CHANGE THIS FILE. IT MAY BE OVERWRITTEN EACH TIME YOU USE * THE GENERATOR. INSTEAD, EDIT THE INHERITED CLASS (Welcome.as). */ package org.test { import flash.utils.IDataInput; import flash.utils.IDataOutput; import flash.utils.IExternalizable; import org.granite.collections.IPersistentCollection; import org.granite.meta; use namespace meta; [Bindable] public class WelcomeBase implements IExternalizable { private var __initialized:Boolean = true; private var __detachedState:String = null; private var _id:Number; private var _name:String; meta function isInitialized(name:String = null):Boolean { if (!name) return __initialized; var property:* = this[name]; return ( (!(property is Welcome) || (property as Welcome).meta::isInitialized()) && (!(property is IPersistentCollection) || (property as IPersistentCollection).isInitialized()) ); } public function get id():Number { return _id; } public function set name(value:String):void { _name = value; } public function get name():String { return _name; } public function readExternal(input:IDataInput):void { __initialized = input.readObject() as Boolean; __detachedState = input.readObject() as String; if (meta::isInitialized()) { _id = function(o:*):Number { return (o is Number ? o as Number : Number.NaN) } (input.readObject()); _name = input.readObject() as String; } else { _id = function(o:*):Number { return (o is Number ? o as Number : Number.NaN) } (input.readObject()); } } public function writeExternal(output:IDataOutput):void { output.writeObject(__initialized); output.writeObject(__detachedState); if (meta::isInitialized()) { output.writeObject(_id); output.writeObject(_name); } else { output.writeObject(_id); } } } }
Here are the details for (re)generation conditions:
Templates | Conditions for (re)generation |
---|---|
Dual templates (base + inherited) | The inherited AS3 class is generated only once if it does not exist. The AS3 base one is generated if it does not exist or if its timestamp (last modified time) is less than the Java class one |
Single template (enums or interfaces) | Like the base condition above, the AS3 class is (re)generated if it does not exist or if its timestamp is less than the Java class one |
Type of Java Class | Template | Base Template |
---|---|---|
Standard Java beans | bean.gsp | beanBase.gsp |
JPA entities: all classes annotated with @Entity and @MappedSuperclass | entity.gsp | entityBase.gsp |
Java enums | enum.gsp | (none) |
Java interfaces | interface.gsp | (none) |
Java services: all classes annotated with @RemoteDestination | remote.gsp | remoteBase.gsp |
Java events (CDI): all classes annotated with @TideEvent | bean.gsp | beanBase.gsp |
For each selected Java source folder you may also configure specific output directories:
Output Directory
: A directory relative to your project directory where generated ActionsScript3 classes are put.
Base Output Directory
: An optional directory relative to your project directory where so-called "Base"
generated ActionsScript 3 classes are put. If left empty, the output directory above is used for both "Base" and inherited
ActionScript 3 classes. See here for this distinction.
The next step in the wizard allows you to configure Java project dependencies. This is required when your Java classes make references to other classes declared in other Java projects. Clicking on the Add project button will open a dialog that lists all other open Java projects which have the GraniteDS nature:
The next step is classpath configuration. If you do not use any custom classes in the Options panel
you do not need to change anything here since the classpath is automatically configured with your current selected source folders.
In the following picture, the helloworld/bin
directory, where Eclipse compiles your Java source, is preselected,
as well as all libraries in the build path (eg. Java runtime jars, ejb3-persistence.jar
and
jboss-ejb3x.jar
):
The next panel lets you configure custom generation templates. Those templates are a mix of the JSP syntax and the . If you need specific code generation, you may write your own template, select one template in the displayed tree, and click on the Edit button:
In the above example, a class:
protocol is used because all standard templates are available in the classpath.
Alternatively, you may use the file:
protocol to load your template from the filesystem. These templates can be
specified either by using absolute paths (eg. file:/absolute/path/to/mytemplate.gsp
) or paths relative to your
current Eclipse project root directory (eg. path/to/mytemplate.gsp
).
Clicking the Use Tide button will configure Tide specific templates for entity beans. Use it if you are configuring the builder for a Tide project.
Clicking the Use LCDS button will configure LCDS specific templates for basic beans and entity beans, and
remove all templates for enum and remote destination services. It will also configure a LCDS specific AS3TypeFactory in the "Options"
panel (see picture below). The LCDS templates generate AS3 beans that can be either [Bindable] (default) or [Managed]. If you need [Managed]
beans, use the following parameter with your include pattern: [managed=true]
. For example, your include patterns could be:
If you want to use a single file generation policy (ie. no "Base" and inherited files), you can reconfigure the templates by using
class:org/granite/generator/template/lcdsStandaloneBean.gsp
as the only template, removing the base template.
WARNING: when switching from dual templates to a single one, be sure to remove and backup any previously generated files.
The last panel lets you configure various options:
Some explanations:
UID Property Name
: If you want your AS3 to implement mx.core.IUID
, you must tell the generator
the name of the Java field that contains this UID; use the same name in all your beans. Default is to search for field named uid
.
AS3TypeFactory Class
: You may use this option to configure a custom factory for special type support.
See Handling Custom Data Types for a detailed example. If you configure this,
you must add your class in the Classpath panel.
EntityFactory Class
: You may use this option to configure a custom factory for special entity support.
Setting this field to org.granite.generator.as3.BVEntityFactory
is useful if you want to use the GraniteDS validation framework.
See Bean Validation (JSR-303) for details.
RemoteDestinationFactory Class
: You may use this option to configure a custom factory for special service support.
You could for example implement a specific factory to analyze services for a particular framework.
"Show debug informations in console"
: If enabled, Gas3 will display more information during the generation process.
"Generate a Flex Builder configuration file"
: If enabled, Gas3 will generate a granite-flex-config.xml
that may be used in your compiler options. Useful to make sure that all generated AS3 beans will be included in your SWF. Note that
all AS3 files present in a Gas3 output directory (even those which are not generated) will be added to the config file.
"Use org.granite.math.Long"
: If enabled, Gas3 will generate AS3 Long
properties for
Java long
or Long
properties. See Big Number Implementations for details.
"Use org.granite.math.BigInteger"
: If enabled, Gas3 will generate AS3 BigInteger
properties for
Java BigInteger
properties. See Big Number Implementations for details.
"Use org.granite.math.BigDecimal"
: If enabled, Gas3 will generate AS3 BigDecimal
properties for
Java BigDecimal
properties. See Big Number Implementations for details.
When you have finished with the wizard, a first generation process will start and you should see something like this in the Eclipse console:
If you need to change your configuration later, you can right-click on your project, select the Properties item, and you'll be able to modify all GraniteDS Eclipse Builder configuration options: The panels are exactly the same as those of the wizard and the above documentation applies.
You can use the GraniteDS builder with Flex Builder provided that the three builders (Java, Granite, and Flex) are configured in the correct order. It will work without modification if you first create a Java project, add the Flex project nature, and then the GraniteDS nature; the builder will make sure that builders are setup in the correct order. Otherwise, you may have to change this order. Right-click on your project, select the Properties item, and select the Builders entry: The order (Java / Granite / Flex) in the above picture is the correct one.
When you have configured your project to use the GraniteDS Eclipse Builder, you may cancel any further generation processes by removing the nature:
Note that the hidden configuration file .granite
in your project is not removed by this action and you must delete it manually.
Otherwise, it will be reused whenever you add the nature again.
The main purpose of the builder is to generate AS3 files based on Java sources which are added or modified. When a Java source file is deleted or renamed, the builder will append to the name of all potentially AS3 generated files a suffix composed of a dot, the current system millisecond since epoch (1/1/1970) and an additionnal extension ".hid". The idea behind these renaming operations is to make sure that the Flex compilation will detect errors if these classes are used in the project (easing refactoring) and to ensure that any manual editing you have made in these classes is recoverable.
<taskdef name="gas3" classname="org.granite.generator.ant.AntJavaAs3Task"/>
$ ant -lib /gas3libs -f build.xml {target} ...
<target name="generate.as3">
<gas3 outputdir="as3">
<classpath>
<pathelement location="classes"/>
</classpath>
<fileset dir="classes">
<include name="com/myapp/entity/**/*.class"/>
</fileset>
</gas3>
</target>
For each JPA entity (say com.myapp.entity.MyEntity
), Gas3 will generate two AS3 beans:
org.entity.MyEntityBase.as
: This bean mainly contains fields, getters, setters, and IExternalizable
methods
(readExternal
/writeExternal
). This file is generated if it does not exist or if it is outdated.
org.entity.MyEntity.as
: This bean inherits from the "Base" one and is only generated if it does not exist.
<target name="generate.as3">
<gas3 outputdir="as3">
<classpath>
<pathelement location="lib/myclasses.jar"/>
</classpath>
<zipfileset src="lib/myclasses.jar">
<include name="com/myapp/entity/**/*.class"/>
</zipfileset>
</gas3>
</target>
<gas3 ...>
<classpath .../>
<fileset .../>
<translator
java="path.to.my.java.class"
as3="path.to.my.as3.class" />
<translator
java="path.to.my.java.class.special"
as3="otherpath.to.my.as3.class.special" />
...
</gas3>
Here is the complete list of Gas3 node attributes:
outputdir
and baseoutputdir
: We have already seen the outputdir
attribute
in basic usage. baseoutputdir
lets you define a custom output directory for your "Base" generated files.
The default is to use the same directory as specified by the outputdir
attribute.
uid
: If you want your AS3 to implement mx.core.IUID
, you must tell the generator
the name of the Java field that contains this UID. By default, Gas3 will search for a field named uid
.
You may change this by adding a uid="myUid"
attribute to the gas3
node.
If Gas3 does not find this uid
, it will be silently ignored.
tide
: Should we use a Tide specific template instead of the standard base template used for entity beans
(true
or false
, defaut is false
). Setting this attribute has no effect
if you use a custom entity base template. See below.
entitytemplate
and entitybasetemplate
: Templates used for classes annotated with
@Entity
or @MappedSuperclass
.
interfacetemplate
: Template used for Java interfaces.
beantemplate
and beanbasetemplate
: Templates used for other Java classes including @Embeddable
.
enumtemplate
: Template used for java.lang.Enum
types.
remotetemplate
and remotebasetemplate
: Templates used for server services (EJB3, Spring or Seam services).
as3typefactory
: You can plug your own org.granite.generator.as3.As3TypeFactory
implementation
in order to add support for custom types. For example, if you have configured a custom Joda time converter,
you may extend Gas3 accordingly for this custom type. Just extend the org.granite.generator.as3.DefaultAs3TypeFactory
class
and return org.granite.generator.as3.As3Type.DATE
when you encounter a Joda DateTime
instance.
See Handling Custom Data Types for a detailed example.
entityfactory
: Class used to introspect specific entity properties or metadata (default is
org.granite.generator.as3.DefaultEntityFactory
).
You may also use the built-in org.granite.generator.as3.BVEntityFactory
in order to replicate bean validation annotations
into your AS3 model Bean Validation (JSR-303).
remotedestinationfactory
: Class used to introspect specific service properties or metadata (default
is org.granite.generator.as3.DefaultRemoteDestinationFactory
).
transformer
: Class used to control the generation process (very advanced use).
externalizelong
: should we write AS3 Long
variables
(see Big Number Implementations). Default is false
.
externalizebiginteger
: should we write AS3 BigInteger
variables
(see Big Number Implementations). Default is false
.
externalizebigdecimal
: should we write AS3 BigDecimal
variables
(see Big Number Implementations). Default is false
.
For example:
<target name="generate.as3">
<gas3
outputdir="as3"
baseoutputdir="base_as3"
uid="myUidFieldName"
entitytemplate="/myEntityTemplate.gsp"
entitybasetemplate="/myEntityBaseTemplate.gsp"
interfacetemplate="/myInterfaceTemplate.gsp"
beantemplate="/myBeanTemplate.gsp"
beanbasetemplate="/myBeanBaseTemplate.gsp"
enumtemplate="/myEnumTemplate.gsp"
remotetemplate="/myRemoteTemplate.gsp"
remotebasetemplate="/myRemoteBaseTemplate.gsp"
tide="true"
as3typefactory="path.to.MyAs3TypeFactory"
entityfactory="path.to.MyEntityFactory"
remotedestinationfactory="path.to.MyRDFactory"
transformer="path.to.MyTransformer"
externalizelong="true"
externalizebiginteger="true"
externalizebigdecimal="true">
<classpath>
<pathelement location="classes"/>
</classpath>
<fileset dir="classes">
<include name="test/granite/ejb3/entity/**/*.class"/>
</fileset>
</gas3>
</target>
Note that when using a custom as3typefactory
, entityfactory
, remotedestinationfactory
or transformer
attribute, you must configure the classpath in order to make your custom classes available to the Gas3 engine;
either use the classpath attribute in the taskdef
declaration or in the gas3
call.
Gas3 templates are based on a specific implementation of . As such, all Groovy template documentation should apply.
The reason why the standard Groovy implementation was not used was the lack of comments support (<%-- ... --%>
)
and some formatting issues, especially with platform specific carriage returns. This may now be fixed but it was not at that time.
While the language itself is already documented on Groovy site, there are two specific bindings (ie. global variables used in Gas3 templates) that should be referenced.
Template execution is a two-phase process. First, the template is transformed to a standard Groovy script (mainly with expressions
like print(...));
second, the Groovy script is compiled and executed. Of course, the result of the first transformation
and the compiled script is cached, so further executions with the same template are much faster.
There are two bindings available in Gas3 templates:
Name | Type | Description |
---|---|---|
gVersion | String | Version number of the generator, e.g., "2.0.0" |
jClass | Implementation of the JavaType interface | An object describing the Java class for which the generator is writting an ActionScript 3 class |
fAttributes | Map<String, String> | A map which contains key-value pairs, as specified in include patterns (Eclipse builder only) |
JavaType implementations (passed as the jClass
parameter) can be of the following types:
Type | Description |
---|---|
JavaEntityBean |
A class defining a JPA entity bean (ie. a class annotated with a @Entity or with a
@MappedSuperclass persistence annotation)
|
JavaEnum |
A class defining a Java enum class
|
JavaInterface | A class defining a Java interface |
JavaRemoteDestination |
A class defining a remote service annotated with @RemoteDestination
|
JavaBean | A class defining all other Java classes |
The two bindings gVersion
and jClass
can be used in your templates as any
other Groovy script variables. For example:
// Generated by Gas3 v.${gVersion}. package ${jClass.as3Type.packageName} { public class ${jClass.as3Type.name} { ... } }
If you execute this template with Gas3 version 2.3.2 and a Java class named com.myapp.MyClass
, the output will be:
// Generated by Gas3 v.2.3.2. package com.myapp { public class MyClass { ... } }
If you plan to write custom templates, you should have a look at the standard GraniteDS templates and API documentation of the JavaType
implementations listed above.
Let's have a look to the standard GraniteDS template for Java interfaces. You may also see all templates :
<%--
GRANITE DATA SERVICES
Copyright (C) 2007-2008 ADEQUATE SYSTEMS SARL
This file is part of Granite Data Services.
Granite Data Services is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or (at your
option) any later version.
Granite Data Services 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 Lesser General Public License
for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, see <http://www.gnu.org/licenses/>.
--%><%
Set as3Imports = new TreeSet();
for (jImport in jClass.imports) {
if (jImport.as3Type.hasPackage() &&
jImport.as3Type.packageName != jClass.as3Type.packageName)
as3Imports.add(jImport.as3Type.qualifiedName);
}
%>/**
* Generated by Gas3 v${gVersion} (Granite Data Services).
*
* WARNING: DO NOT CHANGE THIS FILE. IT MAY BE OVERWRITTEN EACH TIME YOU USE
* THE GENERATOR. INSTEAD, EDIT THE INHERITED INTERFACE (${jClass.as3Type.name}.as).
*/
package ${jClass.as3Type.packageName} {<%
///////////////////////////////////////////////////////////////////////////
// Write Import Statements.
if (as3Imports.size() > 0) {%>
<%
}
for (as3Import in as3Imports) {%>
import ${as3Import};<%
}
///////////////////////////////////////////////////////////////////////////
// Write Interface Declaration.%>
public interface ${jClass.as3Type.name}Base<%
if (jClass.hasSuperInterfaces()) {
%> extends <%
boolean first = true;
for (jInterface in jClass.superInterfaces) {
if (first) {
first = false;
} else {
%>, <%
}
%>${jInterface.as3Type.name}<%
}
}
%> {<%
///////////////////////////////////////////////////////////////////////////
// Write Public Getter/Setter.
for (jProperty in jClass.properties) {
if (jProperty.readable || jProperty.writable) {%>
<%
if (jProperty.writable) {%>
function set ${jProperty.name}(value:${jProperty.as3Type.name}):void;<%
}
if (jProperty.readable) {%>
function get ${jProperty.name}():${jProperty.as3Type.name};<%
}
}
}%>
}
}
The code for this template is rather simple, but it can be very tricky to distinguish between JSP-like expressions, Groovy code, and outputted ActionScript 3 code.
The first block, enclosed with <%-- --%>
, is a template comment: it will be completely ignored at transformation
(Groovy template to Groovy script) time.
The second block, enclosed with <% %>
, is plain Groovy code and will be outputed as is at transformation time.
Its purpose is to collect and sort all references to other classes so we can later write ActionScript 3 import
statements.
Then, the ActionsScript 3 code template really begins with a comment (Gas3 version and warning) and is followed by a package and interface definition with superinterfaces, if any, and finally, by a loop over interface getters/setters. Note that comments like:
/////////////////////////////////////////////////////////////////////////// // Write Import Statements.
... are Groovy script comments. They will be in the Groovy script but you will not find them in the outputted ActionScript3 file.
After the first transformation (Groovy template to Groovy script), the rendered code will be as follows:
Set as3Imports = new TreeSet();
for (jImport in jClass.imports) {
if (jImport.as3Type.hasPackage() &&
jImport.as3Type.packageName != jClass.as3Type.packageName)
as3Imports.add(jImport.as3Type.qualifiedName);
}
print("/**\n");
print(" * Generated by Gas3 v${gVersion} (Granite Data Services).\n");
print(" *\n");
print(" * WARNING: DO NOT CHANGE THIS FILE. IT MAY BE OVERWRITTEN EACH TIME YOU USE\n");
print(" * THE GENERATOR. INSTEAD, EDIT THE INHERITED INTERFACE
(${jClass.as3Type.name}.as).\n");
print(" */\n");
print("\n");
print("package ${jClass.as3Type.packageName} {");
///////////////////////////////////////////////////////////////////////////
// Write Import Statements.
if (as3Imports.size() > 0) {
print("\n");
}
for (as3Import in as3Imports) {
print("\n");
print(" import ${as3Import};");
}
///////////////////////////////////////////////////////////////////////////
// Write Interface Declaration.
print("\n");
print("\n");
print(" public interface ${jClass.as3Type.name}Base");
if (jClass.hasSuperInterfaces()) {
print(" extends ");
boolean first = true;
for (jInterface in jClass.superInterfaces) {
if (first) {
first = false;
} else {
print(", ");
}
print("${jInterface.as3Type.name}");
}
}
print(" {");
///////////////////////////////////////////////////////////////////////////
// Write Public Getter/Setter.
for (jProperty in jClass.properties) {
if (jProperty.readable || jProperty.writable) {
print("\n");
if (jProperty.writable) {
print("\n");
print(" function set ${jProperty.name}(value:${jProperty.as3Type.name}):void;");
}
if (jProperty.readable) {
print("\n");
print(" function get ${jProperty.name}():${jProperty.as3Type.name};");
}
}
}
print("\n");
print(" }\n");
print("}");
</programlisting>
<para>
As you can notice, <literal>${...}</literal> expressions are resolved by the Groovy engine rather than the JSP-like engine.
It would have been possible to use expressions like <literal><%= ... %></literal>, that will result in a script where:
</para>
<programlisting role="JAVA">
print("package ${jClass.as3Type.packageName} {");
</programlisting>
<para>
.. would have been split into three lines:
</para>
<programlisting role="JAVA">
print("package ");
print(jClass.as3Type.packageName);
print(" {");
</programlisting>
<para>
This is just informative, as it does not change anything in the final result.
</para>
<para>
Then, for this Java source code:
</para>
<programlisting role="JAVA">
package com.myapp.entity.types;
public interface NamedEntity {
public String getFirstName();
public void setFirstName(String firstName);
public String getLastName();
public void setLastName(String lastName);
public String getFullName();
}
... you will get this output:
/** * Generated by Gas3 v2.2.0 (Granite Data Services). * * WARNING: DO NOT CHANGE THIS FILE. IT MAY BE OVERWRITTEN EACH TIME YOU USE * THE GENERATOR. INSTEAD, EDIT THE INHERITED INTERFACE (NamedEntity.as). */ package com.myapp.entity.types { public interface NamedEntityBase { function set firstName(value:String):void; function get firstName():String; function get fullName():String; function set lastName(value:String):void; function get lastName():String; } }
Because of the two transformation steps of the template (Groovy template to Groovy script source, then Groovy script source to pre-compiled Groovy script), there are two possible sources of error:
<%
expression.
now TreeSet()
; instead of new TreeSet();
However, since Groovy is an interpreted language, you may get some other errors at execution time:
jClass.neme
instead of jClass.name
.
Whenever these kinds of errors occur, you'll find comprehensive error log in your Shell or Eclipse console. Note that when the error occurs after the first transformation, the Groovy script is printed with line numbers, as well as the Groovy compiler message. It is easy to find the erroneous line in the printed Groovy script, but you have to figure out the corresponding line in the original template:
[gas3] Generating: /dev/workspace/graniteds_ejb3/as3/com/myapp/entity/types/NamedEntityBase.as (output file is outdated) [gas3] org.granite.generator.exception.TemplateCompilationException:Could not compile template: /interfaceBase.gsp [gas3] 1 | [gas3] 2 | Set as3Imports = now TreeSet(); [gas3] 3 | [gas3] 4 | for (jImport in jClass.imports) { [gas3] 5 | if (jImport.as3Type.hasPackage() && jImport.as3Type.packageName != jClass.as3Type.packageName) [gas3] 6 | as3Imports.add(jImport.as3Type.qualifiedName); [gas3] 7 | } [gas3] 8 | [gas3] 9 | [gas3] 10 | print("/**\n"); [gas3] 11 | print(" * Generated by Gas3 v${gVersion} (Granite Data Services).\n"); [gas3] 12 | print(" *\n"); [gas3] 13 | print(" * WARNING: DO NOT CHANGE THIS FILE. IT MAY BE OVERWRITTEN EACH TIME YOU USE\n"); [gas3] 14 | print(" * THE GENERATOR. INSTEAD, EDIT THE INHERITED INTERFACE (${jClass.as3Type.name}.as).\n"); [gas3] 15 | print(" */\n"); [gas3] 16 | print("\n"); [gas3] 17 | print("package ${jClass.as3Type.packageName} {"); [gas3] 18 | [gas3] 19 | [gas3] 20 | /////////////////////////////////////////////////////////////////////////// [gas3] 21 | // Write Import Statements. [gas3] 22 | [gas3] 23 | if (as3Imports.size() > 0) { [gas3] 24 | print("\n"); [gas3] 25 | [gas3] 26 | } [gas3] 27 | for (as3Import in as3Imports) { [gas3] 28 | print("\n"); [gas3] 29 | print(" import ${as3Import};"); [gas3] 30 | [gas3] 31 | } [gas3] 32 | [gas3] 33 | /////////////////////////////////////////////////////////////////////////// [gas3] 34 | // Write Interface Declaration. [gas3] 35 | print("\n"); [gas3] 36 | print("\n"); [gas3] 37 | print(" public interface ${jClass.as3Type.name}Base"); [gas3] 38 | [gas3] 39 | [gas3] 40 | if (jClass.hasSuperInterfaces()) { [gas3] 41 | [gas3] 42 | print(" extends "); [gas3] 43 | [gas3] 44 | boolean first = true; [gas3] 45 | for (jInterface in jClass.superInterfaces) { [gas3] 46 | if (first) { [gas3] 47 | first = false; [gas3] 48 | } else { [gas3] 49 | [gas3] 50 | print(", "); [gas3] 51 | [gas3] 52 | } [gas3] 53 | [gas3] 54 | print("${jInterface.as3Type.name}"); [gas3] 55 | [gas3] 56 | } [gas3] 57 | } [gas3] 58 | [gas3] 59 | [gas3] 60 | print(" {"); [gas3] 61 | [gas3] 62 | [gas3] 63 | /////////////////////////////////////////////////////////////////////////// [gas3] 64 | // Write Public Getter/Setter. [gas3] 65 | [gas3] 66 | for (jProperty in jClass.properties) { [gas3] 67 | [gas3] 68 | if (jProperty.readable || jProperty.writable) { [gas3] 69 | print("\n"); [gas3] 70 | [gas3] 71 | if (jProperty.writable) { [gas3] 72 | print("\n"); [gas3] 73 | print(" function set ${jProperty.name}(value:${jProperty.as3Type.name}):void;"); [gas3] 74 | [gas3] 75 | } [gas3] 76 | if (jProperty.readable) { [gas3] 77 | print("\n"); [gas3] 78 | print(" function get ${jProperty.name}():${jProperty.as3Type.name};"); [gas3] 79 | [gas3] 80 | } [gas3] 81 | } [gas3] 82 | } [gas3] 83 | print("\n"); [gas3] 84 | print(" }\n"); [gas3] 85 | print("}"); [gas3] [gas3] at org.granite.generator.gsp.GroovyTemplate.compile(GroovyTemplate.java:143) [gas3] at org.granite.generator.gsp.GroovyTemplate.execute(GroovyTemplate.java:157) [gas3] at org.granite.generator.as3.JavaAs3GroovyTransformer.generate(JavaAs3GroovyTransformer.java:119) [gas3] at org.granite.generator.as3.JavaAs3GroovyTransformer.generate(JavaAs3GroovyTransformer.java:1) [gas3] at org.granite.generator.Transformer.generate(Transformer.java:71) [gas3] at org.granite.generator.Generator.generate(Generator.java:83) [gas3] at org.granite.generator.ant.AntJavaAs3Task.execute(AntJavaAs3Task.java:327) [gas3] at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288) [gas3] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [gas3] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [gas3] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [gas3] at java.lang.reflect.Method.invoke(Method.java:597) [gas3] at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:105) [gas3] at org.apache.tools.ant.Task.perform(Task.java:348) [gas3] at org.apache.tools.ant.Target.execute(Target.java:357) [gas3] at org.apache.tools.ant.Target.performTasks(Target.java:385) [gas3] at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1329) [gas3] at org.apache.tools.ant.Project.executeTarget(Project.java:1298) [gas3] at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41) [gas3] at org.eclipse.ant.internal.ui.antsupport.EclipseDefaultExecutor.executeTargets(EclipseDefaultExecutor.java:32) [gas3] at org.apache.tools.ant.Project.executeTargets(Project.java:1181) [gas3] at org.eclipse.ant.internal.ui.antsupport.InternalAntRunner.run(InternalAntRunner.java:423) [gas3] at org.eclipse.ant.internal.ui.antsupport.InternalAntRunner.main(InternalAntRunner.java:137) [gas3] Caused by: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed,Script1.groovy: 2: expecting EOF, found 'TreeSet' @ line 2, column 26. [gas3] 1 error
The error at line 2, column 26 is:
[gas3] 2 | Set as3Imports = now TreeSet();
Finding the corresponding line in the original template should be straightforward.