Есть ли способ скопировать объект Java Arraylist в исходный код, сгенерированный кодовой моделью?

У меня есть заполненный массив (не кодовая модель) в классе генерации кода с использованием кодовой модели, и я хотел бы использовать его в сгенерированном коде. Есть какой-либо способ сделать это? это немного "пересекает миры", так как сгенерированный код не ссылается и не зависит от кода, его генерирующего, однако я все же хотел бы использовать значение массива без необходимости вручную копировать его в обход значения путем значение... должен быть способ сделать это, как в случае со строками, числами и т.д...?

мой пример кода выглядит следующим образом:

private JMethod makeHeadersWrapper( String endPointName, ArrayList<BasicNameValuePair> headersList )
{

    JMethod wrapperMethod = definedClass.method( JMod.PUBLIC | JMod.STATIC, codeModel.ref( headersList.getClass() ).narrow( BasicNameValuePair.class ), StringUtils.formatName( "make" + endPointName + "Header", false, StringUtils.FormatType.UP_ENGLISH_WORDS ) );

    JVar headersListVar = wrapperMethod.body().decl( wrapperMethod.type(), "headersList", {X} ) );
    wrapperMethod.body()._return( headersListVar );

    return wrapperMethod;

}

как вы видите в моем объявлении о назначении, есть пустое поле {X}, которое я пытаюсь выяснить, как писать. при этом {X} должен ссылаться на параметр 'headersList' в сигнатуре makeHeadersWrapper. Есть ли способ сделать это, чтобы ссылаться на значение переменной как {X} и иметь его кодовой моделью JExpr(ession)? пожалуйста, помогите мне решить для {X}!:П

искренне спасибо Петр

1 ответ

Решение

В основном я не думаю JExpression поддерживает списки. У него есть JArray но все же вам придется перебирать headersList, До codemode-2.6 нет метода в JExpr или же JExpression который перебирает список. Таким образом, вы не можете сойти с итерационной части. Таким образом, стандартная практика будет повторяться headersList и добавить операторы инициализации.

Скажем, например, у вас есть пара Namevalue, как

public class BasicNameValuePair {
    private String name;
    private String value;

    public BasicNameValuePair(String name, String value) {
        this.name = name;
        this.value = value;
    }
    //getters & setters
}

и инициализируется как

List<BasicNameValuePair> headerList = new ArrayList<BasicNameValuePair>();
headerList.add(new BasicNameValuePair("1", "1"));
headerList.add(new BasicNameValuePair("2", "2"));
headerList.add(new BasicNameValuePair("3", "3"));
headerList.add(new BasicNameValuePair("4", "4"));

Тогда вы можете сгенерировать ваше тело метода как

private JMethod makeHeadersWrapper( String endPointName, List<BasicNameValuePair> headersList ) {

    JClass headerClass = codeModel.ref( headersList.getClass() ).narrow( BasicNameValuePair.class );
    JMethod wrapperMethod = definedClass.method( JMod.PUBLIC | JMod.STATIC, headerClass, ( "make" + endPointName + "Header") );

    JVar headersListVar = wrapperMethod.body().decl( wrapperMethod.type(), "headersList", JExpr._new(headerClass) );
    for(BasicNameValuePair nameValuePair : headersList) {
        wrapperMethod.body().add(headersListVar.invoke("add").arg(JExpr._new(nameValuePairClass).arg(nameValuePair.getName()).arg(nameValuePair.getValue())));
    }
    wrapperMethod.body()._return( headersListVar );

    return wrapperMethod;
}

Это сгенерирует код

public static ArrayList<BasicNameValuePair> makeTestHeader() {
    ArrayList<BasicNameValuePair> headersList = new ArrayList<BasicNameValuePair>();
    headersList.add(new BasicNameValuePair("1", "1"));
    headersList.add(new BasicNameValuePair("2", "2"));
    headersList.add(new BasicNameValuePair("3", "3"));
    headersList.add(new BasicNameValuePair("4", "4"));
    return headersList;
}

тем не мение ArrayList есть метод конструктора, использующий {{ }}, Таким образом, вы могли бы заявить, как

List<String> lst = new ArrayList<String>(){{ add("1"); add("2"); add("3"); add("4"); }};

А также JExpr имеет direct() метод, в котором мы могли бы передать исходный код напрямую. Используя оба из них, мы можем сгенерировать код, как показано ниже. Я не рекомендую этот подход, но это возможно.

private JMethod makeHeadersWrapper( String endPointName, List<BasicNameValuePair> headersList ) {
    JMethod wrapperMethod = definedClass.method( JMod.PUBLIC | JMod.STATIC, codeModel.ref( headersList.getClass() ).narrow( BasicNameValuePair.class ), ( "make" + endPointName + "Header") );

    JVar headersListVar = wrapperMethod.body().decl( wrapperMethod.type(), "headersList", JExpr.direct(generateListConstructor(headersList)) );
    wrapperMethod.body()._return( headersListVar );

    return wrapperMethod;

}

private String generateListConstructor(List<BasicNameValuePair> headersList) {
    StringBuilder listEpr = new StringBuilder("new ArrayList<scope.BasicNameValuePair>(){{");
    for(BasicNameValuePair nameValuePair : headersList) {
        listEpr.append("add(new BasicNameValuePair(\"").append(nameValuePair.getName()).append("\", \"").append(nameValuePair.getValue()).append("\")); ");
    }
    return listEpr.append("}}").toString();
}

Это сгенерирует

public static ArrayList<BasicNameValuePair> makeTestHeader() {
    ArrayList<BasicNameValuePair> headersList = (new ArrayList<scope.BasicNameValuePair>(){{add(new BasicNameValuePair("1", "1")); add(new BasicNameValuePair("2", "2")); add(new BasicNameValuePair("3", "3")); add(new BasicNameValuePair("4", "4")); }});
    return headersList;
}

Это также действительный код Java.

Этот ответ может быть не тем, который вы ищете, но он может дать вам представление о том, как двигаться дальше. Надеюсь это поможет.

Другие вопросы по тегам