2012-08-10 6 views
4

Je travaille sur un projet qui aura plusieurs classes Java très similaires et que je voudrais générer à partir de fichiers XML. Ce que je voudrais être en mesure de faire est de changer le processus de construction Eclipse pour faire quelque chose comme ceci:Génération de code Java à partir de XML dans Eclipse

  • Compile le générateur de code
  • Exécutez le générateur de code, la conversion du XML en Java
  • compiler le reste du projet

Je pourrais le faire tous manuellement mais je préférerais pouvoir faire en sorte qu'Eclipse fasse tout pour moi.

Exemple

Je veux être en mesure de prendre un fichier XML source qui ressemble à ceci:

<command-list> 
    <command name="DATE" /> 
    <command name="GROUP"> 
     <capability "READER" /> 
     <argument "groupname" /> 
    </command> 
    <command name="ARTICLE"> 
     <capability "READER" /> 
     <argument "message-id" optional="true" /> 
    </command> 
</command-list> 

et ai, il me donner quelque chose de semblable à ce qui suit (dans des fichiers séparés selon le cas):

public class Date extends Command { 
    public ResponseCode execute() { 
     Server srv = getServer(); 
     srv.send("DATE"); 
     return srv.getResponse(); 
    } 
} 

public class Group extends Command { 
    public ResponseCode execute() { 
     Server srv = getServer(); 
     if (srv.hasCapability(Capabilities.READER) == false) { 
      Log.debug("Attempting non-available capability: READER"); 
     } 
     String groupname = getArgument("groupname"); 
     if (groupname == null) { 
      throw new InvalidArgumentException("Require groupname"); 
     } 
     String command = "GROUP"; 
     if (groupname != null) command += " " + groupname; 
     srv.send(command); 
     return srv.getResponse(); 
    } 
} 

public class Article extends Command { 
    public ResponseCode execute() { 
     Server srv = getServer(); 
     if (srv.hasCapability(Capabilities.READER) == false) { 
      Log.debug("Attempting non-available capability: READER"); 
     } 
     String messageId = getArgument("messageId"); 
     String command = "ARTICLE"; 
     if (messageId != null) command += " " + messageId; 
     srv.send(command); 
     return srv.getResponse(); 
    } 
} 
+1

Pourquoi ne pas vous suffit d'écrire un script fichier batch/shell pour faire tout cela pour vous? Une ligne deux arguments -> Fait! Je pose cette question parce que personnellement je ne sais pas comment vous le feriez (si possible) dans Eclipse, et il semble que vous allez pour la facilité d'utilisation ici. – thatidiotguy

+0

Je veux que cela fasse partie du processus de construction, de sorte que si je change mon template ou mon XML il régénérera –

+0

@thatidiotguy vous pouvez intégrer des scripts ant dans le processus de construction dans le cadre des propriétés du projet, sous "Builders". Je ne sais pas s'il existe un support de script batch/shell, mais je n'ai pas non plus regardé. –

Répondre

3

Ceci est exactement ce que le composant JET dans le modèle de projet Texte (M2T) a été fait pour. En fait, vous pouvez même créer le projet, .classpath et tous les autres fichiers dont vous avez besoin avec JET.

Les modèles de jet sont les suivants. Notez que ces modèles doivent être nommés exactement comme indiqué.

/templates/main.jet

<%@taglib prefix="ws" id="org.eclipse.jet.workspaceTags" %> 
<%-- Main entry point for com.lacqui.command.xform --%> 

<%-- 
    Let c:iterate tags set the XPath context object. 
    For 100% compatibility with JET 0.9.x or earlier, remove this statement 
--%> 
<c:setVariable var="org.eclipse.jet.taglib.control.iterateSetsContext" select="true()"/> 

    <c:setVariable select="/command-list" var="command-list" /> 

    --- traverse input model, performing calculations and storing 
    --- the results as model annotations via c:set tag 

    <c:set select="$command-list" name="project">com.lacqui.commands</c:set> 
    <c:set select="$command-list" name="commandPkg">com.lacqui.commands</c:set> 
    <c:set select="$command-list" name="commandDir"><c:get select="translate($command-list/@commandPkg,'.','/')" /></c:set> 

    <c:iterate select="$command-list/command" var="command" > 

      - Derive the class name from the name of the command 

     <c:set select="$command" name="classname"><c:get select="camelCase($command/@name)" />Command</c:set> 

     <c:iterate select="$command/argument" var="argument"> 

      <c:if test="not($argument/@optional)"> 
       <c:set select="$argument" name="optional">false</c:set> 
      </c:if> 

     </c:iterate> 

    </c:iterate> 

    --- traverse annotated model, performing text generation actions 
    --- such as ws:file, ws:folder and ws:project 

    <ws:project name="{$command-list/@project}" /> 
    <ws:file template="templates/project.jet" path="{$command-list/@project}/.project" /> 
    <ws:file template="templates/classpath.jet" path="{$command-list/@project}/.classpath"/> 

    <c:iterate select="$command-list/command" var="command" > 

     <ws:file template="templates/class.jet" path="{$command-list/@project}/src/{$command-list/@commandDir}/{$command/@classname}.java" replace="true"/> 

    </c:iterate> 

/templates/classpath.jet

<?xml version="1.0" encoding="UTF-8"?> 
<classpath> 
    <classpathentry kind="src" path="src"/> 
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> 
    <classpathentry kind="output" path="bin"/> 
</classpath> 

/templates/project.jet

<?xml version="1.0" encoding="UTF-8"?> 
<projectDescription> 
    <name><c:get select="$command-list/@project" /></name> 
    <comment></comment> 
    <projects> 
    </projects> 
    <buildSpec> 
     <buildCommand> 
      <name>org.eclipse.jdt.core.javabuilder</name> 
      <arguments> 
      </arguments> 
     </buildCommand> 
    </buildSpec> 
    <natures> 
     <nature>org.eclipse.jdt.core.javanature</nature> 
    </natures> 
</projectDescription> 

/templates/class.jet

package <c:get select="$command-list/@commandPkg" />; 

public class <c:get select="$command/@classname" /> extends Command { 
    public ResponseCode execute() { 
     Server srv = getServer(); 
<c:iterate select="$command/capability" var="capability"> 

     if (srv.hasCapability(Capabilities.<c:get select="$capability/@name"/>) == false) { 
      Log.debug("Attempting non-available capability: <c:get select="$capability/@name"/>"); 
     } 
</c:iterate>   
<c:iterate select="$command/argument" var="argument"> 

     String <c:get select="$argument/@name"/> = getArgument("<c:get select="$argument/@name"/>"); 
<c:if test="$argument/@optional = 'false'" > 
     if (<c:get select="$argument/@name"/> == null) { 
      throw new InvalidArgumentException("Require <c:get select="$argument/@name"/>"); 
     } 
</c:if> 
</c:iterate>   

     String command = "GROUP"; 
<c:iterate select="$command/argument" var="argument"> 
     if (<c:get select="$argument/@name"/> != null) command += " -<c:get select="$argument/@name"/> " + <c:get select="$argument/@name"/>; 
</c:iterate>  

     srv.send(command); 
     return srv.getResponse(); 
    } 
} 

et en utilisant ce modèle:

<command-list> 
    <command name="DATE" /> 
    <command name="GROUP"> 
     <capability name="LOGGER" /> 
     <capability name="AUTHENTICATOR" /> 
     <argument name="groupname" /> 
    </command> 
    <command name="ARTICLE"> 
     <capability name="READER" /> 
     <argument name="article-id" optional="false" /> 
     <argument name="message-id" optional="true" /> 
    </command> 
</command-list> 

donne un projet java complet nommé com.lacqui.commands contenant trois fichiers java:

package com.lacqui.commands; 

public class ArticleCommand extends Command { 
    public ResponseCode execute() { 
     Server srv = getServer(); 

     if (srv.hasCapability(Capabilities.READER) == false) { 
      Log.debug("Attempting non-available capability: READER"); 
     } 

     String article-id = getArgument("article-id"); 
     if (article-id == null) { 
      throw new InvalidArgumentException("Require article-id"); 
     } 

     String message-id = getArgument("message-id"); 

     String command = "GROUP"; 
     if (article-id != null) command += " -article-id " + article-id; 
     if (message-id != null) command += " -message-id " + message-id; 

     srv.send(command); 
     return srv.getResponse(); 
    } 
} 

et ce:

package com.lacqui.commands; 

public class GroupCommand extends Command { 
    public ResponseCode execute() { 
     Server srv = getServer(); 

     if (srv.hasCapability(Capabilities.LOGGER) == false) { 
      Log.debug("Attempting non-available capability: LOGGER"); 
     } 

     if (srv.hasCapability(Capabilities.AUTHENTICATOR) == false) { 
      Log.debug("Attempting non-available capability: AUTHENTICATOR"); 
     } 

     String groupname = getArgument("groupname"); 
     if (groupname == null) { 
      throw new InvalidArgumentException("Require groupname"); 
     } 

     String command = "GROUP"; 
     if (groupname != null) command += " -groupname " + groupname; 

     srv.send(command); 
     return srv.getResponse(); 
    } 
} 
+0

Je n'essaie pas d'utiliser XML comme format de données d'exécution - je l'utilise pour simplifier la génération de mon fichier source. –

+0

JET est un outil de développement qui génère du code, des fichiers JSP, HTML, des fichiers de propriétés, des ressources point Eclipse, etc. dans des projets Eclipse (éventuellement après la création et la configuration de ces projets). Cette génération de ressources est pilotée par un modèle, généralement XML mais peut être n'importe quel format, et ce modèle n'est pas utilisé du tout au moment de l'exécution. Donc JET est vraiment une bonne approche pour vous ici. Publiez un exemple de classe dans votre question et je peux publier un modèle que vous pourriez utiliser pour générer cette classe. –

+0

J'ai quelques exemples dans ma question. –

0

Vous pourriez Je veux jeter un coup d'œil à JaxB. Lars Vogel a fait un simple tutoriel si vous voulez jeter un coup d'œil à celui-ci.
JAXB Tutorial

Voici également un test de référence de xml unmarshaling.
XML unmarshalling benchmark in Java: JAXB vs STax vs Woodstox

+0

Je n'essaie pas d'utiliser XML comme format de données d'exécution - je l'utilise pour simplifier la génération de mon fichier source. –

-1

Ce que vous voulez utiliser est l'option 'Builders' dans vos propriétés de projet. Ici vous pouvez configurer votre projet pour compiler et exécuter votre générateur de code en utilisant un script 'ant' (d'autres types de builders sont également disponibles) avant que le reste de votre projet ne soit compilé.

Je pense que ces articles expliquent mieux:

http://www.eclipsezone.com/eclipse/forums/t65486.html

http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.platform.doc.user%2FgettingStarted%2Fqs-93_project_builder.htm

+0

Puis-je avoir une raison pour la downvote? –

Questions connexes