1 21 22 package org.lobobrowser.html.style; 23 24 import java.net.MalformedURLException ; 25 import java.util.*; 26 27 import org.lobobrowser.html.domimpl.HTMLDocumentImpl; 28 import org.lobobrowser.html.domimpl.HTMLElementImpl; 29 import org.w3c.dom.css.CSSImportRule; 30 import org.w3c.dom.css.CSSRule; 31 import org.w3c.dom.css.CSSRuleList; 32 import org.w3c.dom.css.CSSStyleRule; 33 import org.w3c.dom.css.CSSStyleSheet; 34 35 48 public class StyleSheetAggregator { 49 private final HTMLDocumentImpl document; 50 private final Map classMapsByElement = new HashMap(); 51 private final Map idMapsByElement = new HashMap(); 52 private final Map rulesByElement = new HashMap(); 53 54 public StyleSheetAggregator(HTMLDocumentImpl document) { 55 this.document = document; 56 } 57 58 public final void addStyleSheets(Collection styleSheets) throws MalformedURLException { 59 Iterator i = styleSheets.iterator(); 60 while(i.hasNext()) { 61 CSSStyleSheet sheet = (CSSStyleSheet) i.next(); 62 this.addStyleSheet(sheet); 63 } 64 } 65 66 private final void addStyleSheet(CSSStyleSheet styleSheet) throws MalformedURLException { 67 CSSRuleList ruleList = styleSheet.getCssRules(); 68 int length = ruleList.getLength(); 69 HTMLDocumentImpl document = this.document; 70 for(int i = 0; i < length; i++) { 71 CSSRule rule = ruleList.item(i); 72 if(rule instanceof CSSStyleRule) { 73 CSSStyleRule sr = (CSSStyleRule) rule; 74 String selectorText = sr.getSelectorText(); 75 StringTokenizer commaTok = new StringTokenizer(selectorText, ","); 76 while(commaTok.hasMoreTokens()) { 77 String selectorPart = commaTok.nextToken().toLowerCase(); 78 ArrayList ancestorSelectors = null; 79 String selector = null; 80 StringTokenizer tok = new StringTokenizer(selectorPart, " \t\r\n"); 81 while(tok.hasMoreTokens()) { 82 String token = tok.nextToken(); 83 if(tok.hasMoreTokens()) { 84 if(ancestorSelectors == null) { 85 ancestorSelectors = new ArrayList(); 86 } 87 ancestorSelectors.add(token); 88 } 89 else { 90 selector = token; 91 break; 92 } 93 } 94 if(selector != null) { 95 int dotIdx = selector.indexOf('.'); 96 if(dotIdx != -1) { 97 String elemtl = selector.substring(0, dotIdx); 98 String classtl = selector.substring(dotIdx+1); 99 this.addClassRule(elemtl, classtl, sr, ancestorSelectors); 100 } 101 else { 102 int poundIdx = selector.indexOf('#'); 103 if(poundIdx != -1) { 104 String elemtl = selector.substring(0, poundIdx); 105 String idtl = selector.substring(poundIdx+1); 106 this.addIdRule(elemtl, idtl, sr, ancestorSelectors); 107 } 108 else { 109 String elemtl = selector; 110 this.addElementRule(elemtl, sr, ancestorSelectors); 111 } 112 } 113 } 114 } 115 } 118 else if(rule instanceof CSSImportRule) { 119 CSSImportRule importRule = (CSSImportRule) rule; 120 if(CSSUtilities.matchesMedia(importRule.getMedia(), document.getHtmlRendererContext())) { 121 String href = importRule.getHref(); 122 String styleHref = styleSheet.getHref(); 123 String baseHref = styleHref == null ? this.document.getBaseURI() : styleHref; 124 CSSStyleSheet sheet = CSSUtilities.parse(href, this.document, baseHref, false); 125 if(sheet != null) { 126 this.addStyleSheet(sheet); 127 } 128 } 129 } 130 } 131 } 132 133 private final void addClassRule(String elemtl, String classtl, CSSStyleRule styleRule, ArrayList ancestorSelectors) { 134 Map classMap = (Map) this.classMapsByElement.get(elemtl); 135 if(classMap == null) { 136 classMap = new HashMap(); 137 this.classMapsByElement.put(elemtl, classMap); 138 } 139 Collection rules = (Collection) classMap.get(classtl); 140 if(rules == null) { 141 rules = new LinkedList(); 142 classMap.put(classtl, rules); 143 } 144 rules.add(new StyleRuleInfo(ancestorSelectors, styleRule)); 145 } 146 147 private final void addIdRule(String elemtl, String idtl, CSSStyleRule styleRule, ArrayList ancestorSelectors) { 148 Map idsMap = (Map) this.idMapsByElement.get(elemtl); 149 if(idsMap == null) { 150 idsMap = new HashMap(); 151 this.idMapsByElement.put(elemtl, idsMap); 152 } 153 Collection rules = (Collection) idsMap.get(idtl); 154 if(rules == null) { 155 rules = new LinkedList(); 156 idsMap.put(idtl, rules); 157 } 158 rules.add(new StyleRuleInfo(ancestorSelectors, styleRule)); 159 } 160 161 private final void addElementRule(String elemtl, CSSStyleRule styleRule, ArrayList ancestorSelectors) { 162 Collection rules = (Collection) this.rulesByElement.get(elemtl); 163 if(rules == null) { 164 rules = new LinkedList(); 165 this.rulesByElement.put(elemtl, rules); 166 } 167 rules.add(new StyleRuleInfo(ancestorSelectors, styleRule)); 168 } 169 170 171 public final Collection getStyleDeclarations(HTMLElementImpl element, String elementName, String elementId, String className) { 172 Collection styleDeclarations = null; 173 String elementTL = elementName.toLowerCase(); 174 Collection elementRules = (Collection) this.rulesByElement.get(elementTL); 175 if(elementRules != null) { 176 Iterator i = elementRules.iterator(); 177 while(i.hasNext()) { 178 StyleRuleInfo styleRuleInfo = (StyleRuleInfo) i.next(); 179 if(styleRuleInfo.matches(element)) { 180 CSSStyleRule styleRule = styleRuleInfo.styleRule; 181 if(styleDeclarations == null) { 182 styleDeclarations = new LinkedList(); 183 } 184 styleDeclarations.add(styleRule.getStyle()); 185 } 186 else { 187 } 188 } 189 } 190 elementRules = (Collection) this.rulesByElement.get("*"); 191 if(elementRules != null) { 192 Iterator i = elementRules.iterator(); 193 while(i.hasNext()) { 194 StyleRuleInfo styleRuleInfo = (StyleRuleInfo) i.next(); 195 if(styleRuleInfo.matches(element)) { 196 CSSStyleRule styleRule = styleRuleInfo.styleRule; 197 if(styleDeclarations == null) { 198 styleDeclarations = new LinkedList(); 199 } 200 styleDeclarations.add(styleRule.getStyle()); 201 } 202 } 203 } 204 if(className != null) { 205 String classNameTL = className.toLowerCase(); 206 Map classMaps = (Map) this.classMapsByElement.get(elementTL); 207 if(classMaps != null) { 208 Collection classRules = (Collection) classMaps.get(classNameTL); 209 if(classRules != null) { 210 Iterator i = classRules.iterator(); 211 while(i.hasNext()) { 212 StyleRuleInfo styleRuleInfo = (StyleRuleInfo) i.next(); 213 if(styleRuleInfo.matches(element)) { 214 CSSStyleRule styleRule = styleRuleInfo.styleRule; 215 if(styleDeclarations == null) { 216 styleDeclarations = new LinkedList(); 217 } 218 styleDeclarations.add(styleRule.getStyle()); 219 } 220 } 221 } 222 } 223 classMaps = (Map) this.classMapsByElement.get("*"); 224 if(classMaps != null) { 225 Collection classRules = (Collection) classMaps.get(classNameTL); 226 if(classRules != null) { 227 Iterator i = classRules.iterator(); 228 while(i.hasNext()) { 229 StyleRuleInfo styleRuleInfo = (StyleRuleInfo) i.next(); 230 if(styleRuleInfo.matches(element)) { 231 CSSStyleRule styleRule = styleRuleInfo.styleRule; 232 if(styleDeclarations == null) { 233 styleDeclarations = new LinkedList(); 234 } 235 styleDeclarations.add(styleRule.getStyle()); 236 } 237 } 238 } 239 } 240 } 241 if(elementId != null) { 242 Map idMaps = (Map) this.idMapsByElement.get(elementTL); 243 if(idMaps != null) { 244 String elementIdTL = elementId.toLowerCase(); 245 Collection idRules = (Collection) idMaps.get(elementIdTL); 246 if(idRules != null) { 247 Iterator i = idRules.iterator(); 248 while(i.hasNext()) { 249 StyleRuleInfo styleRuleInfo = (StyleRuleInfo) i.next(); 250 if(styleRuleInfo.matches(element)) { 251 CSSStyleRule styleRule = styleRuleInfo.styleRule; 252 if(styleDeclarations == null) { 253 styleDeclarations = new LinkedList(); 254 } 255 styleDeclarations.add(styleRule.getStyle()); 256 } 257 } 258 } 259 } 260 idMaps = (Map) this.idMapsByElement.get("*"); 261 if(idMaps != null) { 262 String elementIdTL = elementId.toLowerCase(); 263 Collection idRules = (Collection) idMaps.get(elementIdTL); 264 if(idRules != null) { 265 Iterator i = idRules.iterator(); 266 while(i.hasNext()) { 267 StyleRuleInfo styleRuleInfo = (StyleRuleInfo) i.next(); 268 if(styleRuleInfo.matches(element)) { 269 CSSStyleRule styleRule = styleRuleInfo.styleRule; 270 if(styleDeclarations == null) { 271 styleDeclarations = new LinkedList(); 272 } 273 styleDeclarations.add(styleRule.getStyle()); 274 } 275 } 276 } 277 } 278 } 279 return styleDeclarations; 280 } 281 282 private static class StyleRuleInfo { 283 private final CSSStyleRule styleRule; 284 private final ArrayList ancestorSelectors; 285 286 290 public StyleRuleInfo(ArrayList selectors, CSSStyleRule rule) { 291 super(); 292 ancestorSelectors = selectors; 293 styleRule = rule; 294 } 295 296 public boolean matches(HTMLElementImpl element) { 297 ArrayList as = this.ancestorSelectors; 299 if(as == null) { 300 return true; 301 } 302 HTMLElementImpl currentElement = element; 303 int size = as.size(); 304 for(int i = size; --i >= 0;) { 305 String selector = (String ) as.get(i); 306 int dotIdx = selector.indexOf('.'); 307 if(dotIdx != -1) { 308 String elemtl = selector.substring(0, dotIdx); 309 String classtl = selector.substring(dotIdx+1); 310 HTMLElementImpl ancestor = currentElement.getAncestorWithClass(elemtl, classtl); 311 if(ancestor == null) { 312 return false; 313 } 314 currentElement = ancestor; 315 } 316 else { 317 int poundIdx = selector.indexOf('#'); 318 if(poundIdx != -1) { 319 String elemtl = selector.substring(0, poundIdx); 320 String idtl = selector.substring(poundIdx+1); 321 HTMLElementImpl ancestor = currentElement.getAncestorWithId(elemtl, idtl); 322 if(ancestor == null) { 323 return false; 324 } 325 currentElement = ancestor; 326 } 327 else { 328 String elemtl = selector; 329 HTMLElementImpl ancestor = currentElement.getAncestor(elemtl); 330 if(ancestor == null) { 331 return false; 332 } 333 currentElement = ancestor; 334 } 335 } 336 } 337 return true; 338 } 339 } 340 341 } 342 | Popular Tags |