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