1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.service.impl;
17
18 import java.lang.reflect.Modifier;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Properties;
23
24 import org.apache.commons.beanutils.PropertyUtils;
25 import org.apache.commons.lang.StringUtils;
26 import org.apache.commons.lang.builder.ToStringBuilder;
27 import org.apache.log4j.Logger;
28 import org.kuali.rice.core.api.CoreApiServiceLocator;
29 import org.kuali.rice.core.api.config.property.ConfigurationService;
30 import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
31 import org.kuali.rice.coreservice.framework.parameter.ParameterService;
32 import org.kuali.rice.krad.bo.BusinessObject;
33 import org.kuali.rice.krad.bo.DataObjectRelationship;
34 import org.kuali.rice.krad.bo.ExternalizableBusinessObject;
35 import org.kuali.rice.krad.bo.ModuleConfiguration;
36 import org.kuali.rice.krad.data.KradDataServiceLocator;
37 import org.kuali.rice.krad.data.provider.PersistenceProvider;
38 import org.kuali.rice.krad.data.provider.Provider;
39 import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
40 import org.kuali.rice.krad.datadictionary.PrimitiveAttributeDefinition;
41 import org.kuali.rice.krad.datadictionary.RelationshipDefinition;
42 import org.kuali.rice.krad.service.BusinessObjectNotLookupableException;
43 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
44 import org.kuali.rice.krad.service.KualiModuleService;
45 import org.kuali.rice.krad.service.LegacyDataAdapter;
46 import org.kuali.rice.krad.service.LookupService;
47 import org.kuali.rice.krad.service.ModuleService;
48 import org.kuali.rice.krad.uif.UifParameters;
49 import org.kuali.rice.krad.util.ExternalizableBusinessObjectUtils;
50 import org.kuali.rice.krad.util.KRADConstants;
51 import org.kuali.rice.krad.util.UrlFactory;
52 import org.springframework.beans.BeansException;
53 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
54 import org.springframework.context.ApplicationContext;
55
56
57
58
59 public abstract class RemoteModuleServiceBase implements ModuleService {
60 protected static final Logger LOG = Logger.getLogger(RemoteModuleServiceBase.class);
61
62 protected ModuleConfiguration moduleConfiguration;
63 protected KualiModuleService kualiModuleService;
64 protected ApplicationContext applicationContext;
65 protected ConfigurationService kualiConfigurationService;
66 protected LookupService lookupService;
67 protected LegacyDataAdapter legacyDataAdapter;
68
69
70
71
72 @Override
73 public boolean isResponsibleFor(Class businessObjectClass) {
74 ModuleConfiguration mc = getModuleConfiguration();
75
76 if (mc == null) {
77 throw new IllegalStateException("Module configuration has not been initialized for the module service.");
78 }
79
80 if (businessObjectClass == null) {
81 return false;
82 }
83
84 if (packagePrefixesMatchesDataObject(businessObjectClass)) {
85 return true;
86 }
87
88 if (persistenceProvidersMatchDataObject(businessObjectClass)) {
89 return true;
90 }
91
92 if (ExternalizableBusinessObject.class.isAssignableFrom(businessObjectClass)) {
93 Class externalizableBusinessObjectInterface =
94 ExternalizableBusinessObjectUtils.determineExternalizableBusinessObjectSubInterface(
95 businessObjectClass);
96 if (externalizableBusinessObjectInterface != null) {
97 for (String prefix : getModuleConfiguration().getPackagePrefixes()) {
98 if (externalizableBusinessObjectInterface.getPackage().getName().startsWith(prefix)) {
99 return true;
100 }
101 }
102 }
103 }
104 return false;
105 }
106
107
108
109
110
111 protected boolean packagePrefixesMatchesDataObject(Class dataObjectClass) {
112 if (getModuleConfiguration().getPackagePrefixes() != null) {
113 for (String prefix : getModuleConfiguration().getPackagePrefixes()) {
114 if (dataObjectClass.getPackage().getName().startsWith(prefix)) {
115 return true;
116 }
117 }
118 }
119 return false;
120 }
121
122
123
124
125
126 protected boolean persistenceProvidersMatchDataObject(Class dataObjectClass) {
127 List<Provider> providers = getModuleConfiguration().getProviders();
128 if (providers != null) {
129 for (Provider provider: providers) {
130 if (provider instanceof PersistenceProvider) {
131 if (((PersistenceProvider) provider).handles(dataObjectClass)) {
132 return true;
133 }
134 }
135 }
136 }
137 return false;
138 }
139
140
141
142
143
144
145
146
147
148 protected static boolean isNonBlankValueForKey(Map<String, Object> map, String key) {
149 if (map == null) return false;
150
151 Object result = map.get(key);
152 if (result instanceof String) {
153 return !StringUtils.isBlank((String)result);
154 }
155 return result != null;
156 }
157
158 @Override
159 public List listPrimaryKeyFieldNames(Class businessObjectInterfaceClass) {
160 Class clazz = getExternalizableBusinessObjectImplementation(businessObjectInterfaceClass);
161 return KRADServiceLocatorWeb.getLegacyDataAdapter().listPrimaryKeyFieldNames(clazz);
162 }
163
164
165
166
167 @Override
168 public BusinessObjectEntry getExternalizableBusinessObjectDictionaryEntry(Class businessObjectInterfaceClass) {
169 Class boClass = getExternalizableBusinessObjectImplementation(businessObjectInterfaceClass);
170
171 return boClass == null ? null : KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary()
172 .getBusinessObjectEntryForConcreteClass(boClass.getName());
173 }
174
175
176
177
178
179 @Override
180 public String getExternalizableDataObjectInquiryUrl(Class<?> inquiryDataObjectClass, Properties parameters) {
181 String baseUrl = getBaseInquiryUrl();
182
183
184 if (ExternalizableBusinessObject.class.isAssignableFrom(inquiryDataObjectClass)) {
185 Class implementationClass = getExternalizableBusinessObjectImplementation(inquiryDataObjectClass.asSubclass(
186 ExternalizableBusinessObject.class));
187 if (implementationClass == null) {
188 throw new RuntimeException("Can't find ExternalizableBusinessObject implementation class for "
189 + inquiryDataObjectClass.getName());
190 }
191
192 parameters.put(UifParameters.DATA_OBJECT_CLASS_NAME, implementationClass.getName());
193 }
194
195 return UrlFactory.parameterizeUrl(baseUrl, parameters);
196 }
197
198
199
200
201
202
203 protected String getBaseInquiryUrl() {
204 return getKualiConfigurationService().getPropertyValueAsString(KRADConstants.KRAD_INQUIRY_URL_KEY);
205 }
206
207
208
209
210
211 @Override
212 public String getExternalizableDataObjectLookupUrl(Class<?> lookupDataObjectClass, Properties parameters) {
213 String baseUrl = getBaseLookupUrl();
214
215
216 if (ExternalizableBusinessObject.class.isAssignableFrom(lookupDataObjectClass)) {
217 Class implementationClass = getExternalizableBusinessObjectImplementation(lookupDataObjectClass.asSubclass(
218 ExternalizableBusinessObject.class));
219 if (implementationClass == null) {
220 throw new RuntimeException("Can't find ExternalizableBusinessObject implementation class for "
221 + lookupDataObjectClass.getName());
222 }
223
224 parameters.put(UifParameters.DATA_OBJECT_CLASS_NAME, implementationClass.getName());
225 }
226
227 return UrlFactory.parameterizeUrl(baseUrl, parameters);
228 }
229
230
231
232
233
234
235 protected String getRiceBaseLookupUrl() {
236 return BaseLookupUrlsHolder.remoteKradBaseLookupUrl;
237 }
238
239
240 protected static final class BaseLookupUrlsHolder {
241
242 public static final String localKradBaseLookupUrl;
243 public static final String remoteKradBaseLookupUrl;
244
245 static {
246 remoteKradBaseLookupUrl = CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString(KRADConstants.KRAD_SERVER_LOOKUP_URL_KEY);
247 localKradBaseLookupUrl = CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString(KRADConstants.KRAD_LOOKUP_URL_KEY);
248 }
249 }
250
251
252
253
254
255
256 protected String getBaseLookupUrl() {
257 return getRiceBaseLookupUrl();
258 }
259
260 @Override
261 @Deprecated
262 public String getExternalizableBusinessObjectInquiryUrl(Class inquiryBusinessObjectClass,
263 Map<String, String[]> parameters) {
264 if (!isExternalizable(inquiryBusinessObjectClass)) {
265 return KRADConstants.EMPTY_STRING;
266 }
267 String businessObjectClassAttribute;
268
269 Class implementationClass = getExternalizableBusinessObjectImplementation(inquiryBusinessObjectClass);
270 if (implementationClass == null) {
271 LOG.error("Can't find ExternalizableBusinessObject implementation class for " + inquiryBusinessObjectClass
272 .getName());
273 throw new RuntimeException("Can't find ExternalizableBusinessObject implementation class for interface "
274 + inquiryBusinessObjectClass.getName());
275 }
276 businessObjectClassAttribute = implementationClass.getName();
277 return UrlFactory.parameterizeUrl(getInquiryUrl(inquiryBusinessObjectClass), getUrlParameters(
278 businessObjectClassAttribute, parameters));
279 }
280
281
282
283
284
285
286
287 @Deprecated
288 @Override
289 public String getExternalizableBusinessObjectLookupUrl(Class inquiryBusinessObjectClass,
290 Map<String, String> parameters) {
291 Properties urlParameters = new Properties();
292
293 String riceBaseUrl = CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString(
294 KRADConstants.KUALI_RICE_URL_KEY);
295 String lookupUrl = riceBaseUrl;
296 if (!lookupUrl.endsWith("/")) {
297 lookupUrl = lookupUrl + "/";
298 }
299 if (parameters.containsKey(KRADConstants.MULTIPLE_VALUE)) {
300 lookupUrl = lookupUrl + KRADConstants.MULTIPLE_VALUE_LOOKUP_ACTION;
301 } else {
302 lookupUrl = lookupUrl + KRADConstants.LOOKUP_ACTION;
303 }
304 for (String paramName : parameters.keySet()) {
305 urlParameters.put(paramName, parameters.get(paramName));
306 }
307
308 Class clazz = getExternalizableBusinessObjectImplementation(inquiryBusinessObjectClass);
309 urlParameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, clazz == null ? "" : clazz.getName());
310
311 return UrlFactory.parameterizeUrl(lookupUrl, urlParameters);
312 }
313
314
315
316
317
318 @Override
319 public <T extends ExternalizableBusinessObject> List<T> getExternalizableBusinessObjectsListForLookup(
320 Class<T> externalizableBusinessObjectClass, Map<String, Object> fieldValues, boolean unbounded) {
321 Class<? extends ExternalizableBusinessObject> implementationClass =
322 getExternalizableBusinessObjectImplementation(externalizableBusinessObjectClass);
323 if (isExternalizableBusinessObjectLookupable(implementationClass)) {
324 Map<String, String> searchCriteria = new HashMap<String, String>();
325 for (Map.Entry<String, Object> fieldValue : fieldValues.entrySet()) {
326 if (fieldValue.getValue() != null) {
327 searchCriteria.put(fieldValue.getKey(), fieldValue.getValue().toString());
328 } else {
329 searchCriteria.put(fieldValue.getKey(), null);
330 }
331 }
332 return (List<T>) getLookupService().findCollectionBySearchHelper(implementationClass, searchCriteria,
333 unbounded);
334 } else {
335 throw new BusinessObjectNotLookupableException(
336 "External business object is not a Lookupable: " + implementationClass);
337 }
338 }
339
340
341
342
343
344
345
346 @Override
347 public <T extends ExternalizableBusinessObject> T retrieveExternalizableBusinessObjectIfNecessary(
348 BusinessObject businessObject, T currentInstanceExternalizableBO, String externalizableRelationshipName) {
349
350 if (businessObject == null) {
351 return null;
352 }
353 Class clazz;
354 try {
355 clazz = getExternalizableBusinessObjectImplementation(PropertyUtils.getPropertyType(businessObject,
356 externalizableRelationshipName));
357 } catch (Exception iex) {
358 LOG.warn("Exception:"
359 + iex
360 + " thrown while trying to get property type for property:"
361 + externalizableRelationshipName
362 + " from business object:"
363 + businessObject);
364 return null;
365 }
366
367
368
369 BusinessObjectEntry entry =
370 KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getBusinessObjectEntries().get(
371 businessObject.getClass().getSimpleName());
372 RelationshipDefinition relationshipDefinition = entry.getRelationshipDefinition(externalizableRelationshipName);
373 List<PrimitiveAttributeDefinition> primitiveAttributeDefinitions =
374 relationshipDefinition.getPrimitiveAttributes();
375
376 Map<String, Object> fieldValuesInEBO = new HashMap<String, Object>();
377 Object sourcePropertyValue;
378 Object targetPropertyValue = null;
379 boolean sourceTargetPropertyValuesSame = true;
380 for (PrimitiveAttributeDefinition primitiveAttributeDefinition : primitiveAttributeDefinitions) {
381 sourcePropertyValue = KradDataServiceLocator.getDataObjectService().wrap(businessObject).getPropertyValueNullSafe(
382 primitiveAttributeDefinition.getSourceName());
383 if (currentInstanceExternalizableBO != null) {
384 targetPropertyValue = KradDataServiceLocator.getDataObjectService().wrap(currentInstanceExternalizableBO).getPropertyValueNullSafe(
385 primitiveAttributeDefinition.getTargetName());
386 }
387 if (sourcePropertyValue == null) {
388 return null;
389 } else if (targetPropertyValue == null || (targetPropertyValue != null && !targetPropertyValue.equals(
390 sourcePropertyValue))) {
391 sourceTargetPropertyValuesSame = false;
392 }
393 fieldValuesInEBO.put(primitiveAttributeDefinition.getTargetName(), sourcePropertyValue);
394 }
395
396 if (!sourceTargetPropertyValuesSame) {
397 return (T) getExternalizableBusinessObject(clazz, fieldValuesInEBO);
398 }
399 return currentInstanceExternalizableBO;
400 }
401
402
403
404
405
406
407
408 @Override
409 public List<? extends ExternalizableBusinessObject> retrieveExternalizableBusinessObjectsList(
410 BusinessObject businessObject, String externalizableRelationshipName, Class externalizableClazz) {
411
412 if (businessObject == null) {
413 return null;
414 }
415
416
417 String className = businessObject.getClass().getName();
418 String key = className.substring(className.lastIndexOf(".") + 1);
419 BusinessObjectEntry entry =
420 KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getBusinessObjectEntries().get(
421 key);
422 RelationshipDefinition relationshipDefinition = entry.getRelationshipDefinition(externalizableRelationshipName);
423 List<PrimitiveAttributeDefinition> primitiveAttributeDefinitions =
424 relationshipDefinition.getPrimitiveAttributes();
425 Map<String, Object> fieldValuesInEBO = new HashMap<String, Object>();
426 Object sourcePropertyValue;
427 for (PrimitiveAttributeDefinition primitiveAttributeDefinition : primitiveAttributeDefinitions) {
428 sourcePropertyValue = KradDataServiceLocator.getDataObjectService().wrap(businessObject).getPropertyValueNullSafe(
429 primitiveAttributeDefinition.getSourceName());
430 if (sourcePropertyValue == null) {
431 return null;
432 }
433 fieldValuesInEBO.put(primitiveAttributeDefinition.getTargetName(), sourcePropertyValue);
434 }
435 return getExternalizableBusinessObjectsList(getExternalizableBusinessObjectImplementation(externalizableClazz),
436 fieldValuesInEBO);
437 }
438
439
440
441
442 @Override
443 public <E extends ExternalizableBusinessObject> Class<E> getExternalizableBusinessObjectImplementation(
444 Class<E> externalizableBusinessObjectInterface) {
445 if (getModuleConfiguration() == null) {
446 throw new IllegalStateException("Module configuration has not been initialized for the module service.");
447 }
448 Map<Class, Class> ebos = getModuleConfiguration().getExternalizableBusinessObjectImplementations();
449 if (ebos == null) {
450 return null;
451 }
452 if (ebos.containsValue(externalizableBusinessObjectInterface)) {
453 return externalizableBusinessObjectInterface;
454 } else {
455 Class<E> implementationClass = ebos.get(externalizableBusinessObjectInterface);
456
457 int implClassModifiers = implementationClass.getModifiers();
458 if (Modifier.isInterface(implClassModifiers) || Modifier.isAbstract(implClassModifiers)) {
459 throw new RuntimeException("Implementation class must be non-abstract class: ebo interface: "
460 + externalizableBusinessObjectInterface.getName()
461 + " impl class: "
462 + implementationClass.getName()
463 + " module: "
464 + getModuleConfiguration().getNamespaceCode());
465 }
466 return implementationClass;
467 }
468
469 }
470
471 @Deprecated
472 protected Properties getUrlParameters(String businessObjectClassAttribute, Map<String, String[]> parameters) {
473 Properties urlParameters = new Properties();
474 for (String paramName : parameters.keySet()) {
475 String[] parameterValues = parameters.get(paramName);
476 if (parameterValues.length > 0) {
477 urlParameters.put(paramName, parameterValues[0]);
478 }
479 }
480 urlParameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, businessObjectClassAttribute);
481 urlParameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.CONTINUE_WITH_INQUIRY_METHOD_TO_CALL);
482 return urlParameters;
483 }
484
485 @Deprecated
486 protected String getInquiryUrl(Class inquiryBusinessObjectClass) {
487 String riceBaseUrl = CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString(
488 KRADConstants.KUALI_RICE_URL_KEY);
489 String inquiryUrl = riceBaseUrl;
490 if (!inquiryUrl.endsWith("/")) {
491 inquiryUrl = inquiryUrl + "/";
492 }
493 return inquiryUrl + KRADConstants.INQUIRY_ACTION;
494 }
495
496
497
498
499 @Override
500 public void afterPropertiesSet() throws Exception {
501 KualiModuleService kualiModuleService = null;
502 try {
503 kualiModuleService = KRADServiceLocatorWeb.getKualiModuleService();
504 if (kualiModuleService == null) {
505 kualiModuleService = ((KualiModuleService) applicationContext.getBean(
506 KRADServiceLocatorWeb.KUALI_MODULE_SERVICE));
507 }
508 } catch (NoSuchBeanDefinitionException ex) {
509 kualiModuleService = ((KualiModuleService) applicationContext.getBean(
510 KRADServiceLocatorWeb.KUALI_MODULE_SERVICE));
511 }
512 kualiModuleService.getInstalledModuleServices().add(this);
513 }
514
515
516
517
518 @Override
519 public ModuleConfiguration getModuleConfiguration() {
520 return this.moduleConfiguration;
521 }
522
523
524
525
526 public void setModuleConfiguration(ModuleConfiguration moduleConfiguration) {
527 this.moduleConfiguration = moduleConfiguration;
528 }
529
530
531
532
533 @Override
534 public boolean isExternalizable(Class boClazz) {
535 if (boClazz == null) {
536 return false;
537 }
538 return ExternalizableBusinessObject.class.isAssignableFrom(boClazz);
539 }
540
541 @Override
542 public <T extends ExternalizableBusinessObject> T createNewObjectFromExternalizableClass(Class<T> boClass) {
543 try {
544 return (T) getExternalizableBusinessObjectImplementation(boClass).newInstance();
545 } catch (Exception e) {
546 throw new RuntimeException("Unable to create externalizable business object class", e);
547 }
548 }
549
550 public DataObjectRelationship getBusinessObjectRelationship(Class boClass, String attributeName,
551 String attributePrefix) {
552 return null;
553 }
554
555
556
557
558
559 public KualiModuleService getKualiModuleService() {
560 return this.kualiModuleService;
561 }
562
563
564
565
566 public void setKualiModuleService(KualiModuleService kualiModuleService) {
567 this.kualiModuleService = kualiModuleService;
568 }
569
570 protected ConfigurationService getKualiConfigurationService() {
571 if (this.kualiConfigurationService == null) {
572 this.kualiConfigurationService = CoreApiServiceLocator.getKualiConfigurationService();
573 }
574
575 return this.kualiConfigurationService;
576 }
577
578 public void setKualiConfigurationService(ConfigurationService kualiConfigurationService) {
579 this.kualiConfigurationService = kualiConfigurationService;
580 }
581
582
583
584
585 @Override
586 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
587 this.applicationContext = applicationContext;
588 }
589
590
591
592
593
594
595 @Override
596 public List<List<String>> listAlternatePrimaryKeyFieldNames(Class businessObjectInterfaceClass) {
597 return null;
598 }
599
600
601
602
603
604
605 @Override
606 public boolean isLocked() {
607 ModuleConfiguration configuration = this.getModuleConfiguration();
608 if (configuration != null) {
609 String namespaceCode = configuration.getNamespaceCode();
610 String componentCode = KRADConstants.DetailTypes.ALL_DETAIL_TYPE;
611 String parameterName = KRADConstants.SystemGroupParameterNames.OLTP_LOCKOUT_ACTIVE_IND;
612 ParameterService parameterService = CoreFrameworkServiceLocator.getParameterService();
613 String shouldLockout = parameterService.getParameterValueAsString(namespaceCode, componentCode,
614 parameterName);
615 if (StringUtils.isNotBlank(shouldLockout)) {
616 return parameterService.getParameterValueAsBoolean(namespaceCode, componentCode, parameterName);
617 }
618 }
619 return false;
620 }
621
622
623
624
625
626
627 protected LookupService getLookupService() {
628 return lookupService != null ? lookupService : KRADServiceLocatorWeb.getLookupService();
629 }
630
631
632
633
634
635
636 protected LegacyDataAdapter getLegacyDataAdapter() {
637 return legacyDataAdapter != null ? legacyDataAdapter : KRADServiceLocatorWeb.getLegacyDataAdapter();
638 }
639
640 @Override
641 public boolean goToCentralRiceForInquiry() {
642 return false;
643 }
644
645 @Override
646 public String toString() {
647 return new ToStringBuilder(this)
648 .append("applicationContext", applicationContext.getDisplayName())
649 .append("moduleConfiguration", moduleConfiguration)
650 .toString();
651 }
652 }