001: /*
002: * Copyright 2006 Ethan Nicholas. All rights reserved.
003: * Use is subject to license terms.
004: */
005: package jaxx.css;
006:
007: import java.awt.event.*;
008: import java.io.*;
009: import java.lang.reflect.*;
010: import java.util.*;
011:
012: import jaxx.*;
013: import jaxx.compiler.*;
014: import jaxx.parser.*;
015: import jaxx.parser.SimpleNode;
016: import jaxx.reflect.*;
017: import jaxx.tags.*;
018: import jaxx.types.*;
019:
020: public class Stylesheet implements Serializable {
021: private Rule[] rules;
022:
023: public Stylesheet() {
024: rules = new Rule[0];
025: }
026:
027: public Stylesheet(Rule[] rules) {
028: this .rules = rules;
029: Arrays.sort(rules);
030: }
031:
032: public Rule[] getRules() {
033: return rules;
034: }
035:
036: public void add(Rule newRule) {
037: Rule[] oldRules = rules;
038: rules = new Rule[oldRules.length + 1];
039: System.arraycopy(oldRules, 0, rules, 0, oldRules.length);
040: rules[rules.length - 1] = newRule;
041: Arrays.sort(rules);
042: }
043:
044: public void add(Rule[] newRules) {
045: Rule[] oldRules = rules;
046: rules = new Rule[oldRules.length + newRules.length];
047: System.arraycopy(oldRules, 0, rules, 0, oldRules.length);
048: System.arraycopy(newRules, 0, rules, oldRules.length,
049: newRules.length);
050: Arrays.sort(rules);
051: }
052:
053: public void applyTo(CompiledObject object, JAXXCompiler compiler,
054: Stylesheet overrides) throws CompilerException {
055: Map/*<String, String>*/overriddenProperties;
056: if (overrides != null)
057: overriddenProperties = overrides.getApplicableProperties(
058: object, compiler);
059: else
060: overriddenProperties = null;
061:
062: Map/*<String, String>*/properties = getApplicableProperties(
063: object, compiler);
064: if (properties != null) {
065: if (overriddenProperties != null)
066: properties.keySet().removeAll(
067: overriddenProperties.keySet());
068: DefaultObjectHandler handler = TagManager
069: .getTagHandler(object.getObjectClass());
070: Iterator/*<Map.Entry<String, String>>*/i = properties
071: .entrySet().iterator();
072: while (i.hasNext()) {
073: Map.Entry/*<String, String>*/e = (Map.Entry) i.next();
074: String value = (String) e.getValue();
075: if (value == Rule.INLINE_ATTRIBUTE
076: || value == Rule.DATA_BINDING)
077: continue;
078: handler.setAttribute(object, (String) e.getKey(),
079: (String) e.getValue(), false, compiler);
080: }
081: }
082:
083: Rule[] pseudoClasses = getApplicablePseudoClasses(object,
084: compiler);
085: if (pseudoClasses != null) {
086: Map/*<String, Map<String, String>>*/combinedPseudoClasses = new LinkedHashMap/*<String, Map<String, Object>>*/();
087: for (int i = 0; i < pseudoClasses.length; i++) {
088: Selector[] selectors = pseudoClasses[i].getSelectors();
089: for (int j = 0; j < selectors.length; j++) {
090: if (selectors[j].appliesTo(object) == Selector.PSEUDOCLASS_APPLIES) {
091: properties = pseudoClasses[i].getProperties();
092: String pseudoClass = selectors[j]
093: .getPseudoClass();
094: // TODO: overrides by downstream pseudoclasses are not handled
095: Map/*<String, String>*/combinedProperties = (Map) combinedPseudoClasses
096: .get(pseudoClass);
097: if (combinedProperties == null) {
098: combinedProperties = new HashMap/*<String, String>*/();
099: combinedPseudoClasses.put(pseudoClass,
100: combinedProperties);
101: }
102: combinedProperties.putAll(properties);
103: }
104: }
105: }
106:
107: int count = 0;
108: Iterator/*<Map.Entry<String, Map<String, String>>>*/j = combinedPseudoClasses
109: .entrySet().iterator();
110: while (j.hasNext()) {
111: Map.Entry/*<String, Map<String, String>>*/e = (Map.Entry) j
112: .next();
113: applyPseudoClass((String) e.getKey(), (Map) e
114: .getValue(), object, compiler, count++);
115: }
116: }
117: }
118:
119: /** Replaces all references to the variable "object" with the actual object ID. */
120: private String replaceObjectReferences(String code, String id)
121: throws CompilerException {
122: JavaParser p = new JavaParser(new StringReader(code + ";"));
123: p.Expression();
124: SimpleNode node = p.popNode();
125: scanNode(node, id);
126: return node.getText();
127: }
128:
129: private void scanNode(SimpleNode node, String id) {
130: if (node.getId() == JavaParserTreeConstants.JJTNAME) {
131: String name = node.getText();
132: if (name.equals("object")
133: || (name.indexOf(".") != -1 && name.substring(0,
134: name.indexOf(".")).trim().equals("object")))
135: node.firstToken.image = id;
136: } else {
137: int count = node.jjtGetNumChildren();
138: for (int i = 0; i < count; i++)
139: scanNode(node.getChild(i), id);
140: }
141: }
142:
143: private void compilePseudoClassAdd(String pseudoClass,
144: CompiledObject object, String propertyCode,
145: JAXXCompiler compiler) throws CompilerException {
146: if (pseudoClass.equals("mouseover")) {
147: try {
148: MethodDescriptor addMouseListener = object
149: .getObjectClass()
150: .getMethodDescriptor(
151: "addMouseListener",
152: new ClassDescriptor[] { ClassDescriptorLoader
153: .getClassDescriptor(MouseListener.class) });
154: object
155: .addEventHandler(
156: "style." + pseudoClass + ".add",
157: addMouseListener,
158: ClassDescriptorLoader
159: .getClassDescriptor(
160: MouseListener.class)
161: .getMethodDescriptor(
162: "mouseEntered",
163: new ClassDescriptor[] { ClassDescriptorLoader
164: .getClassDescriptor(MouseEvent.class) }),
165: propertyCode, compiler);
166: } catch (NoSuchMethodException e) {
167: compiler
168: .reportError("mouseover pseudoclass cannot be applied to object "
169: + object.getObjectClass().getName()
170: + " (no addMouseListener method)");
171: }
172: } else if (pseudoClass.equals("mouseout")) {
173: try {
174: MethodDescriptor addMouseListener = object
175: .getObjectClass()
176: .getMethodDescriptor(
177: "addMouseListener",
178: new ClassDescriptor[] { ClassDescriptorLoader
179: .getClassDescriptor(MouseListener.class) });
180: object
181: .addEventHandler(
182: "style." + pseudoClass + ".add",
183: addMouseListener,
184: ClassDescriptorLoader
185: .getClassDescriptor(
186: MouseListener.class)
187: .getMethodDescriptor(
188: "mouseExited",
189: new ClassDescriptor[] { ClassDescriptorLoader
190: .getClassDescriptor(MouseEvent.class) }),
191: propertyCode, compiler);
192: compiler.initDataBindings.append("{" + propertyCode
193: + "}");
194: } catch (NoSuchMethodException e) {
195: compiler
196: .reportError("mouseout pseudoclass cannot be applied to object "
197: + object.getObjectClass().getName()
198: + " (no addMouseListener method)");
199: }
200: } else if (pseudoClass.equals("mousedown")) {
201: try {
202: MethodDescriptor addMouseListener = object
203: .getObjectClass()
204: .getMethodDescriptor(
205: "addMouseListener",
206: new ClassDescriptor[] { ClassDescriptorLoader
207: .getClassDescriptor(MouseListener.class) });
208: object
209: .addEventHandler(
210: "style." + pseudoClass + ".add",
211: addMouseListener,
212: ClassDescriptorLoader
213: .getClassDescriptor(
214: MouseListener.class)
215: .getMethodDescriptor(
216: "mousePressed",
217: new ClassDescriptor[] { ClassDescriptorLoader
218: .getClassDescriptor(MouseEvent.class) }),
219: propertyCode, compiler);
220: } catch (NoSuchMethodException e) {
221: compiler
222: .reportError("mousedown pseudoclass cannot be applied to object "
223: + object.getObjectClass().getName()
224: + " (no addMouseListener method)");
225: }
226: } else if (pseudoClass.equals("mouseup")) {
227: try {
228: MethodDescriptor addMouseListener = object
229: .getObjectClass()
230: .getMethodDescriptor(
231: "addMouseListener",
232: new ClassDescriptor[] { ClassDescriptorLoader
233: .getClassDescriptor(MouseListener.class) });
234: object
235: .addEventHandler(
236: "style." + pseudoClass + ".add",
237: addMouseListener,
238: ClassDescriptorLoader
239: .getClassDescriptor(
240: MouseListener.class)
241: .getMethodDescriptor(
242: "mouseReleased",
243: new ClassDescriptor[] { ClassDescriptorLoader
244: .getClassDescriptor(MouseEvent.class) }),
245: propertyCode, compiler);
246: compiler.initDataBindings.append("{" + propertyCode
247: + "}");
248: } catch (NoSuchMethodException e) {
249: compiler
250: .reportError("mouseup pseudoclass cannot be applied to object "
251: + object.getObjectClass().getName()
252: + " (no addMouseListener method)");
253: }
254: } else if (pseudoClass.startsWith("{")) {
255: pseudoClass = pseudoClass.substring(1,
256: pseudoClass.length() - 1).trim();
257: pseudoClass = replaceObjectReferences(pseudoClass, object
258: .getJavaCode());
259: String dest = object.getId() + ".style." + pseudoClass
260: + ".add";
261: String destCode = TypeManager.getJavaCode(dest);
262: if (compiler.processDataBinding.length() > 0)
263: compiler.processDataBinding.append("else ");
264: compiler.processDataBinding.append("if ($dest.equals("
265: + destCode + ")) { if (" + pseudoClass + ") { "
266: + propertyCode + "} }");
267: new DataSource(dest, pseudoClass, compiler)
268: .compile("new jaxx.runtime.DataBindingListener("
269: + compiler.getRootObject().getJavaCode()
270: + ", " + destCode + ")");
271: compiler.initDataBindings.append("applyDataBinding("
272: + destCode + ");");
273: } else
274: throw new IllegalArgumentException(
275: "unrecognized pseudoclass: " + pseudoClass);
276: }
277:
278: private void compilePseudoClassRemove(String pseudoClass,
279: CompiledObject object, String propertyCode,
280: JAXXCompiler compiler) throws CompilerException {
281: if (pseudoClass.equals("mouseover")) {
282: try {
283: MethodDescriptor addMouseListener = object
284: .getObjectClass()
285: .getMethodDescriptor(
286: "addMouseListener",
287: new ClassDescriptor[] { ClassDescriptorLoader
288: .getClassDescriptor(MouseListener.class) });
289: object
290: .addEventHandler(
291: "style." + pseudoClass + ".remove",
292: addMouseListener,
293: ClassDescriptorLoader
294: .getClassDescriptor(
295: MouseListener.class)
296: .getMethodDescriptor(
297: "mouseExited",
298: new ClassDescriptor[] { ClassDescriptorLoader
299: .getClassDescriptor(MouseEvent.class) }),
300: propertyCode, compiler);
301: } catch (NoSuchMethodException e) {
302: compiler
303: .reportError("mouseover pseudoclass cannot be applied to object "
304: + object.getObjectClass().getName()
305: + " (no addMouseListener method)");
306: }
307: } else if (pseudoClass.equals("mouseout")) {
308: try {
309: MethodDescriptor addMouseListener = object
310: .getObjectClass()
311: .getMethodDescriptor(
312: "addMouseListener",
313: new ClassDescriptor[] { ClassDescriptorLoader
314: .getClassDescriptor(MouseListener.class) });
315: object
316: .addEventHandler(
317: "style." + pseudoClass + ".remove",
318: addMouseListener,
319: ClassDescriptorLoader
320: .getClassDescriptor(
321: MouseListener.class)
322: .getMethodDescriptor(
323: "mouseEntered",
324: new ClassDescriptor[] { ClassDescriptorLoader
325: .getClassDescriptor(MouseEvent.class) }),
326: propertyCode, compiler);
327: } catch (NoSuchMethodException e) {
328: compiler
329: .reportError("mouseout pseudoclass cannot be applied to object "
330: + object.getObjectClass().getName()
331: + " (no addMouseListener method)");
332: }
333: } else if (pseudoClass.equals("mousedown")) {
334: try {
335: MethodDescriptor addMouseListener = object
336: .getObjectClass()
337: .getMethodDescriptor(
338: "addMouseListener",
339: new ClassDescriptor[] { ClassDescriptorLoader
340: .getClassDescriptor(MouseListener.class) });
341: object
342: .addEventHandler(
343: "style." + pseudoClass + ".remove",
344: addMouseListener,
345: ClassDescriptorLoader
346: .getClassDescriptor(
347: MouseListener.class)
348: .getMethodDescriptor(
349: "mouseReleased",
350: new ClassDescriptor[] { ClassDescriptorLoader
351: .getClassDescriptor(MouseEvent.class) }),
352: propertyCode, compiler);
353: } catch (NoSuchMethodException e) {
354: compiler
355: .reportError("mousedown pseudoclass cannot be applied to object "
356: + object.getObjectClass().getName()
357: + " (no addMouseListener method)");
358: }
359: } else if (pseudoClass.equals("mouseup")) {
360: try {
361: MethodDescriptor addMouseListener = object
362: .getObjectClass()
363: .getMethodDescriptor(
364: "addMouseListener",
365: new ClassDescriptor[] { ClassDescriptorLoader
366: .getClassDescriptor(MouseListener.class) });
367: object
368: .addEventHandler(
369: "style." + pseudoClass + ".remove",
370: addMouseListener,
371: ClassDescriptorLoader
372: .getClassDescriptor(
373: MouseListener.class)
374: .getMethodDescriptor(
375: "mousePressed",
376: new ClassDescriptor[] { ClassDescriptorLoader
377: .getClassDescriptor(MouseEvent.class) }),
378: propertyCode, compiler);
379: } catch (NoSuchMethodException e) {
380: compiler
381: .reportError("mouseup pseudoclass cannot be applied to object "
382: + object.getObjectClass().getName()
383: + " (no addMouseListener method)");
384: }
385: } else if (pseudoClass.startsWith("{")) {
386: pseudoClass = pseudoClass.substring(1,
387: pseudoClass.length() - 1).trim();
388: pseudoClass = replaceObjectReferences(pseudoClass, object
389: .getJavaCode());
390: String dest = object.getId() + ".style." + pseudoClass
391: + ".remove";
392: String destCode = TypeManager.getJavaCode(dest);
393: if (compiler.processDataBinding.length() > 0)
394: compiler.processDataBinding.append("else ");
395: compiler.processDataBinding.append("if ($dest.equals("
396: + destCode + ")) { if (" + invert(pseudoClass)
397: + ") { " + propertyCode + "} }");
398: new DataSource(dest, pseudoClass, compiler)
399: .compile("new jaxx.runtime.DataBindingListener("
400: + compiler.getRootObject().getJavaCode()
401: + ", " + destCode + ")");
402: compiler.initDataBindings.append("applyDataBinding("
403: + destCode + ");");
404: } else
405: throw new IllegalArgumentException(
406: "unrecognized pseudoclass: " + pseudoClass);
407: }
408:
409: private String invert(String javaCode) {
410: javaCode = javaCode.trim();
411: if (javaCode.startsWith("!"))
412: return javaCode.substring(1);
413: else
414: return "!(" + javaCode + ")";
415: }
416:
417: private String unwrap(ClassDescriptor type, String valueCode) {
418: if (type == ClassDescriptorLoader
419: .getClassDescriptor(boolean.class))
420: return "((java.lang.Boolean) " + valueCode
421: + ").booleanValue()";
422: else if (type == ClassDescriptorLoader
423: .getClassDescriptor(byte.class))
424: return "((java.lang.Byte) " + valueCode + ").byteValue()";
425: else if (type == ClassDescriptorLoader
426: .getClassDescriptor(short.class))
427: return "((java.lang.Short) " + valueCode + ").shortValue()";
428: else if (type == ClassDescriptorLoader
429: .getClassDescriptor(int.class))
430: return "((java.lang.Integer) " + valueCode + ").intValue()";
431: else if (type == ClassDescriptorLoader
432: .getClassDescriptor(long.class))
433: return "((java.lang.Long) " + valueCode + ").longValue()";
434: else if (type == ClassDescriptorLoader
435: .getClassDescriptor(float.class))
436: return "((java.lang.Float) " + valueCode + ").floatValue()";
437: else if (type == ClassDescriptorLoader
438: .getClassDescriptor(double.class))
439: return "((java.lang.Double) " + valueCode
440: + ").doubleValue()";
441: else if (type == ClassDescriptorLoader
442: .getClassDescriptor(char.class))
443: return "((java.lang.Character) " + valueCode
444: + ").charValue()";
445: else
446: return valueCode;
447: }
448:
449: protected void applyPseudoClass(String pseudoClass,
450: Map/*<String, String>*/properties, CompiledObject object,
451: JAXXCompiler compiler, int priority)
452: throws CompilerException {
453: if (pseudoClass.indexOf("[") != -1)
454: pseudoClass = pseudoClass.substring(0, pseudoClass
455: .indexOf("["));
456: final StringBuffer buffer = new StringBuffer();
457: CompiledObject bufferObject = new CompiledObject(
458: object.getId(), object.getJavaCode(), object
459: .getObjectClass(), compiler, true) {
460: public void appendInitializationCode(String code) {
461: buffer.append(code);
462: }
463:
464: public void registerDataBinding(String src,
465: String property, String assignment,
466: JAXXCompiler compiler) throws CompilerException {
467: buffer.append(assignment);
468: }
469: };
470:
471: DefaultObjectHandler handler = TagManager.getTagHandler(object
472: .getObjectClass());
473: boolean valueDeclared = false;
474: Iterator/*<Map.Entry<String, String>>*/i = properties
475: .entrySet().iterator();
476: while (i.hasNext()) {
477: Map.Entry/*<String, String>*/e = (Map.Entry) i.next();
478: String property = (String) e.getKey();
479: ClassDescriptor type = handler.getPropertyType(object,
480: property, compiler);
481: String dataBinding = compiler.processDataBindings(
482: (String) e.getValue(), type);
483: String valueCode;
484: if (dataBinding != null) {
485: valueCode = "new jaxx.runtime.css.DataBinding("
486: + TypeManager.getJavaCode(object.getId() + "."
487: + property + "." + priority) + ")";
488: new jaxx.compiler.DataBinding(
489: dataBinding,
490: object.getId() + "." + property + "."
491: + priority,
492: handler.getSetPropertyCode(
493: object.getJavaCode(), property, "("
494: + JAXXCompiler
495: .getCanonicalName(type)
496: + ") " + dataBinding, compiler),
497: compiler).compile(false);
498: } else {
499: try {
500: Class typeClass = type != null ? ClassDescriptorLoader
501: .getClass(type.getName(), type
502: .getClassLoader())
503: : null;
504: valueCode = TypeManager.getJavaCode(TypeManager
505: .convertFromString((String) e.getValue(),
506: typeClass));
507: } catch (ClassNotFoundException ex) {
508: compiler.reportError("could not find class "
509: + type.getName());
510: return;
511: }
512: }
513: if (!valueDeclared) {
514: buffer.append("java.lang.Object ");
515: valueDeclared = true;
516: }
517: buffer
518: .append("value = jaxx.runtime.css.Pseudoclasses.applyProperty("
519: + compiler.getOutputClassName()
520: + ".this, "
521: + object.getJavaCode()
522: + ", "
523: + TypeManager.getJavaCode(property)
524: + ", "
525: + valueCode
526: + ", jaxx.runtime.css.Pseudoclasses.wrap("
527: + handler.getGetPropertyCode(object
528: .getJavaCode(), property, compiler)
529: + "), "
530: + priority
531: + ");"
532: + JAXXCompiler.getLineSeparator());
533: buffer
534: .append("if (!(value instanceof jaxx.runtime.css.DataBinding)) {"
535: + JAXXCompiler.getLineSeparator());
536: String unwrappedValue = unwrap(type, "value");
537: buffer.append(" "
538: + handler.getSetPropertyCode(object.getJavaCode(),
539: property, "("
540: + JAXXCompiler
541: .getCanonicalName(type)
542: + ") " + unwrappedValue, compiler)
543: + JAXXCompiler.getLineSeparator());
544: buffer.append("}" + JAXXCompiler.getLineSeparator());
545: }
546:
547: if (pseudoClass.equals("focused"))
548: pseudoClass = "{ object.hasFocus() }";
549: else if (pseudoClass.equals("unfocused"))
550: pseudoClass = "{ !object.hasFocus() }";
551: else if (pseudoClass.equals("enabled"))
552: pseudoClass = "{ object.isEnabled() }";
553: else if (pseudoClass.equals("disabled"))
554: pseudoClass = "{ !object.isEnabled() }";
555: else if (pseudoClass.equals("selected"))
556: pseudoClass = "{ object.isSelected() }";
557: else if (pseudoClass.equals("deselected"))
558: pseudoClass = "{ !object.isSelected() }";
559:
560: compilePseudoClassAdd(pseudoClass, object, buffer.toString(),
561: compiler);
562:
563: buffer.setLength(0);
564: valueDeclared = false;
565: i = properties.entrySet().iterator();
566: while (i.hasNext()) {
567: Map.Entry/*<String, String>*/e = (Map.Entry) i.next();
568: String property = (String) e.getKey();
569: ClassDescriptor type = handler.getPropertyType(object,
570: property, compiler);
571: String dataBinding = compiler.processDataBindings(
572: (String) e.getValue(), type);
573: String valueCode;
574: if (dataBinding != null) {
575: valueCode = "new jaxx.runtime.css.DataBinding("
576: + TypeManager.getJavaCode(object.getId() + "."
577: + property + "." + priority) + ")";
578: new jaxx.compiler.DataBinding(
579: dataBinding,
580: object.getId() + "." + property + "."
581: + priority,
582: handler.getSetPropertyCode(
583: object.getJavaCode(), property, "("
584: + JAXXCompiler
585: .getCanonicalName(type)
586: + ") " + dataBinding, compiler),
587: compiler).compile(false);
588: } else {
589: try {
590: Class typeClass = type != null ? ClassDescriptorLoader
591: .getClass(type.getName(), type
592: .getClassLoader())
593: : null;
594: valueCode = TypeManager.getJavaCode(TypeManager
595: .convertFromString((String) e.getValue(),
596: typeClass));
597: } catch (ClassNotFoundException ex) {
598: compiler.reportError("could not find class "
599: + type.getName());
600: return;
601: }
602: }
603: if (!valueDeclared) {
604: buffer.append("java.lang.Object ");
605: valueDeclared = true;
606: }
607: buffer
608: .append("value = jaxx.runtime.css.Pseudoclasses.removeProperty("
609: + compiler.getOutputClassName()
610: + ".this, "
611: + object.getJavaCode()
612: + ", "
613: + TypeManager.getJavaCode(property)
614: + ", "
615: + valueCode
616: + ", jaxx.runtime.css.Pseudoclasses.wrap("
617: + handler.getGetPropertyCode(object
618: .getJavaCode(), property, compiler)
619: + "), "
620: + priority
621: + ");"
622: + JAXXCompiler.getLineSeparator());
623: buffer
624: .append("if (!(value instanceof jaxx.runtime.css.DataBinding)) {"
625: + JAXXCompiler.getLineSeparator());
626: String unwrappedValue = unwrap(type, "value");
627: buffer.append(" "
628: + handler.getSetPropertyCode(object.getJavaCode(),
629: property, "("
630: + JAXXCompiler
631: .getCanonicalName(type)
632: + ") " + unwrappedValue, compiler)
633: + JAXXCompiler.getLineSeparator());
634: buffer.append("}" + JAXXCompiler.getLineSeparator());
635: }
636:
637: compilePseudoClassRemove(pseudoClass, object,
638: buffer.toString(), compiler);
639: }
640:
641: public Map/*<String, String>*/getApplicableProperties(
642: CompiledObject object, JAXXCompiler compiler)
643: throws CompilerException {
644: DefaultObjectHandler handler = TagManager.getTagHandler(object
645: .getObjectClass());
646: Map/*<String, String>*/result = null;
647: for (int i = 0; i < rules.length; i++) {
648: int apply = rules[i].appliesTo(object);
649: if (apply == Selector.ALWAYS_APPLIES
650: || apply == Selector.ALWAYS_APPLIES_INHERIT_ONLY) {
651: if (result == null)
652: result = new HashMap/*<String, String>*/();
653: Iterator/*<Map.Entry<String, String>>*/entries = rules[i]
654: .getProperties().entrySet().iterator();
655: while (entries.hasNext()) {
656: Map.Entry/*<String, String>*/entry = (Map.Entry) entries
657: .next();
658: String property = (String) entry.getKey();
659: if (apply == Selector.ALWAYS_APPLIES
660: || handler.isPropertyInherited(property))
661: result.put(property, entry.getValue());
662: }
663: }
664: }
665: return result;
666: }
667:
668: public Rule[] getApplicablePseudoClasses(CompiledObject object,
669: JAXXCompiler compiler) throws CompilerException {
670: List/*<Rule>*/result = null;
671: for (int i = 0; i < rules.length; i++) {
672: if (rules[i].appliesTo(object) == Selector.PSEUDOCLASS_APPLIES) {
673: if (result == null)
674: result = new ArrayList/*<Rule>*/();
675: result.add(rules[i]);
676: }
677: }
678: return result != null ? (Rule[]) result.toArray(new Rule[result
679: .size()]) : null;
680: }
681:
682: public String toString() {
683: return "Stylesheet" + Arrays.asList(rules);
684: }
685: }
|