View Javadoc
1   /*
2    * Copyright 2008 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl2.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.sys.document.validation.impl;
17  
18  import java.util.Iterator;
19  import java.util.Map;
20  import java.util.Set;
21  
22  import org.apache.commons.lang.StringUtils;
23  import org.kuali.ole.sys.OLEConstants;
24  import org.kuali.ole.sys.OLEKeyConstants;
25  import org.kuali.ole.sys.OLEPropertyConstants;
26  import org.kuali.ole.sys.businessobject.AccountingLine;
27  import org.kuali.ole.sys.businessobject.FinancialSystemDocumentHeader;
28  import org.kuali.ole.sys.document.AccountingDocument;
29  import org.kuali.ole.sys.document.Correctable;
30  import org.kuali.ole.sys.document.authorization.AccountingLineAuthorizer;
31  import org.kuali.ole.sys.document.authorization.AccountingLineAuthorizerBase;
32  import org.kuali.ole.sys.document.datadictionary.AccountingLineGroupDefinition;
33  import org.kuali.ole.sys.document.datadictionary.FinancialSystemTransactionalDocumentEntry;
34  import org.kuali.ole.sys.document.validation.GenericValidation;
35  import org.kuali.ole.sys.document.validation.event.AddAccountingLineEvent;
36  import org.kuali.ole.sys.document.validation.event.AttributedDocumentEvent;
37  import org.kuali.ole.sys.document.validation.event.DeleteAccountingLineEvent;
38  import org.kuali.ole.sys.document.validation.event.UpdateAccountingLineEvent;
39  import org.kuali.rice.kim.api.identity.Person;
40  import org.kuali.rice.krad.service.DataDictionaryService;
41  import org.kuali.rice.krad.rules.rule.event.KualiDocumentEvent;
42  import org.kuali.rice.krad.util.GlobalVariables;
43  
44  /**
45   * A validation that checks whether the given accounting line is accessible to the given user or not
46   */
47  public class AccountingLineAccessibleValidation extends GenericValidation {
48      protected DataDictionaryService dataDictionaryService;
49      protected AccountingDocument accountingDocumentForValidation;
50      protected AccountingLine accountingLineForValidation;
51      
52      /**
53       * Indicates what is being done to an accounting line. This allows the same method to be used for different actions.
54       */
55      public enum AccountingLineAction {
56          ADD(OLEKeyConstants.ERROR_ACCOUNTINGLINE_INACCESSIBLE_ADD), DELETE(OLEKeyConstants.ERROR_ACCOUNTINGLINE_INACCESSIBLE_DELETE), UPDATE(OLEKeyConstants.ERROR_ACCOUNTINGLINE_INACCESSIBLE_UPDATE);
57  
58          public final String accessibilityErrorKey;
59  
60          AccountingLineAction(String accessabilityErrorKey) {
61              this.accessibilityErrorKey = accessabilityErrorKey;
62          }
63      }
64  
65      /**
66       * Validates that the given accounting line is accessible for editing by the current user.
67       * <strong>This method expects a document as the first parameter and an accounting line as the second</strong>
68       * @see org.kuali.ole.sys.document.validation.Validation#validate(java.lang.Object[])
69       */
70      public boolean validate(AttributedDocumentEvent event) {        
71          final Person currentUser = GlobalVariables.getUserSession().getPerson();
72          
73          if (accountingDocumentForValidation instanceof Correctable) {
74              final String errorDocumentNumber = ((FinancialSystemDocumentHeader)accountingDocumentForValidation.getDocumentHeader()).getFinancialDocumentInErrorNumber();
75              if (StringUtils.isNotBlank(errorDocumentNumber))
76                  return true;
77          }
78          
79          final AccountingLineAuthorizer accountingLineAuthorizer = lookupAccountingLineAuthorizer();
80          final boolean lineIsAccessible = accountingLineAuthorizer.hasEditPermissionOnAccountingLine(accountingDocumentForValidation, accountingLineForValidation, getAccountingLineCollectionProperty(), currentUser, true);
81          final boolean isAccessible = accountingLineAuthorizer.hasEditPermissionOnField(accountingDocumentForValidation, accountingLineForValidation, getAccountingLineCollectionProperty(), OLEPropertyConstants.ACCOUNT_NUMBER, lineIsAccessible, true, currentUser);
82  
83          // report errors
84          if (!isAccessible) {
85              final String principalName = currentUser.getPrincipalName();
86              
87              final String[] chartErrorParams = new String[] { getDataDictionaryService().getAttributeLabel(accountingLineForValidation.getClass(), OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE), accountingLineForValidation.getChartOfAccountsCode(),  principalName};
88              GlobalVariables.getMessageMap().putError(OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE, convertEventToMessage(event), chartErrorParams);
89              
90              final String[] accountErrorParams = new String[] { getDataDictionaryService().getAttributeLabel(accountingLineForValidation.getClass(), OLEPropertyConstants.ACCOUNT_NUMBER), accountingLineForValidation.getAccountNumber(), principalName };
91              GlobalVariables.getMessageMap().putError(OLEPropertyConstants.ACCOUNT_NUMBER, convertEventToMessage(event), accountErrorParams);
92          }
93  
94          return isAccessible;
95      }
96      
97      /**
98       * Returns the name of the accounting line group which holds the proper authorizer to do the KIM check
99       * @return the name of the accouting line group to get the authorizer from
100      */
101     protected String getGroupName() {
102         return (accountingLineForValidation.isSourceAccountingLine() ? OLEConstants.SOURCE_ACCOUNTING_LINES_GROUP_NAME : OLEConstants.TARGET_ACCOUNTING_LINES_GROUP_NAME);
103     }
104     
105     /**
106      * @return hopefully, the best accounting line authorizer implementation to do the KIM check for to see if lines are accessible
107      */
108     protected AccountingLineAuthorizer lookupAccountingLineAuthorizer() {
109         final String groupName = getGroupName();
110         final Map<String, AccountingLineGroupDefinition> groups = ((FinancialSystemTransactionalDocumentEntry)dataDictionaryService.getDataDictionary().getDictionaryObjectEntry(accountingDocumentForValidation.getClass().getName())).getAccountingLineGroups();
111         
112         if (groups.isEmpty()) return new AccountingLineAuthorizerBase(); // no groups? just use the default...
113         if (groups.containsKey(groupName)) return groups.get(groupName).getAccountingLineAuthorizer(); // we've got the group
114 
115         final Set<String> groupNames = groups.keySet(); // we've got groups, just not the proper name; try our luck and get the first group iterator
116         final Iterator<String> groupNameIterator = groupNames.iterator();
117         final String firstGroupName = groupNameIterator.next();
118         return groups.get(firstGroupName).getAccountingLineAuthorizer();
119     }
120     
121     /**
122      * Determines the property of the accounting line collection from the error prefixes
123      * @return the accounting line collection property
124      */
125     protected String getAccountingLineCollectionProperty() {
126         String propertyName = null;
127         if (GlobalVariables.getMessageMap().getErrorPath().size() > 0) {
128             propertyName = ((String)GlobalVariables.getMessageMap().getErrorPath().get(0)).replaceFirst(".*?document\\.", "");
129         } else {
130             propertyName = accountingLineForValidation.isSourceAccountingLine() ? OLEConstants.PermissionAttributeValue.SOURCE_ACCOUNTING_LINES.value : OLEConstants.PermissionAttributeValue.TARGET_ACCOUNTING_LINES.value;
131         }
132         if (propertyName.equals("newSourceLine")) return OLEConstants.PermissionAttributeValue.SOURCE_ACCOUNTING_LINES.value;
133         if (propertyName.equals("newTargetLine")) return OLEConstants.PermissionAttributeValue.TARGET_ACCOUNTING_LINES.value;
134         return propertyName;
135     }
136     
137     /**
138      * Determines what error message should be shown based on the event that required this validation
139      * @param event the event to use to determine the error message
140      * @return the key of the error message to display
141      */
142     protected String convertEventToMessage(KualiDocumentEvent event) {
143         if (event instanceof AddAccountingLineEvent) {
144             return AccountingLineAction.ADD.accessibilityErrorKey;
145         } else if (event instanceof UpdateAccountingLineEvent) {
146             return AccountingLineAction.UPDATE.accessibilityErrorKey;
147         } else if (event instanceof DeleteAccountingLineEvent) {
148             return AccountingLineAction.DELETE.accessibilityErrorKey;
149         } else {
150             return "";
151         }
152     }
153 
154     /**
155      * Gets the accountingDocumentForValidation attribute. 
156      * @return Returns the accountingDocumentForValidation.
157      */
158     public AccountingDocument getAccountingDocumentForValidation() {
159         return accountingDocumentForValidation;
160     }
161 
162     /**
163      * Sets the accountingDocumentForValidation attribute value.
164      * @param accountingDocumentForValidation The accountingDocumentForValidation to set.
165      */
166     public void setAccountingDocumentForValidation(AccountingDocument accountingDocumentForValidation) {
167         this.accountingDocumentForValidation = accountingDocumentForValidation;
168     }
169 
170     /**
171      * Gets the accountingLineForValidation attribute. 
172      * @return Returns the accountingLineForValidation.
173      */
174     public AccountingLine getAccountingLineForValidation() {
175         return accountingLineForValidation;
176     }
177 
178     /**
179      * Sets the accountingLineForValidation attribute value.
180      * @param accountingLineForValidation The accountingLineForValidation to set.
181      */
182     public void setAccountingLineForValidation(AccountingLine accountingLineForValidation) {
183         this.accountingLineForValidation = accountingLineForValidation;
184     }
185 
186     /**
187      * Gets the dataDictionaryService attribute. 
188      * @return Returns the dataDictionaryService.
189      */
190     public DataDictionaryService getDataDictionaryService() {
191         return dataDictionaryService;
192     }
193 
194     /**
195      * Sets the dataDictionaryService attribute value.
196      * @param dataDictionaryService The dataDictionaryService to set.
197      */
198     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
199         this.dataDictionaryService = dataDictionaryService;
200     }
201     
202 }
203