1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.maintenance;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException;
20 import org.kuali.rice.core.api.CoreApiServiceLocator;
21 import org.kuali.rice.core.api.encryption.EncryptionService;
22 import org.kuali.rice.kim.api.identity.Person;
23 import org.kuali.rice.krad.bo.AdHocRoutePerson;
24 import org.kuali.rice.krad.bo.AdHocRouteWorkgroup;
25 import org.kuali.rice.krad.bo.BusinessObject;
26 import org.kuali.rice.krad.bo.DocumentHeader;
27 import org.kuali.rice.krad.bo.Note;
28 import org.kuali.rice.krad.bo.PersistableBusinessObject;
29 import org.kuali.rice.krad.exception.PessimisticLockingException;
30 import org.kuali.rice.krad.service.BusinessObjectService;
31 import org.kuali.rice.krad.service.DataObjectAuthorizationService;
32 import org.kuali.rice.krad.service.DataObjectMetaDataService;
33 import org.kuali.rice.krad.service.DocumentDictionaryService;
34 import org.kuali.rice.krad.service.KRADServiceLocator;
35 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
36 import org.kuali.rice.krad.service.LookupService;
37 import org.kuali.rice.krad.service.MaintenanceDocumentService;
38 import org.kuali.rice.krad.uif.container.CollectionGroup;
39 import org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl;
40 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
41 import org.kuali.rice.krad.uif.view.View;
42 import org.kuali.rice.krad.util.KRADConstants;
43 import org.kuali.rice.krad.util.ObjectUtils;
44 import org.kuali.rice.krad.web.form.MaintenanceDocumentForm;
45
46 import java.security.GeneralSecurityException;
47 import java.util.ArrayList;
48 import java.util.Collection;
49 import java.util.Iterator;
50 import java.util.List;
51 import java.util.Map;
52
53
54
55
56
57
58 public class MaintainableImpl extends ViewHelperServiceImpl implements Maintainable {
59 private static final long serialVersionUID = 9125271369161634992L;
60
61 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(MaintainableImpl.class);
62
63 private String documentNumber;
64 private Object dataObject;
65 private Class<?> dataObjectClass;
66 private String maintenanceAction;
67
68 private transient LookupService lookupService;
69 private transient DataObjectAuthorizationService dataObjectAuthorizationService;
70 private transient DataObjectMetaDataService dataObjectMetaDataService;
71 private transient DocumentDictionaryService documentDictionaryService;
72 private transient EncryptionService encryptionService;
73 private transient BusinessObjectService businessObjectService;
74 private transient MaintenanceDocumentService maintenanceDocumentService;
75
76
77
78
79 @Override
80 public Object retrieveObjectForEditOrCopy(MaintenanceDocument document, Map<String, String> dataObjectKeys) {
81 Object dataObject = null;
82
83 try {
84 dataObject = getLookupService().findObjectBySearch(getDataObjectClass(), dataObjectKeys);
85 } catch (ClassNotPersistenceCapableException ex) {
86 if (!document.getOldMaintainableObject().isExternalBusinessObject()) {
87 throw new RuntimeException("Data Object Class: "
88 + getDataObjectClass()
89 + " is not persistable and is not externalizable - configuration error");
90 }
91
92 }
93
94 return dataObject;
95 }
96
97
98
99
100 @Override
101 public void setDocumentNumber(String documentNumber) {
102 this.documentNumber = documentNumber;
103 }
104
105
106
107
108 @Override
109 public String getDocumentTitle(MaintenanceDocument document) {
110
111
112 return "";
113 }
114
115
116
117
118 @Override
119 public Object getDataObject() {
120 return dataObject;
121 }
122
123
124
125
126 @Override
127 public void setDataObject(Object object) {
128 this.dataObject = object;
129 }
130
131
132
133
134 @Override
135 public Class getDataObjectClass() {
136 return dataObjectClass;
137 }
138
139
140
141
142 @Override
143 public void setDataObjectClass(Class dataObjectClass) {
144 this.dataObjectClass = dataObjectClass;
145 }
146
147
148
149
150
151
152 @Override
153 public boolean isLockable() {
154 return KRADServiceLocator.getPersistenceStructureService().isPersistable(getDataObject().getClass());
155 }
156
157
158
159
160
161
162 @Override
163 public PersistableBusinessObject getPersistableBusinessObject() {
164 if (KRADServiceLocator.getPersistenceStructureService().isPersistable(getDataObject().getClass())) {
165 return (PersistableBusinessObject) getDataObject();
166 } else {
167 return null;
168 }
169
170 }
171
172
173
174
175 @Override
176 public String getMaintenanceAction() {
177 return maintenanceAction;
178 }
179
180
181
182
183 @Override
184 public void setMaintenanceAction(String maintenanceAction) {
185 this.maintenanceAction = maintenanceAction;
186 }
187
188
189
190
191
192
193
194 @Override
195 public List<MaintenanceLock> generateMaintenanceLocks() {
196 List<MaintenanceLock> maintenanceLocks = new ArrayList<MaintenanceLock>();
197 StringBuffer lockRepresentation = new StringBuffer(dataObjectClass.getName());
198 lockRepresentation.append(KRADConstants.Maintenance.LOCK_AFTER_CLASS_DELIM);
199
200 Object bo = getDataObject();
201 List keyFieldNames = getDocumentDictionaryService().getLockingKeys(getDocumentTypeName());
202
203 for (Iterator i = keyFieldNames.iterator(); i.hasNext(); ) {
204 String fieldName = (String) i.next();
205 Object fieldValue = ObjectUtils.getPropertyValue(bo, fieldName);
206 if (fieldValue == null) {
207 fieldValue = "";
208 }
209
210
211 if (getDataObjectAuthorizationService()
212 .attributeValueNeedsToBeEncryptedOnFormsAndLinks(dataObjectClass, fieldName)) {
213 try {
214 fieldValue = getEncryptionService().encrypt(fieldValue);
215 } catch (GeneralSecurityException e) {
216 LOG.error("Unable to encrypt secure field for locking representation " + e.getMessage());
217 throw new RuntimeException(
218 "Unable to encrypt secure field for locking representation " + e.getMessage());
219 }
220 }
221
222 lockRepresentation.append(fieldName);
223 lockRepresentation.append(KRADConstants.Maintenance.LOCK_AFTER_FIELDNAME_DELIM);
224 lockRepresentation.append(String.valueOf(fieldValue));
225 if (i.hasNext()) {
226 lockRepresentation.append(KRADConstants.Maintenance.LOCK_AFTER_VALUE_DELIM);
227 }
228 }
229
230 MaintenanceLock maintenanceLock = new MaintenanceLock();
231 maintenanceLock.setDocumentNumber(documentNumber);
232 maintenanceLock.setLockingRepresentation(lockRepresentation.toString());
233 maintenanceLocks.add(maintenanceLock);
234
235 return maintenanceLocks;
236 }
237
238
239
240
241
242 protected String getDocumentTypeName() {
243 return getDocumentDictionaryService().getMaintenanceDocumentTypeName(dataObjectClass);
244 }
245
246
247
248
249 @Override
250 public void saveDataObject() {
251 if (dataObject instanceof PersistableBusinessObject) {
252 getBusinessObjectService().linkAndSave((PersistableBusinessObject) dataObject);
253 } else {
254 throw new RuntimeException(
255 "Cannot save object of type: " + dataObjectClass + " with business object service");
256 }
257 }
258
259
260
261
262 @Override
263 public void deleteDataObject() {
264 if (dataObject == null) {
265 return;
266 }
267
268 if (dataObject instanceof PersistableBusinessObject) {
269 getBusinessObjectService().delete((PersistableBusinessObject) dataObject);
270 dataObject = null;
271 } else {
272 throw new RuntimeException(
273 "Cannot delete object of type: " + dataObjectClass + " with business object service");
274 }
275 }
276
277
278
279
280 @Override
281 public void doRouteStatusChange(DocumentHeader documentHeader) {
282
283 }
284
285
286
287
288 @Override
289 public String getLockingDocumentId() {
290 return getMaintenanceDocumentService().getLockingDocumentId(this, documentNumber);
291 }
292
293
294
295
296 @Override
297 public List<String> getWorkflowEngineDocumentIdsToLock() {
298 return null;
299 }
300
301
302
303
304
305
306
307
308
309 @Override
310 public boolean useCustomLockDescriptors() {
311 return false;
312 }
313
314
315
316
317
318
319
320
321 @Override
322 public String getCustomLockDescriptor(Person user) {
323 throw new PessimisticLockingException("The Maintainable for document " + documentNumber +
324 " is using pessimistic locking with custom lock descriptors, but the Maintainable has not overridden the getCustomLockDescriptor method");
325 }
326
327
328
329
330 @Override
331 public boolean isNotesEnabled() {
332 return getDataObjectMetaDataService().areNotesSupported(dataObjectClass);
333 }
334
335
336
337
338 @Override
339 public boolean isExternalBusinessObject() {
340 return false;
341 }
342
343
344
345
346 @Override
347 public void prepareExternalBusinessObject(BusinessObject businessObject) {
348
349 }
350
351
352
353
354
355
356 @Override
357 public boolean isOldDataObjectInDocument() {
358 boolean isOldDataObjectInExistence = true;
359
360 if (getDataObject() == null) {
361 isOldDataObjectInExistence = false;
362 } else {
363 Map<String, ?> keyFieldValues = getDataObjectMetaDataService().getPrimaryKeyFieldValues(getDataObject());
364 for (Object keyValue : keyFieldValues.values()) {
365 if (keyValue == null) {
366 isOldDataObjectInExistence = false;
367 } else if ((keyValue instanceof String) && StringUtils.isBlank((String) keyValue)) {
368 isOldDataObjectInExistence = false;
369 }
370
371 if (!isOldDataObjectInExistence) {
372 break;
373 }
374 }
375 }
376
377 return isOldDataObjectInExistence;
378 }
379
380
381
382
383 @Override
384 public void prepareForSave() {
385
386 }
387
388
389
390
391 @Override
392 public void processAfterRetrieve() {
393
394 }
395
396
397
398
399 @Override
400 public void setupNewFromExisting(MaintenanceDocument document, Map<String, String[]> parameters) {
401
402 }
403
404
405
406
407 @Override
408 public void processAfterCopy(MaintenanceDocument document, Map<String, String[]> requestParameters) {
409
410 }
411
412
413
414
415 @Override
416 public void processAfterEdit(MaintenanceDocument document, Map<String, String[]> requestParameters) {
417
418 }
419
420
421
422
423 @Override
424 public void processAfterNew(MaintenanceDocument document, Map<String, String[]> requestParameters) {
425
426 }
427
428
429
430
431 @Override
432 public void processAfterPost(MaintenanceDocument document, Map<String, String[]> requestParameters) {
433
434 }
435
436
437
438
439
440
441
442
443
444
445
446 @Override
447 protected void processAfterAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) {
448 super.processAfterAddLine(view, collectionGroup, model, addLine);
449
450
451 if (model instanceof MaintenanceDocumentForm
452 && KRADConstants.MAINTENANCE_EDIT_ACTION.equals(((MaintenanceDocumentForm)model).getMaintenanceAction()) && !(addLine instanceof Note) && !(addLine instanceof AdHocRoutePerson) && !(addLine instanceof AdHocRouteWorkgroup)) {
453 MaintenanceDocumentForm maintenanceForm = (MaintenanceDocumentForm) model;
454 MaintenanceDocument document = maintenanceForm.getDocument();
455
456
457
458 String bindingPrefix = collectionGroup.getBindingInfo().getBindByNamePrefix();
459 String propertyPath = collectionGroup.getPropertyName();
460 if(bindingPrefix!=""&&bindingPrefix!= null) {
461 propertyPath = bindingPrefix + "." + propertyPath;
462 }
463
464 Collection<Object> oldCollection = ObjectPropertyUtils
465 .getPropertyValue(document.getOldMaintainableObject().getDataObject(),
466 propertyPath);
467
468
469 try {
470 Object blankLine = collectionGroup.getCollectionObjectClass().newInstance();
471
472 if(oldCollection instanceof List){
473 ((List) oldCollection).add(0,blankLine);
474 } else {
475 oldCollection.add(blankLine);
476 }
477 } catch (Exception e) {
478 throw new RuntimeException("Unable to create new line instance for old maintenance object", e);
479 }
480 }
481 }
482
483
484
485
486
487
488
489
490 @Override
491 protected void processAfterDeleteLine(View view, CollectionGroup collectionGroup, Object model, int lineIndex) {
492 super.processAfterDeleteLine(view, collectionGroup, model, lineIndex);
493
494
495 if (model instanceof MaintenanceDocumentForm
496 && KRADConstants.MAINTENANCE_EDIT_ACTION.equals(((MaintenanceDocumentForm)model).getMaintenanceAction())
497 && !collectionGroup.getCollectionObjectClass().getName().equals(Note.class.getName())
498 && !collectionGroup.getCollectionObjectClass().getName().equals(AdHocRoutePerson.class.getName())
499 && !collectionGroup.getCollectionObjectClass().getName().equals(AdHocRouteWorkgroup.class.getName())) {
500 MaintenanceDocumentForm maintenanceForm = (MaintenanceDocumentForm) model;
501 MaintenanceDocument document = maintenanceForm.getDocument();
502
503
504 Collection<Object> oldCollection = ObjectPropertyUtils
505 .getPropertyValue(document.getOldMaintainableObject().getDataObject(),
506 collectionGroup.getPropertyName());
507 try {
508
509 oldCollection.remove(oldCollection.toArray()[lineIndex]);
510 } catch (Exception e) {
511 throw new RuntimeException("Unable to delete line instance for old maintenance object", e);
512 }
513 }
514 }
515
516
517
518
519
520
521 protected String getDocumentNumber() {
522 return this.documentNumber;
523 }
524
525 protected LookupService getLookupService() {
526 if (lookupService == null) {
527 lookupService = KRADServiceLocatorWeb.getLookupService();
528 }
529 return this.lookupService;
530 }
531
532 public void setLookupService(LookupService lookupService) {
533 this.lookupService = lookupService;
534 }
535
536 protected DataObjectAuthorizationService getDataObjectAuthorizationService() {
537 if (dataObjectAuthorizationService == null) {
538 this.dataObjectAuthorizationService = KRADServiceLocatorWeb.getDataObjectAuthorizationService();
539 }
540 return dataObjectAuthorizationService;
541 }
542
543 public void setDataObjectAuthorizationService(DataObjectAuthorizationService dataObjectAuthorizationService) {
544 this.dataObjectAuthorizationService = dataObjectAuthorizationService;
545 }
546
547 protected DataObjectMetaDataService getDataObjectMetaDataService() {
548 if (dataObjectMetaDataService == null) {
549 this.dataObjectMetaDataService = KRADServiceLocatorWeb.getDataObjectMetaDataService();
550 }
551 return dataObjectMetaDataService;
552 }
553
554 public void setDataObjectMetaDataService(DataObjectMetaDataService dataObjectMetaDataService) {
555 this.dataObjectMetaDataService = dataObjectMetaDataService;
556 }
557
558 public DocumentDictionaryService getDocumentDictionaryService() {
559 if (documentDictionaryService == null) {
560 this.documentDictionaryService = KRADServiceLocatorWeb.getDocumentDictionaryService();
561 }
562 return documentDictionaryService;
563 }
564
565 public void setDocumentDictionaryService(DocumentDictionaryService documentDictionaryService) {
566 this.documentDictionaryService = documentDictionaryService;
567 }
568
569 protected EncryptionService getEncryptionService() {
570 if (encryptionService == null) {
571 encryptionService = CoreApiServiceLocator.getEncryptionService();
572 }
573 return encryptionService;
574 }
575
576 public void setEncryptionService(EncryptionService encryptionService) {
577 this.encryptionService = encryptionService;
578 }
579
580 protected BusinessObjectService getBusinessObjectService() {
581 if (businessObjectService == null) {
582 businessObjectService = KRADServiceLocator.getBusinessObjectService();
583 }
584 return businessObjectService;
585 }
586
587 public void setBusinessObjectService(BusinessObjectService businessObjectService) {
588 this.businessObjectService = businessObjectService;
589 }
590
591 protected MaintenanceDocumentService getMaintenanceDocumentService() {
592 if (maintenanceDocumentService == null) {
593 maintenanceDocumentService = KRADServiceLocatorWeb.getMaintenanceDocumentService();
594 }
595 return maintenanceDocumentService;
596 }
597
598 public void setMaintenanceDocumentService(MaintenanceDocumentService maintenanceDocumentService) {
599 this.maintenanceDocumentService = maintenanceDocumentService;
600 }
601 }