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.ui.contentapp.browser;
35
36 import info.magnolia.cms.core.Path;
37 import info.magnolia.jcr.util.NodeTypes;
38 import info.magnolia.jcr.util.NodeUtil;
39 import info.magnolia.ui.framework.ContentClipboard;
40 import info.magnolia.ui.framework.ContentClipboardException;
41 import info.magnolia.ui.vaadin.integration.jcr.JcrItemId;
42 import info.magnolia.ui.vaadin.integration.jcr.JcrItemUtil;
43
44 import java.text.MessageFormat;
45 import java.util.ArrayList;
46 import java.util.List;
47
48 import javax.jcr.Item;
49 import javax.jcr.Node;
50 import javax.jcr.Property;
51 import javax.jcr.RepositoryException;
52 import javax.jcr.nodetype.NodeType;
53
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57
58
59
60 public class JcrContentClipboard implements ContentClipboard<JcrItemId> {
61
62 private static final Logger log = LoggerFactory.getLogger(JcrContentClipboard.class);
63
64 private List<JcrItemId> items = new ArrayList<>();
65
66 @Override
67 public void copy(final List<JcrItemId> source) {
68 if (canCopy(source)) {
69 this.items = source;
70 }
71 }
72
73 @Override
74 public List<JcrItemId> paste(final JcrItemId destination) {
75 List<JcrItemId> pastedItems = new ArrayList<>();
76 try {
77 if (canPasteInto(destination)) {
78 for (JcrItemId sourceItem : items) {
79 pastedItems.add(pasteSingleItem(sourceItem, destination));
80 }
81 }
82 } catch (RepositoryException e) {
83 throw new ContentClipboardException(MessageFormat.format("Failed while pasting items under JCR item with UUID [{0}] from [{1}] workspace.", destination.getUuid(), destination.getWorkspace()), e);
84 }
85 return pastedItems;
86 }
87
88 protected JcrItemId pasteSingleItem(final JcrItemId source, final JcrItemId destination) throws RepositoryException {
89 Item sourceItem = JcrItemUtil.getJcrItem(source);
90 Node destinationNode = (Node) JcrItemUtil.getJcrItem(destination);
91 if (sourceItem.isNode()) {
92 return pasteSingleNode((Node) sourceItem, destinationNode);
93 } else {
94 return pasteSingleProperty((Property) sourceItem, destinationNode);
95 }
96 }
97
98 protected JcrItemId pasteSingleNode(final Node sourceNode, final Node destinationNode) throws RepositoryException {
99
100
101
102 String newName = getUniqueNewItemName(sourceNode, destinationNode);
103 String newPath = Path.getAbsolutePath(destinationNode.getPath(), newName);
104
105 sourceNode.getSession().getWorkspace().copy(sourceNode.getPath(), newPath);
106 sourceNode.getSession().save();
107 Node newNode = sourceNode.getSession().getNode(newPath);
108 return JcrItemUtil.getItemId(newNode);
109 }
110
111 protected JcrItemId pasteSingleProperty(final Property property, final Node destinationNode) throws RepositoryException {
112 String newName = getUniqueNewItemName(property, destinationNode);
113 if (property.isMultiple()) {
114 destinationNode.setProperty(newName, property.getValues());
115 } else {
116 destinationNode.setProperty(newName, property.getValue());
117 }
118 destinationNode.getSession().save();
119 return JcrItemUtil.getItemId(destinationNode.getProperty(newName));
120 }
121
122 @Override
123 public boolean canCopy(final List<JcrItemId> source) {
124 if (source.isEmpty()) {
125 return false;
126 } else {
127 for (JcrItemId itemId : source) {
128 try {
129 Item item = JcrItemUtil.getJcrItem(itemId);
130 if (item.isNode() && (NodeUtil.hasMixin((Node) item, NodeTypes.Deleted.NAME))) {
131 return false;
132 }
133 } catch (RepositoryException e) {
134 log.error("Failed to obtain JCR item with UUID [{}] from workspace [{}] due to: {}. Returning false...", itemId.getUuid(), itemId.getWorkspace(), e.getMessage());
135 return false;
136 }
137 }
138 return true;
139 }
140 }
141
142 @Override
143 public boolean canPasteInto(final JcrItemId destination) {
144 try {
145 if (!JcrItemUtil.getJcrItem(destination).isNode()) {
146 return false;
147 }
148 } catch (RepositoryException e) {
149 log.warn("Failed to check whether the clipboard content can be pasted to the JCR item with UUID [{}] from workspace [{}] due to: {}. Returning false...", destination.getUuid(), destination.getWorkspace(), e.getMessage());
150 return false;
151 }
152
153 return items.stream().filter(item -> canPasteInto(item, destination)).findFirst().isPresent();
154 }
155
156 protected boolean canPasteInto(final JcrItemId source, final JcrItemId destination) {
157 boolean result = false;
158 try {
159 Item sourceItem = JcrItemUtil.getJcrItem(source);
160 Item destinationItem = JcrItemUtil.getJcrItem(destination);
161 if (sourceItem != null && destinationItem.isNode() && sourceItem.getSession().getWorkspace().getName().equals(destinationItem.getSession().getWorkspace().getName())) {
162 final Node destinationNode = (Node) destinationItem;
163 final NodeType destinationNodeType = destinationNode.getPrimaryNodeType();
164 if (sourceItem.isNode()) {
165 result = destinationNodeType.canAddChildNode(sourceItem.getName(), ((Node) sourceItem).getPrimaryNodeType().getName());
166 } else {
167 Property property = (Property) sourceItem;
168 if (property.isMultiple()) {
169 result = destinationNodeType.canSetProperty(property.getName(), property.getValues());
170 } else {
171 result = destinationNodeType.canSetProperty(property.getName(), property.getValue());
172 }
173 }
174 }
175 } catch (RepositoryException e) {
176 log.error("Failed to check whether the item with UUID [{}] from workspace [{}] into the item with UUID [{}] from workspace [{}] due to: {}", source.getUuid(), source.getWorkspace(), destination.getUuid(), destination.getWorkspace(), e.getMessage(), e);
177 }
178
179 return result;
180 }
181
182
183
184
185
186 protected String getUniqueNewItemName(Item referenceItem, Node destination) throws RepositoryException {
187 return Path.getUniqueLabel(destination.getSession(), destination.getPath(), referenceItem.getName());
188 }
189 }