View Javadoc
1   /**
2    * This file Copyright (c) 2009-2018 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.nodebuilder;
35  
36  import info.magnolia.cms.core.Content;
37  import info.magnolia.cms.core.ItemType;
38  import info.magnolia.cms.core.NodeData;
39  import info.magnolia.cms.util.ContentUtil;
40  import info.magnolia.cms.util.NodeDataUtil;
41  import info.magnolia.cms.util.NodeTypeFilter;
42  
43  import javax.jcr.ItemExistsException;
44  import javax.jcr.ItemNotFoundException;
45  import javax.jcr.RepositoryException;
46  import javax.jcr.Value;
47  
48  /**
49   * Factory methods for most common NodeOperation implementations.
50   *
51   * @deprecated since 5.2.3 - use {@link info.magnolia.jcr.nodebuilder.Ops} instead.
52   */
53  @Deprecated
54  public abstract class Ops {
55      public static NodeOperation addNode(final String name) {
56          return new AbstractNodeOperation() {
57              @Override
58              protected Content="../../../info/magnolia/cms/core/Content.html#Content">Content doExec(Content context, ErrorHandler errorHandler) throws RepositoryException {
59                  return context.createContent(name);
60              }
61          };
62      }
63  
64      public static NodeOperation addNode(final String name, final String type) {
65          return new AbstractNodeOperation() {
66              @Override
67              protected Content="../../../info/magnolia/cms/core/Content.html#Content">Content doExec(Content context, ErrorHandler errorHandler) throws RepositoryException {
68                  return context.createContent(name, type);
69              }
70          };
71      }
72  
73      public static NodeOperation addNode(final String name, final ItemType type) {
74          return new AbstractNodeOperation() {
75              @Override
76              protected Content="../../../info/magnolia/cms/core/Content.html#Content">Content doExec(Content context, ErrorHandler errorHandler) throws RepositoryException {
77                  return context.createContent(name, type);
78              }
79          };
80      }
81  
82      public static NodeOperation getNode(final String name) {
83          return new AbstractNodeOperation() {
84              @Override
85              protected Content="../../../info/magnolia/cms/core/Content.html#Content">Content doExec(Content context, ErrorHandler errorHandler) throws RepositoryException {
86                  return context.getContent(name);
87              }
88          };
89      }
90  
91      /**
92       * Can remove either a node or property.
93       */
94      public static NodeOperation remove(final String name) {
95          return new AbstractNodeOperation() {
96              @Override
97              protected Content="../../../info/magnolia/cms/core/Content.html#Content">Content doExec(Content context, ErrorHandler errorHandler) throws RepositoryException {
98                  context.delete(name);
99                  return context;
100             }
101         };
102     }
103 
104     /**
105      * Adds a currently non-existing property. Throws an ItemExistsException if the property already exists.
106      */
107     public static NodeOperation addProperty(final String name, final Object value) {
108         return new AbstractNodeOperation() {
109             @Override
110             protected Content="../../../info/magnolia/cms/core/Content.html#Content">Content doExec(Content context, ErrorHandler errorHandler) throws RepositoryException {
111                 if (context.hasNodeData(name)) {
112                     // throw new ItemExistsException("Property " + name + " already exists at " + context.getHandle());
113                     throw new ItemExistsException(name);
114                 }
115                 context.createNodeData(name, value);
116                 return context;
117             }
118         };
119     }
120 
121     /**
122      * Sets the value of an existing property, ignoring its current value.
123      *
124      * @throws ItemNotFoundException if the property does not exist.
125      */
126     public static NodeOperation setProperty(final String name, final Object newValue) {
127         return new AbstractNodeOperation() {
128             @Override
129             protected Content="../../../info/magnolia/cms/core/Content.html#Content">Content doExec(Content context, ErrorHandler errorHandler) throws RepositoryException {
130                 if (!context.hasNodeData(name)) {
131                     throw new ItemNotFoundException(name);
132                 }
133                 final Value value = NodeDataUtil.createValue(newValue, context.getJCRNode().getSession().getValueFactory());
134                 context.setNodeData(name, value);
135                 return context;
136             }
137         };
138     }
139 
140     /**
141      * Sets the value of an existing property, only if the actual current value matches the given expected current value.
142      *
143      * @throws ItemNotFoundException if the property does not exist.
144      * @throws RepositoryException if the current value does not match the expected one.
145      */
146     public static NodeOperation setProperty(final String name, final Object expectedCurrentValue, final Object newValue) {
147         return new AbstractNodeOperation() {
148             @Override
149             protected Content="../../../info/magnolia/cms/core/Content.html#Content">Content doExec(Content context, ErrorHandler errorHandler) throws RepositoryException {
150                 if (!context.hasNodeData(name)) {
151                     throw new ItemNotFoundException(name);
152                 }
153                 final NodeData current = context.getNodeData(name);
154                 if (!expectedCurrentValue.equals(NodeDataUtil.getValueObject(current))) {
155                     errorHandler.report("Expected " + expectedCurrentValue + " at " + current.getHandle() + " but found " + current.getString() + " instead; can't set value to " + newValue + ".");
156                     return context;
157                 }
158 
159                 final Value value = NodeDataUtil.createValue(newValue, context.getJCRNode().getSession().getValueFactory());
160                 current.setValue(value);
161                 return context;
162             }
163         };
164     }
165 
166     /**
167      * Renames a node.
168      */
169     public static NodeOperation renameNode(final String currentName, final String newName) {
170         return new AbstractNodeOperation() {
171             @Override
172             protected Content="../../../info/magnolia/cms/core/Content.html#Content">Content doExec(Content context, ErrorHandler errorHandler) throws RepositoryException {
173                 ContentUtil.rename(context.getContent(currentName), newName);
174                 return context;
175             }
176         };
177     }
178 
179     /**
180      * Renames a property by creating a new one and copying the value.
181      */
182     public static NodeOperation renameProperty(final String name, final String newName) {
183         return new AbstractNodeOperation() {
184             @Override
185             protected Content="../../../info/magnolia/cms/core/Content.html#Content">Content doExec(Content context, ErrorHandler errorHandler) throws RepositoryException {
186                 if (!context.hasNodeData(name)) {
187                     throw new ItemNotFoundException(name);
188                 }
189                 if (context.hasNodeData(newName)) {
190                     //throw new ItemExistsException("Property " + newName + " already exists at " + context.getHandle());
191                     throw new ItemExistsException(newName);
192                 }
193                 final Value value = context.getNodeData(name).getValue();
194                 context.setNodeData(newName, value);
195                 context.deleteNodeData(name);
196                 return context;
197             }
198         };
199     }
200 
201     /**
202      * Moves a node, using session-scoped operation.
203      */
204     public static NodeOperation moveNode(final String nodeName, final String dest) {
205         return new AbstractNodeOperation() {
206             @Override
207             protected Content="../../../info/magnolia/cms/core/Content.html#Content">Content doExec(Content context, ErrorHandler errorHandler) throws RepositoryException {
208                 ContentUtil.moveInSession(context.getContent(nodeName), dest);
209                 return context;
210             }
211         };
212     }
213 
214     /**
215      * Copies a node, using session-scoped operation.
216      */
217     public static NodeOperation copyNode(final String nodeName, final String dest) {
218         return new AbstractNodeOperation() {
219             @Override
220             protected Content="../../../info/magnolia/cms/core/Content.html#Content">Content doExec(Content context, ErrorHandler errorHandler) throws RepositoryException {
221                 ContentUtil.copyInSession(context.getContent(nodeName), dest);
222                 return context;
223             }
224         };
225     }
226 
227     /**
228      * Executes the operation for each child node excluding meta data and jcr base node.
229      */
230     public static NodeOperation onChildNodes(final NodeOperation... childrenOps) {
231         return onChildNodes(ContentUtil.EXCLUDE_META_DATA_CONTENT_FILTER, childrenOps);
232     }
233 
234     /**
235      * Executes the operation for each child node of a certain type.
236      */
237     public static NodeOperation onChildNodes(final String type, final NodeOperation... childrenOps) {
238         return onChildNodes(new NodeTypeFilter(type), childrenOps);
239     }
240 
241     /**
242      * Executes the operation for each child node of a certain type.
243      */
244     public static NodeOperation onChildNodes(final ItemType type, final NodeOperation... childrenOps) {
245         return onChildNodes(new NodeTypeFilter(type), childrenOps);
246     }
247 
248     /**
249      * Executes the operation for each child node matching the filter.
250      */
251     public static NodeOperation onChildNodes(final Content.ContentFilter filter, final NodeOperation... childrenOps) {
252         return new AbstractNodeOperation() {
253             // TODO shouldn't this implement NodeOperation directly instead? it has no business doing with the then() method anyway
254             @Override
255             protected Content="../../../info/magnolia/cms/core/Content.html#Content">Content doExec(Content context, ErrorHandler errorHandler) throws RepositoryException {
256                 for (Content subNode : context.getChildren(filter)) {
257                     for (NodeOperation nodeOperation : childrenOps) {
258                         nodeOperation.exec(subNode, errorHandler);
259                     }
260                 }
261                 return context;
262             }
263         };
264     }
265 
266     /**
267      * No operation; can be useful in ternary expression, for instance.
268      */
269     public static NodeOperation noop() {
270         return new NodeOperation() {
271             @Override
272             public NodeOperation then(NodeOperation... childrenOps) {
273                 return null;
274             }
275 
276             @Override
277             public void exec(Content context, ErrorHandler errorHandler) {
278             }
279         };
280     }
281 
282     /**
283      * See {@link AbstractNodeOperation}.
284      *
285      * @deprecated since 4.4.1, class has been extracted to {@link AbstractNodeOperation}.
286      */
287     abstract static class AbstractOp extends AbstractNodeOperation {
288     }
289 
290 }