1 4 package gnu.kawa.xml; 5 import gnu.bytecode.*; 6 import gnu.mapping.Procedure; 7 import gnu.expr.*; 8 import gnu.text.Printable; 9 import gnu.math.*; 10 import java.math.BigDecimal ; 11 import gnu.lists.Consumer; 12 import gnu.xml.TextUtils; 13 14 17 18 public class XDataType extends Type implements TypeValue 19 { 20 Type implementationType; 21 22 Object name; 23 24 25 XDataType baseType; 26 27 28 int typeCode; 29 30 public static final int DECIMAL_TYPE_CODE = 2; 31 public static final int INTEGER_TYPE_CODE = 3; 32 public static final int NON_POSITIVE_INTEGER_TYPE_CODE = 4; 33 public static final int NEGATIVE_INTEGER_TYPE_CODE = 5; 34 public static final int LONG_TYPE_CODE = 6; 35 public static final int INT_TYPE_CODE = 7; 36 public static final int SHORT_TYPE_CODE = 8; 37 public static final int BYTE_TYPE_CODE = 9; 38 public static final int NONNEGATIVE_INTEGER_TYPE_CODE = 10; 39 public static final int UNSIGNED_LONG_TYPE_CODE = 11; 40 public static final int UNSIGNED_INT_TYPE_CODE = 12; 41 public static final int UNSIGNED_SHORT_TYPE_CODE = 13; 42 public static final int UNSIGNED_BYTE_TYPE_CODE = 14; 43 public static final int POSITIVE_INTEGER_TYPE_CODE = 15; 44 45 public static final int FLOAT_TYPE_CODE = 16; 46 public static final int DOUBLE_TYPE_CODE = 17; 47 48 public static final int DATE_TIME_TYPE_CODE = 18; 49 public static final int DATE_TYPE_CODE = 19; 50 public static final int TIME_TYPE_CODE = 20; 51 public static final int G_YEAR_MONTH_TYPE_CODE = 21; 52 public static final int G_YEAR_TYPE_CODE = 22; 53 public static final int G_MONTH_DAY_TYPE_CODE = 23; 54 public static final int G_DAY_TYPE_CODE = 24; 55 public static final int G_MONTH_TYPE_CODE = 25; 56 public static final int DURATION_TYPE_CODE = 26; 57 public static final int YEAR_MONTH_DURATION_TYPE_CODE = 27; 58 public static final int DAY_TIME_DURATION_TYPE_CODE = 28; 59 60 public static final int BOOLEAN_TYPE_CODE = 29; 61 62 public static final int QNAME_TYPE_CODE = 30; 63 public static final int ANY_URI_TYPE_CODE = 31; 64 public static final int BASE64_BINARY_TYPE_CODE = 32; 65 public static final int HEX_BINARY_TYPE_CODE = 33; 66 public static final int NOTATION_TYPE_CODE = 34; 67 68 public static final int UNTYPED_ATOMIC_TYPE_CODE = 35; 69 70 public static final int STRING_TYPE_CODE = 36; 71 72 public XDataType (Object name, Type implementationType, int typeCode) 73 { 74 super(implementationType); 75 this.name = name; 76 if (name != null) 77 setName(name.toString()); 78 this.implementationType = implementationType; 79 this.typeCode = typeCode; 80 } 81 82 public static final XDataType stringType = 83 new XDataType("string", ClassType.make("java.lang.String"), 84 STRING_TYPE_CODE); 85 86 public static final XDataType untypedAtomicType = 87 new XDataType("string", ClassType.make("gnu.kawa.xml.UntypedAtomic"), 88 UNTYPED_ATOMIC_TYPE_CODE); 89 90 public static final XDataType base64BinaryType = 91 new XDataType("base64Binary", ClassType.make("gnu.kawa.xml.Base64Binary"), 92 BASE64_BINARY_TYPE_CODE); 93 94 public static final XDataType hexBinaryType = 95 new XDataType("hexBinary", ClassType.make("gnu.kawa.xml.HexBinary"), 96 HEX_BINARY_TYPE_CODE); 97 98 public static final XDataType booleanType = 99 new XDataType("boolean", Type.boolean_type, 100 BOOLEAN_TYPE_CODE); 101 102 public static final XDataType anyURIType = 103 new XDataType("anyURI", 104 105 ClassType.make("java.net.URI"), 106 107 109 ANY_URI_TYPE_CODE); 110 111 public static final XDataType NotationType = 112 new XDataType("NOTATION", 113 ClassType.make("gnu.kawa.xml.Notation"), 114 NOTATION_TYPE_CODE); 115 116 public static final XDataType decimalType = 117 new XDataType("decimal", ClassType.make("java.lang.Number"), 121 DECIMAL_TYPE_CODE); 122 123 public static final XDataType floatType = 124 new XDataType("float", ClassType.make("java.lang.Float"), FLOAT_TYPE_CODE); 125 126 public static final XDataType doubleType = 127 new XDataType("double", ClassType.make("java.lang.Double"), DOUBLE_TYPE_CODE); 128 129 public static final XDataType durationType = 130 new XDataType("duration", ClassType.make("gnu.math.Duration"), 131 DURATION_TYPE_CODE); 132 133 public static final XDataType yearMonthDurationType = 134 new XDataType("yearMonthDuration", ClassType.make("gnu.math.Duration"), 135 YEAR_MONTH_DURATION_TYPE_CODE); 136 137 public static final XDataType dayTimeDurationType = 138 new XDataType("dayTimeDuration", ClassType.make("gnu.math.Duration"), 139 DAY_TIME_DURATION_TYPE_CODE); 140 141 public java.lang.Class getReflectClass() 142 { 143 return implementationType.getReflectClass(); 144 } 145 146 public Type getImplementationType() 147 { 148 return implementationType; 149 } 150 151 public void emitCoerceFromObject (CodeAttr code) 152 { 153 Compilation comp = Compilation.getCurrent(); 154 comp.compileConstant(this, Target.pushObject); 155 Method meth = ClassType.make("gnu.kawa.xml.XDataType") 156 .getDeclaredMethod("coerceFromObject", 1); 157 code.emitSwap(); 158 code.emitInvokeVirtual(meth); 159 implementationType.emitCoerceFromObject(code); 161 } 162 163 public void emitCoerceToObject (CodeAttr code) 164 { 165 if (typeCode == BOOLEAN_TYPE_CODE) 166 implementationType.emitCoerceToObject(code); 167 else 168 super.emitCoerceToObject(code); 169 } 170 171 public void emitTestIf(Variable incoming, Declaration decl, Compilation comp) 172 { 173 CodeAttr code = comp.getCode(); 174 if (typeCode == BOOLEAN_TYPE_CODE) 175 { 176 if (incoming != null) 177 code.emitLoad(incoming); 178 Type.boolean_ctype.emitIsInstance(code); 179 code.emitIfIntNotZero(); 180 if (decl != null) 181 { 182 code.emitLoad(incoming); 184 Type.boolean_type.emitCoerceFromObject(code); 185 decl.compileStore(comp); 186 } 187 return; 188 } 189 190 comp.compileConstant(this, Target.pushObject); 191 if (incoming == null) 192 code.emitSwap(); 193 else 194 code.emitLoad(incoming); 195 if (decl != null) 196 { 197 code.emitDup(); 198 decl.compileStore(comp); 199 } 200 code.emitInvokeVirtual(Compilation.typeType 201 .getDeclaredMethod("isInstance", 1)); 202 code.emitIfIntNotZero(); 203 } 204 205 public boolean isInstance (Object obj) 206 { 207 switch (typeCode) 208 { 209 case STRING_TYPE_CODE: 210 return obj instanceof java.lang.String ; 211 case UNTYPED_ATOMIC_TYPE_CODE: 212 return obj instanceof gnu.kawa.xml.UntypedAtomic; 213 case ANY_URI_TYPE_CODE: 214 215 return obj instanceof java.net.URI ; 216 217 219 case BOOLEAN_TYPE_CODE: 220 return obj instanceof java.lang.Boolean ; 221 case FLOAT_TYPE_CODE: 222 return obj instanceof java.lang.Float ; 223 case DOUBLE_TYPE_CODE: 224 return obj instanceof java.lang.Double ; 225 case DECIMAL_TYPE_CODE: 226 return obj instanceof java.math.BigDecimal 227 || obj instanceof gnu.math.IntNum; 228 case DURATION_TYPE_CODE: 229 return obj instanceof Duration; 230 case YEAR_MONTH_DURATION_TYPE_CODE: 231 return obj instanceof Duration 232 && ((Duration) obj).unit() == Unit.month; 233 case DAY_TIME_DURATION_TYPE_CODE: 234 return obj instanceof Duration 235 && ((Duration) obj).unit() == Unit.second; 236 default: 237 return super.isInstance(obj); 238 } 239 } 240 241 public void emitIsInstance(Variable incoming, 242 Compilation comp, Target target) 243 { 244 gnu.kawa.reflect.InstanceOf.emitIsInstance(this, incoming, comp, target); 245 } 246 247 public String toString (Object value) 248 { 249 return value.toString(); 250 } 251 252 253 public void print (Object value, Consumer out) 254 { 255 if (value instanceof Printable) 256 ((Printable) value).print(out); 257 else 258 out.write(toString(value)); 259 } 260 261 public boolean castable (Object value) 262 { 263 try 264 { 265 cast(value); 267 return true; 268 } 269 catch (Throwable ex) 270 { 271 return false; 272 } 273 } 274 275 public Object cast (Object value) 276 { 277 value = KNode.atomicValue(value); 278 if (value instanceof UntypedAtomic) 279 { 280 if (typeCode == UNTYPED_ATOMIC_TYPE_CODE) 281 return value; 282 return valueOf(value.toString()); 283 } 284 if (value instanceof String ) 285 return valueOf(value.toString()); 286 switch (typeCode) 287 { 288 case STRING_TYPE_CODE: 289 return TextUtils.asString(value); 290 case UNTYPED_ATOMIC_TYPE_CODE: 291 return new UntypedAtomic(TextUtils.stringValue(value)); 292 case ANY_URI_TYPE_CODE: 293 return toURI(value); 294 case BOOLEAN_TYPE_CODE: 295 if (value instanceof Boolean ) 296 return (((Boolean )value).booleanValue() ? Boolean.TRUE 297 : Boolean.FALSE); 298 if (value instanceof Number ) 299 { 300 double d = ((Number ) value).doubleValue(); 301 return d == 0.0 || Double.isNaN(d) ? Boolean.FALSE : Boolean.TRUE; 302 } 303 break; 304 case DECIMAL_TYPE_CODE: 305 if (value instanceof java.math.BigDecimal ) 307 return value; 308 if (value instanceof gnu.math.RealNum) 309 return ((gnu.math.RealNum) value).asBigDecimal(); 310 if (value instanceof Float || value instanceof Double ) 311 { 312 double d = ((Number ) value).doubleValue(); 313 314 316 return new BigDecimal (d); 317 318 } 319 if (value instanceof Boolean ) 320 return cast(((Boolean )value).booleanValue() ? IntNum.one() 321 : IntNum.zero()); 322 break; 323 case FLOAT_TYPE_CODE: 324 if (value instanceof java.lang.Float ) 325 return value; 326 if (value instanceof java.lang.Number ) 327 return makeFloat(((Number ) value).floatValue()); 329 if (value instanceof Boolean ) 330 return ((Boolean )value).booleanValue() ? FLOAT_ONE : FLOAT_ZERO; 331 break; 332 case DOUBLE_TYPE_CODE: 333 if (value instanceof java.lang.Double ) 334 return value; 335 if (value instanceof java.lang.Number ) 336 return makeDouble(((Number ) value).doubleValue()); 338 if (value instanceof Boolean ) 339 return ((Boolean )value).booleanValue() ? DOUBLE_ONE : DOUBLE_ZERO; 340 break; 341 case G_YEAR_TYPE_CODE: 342 case G_YEAR_MONTH_TYPE_CODE: 343 case G_MONTH_TYPE_CODE: 344 case G_MONTH_DAY_TYPE_CODE: 345 case G_DAY_TYPE_CODE: 346 if (value instanceof DateTime) 347 { 348 int dstMask = XTimeType.components(((XTimeType) this).typeCode); 349 DateTime dt = (DateTime) value; 350 int srcMask = dt.components(); 351 if (dstMask == srcMask 352 || (srcMask & DateTime.DATE_MASK) == DateTime.DATE_MASK) 353 return dt.cast(dstMask); 354 throw new ClassCastException (); 355 } 356 break; 357 case DATE_TYPE_CODE: 358 case TIME_TYPE_CODE: 359 case DATE_TIME_TYPE_CODE: 360 if (value instanceof DateTime) 361 { 362 int mask = XTimeType.components(((XTimeType) this).typeCode); 363 return ((DateTime) value).cast(mask); 364 } 365 break; 366 case DURATION_TYPE_CODE: 367 return castToDuration(value, Unit.duration); 368 case YEAR_MONTH_DURATION_TYPE_CODE: 369 return castToDuration(value, Unit.month); 370 case DAY_TIME_DURATION_TYPE_CODE: 371 return castToDuration(value, Unit.second); 372 case BASE64_BINARY_TYPE_CODE: 373 if (value instanceof BinaryObject) 374 return new Base64Binary(((BinaryObject) value).getBytes()); 375 case HEX_BINARY_TYPE_CODE: 376 if (value instanceof BinaryObject) 377 return new HexBinary(((BinaryObject) value).getBytes()); 378 } 379 return coerceFromObject(value); 380 } 381 382 Duration castToDuration (Object value, Unit unit) 383 { 384 if (value instanceof Duration) 385 { 386 Duration dur = (Duration) value; 387 if (dur.unit() == unit) 388 return dur; 389 int months = dur.getTotalMonths(); 390 long seconds = dur.getTotalSeconds(); 391 int nanos = dur.getNanoSecondsOnly(); 392 if (unit == Unit.second) 393 months = 0; 394 if (unit == Unit.month) 395 { 396 seconds = 0; 397 nanos = 0; 398 } 399 return Duration.make(months, seconds, nanos, unit); 400 } 401 return (Duration) coerceFromObject(value); 402 } 403 404 public Object coerceFromObject (Object obj) 405 { 406 if (! isInstance(obj)) 407 throw new ClassCastException ("cannot cast "+obj+" to "+name); 408 return obj; 409 } 410 411 public int compare(Type other) 412 { 413 if (this == other) 414 return 0; 415 return implementationType.compare(other); } 417 418 419 public static java.net.URI toURI (Object value) 420 { 421 try 422 { 423 return gnu.text.URI_utils.toURI(value); 424 } 425 catch (java.net.URISyntaxException ex) 426 { 427 return (java.net.URI ) value; 428 } 429 } 430 431 436 437 public Object valueOf (String value) 438 { 439 switch (typeCode) 440 { 441 case STRING_TYPE_CODE: 442 return value; 443 case UNTYPED_ATOMIC_TYPE_CODE: 444 return new UntypedAtomic(value); 445 case ANY_URI_TYPE_CODE: 446 return toURI(TextUtils.replaceWhitespace(value, true)); 447 case BOOLEAN_TYPE_CODE: 448 value = value.trim(); 449 if (value.equals("true") || value.equals("1")) 450 return Boolean.TRUE; 451 if (value.equals("false") || value.equals("0")) 452 return Boolean.FALSE; 453 throw new IllegalArgumentException ("not a valid boolean: '"+value+"'"); 454 case FLOAT_TYPE_CODE: 455 case DOUBLE_TYPE_CODE: 456 value = value.trim(); 457 if ("INF".equals(value)) value = "Infinity"; 458 else if ("-INF".equals(value)) value = "-Infinity"; 459 return typeCode == FLOAT_TYPE_CODE ? (Object ) Float.valueOf(value) 460 : (Object ) Double.valueOf(value); 461 case DECIMAL_TYPE_CODE: 462 value = value.trim(); 463 for (int i = value.length(); --i >= 0; ) 466 { 467 char ch = value.charAt(i); 468 if (ch == 'e' || ch == 'E') 469 throw new IllegalArgumentException ("not a valid decimal: '"+value+"'"); 470 } 471 return new java.math.BigDecimal (value); 472 case DURATION_TYPE_CODE: 473 return Duration.parseDuration(value); 474 case YEAR_MONTH_DURATION_TYPE_CODE: 475 return Duration.parseYearMonthDuration(value); 476 case DAY_TIME_DURATION_TYPE_CODE: 477 return Duration.parseDayTimeDuration(value); 478 case BASE64_BINARY_TYPE_CODE: 479 return Base64Binary.valueOf(value); 480 case HEX_BINARY_TYPE_CODE: 481 return HexBinary.valueOf(value); 482 default: 483 throw new RuntimeException ("valueOf not implemented for "+name); 484 } 485 } 486 487 public static Float makeFloat (float value) 488 { 489 490 492 return new Float (value); 493 494 } 495 496 public static Double makeDouble (double value) 497 { 498 499 501 return new Double (value); 502 503 } 504 505 public static final Double DOUBLE_ZERO = makeDouble(0); 506 public static final Double DOUBLE_ONE = makeDouble(1); 507 public static final Float FLOAT_ZERO = makeFloat(0); 508 public static final Float FLOAT_ONE = makeFloat(1); 509 public static final BigDecimal DECIMAL_ONE = BigDecimal.valueOf(1); 510 511 public Procedure getConstructor () 512 { 513 return null; 514 } 515 } 516 | Popular Tags |