001 package railo.runtime.converter; 002 003 import java.io.IOException; 004 import java.io.StringReader; 005 import java.io.Writer; 006 import java.util.Date; 007 import java.util.HashMap; 008 import java.util.Iterator; 009 import java.util.List; 010 import java.util.ListIterator; 011 import java.util.Map; 012 import java.util.TimeZone; 013 014 import javax.xml.parsers.FactoryConfigurationError; 015 016 import org.apache.xerces.parsers.DOMParser; 017 import org.w3c.dom.Document; 018 import org.w3c.dom.Element; 019 import org.w3c.dom.Node; 020 import org.w3c.dom.NodeList; 021 import org.xml.sax.InputSource; 022 023 import railo.commons.lang.NumberUtil; 024 import railo.runtime.Component; 025 import railo.runtime.ComponentScope; 026 import railo.runtime.ComponentWrap; 027 import railo.runtime.PageContext; 028 import railo.runtime.component.Property; 029 import railo.runtime.engine.ThreadLocalPageContext; 030 import railo.runtime.exp.ExpressionException; 031 import railo.runtime.exp.PageException; 032 import railo.runtime.op.Caster; 033 import railo.runtime.op.date.DateCaster; 034 import railo.runtime.orm.hibernate.HBMCreator; 035 import railo.runtime.text.xml.XMLUtil; 036 import railo.runtime.type.Array; 037 import railo.runtime.type.ArrayImpl; 038 import railo.runtime.type.Collection; 039 import railo.runtime.type.Collection.Key; 040 import railo.runtime.type.KeyImpl; 041 import railo.runtime.type.Query; 042 import railo.runtime.type.QueryImpl; 043 import railo.runtime.type.Struct; 044 import railo.runtime.type.StructImpl; 045 import railo.runtime.type.UDF; 046 import railo.runtime.type.cfc.ComponentAccess; 047 import railo.runtime.type.dt.DateTime; 048 import railo.runtime.type.dt.DateTimeImpl; 049 import railo.runtime.type.util.CollectionUtil; 050 import railo.runtime.type.util.ComponentUtil; 051 import railo.runtime.type.util.KeyConstants; 052 053 /** 054 * class to serialize and desirilize WDDX Packes 055 */ 056 public final class XMLConverter extends ConverterSupport { 057 private static final Collection.Key REMOTING_FETCH = KeyImpl.intern("remotingFetch"); 058 059 private int deep=1; 060 private char _='"'; 061 private TimeZone timeZone; 062 private boolean ignoreRemotingFetch=true; 063 //private PageContext pcx; 064 065 private String type; 066 067 private int id=0; 068 069 /** 070 * constructor of the class 071 * @param timeZone 072 * @param xmlConform define if generated xml conform output or wddx conform output (wddx is not xml conform) 073 */ 074 public XMLConverter(TimeZone timeZone,boolean ignoreRemotingFetch) { 075 this.timeZone=timeZone; 076 this.ignoreRemotingFetch=ignoreRemotingFetch; 077 } 078 079 /** 080 * defines timezone info will 081 * @param timeZone 082 */ 083 public void setTimeZone(TimeZone timeZone) { 084 this.timeZone=timeZone; 085 } 086 087 /** 088 * serialize a Date 089 * @param date Date to serialize 090 * @return serialized date 091 * @throws ConverterException 092 */ 093 private String _serializeDate(Date date) { 094 return _serializeDateTime(new DateTimeImpl(date)); 095 } 096 /** 097 * serialize a DateTime 098 * @param dateTime DateTime to serialize 099 * @return serialized dateTime 100 * @throws ConverterException 101 */ 102 private String _serializeDateTime(DateTime dateTime) { 103 /* ACF FORMAT 104 String strDate = new railo.runtime.format.DateFormat(Locale.US).format(dateTime,"mmmm, dd yyyy"); 105 String strTime = new railo.runtime.format.TimeFormat(Locale.US).format(dateTime,"HH:mm:ss"); 106 return goIn()+strDate+" "+strTime; 107 */ 108 return goIn()+JSONDateFormat.format(dateTime,null); 109 110 // HTTP TIME STRING return goIn()+GetHttpTimeString.invoke(dateTime); 111 } 112 113 /** 114 * serialize a Array 115 * @param array Array to serialize 116 * @param done 117 * @return serialized array 118 * @throws ConverterException 119 */ 120 private String _serializeArray(Array array, Map<Object,String> done, String id) throws ConverterException { 121 return _serializeList(array.toList(),done,id); 122 } 123 124 /** 125 * serialize a List (as Array) 126 * @param list List to serialize 127 * @param done 128 * @return serialized list 129 * @throws ConverterException 130 */ 131 private String _serializeList(List list, Map<Object,String> done, String id) throws ConverterException { 132 // <ARRAY ID="1" SIZE="1"><ITEM INDEX="1" TYPE="STRING">hello world</ITEM></ARRAY> 133 StringBuffer sb=new StringBuffer(goIn()+"<ARRAY ID=\""+id+"\" SIZE="+_+list.size()+_+">"); 134 int index; 135 ListIterator it=list.listIterator(); 136 while(it.hasNext()) { 137 //<ITEM INDEX="1" TYPE="STRING">hello world</ITEM> 138 index=it.nextIndex(); 139 String value = _serialize(it.next(),done); 140 sb.append(goIn()+"<ITEM INDEX=\""+(index+1)+"\" TYPE=\""+type+"\">"); 141 sb.append(value); 142 sb.append(goIn()+"</ITEM>"); 143 } 144 145 sb.append(goIn()+"</ARRAY>"); 146 type="ARRAY"; 147 return sb.toString(); 148 } 149 150 /** 151 * serialize a Component 152 * @param component Component to serialize 153 * @param done 154 * @return serialized component 155 * @throws ConverterException 156 */ 157 private String _serializeComponent(Component component, Map<Object,String> done) throws ConverterException { 158 StringBuffer sb=new StringBuffer(); 159 ComponentAccess ca; 160 try { 161 component=new ComponentWrap(Component.ACCESS_PRIVATE, ca=ComponentUtil.toComponentAccess(component)); 162 } catch (ExpressionException e1) { 163 throw toConverterException(e1); 164 } 165 boolean isPeristent=ca.isPersistent(); 166 167 168 deep++; 169 Object member; 170 Iterator<Key> it = component.keyIterator(); 171 Collection.Key key; 172 while(it.hasNext()) { 173 key=it.next(); 174 member = component.get(key,null); 175 if(member instanceof UDF) continue; 176 sb.append(goIn()+"<var scope=\"this\" name="+_+key.toString()+_+">"); 177 sb.append(_serialize(member,done)); 178 sb.append(goIn()+"</var>"); 179 } 180 181 Property p; 182 Boolean remotingFetch; 183 Struct props = ignoreRemotingFetch?null:ComponentUtil.getPropertiesAsStruct(ca,false); 184 ComponentScope scope = ca.getComponentScope(); 185 it=scope.keyIterator(); 186 while(it.hasNext()) { 187 key=Caster.toKey(it.next(),null); 188 if(!ignoreRemotingFetch) { 189 p=(Property) props.get(key,null); 190 if(p!=null) { 191 remotingFetch=Caster.toBoolean(p.getDynamicAttributes().get(REMOTING_FETCH,null),null); 192 if(remotingFetch==null){ 193 if(isPeristent && HBMCreator.isRelated(p)) continue; 194 } 195 else if(!remotingFetch.booleanValue()) continue; 196 } 197 } 198 199 member = scope.get(key,null); 200 if(member instanceof UDF || key.equals(KeyConstants._this)) continue; 201 sb.append(goIn()+"<var scope=\"variables\" name="+_+key.toString()+_+">"); 202 sb.append(_serialize(member,done)); 203 sb.append(goIn()+"</var>"); 204 } 205 206 207 deep--; 208 try { 209 //return goIn()+"<struct>"+sb+"</struct>"; 210 return goIn()+"<component md5=\""+ComponentUtil.md5(component)+"\" name=\""+component.getAbsName()+"\">"+sb+"</component>"; 211 } 212 catch (Exception e) { 213 throw toConverterException(e); 214 } 215 } 216 217 /** 218 * serialize a Struct 219 * @param struct Struct to serialize 220 * @param done 221 * @return serialized struct 222 * @throws ConverterException 223 */ 224 private String _serializeStruct(Struct struct, Map<Object,String> done, String id) throws ConverterException { 225 StringBuffer sb=new StringBuffer(goIn()+"<STRUCT ID=\""+id+"\">"); 226 227 Iterator<Key> it = struct.keyIterator(); 228 229 deep++; 230 while(it.hasNext()) { 231 Key key = it.next(); 232 // <ENTRY NAME="STRING" TYPE="STRING">hello</ENTRY> 233 String value = _serialize(struct.get(key,null),done); 234 sb.append(goIn()+"<ENTRY NAME=\""+key.toString()+"\" TYPE=\""+type+"\">"); 235 sb.append(value); 236 sb.append(goIn()+"</ENTRY>"); 237 } 238 deep--; 239 240 sb.append(goIn()+"</STRUCT>"); 241 type="STRUCT"; 242 return sb.toString(); 243 } 244 245 /** 246 * serialize a Map (as Struct) 247 * @param map Map to serialize 248 * @param done 249 * @return serialized map 250 * @throws ConverterException 251 */ 252 private String _serializeMap(Map map, Map<Object,String> done) throws ConverterException { 253 StringBuffer sb=new StringBuffer(goIn()+"<struct>"); 254 255 Iterator it=map.keySet().iterator(); 256 257 deep++; 258 while(it.hasNext()) { 259 Object key=it.next(); 260 sb.append(goIn()+"<var name="+_+key.toString()+_+">"); 261 sb.append(_serialize(map.get(key),done)); 262 sb.append(goIn()+"</var>"); 263 } 264 deep--; 265 266 sb.append(goIn()+"</struct>"); 267 return sb.toString(); 268 } 269 270 /** 271 * serialize a Query 272 * @param query Query to serialize 273 * @param done 274 * @return serialized query 275 * @throws ConverterException 276 */ 277 private String _serializeQuery(Query query, Map<Object,String> done, String id) throws ConverterException { 278 279 /*<QUERY ID="1"> 280 * <COLUMNNAMES> 281 * <COLUMN NAME="a"></COLUMN> 282 * <COLUMN NAME="b"></COLUMN> 283 * </COLUMNNAMES> 284 * 285 * <ROWS> 286 * <ROW> 287 * <COLUMN TYPE="STRING">a1</COLUMN> 288 * <COLUMN TYPE="STRING">b1</COLUMN> 289 * </ROW> 290 * <ROW> 291 * <COLUMN TYPE="STRING">a2</COLUMN> 292 * <COLUMN TYPE="STRING">b2</COLUMN> 293 * </ROW> 294 * </ROWS> 295 * </QUERY> 296 */ 297 Collection.Key[] keys = CollectionUtil.keys(query); 298 StringBuffer sb=new StringBuffer(goIn()+"<QUERY ID=\""+id+"\">"); 299 300 // columns 301 sb.append(goIn()+"<COLUMNNAMES>"); 302 for(int i=0;i<keys.length;i++) { 303 sb.append(goIn()+"<COLUMN NAME=\""+keys[i].getString()+"\"></COLUMN>"); 304 } 305 sb.append(goIn()+"</COLUMNNAMES>"); 306 307 String value; 308 deep++; 309 sb.append(goIn()+"<ROWS>"); 310 int len=query.getRecordcount(); 311 for(int row=1;row<=len;row++) { 312 sb.append(goIn()+"<ROW>"); 313 for(int col=0;col<keys.length;col++) { 314 try { 315 value=_serialize(query.getAt(keys[col],row),done); 316 } catch (PageException e) { 317 value=_serialize(e.getMessage(),done); 318 } 319 sb.append("<COLUMN TYPE=\""+type+"\">"+value+"</COLUMN>"); 320 } 321 sb.append(goIn()+"</ROW>"); 322 323 } 324 sb.append(goIn()+"</ROWS>"); 325 deep--; 326 327 sb.append(goIn()+"</QUERY>"); 328 type="QUERY"; 329 return sb.toString(); 330 } 331 332 /** 333 * serialize a Object to his xml Format represenation 334 * @param object Object to serialize 335 * @param done 336 * @return serialized Object 337 * @throws ConverterException 338 */ 339 private String _serialize(Object object, Map<Object,String> done) throws ConverterException { 340 341 type="OBJECT"; 342 343 String rtn; 344 deep++; 345 // NULL 346 if(object==null) { 347 rtn= goIn()+""; 348 deep--; 349 type="NULL"; 350 return rtn; 351 } 352 // String 353 if(object instanceof String) { 354 rtn= goIn()+XMLUtil.escapeXMLString(object.toString()); 355 deep--; 356 type="STRING"; 357 return rtn; 358 } 359 // Number 360 if(object instanceof Number) { 361 rtn= goIn()+((Number)object).doubleValue(); 362 deep--; 363 type="NUMBER"; 364 return rtn; 365 } 366 // Boolean 367 if(object instanceof Boolean) { 368 rtn= goIn()+((Boolean)object).booleanValue(); 369 deep--; 370 type="BOOLEAN"; 371 return rtn; 372 } 373 // DateTime 374 if(object instanceof DateTime) { 375 rtn= _serializeDateTime((DateTime)object); 376 deep--; 377 type="DATE"; 378 return rtn; 379 } 380 // Date 381 if(object instanceof Date) { 382 rtn= _serializeDate((Date)object); 383 deep--; 384 type="DATE"; 385 return rtn; 386 } 387 388 Object raw = LazyConverter.toRaw(object); 389 String strId=done.get(raw); 390 if(strId!=null){ 391 rtn= goIn()+"<REF id=\""+strId+"\"\\>"; 392 deep--; 393 type="NULL"; 394 return rtn; 395 } 396 strId=Caster.toString(++this.id); 397 done.put(raw,strId); 398 try { 399 // Component 400 if(object instanceof Component) { 401 rtn= _serializeComponent((Component)object,done); 402 deep--; 403 return rtn; 404 } 405 // Struct 406 if(object instanceof Struct) { 407 rtn= _serializeStruct((Struct)object,done,strId); 408 deep--; 409 return rtn; 410 } 411 // Map 412 if(object instanceof Map) { 413 rtn= _serializeMap((Map)object,done); 414 deep--; 415 return rtn; 416 } 417 // Array 418 if(object instanceof Array) { 419 rtn= _serializeArray((Array)object,done,strId); 420 deep--; 421 return rtn; 422 } 423 // List 424 if(object instanceof List) { 425 rtn= _serializeList((List)object,done,strId); 426 deep--; 427 return rtn; 428 } 429 // Query 430 if(object instanceof Query) { 431 rtn= _serializeQuery((Query)object,done,strId); 432 deep--; 433 return rtn; 434 } 435 } 436 finally{ 437 done.remove(raw); 438 } 439 // Others 440 rtn="<STRUCT ID=\""+strId+"\" TYPE=\""+Caster.toTypeName(object)+"\"></STRUCT>"; 441 deep--; 442 return rtn; 443 } 444 445 @Override 446 public void writeOut(PageContext pc, Object source, Writer writer) throws ConverterException, IOException { 447 writer.write(serialize(source)); 448 writer.flush(); 449 } 450 451 /** 452 * serialize a Object to his xml Format represenation and create a valid wddx representation 453 * @param object Object to serialize 454 * @return serialized wddx package 455 * @throws ConverterException 456 */ 457 public String serialize(Object object) throws ConverterException { 458 deep=0; 459 460 StringBuffer sb=new StringBuffer(); 461 //if(xmlConform)sb.append("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>"); 462 deep++; 463 sb.append(_serialize(object,new HashMap<Object,String>())); 464 deep--; 465 return sb.toString(); 466 } 467 468 469 /** 470 * deserialize a WDDX Package (XML String Representation) to a runtime object 471 * @param strWddx 472 * @param validate 473 * @return Object represent WDDX Package 474 * @throws ConverterException 475 * @throws IOException 476 * @throws FactoryConfigurationError 477 */ 478 public Object deserialize(String strWddx, boolean validate) throws ConverterException, IOException, FactoryConfigurationError { 479 try { 480 DOMParser parser = new DOMParser(); 481 if(validate) parser.setEntityResolver(new WDDXEntityResolver()); 482 483 parser.parse(new InputSource(new StringReader(strWddx))); 484 Document doc=parser.getDocument(); 485 486 // WDDX Package 487 NodeList docChldren = doc.getChildNodes(); 488 Node wddxPacket=doc; 489 int len = docChldren.getLength(); 490 for(int i = 0; i < len; i++) { 491 Node node=docChldren.item(i); 492 if(node.getNodeName().equalsIgnoreCase("wddxPacket")) { 493 wddxPacket=node; 494 break; 495 } 496 } 497 498 NodeList nl = wddxPacket.getChildNodes(); 499 int n = nl.getLength(); 500 501 502 for(int i = 0; i < n; i++) { 503 Node data = nl.item(i); 504 if(data.getNodeName().equals("data")) { 505 NodeList list=data.getChildNodes(); 506 len=list.getLength(); 507 for(int y=0;y<len;y++) { 508 Node node=list.item(y); 509 if(node instanceof Element) 510 return _deserialize((Element)node); 511 512 } 513 } 514 } 515 516 throw new IllegalArgumentException("Invalid WDDX Format: node 'data' not found in WDD packet"); 517 518 } 519 catch(org.xml.sax.SAXException sxe) { 520 throw new IllegalArgumentException("XML Error: " + sxe.toString()); 521 } 522 } 523 524 525 526 /** 527 * deserialize a WDDX Package (XML Element) to a runtime object 528 * @param element 529 * @return deserialized Element 530 * @throws ConverterException 531 */ 532 private Object _deserialize(Element element) throws ConverterException { 533 String nodeName=element.getNodeName().toLowerCase(); 534 535 // NULL 536 if(nodeName.equals("null")) { 537 return null; 538 } 539 // String 540 else if(nodeName.equals("string")) { 541 return _deserializeString(element); 542 /*Node data=element.getFirstChild(); 543 if(data==null) return ""; 544 545 String value=data.getNodeValue(); 546 547 if(value==null) return ""; 548 return XMLUtil.unescapeXMLString(value);*/ 549 } 550 // Number 551 else if(nodeName.equals("number")) { 552 try { 553 Node data=element.getFirstChild(); 554 if(data==null) return new Double(0); 555 return Caster.toDouble(data.getNodeValue()); 556 } catch (Exception e) { 557 throw toConverterException(e); 558 } 559 } 560 // Boolean 561 else if(nodeName.equals("boolean")) { 562 try { 563 return Caster.toBoolean(element.getAttribute("value")); 564 } catch (PageException e) { 565 throw toConverterException(e); 566 567 } 568 } 569 // Array 570 else if(nodeName.equals("array")) { 571 return _deserializeArray(element); 572 } 573 // Component 574 else if(nodeName.equals("component")) { 575 return _deserializeComponent(element); 576 } 577 // Struct 578 else if(nodeName.equals("struct")) { 579 return _deserializeStruct(element); 580 } 581 // Query 582 else if(nodeName.equals("recordset")) { 583 return _deserializeQuery(element); 584 } 585 // DateTime 586 else if(nodeName.equalsIgnoreCase("dateTime")) { 587 try { 588 return DateCaster.toDateAdvanced(element.getFirstChild().getNodeValue(),timeZone); 589 } 590 catch (Exception e) { 591 throw toConverterException(e); 592 } 593 } 594 else 595 throw new ConverterException("can't deserialize Element of type ["+nodeName+"] to a Object representation"); 596 597 } 598 599 private Object _deserializeString(Element element) { 600 NodeList childList = element.getChildNodes(); 601 int len = childList.getLength(); 602 StringBuffer sb=new StringBuffer(); 603 Node data; 604 String str; 605 for(int i=0;i<len;i++) { 606 data=childList.item(i); 607 if(data==null)continue; 608 609 //<char code="0a"/> 610 if("char".equals(data.getNodeName())) { 611 str=((Element)data).getAttribute("code"); 612 sb.append((char)NumberUtil.hexToInt(str, 10)); 613 } 614 else { 615 sb.append(str=data.getNodeValue()); 616 } 617 } 618 return sb.toString(); 619 //return XMLUtil.unescapeXMLString(sb.toString()); 620 } 621 622 /** 623 * Desirialize a Query Object 624 * @param recordset Query Object as XML Element 625 * @return Query Object 626 * @throws ConverterException 627 */ 628 private Object _deserializeQuery(Element recordset) throws ConverterException { 629 try { 630 // create Query Object 631 Query query=new QueryImpl( 632 railo.runtime.type.util.ListUtil.listToArray( 633 recordset.getAttribute("fieldNames"),',' 634 ) 635 ,Caster.toIntValue(recordset.getAttribute("rowCount")),"query" 636 ); 637 638 NodeList list = recordset.getChildNodes(); 639 int len=list.getLength(); 640 for(int i=0;i<len;i++) { 641 Node node=list.item(i); 642 if(node instanceof Element) { 643 _deserializeQueryField(query,(Element) node); 644 } 645 } 646 return query; 647 } 648 catch(PageException e) { 649 throw toConverterException(e); 650 } 651 652 } 653 654 /** 655 * deserilize a single Field of a query WDDX Object 656 * @param query 657 * @param field 658 * @throws ConverterException 659 * @throws PageException 660 */ 661 private void _deserializeQueryField(Query query,Element field) throws PageException, ConverterException { 662 String name=field.getAttribute("name"); 663 NodeList list = field.getChildNodes(); 664 int len=list.getLength(); 665 int count=0; 666 for(int i=0;i<len;i++) { 667 Node node=list.item(i); 668 if(node instanceof Element) { 669 query.setAt(name,++count,_deserialize((Element) node)); 670 } 671 } 672 673 } 674 675 /** 676 * Desirialize a Component Object 677 * @param elComp Component Object as XML Element 678 * @return Component Object 679 * @throws ConverterException 680 * @throws ConverterException 681 */ 682 private Object _deserializeComponent(Element elComp) throws ConverterException { 683 // String type=elStruct.getAttribute("type"); 684 String name=elComp.getAttribute("name"); 685 String md5=elComp.getAttribute("md5"); 686 687 // TLPC 688 PageContext pc = ThreadLocalPageContext.get(); 689 690 // Load comp 691 ComponentAccess comp=null; 692 try { 693 comp = ComponentUtil.toComponentAccess(pc.loadComponent(name)); 694 if(!ComponentUtil.md5(comp).equals(md5)){ 695 throw new ConverterException("component ["+name+"] in this enviroment has not the same interface as the component to load"); 696 } 697 } 698 catch (ConverterException e) { 699 throw e; 700 } 701 catch (Exception e) { 702 throw new ConverterException(e.getMessage()); 703 } 704 705 706 NodeList list=elComp.getChildNodes(); 707 ComponentScope scope = comp.getComponentScope(); 708 int len=list.getLength(); 709 String scopeName; 710 Element var,value; 711 Collection.Key key; 712 for(int i=0;i<len;i++) { 713 Node node=list.item(i); 714 if(node instanceof Element) { 715 var=(Element)node; 716 value=getChildElement((Element)node); 717 scopeName=var.getAttribute("scope"); 718 if(value!=null) { 719 key=Caster.toKey(var.getAttribute("name"),null); 720 if(key==null) continue; 721 if("variables".equalsIgnoreCase(scopeName)) 722 scope.setEL(key,_deserialize(value)); 723 else 724 comp.setEL(key,_deserialize(value)); 725 } 726 } 727 } 728 return comp; 729 } 730 731 /** 732 * Desirialize a Struct Object 733 * @param elStruct Struct Object as XML Element 734 * @return Struct Object 735 * @throws ConverterException 736 */ 737 private Object _deserializeStruct(Element elStruct) throws ConverterException { 738 String type=elStruct.getAttribute("type"); 739 Struct struct=new StructImpl(); 740 741 NodeList list=elStruct.getChildNodes(); 742 int len=list.getLength(); 743 for(int i=0;i<len;i++) { 744 //print.ln(i); 745 746 Node node=list.item(i); 747 if(node instanceof Element) { 748 Element var=(Element)node; 749 Element value=getChildElement((Element)node); 750 if(value!=null) { 751 struct.setEL(var.getAttribute("name"),_deserialize(value)); 752 753 } 754 } 755 } 756 if(struct.size()==0 && type!=null && type.length()>0) { 757 return ""; 758 } 759 return struct; 760 } 761 762 /** 763 * Desirialize a Struct Object 764 * @param el Struct Object as XML Element 765 * @return Struct Object 766 * @throws ConverterException 767 */ 768 private Array _deserializeArray(Element el) throws ConverterException { 769 Array array=new ArrayImpl(); 770 771 NodeList list=el.getChildNodes(); 772 int len=list.getLength(); 773 for(int i=0;i<len;i++) { 774 Node node=list.item(i); 775 if(node instanceof Element) 776 try { 777 array.append(_deserialize((Element)node)); 778 } catch (PageException e) { 779 throw toConverterException(e); 780 } 781 782 } 783 return array; 784 } 785 786 /** 787 * return fitst child Element of a Element, if there are no child Elements return null 788 * @param parent parent node 789 * @return child Element 790 */ 791 private Element getChildElement(Element parent) { 792 NodeList list=parent.getChildNodes(); 793 int len=list.getLength(); 794 for(int i=0;i<len;i++) { 795 Node node=list.item(i); 796 if(node instanceof Element) { 797 return (Element)node; 798 } 799 } 800 return null; 801 } 802 803 804 /** 805 * @return return current blockquote 806 */ 807 private String goIn() { 808 //StringBuffer rtn=new StringBuffer(deep); 809 //for(int i=0;i<deep;i++) rtn.append('\t'); 810 //return rtn.toString(); 811 return ""; 812 } 813 814 @Override 815 public boolean equals(Object obj) { 816 return timeZone.equals(obj); 817 } 818 }