in tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SaxTemplateParser.java [706:805]
private void possibleTapestryComponent(TemplateParserState state, String elementName,
String identifiedType)
{
String id = null;
String type = identifiedType;
String mixins = null;
int count = tokenStream.getAttributeCount();
Location location = getLocation();
List<TemplateToken> attributeTokens = CollectionFactory.newList();
for (int i = 0; i < count; i++)
{
QName qname = tokenStream.getAttributeName(i);
if (isXMLSpaceAttribute(qname))
continue;
// The name will be blank for an xmlns: attribute
String localName = qname.getLocalPart();
if (InternalUtils.isBlank(localName))
continue;
String uri = qname.getNamespaceURI();
String value = tokenStream.getAttributeValue(i);
Version version = NAMESPACE_URI_TO_VERSION.get(uri);
if (version != null)
{
// We are kind of assuming that the namespace URI appears once, in the outermost element of the template.
// And we don't and can't handle the case that it appears multiple times in the template.
if (T_5_4.sameOrEarlier(version)) {
strictMixinParameters = true;
}
if (localName.equalsIgnoreCase(ID_ATTRIBUTE_NAME))
{
id = nullForBlank(value);
validateId(id, "Component id '%s' is not valid; component ids must be valid Java identifiers: start with a letter, and consist of letters, numbers and underscores.");
continue;
}
if (type == null && localName.equalsIgnoreCase(TYPE_ATTRIBUTE_NAME))
{
type = nullForBlank(value);
continue;
}
if (localName.equalsIgnoreCase(MIXINS_ATTRIBUTE_NAME))
{
mixins = nullForBlank(value);
continue;
}
// Anything else is the name of a Tapestry component parameter
// that is simply
// not part of the template's doctype for the element being
// instrumented.
}
attributeTokens.add(new AttributeToken(uri, localName, value, location));
}
boolean isComponent = (id != null || type != null);
// If provided t:mixins but not t:id or t:type, then its not quite a
// component
if (mixins != null && !isComponent)
throw new TapestryException(String.format("You may not specify mixins for element <%s> because it does not represent a component (which requires either an id attribute or a type attribute).", elementName),
location, null);
if (isComponent)
{
tokenAccumulator.add(new StartComponentToken(elementName, id, type, mixins, location));
} else
{
tokenAccumulator.add(new StartElementToken(tokenStream.getNamespaceURI(), elementName,
location));
}
addDefineNamespaceTokens();
tokenAccumulator.addAll(attributeTokens);
if (id != null)
componentIds.put(id, location);
processBody(state.insideComponent(isComponent));
}