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