in trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/xml/parse/StyleSheetDocument.java [803:1000]
private void _resolveStyleWork(
StyleContext context,
String id,
boolean forIconNode,
StyleSheetList styleSheets,
Map<String, StyleNode> resolvedStyles,
Map<String, StyleNode> resolvedNamedStyles,
Deque<String> includesStack,
Deque<String> namedIncludesStack,
StyleEntry entry,
List<StyleNode> nodeList)
{
if (nodeList != null)
{
for (StyleNode node : nodeList)
{
// We've got a match! We need to do the following:
// 0. Check to see whether we need to reset our properties.
// 1. Resolve any included styles, and shove those properties
// into our StyleEntry.
// 2. Resolve any included properties, and shove those properties
// into our StyleEntry.
// 3. Remove all properties that were inhibited.
// 4. Shove all properties from the matching StyleNode into our
// StyleEntry, overwriting included values
// 5. Shove all skin properties from the matching StyleNode into our
// StyleEntry, overwriting included values
// -= Simon Lessard =-
// FIXME: That sequence looks buggy. If more than 1 matching node
// is found, then the included properties of the second will
// have priority over the properties found at step 5 on the
// first node, which is most likely incorrect.
//
// A possible fix would be to put entries from the 5 steps
// into 5 different lists then resolve all priorities at the
// end.
// 0. Reset properties?
if (node.__getResetProperties() || node.isInhibitingAll())
entry.resetProperties();
// 1. Resolve included styles
Iterable<IncludeStyleNode> includedStyles = node.getIncludedStyles();
for (IncludeStyleNode includeStyle : includedStyles)
{
String includeID = null;
boolean includeIsNamed = false;
if (includeStyle.getName() != null)
{
includeID = includeStyle.getName();
includeIsNamed = true;
}
else
{
includeID = includeStyle.getSelector();
}
// for include styles we do not support selectors and properties within client rules
// this is because, we cannot determine which selector or property should be applied,
// as the client rules are resolved on the browser.
// so we look for a selector or property without any client rules.
// thus pass null for cacheId and clientRule
StyleNode resolvedNode = _resolveStyleNode(context, forIconNode,
styleSheets,
resolvedStyles,
resolvedNamedStyles,
includesStack,
namedIncludesStack,
includeID,
includeIsNamed,
null,
null);
if (resolvedNode != null)
_addIncludedProperties(entry, resolvedNode);
else
{
// Fortunately this is an uncommon usecase
// af|foo::some-icon {content: url(); width:16px; height:16px}
// // In SkinStyleSheetParserUtils, we are not sure if this is an icon or style
// // since there is no explicit 'content' attr. So we create both an Icon and a Style.
// af|bar::some-icon {-tr-rule-ref: selector("af|foo");}
if (_LOG.isFinest() && !forIconNode && StyleUtils.isIcon(includeID) &&
StyleUtils.isIcon(id))
{
_LOG.finest(id + " is being written to the CSS file " +
"even though it is likely a Skin Icon Object, not a style.");
}
}
}
// 2. Resolve included properties
// color: -tr-property-ref(".AFDefaultFont:alias","background-color");
Iterable<IncludePropertyNode> includedProperties = node.getIncludedProperties();
for (IncludePropertyNode includeProperty : includedProperties)
{
StyleNode resolvedNode =
_resolveIncludedProperties(context, forIconNode, styleSheets, resolvedStyles,
resolvedNamedStyles, includesStack, namedIncludesStack,
includeProperty);
if (resolvedNode != null)
{
_addIncludedProperty(entry,
resolvedNode,
includeProperty.getPropertyName(),
includeProperty.getLocalPropertyName());
}
}
// 2'. Resolve included properties in a composite property value.
// e.g., border: 1px solid -tr-property-ref(".AFDarkColor:alias",color);
// e.g., background: -ms-linear-gradient(top, -tr-property-ref(".AFRed:alias", "color") 0%, -tr-property-ref(".AFGreen:alias","color") 100%);
Iterable<EmbeddedIncludePropertyNode> embeddedIncludeProperties =
node.getEmbeddedIncludeProperties();
for (EmbeddedIncludePropertyNode embeddedInclude : embeddedIncludeProperties)
{
// get each IncludePropertyNode, and resolve it.
Map<String, IncludePropertyNode> ipNodes = embeddedInclude.getIncludedProperties();
Map<String, String> resolvedValues = new HashMap<String, String>();
Iterator<Map.Entry<String,IncludePropertyNode>> entryIter = ipNodes.entrySet().iterator();
while (entryIter.hasNext())
{
Map.Entry<String,IncludePropertyNode> currEntry = entryIter.next();
String placeHolder = currEntry.getKey();
IncludePropertyNode includeProperty = currEntry.getValue();
StyleNode resolvedNode = _resolveIncludedProperties(context,
forIconNode,
styleSheets,
resolvedStyles,
resolvedNamedStyles,
includesStack,
namedIncludesStack,
includeProperty);
if (resolvedNode != null)
{
List<PropertyNode> pNodes = _getIncludedPropertyNodes(
resolvedNode,
includeProperty.getPropertyName(),
includeProperty.getLocalPropertyName());
// stores all the resolved 'values'. we will concat these values when we
// create the PropertyNode because these are composite values, like "1px solid red"
if (pNodes != null && !pNodes.isEmpty())
resolvedValues.put(placeHolder, pNodes.get(0).getValue());
}
}
// here we are. We have processed one EmbeddedIncludePropertyNode's includePropertyNodes.
// now we need to add to the entry:
if (!resolvedValues.isEmpty() || embeddedInclude.getPropertyValues().hasNext())
{
String compositeValue = _createCompositeValue(embeddedInclude, resolvedValues);
String localName = embeddedInclude.getLocalPropertyName();
PropertyNode propertyNode = new PropertyNode(localName,
compositeValue);
if (!(localName.startsWith(_TR_PROPERTY_PREFIX)))
entry.addProperty(propertyNode);
else
entry.addSkinProperty(propertyNode);
}
}
// 3. Check inhibited properties
Iterable<String> inhibitedProperties = node.getInhibitedProperties();
for (String inhibitedPropertyName : inhibitedProperties)
{
entry.removeProperty(inhibitedPropertyName);
entry.removeSkinProperty(inhibitedPropertyName);
}
// 4. Add non-included properties
Iterable<PropertyNode> properties = node.getProperties();
for (PropertyNode propertyNode : properties)
{
entry.addProperty(propertyNode);
}
// 5. Add non-included skin property node properties
Iterable<PropertyNode> skinProperties = node.getSkinProperties();
for (PropertyNode skinPropNode : skinProperties)
{
entry.addSkinProperty(skinPropNode);
}
}
}
}