1 19 20 package org.apache.cayenne.xml; 21 22 import java.io.StringWriter ; 23 import java.text.SimpleDateFormat ; 24 import java.util.Collection ; 25 import java.util.Date ; 26 import java.util.Iterator ; 27 28 import javax.xml.transform.OutputKeys ; 29 import javax.xml.transform.Result ; 30 import javax.xml.transform.Source ; 31 import javax.xml.transform.Transformer ; 32 import javax.xml.transform.TransformerFactory ; 33 import javax.xml.transform.dom.DOMSource ; 34 import javax.xml.transform.stream.StreamResult ; 35 36 import org.apache.cayenne.CayenneRuntimeException; 37 import org.w3c.dom.Document ; 38 import org.w3c.dom.Element ; 39 import org.w3c.dom.Node ; 40 41 47 public class XMLEncoder { 48 49 private XMLMappingDescriptor mappingDescriptor; 50 51 private Document document; 53 private Node parent; 54 private String tagOverride; 55 private boolean inProgress; 56 57 60 public XMLEncoder() { 61 62 } 63 64 67 public XMLEncoder(String mappingUrl) { 68 this.mappingDescriptor = new XMLMappingDescriptor(mappingUrl); 69 } 70 71 74 public void setRoot(String xmlTag, String type) { 75 setRoot(xmlTag, type, true); 76 } 77 78 85 public void encodeProperty(String xmlTag, Object value) { 86 encodeProperty(xmlTag, value, true); 87 } 88 89 92 public String encode(Object object) throws CayenneRuntimeException { 93 return encode("root", object); 94 } 95 96 99 public String encode(String rootTag, Object object) throws CayenneRuntimeException { 100 101 try { 102 initDocument(rootTag, object != null ? object.getClass().getName() : null); 103 104 if (mappingDescriptor != null) { 105 mappingDescriptor.getRootEntity().setObject(object); 106 mappingDescriptor.getRootEntity().encodeAsXML(this); 107 } 108 else { 109 encodeProperty(rootTag, object); 110 } 111 112 if (object instanceof Collection ) { 113 return nodeToString(getRootNode(true)); 114 } else { 115 return nodeToString(getRootNode(false)); 116 } 117 } 118 finally { 119 inProgress = false; 121 } 122 } 123 124 127 void initDocument(String rootTag, String type) { 128 this.document = XMLUtil.newBuilder().newDocument(); 129 this.parent = document; 130 131 Element root = push(rootTag); 133 if (type != null) { 134 root.setAttribute("type", type); 135 } 136 137 inProgress = true; 138 } 139 140 143 Node getRootNode(boolean forceSyntheticRoot) { 144 if (document == null) { 145 return null; 146 } 147 148 Node root = document.getDocumentElement(); 150 151 if (!forceSyntheticRoot && root.getChildNodes().getLength() == 1) { 152 root = root.getFirstChild(); 153 } 154 155 return root; 156 } 157 158 String nodeToString(Node rootNode) { 159 160 StringWriter out = new StringWriter (); 161 Result result = new StreamResult (out); 162 163 Source source = new DOMSource (rootNode); 164 165 try { 166 Transformer xformer = TransformerFactory.newInstance().newTransformer(); 167 xformer.setOutputProperty(OutputKeys.METHOD, "xml"); 168 xformer.setOutputProperty(OutputKeys.INDENT, "yes"); 169 xformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 170 xformer.transform(source, result); 171 } 172 catch (Exception e) { 173 throw new CayenneRuntimeException("XML transformation error", e); 174 } 175 176 return out.toString().trim() + System.getProperty("line.separator"); 177 } 178 179 void setRoot(String xmlTag, String type, boolean push) { 180 181 if (!inProgress) { 183 initDocument(xmlTag, type); 184 } 185 186 if (tagOverride != null) { 187 xmlTag = tagOverride; 188 tagOverride = null; 189 } 190 191 if (!push) { 193 pop(); 194 } 195 196 Element element = push(xmlTag); 197 if (type != null) { 198 element.setAttribute("type", type); 199 } 200 } 201 202 void encodeProperty(String xmlTag, Object value, boolean useType) { 203 if (!inProgress) { 205 String type = (useType && value != null) ? value.getClass().getName() : null; 206 initDocument(xmlTag, type); 207 } 208 209 if (value == null) { 210 return; 211 } 212 else if (value instanceof XMLSerializable) { 213 encodeSerializable(xmlTag, (XMLSerializable) value); 214 } 215 else if (value instanceof Collection ) { 216 encodeCollection(xmlTag, (Collection ) value, useType); 217 } 218 else { 219 encodeSimple(xmlTag, value, useType); 220 } 221 } 222 223 void encodeSimple(String xmlTag, Object object, boolean useType) { 224 225 Element node = push(xmlTag); 227 228 if (useType) { 229 node.setAttribute("type", object.getClass().getName()); 230 } 231 232 if (object instanceof Date ) { 234 SimpleDateFormat sdf = new SimpleDateFormat (XMLUtil.DEFAULT_DATE_FORMAT); 235 node.appendChild(document.createTextNode(sdf.format(object))); 236 } 237 else { 238 node.appendChild(document.createTextNode(object.toString())); 239 } 240 241 pop(); 242 } 243 244 void encodeSerializable(String xmlTag, XMLSerializable object) { 245 if (document.getDocumentElement() != parent) { 248 tagOverride = xmlTag; 249 } 250 251 object.encodeAsXML(this); 252 253 tagOverride = null; 254 pop(); 255 } 256 257 263 void encodeCollection(String xmlTag, Collection c, boolean useType) { 264 265 Iterator it = c.iterator(); 266 while (it.hasNext()) { 267 encodeProperty(xmlTag, it.next(), useType); 270 } 271 272 if (c.size() == 1) { 273 ((Element ) parent.getLastChild()).setAttribute("forceList", "YES"); 274 } 275 } 276 277 280 private Element push(String xmlTag) { 281 282 Element child = document.createElement(xmlTag); 283 this.parent.appendChild(child); 284 this.parent = child; 285 return child; 286 } 287 288 291 Node pop() { 292 Node old = parent; 293 parent = parent.getParentNode(); 294 return old; 295 } 296 } 297 | Popular Tags |