1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.onehippo.forge.utilities.commons.jcrmockup;
18
19 import java.util.ArrayList;
20 import java.util.Calendar;
21 import java.util.Collections;
22 import java.util.List;
23
24 import javax.jcr.Item;
25 import javax.jcr.Node;
26 import javax.jcr.PathNotFoundException;
27 import javax.jcr.PropertyType;
28 import javax.jcr.RepositoryException;
29 import javax.jcr.Value;
30
31 import org.mockito.invocation.InvocationOnMock;
32 import org.mockito.stubbing.Answer;
33
34
35
36
37 public class ItemAnswer implements Answer<Item> {
38
39 private static final String DATE = "Date";
40 private MockNode mockNode;
41
42 public ItemAnswer(final MockNode mockNode) {
43 this.mockNode = mockNode;
44 }
45
46 public Item answer(InvocationOnMock invocation) throws RepositoryException {
47 final String methodName = invocation.getMethod().getName();
48 final Object args[] = invocation.getArguments();
49 if ("getNode".equals(methodName)) {
50 return getNode(args);
51 } else if ("getProperty".equals(methodName)) {
52 return getProperty(args);
53 } else if ("setProperty".equals(methodName)) {
54 return setProperty(args);
55 } else if ("addNode".equals(methodName)) {
56 return addNode(args);
57 } else if ("getItem".equals(methodName)) {
58 return getItem(args);
59 } else if ("getParent".equals(methodName)) {
60 return getParent();
61 } else if ("getRootNode".equals(methodName)) {
62 return MockNode.getRooMockNode().getJcrMock();
63 }
64 throw new UnsupportedOperationException("The method " + methodName + " is not supported");
65 }
66
67 private Node getParent() throws RepositoryException {
68 return mockNode.getParent().getJcrMock();
69 }
70
71 private Item getProperty(Object args[]) throws RepositoryException {
72 if (args.length == 1 && args[0] instanceof String) {
73 final MockProperty mockProperty = mockNode.getMockProperty((String) args[0]);
74 if (mockProperty != null) {
75 return mockProperty.mockJcrProperty();
76 }
77 }
78 throw new PathNotFoundException("Property '" + args[0] + "' does not exist");
79 }
80
81 private Item getNode(Object args[]) throws RepositoryException {
82 if (args.length == 1 && args[0] instanceof String) {
83 final MockNode child = mockNode.getMockChildNode((String) args[0]);
84 if (child != null) {
85 return MockNode.mockJcrNode(child);
86 }
87 }
88 throw new PathNotFoundException("Node '" + args[0] + "' does not exist");
89 }
90
91 public Item getItem(Object args[]) throws RepositoryException {
92 if (args.length == 1 && args[0] instanceof String) {
93 if (!((String) args[0]).startsWith("/")) {
94 throw new PathNotFoundException("Path '" + args[0] + "' cannot be found");
95 }
96 final String[] paths = splitString((String) args[0], "/");
97 int pos = 0;
98 MockNode childNode = mockNode.getMockChildNode(paths[pos++]);
99 if (childNode == null) {
100 throw new PathNotFoundException("Path '" + args[0] + "' cannot be found");
101 }
102 MockNode parentNode = childNode;
103 while (pos < paths.length) {
104 childNode = childNode.getMockChildNode(paths[pos]);
105
106 if (childNode == null) {
107 MockProperty mockProperty = parentNode.getMockProperty(paths[pos]);
108 if (mockProperty != null) {
109 return mockProperty.mockJcrProperty();
110 }
111 break;
112 }
113 parentNode = childNode;
114 pos++;
115 }
116 if (childNode != null) {
117 return MockNode.mockJcrNode(childNode);
118 }
119 }
120 throw new PathNotFoundException("Path '" + args[0] + "' cannot be found.");
121 }
122
123 private Item addNode(Object[] args) throws RepositoryException {
124 if (args.length > 0 && args[0] instanceof String) {
125 MockNode newChild = new MockNode();
126 newChild.setMockNodeName((String) args[0]);
127 if (args.length == 2 && args[1] instanceof String) {
128 final MockProperty typeProperty = new MockProperty();
129 typeProperty.setMockValues(Collections.singletonList((String) args[1]));
130 typeProperty.setMockPropertyName("jcr:primaryType");
131 newChild.setMockProperty(typeProperty);
132 }
133 mockNode.addMockChildNode(newChild);
134 return MockNode.mockJcrNode(newChild);
135 }
136 return null;
137 }
138
139 private Item setProperty(Object[] args) throws RepositoryException {
140 final MockProperty mockProperty = new MockProperty();
141 mockProperty.setMockPropertyName((String) args[0]);
142 mockProperty.setMockPropertyType(args[1].getClass().getSimpleName());
143 final ArrayList<String> values = new ArrayList<String>();
144 if (args[1] instanceof Calendar) {
145 values.add(ISO8601.format((Calendar) args[1]));
146 mockProperty.setMockPropertyType(DATE);
147 } else if (args[1] instanceof Value) {
148 final Object object = getValue((Value) args[1]).toString();
149 values.add(object.toString());
150 mockProperty.setMockPropertyType(object.getClass().getSimpleName());
151 } else if (args[1] instanceof Value[]) {
152 for (Value value : (Value[]) args[1]) {
153 final Object object = getValue(value).toString();
154 values.add(object.toString());
155 mockProperty.setMockPropertyType(object.getClass().getSimpleName());
156 }
157 } else if (args[1].getClass().isArray()) {
158 for (Object obj : (Object[]) args[1]) {
159 values.add(obj.toString());
160 mockProperty.setMockPropertyType(obj.getClass().getSimpleName());
161 }
162 } else {
163 values.add(args[1].toString());
164 }
165 mockProperty.setMockValues(values);
166 mockNode.setMockProperty(mockProperty);
167 return mockProperty.mockJcrProperty();
168 }
169
170 private static String[] splitString(final String string, final String separator) {
171 if (isBlank(string)) {
172 return new String[0];
173 }
174 final List<String> valueList = new ArrayList<String>();
175 final String[] values = string.split(separator);
176 for (String value : values) {
177 final String trimmedValue = value.trim();
178 if (!isBlank(trimmedValue)) {
179 valueList.add(trimmedValue);
180 }
181 }
182 return valueList.toArray(new String[valueList.size()]);
183 }
184
185 private static boolean isBlank(String string) {
186 return string == null || string.trim().length() == 0;
187 }
188
189 public static Object getValue(final Value value) throws RepositoryException {
190 final int valueType = value.getType();
191 switch (valueType) {
192 case PropertyType.BOOLEAN:
193 return value.getBoolean();
194 case PropertyType.DATE:
195 return value.getDate();
196 case PropertyType.DOUBLE:
197 return value.getDouble();
198 case PropertyType.LONG:
199 return value.getLong();
200 case PropertyType.STRING:
201 return value.getString();
202 }
203 throw new UnsupportedOperationException("The value type '" + valueType + "' is not supported.");
204 }
205 }