]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.jcr/src/org/argeo/jcr/xml/JcrXmlUtils.java
Improve localization framework.
[lgpl/argeo-commons.git] / org.argeo.jcr / src / org / argeo / jcr / xml / JcrXmlUtils.java
1 package org.argeo.jcr.xml;
2
3 import java.io.IOException;
4 import java.io.Writer;
5 import java.util.Map;
6 import java.util.TreeMap;
7
8 import javax.jcr.Node;
9 import javax.jcr.NodeIterator;
10 import javax.jcr.Property;
11 import javax.jcr.PropertyIterator;
12 import javax.jcr.RepositoryException;
13 import javax.jcr.Value;
14 import javax.jcr.nodetype.NodeType;
15
16 import org.argeo.jcr.Jcr;
17
18 /** Utilities around JCR and XML. */
19 public class JcrXmlUtils {
20 /**
21 * Convenience method calling {@link #toXmlElements(Writer, Node, boolean)} with
22 * <code>false</code>.
23 */
24 public static void toXmlElements(Writer writer, Node node) throws RepositoryException, IOException {
25 toXmlElements(writer, node, null, false, false, false);
26 }
27
28 /**
29 * Write JCR properties as XML elements in a tree structure whose elements are
30 * named by node primary type.
31 *
32 * @param writer the writer to use
33 * @param node the subtree
34 * @param depth maximal depth, or if <code>null</code> the whole
35 * subtree. It must be positive, with depth 0
36 * describing just the node without its children.
37 * @param withMetadata whether to write the primary type and mixins as
38 * elements
39 * @param withPrefix whether to keep the namespace prefixes
40 * @param propertiesAsElements whether single properties should be written as
41 * elements rather than attributes. If
42 * <code>false</code>, multiple properties will be
43 * skipped.
44 */
45 public static void toXmlElements(Writer writer, Node node, Integer depth, boolean withMetadata, boolean withPrefix,
46 boolean propertiesAsElements) throws RepositoryException, IOException {
47 if (depth != null && depth < 0)
48 throw new IllegalArgumentException("Depth " + depth + " is negative.");
49
50 if (node.getName().equals(Jcr.JCR_XMLTEXT)) {
51 writer.write(node.getProperty(Jcr.JCR_XMLCHARACTERS).getString());
52 return;
53 }
54
55 if (!propertiesAsElements) {
56 Map<String, String> attrs = new TreeMap<>();
57 PropertyIterator pit = node.getProperties();
58 properties: while (pit.hasNext()) {
59 Property p = pit.nextProperty();
60 if (!p.isMultiple()) {
61 String pName = p.getName();
62 if (!withMetadata && (pName.equals(Jcr.JCR_PRIMARY_TYPE) || pName.equals(Jcr.JCR_UUID)
63 || pName.equals(Jcr.JCR_CREATED) || pName.equals(Jcr.JCR_CREATED_BY)
64 || pName.equals(Jcr.JCR_LAST_MODIFIED) || pName.equals(Jcr.JCR_LAST_MODIFIED_BY)))
65 continue properties;
66 attrs.put(withPrefix(p.getName(), withPrefix), p.getString());
67 }
68 }
69 if (withMetadata && node.hasProperty(Property.JCR_UUID))
70 attrs.put("id", "urn:uuid:" + node.getProperty(Property.JCR_UUID).getString());
71 attrs.put(withPrefix ? Jcr.JCR_NAME : "name", node.getName());
72 writeStart(writer, withPrefix(node.getPrimaryNodeType().getName(), withPrefix), attrs, node.hasNodes());
73 } else {
74 if (withMetadata && node.hasProperty(Property.JCR_UUID)) {
75 writeStart(writer, withPrefix(node.getPrimaryNodeType().getName(), withPrefix), "id",
76 "urn:uuid:" + node.getProperty(Property.JCR_UUID).getString());
77 } else {
78 writeStart(writer, withPrefix(node.getPrimaryNodeType().getName(), withPrefix));
79 }
80 // name
81 writeStart(writer, withPrefix ? Jcr.JCR_NAME : "name");
82 writer.append(node.getName());
83 writeEnd(writer, withPrefix ? Jcr.JCR_NAME : "name");
84 }
85
86 // mixins
87 if (withMetadata) {
88 for (NodeType mixin : node.getMixinNodeTypes()) {
89 writeStart(writer, withPrefix ? Jcr.JCR_MIXIN_TYPES : "mixinTypes");
90 writer.append(mixin.getName());
91 writeEnd(writer, withPrefix ? Jcr.JCR_MIXIN_TYPES : "mixinTypes");
92 }
93 }
94
95 // properties as elements
96 if (propertiesAsElements) {
97 PropertyIterator pit = node.getProperties();
98 properties: while (pit.hasNext()) {
99 Property p = pit.nextProperty();
100 if (p.isMultiple()) {
101 for (Value value : p.getValues()) {
102 writeStart(writer, withPrefix(p.getName(), withPrefix));
103 writer.write(value.getString());
104 writeEnd(writer, withPrefix(p.getName(), withPrefix));
105 }
106 } else {
107 Value value = p.getValue();
108 String pName = p.getName();
109 if (!withMetadata && (pName.equals(Jcr.JCR_PRIMARY_TYPE) || pName.equals(Jcr.JCR_UUID)
110 || pName.equals(Jcr.JCR_CREATED) || pName.equals(Jcr.JCR_CREATED_BY)
111 || pName.equals(Jcr.JCR_LAST_MODIFIED) || pName.equals(Jcr.JCR_LAST_MODIFIED_BY)))
112 continue properties;
113 writeStart(writer, withPrefix(p.getName(), withPrefix));
114 writer.write(value.getString());
115 writeEnd(writer, withPrefix(p.getName(), withPrefix));
116 }
117 }
118 }
119
120 // children
121 if (node.hasNodes()) {
122 if (depth == null || depth > 0) {
123 NodeIterator nit = node.getNodes();
124 while (nit.hasNext()) {
125 toXmlElements(writer, nit.nextNode(), depth == null ? null : depth - 1, withMetadata, withPrefix,
126 propertiesAsElements);
127 }
128 }
129 writeEnd(writer, withPrefix(node.getPrimaryNodeType().getName(), withPrefix));
130 }
131 }
132
133 private static String withPrefix(String str, boolean withPrefix) {
134 if (withPrefix)
135 return str;
136 int index = str.indexOf(':');
137 if (index < 0)
138 return str;
139 return str.substring(index + 1);
140 }
141
142 private static void writeStart(Writer writer, String tagName) throws IOException {
143 writer.append('<');
144 writer.append(tagName);
145 writer.append('>');
146 }
147
148 private static void writeStart(Writer writer, String tagName, String attr, String value) throws IOException {
149 writer.append('<');
150 writer.append(tagName);
151 writer.append(' ');
152 writer.append(attr);
153 writer.append("=\"");
154 writer.append(value);
155 writer.append("\">");
156 }
157
158 private static void writeStart(Writer writer, String tagName, Map<String, String> attrs, boolean hasChildren)
159 throws IOException {
160 writer.append('<');
161 writer.append(tagName);
162 for (String attr : attrs.keySet()) {
163 writer.append(' ');
164 writer.append(attr);
165 writer.append("=\"");
166 writer.append(attrs.get(attr));
167 writer.append('\"');
168 }
169 if (hasChildren)
170 writer.append('>');
171 else
172 writer.append("/>");
173 }
174
175 private static void writeEnd(Writer writer, String tagName) throws IOException {
176 writer.append("</");
177 writer.append(tagName);
178 writer.append('>');
179 }
180
181 /** Singleton. */
182 private JcrXmlUtils() {
183
184 }
185
186 }