1 4 5 9 10 package org.openlaszlo.compiler; 11 import java.io.*; 12 import java.util.*; 13 import org.apache.oro.text.regex.*; 14 import org.jdom.Document; 15 import org.jdom.Attribute; 16 import org.jdom.Element; 17 import org.jdom.Namespace; 18 import org.jdom.output.XMLOutputter; 19 import org.jdom.input.SAXBuilder; 20 import org.jdom.JDOMException; 21 import org.openlaszlo.xml.internal.Schema; 22 import org.openlaszlo.xml.internal.XMLUtils; 23 import org.openlaszlo.utils.ChainedException; 24 import org.openlaszlo.server.*; 25 26 27 public class ViewSchema extends Schema { 28 private static final Set sInputTextElements = new HashSet(); 29 private static final Set sHTMLContentElements = new HashSet(); 30 31 32 private final String SCHEMA_PATH = LPS.HOME() + File.separator + 33 "WEB-INF" + File.separator + 34 "lps" + File.separator + 35 "schema" + File.separator + "lzx.rng"; 36 37 private Document schemaDOM = null; 38 39 private static Document sCachedSchemaDOM; 40 private static long sCachedSchemaLastModified; 41 42 43 private static final Map sAttributeTypes = new HashMap(); 44 45 46 private static final Map sRNGtoLPSTypeMap = new HashMap(); 47 48 49 private static final Set sMouseEventAttributes; 50 51 55 private final Map mClassMap = new HashMap(); 56 57 58 public static final Type EXPRESSION_TYPE = newType("expression"); 59 public static final Type REFERENCE_TYPE = newType("reference"); 60 61 public static final Type EVENT_TYPE = newType("script"); 62 63 64 public static final Type SETTER_TYPE = newType("setter"); 65 66 67 public static final Type TOKEN_TYPE = newType("token"); 68 public static final Type COLOR_TYPE = newType("color"); 69 public static final Type NUMBER_EXPRESSION_TYPE = newType("numberExpression"); 70 public static final Type SIZE_EXPRESSION_TYPE = newType("sizeExpression"); 71 public static final Type CSS_TYPE = newType("css"); 72 public static final Type INHERITABLE_BOOLEAN_TYPE = newType("inheritableBoolean"); 73 74 static { 75 sHTMLContentElements.add("text"); 76 sInputTextElements.add("inputtext"); 77 78 sRNGtoLPSTypeMap.put("ID", ID_TYPE); 80 sRNGtoLPSTypeMap.put("anyURI", STRING_TYPE); 81 sRNGtoLPSTypeMap.put("boolean", EXPRESSION_TYPE); 82 sRNGtoLPSTypeMap.put("booleanLiteral", EXPRESSION_TYPE); 83 sRNGtoLPSTypeMap.put("inheritableBooleanLiteral", INHERITABLE_BOOLEAN_TYPE); 84 sRNGtoLPSTypeMap.put("color", COLOR_TYPE); 85 sRNGtoLPSTypeMap.put("colorLiteral", COLOR_TYPE); 86 sRNGtoLPSTypeMap.put("css", CSS_TYPE); 87 sRNGtoLPSTypeMap.put("double", NUMBER_TYPE); 88 sRNGtoLPSTypeMap.put("enumeration", STRING_TYPE); 89 sRNGtoLPSTypeMap.put("expression", EXPRESSION_TYPE); 90 sRNGtoLPSTypeMap.put("float", NUMBER_TYPE); 91 sRNGtoLPSTypeMap.put("integer", NUMBER_TYPE); 92 sRNGtoLPSTypeMap.put("number", NUMBER_TYPE); 93 sRNGtoLPSTypeMap.put("numberLiteral", NUMBER_TYPE); 94 sRNGtoLPSTypeMap.put("numberExpression", NUMBER_EXPRESSION_TYPE); 95 sRNGtoLPSTypeMap.put("propertyPath", STRING_TYPE); 96 sRNGtoLPSTypeMap.put("reference", REFERENCE_TYPE); 97 sRNGtoLPSTypeMap.put("script", EVENT_TYPE); 98 sRNGtoLPSTypeMap.put("size", SIZE_EXPRESSION_TYPE); 99 sRNGtoLPSTypeMap.put("sizeLiteral", SIZE_EXPRESSION_TYPE); 100 sRNGtoLPSTypeMap.put("sizeExpression", SIZE_EXPRESSION_TYPE); 101 sRNGtoLPSTypeMap.put("string", STRING_TYPE); 102 sRNGtoLPSTypeMap.put("token", TOKEN_TYPE); 103 sRNGtoLPSTypeMap.put("opacity", NUMBER_TYPE); 104 105 String [] mouseEventAttributes = { 107 "onclick", "ondblclick", "onmousedown", "onmouseup", "onmouseover", 108 "onmousemove", "onmouseout"}; 109 String [] eventAttributes = { 110 "onkeypress", "onstart" , "onstop", 111 "onfocus", "onblur", 112 "onkeydown", "onkeyup", "onsubmit", "onreset", "onselect", 113 "onchange" , "oninit", "onerror", "ondata", "ontimeout", 114 "oncommand" , "onapply" , "onremove"}; 115 setAttributeTypes(mouseEventAttributes, EVENT_TYPE); 116 setAttributeTypes(eventAttributes, EVENT_TYPE); 117 sMouseEventAttributes = new HashSet(Arrays.asList(mouseEventAttributes)); 118 } 119 120 private static final String AUTOINCLUDES_PROPERTY_FILE = 121 LPS.getMiscDirectory() + File.separator + 122 "lzx-autoincludes.properties"; 123 public static final Properties sAutoincludes = new Properties(); 124 125 static { 126 try { 127 InputStream is = new FileInputStream(AUTOINCLUDES_PROPERTY_FILE); 128 try { 129 sAutoincludes.load(is); 130 } finally { 131 is.close(); 132 } 133 } catch (java.io.IOException e) { 134 throw new ChainedException(e); 135 } 136 } 137 138 142 private static void setAttributeTypes(String [] attributes, Type type) { 143 for (int i = 0; i < attributes.length; i++) { 144 sAttributeTypes.put(attributes[i].intern(), type); 145 } 146 } 147 148 public AttributeSpec findSimilarAttribute (String className, String attributeName) { 149 ClassModel info = getClassModel(className); 150 151 if (info != null) { 152 return info.findSimilarAttribute(attributeName); 153 } else { 154 return null; 156 } 157 } 158 159 160 public void setAttributeType (Element elt, String classname, String attrName, AttributeSpec attrspec) { 161 ClassModel classModel = getClassModel(classname); 162 if (classModel == null) { 163 throw new RuntimeException ("undefined class: " + classname); 164 } 165 if (classModel.attributeSpecs.get(attrName) != null) { 166 throw new CompilationError("duplicate definition of attribute " + classname + "." + attrName, elt); 167 } 168 classModel.attributeSpecs.put(attrName, attrspec); 169 170 if (attrName.equals("text")) { 171 classModel.supportsTextAttribute = true; 172 } 173 } 174 175 public void addMethodDeclaration (Element elt, String classname, String methodName, String arglist) { 176 ClassModel classModel = getClassModel(classname); 177 if (classModel == null) { 178 throw new RuntimeException ("undefined class: " + classname); 179 } 180 if (classModel.methods.get(methodName) != null) { 181 throw new CompilationError("duplicate definition of method " + classname + "." + methodName, elt); 182 } 183 classModel.methods.put(methodName, arglist); 184 } 185 186 public String getSuperclassName(String className) { 187 ClassModel model = getClassModel(className); 188 if (model == null) 189 return null; 190 return model.getSuperclassName(); 191 } 192 193 196 public String getBaseClassname(String className) { 197 String ancestor = getSuperclassName(className); 198 String superclass = ancestor; 199 200 while (ancestor != null) { 201 if (ancestor.equals(className)) { 202 throw new CompilationError( 203 "recursive class definition on "+className); 204 } 205 superclass = ancestor; 206 ancestor = getSuperclassName(ancestor); 207 } 208 return superclass; 209 } 210 211 212 AttributeSpec getClassAttribute (String classname, String attrName) { 213 ClassModel info = getClassModel(classname); 215 if (info == null) { 216 return null; 217 } else { 218 return info.getAttribute(attrName); 219 } 220 } 221 222 238 void addAttributeDefs (Element sourceElement, String classname, 239 Element classDef, List attributeDefs) 240 { 241 253 if (!attributeDefs.isEmpty()) { 254 Namespace ns = classDef.getNamespace(); 255 List attrList = new ArrayList(); 256 for (Iterator iter = attributeDefs.iterator(); iter.hasNext();) { 257 AttributeSpec attr = (AttributeSpec) iter.next(); 258 259 268 if (getClassAttribute(classname, attr.name) == null) { 270 Element newAttr = new Element("attribute", ns); 272 newAttr.setAttribute("name", attr.name); 273 292 String attrTypeName = attr.type.toString(); 293 Element datatype; 294 if (attrTypeName.equals("string") || attrTypeName.equals("boolean")) { 295 datatype = new Element("data", ns); 296 datatype.setAttribute("type", attrTypeName); 297 } else { 298 datatype = new Element("ref", ns); 299 datatype.setAttribute("name", attrTypeName); 300 } 301 newAttr.addContent(datatype); 303 Element optional = new Element("optional", ns); 305 optional.addContent(newAttr); 306 if (attr.contentType != attr.NO_CONTENT) { 310 optional = new Element("ref", ns); 311 if (attr.contentType == attr.TEXT_CONTENT) { 312 optional.setAttribute("name", "textContent"); 313 } else if (attr.contentType == attr.HTML_CONTENT) { 314 optional.setAttribute("name", "htmlContent"); 315 } else { 316 throw new RuntimeException ("unknown content type"); 317 } 318 } 319 attrList.add(optional); 320 } else { 321 Type parentType = getAttributeType(classname, attr.name); 323 324 if (parentType != attr.type) { 325 throw new CompilationError(sourceElement, attr.name, new Throwable ("In class '" + classname + "' attribute '"+ attr.name + "' with type '"+attr.type.toString() + 326 "' is overriding superclass attribute with same name but different type: "+ 327 parentType.toString())); 328 } 329 } 330 331 setAttributeType(sourceElement, classname, attr.name, attr); 333 } 334 335 if (!attrList.isEmpty()) { 336 List children = new ArrayList(); 339 for (Iterator iter = classDef.getChildren().iterator(); iter.hasNext();) { 340 Element child = (Element) iter.next(); 341 children.add(child); 342 iter.remove(); 346 } 347 classDef.setContent(attrList); 349 for (Iterator iter = children.iterator(); iter.hasNext();) { 351 Element child = (Element) iter.next(); 352 classDef.addContent(child); 353 } 354 } 355 } 356 } 357 358 367 public void addElement (Element elt, String className, 368 String superclassName, List attributeDefs) 369 { 370 ClassModel superclass = getClassModel(superclassName); 371 372 if (superclass == null) { 373 throw new CompilationError("undefined superclass " + superclassName + " for class "+className); 374 } 375 376 if (mClassMap.get(className) != null) { 377 String builtin = "builtin "; 378 String also = ""; 379 Element other = getClassModel(className).definition; 380 if (other != null) { 381 builtin = ""; 382 also = "; also defined at " + Parser.getSourceMessagePathname(other) + ":" + Parser.getSourceLocation(other, Parser.LINENO); 383 } 384 throw new CompilationError("duplicate class definitions for " + builtin + className + also, elt); 385 } 386 ClassModel info = new ClassModel(className, superclass, this, elt); 387 mClassMap.put(className, info); 388 389 if (sInputTextElements.contains(superclassName)) { 390 info.isInputText = true; 391 info.hasInputText = true; 392 } else { 393 info.isInputText = superclass.isInputText; 394 info.hasInputText = superclass.hasInputText; 395 } 396 397 info.supportsTextAttribute = superclass.supportsTextAttribute; 398 399 400 403 429 430 Element superclassDef = findSchemaClassDef(superclassName, schemaDOM.getRootElement()); 432 if (superclassDef == null) { 433 throw new CompilationError("No definition for superclass "+superclassName+" found in the schema"); 434 } 435 436 Namespace ns = superclassDef.getNamespace(); 437 Element myclassDef = (Element) superclassDef.clone(); 439 440 classElementTable.put(className, myclassDef); 442 443 addAttributeDefs(elt, className, myclassDef, attributeDefs); 445 449 Attribute nameAttr = myclassDef.getAttribute("name"); 451 if (nameAttr == null) { 452 459 463 for (Iterator iter = myclassDef.getChildren("choice", ns).iterator(); iter.hasNext();) { 464 Element choice = (Element) iter.next(); 465 List names = choice.getChildren("name", ns); 466 if (!names.isEmpty()) { 467 iter.remove(); 470 break; 471 } 472 } 473 } 474 475 myclassDef.setAttribute("name", className); 476 477 483 484 Element parent = superclassDef.getParent(); 485 if (parent.getName().equals("choice")) 486 parent.addContent(myclassDef); 487 else { 488 superclassDef.detach(); 489 Element newChoice = new Element("choice", ns); 490 newChoice.addContent(superclassDef); 491 newChoice.addContent(myclassDef); 492 parent.addContent(newChoice); 493 } 494 495 513 519 } 520 521 535 536 Element findSchemaClassDef (String classname, Element elt) { 537 538 Element classdef = (Element) classElementTable.get(classname); 540 if (classdef != null) { 541 return classdef; 542 } 543 544 if (elt.getName().equals("element")) { 545 Namespace ns = elt.getNamespace(); 546 String name = elt.getAttributeValue("name"); 548 if (name != null && name.equals(classname)) { 549 classElementTable.put(classname, elt); 551 return elt; 552 } else if (name == null) { 553 for (Iterator iter = elt.getChildren("choice", ns).iterator(); iter.hasNext();) { 558 Element choice = (Element) iter.next(); 559 for (Iterator iter2 = choice.getChildren("name", ns).iterator(); iter2.hasNext();) { 560 Element child = (Element) iter2.next(); 561 if (child.getTextTrim().equals(classname)) { 562 classElementTable.put(classname, elt); 563 return elt; 564 } 565 } 566 } 567 } 568 } 569 570 for (Iterator iter = elt.getChildren().iterator(); iter.hasNext(); ) { 572 Element child = (Element) iter.next(); 573 Element result = findSchemaClassDef(classname, child); 574 if (result != null) { 575 return result; 576 } 577 } 578 579 return (Element) null; 580 } 581 582 public Type getTypeForName(String name) { 583 if (name.equals("text") || 584 name.equals("html")) 585 name = "string"; 586 if (sRNGtoLPSTypeMap.containsKey(name)) 587 return (Type) sRNGtoLPSTypeMap.get(name); 588 return super.getTypeForName(name); 589 } 590 591 592 private final Map referenceTable = new HashMap(); 593 594 private final List schemaElementTable = new ArrayList(); 595 596 598 private final Map classElementTable = new HashMap(); 599 600 601 604 private void buildReferenceTable (Element elt) { 605 String eltname = elt.getName(); 607 if (eltname.equals("define")) { 608 String name = elt.getAttributeValue("name"); 609 List elts = (List) referenceTable.get(name); 610 if (elts == null) { 611 elts = new ArrayList(); 612 referenceTable.put(name, elts); 613 } 614 elts.add(elt); 615 } else if (eltname.equals("element")) { 617 schemaElementTable.add(elt); 618 } 619 620 for (Iterator iter = elt.getChildren().iterator(); iter.hasNext(); ) { 621 Element child = (Element) iter.next(); 622 buildReferenceTable(child); 623 } 624 } 625 626 627 private void makeNewStaticClass (String classname) { 628 ClassModel info = new ClassModel(classname, this); 629 if (sInputTextElements.contains(classname)) { 630 info.isInputText = true; 631 info.hasInputText = true; 632 } 633 if (mClassMap.get(classname) == null) { 634 mClassMap.put(classname, info); 635 } else { 636 639 } 641 642 } 643 644 645 685 686 public void parseSchemaAttributes () { 687 for (Iterator eltIter = schemaElementTable.iterator(); eltIter.hasNext();) { 688 Element elt = (Element) eltIter.next(); 689 690 List classnames = new ArrayList(); 692 Namespace ns = elt.getNamespace(); 693 String name = elt.getAttributeValue("name"); 694 if (name != null) { 697 classnames.add(name); 698 makeNewStaticClass(name); 700 } else if (name == null) { 701 for (Iterator iter = elt.getChildren("choice", ns).iterator(); iter.hasNext();) { 706 Element choice = (Element) iter.next(); 707 for (Iterator iter2 = choice.getChildren("name", ns).iterator(); iter2.hasNext();) { 708 Element child = (Element) iter2.next(); 709 name = child.getTextTrim(); 710 classnames.add(name); 712 makeNewStaticClass(name); 714 } 715 } 716 } 717 if (!classnames.isEmpty()) { 720 for (Iterator iter = elt.getChildren().iterator(); iter.hasNext(); ) { 723 Element child = (Element) iter.next(); 724 parseSchemaAttributes(child, classnames); 725 } 726 } 727 } 728 } 729 730 737 738 public void parseSchemaAttributes (Element elt, List classnames) { 739 if (elt.getName().equals("element")) { 741 return; 742 } else if (elt.getName().equals("attribute")) { 743 String attrName = elt.getAttributeValue("name"); 744 if (attrName == null) { 745 } else { 748 750 String rngTypeName; 751 752 780 Namespace ns = elt.getNamespace(); 781 782 Element ref = elt.getChild("ref", ns); 783 if (ref != null) { 784 rngTypeName = ref.getAttributeValue("name"); 785 } else { 786 Element data = elt.getChild("data", ns); 787 if (data != null) { 788 rngTypeName = data.getAttributeValue("type"); 789 } else { 790 rngTypeName = "token"; 792 } 793 } 794 795 Type attrType = (Type) sRNGtoLPSTypeMap.get(rngTypeName); 797 798 if (attrType == null) { 799 throw new RuntimeException ("error parsing RNG schema: unknown attribute type name "+ rngTypeName + 800 " for attribute "+attrName); 801 } 802 803 AttributeSpec attrspec = new AttributeSpec(attrName, attrType, null, null); 804 806 Iterator citer = classnames.iterator(); 808 while (citer.hasNext()) { 809 String cname = (String ) citer.next(); 810 812 818 824 boolean ignore = false; 825 if (cname.equals("view")) { 827 Element p = elt; 828 while (p != null) { 829 p = p.getParent(); 830 if (p == null) { 831 break; 832 } 833 if ((p.getName().equals("element")) && ("splash".equals(p.getAttributeValue("name")))) { 834 ignore = true; 835 break; 836 } 837 } 838 } 839 840 ClassModel classModel = getClassModel(cname); 842 if (classModel == null) { 843 throw new RuntimeException ("parseSchemaAttributes: undefined class: " + cname); 844 } 845 if (ignore) { 846 } else { 848 classModel.attributeSpecs.put(attrName, attrspec); 849 } 850 } 851 } 852 } else if (elt.getName().equals("ref")) { 853 String refName = elt.getAttributeValue("name"); 855 List refElements = (List) referenceTable.get(refName); 859 if (refElements == null || refElements.isEmpty()) { 860 throw new RuntimeException ("error parsing schema: could not find definition for reference "+refName+" on elt" + elt); 861 } 862 Iterator riter = refElements.iterator(); 863 while (riter.hasNext()) { 864 Element ref = (Element) riter.next(); 865 if (ref == null) { 866 throw new RuntimeException ("error parsing schema: could not find definition for reference "+refName+" on elt" + elt); 867 } 868 parseSchemaAttributes(ref, classnames); 869 } 870 } 871 872 for (Iterator iter = elt.getChildren().iterator(); iter.hasNext(); ) { 874 Element child = (Element) iter.next(); 875 parseSchemaAttributes(child, classnames); 876 } 877 } 878 879 static Type getAttributeType(String attrName) { 880 return (Type) sAttributeTypes.get(attrName); 881 } 882 883 891 public Type getAttributeType(Element e, String attrName) { 892 return getAttributeType(e.getName(), attrName); 893 } 894 895 904 public Type getAttributeType(String elt, String attrName) 905 throws UnknownAttributeException 906 { 907 String elementName = elt.intern(); 908 912 if (elementName.equals("canvas")) { 913 if (attrName.equals("width") || attrName.equals("height")) { 915 return NUMBER_TYPE; 916 } 917 } 918 919 Type type = null; 920 921 ClassModel classModel = getClassModel(elementName); 923 924 if (classModel != null) { 925 try { 926 type = classModel.getAttributeTypeOrException(attrName); 927 } catch (UnknownAttributeException e) { 928 e.setName(attrName); 929 e.setElementName(elt); 930 throw e; 931 } 932 } else { 933 type = getAttributeType(attrName); 934 if (type == null) { 935 throw new UnknownAttributeException(elt, attrName); 936 } 938 } 939 return type; 940 } 941 942 boolean isMouseEventAttribute(String name) { 943 return sMouseEventAttributes.contains(name); 944 } 945 946 ClassModel getClassModel (String elementName) { 947 return (ClassModel) mClassMap.get(elementName); 948 } 949 950 public void loadSchema() throws JDOMException { 951 String schemaPath = SCHEMA_PATH; 952 while (sCachedSchemaDOM == null || 955 new File(schemaPath).lastModified() != sCachedSchemaLastModified) { 956 sCachedSchemaLastModified = new File(schemaPath).lastModified(); 960 String schemaURI = "file:///" + schemaPath; 963 sCachedSchemaDOM = new SAXBuilder().build(schemaURI); 964 } 965 schemaDOM = (Document) sCachedSchemaDOM.clone(); 966 buildReferenceTable(schemaDOM.getRootElement()); 967 parseSchemaAttributes(); 969 } 970 971 public Document getSchemaDOM() throws JDOMException { 972 if (schemaDOM == null) { 973 loadSchema(); 974 } 975 return schemaDOM; 976 } 977 978 979 boolean isInputTextElement(Element e) { 980 String classname = e.getName(); 981 ClassModel info = getClassModel(classname); 982 if (info != null) { 983 return info.isInputText; 984 } 985 return sInputTextElements.contains(classname); 986 } 987 988 boolean supportsTextAttribute(Element e) { 989 String classname = e.getName(); 990 ClassModel info = getClassModel(classname); 991 if (info != null) { 992 return info.supportsTextAttribute; 993 } else { 994 return false; 995 } 996 } 997 998 999 1000 boolean hasTextContent(Element e) { 1001 return isInputTextElement(e) || supportsTextAttribute(e); 1003 } 1004 1005 1006 boolean hasHTMLContent(Element e) { 1007 String name = e.getName().intern(); 1008 return name != "class" && name != "method" 1015 && name != "property" && name != "script" 1016 && name != "attribute" 1017 && !isHTMLElement(e) && !isInputTextElement(e); 1018 } 1019 1020 1023 static boolean isHTMLElement(Element e) { 1024 String name = e.getName(); 1025 return name.equals("a") 1026 || name.equals("b") 1027 || name.equals("img") 1028 || name.equals("br") 1029 || name.equals("font") 1030 || name.equals("i") 1031 || name.equals("p") 1032 || name.equals("pre") 1033 || name.equals("u"); 1034 } 1035 1036 1037 1038 static final PatternMatcher sMatcher = new Perl5Matcher(); 1039 static final Pattern sRGBPattern; 1040 static final Pattern sHex3Pattern; 1041 static final Pattern sHex6Pattern; 1042 static final HashMap sColorValues = new HashMap(); 1043 static { 1044 try { 1045 Perl5Compiler compiler = new Perl5Compiler(); 1046 String s = "\\s*(-?\\d+(?:(?:.\\d*)%)?)\\s*"; String hexDigit = "[0-9a-fA-F]"; 1048 String hexByte = hexDigit + hexDigit; 1049 sRGBPattern = compiler.compile( 1050 "\\s*rgb\\("+s+","+s+","+s+"\\)\\s*"); 1051 sHex3Pattern = compiler.compile( 1052 "\\s*#\\s*(" + hexDigit + hexDigit + hexDigit + ")\\s*"); 1053 sHex6Pattern = compiler.compile( 1054 "\\s*#\\s*(" + hexByte + hexByte + hexByte + ")\\s*"); 1055 } catch (MalformedPatternException e) { 1056 throw new ChainedException(e); 1057 } 1058 1059 String [] colorNameValues = { 1060 "black", "000000", "green", "008000", 1061 "silver", "C0C0C0", "lime", "00FF00", 1062 "gray", "808080", "olive", "808000", 1063 "white", "FFFFFF", "yellow", "FFFF00", 1064 "maroon", "800000", "navy", "000080", 1065 "red", "FF0000", "blue", "0000FF", 1066 "purple", "800080", "teal", "008080", 1067 "fuchsia", "FF00FF", "aqua", "00FFFF"}; 1068 for (int i = 0; i < colorNameValues.length; ) { 1069 String name = colorNameValues[i++]; 1070 String value = colorNameValues[i++]; 1071 sColorValues.put(name, new Integer (Integer.parseInt(value, 16))); 1072 } 1073 } 1074 1075 static class ColorFormatException extends RuntimeException { 1076 ColorFormatException(String message) { 1077 super(message); 1078 } 1079 } 1080 1081 1083 public static int parseColor(String str) { 1084 { 1085 Object value = sColorValues.get(str); 1086 if (value != null) { 1087 return ((Integer ) value).intValue(); 1088 } 1089 } 1090 if (str.startsWith("0x")) { 1091 try { 1092 return Integer.parseInt(str.substring(2), 16); 1093 } catch (java.lang.NumberFormatException e) { 1094 } 1096 } 1097 if (sMatcher.matches(str, sHex3Pattern)) { 1098 int r1g1b1 = Integer.parseInt(sMatcher.getMatch().group(1), 16); 1099 int r = (r1g1b1 >> 8) * 17; 1100 int g = ((r1g1b1 >> 4) & 0xf) * 17; 1101 int b = (r1g1b1 & 0xf) * 17; 1102 return (r << 16) + (g << 8) + b; 1103 } 1104 if (sMatcher.matches(str, sHex6Pattern)) { 1105 return Integer.parseInt(sMatcher.getMatch().group(1), 16); 1106 } 1107 if (sMatcher.matches(str, sRGBPattern)) { 1108 int v = 0; 1109 for (int i = 0; i < 3; i++) { 1110 String s = sMatcher.getMatch().group(i+1); 1111 int c; 1112 if (s.charAt(s.length()-1) == '%') { 1113 s = s.substring(0, s.length()-1); 1114 float f = Float.parseFloat(s); 1115 c = (int) f * 255 / 100; 1116 } else { 1117 c = Integer.parseInt(s); 1118 } 1119 if (c < 0) c = 0; 1120 if (c > 255) c = 255; 1121 v = (v << 8) | c; 1122 } 1123 return v; 1124 } 1125 throw new ColorFormatException(str); 1126 } 1127} 1128 | Popular Tags |