package org.geotools.styling.css; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.geotools.filter.visitor.SimplifyingFilterVisitor; import org.geotools.styling.css.selector.PseudoClass; import org.geotools.styling.css.selector.Selector; class RulesCombiner { SimplifyingFilterVisitor simplifier; List<CssRule> lastRuleSet; Selector lastCombinedSelector; public RulesCombiner(SimplifyingFilterVisitor simplifier) { this.simplifier = simplifier; } CssRule combineRules(List<CssRule> rules) { CssRule combined; // build the main rule Selector combinedSelector = combineSelectors(rules); // apply cascading on properties Map<PseudoClass, Map<String, Property>> properties = new LinkedHashMap<>(); for (CssRule cssRule : rules) { for (Map.Entry<PseudoClass, List<Property>> entry : cssRule.getProperties() .entrySet()) { PseudoClass ps = entry.getKey(); Map<String, Property> psProperties = properties.get(ps); if (psProperties == null) { psProperties = new LinkedHashMap<String, Property>(); properties.put(ps, psProperties); } for (Property p : entry.getValue()) { psProperties.put(p.getName(), p); } if (ps != PseudoClass.ROOT) { // we also have to fill values for the pseudo classes owned by this one for (PseudoClass containedClass : properties.keySet()) { if (ps.contains(containedClass)) { Map<String, Property> containedProperties = properties .get(containedClass); for (Property p : entry.getValue()) { containedProperties.put(p.getName(), p); } } } } } } // build the new rule Map<PseudoClass, List<Property>> newProperties = new LinkedHashMap<>(); for (Map.Entry<PseudoClass, Map<String, Property>> entry : properties.entrySet()) { newProperties.put(entry.getKey(), new ArrayList<Property>(entry.getValue().values())); } String comment = getCombinedComment(rules); combined = new CssRule(combinedSelector, newProperties, comment); combined.setAncestry(rules); return combined; } private String getCombinedComment(List<CssRule> rules) { StringBuilder sb = new StringBuilder(); for (CssRule rule : rules) { if (rule.getComment() != null) { if (sb.length() > 0) { sb.append("\n"); } sb.append(rule.getComment()); } } if (sb.length() > 0) { return sb.toString(); } else { return null; } } Selector combineSelectors(List<CssRule> rules) { if (rules == lastCombinedSelector) { return lastCombinedSelector; } Selector s; if (rules.size() == 1) { s = rules.get(0).getSelector(); } else { s = rules.get(0).getSelector(); for (int i = 1; i < rules.size() && s != Selector.REJECT; i++) { CssRule rule = rules.get(i); s = Selector.and(s, rule.getSelector(), simplifier); } } this.lastRuleSet = rules; this.lastCombinedSelector = s; return s; } }