/** * Copyright (c) 2009 Farata Systems http://www.faratasystems.com * * Licensed under The MIT License * Re-distributions of files must retain the above copyright notice. * * @license http://www.opensource.org/licenses/mit-license.php The MIT License * */ package com.farata.dto2extjs.annotations; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; /** * Is used to translate the Java class into a matching Ext JS model * <p> * <table class="innertable"> * <tr> * <th>Parameter</th><th>Type</th><th>Required</th><th>Description</th> * </tr> * <tr> * <td><code>value</code></td><td>String</td><td>Optional</td> * <td>A (fully qualified) name of the model (class). This is a default annotation parameter. * If you omit this parameter the (fully qualified) Java name is taken verbatim and transformed * according to the value of the APT option <code>-Acom.faratasystems.dto2extjs.class-name-transformer</code> (see below) * </td> * </tr> * <tr> * <td><code>kind</code></td><td>JSClassKind</td><td>Optional.</td> * <td>May be deprecate in the future. Do not use.</td> * </tr> * <tr> * <td><code>ignoreSuperClasses</code></td><td>Class<?>[]</td><td>Optional</td> * <td>Array of classes and interfaces in the Java inheritance chain that should be exempt from * translation. By design every ancestor class and every interface implemented by a class annotated as @JSClass must in turn * be annotated as @JSClass unless it is exempt via <code>ignoreSuperClasses</code>. Current version expects that developer * will exempt all interfaces. In the future interfaces will be added as mixins. * </td> * </tr> * </table> * * <p><b>Two Generated Classes per One Source</b> * </p> <p> Each Java source is translated into a pair of base model class and it's subclass: <li> a subclass model is reserved for manual changes and is regenerated only if you wipe out its file</i>; <li> a base model is regenerated on every change of the Java source; you should not modify it</li> </p> <p>Assume that you annotated Java class <code>com.farata.clear.dto.UserDTO</code> with <code>@JSClass</code>. Let's also say that the Ext JS application prefix is <code>MyApp</code> and you used APT paremeters (see below) to so that the output model name is <code>MyApp.model.clear.User</code>. Then DTO2ExtJS will make two models: <code>MyApp.model.clear.User</code> extending <code>Myapp.model.clear.generated._User</code>. Your application should make direct references only to <code>MyApp.model.clear.User</code>. * </p> * <p> * The annotated Java is below. Keep in mind that parameter <code>-Acom.faratasystems.dto2extjs.class-name-transformer</code> is set to <code>MyApp.model.$1$3<<^com.farata.((\w+\.)*)dto.(\w+)DTO$</code></code>: * <pre> * package clear.dto; * import com.farata.dto2extjs.annotations.JSClass; * @JSClass public class UserDTO { public String id; public Double salary; private Date dob; public Date getDob() { return dob; } public void setDob(Date value) { dob = value; } @JSOneToMany(foreignKey="userId", getter="getTickets") public List<TicketDTO> tickets; } * </pre> * </p> * <p> * First we show the base model - <code>MyApp.model.clear.generated._User</code>. Your * code should not contain direct references to it: * </p> * <pre>// Generated by DTO2EXTJS from MyApp.model.clear.dto.UserDTO.java on 2012-02-16T20:45:29-05:00 Ext.define('MyApp.model.clear.generated._User', { extend: 'Ext.data.Model', requires: [ 'Ext.data.Types', 'MyApp.model.clear.Ticket' ], fields: [ { name: 'id', type: Ext.data.Types.STRING, useNull: true }, { name: 'salary', type: Ext.data.Types.NUMBER, useNull: true }, { name: 'dob', type: Ext.data.Types.DATE, useNull: true } ], hasMany: [ { model: 'MyApp.model.clear.Ticket', name: 'getTickets', primaryKey:'id', foreignKey:'userId', autoLoad: true, storeType:'MyApp.store.clear.TicketStore' } ] } *</pre> * <p> * And here is subclass. This is the model to be used in your application, feel free to * modify it with computer properties, etc.: <pre>Ext.define('MyApp.model.clear.User, { extend: 'MyApp.model.clear.generated._User' }); </pre> </p> * <p> * Base model carries a field for every Java public variable or getter/setter pair which * has not been excluded by <a href="http://help.faratasystems.com/en_US/cleartoolkit/reference/java/extjs/com/farata/dto2extjs/annotations/JSIgnore.html">@JSIgnore</a> * annotation. * </p> * <p><b>Downloading and Using DTO2ExtJS Annotation Processor in Eclipse Plugin</b></p> * <p> * <li>Copy into your <code>eclipse/plugins folder the jar downloaded from * <a href="http://www.cleartoolkit.com/downloads/plugins/extjs/dto2extjs/com.farata.dto2extjs.asap_4.6.0.jar">http://www.cleartoolkit.com/downloads/plugins/extjs/dto2extjs/com.farata.dto2extjs.asap_4.6.0.jar</a></li> * <li>Copy into <code>WebContent/lib</code> folder of your Dynamic Web Project annotations jar downloaded from * <a href="http://www.cleartoolkit.com/downloads/plugins/extjs/dto2extjs/com.farata.dto2extjs.annotations.jar">http://www.cleartoolkit.com/downloads/plugins/extjs/dto2extjs/com.farata.dto2extjs.annotations.jar</a></li> * <li>Use APT parameters to control placement and naming of the generated models as described below in in sections <b>Placement of the Generated Models</b> and <b>Class Names of the Generated Models</b>. * </li> * </p> * <p><b>Placement of the Generated Models</b> * </p> * <p>Location of the generated models depends on two APT parameters: * <li><code>-Acom.faratasystems.dto2extjs.output</code> determines the root folder to place generated classes into. Expects path: absolute or relative to * Eclipse workspace, such as <code>c:/dev/MyProject/web</code> or <code>MyProject/WebContent</code></li> The <li><code>-Acom.faratasystems.dto2extjs.package-path-transformer</code> determines mapping between application namespace and root subfolder. If you assign AM:app the classes will be created in the <code>WebContent/app</code> and they will belong to <code>AM</code> namespace, starting with <code>Ext.define("AM...</code></li> </p> * <p><b>Class Names of the Generated Models</b> * </p> * <p>Fully qualified name of the generated model is determined in two steps: * <li>Unless you specify a JavaScript classname as the value or <code>@JSClass</code> it is taken verbatim from the Java source.</li> * <li>Value of the annotation parameter <code>-Acom.faratasystems.dto2extjs.class-name-transformer</code> * is used to transform it further: * <table class="innertable" width="100%"> * <tr> * <th>Setting</th><th>Java Class Name</th><th>Model Name</th> * </tr> * <tr> * <td><code>AM.model</code></td><td>clear.dto.UserDTO</td><td>AM.model.clear.dto.UserDTO</td> * </tr> * <tr> * <td><code>AM.model.$1$3<<^com.farata.((\w+\.)*)dto.(\w+)DTO$</code></td><td><code>com.farata.clear.dto.UserDTO</code></td><td><code>AM.model.clear.User</code></td> * </tr> * </table> * </li> * </p> * <p>To inspect/modify APT parameters in Eclipse go to <i>Project Properties->Java Compiler->Annotation Processing->Processor Options</i>. * </p> * <p><b>Downloading and Using Clear Components for Ext JS </b></p> * <p> * To take full advantage of @JSOneToMany you need to use <a href="http://www.cleartoolkit.com/dokuwiki/doku.php?id=clearwiki:40.clear_components_ext">Clear Components for ExtJS</a>. * In this case you get: * <li> automatic injection of reference to the parent record to all "many" associated records on load;</li> * <li> automatic batching of associated changes during <a href="http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.AbstractStore-method-sync">sync()</a> * of the parent store, i.e. "deep sync".</li> * </p> * <p> * To plug in Clear Components for Ext JS to your Ext JS MVC application copy the contents of ClearJS/src into the web root * of your application and make sure that the main application script starts similar to the following: <PRE>// app.js Ext.Loader.setConfig({ disableCaching: false, enabled: true, paths : { MyApp: 'app', Clear:'clear' } }); Ext.application({ name: 'MyApp', requires: ['Clear.override.ExtJSOverrider'], controllers: [ . . . ], autoCreateViewport: true }); </PRE> * </p> */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface JSClass { String value() default ""; JSClassKind kind() default JSClassKind.DEFAULT; Class<?>[] ignoreSuperclasses() default {}; }