Java Maven Mojo: сложный атрибут карты

Пример атрибута карты для моджо, упомянутого в maven.apache.org довольно прост, так как определяет карту со строкой в ​​качестве ключа и значения, как указано ниже:

/**
 * My Map.
 */
@Parameter
private Map myMap;

и его назначенная конфигурация будет выглядеть так:

<myMap>
 <key1>value1</key1>
 <key2>value2</key2>
</myMap>

То, что я пытаюсь достичь, - это более продвинутая карта, которая принимает String в качестве ключа и мой собственный определенный класс Person в качестве значения:

/**
* My Advanced Map.
*/
@Parameter
private Map<String,Person> myMap;

Класс Person находится в том же пакете, что и мой MOJO, и выглядит он так:

public class Person {
  private String name;
  private int age;

  public void setName( String name )
  {
      this.name = name;
  }

  public void setAge( int age )
  {
      this.age = age;
  }

  public String getName( )
  {
      return this.name;
  }

  public int getAge( )
  {
      return this.age ;
  }
}

Я предполагаю, что конфигурация моего MOJO будет выглядеть так:

<myMap>
  <firstPerson>
    <person>
      <name>steve</name>
      <age>26</age>
    </person>
  </firstPerson>
  <secondPerson>
    <person>
      <name>meruem</name>
      <age>1</age>
    </person>
  </secondPerson>
</myMap>

Запуск этого MOJO с приведенной выше конфигурацией создаст карту с определенными ключами, но я всегда получаю нулевые значения: {firstPerson=null,secondPerson=null}

В настоящее время я не знаю, делаю ли я что-то неправильно, или этот пример вообще поддерживается, поскольку не было найдено документации, описывающей «расширенный» атрибут карты, и моим последним средством на данный момент будет просмотр источников.


person Mouadh    schedule 08.05.2014    source источник
comment
Что будет ключевым в вашем случае? Имя человека? Или сочетание нескольких атрибутов класса Person?   -  person khmarbaise    schedule 09.05.2014
comment
Ну а ключ будет атрибутом для идентификации личности.   -  person Mouadh    schedule 10.05.2014


Ответы (2)


Вы на самом деле очень близки к решению. Вам просто нужно настроить свой плагин следующим образом (без внутреннего элемента <person>):

<myMap>
  <firstPerson>
    <name>steve</name>
    <age>26</age>
  </firstPerson>
  <secondPerson>
    <name>meruem</name>
    <age>1</age>
  </secondPerson>
</myMap>

Чтобы предоставить вам полный рабочий пример, рассмотрите следующий POM плагина Maven:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>sample.plugin</groupId>
    <artifactId>test-maven-plugin</artifactId>
    <version>1.0.0</version>
    <packaging>maven-plugin</packaging>
    <dependencies>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>3.4</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

имея следующий MOJO, объявляя цель foo и имея параметр типа Map<String, Person>, который просто регистрирует карту как информацию:

@Mojo(name = "foo")
public class MyMojo extends AbstractMojo {

    @Parameter
    private Map<String, Person> map;

    public void execute() throws MojoExecutionException, MojoFailureException {
        getLog().info(map.toString());
    }

}

и следующий класс Person:

public class Person {

    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}

Как только этот плагин Maven установлен в репозитории (используя mvn clean install), мы можем использовать его в таком проекте:

<plugin>
    <groupId>sample.plugin</groupId>
    <artifactId>test-maven-plugin</artifactId>
    <version>1.0.0</version>
    <executions>
        <execution>
            <id>foo</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>foo</goal>
            </goals>
            <configuration>
                <map>
                    <person1>
                        <name>Name 1</name>
                        <age>10</age>
                    </person1>
                    <person2>
                         <name>Name 2</name>
                         <age>20</age>
                     </person2>
                </map>
            </configuration>
        </execution>
    </executions>
</plugin>

Вывод этого плагина при запуске mvn clean generate-sources:

[INFO] --- test-maven-plugin:1.0.0:foo (add-source) @ test ---
[INFO] {person1=Person [name=Name 1, age=10], person2=Person [name=Name 2, age=20]}
person Tunaki    schedule 11.10.2015
comment
Спасибо за развернутый пример. Я наградил вас наградой. - person peterh; 16.10.2015

Добавьте аннотацию @Parameter к атрибутам имени и возраста в вашем классе Person.

person tdrury    schedule 15.05.2014
comment
Я не думаю, что это также сработает, поскольку я просматривал источники, я попал в класс MapConverter, который создает экземпляр объекта Map, но метод convert всегда обрабатывает значение карты как строку, а не объект. - person Mouadh; 27.05.2014