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.commands.impl;
35
36 import info.magnolia.cms.core.version.VersionManager;
37 import info.magnolia.cms.util.Rule;
38 import info.magnolia.context.Context;
39 import info.magnolia.jcr.predicate.NodeTypePredicate;
40 import info.magnolia.jcr.predicate.RuleBasedNodePredicate;
41 import info.magnolia.jcr.util.NodeTypes;
42 import info.magnolia.jcr.util.NodeUtil;
43
44 import javax.inject.Inject;
45 import javax.jcr.Node;
46 import javax.jcr.RepositoryException;
47 import javax.jcr.version.Version;
48 import javax.jcr.version.VersionIterator;
49
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53
54
55
56 public class RestorePreviousVersionCommand extends RuleBasedCommand {
57
58 private static final Logger log = LoggerFactory.getLogger(RestorePreviousVersionCommand.class);
59
60 public static final String ATTRIBUTE_PARENT_NODE_TYPE_ONLY = "parentNodeTypeOnly";
61
62 public static final String ATTRIBUTE_INCLUDING_CHILDREN = "includingChildren";
63
64 private VersionManager versionManager;
65
66 private boolean parentNodeTypeOnly = false;
67
68 private boolean includingChildren = true;
69
70 @Inject
71 public RestorePreviousVersionCommand(VersionManager versionManager) {
72 this.versionManager = versionManager;
73 }
74
75 @Override
76 public boolean execute(Context context) throws Exception {
77 final Node node = getJCRNode(context);
78
79 parentNodeTypeOnly = (Boolean) (context.containsKey(ATTRIBUTE_PARENT_NODE_TYPE_ONLY) ? context.get(ATTRIBUTE_PARENT_NODE_TYPE_ONLY) : parentNodeTypeOnly);
80
81 includingChildren = (Boolean) (context.containsKey(ATTRIBUTE_INCLUDING_CHILDREN) ? context.get(ATTRIBUTE_INCLUDING_CHILDREN) : includingChildren);
82
83 if (context.containsKey(ATTRIBUTE_RULE)) {
84 setRule((Rule) context.getAttribute(ATTRIBUTE_RULE));
85 }
86
87 restore(node);
88
89 return true;
90 }
91
92 @Override
93 protected Rule getDefaultRule() {
94 final Rule rule = super.getDefaultRule();
95 rule.removeAllowType(NodeTypes.Resource.NAME);
96 return rule;
97 }
98
99 private void restore(Node node) throws RepositoryException {
100 String nodeType = node.getPrimaryNodeType().getName();
101
102 log.debug("Restoring previous version of node at {} of type {}", node.getPath(), nodeType);
103
104
105 Version version = getPreviousVersion(node);
106
107 if (version == null) {
108 throw new RepositoryException("No previous version found for node at " + node.getPath());
109 }
110
111
112 versionManager.restore(node, version, true);
113
114 if (includingChildren) {
115 restoreAllChildren(node, nodeType);
116 }
117 }
118
119
120
121
122
123
124
125
126
127
128
129
130 protected void restoreAllChildren(Node node, String parentNodeType) throws RepositoryException {
131
132 Iterable<Node> children;
133
134 if (isParentNodeTypeOnly()) {
135 children = NodeUtil.collectAllChildren(node, new NodeTypePredicate(parentNodeType));
136 } else {
137 children = NodeUtil.collectAllChildren(node, new RuleBasedNodePredicate(this.getRule()));
138 }
139
140 for (Node child : children) {
141 Version childVersion = getPreviousVersion(child);
142 if (childVersion == null) {
143 log.debug("No previous version found for subnode {}. Skipping restore...", child.getPath());
144 continue;
145 }
146 versionManager.restore(child, childVersion, true);
147 }
148 }
149
150
151
152
153 private Version getPreviousVersion(Node node) throws RepositoryException {
154 Version previousVersion = null;
155 VersionIterator versionIterator = versionManager.getAllVersions(node);
156
157 while (versionIterator.hasNext()) {
158 previousVersion = versionIterator.nextVersion();
159 }
160
161 return previousVersion;
162 }
163
164
165
166
167 public boolean isParentNodeTypeOnly() {
168 return parentNodeTypeOnly;
169 }
170
171 }