1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.data.metadata.impl;
17
18 import java.lang.reflect.Field;
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.kuali.rice.krad.data.metadata.DataObjectAttribute;
28 import org.kuali.rice.krad.data.metadata.DataObjectAttributeRelationship;
29 import org.kuali.rice.krad.data.metadata.DataObjectCollection;
30 import org.kuali.rice.krad.data.metadata.DataObjectRelationship;
31 import org.kuali.rice.krad.data.metadata.MetadataMergeAction;
32 import org.kuali.rice.krad.data.provider.annotation.UifAutoCreateViewType;
33
34 import com.google.common.annotations.Beta;
35
36
37
38
39
40
41
42
43
44
45 public class DataObjectMetadataImpl extends MetadataCommonBase implements DataObjectMetadataInternal {
46 private static final long serialVersionUID = 7722982931510558892L;
47
48 protected DataObjectMetadataInternal embedded;
49
50
51
52
53
54 protected String providerName;
55
56 protected Class<?> type;
57
58 protected List<DataObjectAttribute> attributes;
59 protected Map<String, DataObjectAttribute> attributeMap;
60 protected List<String> removedAttributeNames;
61 protected List<String> orderedAttributeList = new ArrayList<String>();
62
63 protected List<DataObjectCollection> collections;
64 protected Map<String, DataObjectCollection> collectionMap;
65 protected List<String> removedCollectionNames;
66
67 protected List<DataObjectRelationship> relationships;
68 protected Map<String, DataObjectRelationship> relationshipMap;
69 protected List<String> removedRelationshipNames;
70
71 protected Map<String, List<DataObjectRelationship>> attributeToRelationshipMap;
72 protected Map<String, DataObjectRelationship> lastAttributeToRelationshipMap;
73
74 protected List<String> primaryKeyAttributeNames;
75 protected List<String> businessKeyAttributeNames;
76 protected String primaryDisplayAttributeName;
77 protected boolean primaryDisplayAttributeSetManually;
78
79 protected Boolean supportsOptimisticLocking;
80
81 protected Collection<UifAutoCreateViewType> autoCreateUifViewTypes;
82
83 public DataObjectMetadataImpl() {
84 }
85
86
87
88
89 @Override
90 public Object getUniqueKeyForMerging() {
91 return type;
92 }
93
94
95
96
97 @Override
98 public Class<?> getType() {
99 return type;
100 }
101
102
103
104
105
106
107 public void setType(Class<?> type) {
108 if (type == null) {
109 throw new IllegalArgumentException("The data object type may not be set to null.");
110 }
111 this.type = type;
112 }
113
114
115
116
117
118
119 public String getTypeClassName() {
120 if (type == null) {
121 return null;
122 }
123 return type.getName();
124 }
125
126
127
128
129
130
131 public void setTypeClassName(String typeClassName) {
132 try {
133 setType(Class.forName(typeClassName));
134 } catch (ClassNotFoundException e) {
135 throw new IllegalArgumentException("ClassNotFoundException when setting data object type class name "
136 + typeClassName, e);
137 }
138 }
139
140
141
142
143 @Override
144 public List<String> getPrimaryKeyAttributeNames() {
145 if (primaryKeyAttributeNames != null) {
146 return primaryKeyAttributeNames;
147 }
148
149 if (embedded != null) {
150 return embedded.getPrimaryKeyAttributeNames();
151 }
152
153 return Collections.emptyList();
154 }
155
156
157
158
159
160
161 public void setPrimaryKeyAttributeNames(List<String> primaryKeyAttributeNames) {
162 if (primaryKeyAttributeNames == null) {
163 primaryKeyAttributeNames = Collections.emptyList();
164 }
165
166 this.primaryKeyAttributeNames = Collections.unmodifiableList( primaryKeyAttributeNames );
167 }
168
169
170
171
172 @Override
173 public List<String> getBusinessKeyAttributeNames() {
174
175 if (businessKeyAttributeNames != null) {
176 return businessKeyAttributeNames;
177 }
178
179
180 if (primaryKeyAttributeNames != null) {
181 return primaryKeyAttributeNames;
182 }
183
184
185 if (embedded != null) {
186 return embedded.getBusinessKeyAttributeNames();
187 }
188
189 return Collections.emptyList();
190 }
191
192
193
194
195
196
197 public void setBusinessKeyAttributeNames(List<String> businessKeyAttributeNames) {
198 if (businessKeyAttributeNames == null) {
199 businessKeyAttributeNames = Collections.emptyList();
200 }
201
202 this.businessKeyAttributeNames = Collections.unmodifiableList(businessKeyAttributeNames);
203 }
204
205
206
207
208 @Override
209 public Boolean hasDistinctBusinessKey() {
210 return !getPrimaryKeyAttributeNames().equals(getBusinessKeyAttributeNames());
211 }
212
213
214
215
216 @Override
217 public String getPrimaryDisplayAttributeName() {
218 if (primaryDisplayAttributeName == null && !getBusinessKeyAttributeNames().isEmpty()) {
219 primaryDisplayAttributeName = getBusinessKeyAttributeNames().get(getBusinessKeyAttributeNames().size() - 1);
220 }
221
222 return primaryDisplayAttributeName;
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241 }
242
243
244
245
246
247
248 public void setPrimaryDisplayAttributeName(String primaryDisplayAttributeName) {
249 if (StringUtils.isBlank(primaryDisplayAttributeName)) {
250 this.primaryDisplayAttributeName = null;
251 this.primaryDisplayAttributeSetManually = false;
252 } else {
253 this.primaryDisplayAttributeName = primaryDisplayAttributeName;
254 this.primaryDisplayAttributeSetManually = true;
255 }
256 }
257
258
259
260
261
262
263
264
265
266
267
268
269 public List<DataObjectAttribute> orderAttributesByDefinedOrder(List<DataObjectAttribute> attributes) {
270 List<DataObjectAttribute> sorted = new ArrayList<DataObjectAttribute>(attributes.size());
271 Map<String, DataObjectAttribute> keyedAttributes = new HashMap<String, DataObjectAttribute>(attributes.size());
272 Map<String, List<DataObjectAttribute>> inheritedAttributes = new HashMap<String, List<DataObjectAttribute>>();
273
274 for (DataObjectAttribute attr : attributes) {
275 if (attr.isInherited()) {
276 List<DataObjectAttribute> inheritedByProperty = inheritedAttributes.get(attr
277 .getInheritedFromParentAttributeName());
278
279 if (inheritedByProperty == null) {
280 inheritedByProperty = new ArrayList<DataObjectAttribute>();
281 inheritedAttributes.put(attr.getInheritedFromParentAttributeName(), inheritedByProperty);
282 }
283
284 inheritedByProperty.add(attr);
285 } else {
286 keyedAttributes.put(attr.getName(), attr);
287 }
288 }
289
290 for (Field f : getType().getDeclaredFields()) {
291 DataObjectAttribute attr = keyedAttributes.get(f.getName());
292
293 if (attr != null) {
294 sorted.add(attr);
295 keyedAttributes.remove(f.getName());
296 }
297
298 if (inheritedAttributes.containsKey(f.getName())) {
299 sorted.addAll(inheritedAttributes.get(f.getName()));
300 }
301 }
302 sorted.addAll(keyedAttributes.values());
303 return sorted;
304 }
305
306 List<DataObjectAttribute> mergedAttributes = null;
307
308
309
310
311 @Override
312 public List<DataObjectAttribute> getAttributes() {
313
314 if (attributes != null && embedded == null) {
315 return orderAttributesByDefinedOrder(attributes);
316 }
317
318 if (embedded != null) {
319 return orderAttributesByDefinedOrder(mergeLists(embedded.getAttributes(), attributes));
320 }
321
322 return Collections.emptyList();
323 }
324
325
326
327
328
329
330
331
332
333
334 public void setAttributes(List<DataObjectAttribute> attributes) {
335 if (attributes == null) {
336 attributes = Collections.emptyList();
337 }
338
339 this.attributes = Collections.unmodifiableList(attributes);
340 mergedAttributes = null;
341 attributeMap = new HashMap<String, DataObjectAttribute>(attributes.size());
342 removedAttributeNames = new ArrayList<String>();
343 for (DataObjectAttribute attr : attributes) {
344
345
346
347 if (attr.getMergeAction() != MetadataMergeAction.REMOVE
348 && attr.getMergeAction() != MetadataMergeAction.NO_OVERRIDE) {
349 attributeMap.put(attr.getName(), attr);
350 }
351
352
353
354 if (attr.getMergeAction() == MetadataMergeAction.REMOVE) {
355 removedAttributeNames.add(attr.getName());
356 }
357 }
358 }
359
360
361
362
363 @Override
364 public List<DataObjectCollection> getCollections() {
365
366 if (collections != null && embedded == null) {
367 return collections;
368 }
369
370 if (embedded != null) {
371 return mergeLists(embedded.getCollections(), collections);
372 }
373
374 return Collections.emptyList();
375 }
376
377
378
379
380
381
382
383
384
385
386 public void setCollections(List<DataObjectCollection> collections) {
387 if (collections == null) {
388 this.collections = null;
389 return;
390 }
391
392 this.collections = Collections.unmodifiableList(collections);
393 collectionMap = new HashMap<String, DataObjectCollection>(collections.size());
394 removedCollectionNames = new ArrayList<String>();
395 for (DataObjectCollection coll : collections) {
396
397
398
399 if (coll.getMergeAction() != MetadataMergeAction.REMOVE
400 && coll.getMergeAction() != MetadataMergeAction.NO_OVERRIDE) {
401 collectionMap.put(coll.getName(), coll);
402 }
403
404
405
406 if (coll.getMergeAction() == MetadataMergeAction.REMOVE) {
407 removedCollectionNames.add(coll.getName());
408 }
409 }
410 }
411
412
413
414
415 @Override
416 public List<DataObjectRelationship> getRelationships() {
417
418 if (relationships != null && embedded == null) {
419 return relationships;
420 }
421
422 if (embedded != null) {
423 return mergeLists(embedded.getRelationships(), relationships);
424 }
425
426 return Collections.emptyList();
427 }
428
429
430
431
432
433
434
435
436
437
438 public void setRelationships(List<DataObjectRelationship> relationships) {
439 if (relationships == null) {
440 this.relationships = null;
441 relationshipMap = null;
442 lastAttributeToRelationshipMap = null;
443 attributeToRelationshipMap = null;
444 return;
445 }
446
447 this.relationships = Collections.unmodifiableList(relationships);
448 relationshipMap = new HashMap<String, DataObjectRelationship>(relationships.size());
449 attributeToRelationshipMap = new HashMap<String, List<DataObjectRelationship>>();
450 lastAttributeToRelationshipMap = new HashMap<String, DataObjectRelationship>(relationships.size());
451 removedRelationshipNames = new ArrayList<String>();
452
453
454 for (DataObjectRelationship rel : relationships) {
455
456
457
458 if (rel.getMergeAction() != MetadataMergeAction.REMOVE
459 && rel.getMergeAction() != MetadataMergeAction.NO_OVERRIDE) {
460
461 relationshipMap.put(rel.getName(), rel);
462
463
464 if (!rel.getAttributeRelationships().isEmpty()) {
465 DataObjectAttributeRelationship relAttr = rel.getAttributeRelationships().get(
466 rel.getAttributeRelationships().size() - 1);
467 lastAttributeToRelationshipMap.put(relAttr.getParentAttributeName(), rel);
468 }
469
470
471 for (DataObjectAttributeRelationship relAttr : rel.getAttributeRelationships()) {
472 List<DataObjectRelationship> rels = attributeToRelationshipMap
473 .get(relAttr.getParentAttributeName());
474 if (rels == null) {
475 rels = new ArrayList<DataObjectRelationship>();
476 attributeToRelationshipMap.put(relAttr.getParentAttributeName(), rels);
477 }
478 rels.add(rel);
479 }
480 }
481
482
483
484 if (rel.getMergeAction() == MetadataMergeAction.REMOVE) {
485 removedRelationshipNames.add(rel.getName());
486 }
487 }
488 relationshipMap = Collections.unmodifiableMap(relationshipMap);
489 lastAttributeToRelationshipMap = Collections.unmodifiableMap(lastAttributeToRelationshipMap);
490 attributeToRelationshipMap = Collections.unmodifiableMap(attributeToRelationshipMap);
491 }
492
493
494
495
496 @Override
497 public DataObjectAttribute getAttribute(String attributeName) {
498 if (attributeName == null) {
499 return null;
500 }
501
502 DataObjectAttribute attribute = null;
503
504
505 if (attributes != null) {
506 attribute = attributeMap.get(attributeName);
507 }
508
509
510 if (attribute == null && embedded != null) {
511 attribute = embedded.getAttribute(attributeName);
512
513 if (attribute != null && removedAttributeNames != null
514 && removedAttributeNames.contains(attribute.getName())) {
515 attribute = null;
516 }
517 }
518
519 return attribute;
520 }
521
522
523
524
525 @Override
526 public DataObjectCollection getCollection(String collectionName) {
527 if (collectionName == null) {
528 return null;
529 }
530
531 DataObjectCollection collection = null;
532
533
534 if (collections != null) {
535 collection = collectionMap.get(collectionName);
536 }
537
538
539 if (collection == null && embedded != null) {
540 collection = embedded.getCollection(collectionName);
541
542 if (collection != null && removedCollectionNames != null
543 && removedCollectionNames.contains(collection.getName())) {
544 collection = null;
545 }
546 }
547
548 return collection;
549 }
550
551
552
553
554 @Override
555 public DataObjectRelationship getRelationship(String relationshipName) {
556 if (relationshipName == null) {
557 return null;
558 }
559
560 DataObjectRelationship relationship = null;
561
562
563 if (relationships != null) {
564 relationship = relationshipMap.get(relationshipName);
565 }
566
567
568 if (relationship == null && embedded != null) {
569 relationship = embedded.getRelationship(relationshipName);
570
571 if (relationship != null && removedRelationshipNames != null
572 && removedRelationshipNames.contains(relationship.getName())) {
573 relationship = null;
574 }
575 }
576
577 return relationship;
578 }
579
580
581
582
583 @Override
584 public List<DataObjectRelationship> getRelationshipsInvolvingAttribute(String attributeName) {
585
586 if (StringUtils.isBlank(attributeName)) {
587 return null;
588 }
589
590 Map<Object, DataObjectRelationship> relationships = new HashMap<Object, DataObjectRelationship>();
591
592 if (attributeToRelationshipMap != null && attributeToRelationshipMap.containsKey(attributeName)) {
593 for (DataObjectRelationship rel : attributeToRelationshipMap.get(attributeName)) {
594 Object mergeKey = rel.getName();
595
596 if (rel instanceof MetadataCommonInternal) {
597 mergeKey = ((MetadataCommonInternal) rel).getUniqueKeyForMerging();
598 }
599
600 relationships.put(mergeKey, rel);
601 }
602 }
603
604
605
606 if (embedded != null) {
607 for (DataObjectRelationship rel : embedded.getRelationshipsInvolvingAttribute(attributeName)) {
608 Object mergeKey = rel.getName();
609
610 if (rel instanceof MetadataCommonInternal) {
611 mergeKey = ((MetadataCommonInternal) rel).getUniqueKeyForMerging();
612 }
613
614 if (!relationships.containsKey(mergeKey)) {
615 relationships.put(mergeKey, rel);
616 }
617 }
618 }
619
620 return new ArrayList<DataObjectRelationship>(relationships.values());
621 }
622
623
624
625
626 @Override
627 public DataObjectRelationship getRelationshipByLastAttributeInRelationship(String attributeName) {
628
629 if (StringUtils.isBlank(attributeName)) {
630 return null;
631 }
632
633 DataObjectRelationship relationship = null;
634
635
636 if (lastAttributeToRelationshipMap != null) {
637 relationship = lastAttributeToRelationshipMap.get(attributeName);
638 }
639
640
641 if (relationship == null && embedded != null) {
642 relationship = embedded.getRelationshipByLastAttributeInRelationship(attributeName);
643 }
644
645 return relationship;
646 }
647
648
649
650
651 @Override
652 public DataObjectMetadataInternal getEmbedded() {
653 return embedded;
654 }
655
656
657
658
659 @Override
660 public void setEmbedded(DataObjectMetadataInternal embedded) {
661 this.embedded = embedded;
662 setEmbeddedCommonMetadata(embedded);
663 }
664
665
666
667
668
669
670
671
672
673
674
675 public String getProviderName() {
676 return providerName;
677 }
678
679
680
681
682
683
684 public void setProviderName(String providerName) {
685 this.providerName = providerName;
686 }
687
688
689
690
691 @Override
692 public String toString() {
693 StringBuilder builder = new StringBuilder();
694 builder.append("DataObjectMetadata [");
695 builder.append("type=").append(getType()).append(", ");
696 builder.append("typeLabel=").append(label).append(", ");
697 builder.append("backingObjectName=").append(backingObjectName);
698 if (attributes != null && !attributes.isEmpty()) {
699 builder.append(", ").append("attributes=").append(attributes);
700 }
701 if (primaryKeyAttributeNames != null && !primaryKeyAttributeNames.isEmpty()) {
702 builder.append(", ").append("primaryKeyAttributeNames=").append(primaryKeyAttributeNames);
703 }
704 if (getPrimaryDisplayAttributeName() != null) {
705 builder.append(", ").append("primaryDisplayAttributeName=").append(getPrimaryDisplayAttributeName());
706 }
707 if (businessKeyAttributeNames != null && !businessKeyAttributeNames.isEmpty()) {
708 builder.append(", ").append("businessKeyAttributeNames=").append(businessKeyAttributeNames);
709 }
710 if (collections != null && !collections.isEmpty()) {
711 builder.append(", ").append("collections=").append(collections);
712 }
713 if (relationships != null && !relationships.isEmpty()) {
714 builder.append(", ").append("relationships=").append(relationships);
715 }
716 if (providerName != null) {
717 builder.append(", ").append("providerName=").append(providerName);
718 }
719 if (embedded != null) {
720 builder.append(", ").append("mergeAction=").append(mergeAction);
721 builder.append(", ").append("embedded=").append(embedded);
722 }
723 builder.append("]");
724 return builder.toString();
725 }
726
727
728
729
730 @Override
731 public boolean isSupportsOptimisticLocking() {
732 if (supportsOptimisticLocking != null) {
733 return supportsOptimisticLocking;
734 }
735
736 if (embedded != null) {
737 return embedded.isSupportsOptimisticLocking();
738 }
739
740 return false;
741 }
742
743
744
745
746
747
748 public void setSupportsOptimisticLocking(boolean supportsOptimisticLocking) {
749 this.supportsOptimisticLocking = supportsOptimisticLocking;
750 }
751
752
753
754
755 @Override
756 @Beta
757 public boolean shouldAutoCreateUifViewOfType(UifAutoCreateViewType viewType) {
758 if (getAutoCreateUifViewTypes() == null) {
759 return false;
760 }
761
762 return getAutoCreateUifViewTypes().contains(viewType)
763 || getAutoCreateUifViewTypes().contains(UifAutoCreateViewType.ALL);
764 }
765
766
767
768
769 @Override
770 @Beta
771 public Collection<UifAutoCreateViewType> getAutoCreateUifViewTypes() {
772 if (autoCreateUifViewTypes != null) {
773 return autoCreateUifViewTypes;
774 }
775
776 if (embedded != null) {
777 return embedded.getAutoCreateUifViewTypes();
778 }
779
780 return null;
781 }
782
783
784
785
786
787
788 @Beta
789 public void setAutoCreateUifViewTypes(Collection<UifAutoCreateViewType> autoCreateUifViewTypes) {
790 this.autoCreateUifViewTypes = autoCreateUifViewTypes;
791 }
792
793
794
795
796
797
798 public List<String> getOrderedAttributeList() {
799 return orderedAttributeList;
800 }
801
802
803
804
805
806
807 public void setOrderedAttributeList(List<String> orderedAttributeList) {
808 this.orderedAttributeList = orderedAttributeList;
809 }
810
811 }