1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package org.kuali.ole.gl.service.impl;
17  
18  import java.io.IOException;
19  import java.io.PrintStream;
20  import java.util.Collection;
21  import java.util.Iterator;
22  import java.util.LinkedHashMap;
23  import java.util.Map;
24  import java.util.Map.Entry;
25  import java.util.Set;
26  import java.util.TreeSet;
27  
28  import org.apache.commons.lang.StringUtils;
29  import org.kuali.ole.coa.businessobject.Account;
30  import org.kuali.ole.coa.service.AccountService;
31  import org.kuali.ole.gl.GeneralLedgerConstants;
32  import org.kuali.ole.gl.report.PreScrubberReportData;
33  import org.kuali.ole.gl.service.PreScrubberService;
34  import org.kuali.ole.sys.OLEConstants.SystemGroupParameterNames;
35  import org.kuali.ole.sys.context.SpringContext;
36  import org.kuali.ole.sys.service.impl.OleParameterConstants;
37  import org.kuali.ole.sys.util.TransactionalServiceUtils;
38  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
39  
40  
41  
42  
43  
44  public class PreScrubberServiceImpl implements PreScrubberService {
45      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PreScrubberServiceImpl.class);
46      
47      private int maxCacheSize = 10000;
48      private ParameterService parameterService;
49      
50      public PreScrubberReportData preprocessOriginEntries(Iterator<String> inputOriginEntries, String outputFileName) throws IOException {
51          PrintStream outputStream = new PrintStream(outputFileName);
52          
53          Map<String, String> chartCodeCache = new LinkedHashMap<String, String>() {
54              @Override
55              protected boolean removeEldestEntry(Entry<String, String> eldest) {
56                  return size() > getMaxCacheSize();
57              }
58          };
59          
60          Set<String> nonExistentAccountCache = new TreeSet<String>();
61          Set<String> multipleAccountCache = new TreeSet<String>();
62          
63          AccountService accountService = SpringContext.getBean(AccountService.class);
64          ParameterService parameterService = SpringContext.getBean(ParameterService.class);
65          boolean fillInChartCodesIfSpaces = deriveChartOfAccountsCodeIfSpaces();
66          
67          int inputLines = 0;
68          int outputLines = 0;
69          
70          try {
71              while (inputOriginEntries.hasNext()) {
72                  inputLines++;
73                  
74                  String originEntry = inputOriginEntries.next();
75                  String outputLine = originEntry;
76                  if (fillInChartCodesIfSpaces && originEntry.length() >= getExclusiveAccountNumberEndPosition()) {
77                      String chartOfAccountsCode = originEntry.substring(getInclusiveChartOfAccountsCodeStartPosition(), getExclusiveChartOfAccountsCodeEndPosition());
78                      if (GeneralLedgerConstants.getSpaceChartOfAccountsCode().equals(chartOfAccountsCode)) {
79                          
80                          String accountNumber = originEntry.substring(getInclusiveAccountNumberStartPosition(), getExclusiveAccountNumberEndPosition());
81                          if (StringUtils.isNotEmpty(accountNumber)) {
82                              String replacementChartOfAccountsCode = null;
83                              boolean nonExistent = false;
84                              boolean multipleFound = false;
85                              
86                              if (chartCodeCache.containsKey(accountNumber))
87                                  replacementChartOfAccountsCode = chartCodeCache.get(accountNumber);
88                              else if (nonExistentAccountCache.contains(accountNumber))
89                                  nonExistent = true;
90                              else if (multipleAccountCache.contains(accountNumber))
91                                  multipleFound = true;
92                              else {
93                                  Collection<Account> results = accountService.getAccountsForAccountNumber(accountNumber);
94                                  
95                                  if (results.isEmpty()) {
96                                      nonExistent = true;
97                                      nonExistentAccountCache.add(accountNumber);
98                                      LOG.warn("Could not find account record for account number " + accountNumber);
99                                  }
100                                 else {
101                                     Iterator<Account> accounts = results.iterator();
102                                     Account account = accounts.next();
103                                     if (accounts.hasNext()) {
104                                         LOG.warn("Multiple chart codes found for account number " + accountNumber + ", not filling in chart code for this account");
105                                         TransactionalServiceUtils.exhaustIterator(accounts);
106                                         multipleAccountCache.add(accountNumber);
107                                         multipleFound = true;
108                                     }
109                                     else {
110                                         replacementChartOfAccountsCode = account.getChartOfAccountsCode();
111                                         chartCodeCache.put(accountNumber, replacementChartOfAccountsCode);
112                                     }
113                                 }
114                             }
115                             
116                             if (!nonExistent && !multipleFound) {
117                                 StringBuilder buf = new StringBuilder(originEntry.length());
118                                 buf.append(originEntry.substring(0, getInclusiveChartOfAccountsCodeStartPosition()));
119                                 buf.append(replacementChartOfAccountsCode);
120                                 buf.append(originEntry.subSequence(getExclusiveChartOfAccountsCodeEndPosition(), originEntry.length()));
121                                 outputLine = buf.toString();
122                             }
123                         }
124                     }
125                 }
126                 outputStream.printf("%s\n", outputLine);
127                 outputLines++;
128             }
129         }
130         finally {
131             outputStream.close();
132         }
133         return new PreScrubberReportData(inputLines, outputLines, nonExistentAccountCache, multipleAccountCache);
134     }
135     
136     
137 
138 
139 
140     protected int getInclusiveChartOfAccountsCodeStartPosition() {
141         return 4;
142     }
143     
144     
145 
146 
147 
148     protected int getExclusiveChartOfAccountsCodeEndPosition() {
149         return 6;
150     }
151     
152     
153 
154 
155 
156     protected int getInclusiveAccountNumberStartPosition() {
157         return 6;
158     }
159     
160     
161 
162 
163 
164     protected int getExclusiveAccountNumberEndPosition() {
165         return 13;
166     }
167     
168     public int getMaxCacheSize() {
169         return maxCacheSize;
170     }
171 
172     public void setMaxCacheSize(int maxCacheSize) {
173         this.maxCacheSize = maxCacheSize;
174     }
175     
176     
177 
178 
179     public boolean deriveChartOfAccountsCodeIfSpaces() {
180         return !parameterService.getParameterValueAsBoolean(OleParameterConstants.FINANCIAL_SYSTEM_ALL.class, SystemGroupParameterNames.ACCOUNTS_CAN_CROSS_CHARTS_IND);
181     }
182 
183     
184 
185 
186 
187     public void setParameterService(ParameterService parameterService) {
188         this.parameterService = parameterService;
189     }
190 }