nested elements of types/tasks use the same NS uri as the task/type. also cleanup macrodef attribute handling git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275639 13f79535-47bb-0310-9956-ffa450edef68master
@@ -133,9 +133,9 @@ | |||
<sequential> | |||
<current:if> | |||
<current:isallowed test="${action}"/> | |||
<then> | |||
<do/> | |||
</then> | |||
<current:then> | |||
<current:do/> | |||
</current:then> | |||
</current:if> | |||
</sequential> | |||
</macrodef> | |||
@@ -642,6 +642,52 @@ public final class IntrospectionHelper implements BuildListener { | |||
return nc; | |||
} | |||
private NestedCreator getNestedCreator( | |||
Project project, String parentUri, Object parent, | |||
String elementName) throws BuildException { | |||
String uri = ProjectHelper.extractUriFromComponentName(elementName); | |||
String name = ProjectHelper.extractNameFromComponentName(elementName); | |||
NestedCreator nc = null; | |||
if (uri.equals(parentUri)) { // || uri.equals("")) { | |||
nc = (NestedCreator) nestedCreators.get( | |||
name.toLowerCase(Locale.US)); | |||
} | |||
if (nc == null) { | |||
nc = createAddTypeCreator(project, parent, elementName); | |||
} | |||
if (nc == null && parent instanceof DynamicConfigurator) { | |||
DynamicConfigurator dc = (DynamicConfigurator) parent; | |||
final Object nestedElement = dc.createDynamicElement(elementName); | |||
if (nestedElement != null) { | |||
nc = new NestedCreator() { | |||
public boolean isPolyMorphic() { | |||
return false; | |||
} | |||
public Class getElementClass() { | |||
return null; | |||
} | |||
public Object getRealObject() { | |||
return null; | |||
} | |||
public Object create( | |||
Project project, Object parent, Object ignore) { | |||
return nestedElement; | |||
} | |||
public void store(Object parent, Object child) { | |||
} | |||
}; | |||
} | |||
} | |||
if (nc == null) { | |||
throwNotSupported(project, parent, elementName); | |||
} | |||
return nc; | |||
} | |||
/** | |||
* Creates a named nested element. Depending on the results of the | |||
* initial introspection, either a method in the given parent instance | |||
@@ -692,6 +738,7 @@ public final class IntrospectionHelper implements BuildListener { | |||
* for an element of a parent. | |||
* | |||
* @param project Project to which the parent object belongs. | |||
* @param parentUri The namespace uri of the parent object. | |||
* @param parent Parent object used to create the creator object to | |||
* create and store and instance of a subelement. | |||
* @param elementName Name of the element to create an instance of. | |||
@@ -699,8 +746,9 @@ public final class IntrospectionHelper implements BuildListener { | |||
*/ | |||
public Creator getElementCreator( | |||
Project project, Object parent, String elementName) { | |||
NestedCreator nc = getNestedCreator(project, parent, elementName); | |||
Project project, String parentUri, Object parent, String elementName) { | |||
NestedCreator nc = getNestedCreator( | |||
project, parentUri, parent, elementName); | |||
return new Creator(project, parent, nc); | |||
} | |||
@@ -718,6 +766,26 @@ public final class IntrospectionHelper implements BuildListener { | |||
|| addTypeMethods.size() != 0; | |||
} | |||
/** | |||
* Indicate if this element supports a nested element of the | |||
* given name. | |||
* | |||
* @param parentUri the uri of the parent | |||
* @param elementName the name of the nested element being checked | |||
* | |||
* @return true if the given nested element is supported | |||
*/ | |||
public boolean supportsNestedElement(String parentUri, String elementName) { | |||
String uri = ProjectHelper.extractUriFromComponentName(elementName); | |||
String name = ProjectHelper.extractNameFromComponentName(elementName); | |||
return ( | |||
nestedCreators.containsKey(name.toLowerCase(Locale.US)) | |||
&& (uri.equals(parentUri))) // || uri.equals(""))) | |||
|| DynamicConfigurator.class.isAssignableFrom(bean) | |||
|| addTypeMethods.size() != 0; | |||
} | |||
/** | |||
* Stores a named nested element using a storage method determined | |||
* by the initial introspection. If no appropriate storage method | |||
@@ -525,12 +525,29 @@ public class ProjectHelper { | |||
* @return The uri or "" if not present | |||
*/ | |||
public static String extractUriFromComponentName(String componentName) { | |||
if (componentName == null) { | |||
return ""; | |||
} | |||
int index = componentName.lastIndexOf(':'); | |||
if (index == -1) { | |||
return ""; | |||
} | |||
return componentName.substring(0, index); | |||
} | |||
/** | |||
* extract the element name from a component name | |||
* | |||
* @param componentName The stringified form for {uri, name} | |||
* @return The element name of the component | |||
*/ | |||
public static String extractNameFromComponentName(String componentName) { | |||
int index = componentName.lastIndexOf(':'); | |||
if (index == -1) { | |||
return componentName; | |||
} | |||
return componentName.substring(index+1); | |||
} | |||
/** | |||
* Add location to build exception. | |||
@@ -493,7 +493,7 @@ public abstract class Task extends ProjectComponent { | |||
* | |||
* @return the type of task | |||
*/ | |||
protected String getTaskType() { | |||
public String getTaskType() { | |||
return taskType; | |||
} | |||
@@ -336,13 +336,15 @@ public class UnknownElement extends Task { | |||
* | |||
* @exception BuildException if the children cannot be configured. | |||
*/ | |||
protected void handleChildren(Object parent, | |||
RuntimeConfigurable parentWrapper) | |||
protected void handleChildren( | |||
Object parent, | |||
RuntimeConfigurable parentWrapper) | |||
throws BuildException { | |||
if (parent instanceof TypeAdapter) { | |||
parent = ((TypeAdapter) parent).getProxy(); | |||
} | |||
String parentUri = getNamespace(); | |||
Class parentClass = parent.getClass(); | |||
IntrospectionHelper ih = IntrospectionHelper.getHelper(parentClass); | |||
@@ -352,8 +354,8 @@ public class UnknownElement extends Task { | |||
for (int i = 0; it.hasNext(); i++) { | |||
RuntimeConfigurable childWrapper = parentWrapper.getChild(i); | |||
UnknownElement child = (UnknownElement) it.next(); | |||
if (!handleChild(ih, parent, child, | |||
childWrapper)) { | |||
if (!handleChild( | |||
parentUri, ih, parent, child, childWrapper)) { | |||
if (!(parent instanceof TaskContainer)) { | |||
ih.throwNotSupported(getProject(), parent, | |||
child.getTag()); | |||
@@ -548,14 +550,16 @@ public class UnknownElement extends Task { | |||
* | |||
* @return whether the creation has been successful | |||
*/ | |||
private boolean handleChild(IntrospectionHelper ih, | |||
Object parent, UnknownElement child, | |||
RuntimeConfigurable childWrapper) { | |||
private boolean handleChild( | |||
String parentUri, | |||
IntrospectionHelper ih, | |||
Object parent, UnknownElement child, | |||
RuntimeConfigurable childWrapper) { | |||
String childName = ProjectHelper.genComponentName( | |||
child.getNamespace(), child.getTag()); | |||
if (ih.supportsNestedElement(childName)) { | |||
if (ih.supportsNestedElement(parentUri, childName)) { | |||
IntrospectionHelper.Creator creator = | |||
ih.getElementCreator(getProject(), parent, childName); | |||
ih.getElementCreator(getProject(), parentUri, parent, childName); | |||
creator.setPolyType(childWrapper.getPolyType()); | |||
Object realChild = creator.create(); | |||
if (realChild instanceof PreSetDef.PreSetDefinition) { | |||
@@ -939,8 +939,9 @@ public class ProjectHelper2 extends ProjectHelper { | |||
UnknownElement task = new UnknownElement(tag); | |||
task.setProject(context.getProject()); | |||
task.setNamespace(uri); | |||
//XXX task.setTaskType(qname); | |||
task.setQName(qname); | |||
task.setTaskType( | |||
ProjectHelper.genComponentName(task.getNamespace(), tag)); | |||
task.setTaskName(qname); | |||
Location location = new Location(context.getLocator().getSystemId(), | |||
@@ -84,8 +84,10 @@ import org.apache.tools.ant.UnknownElement; | |||
public class MacroInstance extends Task implements DynamicConfigurator { | |||
private MacroDef macroDef; | |||
private Map map = new HashMap(); | |||
private Map elements = new HashMap(); | |||
private Map nsElements = null; | |||
private Map presentElements = new HashMap(); | |||
private Hashtable localProperties = new Hashtable(); | |||
/** | |||
* Called from MacroDef.MyAntTypeDefinition#create() | |||
@@ -114,17 +116,33 @@ public class MacroInstance extends Task implements DynamicConfigurator { | |||
* has already been seen | |||
*/ | |||
public Object createDynamicElement(String name) throws BuildException { | |||
if (macroDef.getElements().get(name) == null) { | |||
if (getNsElements().get(name) == null) { | |||
throw new BuildException("unsupported element " + name); | |||
} | |||
if (elements.get(name) != null) { | |||
if (presentElements.get(name) != null) { | |||
throw new BuildException("Element " + name + " already present"); | |||
} | |||
Element ret = new Element(); | |||
elements.put(name, ret); | |||
presentElements.put(name, ret); | |||
return ret; | |||
} | |||
private Map getNsElements() { | |||
if (nsElements == null) { | |||
nsElements = new HashMap(); | |||
String myUri = ProjectHelper.extractUriFromComponentName( | |||
getTaskType()); | |||
for (Iterator i = macroDef.getElements().entrySet().iterator(); | |||
i.hasNext();) { | |||
Map.Entry entry = (Map.Entry) i.next(); | |||
nsElements.put(ProjectHelper.genComponentName( | |||
myUri, (String) entry.getKey()), | |||
entry.getValue()); | |||
} | |||
} | |||
return nsElements; | |||
} | |||
/** | |||
* Embedded element in macro instance | |||
*/ | |||
@@ -148,18 +166,38 @@ public class MacroInstance extends Task implements DynamicConfigurator { | |||
} | |||
} | |||
private static final int STATE_NORMAL = 0; | |||
private static final int STATE_EXPECT_BRACKET = 1; | |||
private static final int STATE_EXPECT_NAME = 2; | |||
private String macroSubs(String s, Map macroMapping) { | |||
StringBuffer ret = new StringBuffer(); | |||
StringBuffer macroName = new StringBuffer(); | |||
StringBuffer macroName = null; | |||
boolean inMacro = false; | |||
int state = STATE_NORMAL; | |||
for (int i = 0; i < s.length(); ++i) { | |||
if (s.charAt(i) == '$') { | |||
inMacro = true; | |||
} else { | |||
if (inMacro) { | |||
if (s.charAt(i) == '{') { | |||
continue; | |||
} else if (s.charAt(i) == '}') { | |||
char ch = s.charAt(i); | |||
switch (state) { | |||
case STATE_NORMAL: | |||
if (ch == '$') { | |||
state = 1; | |||
} else { | |||
ret.append(ch); | |||
} | |||
break; | |||
case STATE_EXPECT_BRACKET: | |||
if (ch == '{') { | |||
state = 2; | |||
macroName = new StringBuffer(); | |||
} else { | |||
state = 0; | |||
ret.append('$'); | |||
ret.append(ch); | |||
} | |||
break; | |||
case STATE_EXPECT_NAME: | |||
if (ch == '}') { | |||
state = 0; | |||
String name = macroName.toString(); | |||
String value = (String) macroMapping.get(name); | |||
if (value == null) { | |||
@@ -167,16 +205,23 @@ public class MacroInstance extends Task implements DynamicConfigurator { | |||
} else { | |||
ret.append(value); | |||
} | |||
macroName = new StringBuffer(); | |||
inMacro = false; | |||
macroName = null; | |||
} else { | |||
macroName.append(s.charAt(i)); | |||
} | |||
} else { | |||
ret.append(s.charAt(i)); | |||
} | |||
} | |||
} | |||
switch (state) { | |||
case STATE_NORMAL: | |||
break; | |||
case STATE_EXPECT_BRACKET: | |||
ret.append('$'); | |||
break; | |||
case STATE_EXPECT_NAME: | |||
ret.append("${"); | |||
ret.append(macroName.toString()); | |||
break; | |||
} | |||
return ret.toString(); | |||
} | |||
@@ -212,15 +257,15 @@ public class MacroInstance extends Task implements DynamicConfigurator { | |||
while (e.hasMoreElements()) { | |||
RuntimeConfigurable r = (RuntimeConfigurable) e.nextElement(); | |||
UnknownElement unknownElement = (UnknownElement) r.getProxy(); | |||
String tag = unknownElement.getTag(); | |||
String tag = unknownElement.getTaskType(); | |||
MacroDef.TemplateElement templateElement = | |||
(MacroDef.TemplateElement) macroDef.getElements().get(tag); | |||
(MacroDef.TemplateElement) getNsElements().get(tag); | |||
if (templateElement == null) { | |||
UnknownElement child = copy(unknownElement); | |||
rc.addChild(child.getWrapper()); | |||
ret.addChild(child); | |||
} else { | |||
Element element = (Element) elements.get(tag); | |||
Element element = (Element) presentElements.get(tag); | |||
if (element == null) { | |||
if (!templateElement.isOptional()) { | |||
throw new BuildException( | |||