1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.ole.sys.document.authorization;
17
18 import java.text.MessageFormat;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.kuali.ole.sys.OLEConstants;
28 import org.kuali.ole.sys.OLEKeyConstants;
29 import org.kuali.ole.sys.businessobject.AccountingLine;
30 import org.kuali.ole.sys.businessobject.FinancialSystemDocumentHeader;
31 import org.kuali.ole.sys.context.SpringContext;
32 import org.kuali.ole.sys.document.AccountingDocument;
33 import org.kuali.ole.sys.document.Correctable;
34 import org.kuali.ole.sys.document.web.AccountingLineRenderingContext;
35 import org.kuali.ole.sys.document.web.AccountingLineViewAction;
36 import org.kuali.ole.sys.document.web.AccountingLineViewField;
37 import org.kuali.ole.sys.identity.OleKimAttributes;
38 import org.kuali.rice.core.api.config.property.ConfigurationService;
39 import org.kuali.rice.kew.api.WorkflowDocument;
40 import org.kuali.rice.kim.api.KimConstants;
41 import org.kuali.rice.kim.api.identity.Person;
42 import org.kuali.rice.kns.document.authorization.DocumentAuthorizer;
43 import org.kuali.rice.kns.service.DocumentHelperService;
44 import org.kuali.rice.krad.util.GlobalVariables;
45 import org.kuali.rice.krad.util.KRADConstants;
46 import org.kuali.rice.krad.util.ObjectUtils;
47
48
49
50
51 public class AccountingLineAuthorizerBase implements AccountingLineAuthorizer {
52 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AccountingLineAuthorizerBase.class);
53
54 private static ConfigurationService kualiConfigurationService;
55 protected static String riceImagePath;
56 protected static String kfsImagePath;
57
58
59
60
61
62
63
64
65 public List<AccountingLineViewAction> getActions(AccountingDocument accountingDocument, AccountingLineRenderingContext accountingLineRenderingContext, String accountingLinePropertyName, Integer accountingLineIndex, Person currentUser, String groupTitle) {
66 List<AccountingLineViewAction> actions = new ArrayList<AccountingLineViewAction>();
67
68 if (accountingLineRenderingContext.isEditableLine() || isMessageMapContainingErrorsOnLine(accountingLinePropertyName)) {
69 Map<String, AccountingLineViewAction> actionMap = this.getActionMap(accountingLineRenderingContext, accountingLinePropertyName, accountingLineIndex, groupTitle);
70 actions.addAll(actionMap.values());
71 }
72
73 return actions;
74 }
75
76
77
78
79
80
81 protected boolean isMessageMapContainingErrorsOnLine(String accountingLinePropertyName) {
82 for (Object errorKeyAsObject : GlobalVariables.getMessageMap().getPropertiesWithErrors()) {
83 if (((String)errorKeyAsObject).startsWith(accountingLinePropertyName)) return true;
84 }
85 return false;
86 }
87
88
89
90
91
92
93
94 public Set<String> getUnviewableBlocks(AccountingDocument accountingDocument, AccountingLine accountingLine, boolean newLine, Person currentUser) {
95 return new HashSet<String>();
96 }
97
98
99
100
101
102 public boolean renderNewLine(AccountingDocument accountingDocument, String accountingGroupProperty) {
103 return (accountingDocument.getDocumentHeader().getWorkflowDocument().isInitiated() || accountingDocument.getDocumentHeader().getWorkflowDocument().isSaved());
104 }
105
106
107
108
109
110 public boolean isGroupEditable(AccountingDocument accountingDocument, List<? extends AccountingLineRenderingContext> accountingLineRenderingContexts, Person currentUser) {
111 WorkflowDocument workflowDocument = accountingDocument.getDocumentHeader().getWorkflowDocument();
112 if (workflowDocument.isInitiated() || workflowDocument.isSaved()) {
113 return StringUtils.equalsIgnoreCase( workflowDocument.getInitiatorPrincipalId(), currentUser.getPrincipalId() );
114 }
115
116 for (AccountingLineRenderingContext renderingContext : accountingLineRenderingContexts) {
117 if (renderingContext.isEditableLine()) return true;
118 }
119
120 return false;
121 }
122
123
124
125
126
127
128
129
130
131
132 protected Map<String, AccountingLineViewAction> getActionMap(AccountingLineRenderingContext accountingLineRenderingContext, String accountingLinePropertyName, Integer accountingLineIndex, String groupTitle) {
133 Map<String, AccountingLineViewAction> actionMap = new HashMap<String, AccountingLineViewAction>();
134
135 if (accountingLineIndex == null || accountingLineIndex < 0) {
136 AccountingLineViewAction addAction = this.getAddAction(accountingLineRenderingContext.getAccountingLine(), accountingLinePropertyName, groupTitle);
137 actionMap.put(OLEConstants.INSERT_METHOD, addAction);
138 }
139 else {
140 if (accountingLineRenderingContext.allowDelete()) {
141 AccountingLineViewAction deleteAction = this.getDeleteAction(accountingLineRenderingContext.getAccountingLine(), accountingLinePropertyName, accountingLineIndex, groupTitle);
142 actionMap.put(KRADConstants.DELETE_METHOD, deleteAction);
143 }
144
145 AccountingLineViewAction balanceInquiryAction = this.getBalanceInquiryAction(accountingLineRenderingContext.getAccountingLine(), accountingLinePropertyName, accountingLineIndex, groupTitle);
146 actionMap.put(OLEConstants.PERFORMANCE_BALANCE_INQUIRY_FOR_METHOD, balanceInquiryAction);
147 }
148
149 return actionMap;
150 }
151
152
153
154
155
156
157
158
159
160
161
162
163 public final boolean hasEditPermissionOnField(AccountingDocument accountingDocument, AccountingLine accountingLine, String accountingLineCollectionProperty, String fieldName, boolean editableLine, boolean editablePage, Person currentUser) {
164 if (accountingDocument.getDocumentHeader() != null && accountingDocument.getDocumentHeader().getWorkflowDocument() != null && accountingDocument.getDocumentHeader().getWorkflowDocument().getDocumentTypeName().equalsIgnoreCase(OLEConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER_AMENDMENT) && accountingDocument.getDocumentHeader().getWorkflowDocument().isInitiated()) {
165 return true;
166 }
167 if (!determineEditPermissionOnField(accountingDocument, accountingLine, accountingLineCollectionProperty, fieldName, editablePage)) {
168 return false;
169 }
170
171
172 if (accountingLine.getSequenceNumber() == null) {
173 return true;
174 }
175
176
177 boolean hasEditPermissionOnField = editableLine || this.determineEditPermissionByFieldName(accountingDocument, accountingLine, getKimHappyPropertyNameForField(accountingLineCollectionProperty+"."+fieldName), currentUser);
178 if (hasEditPermissionOnField == false) {
179
180
181 WorkflowDocument workflowDocument = accountingDocument.getDocumentHeader().getWorkflowDocument();
182 if (workflowDocument.isEnroute() && isMessageMapContainingErrorsOnLine(accountingLineCollectionProperty)) return true;
183 }
184 return hasEditPermissionOnField;
185 }
186
187
188
189
190
191
192
193
194
195
196
197 public boolean determineEditPermissionOnField(AccountingDocument accountingDocument, AccountingLine accountingLine, String accountingLineCollectionProperty, String fieldName, boolean editablePage) {
198 if (!editablePage) return false;
199
200 final FinancialSystemDocumentHeader documentHeader = (FinancialSystemDocumentHeader) accountingDocument.getDocumentHeader();
201 final WorkflowDocument workflowDocument = documentHeader.getWorkflowDocument();
202
203
204 if (workflowDocument.isCanceled() || ObjectUtils.isNotNull(documentHeader.getFinancialDocumentInErrorNumber())) {
205 return false;
206 }
207
208 return true;
209 }
210
211
212
213
214
215
216
217
218
219 public final boolean hasEditPermissionOnAccountingLine(AccountingDocument accountingDocument, AccountingLine accountingLine, String accountingLineCollectionProperty, Person currentUser, boolean pageIsEditable) {
220 if (determineEditPermissionOnLine(accountingDocument, accountingLine, accountingLineCollectionProperty, StringUtils.equalsIgnoreCase( accountingDocument.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId(), currentUser.getPrincipalId() ), pageIsEditable)) {
221
222 if (approvedForUnqualifiedEditing(accountingDocument, accountingLine, accountingLineCollectionProperty, StringUtils.equalsIgnoreCase( accountingDocument.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId(), currentUser.getPrincipalId() ))) {
223 return true;
224 }
225
226
227 final String lineFieldName = getKimHappyPropertyNameForField(accountingLineCollectionProperty);
228 return this.determineEditPermissionByFieldName(accountingDocument, accountingLine, lineFieldName, currentUser);
229 }
230 return false;
231 }
232
233
234
235
236
237
238
239
240
241 public boolean determineEditPermissionOnLine(AccountingDocument accountingDocument, AccountingLine accountingLine, String accountingLineCollectionProperty, boolean currentUserIsDocumentInitiator, boolean pageIsEditable) {
242 if (accountingDocument instanceof Correctable) {
243 String errorDocumentNumber = ((FinancialSystemDocumentHeader)accountingDocument.getDocumentHeader()).getFinancialDocumentInErrorNumber();
244 if (StringUtils.isNotBlank(errorDocumentNumber))
245 return false;
246 }
247
248 return true;
249 }
250
251
252
253
254
255
256
257
258
259
260 protected boolean approvedForUnqualifiedEditing(AccountingDocument accountingDocument, AccountingLine accountingLine, String accountingLineCollectionProperty, boolean currentUserIsDocumentInitiator) {
261
262 if (accountingLine.getSequenceNumber() == null) {
263 return true;
264 }
265
266
267 WorkflowDocument workflowDocument = accountingDocument.getDocumentHeader().getWorkflowDocument();
268 if (workflowDocument.isInitiated() || workflowDocument.isSaved()) {
269 return currentUserIsDocumentInitiator;
270 }
271 return false;
272 }
273
274
275
276
277
278
279
280
281
282
283 protected boolean determineEditPermissionByFieldName(AccountingDocument accountingDocument, AccountingLine accountingLine, String fieldName, Person currentUser) {
284 final Map<String,String> roleQualifiers = this.getRoleQualifiers(accountingDocument, accountingLine);
285 final String documentTypeName = accountingDocument.getDocumentHeader().getWorkflowDocument().getDocumentTypeName();
286 final Map<String,String> permissionDetail = this.getPermissionDetails(documentTypeName, fieldName);
287
288 return this.hasEditPermission(accountingDocument, currentUser, permissionDetail, roleQualifiers);
289 }
290
291
292
293
294
295
296
297
298
299
300 protected boolean hasEditPermission(AccountingDocument accountingDocument, Person currentUser, Map<String,String> permissionDetails, Map<String,String> roleQualifiers) {
301 String pricipalId = currentUser.getPrincipalId();
302 DocumentAuthorizer accountingDocumentAuthorizer = this.getDocumentAuthorizer(accountingDocument);
303
304 return accountingDocumentAuthorizer.isAuthorizedByTemplate(accountingDocument, OLEConstants.ParameterNamespaces.OLE, OLEConstants.PermissionTemplate.MODIFY_ACCOUNTING_LINES.name, pricipalId, permissionDetails, roleQualifiers);
305 }
306
307
308
309
310
311
312
313
314 protected Map<String,String> getPermissionDetails(String documentTypeName, String fieldName) {
315 Map<String,String> permissionDetails = new HashMap<String,String>();
316
317 if (StringUtils.isNotBlank(documentTypeName)) {
318 permissionDetails.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, documentTypeName);
319 }
320
321 if (StringUtils.isNotBlank(fieldName)) {
322 permissionDetails.put(KimConstants.AttributeConstants.PROPERTY_NAME, fieldName);
323 }
324
325 return permissionDetails;
326 }
327
328
329
330
331
332
333
334 protected final Map<String,String> getRoleQualifiers(AccountingDocument accountingDocument, AccountingLine accountingLine) {
335 Map<String,String> roleQualifiers = new HashMap<String,String>();
336
337 if (accountingLine != null) {
338 roleQualifiers.put(OleKimAttributes.CHART_OF_ACCOUNTS_CODE, accountingLine.getChartOfAccountsCode());
339 roleQualifiers.put(OleKimAttributes.ACCOUNT_NUMBER, accountingLine.getAccountNumber());
340 }
341
342 return roleQualifiers;
343 }
344
345
346
347
348
349 protected String getKimHappyPropertyNameForField(String convertedName) {
350 convertedName = stripDocumentPrefixFromName(convertedName);
351
352 return replaceCollectionElementsWithPlurals(convertedName);
353 }
354
355
356
357
358
359
360
361 protected String getFieldName(AccountingLineViewField field) {
362 String propertyPrefix = field.getField().getPropertyPrefix();
363 String propertyName = field.getField().getPropertyName();
364
365 return StringUtils.isNotBlank(propertyPrefix) ? (propertyPrefix + "." + propertyName) : propertyName;
366 }
367
368
369
370
371
372
373
374 protected String stripDocumentPrefixFromName(String name) {
375 return name.replaceFirst("(.)*document\\.", StringUtils.EMPTY);
376 }
377
378
379
380
381
382
383
384
385 protected String replaceCollectionElementsWithPlurals(String name) {
386 String temp = name.replaceAll("\\[\\d+\\]", "s");
387
388 if ( temp.endsWith( "ss" ) ) {
389 temp = StringUtils.chop(temp);
390 }
391 return temp;
392 }
393
394
395
396
397
398
399
400
401
402
403 protected AccountingLineViewAction getBalanceInquiryAction(AccountingLine accountingLine, String accountingLinePropertyName, Integer accountingLineIndex, String groupTitle) {
404 String actionMethod = this.getBalanceInquiryMethod(accountingLine, accountingLinePropertyName, accountingLineIndex);
405 String actionLabel = this.getActionLabel(OLEKeyConstants.AccountingLineViewRendering.ACCOUNTING_LINE_BALANCE_INQUIRY_ACTION_LABEL, groupTitle, accountingLineIndex + 1);
406
407 String actionImageName = getKFSImagePath() + "tinybutton-balinquiry.gif";
408
409 return new AccountingLineViewAction(actionMethod, actionLabel, actionImageName);
410 }
411
412
413
414
415
416
417
418
419
420
421 protected AccountingLineViewAction getDeleteAction(AccountingLine accountingLine, String accountingLinePropertyName, Integer accountingLineIndex, String groupTitle) {
422 String actionMethod = this.getDeleteLineMethod(accountingLine, accountingLinePropertyName, accountingLineIndex);
423 String actionLabel = this.getActionLabel(OLEKeyConstants.AccountingLineViewRendering.ACCOUNTING_LINE_DELETE_ACTION_LABEL, groupTitle, accountingLineIndex + 1);
424
425 String actionImageName = getRiceImagePath() + "tinybutton-delete1.gif";
426
427 return new AccountingLineViewAction(actionMethod, actionLabel, actionImageName);
428 }
429
430
431
432
433
434
435
436
437
438
439 protected AccountingLineViewAction getAddAction(AccountingLine accountingLine, String accountingLinePropertyName, String groupTitle) {
440 String actionMethod = this.getAddMethod(accountingLine, accountingLinePropertyName);
441 String actionLabel = this.getActionLabel(OLEKeyConstants.AccountingLineViewRendering.ACCOUNTING_LINE_ADD_ACTION_LABEL, groupTitle);
442
443 String actionImageName = getRiceImagePath() + "tinybutton-add1.gif";
444
445 return new AccountingLineViewAction(actionMethod, actionLabel, actionImageName);
446 }
447
448
449
450
451
452
453
454
455 protected String getActionLabel(String messageKey, Object... values) {
456 String messageBody = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(messageKey);
457
458 return MessageFormat.format(messageBody, values);
459 }
460
461
462
463
464
465
466
467
468 protected String getAddMethod(AccountingLine accountingLine, String accountingLineProperty) {
469 final String infix = getActionInfixForNewAccountingLine(accountingLine, accountingLineProperty);
470 return OLEConstants.INSERT_METHOD + infix + "Line.anchoraccounting" + infix + "Anchor";
471 }
472
473
474
475
476
477
478
479
480
481 protected String getDeleteLineMethod(AccountingLine accountingLine, String accountingLineProperty, Integer accountingLineIndex) {
482 final String infix = getActionInfixForExtantAccountingLine(accountingLine, accountingLineProperty);
483 return KRADConstants.DELETE_METHOD + infix + "Line.line" + accountingLineIndex + ".anchoraccounting" + infix + "Anchor";
484 }
485
486
487
488
489
490
491
492
493
494 protected String getBalanceInquiryMethod(AccountingLine accountingLine, String accountingLineProperty, Integer accountingLineIndex) {
495 final String infix = getActionInfixForExtantAccountingLine(accountingLine, accountingLineProperty);
496 return OLEConstants.PERFORMANCE_BALANCE_INQUIRY_FOR_METHOD + infix + "Line.line" + accountingLineIndex + ".anchoraccounting" + infix + "existingLineLineAnchor" + accountingLineIndex;
497 }
498
499
500
501
502
503
504
505
506 protected String getActionInfixForNewAccountingLine(AccountingLine accountingLine, String accountingLinePropertyName) {
507 if (accountingLine.isSourceAccountingLine()) {
508 return OLEConstants.SOURCE;
509 }
510
511 if (accountingLine.isTargetAccountingLine()) {
512 return OLEConstants.TARGET;
513 }
514
515 return OLEConstants.EMPTY_STRING;
516 }
517
518
519
520
521
522
523
524
525
526 protected String getActionInfixForExtantAccountingLine(AccountingLine accountingLine, String accountingLinePropertyName) {
527 if (accountingLine.isSourceAccountingLine()) {
528 return OLEConstants.SOURCE;
529 }
530
531 if (accountingLine.isTargetAccountingLine()) {
532 return OLEConstants.TARGET;
533 }
534
535 return OLEConstants.EMPTY_STRING;
536 }
537
538
539
540
541
542
543
544 protected DocumentAuthorizer getDocumentAuthorizer(AccountingDocument accountingDocument) {
545 return SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(accountingDocument);
546 }
547
548
549
550
551 protected String getRiceImagePath() {
552 if (riceImagePath == null) {
553 riceImagePath = getConfigurationService().getPropertyValueAsString(KRADConstants.EXTERNALIZABLE_IMAGES_URL_KEY);
554 }
555 return riceImagePath;
556 }
557
558
559
560
561 protected String getKFSImagePath() {
562 if (kfsImagePath == null) {
563 kfsImagePath = getConfigurationService().getPropertyValueAsString(KRADConstants.APPLICATION_EXTERNALIZABLE_IMAGES_URL_KEY);
564 }
565 return kfsImagePath;
566 }
567
568 protected ConfigurationService getConfigurationService() {
569 if ( kualiConfigurationService == null ) {
570 kualiConfigurationService = SpringContext.getBean(ConfigurationService.class);
571 }
572 return kualiConfigurationService;
573 }
574 }