1 /** 2 * ServingXML 3 * 4 * Copyright (C) 2006 Daniel Parker 5 * daniel.parker@servingxml.com 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 **/ 20 21 package com.servingxml.util.record; 22 23 import java.sql.Timestamp; 24 import java.sql.Time; 25 import java.sql.Date; 26 import java.math.BigDecimal; 27 28 import org.xml.sax.SAXException; 29 import org.xml.sax.ContentHandler; 30 31 import com.servingxml.util.Name; 32 import com.servingxml.util.PrefixMap; 33 import com.servingxml.util.PrefixMapImpl; 34 35 /** 36 * A <code>RecordBuilder</code> class builds instances of {@link 37 * com.servingxml.util.record.Record}. 38 * 39 * 40 * @author Daniel A. Parker (daniel.parker@servingxml.com) 41 */ 42 43 public class RecordBuilder extends AbstractRecord implements Record { 44 45 private final Name recordTypeName; 46 private FieldType[] fieldTypes; 47 private int fieldCount = 0; 48 private Value[] values; 49 50 /** 51 * Creates a record builder with no initial field types. 52 */ 53 RecordBuilder(RecordType recordType)54 public RecordBuilder(RecordType recordType) { 55 this.recordTypeName = recordType.getName(); 56 this.fieldCount = recordType.count(); 57 58 if (fieldCount > 0) { 59 this.fieldTypes = recordType.getFieldTypes(); 60 this.values = new Value[fieldTypes.length]; 61 } else { 62 this.fieldTypes = new FieldType[10]; 63 this.values = new Value[10]; 64 } 65 } 66 67 /** 68 * Creates a record builder with no initial field types. 69 */ 70 RecordBuilder(Name recordTypeName)71 public RecordBuilder(Name recordTypeName) { 72 this.recordTypeName = recordTypeName; 73 this.fieldTypes = new FieldType[10]; 74 this.values = new Value[10]; 75 } 76 77 /** 78 * Creates a record builder with no initial field types. 79 */ 80 RecordBuilder(Name recordTypeName, int capacity)81 public RecordBuilder(Name recordTypeName, int capacity) { 82 this.recordTypeName = recordTypeName; 83 this.fieldTypes = new FieldType[capacity]; 84 this.values = new Value[capacity]; 85 } 86 87 /** 88 * Creates a record builder with the same record type and fields as an existing record. 89 */ 90 RecordBuilder(Record record)91 public RecordBuilder(Record record) { 92 93 this(record.getRecordType().getName(),record); 94 } 95 96 /** 97 * Creates a record builder with the same fields as an exisiting record, but a different record type. 98 */ 99 RecordBuilder(Name recordTypeName, Record record)100 public RecordBuilder(Name recordTypeName, Record record) { 101 102 RecordType recordType = record.getRecordType(); 103 104 this.recordTypeName = recordTypeName; 105 int inititialCapacity = recordType.count() >= 10 ? recordType.count() : 10; 106 this.values = new Value[inititialCapacity]; 107 this.fieldTypes = new FieldType[inititialCapacity]; 108 109 for (int i = 0; i < recordType.count(); ++i) { 110 FieldType fieldType = recordType.getFieldType(i); 111 Value value = record.getValue(i); 112 fieldTypes[i] = fieldType; 113 values[i] = value; 114 } 115 this.fieldCount = recordType.count(); 116 } 117 118 /** 119 * Sets a value for a field at an index. 120 * @param index The index 121 * @param value The value. 122 */ 123 setValue(int index, Value value)124 public void setValue(int index, Value value) { 125 if (index+1 >= values.length) { 126 int capacity = values.length < 10 ? 10 : values.length*2; 127 Value[] newData = new Value[capacity]; 128 System.arraycopy(values, 0, newData, 0, values.length); 129 values = newData; 130 } 131 values[index] = value; 132 } 133 134 /** 135 * Sets a value for a field. 136 * @param name The field name. 137 * @param value The field value. 138 * @deprecated since ServingXML 0.6.4: use {@link RecordBuilder#setValue} 139 */ 140 141 @Deprecated 142 public void setField(Name name, Value value) { 143 setValue(name,value); 144 } 145 146 /** 147 * Sets a string value for a field. 148 * @param name The field name. 149 * @param s The string value. 150 * @deprecated since ServingXML 0.6.1: use {@link RecordBuilder#setString} 151 */ 152 153 @Deprecated 154 public void setField(Name name, String s) { 155 setString(name, s); 156 } 157 158 /** 159 * Sets a string array value for a field. 160 * @param name The field name. 161 * @param sa The string array value. 162 * @deprecated since ServingXML 0.6.1: use {@link RecordBuilder#setStringArray} 163 */ 164 165 @Deprecated 166 public void setField(Name name, String[] sa) { 167 setStringArray(name, sa); 168 } 169 170 /** 171 * Sets a Object value for a field. 172 * @param name The field name. 173 * @param o The object value. 174 */ 175 176 public void setObject(Name name, Object o) { 177 178 ValueType valueType = new ObjectValueType(); 179 if (o != null) { 180 Value fieldValue = new ScalarValue(o, valueType); 181 setValue(name, fieldValue); 182 } else { 183 Value fieldValue = new NullValue(valueType); 184 setValue(name, fieldValue); 185 } 186 } 187 188 /** 189 * Sets a string value for a field. 190 * @param name The field name. 191 * @param s The string value. 192 */ 193 194 public void setString(Name name, String s) { 195 196 ValueType valueType = ValueTypeFactory.STRING_TYPE; 197 if (s != null) { 198 Value fieldValue = new ScalarValue(s, valueType); 199 setValue(name, fieldValue); 200 } else { 201 Value fieldValue = new NullValue(valueType); 202 setValue(name, fieldValue); 203 } 204 } 205 206 /** 207 * Sets a string array value for a field. 208 * @param name The field name. 209 * @param sa The string array value. 210 */ 211 212 public void setStringArray(Name name, String[] sa) { 213 214 ValueType valueType = ValueTypeFactory.STRING_TYPE; 215 Value fieldValue = ValueFactory.createStringArrayValue(sa); 216 setValue(name, fieldValue); 217 } 218 219 /** 220 * Sets a SQL timestamp value for a field. 221 * @param name The field name. 222 * @param value The timestamp value. 223 */ 224 225 public void setDateTime(Name name, Timestamp value) { 226 227 ValueType valueType = ValueTypeFactory.DATETIME_TYPE; 228 229 if (value != null) { 230 DateTimeData o = DateTimeData.fromSqlTimestamp(value); 231 Value fieldValue = new ScalarValue(o, valueType); 232 setValue(name, fieldValue); 233 } else { 234 Value fieldValue = new NullValue(valueType); 235 setValue(name, fieldValue); 236 } 237 } 238 239 /** 240 * Sets a SQL timestamp value for a field. 241 * @param name The field name. 242 * @param value milliseconds since January 1, 1970, 00:00:00 GMT. A negative number is the number of millisecondsbefore January 1, 1970, 00:00:00 GMT. 243 */ 244 245 public void setDateTime(Name name, long value) { 246 247 ValueType valueType = ValueTypeFactory.DATETIME_TYPE; 248 249 DateTimeData o = DateTimeData.fromSqlTimestamp(new Timestamp(value)); 250 Value fieldValue = new ScalarValue(o, valueType); 251 setValue(name, fieldValue); 252 } 253 254 /** 255 * Sets a SQL date value for a field. 256 * @param name The field name. 257 * @param value The date value. 258 */ 259 260 public void setDate(Name name, Date value) { 261 262 ValueType valueType = ValueTypeFactory.DATE_TYPE; 263 264 if (value != null) { 265 DateTimeData o = DateTimeData.fromSqlDate(value); 266 Value fieldValue = new ScalarValue(o, valueType); 267 setValue(name, fieldValue); 268 } else { 269 Value fieldValue = new NullValue(valueType); 270 setValue(name, fieldValue); 271 } 272 } 273 274 /** 275 * Sets a SQL date value for a field. 276 * @param name The field name. 277 * @param value milliseconds since January 1, 1970, 00:00:00 GMT. A negative number is the number of millisecondsbefore January 1, 1970, 00:00:00 GMT. 278 */ 279 280 public void setDate(Name name, long value) { 281 282 ValueType valueType = ValueTypeFactory.DATE_TYPE; 283 284 DateTimeData o = DateTimeData.fromSqlDate(new Date(value)); 285 Value fieldValue = new ScalarValue(o, valueType); 286 setValue(name, fieldValue); 287 } 288 289 /** 290 * Sets a SQL time value for a field. 291 * @param name The field name. 292 * @param value The time value. 293 */ 294 295 public void setTime(Name name, Time value) { 296 297 ValueType valueType = ValueTypeFactory.TIME_TYPE; 298 299 if (value != null) { 300 DateTimeData o = DateTimeData.fromSqlTime(value); 301 Value fieldValue = new ScalarValue(o, valueType); 302 setValue(name, fieldValue); 303 } else { 304 Value fieldValue = new NullValue(valueType); 305 setValue(name, fieldValue); 306 } 307 } 308 309 /** 310 * Sets a SQL time value for a field. 311 * @param name The field name. 312 * @param value The time value. 313 */ 314 315 public void setTime(Name name, long value) { 316 317 ValueType valueType = ValueTypeFactory.TIME_TYPE; 318 319 DateTimeData o = DateTimeData.fromSqlTime(new Time(value)); 320 Value fieldValue = new ScalarValue(o, valueType); 321 setValue(name, fieldValue); 322 } 323 324 /** 325 * Sets a byte[] value for a field. 326 * @param name The field name. 327 * @param value The byte[] value. 328 */ 329 330 public void setHexBinary(Name name, byte[] value) { 331 332 ValueType valueType = ValueTypeFactory.HEX_BINARY_TYPE; 333 if (value != null) { 334 Value fieldValue = new ScalarValue(value, valueType); 335 setValue(name, fieldValue); 336 } else { 337 Value fieldValue = new NullValue(valueType); 338 setValue(name, fieldValue); 339 } 340 } 341 342 /** 343 * Sets a packed decimal value for a field. 344 * @param name the field name. 345 * @param value the packed decimal value. 346 */ 347 348 public void setPackedDecimal(Name name, PackedDecimal value) { 349 350 if (value != null) { 351 ValueType valueType = new PackedDecimalValueType(value.digitCount(), value.decimalPlaces()); 352 Value fieldValue = new ScalarValue(value, valueType); 353 setValue(name, fieldValue); 354 } else { 355 ValueType valueType = new PackedDecimalValueType(0, 0); 356 Value fieldValue = new NullValue(valueType); 357 setValue(name, fieldValue); 358 } 359 } 360 361 /** 362 * Sets a byte value for a field. 363 * @param name The field name. 364 * @param value The byte value. 365 */ 366 367 public void setByte(Name name, byte value) { 368 369 ValueType valueType = ValueTypeFactory.BYTE_TYPE; 370 Value fieldValue = new ScalarValue(new Byte(value), valueType); 371 setValue(name, fieldValue); 372 } 373 374 /** 375 * Sets a Byte value for a field. 376 * @param name The field name. 377 * @param value The Byte value. 378 */ 379 380 public void setByte(Name name, Byte value) { 381 382 ValueType valueType = ValueTypeFactory.BYTE_TYPE; 383 if (value != null) { 384 Value fieldValue = new ScalarValue(value, valueType); 385 setValue(name, fieldValue); 386 } else { 387 Value fieldValue = new NullValue(valueType); 388 setValue(name, fieldValue); 389 } 390 } 391 392 /** 393 * Sets a short value for a field. 394 * @param name The field name. 395 * @param value The short value. 396 */ 397 398 public void setShort(Name name, short value) { 399 400 ValueType valueType = ValueTypeFactory.SHORT_TYPE; 401 Value fieldValue = new ScalarValue(new Short(value), valueType); 402 setValue(name, fieldValue); 403 } 404 405 /** 406 * Sets a Short value for a field. 407 * @param name The field name. 408 * @param value The Short value. 409 */ 410 411 public void setShort(Name name, Short value) { 412 413 ValueType valueType = ValueTypeFactory.SHORT_TYPE; 414 if (value != null) { 415 Value fieldValue = new ScalarValue(value, valueType); 416 setValue(name, fieldValue); 417 } else { 418 Value fieldValue = new NullValue(valueType); 419 setValue(name, fieldValue); 420 } 421 } 422 423 /** 424 * Sets a int value for a field. 425 * @param name The field name. 426 * @param value The int value. 427 */ 428 429 public void setInteger(Name name, int value) { 430 431 ValueType valueType = ValueTypeFactory.INTEGER_TYPE; 432 Value fieldValue = new ScalarValue(new Integer(value), valueType); 433 setValue(name, fieldValue); 434 } 435 436 /** 437 * Sets a Integer value for a field. 438 * @param name The field name. 439 * @param value The Integer value. 440 */ 441 442 public void setInteger(Name name, Integer value) { 443 444 ValueType valueType = ValueTypeFactory.INTEGER_TYPE; 445 if (value != null) { 446 Value fieldValue = new ScalarValue(value, valueType); 447 setValue(name, fieldValue); 448 } else { 449 Value fieldValue = new NullValue(valueType); 450 setValue(name, fieldValue); 451 } 452 } 453 454 /** 455 * Sets a long value for a field. 456 * @param name The field name. 457 * @param value The long value. 458 */ 459 460 public void setLong(Name name, long value) { 461 462 ValueType valueType = ValueTypeFactory.LONG_TYPE; 463 Value fieldValue = new ScalarValue(new Long(value), valueType); 464 setValue(name, fieldValue); 465 } 466 467 /** 468 * Sets a Long value for a field. 469 * @param name The field name. 470 * @param value The Long value. 471 */ 472 473 public void setLong(Name name, Long value) { 474 475 ValueType valueType = ValueTypeFactory.LONG_TYPE; 476 if (value != null) { 477 Value fieldValue = new ScalarValue(value, valueType); 478 setValue(name, fieldValue); 479 } else { 480 Value fieldValue = new NullValue(valueType); 481 setValue(name, fieldValue); 482 } 483 } 484 485 /** 486 * Sets a boolean value for a field. 487 * @param name The field name. 488 * @param value The boolean value. 489 */ 490 491 public void setBoolean(Name name, boolean value) { 492 493 ValueType valueType = ValueTypeFactory.BOOLEAN_TYPE; 494 Value fieldValue = new ScalarValue(new Boolean(value), valueType); 495 setValue(name, fieldValue); 496 } 497 498 /** 499 * Sets a Boolean value for a field. 500 * @param name The field name. 501 * @param value The Boolean value. 502 */ 503 504 public void setBoolean(Name name, Boolean value) { 505 506 ValueType valueType = ValueTypeFactory.BOOLEAN_TYPE; 507 if (value != null) { 508 Value fieldValue = new ScalarValue(value, valueType); 509 setValue(name, fieldValue); 510 } else { 511 Value fieldValue = new NullValue(valueType); 512 setValue(name, fieldValue); 513 } 514 } 515 516 /** 517 * Sets a float value for a field. 518 * @param name The field name. 519 * @param value The float value. 520 */ 521 522 public void setFloat(Name name, float value) { 523 524 ValueType valueType = ValueTypeFactory.FLOAT_TYPE; 525 Value fieldValue = new ScalarValue(new Float(value), valueType); 526 setValue(name, fieldValue); 527 } 528 529 /** 530 * Sets a Float value for a field. 531 * @param name The field name. 532 * @param value The Float value. 533 */ 534 535 public void setFloat(Name name, Float value) { 536 537 ValueType valueType = ValueTypeFactory.FLOAT_TYPE; 538 if (value != null) { 539 Value fieldValue = new ScalarValue(value, valueType); 540 setValue(name, fieldValue); 541 } else { 542 Value fieldValue = new NullValue(valueType); 543 setValue(name, fieldValue); 544 } 545 } 546 547 /** 548 * Sets a double value for a field. 549 * @param name The field name. 550 * @param value The double value. 551 */ 552 553 public void setDouble(Name name, double value) { 554 555 ValueType valueType = ValueTypeFactory.DOUBLE_TYPE; 556 Value fieldValue = new ScalarValue(new Double(value), valueType); 557 setValue(name, fieldValue); 558 } 559 560 /** 561 * Sets a Double value for a field. 562 * @param name The field name. 563 * @param value The Double value. 564 */ 565 566 public void setDouble(Name name, Double value) { 567 568 ValueType valueType = ValueTypeFactory.DOUBLE_TYPE; 569 if (value != null) { 570 Value fieldValue = new ScalarValue(value, valueType); 571 setValue(name, fieldValue); 572 } else { 573 Value fieldValue = new NullValue(valueType); 574 setValue(name, fieldValue); 575 } 576 } 577 578 /** 579 * Sets a BigDecimal value for a field. 580 * @param name The field name. 581 * @param value The BigDecimal value. 582 */ 583 584 public void setBigDecimal(Name name, BigDecimal value) { 585 586 ValueType valueType = ValueTypeFactory.DECIMAL_TYPE; 587 588 if (value != null) { 589 Value fieldValue = new ScalarValue(value, valueType); 590 setValue(name, fieldValue); 591 } else { 592 Value fieldValue = new NullValue(valueType); 593 setValue(name, fieldValue); 594 } 595 } 596 597 /** 598 * Sets a value for a field. 599 * @param name The field name. 600 * @param value The field value. 601 */ 602 603 public void setValue(Name name, Value value) { 604 605 if (value != null) { 606 int index = getFieldIndex(name); 607 if (index == -1) { 608 FieldType fieldType = new DefaultFieldType(name); 609 index = addFieldType(fieldType); 610 } 611 612 setValue(index,value); 613 } 614 } 615 616 /** 617 * Sets a value for a field. 618 * @param fieldType The field type. 619 * @param value The field value. 620 */ 621 622 public void setValue(FieldType fieldType, Value value) { 623 624 if (value != null) { 625 int index = getFieldIndex(fieldType.getName()); 626 if (index == -1) { 627 index = addFieldType(fieldType); 628 } else { 629 fieldTypes[index] = fieldType; 630 } 631 632 setValue(index,value); 633 } 634 } 635 636 /** 637 * Sets a segment value for a field. 638 * @param name The field name. 639 * @param segment The segment value. 640 * @deprecated since ServingXML 0.8.1: replaced by {@link RecordBuilder#setSegments} 641 */ 642 643 @Deprecated 644 public void setField(Name name, Record segment) { 645 setField(name, new Record[]{segment}); 646 } 647 648 /** 649 * Sets a segment array value for a field. 650 * @param name The field name. 651 * @param segments The segment array value. 652 * @deprecated since ServingXML 0.8.1: replaced by {@link RecordBuilder#setSegments} 653 */ 654 655 @Deprecated 656 public void setField(Name name, Record[] segments) { 657 658 if (segments != null) { 659 int index = getFieldIndex(name); 660 if (index == -1) { 661 FieldType fieldType = new DefaultFieldType(name); 662 index = addFieldType(fieldType); 663 } 664 665 Value value = new SegmentArrayValue(segments); 666 setValue(index,value); 667 } 668 } 669 670 /** 671 * Sets a record array value for a field. 672 * @param name The field name. 673 * @param records The record array value. 674 * @deprecated since ServingXML 0.8.3: replaced by {@link 675 * RecordBuilder#setRecords} 676 */ 677 678 @Deprecated 679 public void setSegments(Name name, Record[] records) { 680 setRecords(name, records); 681 } 682 683 /** 684 * Sets a record array value for a field. 685 * @param name The field name. 686 * @param records The record array value. 687 */ 688 689 public void setRecords(Name name, Record[] records) { 690 691 if (records != null) { 692 int index = getFieldIndex(name); 693 if (index == -1) { 694 FieldType fieldType = new DefaultFieldType(name); 695 index = addFieldType(fieldType); 696 } 697 698 Value value = new SegmentArrayValue(records); 699 setValue(index,value); 700 } 701 } 702 703 public Record toRecord() { 704 705 RecordType recordType = getRecordType(); 706 707 Record record = new RecordImpl(recordType,values); 708 709 return record; 710 } 711 712 /** 713 * Gets the number of fields 714 * @return The number of fields 715 */ 716 717 public int fieldCount() { 718 return fieldCount; 719 } 720 721 public RecordType getRecordType() { 722 FieldType[] types = new FieldType[fieldCount]; 723 System.arraycopy(fieldTypes, 0, types, 0, fieldCount); 724 RecordType recordType = new RecordTypeImpl(recordTypeName,types); 725 return recordType; 726 } 727 728 public Value getValue(Name name) { 729 int index = getFieldIndex(name); 730 return index == -1 ? null : values[index]; 731 } 732 733 public Value getValue(int index) { 734 return values[index]; 735 } 736 737 public Name getFieldName(int i) { 738 return fieldTypes[i].getName(); 739 } 740 741 protected int getFieldIndex(Name name) { 742 int index = -1; 743 for (int i = 0; index == -1 && i < fieldCount; ++i) { 744 if (fieldTypes[i].getName().equals(name)) { 745 index = i; 746 } 747 } 748 return index; 749 } 750 751 /** 752 * Adds a field type. 753 * @param fieldType A field type. 754 */ 755 756 protected int addFieldType(FieldType fieldType) { 757 if (fieldCount+1 >= fieldTypes.length) { 758 int capacity = fieldTypes.length < 10 ? 10 : fieldTypes.length*2; 759 FieldType[] newFields = new FieldType[capacity]; 760 System.arraycopy(fieldTypes, 0, newFields, 0, fieldTypes.length); 761 fieldTypes = newFields; 762 } 763 int index = fieldCount; 764 fieldTypes[index] = fieldType; 765 fieldCount++; 766 767 return index; 768 } 769 770 public void clear() { 771 this.values = new Value[fieldCount]; 772 for (int i = 0; i < fieldCount; ++i) { 773 values[i] = Value.EMPTY; 774 } 775 } 776 777 public void writeToContentHandler(PrefixMap prefixMap, ContentHandler handler) 778 throws SAXException { 779 780 //System.out.println(getClass().getName()+".writeToContentHandler start"); 781 String qname = recordTypeName.toQname(prefixMap); 782 String namespaceUri = recordTypeName.getNamespaceUri(); 783 if (namespaceUri.length() > 0) { 784 String prefix = prefixMap.getPrefix(namespaceUri); 785 if (!prefixMap.containsPrefixMapping(prefix, namespaceUri)) { 786 PrefixMapImpl newPrefixMap = new PrefixMapImpl(prefixMap); 787 newPrefixMap.setPrefixMapping(prefix,namespaceUri); 788 prefixMap = newPrefixMap; 789 handler.startPrefixMapping(prefix,namespaceUri); 790 } 791 } 792 handler.startElement(namespaceUri,recordTypeName.getLocalName(),qname, FieldType.EMPTY_ATTRIBUTES); 793 for (int i = 0; i < fieldCount; ++i) { 794 FieldType fieldType = fieldTypes[i]; 795 Value value = values[i]; 796 //System.out.println(value.getClass().getName()); 797 value.writeToContentHandler(fieldType.getName(), prefixMap, handler); 798 } 799 handler.endElement(namespaceUri,recordTypeName.getLocalName(),qname); 800 //System.out.println(getClass().getName()+".writeToContentHandler end"); 801 } 802 803 public String[] getStringArray(Name name) { 804 String[] sa = null; 805 806 int index = getFieldIndex(name); 807 if (index != -1) { 808 Value value = values[index]; 809 sa = value.getStringArray(); 810 } 811 return sa; 812 } 813 814 public String getString(Name name) { 815 String s = null; 816 int index = getFieldIndex(name); 817 if (index != -1) { 818 Value value = values[index]; 819 s = value.getString(); 820 } 821 return s; 822 } 823 824 public Object getObject(Name name) { 825 Object o = null; 826 int index = getFieldIndex(name); 827 if (index != -1) { 828 Value value = values[index]; 829 o = value.getObject(); 830 } 831 return o; 832 } 833 } 834 835 836 837