1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.data.provider.annotation.impl;
17
18 import java.lang.annotation.Annotation;
19 import java.lang.reflect.Field;
20 import java.lang.reflect.Method;
21 import java.lang.reflect.ParameterizedType;
22 import java.lang.reflect.Type;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.HashSet;
28 import java.util.List;
29
30 import javax.validation.constraints.NotNull;
31 import javax.validation.constraints.Size;
32
33 import org.apache.commons.lang.StringUtils;
34 import org.kuali.rice.core.api.data.DataType;
35 import org.kuali.rice.krad.data.DataObjectService;
36 import org.kuali.rice.krad.data.KradDataServiceLocator;
37 import org.kuali.rice.krad.data.metadata.DataObjectAttribute;
38 import org.kuali.rice.krad.data.metadata.DataObjectAttributeRelationship;
39 import org.kuali.rice.krad.data.metadata.DataObjectCollection;
40 import org.kuali.rice.krad.data.metadata.DataObjectCollectionSortAttribute;
41 import org.kuali.rice.krad.data.metadata.DataObjectMetadata;
42 import org.kuali.rice.krad.data.metadata.DataObjectRelationship;
43 import org.kuali.rice.krad.data.metadata.MetadataConfigurationException;
44 import org.kuali.rice.krad.data.metadata.MetadataMergeAction;
45 import org.kuali.rice.krad.data.metadata.MetadataRepository;
46 import org.kuali.rice.krad.data.metadata.impl.DataObjectAttributeImpl;
47 import org.kuali.rice.krad.data.metadata.impl.DataObjectAttributeRelationshipImpl;
48 import org.kuali.rice.krad.data.metadata.impl.DataObjectCollectionImpl;
49 import org.kuali.rice.krad.data.metadata.impl.DataObjectCollectionSortAttributeImpl;
50 import org.kuali.rice.krad.data.metadata.impl.DataObjectMetadataImpl;
51 import org.kuali.rice.krad.data.metadata.impl.DataObjectRelationshipImpl;
52 import org.kuali.rice.krad.data.metadata.impl.MetadataCommonBase;
53 import org.kuali.rice.krad.data.provider.annotation.AttributeRelationship;
54 import org.kuali.rice.krad.data.provider.annotation.BusinessKey;
55 import org.kuali.rice.krad.data.provider.annotation.CollectionRelationship;
56 import org.kuali.rice.krad.data.provider.annotation.CollectionSortAttribute;
57 import org.kuali.rice.krad.data.provider.annotation.Description;
58 import org.kuali.rice.krad.data.provider.annotation.ForceUppercase;
59 import org.kuali.rice.krad.data.provider.annotation.InheritProperties;
60 import org.kuali.rice.krad.data.provider.annotation.InheritProperty;
61 import org.kuali.rice.krad.data.provider.annotation.KeyValuesFinderClass;
62 import org.kuali.rice.krad.data.provider.annotation.Label;
63 import org.kuali.rice.krad.data.provider.annotation.MergeAction;
64 import org.kuali.rice.krad.data.provider.annotation.NonPersistentProperty;
65 import org.kuali.rice.krad.data.provider.annotation.PropertyEditorClass;
66 import org.kuali.rice.krad.data.provider.annotation.ReadOnly;
67 import org.kuali.rice.krad.data.provider.annotation.Relationship;
68 import org.kuali.rice.krad.data.provider.annotation.Sensitive;
69 import org.kuali.rice.krad.data.provider.annotation.ShortLabel;
70 import org.kuali.rice.krad.data.provider.annotation.UifAutoCreateViews;
71 import org.kuali.rice.krad.data.provider.annotation.UifDisplayHint;
72 import org.kuali.rice.krad.data.provider.annotation.UifDisplayHints;
73 import org.kuali.rice.krad.data.provider.annotation.UifValidCharactersConstraintBeanName;
74 import org.kuali.rice.krad.data.provider.impl.MetadataProviderBase;
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 public class AnnotationMetadataProviderImpl extends MetadataProviderBase {
91 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
92 .getLogger(AnnotationMetadataProviderImpl.class);
93
94 private boolean initializationAttempted = false;
95 private DataObjectService dataObjectService;
96
97
98
99
100 @Override
101 protected void initializeMetadata(Collection<Class<?>> types) {
102 if (initializationAttempted) {
103 return;
104 }
105 initializationAttempted = true;
106 if (LOG.isDebugEnabled()) {
107 LOG.debug("Processing annotations for the given list of data objects: " + types);
108 }
109 if (types == null || types.isEmpty()) {
110 LOG.warn(getClass().getSimpleName() + " was passed an empty list of types to initialize, doing nothing");
111 return;
112 }
113 LOG.info("Started Scanning For Metadata Annotations");
114 for (Class<?> type : types) {
115 if (LOG.isDebugEnabled()) {
116 LOG.debug("Processing Annotations on : " + type);
117 }
118 boolean annotationsFound = false;
119 DataObjectMetadataImpl metadata = new DataObjectMetadataImpl();
120 metadata.setProviderName(this.getClass().getSimpleName());
121 metadata.setType(type);
122
123 annotationsFound |= processClassLevelAnnotations(type, metadata);
124
125 annotationsFound |= processFieldLevelAnnotations(type, metadata);
126
127 annotationsFound |= processMethodLevelAnnotations(type, metadata);
128
129 annotationsFound |= processInheritedAttributes(type, metadata);
130 if (annotationsFound) {
131 masterMetadataMap.put(type, metadata);
132 }
133 }
134 LOG.info("Completed Scanning For Metadata Annotations");
135 if (LOG.isDebugEnabled()) {
136 LOG.debug("Annotation Metadata: " + masterMetadataMap);
137 }
138 }
139
140
141
142
143
144
145
146
147 protected boolean processClassLevelAnnotations(Class<?> clazz, DataObjectMetadataImpl metadata) {
148 boolean classAnnotationFound = false;
149 boolean fieldAnnotationsFound = false;
150
151 List<DataObjectAttribute> attributes = new ArrayList<DataObjectAttribute>(metadata.getAttributes());
152 Annotation[] classAnnotations = clazz.getAnnotations();
153 if (LOG.isDebugEnabled()) {
154 LOG.debug("Class-level annotations: " + Arrays.asList(classAnnotations));
155 }
156 for (Annotation a : classAnnotations) {
157
158
159 if (processAnnotationsforCommonMetadata(a, metadata)) {
160 classAnnotationFound = true;
161 continue;
162 }
163 if (a instanceof MergeAction) {
164 MetadataMergeAction mma = ((MergeAction) a).value();
165 if (!(mma == MetadataMergeAction.MERGE || mma == MetadataMergeAction.REMOVE)) {
166 throw new MetadataConfigurationException(
167 "Only the MERGE and REMOVE merge actions are supported since the annotation metadata provider can not specify all required properties and may only be used as an overlay.");
168 }
169 metadata.setMergeAction(mma);
170 classAnnotationFound = true;
171 continue;
172 }
173 if (a instanceof UifAutoCreateViews) {
174 metadata.setAutoCreateUifViewTypes(Arrays.asList(((UifAutoCreateViews) a).value()));
175 classAnnotationFound = true;
176 }
177 }
178 if (fieldAnnotationsFound) {
179 metadata.setAttributes(attributes);
180 }
181 return classAnnotationFound;
182 }
183
184
185
186
187
188
189
190
191 protected boolean processFieldLevelAnnotations(Class<?> clazz, DataObjectMetadataImpl metadata) {
192 boolean fieldAnnotationsFound = false;
193 boolean additionalClassAnnotationsFound = false;
194 List<DataObjectAttribute> attributes = new ArrayList<DataObjectAttribute>();
195 for (Field f : clazz.getDeclaredFields()) {
196 boolean fieldAnnotationFound = false;
197 String propertyName = f.getName();
198 DataObjectAttributeImpl attr = (DataObjectAttributeImpl) metadata.getAttribute(propertyName);
199 boolean existingAttribute = attr != null;
200 if (!existingAttribute) {
201 attr = new DataObjectAttributeImpl();
202 attr.setName(propertyName);
203 attr.setType(f.getType());
204 DataType dataType = DataType.getDataTypeFromClass(f.getType());
205 if (dataType == null) {
206 dataType = DataType.STRING;
207 }
208 attr.setDataType(dataType);
209 attr.setOwningType(metadata.getType());
210 }
211 Annotation[] fieldAnnotations = f.getDeclaredAnnotations();
212 if (LOG.isDebugEnabled()) {
213 LOG.debug(f.getDeclaringClass() + "." + f.getName() + " Field-level annotations: "
214 + Arrays.asList(fieldAnnotations));
215 }
216 for (Annotation a : fieldAnnotations) {
217
218 fieldAnnotationFound |= processAnnotationForAttribute(a, attr, metadata);
219 if (!fieldAnnotationFound) {
220 if (a instanceof BusinessKey) {
221 ArrayList<String> businessKeys = new ArrayList<String>(metadata.getBusinessKeyAttributeNames());
222 businessKeys.add(f.getName());
223 metadata.setBusinessKeyAttributeNames(businessKeys);
224
225
226 additionalClassAnnotationsFound = true;
227 continue;
228 }
229 if (a instanceof Relationship) {
230 addDataObjectRelationship(metadata, f, (Relationship) a);
231
232 additionalClassAnnotationsFound = true;
233 continue;
234 }
235 if (a instanceof CollectionRelationship) {
236 addDataObjectCollection(metadata, f, (CollectionRelationship) a);
237
238 additionalClassAnnotationsFound = true;
239 continue;
240 }
241 }
242 }
243 if (fieldAnnotationFound) {
244 attributes.add(attr);
245 fieldAnnotationsFound = true;
246 }
247 }
248 if (fieldAnnotationsFound) {
249 metadata.setAttributes(attributes);
250 }
251 return fieldAnnotationsFound || additionalClassAnnotationsFound;
252 }
253
254
255
256
257
258
259
260
261 protected boolean processAnnotationsforCommonMetadata(Annotation a, MetadataCommonBase metadata) {
262 if (a instanceof Label) {
263 if (StringUtils.isNotBlank(((Label) a).value())) {
264 metadata.setLabel(((Label) a).value());
265 return true;
266 }
267 }
268 if (a instanceof ShortLabel) {
269 metadata.setShortLabel(((ShortLabel) a).value());
270 return true;
271 }
272 if (a instanceof Description) {
273 metadata.setDescription(((Description) a).value());
274 return true;
275 }
276 return false;
277 }
278
279
280
281
282
283
284
285
286
287
288
289
290 protected boolean processAnnotationForAttribute(Annotation a, DataObjectAttributeImpl attr,
291 DataObjectMetadataImpl metadata) {
292 if (a == null) {
293 return false;
294 }
295 if (a instanceof NonPersistentProperty) {
296 attr.setPersisted(false);
297 return true;
298 }
299 if (processAnnotationsforCommonMetadata(a, attr)) {
300 return true;
301 }
302 if (a instanceof ReadOnly) {
303 attr.setReadOnly(true);
304 return true;
305 }
306 if (a instanceof UifValidCharactersConstraintBeanName) {
307 attr.setValidCharactersConstraintBeanName(((UifValidCharactersConstraintBeanName) a).value());
308 return true;
309 }
310 if (a instanceof KeyValuesFinderClass) {
311 try {
312 attr.setValidValues(((KeyValuesFinderClass) a).value().newInstance());
313 return true;
314 } catch (Exception ex) {
315 LOG.error("Unable to instantiate options finder: " + ((KeyValuesFinderClass) a).value(), ex);
316 }
317 }
318 if (a instanceof NotNull) {
319 attr.setRequired(true);
320 return true;
321 }
322 if (a instanceof ForceUppercase) {
323 attr.setForceUppercase(true);
324 return true;
325 }
326 if (a instanceof PropertyEditorClass) {
327 try {
328 attr.setPropertyEditor(((PropertyEditorClass) a).value().newInstance());
329 return true;
330 } catch (Exception ex) {
331 LOG.warn("Unable to instantiate property editor class for " + metadata.getTypeClassName()
332 + "." + attr.getName() + " : " + ((PropertyEditorClass) a).value());
333 }
334 }
335 if (a instanceof Size) {
336
337
338 if (((Size) a).max() != Integer.MAX_VALUE) {
339 attr.setMaxLength((long) ((Size) a).max());
340 return true;
341 }
342 }
343 if (a instanceof Sensitive) {
344 attr.setSensitive(true);
345 return true;
346 }
347 if (a instanceof UifDisplayHints) {
348 attr.setDisplayHints(new HashSet<UifDisplayHint>(Arrays.asList(((UifDisplayHints) a).value())));
349 return true;
350 }
351 if (a instanceof MergeAction) {
352 MetadataMergeAction mma = ((MergeAction) a).value();
353 if (!(mma == MetadataMergeAction.MERGE || mma == MetadataMergeAction.REMOVE)) {
354 throw new MetadataConfigurationException(
355 "Only the MERGE and REMOVE merge actions are supported since the annotation metadata provider can not specify all required properties and may only be used as an overlay.");
356 }
357 attr.setMergeAction(mma);
358 return true;
359 }
360 return false;
361 }
362
363
364
365
366
367
368
369
370
371 protected String getPropertyNameFromGetterMethod(Method m) {
372 String propertyName = "";
373 if (m.getName().startsWith("get")) {
374 propertyName = StringUtils.uncapitalize(StringUtils.removeStart(m.getName(), "get"));
375 } else {
376 propertyName = StringUtils.uncapitalize(StringUtils.removeStart(m.getName(), "is"));
377 }
378 return propertyName;
379 }
380
381
382
383
384
385
386
387
388
389 protected boolean processMethodLevelAnnotations(Class<?> clazz, DataObjectMetadataImpl metadata) {
390 boolean fieldAnnotationsFound = false;
391 if (LOG.isDebugEnabled()) {
392 LOG.debug("Processing Method Annotations on " + clazz);
393 }
394 List<DataObjectAttribute> attributes = new ArrayList<DataObjectAttribute>(metadata.getAttributes());
395 for (Method m : clazz.getDeclaredMethods()) {
396
397
398
399 if (!m.isAnnotationPresent(NonPersistentProperty.class)) {
400 if (LOG.isTraceEnabled()) {
401 LOG.trace("Rejecting method " + m.getName()
402 + " because does not have NonPersistentProperty annotation");
403 }
404 continue;
405 }
406
407 if (!m.getName().startsWith("get") && !m.getName().startsWith("is")) {
408 if (LOG.isDebugEnabled()) {
409 LOG.debug("Rejecting method " + m.getName() + " because name does not match getter pattern");
410 }
411 continue;
412 }
413
414 if (m.getReturnType() == null || m.getParameterTypes().length > 0) {
415 if (LOG.isDebugEnabled()) {
416 LOG.debug("Rejecting method " + m.getName() + " because has no return type or has arguments");
417 }
418 continue;
419 }
420 String propertyName = getPropertyNameFromGetterMethod(m);
421 boolean fieldAnnotationFound = false;
422 boolean existingAttribute = true;
423 DataObjectAttributeImpl attr = (DataObjectAttributeImpl) metadata.getAttribute(propertyName);
424 if (attr == null) {
425 existingAttribute = false;
426 attr = new DataObjectAttributeImpl();
427 attr.setName(propertyName);
428 attr.setType(m.getReturnType());
429 DataType dataType = DataType.getDataTypeFromClass(m.getReturnType());
430 if (dataType == null) {
431 dataType = DataType.STRING;
432 }
433 attr.setDataType(dataType);
434 attr.setOwningType(metadata.getType());
435 }
436 Annotation[] methodAnnotations = m.getDeclaredAnnotations();
437 if (LOG.isDebugEnabled()) {
438 LOG.debug(m.getDeclaringClass() + "." + m.getName() + " Method-level annotations: "
439 + Arrays.asList(methodAnnotations));
440 }
441 for (Annotation a : methodAnnotations) {
442 fieldAnnotationFound |= processAnnotationForAttribute(a, attr, metadata);
443 }
444 if (fieldAnnotationFound) {
445 if (!existingAttribute) {
446 attributes.add(attr);
447 }
448 fieldAnnotationsFound = true;
449 }
450 }
451 if (fieldAnnotationsFound) {
452 metadata.setAttributes(attributes);
453 }
454
455 return fieldAnnotationsFound;
456 }
457
458
459
460
461
462
463
464
465 protected void addDataObjectRelationship(DataObjectMetadataImpl metadata, Field f, Relationship a) {
466 List<DataObjectRelationship> relationships = new ArrayList<DataObjectRelationship>(metadata.getRelationships());
467 DataObjectRelationshipImpl relationship = new DataObjectRelationshipImpl();
468 relationship.setName(f.getName());
469 Class<?> childType = f.getType();
470 relationship.setRelatedType(childType);
471 relationship.setReadOnly(true);
472 relationship.setSavedWithParent(false);
473 relationship.setDeletedWithParent(false);
474 relationship.setLoadedAtParentLoadTime(false);
475 relationship.setLoadedDynamicallyUponUse(true);
476
477 List<DataObjectAttributeRelationship> attributeRelationships = new ArrayList<DataObjectAttributeRelationship>();
478 List<String> referencePkFields = Collections.emptyList();
479 MetadataRepository metadataRepository = getDataObjectService().getMetadataRepository();
480 if (metadataRepository.contains(childType)) {
481 DataObjectMetadata childMetadata = metadataRepository.getMetadata(childType);
482 referencePkFields = childMetadata.getPrimaryKeyAttributeNames();
483 } else {
484
485 if (f.getType().getName().equals("org.kuali.rice.kim.api.identity.Person")) {
486 referencePkFields = Collections.singletonList("principalId");
487 }
488 }
489 if (!referencePkFields.isEmpty()) {
490 int index = 0;
491 for (String pkField : a.foreignKeyFields()) {
492 attributeRelationships.add(new DataObjectAttributeRelationshipImpl(pkField, referencePkFields
493 .get(index)));
494 index++;
495 }
496 relationship.setAttributeRelationships(attributeRelationships);
497
498 relationships.add(relationship);
499 }
500 metadata.setRelationships(relationships);
501 }
502
503
504
505
506
507
508
509
510 protected void addDataObjectCollection(DataObjectMetadataImpl metadata, Field f, CollectionRelationship a) {
511 List<DataObjectCollection> collections = new ArrayList<DataObjectCollection>(metadata.getCollections());
512 DataObjectCollectionImpl collection = new DataObjectCollectionImpl();
513 collection.setName(f.getName());
514
515 if ( !Collection.class.isAssignableFrom(f.getType()) ) {
516 throw new IllegalArgumentException(
517 "@CollectionRelationship annotations can only be on attributes of Collection type. Field: "
518 + f.getDeclaringClass().getName() + "." + f.getName() + " (" + f.getType() + ")");
519 }
520
521 if (a.collectionElementClass().equals(Object.class)) {
522 Type[] genericArgs = ((ParameterizedType) f.getGenericType()).getActualTypeArguments();
523 if (genericArgs.length == 0) {
524 throw new IllegalArgumentException(
525 "You can only leave off the collectionElementClass annotation on a @CollectionRelationship when the Collection type has been <typed>. Field: "
526 + f.getDeclaringClass().getName() + "." + f.getName() + " (" + f.getType() + ")");
527 }
528 collection.setRelatedType((Class<?>) genericArgs[0]);
529 } else {
530 collection.setRelatedType(a.collectionElementClass());
531 }
532
533 List<DataObjectAttributeRelationship> attributeRelationships = new ArrayList<DataObjectAttributeRelationship>(
534 a.attributeRelationships().length);
535 for (AttributeRelationship rel : a.attributeRelationships()) {
536 attributeRelationships.add(new DataObjectAttributeRelationshipImpl(rel.parentAttributeName(), rel
537 .childAttributeName()));
538 }
539 collection.setAttributeRelationships(attributeRelationships);
540
541 collection.setReadOnly(false);
542 collection.setSavedWithParent(false);
543 collection.setDeletedWithParent(false);
544 collection.setLoadedAtParentLoadTime(true);
545 collection.setLoadedDynamicallyUponUse(false);
546 List<DataObjectCollectionSortAttribute> sortAttributes = new ArrayList<DataObjectCollectionSortAttribute>(
547 a.sortAttributes().length);
548 for (CollectionSortAttribute csa : a.sortAttributes()) {
549 sortAttributes.add(new DataObjectCollectionSortAttributeImpl(csa.value(), csa.sortDirection()));
550 }
551 collection.setDefaultCollectionOrderingAttributeNames(sortAttributes);
552
553 collection.setIndirectCollection(a.indirectCollection());
554 collection.setMinItemsInCollection(a.minItemsInCollection());
555 collection.setMaxItemsInCollection(a.maxItemsInCollection());
556 if (StringUtils.isNotBlank(a.label())) {
557 collection.setLabel(a.label());
558 }
559 if (StringUtils.isNotBlank(a.elementLabel())) {
560 collection.setLabel(a.elementLabel());
561 }
562
563 collections.add(collection);
564 metadata.setCollections(collections);
565 }
566
567
568
569
570
571
572
573
574
575 protected boolean processInheritedAttributes(Class<?> clazz, DataObjectMetadataImpl metadata) {
576 if (LOG.isDebugEnabled()) {
577 LOG.debug("Processing InheritProperties field Annotations on " + clazz);
578 }
579 List<DataObjectAttribute> attributes = new ArrayList<DataObjectAttribute>(metadata.getAttributes());
580 boolean fieldAnnotationsFound = false;
581 for (Field f : clazz.getDeclaredFields()) {
582 boolean fieldAnnotationFound = false;
583 String propertyName = f.getName();
584
585 if (!f.isAnnotationPresent(InheritProperties.class) && !f.isAnnotationPresent(InheritProperty.class)) {
586 continue;
587 }
588 fieldAnnotationFound = true;
589
590 InheritProperty[] propertyList = null;
591 InheritProperties a = f.getAnnotation(InheritProperties.class);
592 if (a != null) {
593 propertyList = a.value();
594 } else {
595
596 InheritProperty ip = f.getAnnotation(InheritProperty.class);
597 propertyList = new InheritProperty[] { ip };
598 }
599 if (LOG.isDebugEnabled()) {
600 LOG.debug("InheritProperties found on " + clazz + "." + f.getName() + " : "
601 + Arrays.toString(propertyList));
602 }
603 for (InheritProperty inheritedProperty : propertyList) {
604 String inheritedPropertyName = inheritedProperty.name();
605 String extendedPropertyName = propertyName + "." + inheritedPropertyName;
606 DataObjectAttributeImpl attr = (DataObjectAttributeImpl) metadata.getAttribute(extendedPropertyName);
607 boolean existingAttribute = attr != null;
608 if (!existingAttribute) {
609
610
611
612
613 attr = new DataObjectAttributeImpl();
614 attr.setName(extendedPropertyName);
615 Class<?> relatedClass = f.getType();
616 try {
617 attr.setType(getTypeOfProperty(relatedClass, inheritedPropertyName));
618 DataType dataType = DataType.getDataTypeFromClass(attr.getType());
619 if (dataType == null) {
620 dataType = DataType.STRING;
621 }
622 attr.setDataType(dataType);
623 } catch (Exception e) {
624 throw new IllegalArgumentException("no field with name " + inheritedPropertyName
625 + " exists on " + relatedClass, e);
626 }
627
628
629 attr.setPersisted(false);
630 attr.setOwningType(metadata.getType());
631 attr.setInheritedFromType(relatedClass);
632 attr.setInheritedFromAttributeName(inheritedPropertyName);
633 attr.setInheritedFromParentAttributeName(propertyName);
634
635
636 processAnnotationForAttribute(inheritedProperty.label(), attr, metadata);
637
638 processAnnotationForAttribute(inheritedProperty.displayHints(), attr, metadata);
639
640 attributes.add(attr);
641 }
642 }
643
644 fieldAnnotationsFound |= fieldAnnotationFound;
645 }
646 if (fieldAnnotationsFound) {
647 metadata.setAttributes(attributes);
648 }
649 return fieldAnnotationsFound;
650 }
651
652
653
654
655
656
657
658
659
660
661
662 protected Class<?> getTypeOfProperty(Class<?> clazz, String propertyName) {
663 try {
664 Field f = clazz.getField(propertyName);
665 return f.getType();
666 } catch (Exception e) {
667
668 }
669 try {
670 Method m = clazz.getMethod("get" + StringUtils.capitalize(propertyName));
671 return m.getReturnType();
672 } catch (Exception e) {
673
674 }
675 try {
676 Method m = clazz.getMethod("is" + StringUtils.capitalize(propertyName));
677 return m.getReturnType();
678 } catch (Exception e) {
679
680 }
681 return null;
682 }
683
684
685
686
687
688
689
690 @Override
691 public boolean requiresListOfExistingTypes() {
692 return true;
693 }
694
695
696
697
698
699
700 public boolean isInitializationAttempted() {
701 return initializationAttempted;
702 }
703
704
705
706
707
708 public DataObjectService getDataObjectService() {
709 if (dataObjectService == null) {
710 dataObjectService = KradDataServiceLocator.getDataObjectService();
711 }
712 return dataObjectService;
713 }
714
715
716
717
718
719
720 public void setDataObjectService(DataObjectService dataObjectService) {
721 this.dataObjectService = dataObjectService;
722 }
723 }