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.composite;
35
36 import info.magnolia.jcr.util.NodeTypes;
37 import info.magnolia.jcr.util.NodeUtil;
38 import info.magnolia.jcr.util.PropertyUtil;
39 import info.magnolia.jcr.wrapper.JCRMgnlPropertiesFilteringNodeWrapper;
40 import info.magnolia.ui.api.i18n.I18NAuthoringSupport;
41 import info.magnolia.ui.form.field.definition.CompositeFieldDefinition;
42 import info.magnolia.ui.form.field.definition.ConfiguredFieldDefinition;
43 import info.magnolia.ui.form.field.transformer.basic.BasicTransformer;
44 import info.magnolia.ui.vaadin.integration.NullItem;
45 import info.magnolia.ui.vaadin.integration.jcr.JcrNewNodeAdapter;
46 import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter;
47
48 import java.util.List;
49
50 import javax.inject.Inject;
51 import javax.jcr.Node;
52 import javax.jcr.Property;
53 import javax.jcr.PropertyIterator;
54 import javax.jcr.RepositoryException;
55
56 import org.apache.commons.lang3.StringUtils;
57 import org.apache.commons.lang3.math.NumberUtils;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61 import com.vaadin.v7.data.Item;
62 import com.vaadin.v7.data.util.ObjectProperty;
63 import com.vaadin.v7.data.util.PropertysetItem;
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 public class DelegatingSubnodeCompositeTransformer extends BasicTransformer<PropertysetItem> {
85
86 private static final Logger log = LoggerFactory.getLogger(DelegatingSubnodeCompositeTransformer.class);
87
88 private static String DEFAULT_CHILD_NODE_TYPE = NodeTypes.Content.NAME;
89
90 private PropertysetItem delegateAggregatorItem = new PropertysetItem();
91
92 @Inject
93 public DelegatingSubnodeCompositeTransformer(Item relatedFormItem, ConfiguredFieldDefinition definition, Class<PropertysetItem> type, I18NAuthoringSupport i18NAuthoringSupport) {
94 super(relatedFormItem, definition, type, i18NAuthoringSupport);
95 }
96
97 @Override
98 public PropertysetItem readFromItem() {
99
100 if (!delegateAggregatorItem.getItemPropertyIds().isEmpty()) {
101 return delegateAggregatorItem;
102 }
103 JcrNodeAdapter rootItem = getRootItem();
104
105
106 if (!rootItem.hasChildItemChanges()) {
107 populateStoredItems(rootItem);
108 }
109
110 List<ConfiguredFieldDefinition> fields = ((CompositeFieldDefinition) definition).getFields();
111 for (ConfiguredFieldDefinition fieldDefinition : fields) {
112 delegateAggregatorItem.addItemProperty(fieldDefinition.getName(), new ObjectProperty<>(rootItem));
113 }
114 return delegateAggregatorItem;
115 }
116
117 @Override
118 public void writeToItem(PropertysetItem newValue) {
119 log.debug("CALL writeToItem");
120 }
121
122 private String getChildNodeType(CompositeFieldDefinition definition) {
123 return StringUtils.defaultIfBlank(definition.getNodeType(), DEFAULT_CHILD_NODE_TYPE);
124 }
125
126 protected JcrNodeAdapter getRootItem() {
127 JcrNodeAdapter res = null;
128 try {
129 res = getOrCreateChildNode(relatedFormItem, deriveLocaleAwareName(definition.getName()), getChildNodeType((CompositeFieldDefinition) definition));
130 } catch (RepositoryException re) {
131 log.warn("Not able to retrieve or create a sub node for the parent node {}", ((JcrNodeAdapter) relatedFormItem).getItemId());
132 }
133 return res;
134 }
135
136
137
138
139 private void populateStoredItems(JcrNodeAdapter rootItem) {
140 if (rootItem instanceof JcrNewNodeAdapter) {
141 return;
142 }
143 try {
144 Node jcrNode = rootItem.getJcrItem();
145 if (jcrNode.hasProperties()) {
146 PropertyIterator iterator = new JCRMgnlPropertiesFilteringNodeWrapper(jcrNode).getProperties();
147 while (iterator.hasNext()) {
148 Property jcrProperty = iterator.nextProperty();
149 String propertyName = jcrProperty.getName();
150 Object propertyValue = PropertyUtil.getPropertyValueObject(jcrNode, propertyName);
151 com.vaadin.v7.data.Property newProperty = new ObjectProperty<>(propertyValue);
152 rootItem.addItemProperty(NumberUtils.isNumber(propertyName) ? Integer.valueOf(propertyName) : propertyName, newProperty);
153 }
154 }
155
156 if (jcrNode.hasNodes()) {
157 Iterable<Node> childNodes = NodeUtil.getNodes(jcrNode, NodeUtil.MAGNOLIA_FILTER);
158 for (Node child : childNodes) {
159 JcrNodeAdapter item = new JcrNodeAdapter(child);
160 rootItem.addChild(item);
161 }
162 }
163 } catch (RepositoryException re) {
164 log.warn("Not able to access the child nodes/properties of the following Node Identifier {}", rootItem, re);
165 }
166 }
167
168
169
170
171 private JcrNodeAdapter getOrCreateChildNode(Item parent, String childNodeName, String childNodeType) throws RepositoryException {
172 JcrNodeAdapter child;
173 if (parent instanceof NullItem) {
174 return null;
175 }
176 if (!(parent instanceof JcrNodeAdapter)) {
177 log.warn("Detected attempt to retrieve a Jcr Item from a Non Jcr Item Adapter. Will return null.");
178 return null;
179 }
180 Node node = ((JcrNodeAdapter) parent).getJcrItem();
181 if (node.hasNode(childNodeName) && !(parent instanceof JcrNewNodeAdapter)) {
182 child = new JcrNodeAdapter(node.getNode(childNodeName));
183 ((JcrNodeAdapter) parent).addChild(child);
184 return child;
185 } else if (((JcrNodeAdapter) parent).getChild(childNodeName) != null) {
186 return (JcrNodeAdapter) ((JcrNodeAdapter) parent).getChild(childNodeName);
187 }
188 child = new JcrNewNodeAdapter(node, childNodeType, childNodeName);
189 ((JcrNodeAdapter) parent).addChild(child);
190 return child;
191 }
192 }