in src/main/org/apache/tools/ant/taskdefs/AntStructure.java [250:362]
public void printElementDecl(final PrintWriter out, final Project p,
final String name, final Class<?> element) {
if (visited.containsKey(name)) {
return;
}
visited.put(name, "");
IntrospectionHelper ih;
try {
ih = IntrospectionHelper.getHelper(p, element);
} catch (final Throwable t) {
/*
* TODO - failed to load the class properly.
*
* should we print a warning here?
*/
return;
}
StringBuilder sb = new StringBuilder("<!ELEMENT ").append(name).append(" ");
if (Reference.class.equals(element)) {
sb.append(String.format("EMPTY>%n<!ATTLIST %s%n"
+ " id ID #IMPLIED%n refid IDREF #IMPLIED>%n",
name));
out.println(sb);
return;
}
final List<String> v = new ArrayList<>();
if (ih.supportsCharacters()) {
v.add("#PCDATA");
}
if (TaskContainer.class.isAssignableFrom(element)) {
v.add(TASKS);
}
v.addAll(Collections.list(ih.getNestedElements()));
final Collector<CharSequence, ?, String> joinAlts =
Collectors.joining(" | ", "(", ")");
if (v.isEmpty()) {
sb.append("EMPTY");
} else {
sb.append(v.stream().collect(joinAlts));
if (v.size() > 1 || !"#PCDATA".equals(v.get(0))) {
sb.append("*");
}
}
sb.append(">");
out.println(sb);
sb = new StringBuilder();
sb.append(String.format("<!ATTLIST %s%n id ID #IMPLIED", name));
for (final String attrName : Collections.list(ih.getAttributes())) {
if ("id".equals(attrName)) {
continue;
}
sb.append(String.format("%n %s ", attrName));
final Class<?> type = ih.getAttributeType(attrName);
if (type.equals(Boolean.class) || type.equals(Boolean.TYPE)) {
sb.append(BOOLEAN).append(" ");
} else if (Reference.class.isAssignableFrom(type)) {
sb.append("IDREF ");
} else if (EnumeratedAttribute.class.isAssignableFrom(type)) {
try {
final EnumeratedAttribute ea =
type.asSubclass(EnumeratedAttribute.class).getDeclaredConstructor().newInstance();
final String[] values = ea.getValues();
if (values == null || values.length == 0
|| !areNmtokens(values)) {
sb.append("CDATA ");
} else {
sb.append(Stream.of(values).collect(joinAlts)).append(" ");
}
} catch (final InstantiationException | IllegalAccessException
| NoSuchMethodException | InvocationTargetException ie) {
sb.append("CDATA ");
}
} else if (Enum.class.isAssignableFrom(type)) {
try {
final Enum<?>[] values =
(Enum<?>[]) type.getMethod("values").invoke(null);
if (values.length == 0) {
sb.append("CDATA ");
} else {
sb.append(Stream.of(values).map(Enum::name)
.collect(joinAlts)).append(" ");
}
} catch (final Exception x) {
sb.append("CDATA ");
}
} else {
sb.append("CDATA ");
}
sb.append("#IMPLIED");
}
sb.append(String.format(">%n"));
out.println(sb);
for (String nestedName : v) {
if (!"#PCDATA".equals(nestedName)
&& !TASKS.equals(nestedName)
&& !TYPES.equals(nestedName)) {
printElementDecl(out, p, nestedName, ih.getElementType(nestedName));
}
}
}