View Javadoc
1   /*
2    * Copyright 2012-2022 Bloomreach
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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   * Item answer for getNode, getProperty, setProperty, addNode, getItem
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                 // check if property exists
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 }