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