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