= Multimaps.newListHashMultimap();
for (WhiteList.TypeDefinition def : attribList.typeDefinitions().values()) {
String key = Strings.lower((String) def.get("key", null));
AttribKey elAndAttrib = attribKey(key);
if (elAndAttrib == null) { throw new NullPointerException(key); }
ElKey element = elAndAttrib.el;
HTML.Attribute.Type type = HTML.Attribute.Type.NONE;
String typeName = (String) def.get("type", null);
if (typeName != null) {
// TODO(mikesamuel): divert IllegalArgumentExceptions to MessageQueue
type = HTML.Attribute.Type.valueOf(typeName);
}
String loaderTypeStr = (String) def.get("loaderType", null);
// TODO(mikesamuel): divert IllegalArgumentExceptions to MessageQueue
LoaderType loaderType = loaderTypeStr != null
? LoaderType.valueOf(loaderTypeStr) : null;
String uriEffectStr = (String) def.get("uriEffect", null);
// TODO(mikesamuel): divert IllegalArgumentExceptions to MessageQueue
UriEffect uriEffect = uriEffectStr != null
? UriEffect.valueOf(uriEffectStr) : null;
RegularCriterion elCriterion = criteria.get(elAndAttrib);
RegularCriterion wcCriterion = criteria.get(elAndAttrib.onAnyElement());
RegularCriterion criterion = conjunction(elCriterion, wcCriterion);
String defaultValue = (String) def.get("default", null);
boolean optional = Boolean.TRUE.equals(def.get("optional", true));
String safeValue = (String) def.get("safeValue", null);
if (safeValue == null) {
String candidate = defaultValue != null ? defaultValue : "";
if (criterion.accept(candidate)) {
safeValue = candidate;
} else {
String values = (String) def.get("values", null);
if (values != null) {
safeValue = values.split(",")[0];
}
}
}
boolean valueless = Boolean.TRUE.equals(def.get("valueless", false));
// For valueless attributes, like checked, we allow the blank value.
if (valueless && !criterion.accept("")) {
criterion = RegularCriterion.Factory.or(
criterion,
RegularCriterion.Factory.fromValueSet(Collections.singleton("")));
}
HTML.Attribute a = new HTML.Attribute(
elAndAttrib, type, defaultValue, safeValue, valueless, optional,
loaderType, uriEffect, criterion);
attributeDetails.put(elAndAttrib, a);
attributeDetailsByElement.put(element, a);
}
this.attributesForUnknownHTMLElement = Collections.unmodifiableList(
Lists.newArrayList(attributeDetailsByElement.get(ElKey.HTML_WILDCARD)));
this.allowedElements = Sets.newHashSet();
for (String qualifiedName : tagList.allowedItems()) {
allowedElements.add(
ElKey.forElement(Namespaces.HTML_DEFAULT, qualifiedName));
}
this.elementDetails = Maps.newHashMap();
for (WhiteList.TypeDefinition def : tagList.typeDefinitions().values()) {
String qualifiedTagName = (String) def.get("key", null);
ElKey key = ElKey.forElement(Namespaces.HTML_DEFAULT, qualifiedTagName);
Collection<HTML.Attribute> specific = attributeDetailsByElement.get(key);
ElKey wc = ElKey.wildcard(key.ns);
Collection<HTML.Attribute> general = attributeDetailsByElement.get(wc);
List<HTML.Attribute> attrs = Lists.newArrayList(specific);
if (!general.isEmpty()) {
Set<AttribKey> present = Sets.newHashSet();
for (HTML.Attribute a : attrs) {