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.io.Serializable;
19 import java.util.Arrays;
20 import java.util.List;
21 import java.util.Map;
22
23 import org.apache.commons.lang.StringUtils;
24 import org.apache.log4j.Logger;
25 import org.kuali.rice.core.framework.persistence.jta.TransactionalNoValidationExceptionRollback;
26 import org.kuali.rice.kew.api.exception.WorkflowException;
27 import org.kuali.rice.kim.api.identity.Person;
28 import org.kuali.rice.krad.bo.BusinessObject;
29 import org.kuali.rice.krad.bo.PersistableBusinessObject;
30 import org.kuali.rice.krad.dao.MaintenanceDocumentDao;
31 import org.kuali.rice.krad.maintenance.MaintenanceDocument;
32 import org.kuali.rice.krad.maintenance.MaintenanceLock;
33 import org.kuali.rice.krad.exception.DocumentTypeAuthorizationException;
34 import org.kuali.rice.krad.maintenance.Maintainable;
35 import org.kuali.rice.krad.service.DataObjectAuthorizationService;
36 import org.kuali.rice.krad.service.DataObjectMetaDataService;
37 import org.kuali.rice.krad.service.DocumentDictionaryService;
38 import org.kuali.rice.krad.service.DocumentService;
39 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
40 import org.kuali.rice.krad.service.MaintenanceDocumentService;
41 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
42 import org.kuali.rice.krad.util.GlobalVariables;
43 import org.kuali.rice.krad.util.KRADConstants;
44 import org.kuali.rice.krad.util.KRADUtils;
45 import org.kuali.rice.krad.util.ObjectUtils;
46
47
48
49
50
51
52
53 @TransactionalNoValidationExceptionRollback
54 public class MaintenanceDocumentServiceImpl implements MaintenanceDocumentService {
55 protected static final Logger LOG = Logger.getLogger(MaintenanceDocumentServiceImpl.class);
56
57 private MaintenanceDocumentDao maintenanceDocumentDao;
58 private DataObjectAuthorizationService dataObjectAuthorizationService;
59 private DocumentService documentService;
60 private DataObjectMetaDataService dataObjectMetaDataService;
61 private DocumentDictionaryService documentDictionaryService;
62
63
64
65
66
67 @SuppressWarnings("unchecked")
68 public MaintenanceDocument setupNewMaintenanceDocument(String objectClassName, String documentTypeName,
69 String maintenanceAction) {
70 if (StringUtils.isEmpty(objectClassName) && StringUtils.isEmpty(documentTypeName)) {
71 throw new IllegalArgumentException("Document type name or bo class not given!");
72 }
73
74
75 if (StringUtils.isEmpty(documentTypeName)) {
76 try {
77 documentTypeName =
78 getDocumentDictionaryService().getMaintenanceDocumentTypeName(Class.forName(objectClassName));
79 } catch (ClassNotFoundException e) {
80 throw new RuntimeException(e);
81 }
82
83 if (StringUtils.isEmpty(documentTypeName)) {
84 throw new RuntimeException(
85 "documentTypeName is empty; does this Business Object have a maintenance document definition? " +
86 objectClassName);
87 }
88 }
89
90
91 if (KRADConstants.MAINTENANCE_NEW_ACTION.equals(maintenanceAction) ||
92 KRADConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceAction)) {
93 Class<?> boClass =
94 getDocumentDictionaryService().getMaintenanceDataObjectClass(documentTypeName);
95 boolean allowsNewOrCopy = getDataObjectAuthorizationService()
96 .canCreate(boClass, GlobalVariables.getUserSession().getPerson(), documentTypeName);
97 if (!allowsNewOrCopy) {
98 LOG.error("Document type " + documentTypeName + " does not allow new or copy actions.");
99 throw new DocumentTypeAuthorizationException(
100 GlobalVariables.getUserSession().getPerson().getPrincipalId(), "newOrCopy", documentTypeName);
101 }
102 }
103
104
105 try {
106 return (MaintenanceDocument) getDocumentService().getNewDocument(documentTypeName);
107 } catch (WorkflowException e) {
108 LOG.error("Cannot get new maintenance document instance for doc type: " + documentTypeName, e);
109 throw new RuntimeException("Cannot get new maintenance document instance for doc type: " + documentTypeName,
110 e);
111 }
112 }
113
114
115
116
117 @Override
118 public void setupMaintenanceObject(MaintenanceDocument document, String maintenanceAction,
119 Map<String, String[]> requestParameters) {
120 document.getNewMaintainableObject().setMaintenanceAction(maintenanceAction);
121 document.getOldMaintainableObject().setMaintenanceAction(maintenanceAction);
122
123
124 if (!KRADConstants.MAINTENANCE_NEW_ACTION.equals(maintenanceAction) &&
125 !KRADConstants.MAINTENANCE_NEWWITHEXISTING_ACTION.equals(maintenanceAction)) {
126 Object oldDataObject = retrieveObjectForMaintenance(document, requestParameters);
127
128
129
130 Object newDataObject = ObjectUtils.deepCopy((Serializable) oldDataObject);
131
132
133 if (KRADConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceAction)) {
134 processMaintenanceObjectForCopy(document, newDataObject, requestParameters);
135 } else {
136 checkMaintenanceActionAuthorization(document, oldDataObject, maintenanceAction, requestParameters);
137 }
138
139
140 document.getOldMaintainableObject().setDataObject(oldDataObject);
141 document.getNewMaintainableObject().setDataObject(newDataObject);
142 }
143
144
145 if (KRADConstants.MAINTENANCE_NEWWITHEXISTING_ACTION.equals(maintenanceAction)) {
146 Object newBO = document.getNewMaintainableObject().getDataObject();
147 Map<String, String> parameters =
148 buildKeyMapFromRequest(requestParameters, document.getNewMaintainableObject().getDataObjectClass());
149 ObjectPropertyUtils.copyPropertiesToObject(parameters, newBO);
150 if (newBO instanceof PersistableBusinessObject) {
151 ((PersistableBusinessObject) newBO).refresh();
152 }
153
154 document.getNewMaintainableObject().setupNewFromExisting(document, requestParameters);
155 } else if (KRADConstants.MAINTENANCE_NEW_ACTION.equals(maintenanceAction)) {
156 document.getNewMaintainableObject().processAfterNew(document, requestParameters);
157 }
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171 protected void checkMaintenanceActionAuthorization(MaintenanceDocument document, Object oldBusinessObject,
172 String maintenanceAction, Map<String, String[]> requestParameters) {
173 if (KRADConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceAction)) {
174 boolean allowsEdit = getDataObjectAuthorizationService()
175 .canMaintain(oldBusinessObject, GlobalVariables.getUserSession().getPerson(),
176 document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
177 if (!allowsEdit) {
178 LOG.error("Document type " + document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName() +
179 " does not allow edit actions.");
180 throw new DocumentTypeAuthorizationException(
181 GlobalVariables.getUserSession().getPerson().getPrincipalId(), "edit",
182 document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
183 }
184
185
186 document.getNewMaintainableObject().processAfterEdit(document, requestParameters);
187 }
188
189 else if (KRADConstants.MAINTENANCE_DELETE_ACTION.equals(maintenanceAction)) {
190 boolean allowsDelete = getDataObjectAuthorizationService()
191 .canMaintain((BusinessObject) oldBusinessObject, GlobalVariables.getUserSession().getPerson(),
192 document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
193 if (!allowsDelete) {
194 LOG.error("Document type " + document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName() +
195 " does not allow delete actions.");
196 throw new DocumentTypeAuthorizationException(
197 GlobalVariables.getUserSession().getPerson().getPrincipalId(), "delete",
198 document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
199 }
200 }
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218 protected Object retrieveObjectForMaintenance(MaintenanceDocument document,
219 Map<String, String[]> requestParameters) {
220 Map<String, String> keyMap =
221 buildKeyMapFromRequest(requestParameters, document.getNewMaintainableObject().getDataObjectClass());
222
223 Object oldDataObject = document.getNewMaintainableObject().retrieveObjectForEditOrCopy(document, keyMap);
224
225 if (oldDataObject == null && !document.getOldMaintainableObject().isExternalBusinessObject()) {
226 throw new RuntimeException(
227 "Cannot retrieve old record for maintenance document, incorrect parameters passed on maint url: " +
228 requestParameters);
229 }
230
231 if (document.getOldMaintainableObject().isExternalBusinessObject()) {
232 if (oldDataObject == null) {
233 try {
234 oldDataObject = document.getOldMaintainableObject().getDataObjectClass().newInstance();
235 } catch (Exception ex) {
236 throw new RuntimeException(
237 "External BO maintainable was null and unable to instantiate for old maintainable object.",
238 ex);
239 }
240 }
241
242 populateMaintenanceObjectWithCopyKeyValues(KRADUtils.translateRequestParameterMap(requestParameters),
243 oldDataObject, document.getOldMaintainableObject());
244 document.getOldMaintainableObject().prepareExternalBusinessObject((PersistableBusinessObject) oldDataObject);
245 oldDataObject = document.getOldMaintainableObject().getDataObject();
246 }
247
248 return oldDataObject;
249 }
250
251
252
253
254
255
256
257
258
259
260 protected void processMaintenanceObjectForCopy(MaintenanceDocument document, Object maintenanceObject,
261 Map<String, String[]> requestParameters) {
262 if (!document.isFieldsClearedOnCopy()) {
263 Maintainable maintainable = document.getNewMaintainableObject();
264 if (!getDocumentDictionaryService().getPreserveLockingKeysOnCopy(maintainable.getDataObjectClass())) {
265 clearPrimaryKeyFields(maintenanceObject, maintainable.getDataObjectClass());
266 }
267
268 clearUnauthorizedNewFields(document);
269
270 maintainable.processAfterCopy(document, requestParameters);
271
272
273 document.setFieldsClearedOnCopy(true);
274 }
275 }
276
277
278
279
280
281
282
283 protected void clearPrimaryKeyFields(Object maintenanceObject, Class<?> dataObjectClass) {
284 List<String> keyFieldNames = getDataObjectMetaDataService().listPrimaryKeyFieldNames(dataObjectClass);
285 for (String keyFieldName : keyFieldNames) {
286 ObjectPropertyUtils.setPropertyValue(maintenanceObject, keyFieldName, null);
287 }
288 }
289
290
291
292
293
294
295
296
297 protected void clearUnauthorizedNewFields(MaintenanceDocument document) {
298
299 Person user = GlobalVariables.getUserSession().getPerson();
300
301
302
303
304
305
306
307 }
308
309
310
311
312
313
314
315
316
317
318
319 protected Map<String, String> buildKeyMapFromRequest(Map<String, String[]> requestParameters,
320 Class<?> dataObjectClass) {
321 List<String> keyFieldNames = null;
322
323
324 Map<String, String> parameters = KRADUtils.translateRequestParameterMap(requestParameters);
325
326
327
328 if (!StringUtils.isBlank(parameters.get(KRADConstants.OVERRIDE_KEYS))) {
329 String[] overrideKeys =
330 parameters.get(KRADConstants.OVERRIDE_KEYS).split(KRADConstants.FIELD_CONVERSIONS_SEPARATOR);
331 keyFieldNames = Arrays.asList(overrideKeys);
332 } else {
333 keyFieldNames = getDataObjectMetaDataService().listPrimaryKeyFieldNames(dataObjectClass);
334 }
335
336 return KRADUtils.getParametersFromRequest(keyFieldNames, dataObjectClass, parameters);
337 }
338
339
340
341
342
343
344
345
346
347
348
349 protected void populateMaintenanceObjectWithCopyKeyValues(Map<String, String> parameters, Object oldBusinessObject,
350 Maintainable oldMaintainableObject) {
351 List<String> keyFieldNamesToCopy = null;
352 Map<String, String> parametersToCopy = null;
353
354 if (!StringUtils.isBlank(parameters.get(KRADConstants.COPY_KEYS))) {
355 String[] copyKeys =
356 parameters.get(KRADConstants.COPY_KEYS).split(KRADConstants.FIELD_CONVERSIONS_SEPARATOR);
357 keyFieldNamesToCopy = Arrays.asList(copyKeys);
358 parametersToCopy = KRADUtils
359 .getParametersFromRequest(keyFieldNamesToCopy, oldMaintainableObject.getDataObjectClass(),
360 parameters);
361 }
362
363 if (parametersToCopy != null) {
364
365 ObjectPropertyUtils.copyPropertiesToObject(parametersToCopy, oldBusinessObject);
366 }
367 }
368
369
370
371
372 public String getLockingDocumentId(MaintenanceDocument document) {
373 return getLockingDocumentId(document.getNewMaintainableObject(), document.getDocumentNumber());
374 }
375
376
377
378
379
380 public String getLockingDocumentId(Maintainable maintainable, String documentNumber) {
381 String lockingDocId = null;
382 List<MaintenanceLock> maintenanceLocks = maintainable.generateMaintenanceLocks();
383 for (MaintenanceLock maintenanceLock : maintenanceLocks) {
384 lockingDocId = maintenanceDocumentDao
385 .getLockingDocumentNumber(maintenanceLock.getLockingRepresentation(), documentNumber);
386 if (StringUtils.isNotBlank(lockingDocId)) {
387 break;
388 }
389 }
390 return lockingDocId;
391 }
392
393
394
395
396 public void deleteLocks(String documentNumber) {
397 maintenanceDocumentDao.deleteLocks(documentNumber);
398 }
399
400
401
402
403 public void storeLocks(List<MaintenanceLock> maintenanceLocks) {
404 maintenanceDocumentDao.storeLocks(maintenanceLocks);
405 }
406
407 public MaintenanceDocumentDao getMaintenanceDocumentDao() {
408 return maintenanceDocumentDao;
409 }
410
411 public void setMaintenanceDocumentDao(MaintenanceDocumentDao maintenanceDocumentDao) {
412 this.maintenanceDocumentDao = maintenanceDocumentDao;
413 }
414
415 protected DataObjectAuthorizationService getDataObjectAuthorizationService() {
416 if (dataObjectAuthorizationService == null) {
417 this.dataObjectAuthorizationService = KRADServiceLocatorWeb.getDataObjectAuthorizationService();
418 }
419 return dataObjectAuthorizationService;
420 }
421
422 public void setDataObjectAuthorizationService(DataObjectAuthorizationService dataObjectAuthorizationService) {
423 this.dataObjectAuthorizationService = dataObjectAuthorizationService;
424 }
425
426 protected DocumentService getDocumentService() {
427 return this.documentService;
428 }
429
430 public void setDocumentService(DocumentService documentService) {
431 this.documentService = documentService;
432 }
433
434 protected DataObjectMetaDataService getDataObjectMetaDataService() {
435 if (dataObjectMetaDataService == null) {
436 dataObjectMetaDataService = KRADServiceLocatorWeb.getDataObjectMetaDataService();
437 }
438 return dataObjectMetaDataService;
439 }
440
441 public void setDataObjectMetaDataService(DataObjectMetaDataService dataObjectMetaDataService) {
442 this.dataObjectMetaDataService = dataObjectMetaDataService;
443 }
444
445 public DocumentDictionaryService getDocumentDictionaryService() {
446 if (documentDictionaryService == null) {
447 this.documentDictionaryService = KRADServiceLocatorWeb.getDocumentDictionaryService();
448 }
449 return documentDictionaryService;
450 }
451
452 public void setDocumentDictionaryService(DocumentDictionaryService documentDictionaryService) {
453 this.documentDictionaryService = documentDictionaryService;
454 }
455 }