XStringType.java 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // Copyright (c) 2007 Per M.A. Bothner.
  2. // This is free software; for specifics see ../../../COPYING.
  3. package gnu.kawa.xml;
  4. import gnu.bytecode.*;
  5. import gnu.xml.*;
  6. /* #ifdef use:java.util.regex */
  7. import java.util.regex.Pattern;
  8. import java.util.regex.Matcher;
  9. /* #endif */
  10. public class XStringType extends XDataType
  11. {
  12. /* #ifdef use:java.util.regex */
  13. Pattern pattern;
  14. /* #endif */
  15. static ClassType XStringType = ClassType.make("gnu.kawa.xml.XString");
  16. public XStringType (String name, XDataType base, int typeCode,
  17. String pattern)
  18. {
  19. super(name, XStringType, typeCode);
  20. baseType = base;
  21. /* #ifdef use:java.util.regex */
  22. if (pattern != null)
  23. this.pattern = Pattern.compile(pattern);
  24. /* #endif */
  25. }
  26. public static final XStringType normalizedStringType =
  27. new XStringType ("normalizedString", stringType,
  28. NORMALIZED_STRING_TYPE_CODE, null);
  29. public static final XStringType tokenType =
  30. new XStringType ("token", normalizedStringType,
  31. TOKEN_TYPE_CODE, null);
  32. public static final XStringType languageType =
  33. new XStringType ("language", tokenType,
  34. LANGUAGE_TYPE_CODE, "[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*");
  35. public static final XStringType NMTOKENType =
  36. new XStringType ("NMTOKEN", tokenType,
  37. NMTOKEN_TYPE_CODE, "\\c+"); // FIXME check pattern
  38. public static final XStringType NameType =
  39. new XStringType ("Name", tokenType,
  40. NAME_TYPE_CODE, null);
  41. public static final XStringType NCNameType =
  42. new XStringType ("NCName", NameType,
  43. NCNAME_TYPE_CODE, null);
  44. public static final XStringType IDType =
  45. new XStringType ("ID", NCNameType,
  46. ID_TYPE_CODE, null);
  47. public static final XStringType IDREFType =
  48. new XStringType ("IDREF", NCNameType,
  49. IDREF_TYPE_CODE, null);
  50. public static final XStringType ENTITYType =
  51. new XStringType ("ENTITY", NCNameType,
  52. ENTITY_TYPE_CODE, null);
  53. public boolean isInstance (Object obj)
  54. {
  55. if (! (obj instanceof XString))
  56. return false;
  57. /*
  58. if (this == stringType)
  59. return true;
  60. */
  61. XDataType objType = ((XString) obj).getStringType();
  62. while (objType != null)
  63. {
  64. if (objType == this)
  65. return true;
  66. objType = objType.baseType;
  67. }
  68. return false;
  69. }
  70. /** Check if the String matches the restrictions on this type.
  71. * Assumes any normalization has been done.
  72. * @return null on success or an error message otherwise.
  73. */
  74. public String matches (String value)
  75. {
  76. boolean status;
  77. switch (typeCode)
  78. {
  79. /* #ifndef use:java.util.regex */
  80. // case LANGUAGE_TYPE_CODE:
  81. /* #endif */
  82. case NORMALIZED_STRING_TYPE_CODE:
  83. case TOKEN_TYPE_CODE:
  84. // Assumes that TextUtils.replaceWhitespace returns the original
  85. // string if it was original normalized.
  86. // This is suboptimal, but the extra cost is minor when the string
  87. // is already normalized, which presumably is the common case.
  88. boolean collapse = typeCode != NORMALIZED_STRING_TYPE_CODE;
  89. status = value == TextUtils.replaceWhitespace(value, collapse);
  90. break;
  91. case NAME_TYPE_CODE:
  92. status = XName.isName(value);
  93. break;
  94. case NCNAME_TYPE_CODE:
  95. case ID_TYPE_CODE:
  96. case IDREF_TYPE_CODE:
  97. case ENTITY_TYPE_CODE:
  98. status = XName.isNCName(value);
  99. break;
  100. case NMTOKEN_TYPE_CODE:
  101. status = XName.isNmToken(value);
  102. break;
  103. default:
  104. /* #ifdef use:java.util.regex */
  105. status = pattern == null || pattern.matcher(value).matches();
  106. /* #else */
  107. // status = true;
  108. /* #endif */
  109. }
  110. // If we haven't returned a more specific error message:
  111. return status ? null : "not a valid XML "+getName();
  112. }
  113. public Object valueOf (String value)
  114. {
  115. value = TextUtils.replaceWhitespace(value, this != normalizedStringType);
  116. String err = matches(value);
  117. if (err != null) // we're not using err yet. FIXME.
  118. throw new ClassCastException("cannot cast "+value+" to "+name);
  119. return new XString(value, this);
  120. }
  121. public Object cast (Object value)
  122. {
  123. if (value instanceof XString)
  124. {
  125. XString xvalue = (XString) value;
  126. if (xvalue.getStringType() == this)
  127. return xvalue;
  128. }
  129. return valueOf((String) stringType.cast(value));
  130. }
  131. public static XString makeNCName (String value)
  132. {
  133. return (XString) NCNameType.valueOf(value);
  134. }
  135. }