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