package com.mozz.htmlnative.css; import com.mozz.htmlnative.css.selector.AnySelector; import com.mozz.htmlnative.css.selector.ClassSelector; import com.mozz.htmlnative.css.selector.CssSelector; import com.mozz.htmlnative.css.selector.IdSelector; import com.mozz.htmlnative.css.selector.TypeSelector; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * @author Yang Tao, 17/3/27. */ public final class StyleSheet extends AttrsSet { private StringSelectorHolder mClassSelectors; private StringSelectorHolder mIdSelectors; private StringSelectorHolder mTypeSelectors; private AnySelectorHolder mAnySelectors; /** * used to store the css selector order in file */ private Map<CssSelector, Integer> mSelectorOrderMap = new HashMap<>(); private int mInsertOrderSave = 0; public StyleSheet() { super("StyleSheet"); mClassSelectors = new StringSelectorHolder(); mIdSelectors = new StringSelectorHolder(); mTypeSelectors = new StringSelectorHolder(); mAnySelectors = new AnySelectorHolder(); } public void putSelector(CssSelector cssSelector) { putSingleSelector(cssSelector.tail()); } private void putSingleSelector(CssSelector cssSelector) { mSelectorOrderMap.put(cssSelector, mInsertOrderSave++); if (cssSelector.getClass().equals(ClassSelector.class)) { ClassSelector classSelector = (ClassSelector) cssSelector; mClassSelectors.put(classSelector.getName(), classSelector); } else if (cssSelector.getClass().equals(IdSelector.class)) { IdSelector idSelector = (IdSelector) cssSelector; mIdSelectors.put(idSelector.getName(), idSelector); } else if (cssSelector.getClass().equals(TypeSelector.class)) { TypeSelector typeSelector = (TypeSelector) cssSelector; mTypeSelectors.put(typeSelector.getName(), typeSelector); } else if (cssSelector.getClass().equals(AnySelector.class)) { mAnySelectors.put((AnySelector) cssSelector); } } /** * Find selectors according to type, id and class. All selectors found will be stored in * insert order. * * @param type type of element * @param id id of element if have * @param clazz class name of element if have * @return List containing all the selectors matched in insert order. */ public CssSelector[] matchedSelector(String type, String id, String[] clazz) { // Pass mSelectorOrderMap.size() to make sure that matchedSelector is big enough to hold // all the selectors found. CssSelector[] matchedSelector = new CssSelector[mSelectorOrderMap.size()]; mClassSelectors.matches(clazz, matchedSelector); mIdSelectors.matches(id, matchedSelector); mTypeSelectors.matches(type, matchedSelector); mAnySelectors.matches(matchedSelector); return matchedSelector; } @Override public String toString() { return "AttrSet=" + super.toString() + "\n, class=" + mClassSelectors + "\n, id=" + mIdSelectors + "\n, type=" + mTypeSelectors; } /** * @author Yang Tao, 17/3/30. */ private final class StringSelectorHolder { private Map<String, Set<CssSelector>> mSelectors = new HashMap<>(); public void put(String key, CssSelector selector) { Set<CssSelector> sets = mSelectors.get(key); if (sets == null) { sets = new HashSet<>(); mSelectors.put(key, sets); } sets.add(selector); } void matches(String key, CssSelector[] outSelectors) { Set<CssSelector> sets = mSelectors.get(key); if (sets != null) { for (CssSelector selector : sets) { Integer index = mSelectorOrderMap.get(selector); outSelectors[index] = selector; } } } void matches(String[] key, CssSelector[] outSelectors) { if (key != null && key.length > 0) { for (String k : key) { if (k != null) { matches(k, outSelectors); } } } } @Override public String toString() { return mSelectors.toString(); } } private final class AnySelectorHolder { private List<CssSelector> mSelectors = new ArrayList<>(); public void put(AnySelector selector) { mSelectors.add(selector); } void matches(CssSelector[] outSelectors) { for (CssSelector selector : mSelectors) { Integer index = mSelectorOrderMap.get(selector); outSelectors[index] = selector; } } @Override public String toString() { return mSelectors.toString(); } } }