001 package railo.runtime.text.xml.struct; 002 003 import java.lang.reflect.Method; 004 import java.util.Date; 005 import java.util.Iterator; 006 import java.util.Map; 007 008 import org.w3c.dom.DOMException; 009 import org.w3c.dom.Document; 010 import org.w3c.dom.Element; 011 import org.w3c.dom.NamedNodeMap; 012 import org.w3c.dom.Node; 013 import org.w3c.dom.NodeList; 014 import org.w3c.dom.UserDataHandler; 015 import org.xml.sax.SAXException; 016 017 import railo.commons.collections.HashTable; 018 import railo.runtime.PageContext; 019 import railo.runtime.dump.DumpData; 020 import railo.runtime.dump.DumpProperties; 021 import railo.runtime.dump.DumpUtil; 022 import railo.runtime.exp.ExpressionException; 023 import railo.runtime.exp.PageException; 024 import railo.runtime.exp.PageRuntimeException; 025 import railo.runtime.exp.XMLException; 026 import railo.runtime.op.Caster; 027 import railo.runtime.op.Operator; 028 import railo.runtime.text.xml.XMLAttributes; 029 import railo.runtime.text.xml.XMLCaster; 030 import railo.runtime.text.xml.XMLNodeList; 031 import railo.runtime.text.xml.XMLUtil; 032 import railo.runtime.type.Collection; 033 import railo.runtime.type.KeyImpl; 034 import railo.runtime.type.dt.DateTime; 035 import railo.runtime.type.it.EntryIterator; 036 import railo.runtime.type.it.KeyIterator; 037 import railo.runtime.type.it.StringIterator; 038 import railo.runtime.type.it.ValueIterator; 039 import railo.runtime.type.util.ArrayUtil; 040 import railo.runtime.type.util.StructSupport; 041 042 /** 043 * 044 */ 045 public class XMLNodeStruct extends StructSupport implements XMLStruct { 046 047 private Node node; 048 protected boolean caseSensitive; 049 050 /** 051 * constructor of the class 052 * @param node Node 053 * @param caseSensitive 054 */ 055 protected XMLNodeStruct(Node node, boolean caseSensitive) { 056 if(node instanceof XMLStruct)node=((XMLStruct)node).toNode(); 057 this.node=node; 058 this.caseSensitive=caseSensitive; 059 } 060 061 @Override 062 public Object remove(Key key) throws PageException { 063 Object o= XMLUtil.removeProperty(node,key,caseSensitive); 064 if(o!=null)return o; 065 throw new ExpressionException("node has no child with name ["+key+"]"); 066 } 067 068 @Override 069 public Object removeEL(Key key) { 070 return XMLUtil.removeProperty(node,key,caseSensitive); 071 } 072 073 @Override 074 public Object get(Collection.Key key) throws PageException { 075 try { 076 return XMLUtil.getProperty(node,key,caseSensitive); 077 } catch (SAXException e) { 078 throw new XMLException(e); 079 } 080 } 081 082 @Override 083 public Object set(Collection.Key key, Object value) throws PageException { 084 return XMLUtil.setProperty(node,key,value,caseSensitive); 085 } 086 087 /** 088 * @return retun the inner map 089 */ 090 public Map getMap() { 091 NodeList elements=XMLUtil.getChildNodes(node,Node.ELEMENT_NODE,false,null);// TODO ist das false hier ok? 092 Map map=new HashTable(); 093 int len=elements.getLength(); 094 095 for(int i=0;i<len;i++) { 096 Node node=elements.item(i); 097 map.put(node.getNodeName(),node); 098 } 099 return map; 100 } 101 102 @Override 103 public Collection duplicate(boolean deepCopy) { 104 return new XMLNodeStruct(node.cloneNode(deepCopy),caseSensitive); 105 } 106 107 108 109 110 111 112 @Override 113 public Node cloneNode(boolean deep) { 114 return new XMLNodeStruct(node.cloneNode(deep),caseSensitive); 115 } 116 117 118 @Override 119 public short getNodeType() { 120 return node.getNodeType(); 121 } 122 123 @Override 124 public void normalize() { 125 node.normalize(); 126 } 127 128 @Override 129 public boolean hasAttributes() { 130 return node.hasAttributes(); 131 } 132 133 @Override 134 public boolean hasChildNodes() { 135 return node.hasChildNodes(); 136 } 137 138 @Override 139 public String getLocalName() { 140 return node.getLocalName(); 141 } 142 143 @Override 144 public String getNamespaceURI() { 145 return node.getNamespaceURI(); 146 } 147 148 @Override 149 public String getNodeName() { 150 return node.getNodeName(); 151 } 152 153 @Override 154 public String getNodeValue() throws DOMException { 155 return node.getNodeValue(); 156 } 157 158 @Override 159 public String getPrefix() { 160 return node.getPrefix(); 161 } 162 163 @Override 164 public void setNodeValue(String nodeValue) throws DOMException { 165 node.setNodeValue(nodeValue); 166 } 167 168 @Override 169 public void setPrefix(String prefix) throws DOMException { 170 node.setPrefix(prefix); 171 } 172 173 @Override 174 public Document getOwnerDocument() { 175 if(node instanceof Document) return (Document) node; 176 return node.getOwnerDocument(); 177 } 178 179 @Override 180 public NamedNodeMap getAttributes() { 181 return new XMLAttributes(node,caseSensitive); 182 } 183 184 @Override 185 public Node getFirstChild() { 186 return node.getFirstChild(); 187 } 188 189 @Override 190 public Node getLastChild() { 191 return node.getLastChild(); 192 } 193 194 @Override 195 public Node getNextSibling() { 196 return node.getNextSibling(); 197 } 198 199 @Override 200 public Node getParentNode() { 201 return node.getParentNode(); 202 } 203 204 @Override 205 public Node getPreviousSibling() { 206 return node.getPreviousSibling(); 207 } 208 209 210 211 @Override 212 public NodeList getChildNodes() { 213 return node.getChildNodes(); 214 } 215 216 @Override 217 public boolean isSupported(String feature, String version) { 218 return node.isSupported(feature, version); 219 } 220 221 @Override 222 public Node appendChild(Node newChild) throws DOMException { 223 return node.appendChild(newChild); 224 } 225 226 @Override 227 public Node removeChild(Node oldChild) throws DOMException { 228 return node.removeChild(XMLCaster.toRawNode(oldChild)); 229 } 230 231 @Override 232 public Node insertBefore(Node newChild, Node refChild) throws DOMException { 233 return node.insertBefore(newChild, refChild); 234 } 235 236 @Override 237 public Node replaceChild(Node newChild, Node oldChild) throws DOMException { 238 return node.replaceChild(XMLCaster.toRawNode(newChild), XMLCaster.toRawNode(oldChild)); 239 } 240 241 @Override 242 public int size() { 243 NodeList list = node.getChildNodes(); 244 int len=list.getLength(); 245 int count=0; 246 for(int i=0;i<len;i++) { 247 if(list.item(i) instanceof Element) count++; 248 } 249 return count; 250 } 251 252 public Collection.Key[] keys() { 253 NodeList elements=XMLUtil.getChildNodes(node,Node.ELEMENT_NODE,false,null);// TODO ist das false hie ok 254 Collection.Key[] arr=new Collection.Key[elements.getLength()]; 255 for(int i=0;i<arr.length;i++) { 256 arr[i]=KeyImpl.init(elements.item(i).getNodeName()); 257 } 258 return arr; 259 } 260 261 @Override 262 public void clear() { 263 /*NodeList elements=XMLUtil.getChildNodes(node,Node.ELEMENT_NODE); 264 int len=elements.getLength(); 265 for(int i=0;i<len;i++) { 266 node.removeChild(elements.item(i)); 267 }*/ 268 } 269 270 @Override 271 public Object get(Collection.Key key, Object defaultValue) { 272 return XMLUtil.getProperty(node,key,caseSensitive,defaultValue); 273 } 274 275 @Override 276 public Object setEL(Key key, Object value) { 277 return XMLUtil.setProperty(node,key,value,caseSensitive,null); 278 } 279 280 @Override 281 public Iterator<Collection.Key> keyIterator() { 282 return new KeyIterator(keys()); 283 } 284 285 @Override 286 public Iterator<String> keysAsStringIterator() { 287 return new StringIterator(keys()); 288 } 289 290 @Override 291 public Iterator<Entry<Key, Object>> entryIterator() { 292 return new EntryIterator(this,keys()); 293 } 294 295 @Override 296 public Iterator<Object> valueIterator() { 297 return new ValueIterator(this,keys()); 298 } 299 300 @Override 301 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { 302 return DumpUtil.toDumpData(node, pageContext,maxlevel,dp); 303 } 304 305 @Override 306 public final Node toNode() { 307 return node; 308 } 309 310 /** 311 * @return Returns the caseSensitive. 312 */ 313 public boolean getCaseSensitive() { 314 return caseSensitive; 315 } 316 317 @Override 318 public boolean containsKey(Collection.Key key) { 319 return get(key,null)!=null; 320 } 321 322 @Override 323 public XMLNodeList getXMLNodeList() { 324 return new XMLNodeList(node,getCaseSensitive()); 325 } 326 327 @Override 328 public String castToString() throws PageException { 329 return XMLCaster.toString(this.node); 330 } 331 332 @Override 333 public String castToString(String defaultValue) { 334 return XMLCaster.toString(this.node,defaultValue); 335 } 336 337 @Override 338 public boolean castToBooleanValue() throws ExpressionException { 339 throw new ExpressionException("Can't cast XML Node to a boolean value"); 340 } 341 342 @Override 343 public Boolean castToBoolean(Boolean defaultValue) { 344 return defaultValue; 345 } 346 347 348 @Override 349 public double castToDoubleValue() throws ExpressionException { 350 throw new ExpressionException("Can't cast XML Node to a number value"); 351 } 352 353 @Override 354 public double castToDoubleValue(double defaultValue) { 355 return defaultValue; 356 } 357 358 359 @Override 360 public DateTime castToDateTime() throws ExpressionException { 361 throw new ExpressionException("Can't cast XML Node to a Date"); 362 } 363 364 @Override 365 public DateTime castToDateTime(DateTime defaultValue) { 366 return defaultValue; 367 } 368 369 @Override 370 public int compareTo(boolean b) throws PageException { 371 return Operator.compare(castToString(), b); 372 } 373 374 @Override 375 public int compareTo(DateTime dt) throws PageException { 376 return Operator.compare(castToString(), (Date)dt); 377 } 378 379 @Override 380 public int compareTo(double d) throws PageException { 381 return Operator.compare(castToString(), d); 382 } 383 384 @Override 385 public int compareTo(String str) throws PageException { 386 return Operator.compare(castToString(), str); 387 } 388 389 public String getBaseURI() { 390 // not supported 391 return null; 392 } 393 394 public short compareDocumentPosition(Node other) throws DOMException { 395 // not supported 396 return -1; 397 } 398 399 public void setTextContent(String textContent) throws DOMException { 400 //TODO not supported 401 throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,"this method is not supported"); 402 } 403 404 public boolean isSameNode(Node other) { 405 return this==other; 406 } 407 408 public String lookupPrefix(String namespaceURI) { 409 // TODO not supported 410 return null; 411 } 412 413 public boolean isDefaultNamespace(String namespaceURI) { 414 // TODO not supported 415 return false; 416 } 417 418 public String lookupNamespaceURI(String prefix) { 419 // TODO not supported 420 return null; 421 } 422 423 public boolean isEqualNode(Node node) { 424 // TODO not supported 425 return this==node; 426 } 427 428 public Object getFeature(String feature, String version) { 429 // TODO not supported 430 return null; 431 } 432 433 public Object getUserData(String key) { 434 // dynamic load to support jre 1.4 and 1.5 435 try { 436 Method m = node.getClass().getMethod("getUserData", new Class[]{key.getClass()}); 437 return m.invoke(node, new Object[]{key}); 438 } 439 catch (Exception e) { 440 throw new PageRuntimeException(Caster.toPageException(e)); 441 } 442 } 443 444 public String getTextContent() throws DOMException { 445 // dynamic load to support jre 1.4 and 1.5 446 try { 447 Method m = node.getClass().getMethod("getTextContent", new Class[]{}); 448 return Caster.toString(m.invoke(node, ArrayUtil.OBJECT_EMPTY)); 449 } 450 catch (Exception e) { 451 throw new PageRuntimeException(Caster.toPageException(e)); 452 } 453 } 454 455 public Object setUserData(String key, Object data, UserDataHandler handler) { 456 // dynamic load to support jre 1.4 and 1.5 457 try { 458 Method m = node.getClass().getMethod("setUserData", new Class[]{key.getClass(),data.getClass(),handler.getClass()}); 459 return m.invoke(node, new Object[]{key,data,handler}); 460 } 461 catch (Exception e) { 462 throw new PageRuntimeException(Caster.toPageException(e)); 463 } 464 } 465 466 public boolean isCaseSensitive() { 467 return caseSensitive; 468 } 469 470 public boolean equals(Object obj) { 471 if(!(obj instanceof XMLNodeStruct)) 472 return super.equals(obj); 473 XMLNodeStruct other = ((XMLNodeStruct)obj); 474 return other.caseSensitive=caseSensitive && other.node.equals(node); 475 } 476 477 478 479 }