1 /***
2 * Copyright (c) 2002, CodeStreet LLC. All rights reserved.<p>
3 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
4 * conditions are met:<p>
5 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
7 * in the documentation and/or other materials provided with the distribution. Neither the name of CodeStreet LLC. nor the
8 * names of its contributors may be used to endorse or promote products derived from this software without specific prior written
9 * permission.<p>
10 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
11 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
12 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
15 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.<p>
16 */
17
18 package com.codestreet.messageforge;
19
20 import com.tibco.tibrv.TibrvMsg;
21 import com.tibco.tibrv.TibrvMsgField;
22 import com.tibco.tibrv.TibrvException;
23 import java.io.IOException;
24 import java.io.ObjectInputStream;
25 import java.io.ObjectOutputStream;
26
27 /***
28 * Class to represent a <tt>TibrvMsg[]</tt> field.
29 * @see com.tibco.tibrv.TibrvMsg
30 * @author Jawaid Hakim.
31 */
32 public class RFldTibrvMsgArray extends RFldArray
33 {
34 /***
35 * Constructor.
36 * @param name Field name. Field names must follow the TibrvMsg
37 * field naming conventions.
38 * @param fieldId Field id. Field ids must be either <tt>0</tt>
39 * to indicate that there is no id on the field, or greater. In addition,
40 * field ids must be unique within a messages - no two fields are allowed
41 * to have the same field id.
42 * @see com.tibco.tibrv.TibrvMsg
43 */
44 public RFldTibrvMsgArray(String name, int fieldId)
45 {
46 super(name, fieldId);
47 }
48
49 /***
50 * Constructor.
51 * @param name Field name. Field names must follow the TibrvMsg
52 * field naming conventions.
53 * @param fieldId Field id. Field ids must be either <tt>0</tt>
54 * to indicate that there is no id on the field, or greater. In addition,
55 * field ids must be unique within a messages - no two fields are allowed
56 * to have the same field id.
57 * @param desc Field description.
58 * @see com.tibco.tibrv.TibrvMsg
59 */
60 public RFldTibrvMsgArray(String name, int fieldId, String desc)
61 {
62 super(name, fieldId, desc);
63 }
64
65 /***
66 * Get field type.
67 * @return Field type <tt>MSGARRAY</tt>.
68 * @see RFldType
69 */
70 public final RFldType getType()
71 {
72 return RFldType.MSGARRAY;
73 }
74
75 /***
76 * Check if another field is equal to this field. Equality is defined as both array instances
77 * having the same number of elements, and each element containing fields with same name
78 * and type.
79 * @param anObject Another field.
80 * @return <tt>true</tt> if another field is equal to this field.
81 * Otherwise, returns <tt>false</tt>.
82 */
83 public boolean equals(Object anObject)
84 {
85 if (this == anObject)
86 {
87 return true;
88 }
89 else if (! (anObject instanceof RFldTibrvMsgArray))
90 {
91 return false;
92 }
93
94 RFldTibrvMsgArray another = (RFldTibrvMsgArray)anObject;
95
96 if (valSet_ != another.isValSet())
97 return false;
98 else if (! valSet_)
99 return true;
100 else if (dataObj_.length != another.length())
101 return false;
102
103 TibrvMsg[] anotherElems = another.getValue();
104 for (int i = dataObj_.length - 1; i >= 0; --i)
105 {
106 TibrvMsg elem = dataObj_[i];
107 TibrvMsg anotherElem = anotherElems[i];
108 for (int j = elem.getNumFields() - 1; j >= 0; --j)
109 {
110 try
111 {
112 TibrvMsgField rvFld = elem.getFieldByIndex(j);
113 TibrvMsgField anotherRvFld = anotherElem.getField(rvFld.name);
114 if (rvFld.type != anotherRvFld.type)
115 return false;
116 }
117 catch (TibrvException ex)
118 {
119 return false;
120 }
121 }
122 }
123 return true;
124 }
125
126 /***
127 * Get the number of elements in the array.
128 * @return Number of elements in the array. If the value is not set
129 * returns <tt>-1</tt>.
130 */
131 public int length()
132 {
133 return (! valSet_) ? -1 : dataObj_.length;
134 }
135
136 /***
137 * Get an element from the array.
138 * @param index Array index.
139 * @return Specified element. Returns <tt>null</tt> if the index
140 * is out of bounds or the value is not set.
141 * @see #length()
142 */
143 public TibrvMsg getElement(int index)
144 {
145 return (valSet_ && index >= 0 && index < dataObj_.length) ? dataObj_[index] : null;
146 }
147
148 /***
149 * Returns the hash code value for the field. Since the equals method
150 * is using the comparison of the string representation of the TibrvMsg
151 * then the hashcode is the hashcode of this string.
152 * @return A hash code value for the field.
153 */
154 public int hashCode()
155 {
156 int hash = 17;
157 if (valSet_)
158 {
159 for (int i = dataObj_.length - 1; i >= 0; --i)
160 hash = 31 * hash + dataObj_[i].hashCode();
161 }
162 return hash;
163 }
164
165 /***
166 * Reset the field value.
167 * @see #isValSet()
168 */
169 public void reset() throws FieldValidationException
170 {
171 if (isLocked())
172 throw new FieldValidationException("Field " + getName() + " is locked");
173
174 if (valSet_)
175 {
176 valSet_ = false;
177 dataObj_ = null;
178 }
179 }
180
181 /***
182 * Set data.
183 * @param newData New data.
184 */
185 public RFld set(Object newData) throws FieldValidationException
186 {
187 if (newData instanceof TibrvMsg[])
188 return set((TibrvMsg[])newData);
189 else if (newData instanceof TibrvMsg)
190 return set((TibrvMsg)newData);
191 else if (newData != null)
192 throw new FieldValidationException("Unsupported value type: " + newData.getClass().getName());
193 else
194 throw new FieldValidationException("New value is NULL for field: " + getName());
195 }
196
197 /***
198 * Set data.
199 * @param newData New data.
200 */
201 public RFld set(TibrvMsg newData) throws FieldValidationException
202 {
203 try
204 {
205 TibrvMsg[] elements = new TibrvMsg[newData.getNumFields()];
206 for (int i = 0; i < elements.length; ++i)
207 {
208 elements[i] = (TibrvMsg)newData.get(String.valueOf(i));
209 }
210
211 return set(elements);
212 }
213 catch (Exception ex)
214 {
215 throw new FieldValidationException(ex);
216 }
217 }
218
219 /***
220 * Set data.
221 * @param newData New data.
222 */
223 public RFld set(TibrvMsg[] newData) throws FieldValidationException
224 {
225 validate(newData);
226
227 dataObj_ = newData;
228 valSet_ = true;
229
230 return this;
231 }
232
233 /***
234 * Set data.
235 * @param newData New data.
236 */
237 public RFld set(java.util.Hashtable newData) throws FieldValidationException
238 {
239 try
240 {
241 synchronized (newData)
242 {
243 TibrvMsg[] elements = new TibrvMsg[newData.size()];
244 for (int i = elements.length - 1; i >= 0; --i)
245 {
246 Object fldValue = newData.get(String.valueOf(i));
247 if (fldValue instanceof java.util.Hashtable)
248 {
249 elements[i] = new TibrvMsg();
250 set((java.util.Hashtable)fldValue, elements[i]);
251 }
252 else
253 throw new FieldValidationException("Expected a java.util.Hashtable");
254 }
255 return set(elements);
256 }
257 }
258 catch (ProtocolException ex)
259 {
260 throw new FieldValidationException(ex);
261 }
262 }
263
264 /***
265 * Set data.
266 * @param source Source <tt>java.util.Hashtable</tt>.
267 * @param target Target <tt>com.tibco.tibrv.TibrvMsg</tt>.
268 */
269 protected void set(java.util.Hashtable source, TibrvMsg target) throws ProtocolException
270 {
271 try
272 {
273 synchronized (source)
274 {
275 for (java.util.Enumeration enum = source.keys(); enum.hasMoreElements(); )
276 {
277 String nestedFldName = (String)enum.nextElement();
278 Object nestedFldValue = source.get(nestedFldName);
279 if (nestedFldValue instanceof java.util.Hashtable)
280 {
281 TibrvMsg nestedRvMsg = new TibrvMsg();
282 set((java.util.Hashtable)nestedFldValue, nestedRvMsg);
283 target.add(nestedFldName, nestedRvMsg);
284 }
285 else
286 target.add(nestedFldName, nestedFldValue);
287 }
288 }
289 }
290 catch (TibrvException ex)
291 {
292 throw new ProtocolException(ex);
293 }
294 }
295
296 /***
297 * Set the field value from a JDOM element.
298 * @param elem Field value as a JDOM element.
299 */
300 public final RFld set(org.jdom.Element elem) throws FieldValidationException
301 {
302 java.util.List children = elem.getChildren();
303 if (children.size() > 0)
304 {
305 TibrvMsg[] newData = new TibrvMsg[children.size()];
306 for (int i = newData.length - 1; i >= 0; --i)
307 {
308 org.jdom.Element child = (org.jdom.Element)children.get(i);
309 TibrvMsg rvMsg = new TibrvMsg();
310 RFldTibrvMsg.set(rvMsg, child.getChildren());
311
312 int index = Integer.valueOf(child.getAttributeValue(XML_ATTR_NAME)).intValue();
313 newData[index] = rvMsg;
314 }
315 set(newData);
316 }
317 return this;
318 }
319
320 /***
321 * Validate against constraints. A field is valid if either it's value is set
322 * and satisfies all constraints, or the the field is optional.
323 */
324 public void validate() throws FieldValidationException
325 {
326 // Only need to check that non-optional fields have been set. If a
327 // field has been set then it must be valid since validation is done
328 // with each set.
329 if (! valSet_ && !optional_)
330 throw new FieldValidationException("Field not set: " + getName());
331 }
332
333 /***
334 * Check if a new value will satifsy constraints.
335 * @param newData New value.
336 */
337 public void validate(TibrvMsg[] newData) throws FieldValidationException
338 {
339 if (locked_)
340 throw new FieldValidationException("Cannot modify locked field: " + getName());
341
342 if (newData == null)
343 throw new FieldValidationException("New value is NULL for field: " + getName());;
344 }
345
346 /***
347 * Get data.
348 * @return data Data. Returns <tt>null</tt> if
349 * the field value is not set
350 */
351 public TibrvMsg[] getValue()
352 {
353 return dataObj_;
354 }
355
356 /***
357 * Get the field value as an object.
358 * @return Field value as an object. Reference to data is passed out so be
359 * very careful about modifying the data. Returns <tt>null</tt> if
360 * the field value is not set
361 */
362 public Object getValueAsObject()
363 {
364 return dataObj_;
365 }
366
367 /***
368 * Get the field value as a string. Throws an exception if the field
369 * value is not set.
370 * @return Field value as a string.
371 */
372 public String getValueAsString()
373 {
374 if (valSet_)
375 return null;
376
377 StringBuffer buf = new StringBuffer((80 * dataObj_.length) + 1);
378 buf.append(RMsg.NESTED_FIELD_START);
379 for (int i = 0; i < dataObj_.length; ++i)
380 {
381 buf.append(String.valueOf(i)).append(RMsg.FIELD_EQUAL).append(dataObj_[i].toString());
382 }
383 buf.append(RMsg.NESTED_FIELD_END);
384
385 return buf.toString();
386 }
387
388 /***
389 * Get the field value as a <tt>java.util.Hashtable</tt>.
390 * @return Field value as a <tt>java.util.Hashtable</tt>.
391 */
392 public java.util.Hashtable getValueAsHashtable() throws FieldValidationException
393 {
394 if (! valSet_)
395 throw new FieldValidationException("Field not set: " + getName());
396
397 java.util.Hashtable hashTbl = new java.util.Hashtable(2 * dataObj_.length + 1);
398 synchronized (hashTbl)
399 {
400 for (int i = 0; i < dataObj_.length; ++i)
401 hashTbl.put(String.valueOf(i), getValueAsHashtable(dataObj_[i]));
402 }
403 return hashTbl;
404 }
405
406 /***
407 * Convert a TibrvMsg to a java.util.Hashtable.
408 * @param rvMsg TibrvMsg.
409 * @return TibrvMsg value as java.util.Hashtable.
410 */
411 protected java.util.Hashtable getValueAsHashtable(TibrvMsg rvMsg) throws FieldValidationException
412 {
413 try
414 {
415 int fldCount = rvMsg.getNumFields();
416 java.util.Hashtable flds = new java.util.Hashtable(2 * fldCount + 1);
417 synchronized (flds)
418 {
419 for (int i = 0; i < fldCount; ++i)
420 {
421 TibrvMsgField fld = rvMsg.getFieldByIndex(i);
422 if (fld.data instanceof TibrvMsg)
423 flds.put(fld.name, getValueAsHashtable((TibrvMsg)fld.data));
424 else
425 flds.put(fld.name, fld.data);
426 }
427 }
428 return flds;
429 }
430 catch (TibrvException ex)
431 {
432 throw new FieldValidationException(ex);
433 }
434 }
435
436
437 /***
438 * Write the field as XML to target writer.
439 * @param writer Output target.
440 * @param indent Indentation.
441 * @param newLines Newlines are inserted after each element if <tt>true</tt>.
442 * @param expandEmptyElements Empty elements - elements with no content - are expanded if <tt>true</tt>.
443 */
444 public void marshal(java.io.Writer writer, int indentLevel, String indent, boolean newLines, boolean expandEmptyElements) throws ConverterException
445 {
446 if (! isValSet())
447 throw new ConverterException("Field not set: " + getName());
448
449 marshal(writer, getTag(), getName(), getValueAsObject(), getType().toString(), indentLevel, indent, newLines, expandEmptyElements);
450 }
451
452 /***
453 * Write the field as XML to target writer.
454 * @param writer Output target.
455 * @param tag XML tag.
456 * @param name Field name.
457 * @param value Field value.
458 * @param type Field type.
459 * @param indentLevel Indentation level.
460 * @param indent Indentation <tt>String</tt>.
461 * @param newLines Newlines are inserted after each element if <tt>true</tt>.
462 * @param expandEmptyElements Empty elements - elements with no content - are expanded if <tt>true</tt>.
463 */
464 static void marshal(java.io.Writer writer, String tag, String name, Object value, String type, int indentLevel, String indent, boolean newLines, boolean expandEmptyElements) throws ConverterException
465 {
466 try
467 {
468 ConverterXML.openTag(writer, tag, indentLevel, indent);
469 ConverterXML.writeAttribute(writer, XML_ATTR_NAME, name);
470 ConverterXML.closeStartTag(writer, newLines);
471
472 ++indentLevel;
473 TibrvMsg[] elems = (TibrvMsg[])value;
474 for (int i = elems.length - 1; i >= 0; --i)
475 {
476 RFldTibrvMsg.marshal(writer, RFldTibrvMsg.XML_TAG, String.valueOf(i), elems[i], RFldType.MSG.toString(), indentLevel + 1, indent, newLines, expandEmptyElements);
477 }
478
479 --indentLevel;
480 ConverterXML.closeTag(writer, tag, indentLevel, indent, newLines);
481 }
482 catch (java.io.IOException ex)
483 {
484 throw new ConverterException(ex);
485 }
486 }
487
488
489 /***
490 * Write state of object to object output stream.
491 * @param out Object output stream.
492 */
493 private void writeObject(ObjectOutputStream out) throws IOException
494 {
495 try
496 {
497 if (valSet_)
498 {
499 out.writeInt(dataObj_.length);
500 for (int i = 0; i < dataObj_.length; ++i)
501 out.write(dataObj_[i].getAsBytes());
502 }
503 }
504 catch (TibrvException ex)
505 {
506 throw new IOException(ex.toString());
507 }
508 }
509
510 /***
511 * Read state of object from object input stream.
512 * @param in Object input stream.
513 */
514 private void readObject(ObjectInputStream in) throws IOException
515 {
516 try
517 {
518 if (valSet_)
519 {
520 int length = in.readInt();
521 dataObj_ = new TibrvMsg[length];
522 for (int i = 0; i < length; ++i)
523 dataObj_[i] = new TibrvMsg((byte[])in.readObject());
524 }
525 }
526 catch (TibrvException ex)
527 {
528 throw new IOException(ex.toString());
529 }
530 catch (ClassNotFoundException ex)
531 {
532 throw new IOException(ex.toString());
533 }
534 }
535
536 /***
537 * Get the XML tag for this field type.
538 * @return XML tag for this field type.
539 */
540 public final String getTag()
541 {
542 return XML_TAG;
543 }
544
545 /***
546 * Set the XML tag for this field type.
547 * @param tag New XML tag for this field type.
548 */
549 public static void setTag(String tag)
550 {
551 XML_TAG = tag;
552 }
553
554 /***
555 * XML tag for this element type.
556 */
557 static transient String XML_TAG = "tibrvmsgarray";
558
559 /***
560 * Data.
561 */
562 protected TibrvMsg[] dataObj_;
563 }
This page was automatically generated by Maven