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.form.field.transformer.multi;
35
36 import info.magnolia.cms.i18n.I18nContentSupport;
37 import info.magnolia.jcr.util.NodeTypes;
38 import info.magnolia.jcr.util.NodeUtil;
39 import info.magnolia.objectfactory.Components;
40 import info.magnolia.ui.api.i18n.I18NAuthoringSupport;
41 import info.magnolia.ui.form.field.definition.ConfiguredFieldDefinition;
42 import info.magnolia.ui.form.field.transformer.basic.BasicTransformer;
43 import info.magnolia.ui.vaadin.integration.jcr.JcrNewNodeAdapter;
44 import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter;
45
46 import java.util.ArrayList;
47 import java.util.List;
48 import java.util.Locale;
49
50 import javax.inject.Inject;
51 import javax.jcr.Node;
52 import javax.jcr.RepositoryException;
53
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 import com.google.common.collect.ImmutableList;
58 import com.vaadin.v7.data.Item;
59 import com.vaadin.v7.data.Property;
60 import com.vaadin.v7.data.util.ObjectProperty;
61 import com.vaadin.v7.data.util.PropertysetItem;
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 public class DelegatingMultiValueFieldTransformer extends BasicTransformer<PropertysetItem> implements MultiTransformer {
78
79 private static final Logger log = LoggerFactory.getLogger(DelegatingMultiValueFieldTransformer.class);
80
81 protected String childNodeType = NodeTypes.ContentNode.NAME;
82
83 protected String subItemBaseName;
84
85 private List<String> delegateItemNames = new ArrayList<>();
86
87 private PropertysetItem delegateAggregatorItem = new PropertysetItem();
88
89
90
91
92
93 @Deprecated
94 public DelegatingMultiValueFieldTransformer(Item relatedFormItem, ConfiguredFieldDefinition definition, Class<PropertysetItem> type, I18nContentSupport i18nContentSupport) {
95 this(relatedFormItem, definition, type, Components.getComponent(I18NAuthoringSupport.class));
96 }
97
98 @Inject
99 public DelegatingMultiValueFieldTransformer(Item relatedFormItem, ConfiguredFieldDefinition definition, Class<PropertysetItem> type, I18NAuthoringSupport i18nAuthoringSupport) {
100 super(relatedFormItem, definition, type, i18nAuthoringSupport);
101 this.subItemBaseName = getSubItemBaseName();
102 }
103
104
105
106
107
108
109
110 @Override
111 public PropertysetItem readFromItem() {
112
113 if (delegateAggregatorItem.getItemPropertyIds().isEmpty()) {
114 JcrNodeAdapter rootItem = getRootItem();
115
116 if (!rootItem.hasChildItemChanges()) {
117 populateStoredChildItems(rootItem);
118 }
119
120 int position = 0;
121 for (String itemName : rootItem.getChildren().keySet()) {
122 if (itemName.matches(childItemRegexRepresentation())) {
123 delegateAggregatorItem.addItemProperty(position, new ObjectProperty<Item>(rootItem.getChild(itemName)));
124 delegateItemNames.add(itemName);
125 ++position;
126 }
127 }
128 }
129 return delegateAggregatorItem;
130 }
131
132
133
134
135 @Override
136 public void writeToItem(PropertysetItem newValue) {
137 log.debug("CALL writeToItem");
138 }
139
140
141
142
143
144
145
146
147 @Override
148 public Property<?> createProperty() {
149 final String newItemName = createNewItemName();
150
151 final JcrNodeAdapter child;
152
153
154 if (getRootItem().getChild(newItemName) instanceof JcrNodeAdapter) {
155 child = (JcrNodeAdapter) getRootItem().getChild(newItemName);
156 } else {
157 child = new JcrNewNodeAdapter(getRootItem().getJcrItem(), childNodeType, newItemName);
158 }
159
160 getRootItem().addChild(child);
161 Property<?> res = new ObjectProperty<Item>(child);
162 delegateAggregatorItem.addItemProperty(delegateAggregatorItem.getItemPropertyIds().size(), res);
163
164 return res;
165 }
166
167 @Override
168 public void removeProperty(Object id) {
169 Property<?> propertyToRemove = delegateAggregatorItem.getItemProperty(id);
170 if (propertyToRemove != null && propertyToRemove.getValue() != null) {
171 JcrNodeAdapter./../../../info/magnolia/ui/vaadin/integration/jcr/JcrNodeAdapter.html#JcrNodeAdapter">JcrNodeAdapter toRemove = (JcrNodeAdapter) propertyToRemove.getValue();
172 toRemove.getParent().removeChild(toRemove);
173 }
174 delegateAggregatorItem.removeItemProperty(id);
175 reorganizeIndex((Integer) id);
176 }
177
178 @Override
179 public void setLocale(Locale locale) {
180 super.setLocale(locale);
181 ImmutableList<Object> propertyIds = ImmutableList.copyOf(delegateAggregatorItem.getItemPropertyIds());
182 for (Object id : propertyIds) {
183 delegateAggregatorItem.removeItemProperty(id);
184 }
185 }
186
187
188
189
190
191
192
193 private void reorganizeIndex(int fromIndex) {
194 int valuesSize = delegateAggregatorItem.getItemPropertyIds().size();
195 if (fromIndex == valuesSize) {
196 return;
197 }
198 while (fromIndex < valuesSize) {
199 int toIndex = fromIndex;
200 ++fromIndex;
201 delegateAggregatorItem.addItemProperty(toIndex, delegateAggregatorItem.getItemProperty(fromIndex));
202 delegateAggregatorItem.removeItemProperty(fromIndex);
203 }
204 }
205
206
207
208
209 protected JcrNodeAdapter getRootItem() {
210 return (JcrNodeAdapter) relatedFormItem;
211 }
212
213
214
215
216
217
218 protected String getSubItemBaseName() {
219 return definition.getName();
220 }
221
222
223
224
225 protected void populateStoredChildItems(JcrNodeAdapter rootItem) {
226 List<Node> childNodes = getStoredChildNodes(rootItem);
227 for (Node child : childNodes) {
228 JcrNodeAdapterntegration/jcr/JcrNodeAdapter.html#JcrNodeAdapter">JcrNodeAdapter item = new JcrNodeAdapter(child);
229 rootItem.addChild(item);
230 }
231 }
232
233
234
235
236 protected List<Node> getStoredChildNodes(JcrNodeAdapter parent) {
237 try {
238 if (!(parent instanceof JcrNewNodeAdapter) && parent.getJcrItem().hasNodes()) {
239 return NodeUtil.asList(NodeUtil.getNodes(parent.getJcrItem(), NodeUtil.MAGNOLIA_FILTER));
240 }
241 } catch (RepositoryException re) {
242 log.warn("Not able to access the Child Nodes of the following Node Identifier {}", parent.getItemId(), re);
243 }
244 return new ArrayList<Node>();
245 }
246
247
248
249
250
251
252
253
254
255
256
257 protected String createNewItemName() {
258 int increment = 0;
259 final List<String> childNodeNames = getChildItemNames();
260 String name;
261 do {
262 name = deriveLocaleAwareName(String.format("%s%d", subItemBaseName, increment));
263 ++increment;
264 } while (childNodeNames.contains(name));
265 return name;
266 }
267
268
269
270
271 protected String childItemRegexRepresentation() {
272 if (hasI18NSupport()) {
273 if (getLocale() == null || getI18NAuthoringSupport().isDefaultLocale(getLocale(), relatedFormItem)) {
274
275
276 return subItemBaseName + incrementRegexRepresentation() + "((?!(_\\w{2}){1,3}))$";
277 } else {
278
279 return getI18NAuthoringSupport().deriveLocalisedPropertyName(subItemBaseName + incrementRegexRepresentation(), getLocale());
280 }
281 } else {
282 return subItemBaseName + incrementRegexRepresentation();
283 }
284 }
285
286 protected String incrementRegexRepresentation() {
287 return "(\\d{1,3})";
288 }
289
290 protected List<String> getChildItemNames() {
291 List<String> res = new ArrayList<>();
292 res.addAll(delegateItemNames);
293 for (Object delegateIds : delegateAggregatorItem.getItemPropertyIds()) {
294 Object value = delegateAggregatorItem.getItemProperty(delegateIds).getValue();
295 if (value instanceof JcrNodeAdapter) {
296 res.add(((JcrNodeAdapter) value).getNodeName());
297 }
298 }
299 return res;
300 }
301
302
303
304 @Override
305 public String getBasePropertyName() {
306 return subItemBaseName;
307 }
308
309 @Override
310 public void setI18NPropertyName(String i18NSubNodeName) {
311 log.warn("DelegatingMultiValueFieldTransformer.setI18NPropertyName is deprecated since 5.4.2 - should you need a different locale-specific node name, it is possible to alter #i18nSuffix field in #setLocale() method.");
312 }
313 }