使用JET生成代码:缩进代码

时间:2011-10-14 01:47:41

标签: java eclipse code-generation eclipse-m2t-jet

我正在尝试执行以下操作:

  

编写一个接收类型为Class的对象的JET模板   论点。该对象应代表Java接口。模板   生成一个实现接口的类,即提供方法   对于它定义的所有方法签名。生成的名称   class应该是XImplementation,其中X是参数的名称   接口。生成的类中的方法不执行任何操作或仅执行操作   返回常量值:0表示int和double,false表示布尔值,和   null用于引用类型。您无需考虑任何其他回报   类型。例如。对于以下接口A,类实现会   生成:

interface A {  
    void m1(int x, int y);  
    int m2(Object a);  
    Object m3();  
}  

class AImplementation implements A {  
    public void m1(int p1, int p2) { }  
    public int m2(Object p1) { return 0; }  
    public Object m3() { return null; }  
}  
     

提示:类型的非限定(简单)名称   可以通过使用getSimpleName()方法获取   对应的Class对象。

我已经阅读了eclipse.org上有关JET的教程,但我仍然无法理解我需要做什么。

当我制作.txtjet文件进行翻译时,我是否尝试制作它以便.txtjet文件的实现使用我想在generate方法中生成的代码写入一个巨大的字符串?这是正确的概念吗?

如果是这种情况,我就遇到了一个特殊方面的问题。这是我到目前为止提出的JET模板:

<%@ jet imports="java.lang.reflect.*" class="Q2Generator" %>
<%Object o = (Object) argument;%>
<%Class c = o.getClass();%>

public class <%=c.getName()%>Implementation implements <%=c.getName()%> {
<%for (Method m : c.getDeclaredMethods()) {%>
<%  Class type = m.getReturnType();%>
<%  if (!type.isPrimitive()) {%>
public <%=type.getSimpleName()%> <%=m.getName()%> { return null; } // this line is the problem
<%  }%>
<%}%>       
}

此模板在generate方法中生成以下代码:

  public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
  protected final String TEXT_1 = NL + "public class ";
  protected final String TEXT_2 = "Implementation implements ";
  protected final String TEXT_3 = " {";
  protected final String TEXT_4 = NL + "public ";
  protected final String TEXT_5 = " ";
  protected final String TEXT_6 = " { return null; }";
  protected final String TEXT_7 = NL + "\t\t" + NL + "}";
  protected final String TEXT_8 = NL;

  public String generate(Object argument)
  {
    final StringBuffer stringBuffer = new StringBuffer();
    Object o = (Object) argument;
    Class c = o.getClass();
    stringBuffer.append(TEXT_1);
    stringBuffer.append(c.getName());
    stringBuffer.append(TEXT_2);
    stringBuffer.append(c.getName());
    stringBuffer.append(TEXT_3);
    for (Method m : c.getDeclaredMethods()) {
        Class type = m.getReturnType();
        if (!type.isPrimitive()) {
    stringBuffer.append(TEXT_4);
    stringBuffer.append(type.getSimpleName());
    stringBuffer.append(TEXT_5);
    stringBuffer.append(m.getName());
    stringBuffer.append(TEXT_6);
        }
    }
    stringBuffer.append(TEXT_7);
    stringBuffer.append(TEXT_8);
    return stringBuffer.toString();
  }

有没有办法在if语句中缩进stringBuffer.append()行?并且String是正确的方式来完成这项任务吗?

感谢。

1 个答案:

答案 0 :(得分:0)

我会使用更新的JET2语法。您应该能够使用New创建一个新的JET转换 - &gt;其他

至于在高级别发生的事情,你将拥有一个名为main.jet的模板,它将充当控制器。它本身不会创建任何文本内容,但会管理项目,文件夹和文件的生成。

我知道您希望使用类对象作为输入,但我建议您构建模板以使用XML文件作为输入。像这样:

<root>
    <object name="A">
        <method name="m1" returns="void">
            <arg name="x" type="int" />
            <arg name="y" type="int" />
        </method>
        <method name="m2" returns="int">
            <arg name="a" type="Object" />
        </method>
        <method name="m3" returns="Object">
        </method>
    </object>
</root>

您可以看到,给定一个类,我们可以“轻松”创建这样的XML文档。

所以main.jet看起来像这样:

<%@taglib prefix="ws" id="org.eclipse.jet.workspaceTags" %>

<c:iterate select="/root/object" var="object"

    <c:set select="$object" name="impl" ><c:get select="$object/@name"/>Implementation</c:set>
    <c:set select="$object" name="interface" ><c:get select="$object/@name"/></c:set>

</c:iterate>


<c:iterate select="/root/object" var="object">

    <ws:file path="my project/src/a/b/c/{$object/@interface}.java" template="interface.jet" />
    <ws:file path="my project/src/a/b/c/{$object/@impl}.java" template="impl.jet" />

</c:iterate>

基本上你在迭代每个对象(你可以根据需要定义),然后构建实现和接口名称并将这些名称存储回模型中。
完成所有命名约定后,迭代对象元素并使用ws:file标记将模板应用于模型。标签告诉我们使用哪个模板,然后使用生成结果指定要创建的文件名。

interface.jet文件可能如下所示:

package a.b.c;

interface <c:get select="$object/@interface"/> { 
<c:iterate select="$object/method" var="method" > 
    <c:get select="$method/@returns"/> <c:get select="$method/@name"/>(int x, int y);  
</c:iterate>
}  

请注意,我已将软件包硬编码为a.b.c.您可以通过向XML文件添加属性来创建该变量,可能是对象元素,并使用c:get标记将其插入到源中。我还将args保留为硬编码,但您可以使用另一个迭代标记来迭代模型中的嵌套元素以写出方法签名。

所以我会在那里停下来看看这是不是你要找的东西。您可能想在评论中提出更多问题或发布更多问题。