1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.rest.service.node.v1;
35
36 import info.magnolia.jcr.util.NodeTypes;
37 import info.magnolia.jcr.util.NodeUtil;
38 import info.magnolia.jcr.util.PropertyUtil;
39
40 import java.io.ByteArrayInputStream;
41 import java.io.IOException;
42 import java.util.ArrayList;
43 import java.util.Collections;
44 import java.util.List;
45
46 import javax.jcr.Node;
47 import javax.jcr.NodeIterator;
48 import javax.jcr.Property;
49 import javax.jcr.PropertyIterator;
50 import javax.jcr.PropertyType;
51 import javax.jcr.RepositoryException;
52 import javax.jcr.Value;
53 import javax.jcr.ValueFactory;
54
55 import org.apache.commons.codec.binary.Base64;
56 import org.apache.commons.io.IOUtils;
57
58
59
60
61
62 public class RepositoryMarshaller {
63
64 public RepositoryNode marshallNode(final Node node) throws RepositoryException {
65 return marshallNode(node, 0, Collections.<String>emptyList(), true);
66 }
67
68 public RepositoryNode marshallNode(final Node node, final int depth, final List<String> excludeNodeTypes, final boolean includeMeta) throws RepositoryException {
69
70 RepositoryNode data = new RepositoryNode();
71 data.setName(node.getName());
72 data.setPath(node.getPath());
73 data.setIdentifier(node.getIdentifier());
74 data.setType(node.getPrimaryNodeType().getName());
75
76 final PropertyIterator properties = node.getProperties();
77 while (properties.hasNext()) {
78 Property property = properties.nextProperty();
79 String propertyName = property.getName();
80
81 if (!includeMeta && (propertyName.startsWith(NodeTypes.MGNL_PREFIX) || propertyName.startsWith(NodeTypes.JCR_PREFIX))) {
82 continue;
83 }
84
85 data.getProperties().add(marshallProperty(property));
86 }
87
88 if (depth > 0) {
89 final NodeIterator nodes = node.getNodes();
90 while (nodes.hasNext()) {
91 Node child = nodes.nextNode();
92 if (excludeNodeTypes == null || (!excludeNodeTypes.contains(child.getPrimaryNodeType().getName()))) {
93 data.addNode(marshallNode(child, depth-1, excludeNodeTypes, includeMeta));
94 }
95 }
96 }
97
98 return data;
99 }
100
101 public RepositoryProperty marshallProperty(Property property) throws RepositoryException {
102
103 RepositoryProperty data = new RepositoryProperty();
104 data.setName(property.getName());
105 data.setType(PropertyType.nameFromValue(property.getType()));
106 data.setMultiple(property.isMultiple());
107
108 List<String> values = new ArrayList<String>();
109 if (property.isMultiple()) {
110 for (Value propertyValue : property.getValues()) {
111 values.add(getStringByValue(propertyValue));
112 }
113 } else {
114 values.add(getStringByValue(property.getValue()));
115 }
116 data.setValues(values);
117
118 return data;
119 }
120
121 public void unmarshallProperties(final Node node, List<RepositoryProperty> properties) throws RepositoryException {
122 for (RepositoryProperty property : properties) {
123 unmarshallProperty(node, property);
124 }
125 }
126
127 public void unmarshallProperty(Node node, RepositoryProperty property) throws RepositoryException {
128
129 ValueFactory valueFactory = node.getSession().getValueFactory();
130
131 if (property.isMultiple()) {
132
133
134
135 Value[] values;
136 if (property.getValues() != null) {
137 values = new Value[property.getValues().size()];
138 int propertyType = PropertyType.valueFromName(property.getType());
139 int i = 0;
140 for (String propertyValue : property.getValues()) {
141 values[i++] = getValueByType(propertyType, propertyValue, valueFactory);
142 }
143 } else {
144 values = new Value[0];
145 }
146
147 String name = property.getName();
148 if (node.hasProperty(name)) {
149 Property existingProperty = node.getProperty(name);
150 if (!existingProperty.isMultiple()) {
151 existingProperty.remove();
152 }
153 }
154
155 node.setProperty(property.getName(), values);
156
157 } else {
158
159
160
161 if (property.getValues() == null || property.getValues().size() != 1) {
162 throw new IllegalArgumentException("Cannot set more than one value unless the property is multi-valued, [" + property.getName() + "] on [" + NodeUtil.getNodePathIfPossible(node) + "]");
163 }
164
165 final int propertyType = PropertyType.valueFromName(property.getType());
166 final String propertyValue = property.getValues().get(0);
167 Value value = getValueByType(propertyType, propertyValue, valueFactory);
168
169 String name = property.getName();
170 if (node.hasProperty(name)) {
171 Property existingProperty = node.getProperty(name);
172 if (existingProperty.isMultiple()) {
173 existingProperty.remove();
174 }
175 }
176
177 node.setProperty(property.getName(), value);
178 }
179 }
180
181
182
183
184
185
186 protected String getStringByValue(final Value propertyValue) throws RepositoryException {
187 String value;
188 final int propertyType = propertyValue.getType();
189
190 switch (propertyType) {
191 case PropertyType.BINARY:
192
193 byte[] decodedPropertyValue;
194 try {
195 decodedPropertyValue = Base64.encodeBase64(IOUtils.toByteArray(propertyValue.getBinary().getStream()));
196 } catch (IOException e) {
197 throw new RepositoryException(e);
198 }
199 value = new String(decodedPropertyValue);
200 break;
201 default:
202 value = propertyValue.getString();
203 }
204
205 return value;
206 }
207
208
209
210
211
212
213 protected Value getValueByType(final int propertyType, final String propertyValue, final ValueFactory valueFactory) throws RepositoryException {
214 Value value;
215
216 switch (propertyType) {
217 case PropertyType.BINARY:
218
219 byte[] decodedPropertyValue = Base64.decodeBase64(propertyValue);
220 value = PropertyUtil.createValue(new ByteArrayInputStream(decodedPropertyValue), valueFactory);
221 break;
222 default:
223 value = PropertyUtil.createValue(propertyValue, propertyType, valueFactory);
224 }
225
226 return value;
227 }
228
229 }