1 10 11 package org.mmbase.bridge.util.xml; 12 13 import org.w3c.dom.*; 14 import org.w3c.dom.Node ; 15 import org.w3c.dom.NodeList ; 16 import javax.xml.parsers.DocumentBuilder ; 17 import org.mmbase.bridge.*; 18 19 import org.mmbase.util.logging.*; 20 import org.mmbase.util.xml.XMLWriter; 21 22 23 31 public class Generator { 32 33 private static final Logger log = Logging.getLoggerInstance(Generator.class); 34 35 public final static String NAMESPACE = "http://www.mmbase.org/xmlns/objects"; 36 private final static String DOCUMENTTYPE_PUBLIC = "-//MMBase//DTD objects config 1.0//EN"; 37 private final static String DOCUMENTTYPE_SYSTEM = "http://www.mmbase.org/dtd/objects_1_0.dtd"; 38 39 private Document document = null; 40 private DocumentBuilder documentBuilder = null; 41 private Cloud cloud = null; 42 43 private boolean namespaceAware = false; 44 45 54 public Generator(DocumentBuilder documentBuilder, Cloud cloud) { 55 this.documentBuilder = documentBuilder; 56 this.cloud = cloud; 57 58 } 59 60 public Generator(DocumentBuilder documentBuilder) { 61 this(documentBuilder, null); 62 } 63 64 public Generator(Document doc) { 65 document = doc; 66 namespaceAware = document.getDocumentElement().getNamespaceURI() != null; 67 } 68 69 73 public Document getDocument() { 74 if (document == null) { 75 DOMImplementation impl = documentBuilder.getDOMImplementation(); 76 document = impl.createDocument(namespaceAware ? NAMESPACE : null, 77 "objects", 78 impl.createDocumentType("objects", DOCUMENTTYPE_PUBLIC, DOCUMENTTYPE_SYSTEM) 79 ); 80 if (cloud != null) { 81 addCloud(); 82 } 83 } 84 return document; 85 } 86 87 92 public void setNamespaceAware(boolean n) { 93 if (document != null) throw new IllegalStateException ("Already started constructing"); 94 namespaceAware = n; 95 } 96 97 100 public boolean isNamespaceAware() { 101 return namespaceAware; 102 } 103 104 107 protected Element createElement(String name) { 108 getDocument(); 109 if (namespaceAware) { 110 return document.createElementNS(NAMESPACE, name); 111 } else { 112 return document.createElement(name); 113 } 114 115 } 116 protected final void setAttribute(Element element, String name, String value) { 117 127 element.setAttribute(name, value); 128 } 129 130 protected final String getAttribute(Element element, String name) { 131 139 return element.getAttribute(name); 140 } 141 142 146 public String toString() { 147 return toString(false); 148 } 149 150 155 public String toString(boolean ident) { 156 return XMLWriter.write(document, ident); 157 } 158 159 private void addCloud() { 160 setAttribute(document.getDocumentElement(), "cloud", cloud.getName()); 161 } 162 163 169 public Element add(org.mmbase.bridge.Node node, Field fieldDefinition) { 170 getDocument(); 171 if (cloud == null) { 172 cloud = node.getCloud(); 173 addCloud(); 174 } 175 176 Element object = getNode(node); 177 178 if (! (object.getFirstChild() instanceof Element)) { 179 log.warn("Cannot find first field of " + XMLWriter.write(object, false)); 180 return object; 181 } 182 Element field = (Element)object.getFirstChild(); 184 while (field != null && !fieldDefinition.getName().equals(getAttribute(field, "name"))) { 185 field = (Element)field.getNextSibling(); 186 } 187 if(field == null) throw new BridgeException("field with name: " + fieldDefinition.getName() + " of node " + node.getNumber() + " with nodetype: " + fieldDefinition.getNodeManager().getName() + " not found, while it should be in the node skeleton.. xml:\n" + toString(true)); 189 if (field.getTagName().equals("field")) { 191 return field; 192 } 193 194 Element filledField = createElement("field"); 196 197 field.getParentNode().replaceChild(filledField, field); 198 field = filledField; 199 setAttribute(field, "name", fieldDefinition.getName()); 201 setAttribute(field, "format", getFieldFormat(fieldDefinition)); 204 switch (fieldDefinition.getType()) { 206 case Field.TYPE_XML : 207 Document doc = node.getXMLValue(fieldDefinition.getName()); 208 if (doc != null) { 210 field.appendChild(importDocument(field, doc)); 212 } 213 break; 214 case Field.TYPE_BINARY : 215 org.mmbase.util.transformers.Base64 transformer = new org.mmbase.util.transformers.Base64(); 216 field.appendChild(document.createTextNode(transformer.transform(node.getByteValue(fieldDefinition.getName())))); 217 break; 218 case Field.TYPE_DATETIME : 219 field.appendChild(document.createTextNode(org.mmbase.util.Casting.ISO_8601_LOOSE.format(node.getDateValue(fieldDefinition.getName())))); 221 break; 222 default : 223 field.appendChild(document.createTextNode(node.getStringValue(fieldDefinition.getName()))); 224 } 225 return field; 227 } 228 229 233 public Element add(org.mmbase.bridge.Node node) { 234 NodeManager nm = node.getNodeManager(); 236 FieldIterator i = nm.getFields(NodeManager.ORDER_CREATE).fieldIterator(); 237 while (i.hasNext()) { 238 Field field = i.nextField(); 239 if (field.getType() != Field.TYPE_BINARY) { 240 add(node, field); 241 } 242 } 243 return getNode(node); 244 } 245 246 250 public Element add(Relation relation) { 251 return add((org.mmbase.bridge.Node)relation); 252 253 } 254 255 259 public void add(org.mmbase.bridge.NodeList nodes) { 260 NodeIterator i = nodes.nodeIterator(); 261 while (i.hasNext()) { 262 add(i.nextNode()); 263 } 264 } 265 266 270 public void add(RelationList relations) { 271 RelationIterator i = relations.relationIterator(); 272 while (i.hasNext()) { 273 add(i.nextRelation()); 274 275 } 276 } 277 278 protected Element getElementById(Node n, String id) { 279 280 NodeList list = n.getChildNodes(); 281 for (int i = 0 ; i < list.getLength(); i++) { 282 Node node = list.item(i); 283 if (node instanceof Element) { 284 if (getAttribute((Element) node, "id").equals(id)) { 285 return (Element) node; 286 } 287 } 288 } 289 for (int i = 0 ; i < list.getLength(); i++) { 290 Node node = list.item(i); 291 Element subs = getElementById(node, id); 292 if (subs != null) return subs; 293 } 294 return null; 295 296 } 297 302 private Element getNode(org.mmbase.bridge.Node node) { 303 304 boolean getElementByIdWorks = false; 307 Element object = null; 308 if (getElementByIdWorks) { 309 object = getDocument().getElementById("" + node.getNumber()); 311 } else { 312 object = getElementById(getDocument(), "" + node.getNumber()); 313 } 314 315 if (object != null) 316 return object; 317 318 if (node instanceof Relation) { 321 Relation relation = (Relation)node; 322 getNode(relation.getSource()).appendChild(createRelationEntry(relation, relation.getSource())); 323 getNode(relation.getDestination()).appendChild(createRelationEntry(relation, relation.getDestination())); 324 } 325 326 object = createElement("object"); 328 329 setAttribute(object, "id", "" + node.getNumber()); 330 setAttribute(object, "type", node.getNodeManager().getName()); 331 setAttribute(object, "otype", node.getStringValue("otype")); 333 334 338 FieldIterator i = node.getNodeManager().getFields(NodeManager.ORDER_CREATE).fieldIterator(); 339 while (i.hasNext()) { 340 Field fieldDefinition = i.nextField(); 341 Element field = createElement("unfilledField"); 342 343 setAttribute(field, "name", fieldDefinition.getName()); 345 object.appendChild(field); 347 } 348 document.getDocumentElement().appendChild(object); 349 return object; 350 } 351 352 359 private Element importDocument(Element fieldElement, Document toImport) { 360 DocumentType dt = toImport.getDoctype(); 361 String tagName = toImport.getDocumentElement().getTagName(); 362 363 String namespace; 364 if (dt != null) { 365 namespace = dt.getSystemId(); 366 } else { 367 namespace = "http://www.mmbase.org/xmlns/" + tagName; 368 } 369 if (log.isDebugEnabled()) { 370 log.debug("using namepace: " + namespace); 371 } 372 Element fieldContent = (Element)document.importNode(toImport.getDocumentElement(), true); 373 fieldContent.setAttribute("xmlns", namespace); 374 fieldElement.appendChild(fieldContent); 375 return fieldContent; 376 } 377 378 private String getFieldFormat(Field field) { 379 switch (field.getType()) { 380 case Field.TYPE_XML : 381 return "xml"; 382 case Field.TYPE_STRING : 383 return "string"; 384 case Field.TYPE_NODE : 385 return "object"; case Field.TYPE_INTEGER : 387 case Field.TYPE_LONG : 388 String fieldName = field.getName(); 390 String guiType = field.getGUIType(); 391 392 if (fieldName.equals("otype") 394 || fieldName.equals("number") 395 || fieldName.equals("snumber") 396 || fieldName.equals("dnumber") 397 || fieldName.equals("rnumber") 398 || fieldName.equals("role") 399 || guiType.equals("reldefs")) { 400 return "object"; } 402 if (guiType.equals("eventtime")) { 403 return "date"; 404 } 405 case Field.TYPE_FLOAT : 406 case Field.TYPE_DOUBLE : 407 return "numeric"; 408 case Field.TYPE_BINARY : 409 return "bytes"; 410 case Field.TYPE_DATETIME: 411 return "datetime"; 412 case Field.TYPE_BOOLEAN: 413 return "boolean"; 414 case Field.TYPE_LIST: 415 return "list"; 416 default : 417 throw new RuntimeException ("could not find field-type for:" + field.getType() + " for field: " + field); 418 } 419 } 420 421 private Element createRelationEntry(Relation relation, org.mmbase.bridge.Node relatedNode) { 422 Element fieldElement = createElement("relation"); 423 org.mmbase.bridge.Node reldef = cloud.getNode(relation.getStringValue("rnumber")); 425 426 setAttribute(fieldElement, "object", "" + relation.getNumber()); 427 428 if (relation.getSource().getNumber() == relatedNode.getNumber()) { 429 setAttribute(fieldElement, "role", reldef.getStringValue("sname")); 430 setAttribute(fieldElement, "related", "" + relation.getDestination().getNumber()); 431 setAttribute(fieldElement, "type", "source"); 432 } else { 433 setAttribute(fieldElement, "role", reldef.getStringValue("dname")); 434 setAttribute(fieldElement, "related", "" + relation.getSource().getNumber()); 435 setAttribute(fieldElement, "type", "destination"); 436 } 437 return fieldElement; 438 } 439 } 440 | Popular Tags |