1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.data.provider.impl;
17
18 import com.google.common.collect.Sets;
19 import org.apache.commons.lang.StringUtils;
20 import org.kuali.rice.core.api.criteria.QueryByCriteria;
21 import org.kuali.rice.krad.data.CompoundKey;
22 import org.kuali.rice.krad.data.DataObjectService;
23 import org.kuali.rice.krad.data.DataObjectWrapper;
24 import org.kuali.rice.krad.data.metadata.DataObjectAttribute;
25 import org.kuali.rice.krad.data.metadata.DataObjectAttributeRelationship;
26 import org.kuali.rice.krad.data.metadata.DataObjectCollection;
27 import org.kuali.rice.krad.data.metadata.DataObjectMetadata;
28 import org.kuali.rice.krad.data.metadata.DataObjectRelationship;
29 import org.kuali.rice.krad.data.metadata.MetadataChild;
30 import org.kuali.rice.krad.data.util.ReferenceLinker;
31 import org.springframework.beans.BeanWrapper;
32 import org.springframework.beans.BeansException;
33 import org.springframework.beans.InvalidPropertyException;
34 import org.springframework.beans.NullValueInNestedPathException;
35 import org.springframework.beans.PropertyAccessorFactory;
36 import org.springframework.beans.PropertyAccessorUtils;
37 import org.springframework.beans.PropertyValue;
38 import org.springframework.beans.PropertyValues;
39 import org.springframework.beans.TypeMismatchException;
40 import org.springframework.core.CollectionFactory;
41 import org.springframework.core.MethodParameter;
42 import org.springframework.core.convert.ConversionService;
43 import org.springframework.core.convert.TypeDescriptor;
44
45 import java.beans.PropertyDescriptor;
46 import java.beans.PropertyEditor;
47 import java.lang.reflect.Field;
48 import java.util.ArrayList;
49 import java.util.Collection;
50 import java.util.HashMap;
51 import java.util.LinkedHashMap;
52 import java.util.List;
53 import java.util.Map;
54 import java.util.Set;
55
56
57
58
59
60
61
62
63 public abstract class DataObjectWrapperBase<T> implements DataObjectWrapper<T> {
64 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DataObjectWrapperBase.class);
65
66 private final T dataObject;
67 private final DataObjectMetadata metadata;
68 private final BeanWrapper wrapper;
69 private final DataObjectService dataObjectService;
70 private final ReferenceLinker referenceLinker;
71
72
73
74
75
76
77
78
79
80 protected DataObjectWrapperBase(T dataObject, DataObjectMetadata metadata, DataObjectService dataObjectService,
81 ReferenceLinker referenceLinker) {
82 this.dataObject = dataObject;
83 this.metadata = metadata;
84 this.dataObjectService = dataObjectService;
85 this.referenceLinker = referenceLinker;
86 this.wrapper = PropertyAccessorFactory.forBeanPropertyAccess(dataObject);
87
88
89
90 }
91
92
93
94
95 @Override
96 public DataObjectMetadata getMetadata() {
97 return metadata;
98 }
99
100
101
102
103 @Override
104 public T getWrappedInstance() {
105 return dataObject;
106 }
107
108
109
110
111 @Override
112 public Object getPropertyValueNullSafe(String propertyName) throws BeansException {
113 try {
114 return getPropertyValue(propertyName);
115 } catch (NullValueInNestedPathException e) {
116 return null;
117 }
118 }
119
120
121
122
123 @SuppressWarnings("unchecked")
124 @Override
125 public Class<T> getWrappedClass() {
126 return (Class<T>) wrapper.getWrappedClass();
127 }
128
129
130
131
132 @Override
133 public PropertyDescriptor[] getPropertyDescriptors() {
134 return wrapper.getPropertyDescriptors();
135 }
136
137
138
139
140 @Override
141 public PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException {
142 return wrapper.getPropertyDescriptor(propertyName);
143 }
144
145
146
147
148 @Override
149 public void setAutoGrowNestedPaths(boolean autoGrowNestedPaths) {
150 wrapper.setAutoGrowNestedPaths(autoGrowNestedPaths);
151 }
152
153
154
155
156 @Override
157 public boolean isAutoGrowNestedPaths() {
158 return wrapper.isAutoGrowNestedPaths();
159 }
160
161
162
163
164 @Override
165 public void setAutoGrowCollectionLimit(int autoGrowCollectionLimit) {
166 wrapper.setAutoGrowCollectionLimit(autoGrowCollectionLimit);
167 }
168
169
170
171
172 @Override
173 public int getAutoGrowCollectionLimit() {
174 return wrapper.getAutoGrowCollectionLimit();
175 }
176
177
178
179
180 @Override
181 public void setConversionService(ConversionService conversionService) {
182 wrapper.setConversionService(conversionService);
183 }
184
185
186
187
188 @Override
189 public ConversionService getConversionService() {
190 return wrapper.getConversionService();
191 }
192
193
194
195
196 @Override
197 public void setExtractOldValueForEditor(boolean extractOldValueForEditor) {
198 wrapper.setExtractOldValueForEditor(extractOldValueForEditor);
199 }
200
201
202
203
204 @Override
205 public boolean isExtractOldValueForEditor() {
206 return wrapper.isExtractOldValueForEditor();
207 }
208
209
210
211
212 @Override
213 public boolean isReadableProperty(String propertyName) {
214 return wrapper.isReadableProperty(propertyName);
215 }
216
217
218
219
220 @Override
221 public boolean isWritableProperty(String propertyName) {
222 return wrapper.isWritableProperty(propertyName);
223 }
224
225
226
227
228 @Override
229 public Class<?> getPropertyType(String propertyName) throws BeansException {
230 return wrapper.getPropertyType(propertyName);
231 }
232
233
234
235
236 @Override
237 public TypeDescriptor getPropertyTypeDescriptor(String propertyName) throws BeansException {
238 return wrapper.getPropertyTypeDescriptor(propertyName);
239 }
240
241
242
243
244 @Override
245 public Object getPropertyValue(String propertyName) throws BeansException {
246 return wrapper.getPropertyValue(propertyName);
247 }
248
249
250
251
252 @Override
253 public void setPropertyValue(String propertyName, Object value) throws BeansException {
254 wrapper.setPropertyValue(propertyName, value);
255 }
256
257
258
259
260 @Override
261 public void setPropertyValue(PropertyValue pv) throws BeansException {
262 wrapper.setPropertyValue(pv);
263 }
264
265
266
267
268 @Override
269 public void setPropertyValues(Map<?, ?> map) throws BeansException {
270 wrapper.setPropertyValues(map);
271 }
272
273
274
275
276 @Override
277 public void setPropertyValues(PropertyValues pvs) throws BeansException {
278 wrapper.setPropertyValues(pvs);
279 }
280
281
282
283
284 @Override
285 public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown) throws BeansException {
286 wrapper.setPropertyValues(pvs, ignoreUnknown);
287 }
288
289
290
291
292 @Override
293 public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown,
294 boolean ignoreInvalid) throws BeansException {
295 wrapper.setPropertyValues(pvs, ignoreUnknown, ignoreInvalid);
296 }
297
298
299
300
301 @Override
302 public void registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor) {
303 wrapper.registerCustomEditor(requiredType, propertyEditor);
304 }
305
306
307
308
309 @Override
310 public void registerCustomEditor(Class<?> requiredType, String propertyPath, PropertyEditor propertyEditor) {
311 wrapper.registerCustomEditor(requiredType, propertyPath, propertyEditor);
312 }
313
314
315
316
317 @Override
318 public PropertyEditor findCustomEditor(Class<?> requiredType, String propertyPath) {
319 return wrapper.findCustomEditor(requiredType, propertyPath);
320 }
321
322
323
324
325 @Override
326 public <Y> Y convertIfNecessary(Object value, Class<Y> requiredType) throws TypeMismatchException {
327 return wrapper.convertIfNecessary(value, requiredType);
328 }
329
330
331
332
333 @Override
334 public <Y> Y convertIfNecessary(Object value, Class<Y> requiredType,
335 MethodParameter methodParam) throws TypeMismatchException {
336 return wrapper.convertIfNecessary(value, requiredType, methodParam);
337 }
338
339
340
341
342 @Override
343 public <Y> Y convertIfNecessary(Object value, Class<Y> requiredType, Field field) throws TypeMismatchException {
344 return wrapper.convertIfNecessary(value, requiredType, field);
345 }
346
347
348
349
350 @Override
351 public Map<String, Object> getPrimaryKeyValues() {
352 Map<String, Object> primaryKeyValues = new HashMap<String, Object>();
353 if (metadata != null) {
354 List<String> primaryKeyAttributeNames = metadata.getPrimaryKeyAttributeNames();
355 if (primaryKeyAttributeNames != null) {
356 for (String primaryKeyAttributeName : primaryKeyAttributeNames) {
357 primaryKeyValues.put(primaryKeyAttributeName, getPropertyValue(primaryKeyAttributeName));
358 }
359 }
360 } else {
361 LOG.warn("Attempt to retrieve PK fields on object with no metadata: " + dataObject.getClass().getName());
362 }
363 return primaryKeyValues;
364 }
365
366
367
368
369 @Override
370 public Object getPrimaryKeyValue() {
371 if (!areAllPrimaryKeyAttributesPopulated()) {
372 return null;
373 }
374 Map<String, Object> primaryKeyValues = getPrimaryKeyValues();
375 if (getPrimaryKeyValues().size() == 1) {
376 return primaryKeyValues.values().iterator().next();
377 } else {
378 return new CompoundKey(primaryKeyValues);
379 }
380 }
381
382
383
384
385 @Override
386 public boolean areAllPrimaryKeyAttributesPopulated() {
387 if (metadata != null) {
388 List<String> primaryKeyAttributeNames = metadata.getPrimaryKeyAttributeNames();
389 if (primaryKeyAttributeNames != null) {
390 for (String primaryKeyAttributeName : primaryKeyAttributeNames) {
391 Object propValue = getPropertyValue(primaryKeyAttributeName);
392 if (propValue == null || (propValue instanceof String && StringUtils.isBlank((String) propValue))) {
393 return false;
394 }
395 }
396 }
397 return true;
398 } else {
399 LOG.warn("Attempt to check areAllPrimaryKeyAttributesPopulated on object with no metadata: "
400 + dataObject.getClass().getName());
401 return true;
402 }
403 }
404
405
406
407
408 @Override
409 public boolean areAnyPrimaryKeyAttributesPopulated() {
410 if (metadata != null) {
411 List<String> primaryKeyAttributeNames = metadata.getPrimaryKeyAttributeNames();
412 if (primaryKeyAttributeNames != null) {
413 for (String primaryKeyAttributeName : primaryKeyAttributeNames) {
414 Object propValue = getPropertyValue(primaryKeyAttributeName);
415 if (propValue instanceof String && StringUtils.isNotBlank((String) propValue)) {
416 return true;
417 } else if (propValue != null) {
418 return true;
419 }
420 }
421 }
422 return false;
423 } else {
424 LOG.warn("Attempt to check areAnyPrimaryKeyAttributesPopulated on object with no metadata: "
425 + dataObject.getClass().getName());
426 return true;
427 }
428 }
429
430
431
432
433 @Override
434 public List<String> getUnpopulatedPrimaryKeyAttributeNames() {
435 List<String> emptyKeys = new ArrayList<String>();
436 if (metadata != null) {
437 List<String> primaryKeyAttributeNames = metadata.getPrimaryKeyAttributeNames();
438 if (primaryKeyAttributeNames != null) {
439 for (String primaryKeyAttributeName : primaryKeyAttributeNames) {
440 Object propValue = getPropertyValue(primaryKeyAttributeName);
441 if (propValue == null || (propValue instanceof String && StringUtils.isBlank((String) propValue))) {
442 emptyKeys.add(primaryKeyAttributeName);
443 }
444 }
445 }
446 } else {
447 LOG.warn("Attempt to check getUnpopulatedPrimaryKeyAttributeNames on object with no metadata: "
448 + dataObject.getClass().getName());
449 }
450 return emptyKeys;
451 }
452
453
454
455
456 @Override
457 public boolean equalsByPrimaryKey(T object) {
458 if (object == null) {
459 return false;
460 }
461 DataObjectWrapper<T> wrap = dataObjectService.wrap(object);
462 if (!getWrappedClass().isAssignableFrom(wrap.getWrappedClass())) {
463 throw new IllegalArgumentException("The type of the given data object does not match the type of this " +
464 "data object. Given: " + wrap.getWrappedClass() + ", but expected: " + getWrappedClass());
465 }
466
467 Map<String, Object> localPks = getPrimaryKeyValues();
468 Map<String, Object> givenPks = wrap.getPrimaryKeyValues();
469 for (String localPk : localPks.keySet()) {
470 Object localPkValue = localPks.get(localPk);
471 if (localPkValue == null || !localPkValue.equals(givenPks.get(localPk))) {
472 return false;
473 }
474 }
475 return true;
476 }
477
478
479
480
481 @Override
482 public Object getForeignKeyValue(String relationshipName) {
483 Object foreignKeyAttributeValue = getForeignKeyAttributeValue(relationshipName);
484 if (foreignKeyAttributeValue != null) {
485 return foreignKeyAttributeValue;
486 }
487
488
489 Object relationshipObject = getPropertyValue(relationshipName);
490 if (relationshipObject == null) {
491 return null;
492 }
493 return dataObjectService.wrap(relationshipObject).getPrimaryKeyValue();
494 }
495
496
497
498
499 @Override
500 public Object getForeignKeyAttributeValue(String relationshipName) {
501 Map<String, Object> attributeMap = getForeignKeyAttributeMap(relationshipName);
502 if (attributeMap == null) {
503 return null;
504 }
505 return asSingleKey(attributeMap);
506 }
507
508
509
510
511
512
513
514 public Map<String, Object> getForeignKeyAttributeMap(String relationshipName) {
515 MetadataChild relationship = findAndValidateRelationship(relationshipName);
516 List<DataObjectAttributeRelationship> attributeRelationships = relationship.getAttributeRelationships();
517
518 if (!attributeRelationships.isEmpty()) {
519 Map<String, Object> attributeMap = new LinkedHashMap<String, Object>();
520
521 for (DataObjectAttributeRelationship attributeRelationship : attributeRelationships) {
522
523 String parentAttributeName = attributeRelationship.getParentAttributeName();
524 Object parentAttributeValue = null;
525
526 try {
527 parentAttributeValue = getPropertyValue(parentAttributeName);
528 } catch (BeansException be) {
529
530
531 }
532
533
534 if (parentAttributeValue == null) {
535 return null;
536 }
537
538
539 String childAttributeName = attributeRelationship.getChildAttributeName();
540 attributeMap.put(childAttributeName, parentAttributeValue);
541 }
542
543 return attributeMap;
544 }
545
546 return null;
547 }
548
549
550
551
552
553
554
555
556 private Object asSingleKey(Map<String, Object> keyValues) {
557 if (keyValues.size() == 1) {
558 return keyValues.values().iterator().next();
559 }
560 return new CompoundKey(keyValues);
561 }
562
563
564
565
566 @Override
567 public Class<?> getPropertyTypeNullSafe(Class<?> objectType, String propertyName) {
568 DataObjectMetadata objectMetadata = dataObjectService.getMetadataRepository().getMetadata(objectType);
569 return getPropertyTypeChild(objectMetadata,propertyName);
570 }
571
572
573
574
575
576
577
578
579 private Class<?> getPropertyTypeChild(DataObjectMetadata objectMetadata, String propertyName){
580 if(PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName)){
581 String attributePrefix = StringUtils.substringBefore(propertyName,".");
582 String attributeName = StringUtils.substringAfter(propertyName,".");
583
584 if(StringUtils.isNotBlank(attributePrefix) && StringUtils.isNotBlank(attributeName) &&
585 objectMetadata!= null){
586 Class<?> propertyType = traverseRelationship(objectMetadata,attributePrefix,attributeName);
587 if(propertyType != null){
588 return propertyType;
589 }
590 }
591 }
592 return getPropertyType(propertyName);
593 }
594
595
596
597
598
599
600
601
602
603 private Class<?> traverseRelationship(DataObjectMetadata objectMetadata,String attributePrefix,
604 String attributeName){
605 DataObjectRelationship rd = objectMetadata.getRelationship(attributePrefix);
606 if(rd != null){
607 DataObjectMetadata relatedObjectMetadata =
608 dataObjectService.getMetadataRepository().getMetadata(rd.getRelatedType());
609 if(relatedObjectMetadata != null){
610 if(PropertyAccessorUtils.isNestedOrIndexedProperty(attributeName)){
611 return getPropertyTypeChild(relatedObjectMetadata,attributeName);
612 } else{
613 if(relatedObjectMetadata.getAttribute(attributeName) == null &&
614 relatedObjectMetadata.getRelationship(attributeName)!=null){
615 DataObjectRelationship relationship = relatedObjectMetadata.getRelationship(attributeName);
616 return relationship.getRelatedType();
617 }
618 return relatedObjectMetadata.getAttribute(attributeName).getDataType().getType();
619 }
620 }
621 }
622 return null;
623 }
624
625
626
627
628 @Override
629 public void linkChanges(Set<String> changedPropertyPaths) {
630 referenceLinker.linkChanges(getWrappedInstance(), changedPropertyPaths);
631 }
632
633
634
635
636 @Override
637 public void linkForeignKeys(boolean onlyLinkReadOnly) {
638 linkForeignKeysInternalWrapped(this, onlyLinkReadOnly, Sets.newHashSet());
639 }
640
641
642
643
644
645
646
647
648 protected void linkForeignKeysInternal(Object object, boolean onlyLinkReadOnly, Set<Object> linked) {
649 if (object == null || linked.contains(object) || !dataObjectService.supports(object.getClass())) {
650 return;
651 }
652 linked.add(object);
653 DataObjectWrapper<?> wrapped = dataObjectService.wrap(object);
654 linkForeignKeysInternalWrapped(wrapped, onlyLinkReadOnly, linked);
655 }
656
657
658
659
660
661
662
663
664 protected void linkForeignKeysInternalWrapped(DataObjectWrapper<?> wrapped, boolean onlyLinkReadOnly, Set<Object> linked) {
665 List<DataObjectRelationship> relationships = wrapped.getMetadata().getRelationships();
666 for (DataObjectRelationship relationship : relationships) {
667 String relationshipName = relationship.getName();
668 Object relationshipValue = wrapped.getPropertyValue(relationshipName);
669
670
671 if (relationship.isSavedWithParent()) {
672
673 linkForeignKeysInternal(relationshipValue, onlyLinkReadOnly, linked);
674 }
675
676
677 linkForeignKeysInternal(wrapped, relationship, relationshipValue, onlyLinkReadOnly);
678 }
679 List<DataObjectCollection> collections = wrapped.getMetadata().getCollections();
680 for (DataObjectCollection collection : collections) {
681 String relationshipName = collection.getName();
682
683
684 if (collection.isSavedWithParent()) {
685 Collection<?> collectionValue = (Collection<?>)wrapped.getPropertyValue(relationshipName);
686 if (collectionValue != null) {
687 for (Object object : collectionValue) {
688 linkForeignKeysInternal(object, onlyLinkReadOnly, linked);
689 }
690 }
691 }
692 }
693
694 }
695
696
697
698
699 @Override
700 public void fetchRelationship(String relationshipName) {
701 fetchRelationship(relationshipName, true, true);
702 }
703
704
705
706
707 @Override
708 public void fetchRelationship(String relationshipName, boolean useForeignKeyAttribute, boolean nullifyDanglingRelationship) {
709 fetchRelationship(findAndValidateRelationship(relationshipName), useForeignKeyAttribute,
710 nullifyDanglingRelationship);
711 }
712
713
714
715
716
717
718
719 protected void fetchRelationship(MetadataChild relationship, boolean useForeignKeyAttribute, boolean nullifyDanglingRelationship) {
720 Class<?> relatedType = relationship.getRelatedType();
721 if (!dataObjectService.supports(relatedType)) {
722 LOG.warn("Encountered a related type that is not supported by DataObjectService, fetch "
723 + "relationship will do nothing: " + relatedType);
724 return;
725 }
726
727 if (useForeignKeyAttribute) {
728 fetchRelationshipUsingAttributes(relationship, nullifyDanglingRelationship);
729 } else {
730 fetchRelationshipUsingIdentity(relationship, nullifyDanglingRelationship);
731 }
732 }
733
734
735
736
737
738
739
740 protected void fetchRelationshipUsingAttributes(MetadataChild relationship, boolean nullifyDanglingRelationship) {
741 Class<?> relatedType = relationship.getRelatedType();
742 if (relationship.getAttributeRelationships().isEmpty()) {
743 LOG.warn("Attempted to fetch a relationship using a foreign key attribute "
744 + "when one does not exist: "
745 + relationship.getName());
746 } else {
747 Object fetchedValue = null;
748 if (relationship instanceof DataObjectRelationship) {
749 Object foreignKey = getForeignKeyAttributeValue(relationship.getName());
750 if (foreignKey != null) {
751 fetchedValue = dataObjectService.find(relatedType, foreignKey);
752 }
753 } else if (relationship instanceof DataObjectCollection) {
754 Map<String, Object> foreignKeyAttributeMap = getForeignKeyAttributeMap(relationship.getName());
755 fetchedValue = dataObjectService.findMatching(relatedType,
756 QueryByCriteria.Builder.andAttributes(foreignKeyAttributeMap).build()).getResults();
757 }
758 if (fetchedValue != null || nullifyDanglingRelationship) {
759 setPropertyValue(relationship.getName(), fetchedValue);
760 }
761 }
762 }
763
764
765
766
767
768
769
770 protected void fetchRelationshipUsingIdentity(MetadataChild relationship, boolean nullifyDanglingRelationship) {
771 Object propertyValue = getPropertyValue(relationship.getName());
772 if (propertyValue != null) {
773 if (!dataObjectService.supports(propertyValue.getClass())) {
774 throw new IllegalArgumentException("Attempting to fetch an invalid relationship, must be a"
775 + "DataObjectRelationship when fetching without a foreign key");
776 }
777 DataObjectWrapper<?> wrappedRelationship = dataObjectService.wrap(propertyValue);
778 Map<String, Object> primaryKeyValues = wrappedRelationship.getPrimaryKeyValues();
779 Object newPropertyValue = dataObjectService.find(wrappedRelationship.getWrappedClass(),
780 new CompoundKey(primaryKeyValues));
781 if (newPropertyValue != null || nullifyDanglingRelationship) {
782 propertyValue = newPropertyValue;
783 setPropertyValue(relationship.getName(), propertyValue);
784 }
785 }
786
787
788
789 linkForeignKeysInternal(this, relationship, propertyValue, false);
790 populateInverseRelationship(relationship, propertyValue);
791 }
792
793
794
795
796 @Override
797 public void linkForeignKeys(String relationshipName, boolean onlyLinkReadOnly) {
798 MetadataChild relationship = findAndValidateRelationship(relationshipName);
799 Object propertyValue = getPropertyValue(relationshipName);
800 linkForeignKeysInternal(this, relationship, propertyValue, onlyLinkReadOnly);
801 }
802
803
804
805
806
807
808
809
810
811 protected void linkForeignKeysInternal(DataObjectWrapper<?> wrapped, MetadataChild relationship,
812 Object relationshipValue, boolean onlyLinkReadOnly) {
813 if (!relationship.getAttributeRelationships().isEmpty()) {
814
815 DataObjectWrapper<?> wrappedRelationship = null;
816 if (relationshipValue != null) {
817 wrappedRelationship = dataObjectService.wrap(relationshipValue);
818 }
819 for (DataObjectAttributeRelationship attributeRelationship : relationship.getAttributeRelationships()) {
820 String parentAttributeName = attributeRelationship.getParentAttributeName();
821
822
823 Object childAttributeValue = null;
824 if (wrappedRelationship != null) {
825 childAttributeValue =
826 wrappedRelationship.getPropertyValue(attributeRelationship.getChildAttributeName());
827 }
828 if (onlyLinkReadOnly) {
829 DataObjectAttribute attribute = wrapped.getMetadata().getAttribute(parentAttributeName);
830 if (attribute.isReadOnly()) {
831 wrapped.setPropertyValue(parentAttributeName, childAttributeValue);
832 }
833 } else {
834 wrapped.setPropertyValue(parentAttributeName, childAttributeValue);
835 }
836 }
837 }
838 }
839
840
841
842
843
844
845
846 protected void populateInverseRelationship(MetadataChild relationship, Object propertyValue) {
847 if (propertyValue != null) {
848 MetadataChild inverseRelationship = relationship.getInverseRelationship();
849 if (inverseRelationship != null) {
850 DataObjectWrapper<?> wrappedRelationship = dataObjectService.wrap(propertyValue);
851 if (inverseRelationship instanceof DataObjectCollection) {
852 DataObjectCollection collectionRelationship = (DataObjectCollection)inverseRelationship;
853 String colRelName = inverseRelationship.getName();
854 Collection<Object> collection =
855 (Collection<Object>)wrappedRelationship.getPropertyValue(colRelName);
856 if (collection == null) {
857
858 collection =
859 CollectionFactory.createCollection(wrappedRelationship.getPropertyType(colRelName), 1);
860 wrappedRelationship.setPropertyValue(colRelName, collection);
861 }
862 collection.add(getWrappedInstance());
863 }
864 }
865 }
866 }
867
868
869
870
871
872
873
874 private MetadataChild findAndValidateRelationship(String relationshipName) {
875 if (StringUtils.isBlank(relationshipName)) {
876 throw new IllegalArgumentException("The relationshipName must not be null or blank");
877 }
878
879 MetadataChild relationship = getMetadata().getRelationship(relationshipName);
880 if (relationship == null) {
881 relationship = getMetadata().getCollection(relationshipName);
882 if (relationship == null) {
883 throw new IllegalArgumentException("Failed to locate a valid relationship from " + getWrappedClass()
884 + " with the given relationship name '" + relationshipName + "'");
885 }
886 }
887 return relationship;
888 }
889
890 }