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 (!determineEditPermissionOnField(accountingDocument, accountingLine, accountingLineCollectionProperty, fieldName, editablePage)) {
165 return false;
166 }
167
168
169 if (accountingLine.getSequenceNumber() == null) {
170 return true;
171 }
172
173
174 boolean hasEditPermissionOnField = editableLine || this.determineEditPermissionByFieldName(accountingDocument, accountingLine, getKimHappyPropertyNameForField(accountingLineCollectionProperty+"."+fieldName), currentUser);
175 if (hasEditPermissionOnField == false) {
176
177
178 WorkflowDocument workflowDocument = accountingDocument.getDocumentHeader().getWorkflowDocument();
179 if (workflowDocument.isEnroute() && isMessageMapContainingErrorsOnLine(accountingLineCollectionProperty)) return true;
180 }
181 return hasEditPermissionOnField;
182 }
183
184
185
186
187
188
189
190
191
192
193
194 public boolean determineEditPermissionOnField(AccountingDocument accountingDocument, AccountingLine accountingLine, String accountingLineCollectionProperty, String fieldName, boolean editablePage) {
195 if (!editablePage) return false;
196
197
198 final FinancialSystemDocumentHeader documentHeader = (FinancialSystemDocumentHeader) accountingDocument;
199 final WorkflowDocument workflowDocument = documentHeader.getWorkflowDocument();
200
201
202 if (workflowDocument.isCanceled() || ObjectUtils.isNotNull(documentHeader.getFinancialDocumentInErrorNumber())) {
203 return false;
204 }
205
206 return true;
207 }
208
209
210
211
212
213
214
215
216
217 public final boolean hasEditPermissionOnAccountingLine(AccountingDocument accountingDocument, AccountingLine accountingLine, String accountingLineCollectionProperty, Person currentUser, boolean pageIsEditable) {
218 if (determineEditPermissionOnLine(accountingDocument, accountingLine, accountingLineCollectionProperty, StringUtils.equalsIgnoreCase( accountingDocument.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId(), currentUser.getPrincipalId() ), pageIsEditable)) {
219
220 if (approvedForUnqualifiedEditing(accountingDocument, accountingLine, accountingLineCollectionProperty, StringUtils.equalsIgnoreCase( accountingDocument.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId(), currentUser.getPrincipalId() ))) {
221 return true;
222 }
223
224
225 final String lineFieldName = getKimHappyPropertyNameForField(accountingLineCollectionProperty);
226 return this.determineEditPermissionByFieldName(accountingDocument, accountingLine, lineFieldName, currentUser);
227 }
228 return false;
229 }
230
231
232
233
234
235
236
237
238
239 public boolean determineEditPermissionOnLine(AccountingDocument accountingDocument, AccountingLine accountingLine, String accountingLineCollectionProperty, boolean currentUserIsDocumentInitiator, boolean pageIsEditable) {
240 if (accountingDocument instanceof Correctable) {
241
242 String errorDocumentNumber = ((FinancialSystemDocumentHeader)accountingDocument).getFinancialDocumentInErrorNumber();
243 if (StringUtils.isNotBlank(errorDocumentNumber))
244 return false;
245 }
246
247 return true;
248 }
249
250
251
252
253
254
255
256
257
258
259 protected boolean approvedForUnqualifiedEditing(AccountingDocument accountingDocument, AccountingLine accountingLine, String accountingLineCollectionProperty, boolean currentUserIsDocumentInitiator) {
260
261 if (accountingLine.getSequenceNumber() == null) {
262 return true;
263 }
264
265
266 WorkflowDocument workflowDocument = accountingDocument.getDocumentHeader().getWorkflowDocument();
267 if (workflowDocument.isInitiated() || workflowDocument.isSaved()) {
268 return currentUserIsDocumentInitiator;
269 }
270 return false;
271 }
272
273
274
275
276
277
278
279
280
281
282 protected boolean determineEditPermissionByFieldName(AccountingDocument accountingDocument, AccountingLine accountingLine, String fieldName, Person currentUser) {
283 final Map<String,String> roleQualifiers = this.getRoleQualifiers(accountingDocument, accountingLine);
284 final String documentTypeName = accountingDocument.getDocumentHeader().getWorkflowDocument().getDocumentTypeName();
285 final Map<String,String> permissionDetail = this.getPermissionDetails(documentTypeName, fieldName);
286
287 return this.hasEditPermission(accountingDocument, currentUser, permissionDetail, roleQualifiers);
288 }
289
290
291
292
293
294
295
296
297
298
299 protected boolean hasEditPermission(AccountingDocument accountingDocument, Person currentUser, Map<String,String> permissionDetails, Map<String,String> roleQualifiers) {
300 String pricipalId = currentUser.getPrincipalId();
301 DocumentAuthorizer accountingDocumentAuthorizer = this.getDocumentAuthorizer(accountingDocument);
302
303 return accountingDocumentAuthorizer.isAuthorizedByTemplate(accountingDocument, OLEConstants.ParameterNamespaces.OLE, OLEConstants.PermissionTemplate.MODIFY_ACCOUNTING_LINES.name, pricipalId, permissionDetails, roleQualifiers);
304 }
305
306
307
308
309
310
311
312
313 protected Map<String,String> getPermissionDetails(String documentTypeName, String fieldName) {
314 Map<String,String> permissionDetails = new HashMap<String,String>();
315
316 if (StringUtils.isNotBlank(documentTypeName)) {
317 permissionDetails.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, documentTypeName);
318 }
319
320 if (StringUtils.isNotBlank(fieldName)) {
321 permissionDetails.put(KimConstants.AttributeConstants.PROPERTY_NAME, fieldName);
322 }
323
324 return permissionDetails;
325 }
326
327
328
329
330
331
332
333 protected final Map<String,String> getRoleQualifiers(AccountingDocument accountingDocument, AccountingLine accountingLine) {
334 Map<String,String> roleQualifiers = new HashMap<String,String>();
335
336 if (accountingLine != null) {
337 roleQualifiers.put(OleKimAttributes.CHART_OF_ACCOUNTS_CODE, accountingLine.getChartOfAccountsCode());
338 roleQualifiers.put(OleKimAttributes.ACCOUNT_NUMBER, accountingLine.getAccountNumber());
339 }
340
341 return roleQualifiers;
342 }
343
344
345
346
347
348 protected String getKimHappyPropertyNameForField(String convertedName) {
349 convertedName = stripDocumentPrefixFromName(convertedName);
350
351 return replaceCollectionElementsWithPlurals(convertedName);
352 }
353
354
355
356
357
358
359
360 protected String getFieldName(AccountingLineViewField field) {
361 String propertyPrefix = field.getField().getPropertyPrefix();
362 String propertyName = field.getField().getPropertyName();
363
364 return StringUtils.isNotBlank(propertyPrefix) ? (propertyPrefix + "." + propertyName) : propertyName;
365 }
366
367
368
369
370
371
372
373 protected String stripDocumentPrefixFromName(String name) {
374 return name.replaceFirst("(.)*document\\.", StringUtils.EMPTY);
375 }
376
377
378
379
380
381
382
383
384 protected String replaceCollectionElementsWithPlurals(String name) {
385 String temp = name.replaceAll("\\[\\d+\\]", "s");
386
387 if ( temp.endsWith( "ss" ) ) {
388 temp = StringUtils.chop(temp);
389 }
390 return temp;
391 }
392
393
394
395
396
397
398
399
400
401
402 protected AccountingLineViewAction getBalanceInquiryAction(AccountingLine accountingLine, String accountingLinePropertyName, Integer accountingLineIndex, String groupTitle) {
403 String actionMethod = this.getBalanceInquiryMethod(accountingLine, accountingLinePropertyName, accountingLineIndex);
404 String actionLabel = this.getActionLabel(OLEKeyConstants.AccountingLineViewRendering.ACCOUNTING_LINE_BALANCE_INQUIRY_ACTION_LABEL, groupTitle, accountingLineIndex + 1);
405
406 String actionImageName = getKFSImagePath() + "tinybutton-balinquiry.gif";
407
408 return new AccountingLineViewAction(actionMethod, actionLabel, actionImageName);
409 }
410
411
412
413
414
415
416
417
418
419
420 protected AccountingLineViewAction getDeleteAction(AccountingLine accountingLine, String accountingLinePropertyName, Integer accountingLineIndex, String groupTitle) {
421 String actionMethod = this.getDeleteLineMethod(accountingLine, accountingLinePropertyName, accountingLineIndex);
422 String actionLabel = this.getActionLabel(OLEKeyConstants.AccountingLineViewRendering.ACCOUNTING_LINE_DELETE_ACTION_LABEL, groupTitle, accountingLineIndex + 1);
423
424 String actionImageName = getRiceImagePath() + "tinybutton-delete1.gif";
425
426 return new AccountingLineViewAction(actionMethod, actionLabel, actionImageName);
427 }
428
429
430
431
432
433
434
435
436
437
438 protected AccountingLineViewAction getAddAction(AccountingLine accountingLine, String accountingLinePropertyName, String groupTitle) {
439 String actionMethod = this.getAddMethod(accountingLine, accountingLinePropertyName);
440 String actionLabel = this.getActionLabel(OLEKeyConstants.AccountingLineViewRendering.ACCOUNTING_LINE_ADD_ACTION_LABEL, groupTitle);
441
442 String actionImageName = getRiceImagePath() + "tinybutton-add1.gif";
443
444 return new AccountingLineViewAction(actionMethod, actionLabel, actionImageName);
445 }
446
447
448
449
450
451
452
453
454 protected String getActionLabel(String messageKey, Object... values) {
455 String messageBody = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(messageKey);
456
457 return MessageFormat.format(messageBody, values);
458 }
459
460
461
462
463
464
465
466
467 protected String getAddMethod(AccountingLine accountingLine, String accountingLineProperty) {
468 final String infix = getActionInfixForNewAccountingLine(accountingLine, accountingLineProperty);
469 return OLEConstants.INSERT_METHOD + infix + "Line.anchoraccounting" + infix + "Anchor";
470 }
471
472
473
474
475
476
477
478
479
480 protected String getDeleteLineMethod(AccountingLine accountingLine, String accountingLineProperty, Integer accountingLineIndex) {
481 final String infix = getActionInfixForExtantAccountingLine(accountingLine, accountingLineProperty);
482 return KRADConstants.DELETE_METHOD + infix + "Line.line" + accountingLineIndex + ".anchoraccounting" + infix + "Anchor";
483 }
484
485
486
487
488
489
490
491
492
493 protected String getBalanceInquiryMethod(AccountingLine accountingLine, String accountingLineProperty, Integer accountingLineIndex) {
494 final String infix = getActionInfixForExtantAccountingLine(accountingLine, accountingLineProperty);
495 return OLEConstants.PERFORMANCE_BALANCE_INQUIRY_FOR_METHOD + infix + "Line.line" + accountingLineIndex + ".anchoraccounting" + infix + "existingLineLineAnchor" + accountingLineIndex;
496 }
497
498
499
500
501
502
503
504
505 protected String getActionInfixForNewAccountingLine(AccountingLine accountingLine, String accountingLinePropertyName) {
506 if (accountingLine.isSourceAccountingLine()) {
507 return OLEConstants.SOURCE;
508 }
509
510 if (accountingLine.isTargetAccountingLine()) {
511 return OLEConstants.TARGET;
512 }
513
514 return OLEConstants.EMPTY_STRING;
515 }
516
517
518
519
520
521
522
523
524
525 protected String getActionInfixForExtantAccountingLine(AccountingLine accountingLine, String accountingLinePropertyName) {
526 if (accountingLine.isSourceAccountingLine()) {
527 return OLEConstants.SOURCE;
528 }
529
530 if (accountingLine.isTargetAccountingLine()) {
531 return OLEConstants.TARGET;
532 }
533
534 return OLEConstants.EMPTY_STRING;
535 }
536
537
538
539
540
541
542
543 protected DocumentAuthorizer getDocumentAuthorizer(AccountingDocument accountingDocument) {
544 return SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(accountingDocument);
545 }
546
547
548
549
550 protected String getRiceImagePath() {
551 if (riceImagePath == null) {
552 riceImagePath = getConfigurationService().getPropertyValueAsString(KRADConstants.EXTERNALIZABLE_IMAGES_URL_KEY);
553 }
554 return riceImagePath;
555 }
556
557
558
559
560 protected String getKFSImagePath() {
561 if (kfsImagePath == null) {
562 kfsImagePath = getConfigurationService().getPropertyValueAsString(KRADConstants.APPLICATION_EXTERNALIZABLE_IMAGES_URL_KEY);
563 }
564 return kfsImagePath;
565 }
566
567 protected ConfigurationService getConfigurationService() {
568 if ( kualiConfigurationService == null ) {
569 kualiConfigurationService = SpringContext.getBean(ConfigurationService.class);
570 }
571 return kualiConfigurationService;
572 }
573 }