Использование JET для генерации кода: отступ кода - PullRequest
4 голосов
/ 14 октября 2011

Я пытаюсь сделать следующее:

Написать шаблон JET, который получает объект типа Class как аргумент. Объект должен представлять интерфейс Java. Шаблон генерирует класс, который реализует интерфейс, т.е. предоставляет методы для всех сигнатур методов, которые он определяет. Имя сгенерированного класс должен быть XImplementation, где X - имя аргумента интерфейс. Методы в сгенерированном классе не делают ничего или только возвращаемое значение константы: 0 для int и double, false для логического значения и нуль для ссылочных типов. Вам не нужно рассматривать любой другой возврат типы. Например. для следующего интерфейса A класс AImplementation будет быть сгенерировано:

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 () соответствующий объект класса.

Я прочитал учебники по JET, найденные на eclipse.org, но у меня все еще возникают проблемы с пониманием того, что мне нужно делать.

Когда я делаю файл .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();
  }

Есть ли способ отступить строки stringBuffer.append() в операторе if? И является ли способ String правильным решением этой задачи?

Спасибо.

1 Ответ

0 голосов
/ 10 октября 2012

Я бы использовал более новый синтаксис JET2. Вы должны быть в состоянии создать новое преобразование JET с помощью New -> Other.

Что касается того, что происходит на высоком уровне, у вас будет шаблон с именем 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, чтобы вставить его в источник. Я также оставил аргументы жестко запрограммированными, но вы можете использовать другой тег итерации для итерации по вложенным элементам в модели для записи сигнатуры метода.

Так что я остановлюсь здесь, чтобы посмотреть, если это то, что вы искали. Возможно, вы захотите задать больше в комментариях или оставить больше вопросов.

...