2

http://ant.apache.org/manual/develop.html#nested-elementsで説明されているように、カスタムAntタグにネストされた型を追加しようとしていますが、例外が発生し続けますouter doesn't support the nested "innerone" element.

私は午前中グーグルで過ごしましたが、この問題に対処するこのパターンを使用した例、チュートリアル、またはヘルプを見つけることができず、それが実装されているかどうか疑問に思い始めています!

私のビルドファイル:

<?xml version="1.0"?>
<project name="test" default="tester" basedir="../../..">
  <taskdef name="outer" classname="tester.Outer" classpath="target/classes"/>
  <typedef name="innerone" classname="tester.Outer$InnerOne" classpath="target/classes"/>
  <typedef name="innertwo" classname="tester.Outer$InnerTwo" classpath="target/classes"/>

  <target name="tester">
    <innerone/>
    <innertwo/>
    <outer>
      <innerone/>
      <innertwo/>
    </outer>
  </target>
</project>

Javaコード:

public class Outer extends Task
{
  private List<Inner> inners = new ArrayList<Inner>();
  public void add(Inner inner) {
    inners.add(inner);
    System.out.println("Add: ");
  }
  public void addConfigured(Inner inner) {
    inners.add(inner);
    System.out.println("AddConfigured: ");
  }
  public void execute() {
    for (Inner inner : inners) {
      System.out.println("Inner: " + inner.getMsg());
    }
  }

  public interface Inner {
    String getMsg();
  }
  public static class InnerOne implements Inner {
    public String getMsg() {
      return "One";
    }
  }
  public static class InnerTwo implements Inner {
    public String getMsg() {
      return "Two";
    }
  }
}

メソッドを使用するaddInner(Inner inner)addConfiguredInner(Inner inner)両方とも機能しますが、Outerクラスでメソッドを明示的に作成しなくても、Innerインターフェイスを実装する内部タグを追加できるようにしたいと思います。

4

2 に答える 2

1

従来、ネストされた要素の名前は、メソッド名で指定する必要がありました。たとえば、ネストされた要素をorとして定義する<inner>必要addInner(Inner inner)addConfiguredInner(Inner inner)ありました(前述のとおり、これは機能します)。

Ant 1.5では、DynamicConfigurator属性とネストされた要素の名前を動的に定義するメカニズムを提供するインターフェイスが導入されました。これはあなたが探している機能を正確に提供するわけではありませんが、それでもあなたはそれが役に立つと思うかもしれません。たとえば、Outerタスクは次のように実装できます。

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DynamicConfigurator;
import org.apache.tools.ant.Task;

import java.util.ArrayList;
import java.util.List;

public class Outer extends Task implements DynamicConfigurator
{
  private List<Inner> inners = new ArrayList<Inner>();

  public void setDynamicAttribute(String name, String value)
      throws BuildException {
    throw new BuildException("Attribute " + name + " is not supported");
  }

  public Inner createDynamicElement(String elementName) {
    Inner newInner = null;
    if (elementName.equalsIgnoreCase("innerone")) {
      newInner = new InnerOne();
    } else if (elementName.equalsIgnoreCase("innertwo")) {
      newInner = new InnerTwo();
    } else {
      throw new BuildException("Unsupported nested element: " + elementName);
    }
    inners.add(newInner);
    return newInner;
  }

  public void execute() {
    for (Inner inner : inners) {
      System.out.println("Inner: " + inner.getMsg());
    }
  }

  public interface Inner {
    String getMsg();
  }

  public static class InnerOne implements Inner {
    public String getMsg() {
      return "One";
    }
  }

  public static class InnerTwo implements Inner {
    public String getMsg() {
      return "Two";
    }
  }
}

ビルドファイル(抜粋)

<taskdef name="outer" classname="tester.Outer" classpath="target/classes"/>

<target name="outer-test">
  <outer>
    <innerone />
    <innertwo />
  </outer>
</target>

出力

outer-test:
    [outer] Inner: One
    [outer] Inner: Two

BUILD SUCCESSFUL
Total time: 0 seconds
于 2012-10-02T16:45:35.050 に答える
1

あなたの例は、ant マニュアルからリンクしたものと非常によく似ています。一方が機能し、もう一方が機能しないという違いは何ですか? かなり長い道のりでしたが、一歩一歩似たものにしていくうちに、違いがわかりました。

にはtypedefloaderRef、 に等しい属性を指定する必要がありclasspathます。typedef タスクのドキュメントには次のように書かれています。

これを使用して、複数のタスク/タイプを同じローダーでロードできるようにして、相互に呼び出すことができるようにします。

おそらくantlibを使用すると、この問題は存在しなくなります。これは、1つのantスクリプト行で宣言されるためです。

最後に答えは: はい、それらは動作します:)

于 2012-10-02T17:54:37.123 に答える