View Javadoc
1   /*
2    * Copyright 2009 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.workflow;
17  
18  import java.sql.*;
19  import java.text.DateFormat;
20  import java.text.ParseException;
21  import java.text.SimpleDateFormat;
22  import java.util.*;
23  
24  import org.apache.commons.lang.StringUtils;
25  import org.kuali.ole.DocumentUniqueIDPrefix;
26  import org.kuali.ole.coa.businessobject.Account;
27  import org.kuali.ole.coa.businessobject.Organization;
28  import org.kuali.ole.module.purap.businessobject.PurApItem;
29  import org.kuali.ole.module.purap.businessobject.ReceivingItem;
30  import org.kuali.ole.module.purap.document.PurchaseOrderDocument;
31  import org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument;
32  import org.kuali.ole.module.purap.document.ReceivingDocument;
33  import org.kuali.ole.module.purap.document.RequisitionDocument;
34  import org.kuali.ole.select.OleSelectConstant;
35  import org.kuali.ole.select.bo.OLELinkPurapDonor;
36  import org.kuali.ole.select.businessobject.*;
37  import org.kuali.ole.select.document.OleCorrectionReceivingDocument;
38  import org.kuali.ole.select.document.OleInvoiceDocument;
39  import org.kuali.ole.select.document.OleLineItemReceivingDocument;
40  import org.kuali.ole.select.document.OlePaymentRequestDocument;
41  import org.kuali.ole.sys.OLEPropertyConstants;
42  import org.kuali.ole.sys.businessobject.AccountingLine;
43  import org.kuali.ole.sys.businessobject.FinancialSystemDocumentHeader;
44  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry;
45  import org.kuali.ole.sys.businessobject.SourceAccountingLine;
46  import org.kuali.ole.sys.context.SpringContext;
47  import org.kuali.ole.sys.document.AccountingDocument;
48  import org.kuali.ole.sys.document.AmountTotaling;
49  import org.kuali.ole.sys.document.GeneralLedgerPostingDocument;
50  import org.kuali.ole.sys.document.datadictionary.AccountingLineGroupDefinition;
51  import org.kuali.ole.sys.document.datadictionary.FinancialSystemTransactionalDocumentEntry;
52  import org.kuali.rice.core.api.uif.RemotableAttributeError;
53  import org.kuali.rice.core.api.util.ConcreteKeyValue;
54  import org.kuali.rice.core.api.util.KeyValue;
55  import org.kuali.rice.core.api.util.RiceConstants;
56  import org.kuali.rice.core.api.util.RiceKeyConstants;
57  import org.kuali.rice.core.api.util.type.KualiDecimal;
58  import org.kuali.rice.core.web.format.*;
59  import org.kuali.rice.core.web.format.Formatter;
60  import org.kuali.rice.kew.api.KewApiConstants.SearchableAttributeConstants;
61  import org.kuali.rice.kew.api.document.DocumentWithContent;
62  import org.kuali.rice.kew.api.document.attribute.DocumentAttribute;
63  import org.kuali.rice.kew.api.document.attribute.DocumentAttributeDecimal;
64  import org.kuali.rice.kew.api.document.attribute.DocumentAttributeString;
65  import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
66  import org.kuali.rice.kew.api.document.search.DocumentSearchResult;
67  import org.kuali.rice.kew.api.exception.WorkflowException;
68  import org.kuali.rice.kew.api.extension.ExtensionDefinition;
69  import org.kuali.rice.kns.lookup.LookupUtils;
70  import org.kuali.rice.kns.service.DataDictionaryService;
71  import org.kuali.rice.kns.service.DictionaryValidationService;
72  import org.kuali.rice.kns.util.FieldUtils;
73  import org.kuali.rice.kns.web.ui.Field;
74  import org.kuali.rice.kns.web.ui.Row;
75  import org.kuali.rice.kns.workflow.attribute.DataDictionarySearchableAttribute;
76  import org.kuali.rice.krad.bo.BusinessObject;
77  import org.kuali.rice.krad.datadictionary.DocumentEntry;
78  import org.kuali.rice.krad.document.Document;
79  import org.kuali.rice.krad.service.DocumentService;
80  import org.kuali.rice.krad.service.KRADServiceLocator;
81  import org.kuali.rice.krad.util.ObjectUtils;
82  
83  import javax.swing.text.*;
84  import javax.swing.text.DateFormatter;
85  
86  //RICE20 This class needs to be fixed to support pre-rice2.0 features
87  public class OLESearchableAttribute extends DataDictionarySearchableAttribute {
88      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OLESearchableAttribute.class);
89  
90      protected static final String DISPLAY_TYPE_SEARCH_ATTRIBUTE_LABEL = "Search Result Type";
91      protected static final String WORKFLOW_DISPLAY_TYPE_LABEL = "Workflow Data";
92      protected static final String DOCUMENT_DISPLAY_TYPE_LABEL = "Document Specific Data";
93      protected static final String WORKFLOW_DISPLAY_TYPE_VALUE = "workflow";
94      protected static final String DOCUMENT_DISPLAY_TYPE_VALUE = "document";
95      protected static final String DISPLAY_TYPE_SEARCH_ATTRIBUTE_NAME = "displayType";
96  
97      protected static final List<KeyValue> SEARCH_ResultType_OPTION_LIST = new ArrayList<KeyValue>(2);
98      static {
99          SEARCH_ResultType_OPTION_LIST.add(new ConcreteKeyValue(DOCUMENT_DISPLAY_TYPE_VALUE, DOCUMENT_DISPLAY_TYPE_LABEL));
100         SEARCH_ResultType_OPTION_LIST.add(new ConcreteKeyValue(WORKFLOW_DISPLAY_TYPE_VALUE, WORKFLOW_DISPLAY_TYPE_LABEL));
101     }
102 
103     // used to map the special fields to the DD Entry that validate it.
104     private static final Map<String, String> magicFields = new HashMap<String, String>();
105 
106     static {
107         magicFields.put(OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE, SourceAccountingLine.class.getSimpleName());
108         magicFields.put(OLEPropertyConstants.ORGANIZATION_CODE, Organization.class.getSimpleName());
109         magicFields.put(OLEPropertyConstants.ACCOUNT_NUMBER, SourceAccountingLine.class.getSimpleName());
110         magicFields.put(OLEPropertyConstants.FINANCIAL_DOCUMENT_TYPE_CODE, GeneralLedgerPendingEntry.class.getSimpleName());
111         magicFields.put(OLEPropertyConstants.FINANCIAL_DOCUMENT_TOTAL_AMOUNT, FinancialSystemDocumentHeader.class.getSimpleName() );
112     }
113 
114     @Override
115     protected List<Row> getSearchingRows(String documentTypeName) {
116         if ( LOG.isDebugEnabled() ) {
117             LOG.debug( "getSearchingRows( " + documentTypeName + " )" );
118             if ( LOG.isTraceEnabled() ) {
119                 LOG.trace("Stack Trace at point of call", new Throwable());
120             }
121         }
122 
123         DataDictionaryService ddService = SpringContext.getBean(DataDictionaryService.class);
124 
125         List<Row> docSearchRows = super.getSearchingRows(documentTypeName);
126 
127         DocumentEntry entry = ddService.getDataDictionary().getDocumentEntry(documentTypeName);
128 
129         if (entry == null) {
130             return docSearchRows;
131         }
132         Class<? extends Document> docClass = entry.getDocumentClass();
133 
134         if (AccountingDocument.class.isAssignableFrom(docClass)) {
135             Map<String, AccountingLineGroupDefinition> alGroups = ((FinancialSystemTransactionalDocumentEntry) entry).getAccountingLineGroups();
136             Class alClass = SourceAccountingLine.class;
137 
138             if (ObjectUtils.isNotNull(alGroups)) {
139                 if (alGroups.containsKey("source")) {
140                     alClass = alGroups.get("source").getAccountingLineClass();
141                 }
142             }
143 
144             BusinessObject alBusinessObject = null;
145 
146             try {
147                 alBusinessObject = (BusinessObject) alClass.newInstance();
148             } catch (Exception cnfe) {
149                 throw new RuntimeException( "Unable to instantiate accounting line class: " + alClass, cnfe);
150             }
151 
152             Field chartField = FieldUtils.getPropertyField(alClass, OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE, true);
153             chartField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
154             if (OleInvoiceDocument.class.isAssignableFrom(docClass)) {
155                 chartField.setColumnVisible(false);
156             } else {
157                 chartField.setColumnVisible(true);
158             }
159             LookupUtils.setFieldQuickfinder(alBusinessObject, OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE, chartField, Collections.singletonList(OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE));
160             docSearchRows.add(new Row(Collections.singletonList(chartField)));
161 
162             Field orgField = FieldUtils.getPropertyField(Organization.class, OLEPropertyConstants.ORGANIZATION_CODE, true);
163             orgField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
164             orgField.setFormatter(new Formatter());
165             if (OleInvoiceDocument.class.isAssignableFrom(docClass)) {
166                 orgField.setColumnVisible(false);
167             } else {
168                 orgField.setColumnVisible(true);
169             }
170 
171             LookupUtils.setFieldQuickfinder(new Account(), OLEPropertyConstants.ORGANIZATION_CODE, orgField, Collections.singletonList(OLEPropertyConstants.ORGANIZATION_CODE));
172             docSearchRows.add(new Row(Collections.singletonList(orgField)));
173 
174             Field accountField = FieldUtils.getPropertyField(alClass, OLEPropertyConstants.ACCOUNT_NUMBER, true);
175             accountField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
176             if (OleInvoiceDocument.class.isAssignableFrom(docClass)) {
177                 accountField.setColumnVisible(false);
178             } else {
179                 accountField.setColumnVisible(true);
180             }
181             LookupUtils.setFieldQuickfinder(alBusinessObject, OLEPropertyConstants.ACCOUNT_NUMBER, accountField, Collections.singletonList(OLEPropertyConstants.ACCOUNT_NUMBER));
182             docSearchRows.add(new Row(Collections.singletonList(accountField)));
183         }
184 
185         boolean displayedLedgerPostingDoc = false;
186 
187         if (GeneralLedgerPostingDocument.class.isAssignableFrom(docClass) && !displayedLedgerPostingDoc) {
188             Field searchField = FieldUtils.getPropertyField(GeneralLedgerPendingEntry.class, OLEPropertyConstants.FINANCIAL_DOCUMENT_TYPE_CODE, true);
189             searchField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
190             if (OleInvoiceDocument.class.isAssignableFrom(docClass)) {
191                 searchField.setColumnVisible(false);
192             } else {
193                 searchField.setColumnVisible(true);
194             }
195             LookupUtils.setFieldQuickfinder(new GeneralLedgerPendingEntry(), OLEPropertyConstants.FINANCIAL_DOCUMENT_TYPE_CODE, searchField, Collections.singletonList(OLEPropertyConstants.FINANCIAL_DOCUMENT_TYPE_CODE));
196             docSearchRows.add(new Row(Collections.singletonList(searchField)));
197         }
198 
199         if (AmountTotaling.class.isAssignableFrom(docClass)) {
200             Field searchField = FieldUtils.getPropertyField(FinancialSystemDocumentHeader.class, OLEPropertyConstants.FINANCIAL_DOCUMENT_TOTAL_AMOUNT, true);
201             searchField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_FLOAT);
202             docSearchRows.add(new Row(Collections.singletonList(searchField)));
203         }
204 
205         if(RequisitionDocument.class.isAssignableFrom(docClass)) {
206 
207             magicFields.put(OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID,OleRequisitionItem.class.getSimpleName());
208             magicFields.put(OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID,OleRequisitionItem.class.getSimpleName());
209             Class boClass = OleRequisitionItem.class;
210 
211             Field searchField = FieldUtils.getPropertyField(boClass, OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID, true);
212             searchField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
213             searchField.setColumnVisible(false);
214 
215 
216             Field searchFieldLocalTitleId = FieldUtils.getPropertyField(boClass, OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID, true);
217             searchFieldLocalTitleId.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
218 
219             //searchField.setFieldType("multibox");
220 
221            /* List<Field> fieldList = new ArrayList<Field>();
222             fieldList.add(searchField);*/
223             docSearchRows.add(new Row(Collections.singletonList(searchField)));
224             docSearchRows.add(new Row(Collections.singletonList(searchFieldLocalTitleId)));
225 
226         }
227 
228         if(PurchaseOrderDocument.class.isAssignableFrom(docClass)) {
229             magicFields.put(OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID,OlePurchaseOrderItem.class.getSimpleName());
230             magicFields.put(OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID,OlePurchaseOrderItem.class.getSimpleName());
231             magicFields.put(OleSelectConstant.AcquisitionsSearch.DONOR_CODES,OlePurchaseOrderItem.class.getSimpleName());
232             Class boClass = OlePurchaseOrderItem.class;
233 
234             Field searchField = FieldUtils.getPropertyField(boClass, OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID, true);
235             searchField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
236             searchField.setColumnVisible(false);
237 
238             Field searchFieldLocalTitleId = FieldUtils.getPropertyField(boClass, OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID, true);
239             searchFieldLocalTitleId.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
240 
241             Field searchFieldDonorCode = FieldUtils.getPropertyField(boClass, OleSelectConstant.AcquisitionsSearch.DONOR_CODES, true);
242             searchFieldDonorCode.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
243             searchFieldDonorCode.setColumnVisible(false);
244 
245             //searchField.setFieldType("multibox");
246             List<Field> fieldList = new ArrayList<Field>();
247             fieldList.add(searchField);
248             fieldList.add(searchFieldLocalTitleId);
249             fieldList.add(searchFieldDonorCode);
250             docSearchRows.add(new Row(fieldList));
251 
252         }
253         if(OlePaymentRequestDocument.class.isAssignableFrom(docClass)) {
254             magicFields.put(OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID,OlePaymentRequestItem.class.getSimpleName());
255             magicFields.put(OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID,OlePaymentRequestItem.class.getSimpleName());
256             Class boClass = OlePaymentRequestItem.class;
257 
258             Field searchField = FieldUtils.getPropertyField(boClass, OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID, true);
259             searchField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
260             searchField.setColumnVisible(false);
261 
262             Field searchFieldLocalTitleId = FieldUtils.getPropertyField(boClass, OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID, true);
263             searchFieldLocalTitleId.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
264             /*List<Field> fieldList = new ArrayList<Field>();
265             fieldList.add(searchField);*/
266             docSearchRows.add(new Row(Collections.singletonList(searchField)));
267             docSearchRows.add(new Row(Collections.singletonList(searchFieldLocalTitleId)));
268 
269         }
270         if (OleLineItemReceivingDocument.class.isAssignableFrom(docClass)) {
271             magicFields.put(OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID, OleLineItemReceivingItem.class.getSimpleName());
272             magicFields.put(OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID, OleLineItemReceivingItem.class.getSimpleName());
273             Class boClass = OleLineItemReceivingItem.class;
274 
275             Field searchField = FieldUtils.getPropertyField(boClass, OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID, true);
276             searchField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
277             searchField.setColumnVisible(false);
278 
279             Field searchFieldLocalTitleId = FieldUtils.getPropertyField(boClass,OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID, true);
280             searchFieldLocalTitleId.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
281                 /*List<Field> fieldList = new ArrayList<Field>();
282                 fieldList.add(searchField);*/
283             docSearchRows.add(new Row(Collections.singletonList(searchField)));
284             docSearchRows.add(new Row(Collections.singletonList(searchFieldLocalTitleId)));
285         }
286         if (OleCorrectionReceivingDocument.class.isAssignableFrom(docClass)) {
287 
288             magicFields.put(OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID, OleCorrectionReceivingItem.class.getSimpleName());
289             magicFields.put(OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID, OleCorrectionReceivingItem.class.getSimpleName());
290             Class boClass = OleCorrectionReceivingItem.class;
291 
292             Field searchField = FieldUtils.getPropertyField(boClass, OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID, true);
293             searchField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
294             searchField.setColumnVisible(false);
295 
296             Field searchFieldLocalTitleId = FieldUtils.getPropertyField(boClass, OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID, true);
297             searchFieldLocalTitleId.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
298                 /*List<Field> fieldList = new ArrayList<Field>();
299                 fieldList.add(searchField);*/
300             docSearchRows.add(new Row(Collections.singletonList(searchField)));
301             docSearchRows.add(new Row(Collections.singletonList(searchFieldLocalTitleId)));
302         }
303         if (OleInvoiceDocument.class.isAssignableFrom(docClass)) {
304             Class boClass = OleInvoiceDocument.class;
305             magicFields.put(OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID, OleInvoiceItem.class.getSimpleName());
306             magicFields.put(OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID, OleInvoiceItem.class.getSimpleName());
307             Class itemClass = OleInvoiceItem.class;
308 
309 
310             Field searchResultInvDateField = FieldUtils.getPropertyField(boClass, OleSelectConstant.InvoiceSearch.PO_DIS_INV_DT, true);
311             searchResultInvDateField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_DATE);
312             docSearchRows.add(new Row(Collections.singletonList(searchResultInvDateField)));
313 
314 
315             Field poDocNumbersField = FieldUtils.getPropertyField(boClass, OleSelectConstant.InvoiceSearch.PO_DOC_NUMS, true);
316             poDocNumbersField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
317             Row poNumRow = new Row(Collections.singletonList(poDocNumbersField));
318             poNumRow.setHidden(true);
319             docSearchRows.add(poNumRow);
320 
321             Field itemSearchField = FieldUtils.getPropertyField(itemClass, OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID, true);
322             itemSearchField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
323             itemSearchField.setColumnVisible(false);
324 
325             Field itemSearchLocalTitleField = FieldUtils.getPropertyField(itemClass, OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID, true);
326             itemSearchLocalTitleField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
327             itemSearchLocalTitleField.setColumnVisible(false);
328 
329             docSearchRows.add(new Row(Collections.singletonList(itemSearchField)));
330             docSearchRows.add(new Row(Collections.singletonList(itemSearchLocalTitleField)));
331 
332             magicFields.put(OleSelectConstant.InvoiceSearch.PO_ID, OleInvoiceItem.class.getSimpleName());
333 
334             Field poDocNumField = FieldUtils.getPropertyField(boClass, OleSelectConstant.InvoiceSearch.PO_ID, true);
335             poDocNumField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_STRING);
336             poDocNumField.setColumnVisible(false);
337             docSearchRows.add(new Row(Collections.singletonList(poDocNumField)));
338 
339             // JIRA-4919
340 
341 
342             Field searchResultInvPayDateField = FieldUtils.getPropertyField(boClass, OleSelectConstant.InvoiceSearch.PO_DIS_INV_PAY_DT, true);
343             searchResultInvPayDateField.setFieldDataType(SearchableAttributeConstants.DATA_TYPE_DATE);
344             docSearchRows.add(new Row(Collections.singletonList(searchResultInvPayDateField)));
345 
346             //magicFields.put(OleSelectConstant.InvoiceSearch.PO_DOC_NUMS, boClass.getSimpleName());
347 
348             for (Row row : docSearchRows) {
349                 List<Field> fields= row.getFields();
350                 Field field=fields.get(0);
351                 if(field.getPropertyName().equalsIgnoreCase(OleSelectConstant.InvoiceSearch.ORG_DOC_NUMBER)){
352                     field.setColumnVisible(false);
353                 }
354                 if(field.getPropertyName().equalsIgnoreCase(OleSelectConstant.InvoiceSearch.INV_DATE)){
355                     field.setColumnVisible(false);
356                 }
357                 if(field.getPropertyName().equalsIgnoreCase(OleSelectConstant.InvoiceSearch.INV_PAY_DATE)){
358                     field.setColumnVisible(false);
359                 }
360                 if(field.getFieldDataType().equalsIgnoreCase(SearchableAttributeConstants.DATA_TYPE_DATE)) {
361                     field.setMaxLength(10);
362                 }
363             }
364         }
365 
366         Row resultType = createSearchResultDisplayTypeRow();
367         docSearchRows.add(resultType);
368         if ( LOG.isDebugEnabled() ) {
369             LOG.debug( "Returning Rows: " + docSearchRows );
370         }
371         return docSearchRows;
372     }
373 
374 
375 
376 
377 
378     @Override
379     public List<DocumentAttribute> extractDocumentAttributes(ExtensionDefinition extensionDefinition, DocumentWithContent documentWithContent) {
380         if (LOG.isDebugEnabled()) {
381             LOG.debug("extractDocumentAttributes( " + extensionDefinition + ", " + documentWithContent + " )");
382         }
383         List<DocumentAttribute> searchAttrValues = super.extractDocumentAttributes(extensionDefinition, documentWithContent);
384 
385         String docId = documentWithContent.getDocument().getDocumentId();
386         DocumentService docService = SpringContext.getBean(DocumentService.class);
387         Document doc = null;
388         try {
389             doc = docService.getByDocumentHeaderIdSessionless(docId);
390         }
391         catch (WorkflowException we) {
392 
393         }
394         if (doc != null) {
395             if (doc instanceof AmountTotaling) {
396                 DocumentAttributeDecimal.Builder searchableAttributeValue = DocumentAttributeDecimal.Builder.create(OLEPropertyConstants.FINANCIAL_DOCUMENT_TOTAL_AMOUNT);
397                 searchableAttributeValue.setValue(((AmountTotaling) doc).getTotalDollarAmount().bigDecimalValue());
398                 searchAttrValues.add(searchableAttributeValue.build());
399             }
400 
401             if (doc instanceof AccountingDocument) {
402                 AccountingDocument accountingDoc = (AccountingDocument) doc;
403                 searchAttrValues.addAll(harvestAccountingDocumentSearchableAttributes(accountingDoc));
404             }
405 
406             boolean indexedLedgerDoc = false;
407 
408             if (doc instanceof GeneralLedgerPostingDocument && !indexedLedgerDoc) {
409                 GeneralLedgerPostingDocument GLPostingDoc = (GeneralLedgerPostingDocument) doc;
410                 searchAttrValues.addAll(harvestGLPDocumentSearchableAttributes(GLPostingDoc));
411             }
412 
413             if (doc instanceof PurchasingAccountsPayableDocument) {
414                 PurchasingAccountsPayableDocument purchasingAccountsPayableDocument = (PurchasingAccountsPayableDocument)doc;
415                 searchAttrValues.addAll(harvestPurchasingAccountsPayableDocument(purchasingAccountsPayableDocument));
416             }
417 
418             if (doc instanceof OleLineItemReceivingDocument |
419                     doc instanceof OleCorrectionReceivingDocument) {
420                 ReceivingDocument receivingDocument = (ReceivingDocument)doc;
421                 searchAttrValues.addAll(harvestReceivingDocument(receivingDocument));
422             }
423             if(doc instanceof OleInvoiceDocument){
424                 StringBuffer purchaseOrderDocumentNums = new StringBuffer();
425                 OleInvoiceDocument invoiceDocument = (OleInvoiceDocument) doc;
426                 KualiDecimal invoicedAmount = KualiDecimal.ZERO;
427                 for (Object purApItem : invoiceDocument.getItems()) {
428                     OleInvoiceItem invoiceItem = (OleInvoiceItem) purApItem;
429                     if (invoiceItem.getPurchaseOrderIdentifier() != null) {
430                         purchaseOrderDocumentNums.append(invoiceItem.getPurchaseOrderIdentifier().toString() + ",");
431                     }
432                     if (invoiceItem.isDebitItem()) {
433                         invoicedAmount = invoicedAmount.add(invoiceItem.getItemListPrice().multiply(new KualiDecimal(invoiceItem.getOleCopiesOrdered())));
434                     } else {
435                         invoicedAmount = invoicedAmount.subtract(invoiceItem.getItemListPrice().multiply(new KualiDecimal(invoiceItem.getOleCopiesOrdered())));
436                     }
437                 }
438                 for(int i=0;i<searchAttrValues.size();i++) {
439                     if (searchAttrValues.get(i).getName().equals(OLEPropertyConstants.FIN_DOC_TOT_AMT)) {
440                         searchAttrValues.remove(i);
441                         DocumentAttributeDecimal.Builder invDebitItemSearchableAttributeValue = DocumentAttributeDecimal.Builder.create(OLEPropertyConstants.FIN_DOC_TOT_AMT);
442                         invDebitItemSearchableAttributeValue.setValue(invoicedAmount.bigDecimalValue());
443                         searchAttrValues.add(invDebitItemSearchableAttributeValue.build());
444                     }
445                 }
446 
447                 int len = purchaseOrderDocumentNums.lastIndexOf(",");
448                 if (len > 0) {
449                     purchaseOrderDocumentNums.replace(len, len + 1, " ");
450                 }
451                 DocumentAttributeString.Builder poDocNumSearchableAttributeValue = DocumentAttributeString.Builder.create(OleSelectConstant.InvoiceSearch.PO_DOC_NUMS);
452                 poDocNumSearchableAttributeValue.setValue(purchaseOrderDocumentNums.toString());
453                 searchAttrValues.add(poDocNumSearchableAttributeValue.build());
454 
455                 DateFormat sourceFormat = new SimpleDateFormat(RiceConstants.SIMPLE_DATE_FORMAT_FOR_DATE);
456 
457                 String invoiceDate = sourceFormat.format(invoiceDocument.getInvoiceDate());
458                 String invoicePayDate = sourceFormat.format(invoiceDocument.getInvoicePayDate());
459 
460                 DocumentAttributeString.Builder invDateSearchableAttributeValue = DocumentAttributeString.Builder.create(OleSelectConstant.InvoiceSearch.PO_DIS_INV_DT);
461                 invDateSearchableAttributeValue.setValue(invoiceDate);
462                 searchAttrValues.add(invDateSearchableAttributeValue.build());
463 
464                 DocumentAttributeString.Builder invPayDateSearchableAttributeValue = DocumentAttributeString.Builder.create(OleSelectConstant.InvoiceSearch.PO_DIS_INV_PAY_DT);
465                 invPayDateSearchableAttributeValue.setValue(invoicePayDate);
466                 searchAttrValues.add(invPayDateSearchableAttributeValue.build());
467             }
468         }
469         return searchAttrValues;
470     }
471 
472 
473 
474 
475 
476     @Override
477     public List<RemotableAttributeError> validateDocumentAttributeCriteria(ExtensionDefinition extensionDefinition, DocumentSearchCriteria documentSearchCriteria) {
478         if (LOG.isDebugEnabled()) {
479             LOG.debug("validateDocumentAttributeCriteria( " + extensionDefinition + ", " + documentSearchCriteria + " )");
480         }
481         // this list is irrelevant. the validation errors are put on the stack in the validationService.
482         List<RemotableAttributeError> errors =  super.validateDocumentAttributeCriteria(extensionDefinition, documentSearchCriteria);
483 
484         DictionaryValidationService validationService = SpringContext.getBean(DictionaryValidationService.class);
485         Map<String,List<String>> paramMap = documentSearchCriteria.getDocumentAttributeValues();
486         for (String key : paramMap.keySet()) {
487             List<String> values = paramMap.get(key);
488             if ( values != null && !values.isEmpty() ) {
489                 for ( String value : values ) {
490                     if (!StringUtils.isEmpty(value)) {
491                         if (magicFields.containsKey(key)) {
492                             validationService.validateAttributeFormat(magicFields.get(key), key, value, key);
493                         }
494                     }
495                 }
496             }
497         }
498 
499         retrieveValidationErrorsFromGlobalVariables(errors);
500 
501         return errors;
502     };
503 
504     /**
505      * Harvest chart of accounts code, account number, and organization code as searchable attributes from an accounting document
506      * @param accountingDoc the accounting document to pull values from
507      * @return a List of searchable values
508      */
509     protected List<DocumentAttribute> harvestAccountingDocumentSearchableAttributes(AccountingDocument accountingDoc) {
510         List<DocumentAttribute> searchAttrValues = new ArrayList<DocumentAttribute>();
511 
512         for ( AccountingLine line : (List<AccountingLine>)accountingDoc.getSourceAccountingLines() ) {
513             addSearchableAttributesForAccountingLine(searchAttrValues, line);
514         }
515         for ( AccountingLine line : (List<AccountingLine>)accountingDoc.getTargetAccountingLines() ) {
516             addSearchableAttributesForAccountingLine(searchAttrValues, line);
517         }
518 
519         return searchAttrValues;
520     }
521 
522     /**
523      * Harvest GLPE document type as searchable attributes from a GL posting document
524      * @param doc the GLP document to pull values from
525      * @return a List of searchable values
526      */
527     protected List<DocumentAttribute> harvestGLPDocumentSearchableAttributes(GeneralLedgerPostingDocument doc) {
528         List<DocumentAttribute> searchAttrValues = new ArrayList<DocumentAttribute>();
529 
530         for ( GeneralLedgerPendingEntry glpe : doc.getGeneralLedgerPendingEntries() ) {
531             addSearchableAttributesForGLPE(searchAttrValues, glpe);
532         }
533         return searchAttrValues;
534     }
535 
536     /**
537      * Harvest itemTitle Id searchable attributes from the Purchasing Accounts Payable Document
538      * @param purapDoc the PurchasingAccountsPyable Document to pull values from
539      * @return a List of searchable values
540      */
541     protected List<DocumentAttribute> harvestPurchasingAccountsPayableDocument(PurchasingAccountsPayableDocument purapDoc) {
542         List<DocumentAttribute> searchAttrValues = new ArrayList<DocumentAttribute>();
543         for (Object element : purapDoc.getItems()) {
544             PurApItem purapItem = (PurApItem)element;
545             addSearchableAttributesForPurApItemTitleId(searchAttrValues, purapItem);
546         }
547         return searchAttrValues;
548     }
549 
550     /**
551      * Harvest itemTitle Id searchable attributes from the Receiving Document
552      * @param receivingDoc the Receiving Document to pull values from
553      * @return a List of searchable values
554      */
555     protected List<DocumentAttribute> harvestReceivingDocument(ReceivingDocument receivingDoc) {
556         List<DocumentAttribute> searchAttrValues = new ArrayList<DocumentAttribute>();
557         for (Iterator itr = receivingDoc.getItems().iterator(); itr.hasNext();) {
558             ReceivingItem receivingItem = (ReceivingItem)itr.next();
559             addSearchableAttributesForReceivingItemTitleIds(searchAttrValues, receivingItem);
560         }
561         return searchAttrValues;
562     }
563 
564     /**
565      * Pulls the default searchable attributes - chart code, account number, and account organization code - from a given accounting line and populates
566      * the searchable attribute values in the given list
567      * @param searchAttrValues a List of SearchableAttributeValue objects to populate
568      * @param accountingLine an AccountingLine to get values from
569      */
570     protected void addSearchableAttributesForAccountingLine(List<DocumentAttribute> searchAttrValues, AccountingLine accountingLine) {
571         DocumentAttributeString.Builder searchableAttributeValue = DocumentAttributeString.Builder.create(OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE);
572         searchableAttributeValue.setValue(accountingLine.getChartOfAccountsCode());
573         searchAttrValues.add(searchableAttributeValue.build());
574 
575         searchableAttributeValue = DocumentAttributeString.Builder.create(OLEPropertyConstants.ACCOUNT_NUMBER);
576         searchableAttributeValue.setValue(accountingLine.getAccountNumber());
577         searchAttrValues.add(searchableAttributeValue.build());
578 
579         searchableAttributeValue = DocumentAttributeString.Builder.create(OLEPropertyConstants.ORGANIZATION_CODE);
580         searchableAttributeValue.setValue(accountingLine.getAccount().getOrganizationCode());
581         searchAttrValues.add(searchableAttributeValue.build());
582     }
583 
584     /**
585      * Pulls the default searchable attribute - financialSystemTypeCode - from a given accounting line and populates
586      * the searchable attribute values in the given list
587      * @param searchAttrValues a List of SearchableAttributeValue objects to populate
588      * @param glpe a GeneralLedgerPendingEntry to get values from
589      */
590     protected void addSearchableAttributesForGLPE(List<DocumentAttribute> searchAttrValues, GeneralLedgerPendingEntry glpe) {
591         DocumentAttributeString.Builder searchableAttributeValue = DocumentAttributeString.Builder.create(OLEPropertyConstants.FINANCIAL_DOCUMENT_TYPE_CODE);
592         searchableAttributeValue.setValue(glpe.getFinancialDocumentTypeCode());
593         searchAttrValues.add(searchableAttributeValue.build());
594 
595     }
596 
597     /**
598      * Pulls the default searchable attribute - itemTitleId - from a given PurApItem and populates
599      * the searchable attribute values in the given list
600      * @param searchAttrValues a List of SearchableAttributeValue objects to populate
601      * @param purapItem a PurApItem to get values from
602      */
603     protected void addSearchableAttributesForPurApItemTitleId(List<DocumentAttribute> searchAttrValues, PurApItem purapItem) {
604         if (purapItem instanceof OleRequisitionItem ) {
605             DocumentAttributeString.Builder searchableAttributeValue = DocumentAttributeString.Builder.create(OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID);
606             searchableAttributeValue.setValue(((OleRequisitionItem) purapItem).getItemTitleId());
607 
608             DocumentAttributeString.Builder searchableAttributeLocalValue = DocumentAttributeString.Builder.create(OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID);
609             if(((OleRequisitionItem) purapItem).getItemTitleId()!=null){
610                 searchableAttributeLocalValue.setValue(DocumentUniqueIDPrefix.getDocumentId(((OleRequisitionItem) purapItem).getItemTitleId()));
611             }
612             searchAttrValues.add(searchableAttributeValue.build());
613             searchAttrValues.add(searchableAttributeLocalValue.build());
614         }
615         else if (purapItem instanceof OlePaymentRequestItem) {
616             DocumentAttributeString.Builder searchableAttributeValue = DocumentAttributeString.Builder.create(OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID);
617             searchableAttributeValue.setValue(((OlePaymentRequestItem)purapItem).getItemTitleId());
618 
619             DocumentAttributeString.Builder searchableAttributeLocalValue = DocumentAttributeString.Builder.create(OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID);
620             if(((OlePaymentRequestItem) purapItem).getItemTitleId()!=null){
621                 searchableAttributeLocalValue.setValue(DocumentUniqueIDPrefix.getDocumentId(((OlePaymentRequestItem)purapItem).getItemTitleId()));
622             }
623             searchAttrValues.add(searchableAttributeLocalValue.build());
624             searchAttrValues.add(searchableAttributeValue.build());
625         }
626         else if (purapItem instanceof OlePurchaseOrderItem){
627             DocumentAttributeString.Builder searchableAttributeValue = DocumentAttributeString.Builder.create(OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID);
628             searchableAttributeValue.setValue(((OlePurchaseOrderItem) purapItem).getItemTitleId());
629             for(OLELinkPurapDonor oleDonor:((OlePurchaseOrderItem) purapItem).getOleDonors()){
630 
631                 DocumentAttributeString.Builder searchableAttributeDonorValue = DocumentAttributeString.Builder.create(OleSelectConstant.AcquisitionsSearch.DONOR_CODES);
632                 searchableAttributeDonorValue.setValue(oleDonor.getDonorCode());
633                 searchAttrValues.add(searchableAttributeDonorValue.build());
634             }
635             DocumentAttributeString.Builder searchableAttributeLocalValue = DocumentAttributeString.Builder.create(OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID);
636             if(((OlePurchaseOrderItem) purapItem).getItemTitleId()!=null){
637                 searchableAttributeLocalValue.setValue(DocumentUniqueIDPrefix.getDocumentId(((OlePurchaseOrderItem) purapItem).getItemTitleId()));
638             }
639             searchAttrValues.add(searchableAttributeLocalValue.build());
640             searchAttrValues.add(searchableAttributeValue.build());
641         }
642         else if (purapItem instanceof OleInvoiceItem){
643             DocumentAttributeString.Builder searchableAttributeValue = DocumentAttributeString.Builder.create(OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID);
644             searchableAttributeValue.setValue(((OleInvoiceItem)purapItem).getItemTitleId());
645 
646             DocumentAttributeString.Builder searchableAttributeLocalValue = DocumentAttributeString.Builder.create(OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID);
647             if(((OleInvoiceItem) purapItem).getItemTitleId()!=null){
648                 searchableAttributeLocalValue.setValue(DocumentUniqueIDPrefix.getDocumentId(((OleInvoiceItem)purapItem).getItemTitleId()));
649             }
650             searchAttrValues.add(searchableAttributeValue.build());
651             searchAttrValues.add(searchableAttributeLocalValue.build());
652 
653             if (((OleInvoiceItem)purapItem).getPurchaseOrderIdentifier() != null) {
654                 DocumentAttributeString.Builder poDocNumSearchableAttributeValue = DocumentAttributeString.Builder.create(OleSelectConstant.InvoiceSearch.PO_ID);
655                 poDocNumSearchableAttributeValue.setValue(((OleInvoiceItem)purapItem).getPurchaseOrderIdentifier().toString());
656                 searchAttrValues.add(poDocNumSearchableAttributeValue.build());
657             }
658 
659 
660         }
661     }
662 
663     /**
664      * Pulls the default searchable attribute - itemTitleId - from a given ReceivingItem and populates
665      * the searchable attribute values in the given list
666      * @param searchAttrValues a List of SearchableAttributeValue objects to populate
667      * @param receivingItem a ReceivingItem to get values from
668      */
669     protected void addSearchableAttributesForReceivingItemTitleIds(List<DocumentAttribute> searchAttrValues, ReceivingItem receivingItem) {
670         if(receivingItem instanceof OleCorrectionReceivingItem) {
671             DocumentAttributeString.Builder searchableAttributeValue = DocumentAttributeString.Builder.create(OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID);
672             searchableAttributeValue.setValue(((OleCorrectionReceivingItem)receivingItem).getItemTitleId());
673 
674             DocumentAttributeString.Builder searchableAttributeLocalValue = DocumentAttributeString.Builder.create(OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID);
675             if(((OleCorrectionReceivingItem) receivingItem).getItemTitleId()!=null){
676                 searchableAttributeLocalValue.setValue(DocumentUniqueIDPrefix.getDocumentId(((OleCorrectionReceivingItem)receivingItem).getItemTitleId()));
677             }
678             searchAttrValues.add(searchableAttributeValue.build());
679             searchAttrValues.add(searchableAttributeLocalValue.build());
680         }
681         else if(receivingItem instanceof OleLineItemReceivingItem) {
682             DocumentAttributeString.Builder searchableAttributeValue = DocumentAttributeString.Builder.create(OleSelectConstant.AcquisitionsSearch.ITEM_TITLE_ID);
683             searchableAttributeValue.setValue(((OleLineItemReceivingItem)receivingItem).getItemTitleId());
684 
685             DocumentAttributeString.Builder searchableAttributeLocalValue = DocumentAttributeString.Builder.create(OleSelectConstant.AcquisitionsSearch.ITEM_LOCAL_TITLE_ID);
686             if(((OleLineItemReceivingItem) receivingItem).getItemTitleId()!=null){
687                 searchableAttributeLocalValue.setValue(DocumentUniqueIDPrefix.getDocumentId(((OleLineItemReceivingItem)receivingItem).getItemTitleId()));
688             }
689             searchAttrValues.add(searchableAttributeLocalValue.build());
690             searchAttrValues.add(searchableAttributeValue.build());
691         }
692     }
693 
694     protected Row createSearchResultDisplayTypeRow() {
695         Field searchField = new Field(DISPLAY_TYPE_SEARCH_ATTRIBUTE_NAME, DISPLAY_TYPE_SEARCH_ATTRIBUTE_LABEL);
696         searchField.setFieldType(Field.RADIO);
697         searchField.setIndexedForSearch(false);
698         searchField.setBusinessObjectClassName("");
699         searchField.setFieldHelpName("");
700         searchField.setFieldHelpSummary("");
701         searchField.setColumnVisible(false);
702         searchField.setFieldValidValues(SEARCH_ResultType_OPTION_LIST);
703         searchField.setPropertyValue(DOCUMENT_DISPLAY_TYPE_VALUE);
704         searchField.setDefaultValue(DOCUMENT_DISPLAY_TYPE_VALUE);
705 
706         return new Row(Collections.singletonList(searchField));
707     }
708 
709 
710     // RICE20: fixes to allow document search to function until Rice 2.0.1
711 //    @Override
712 //    public List<RemotableAttributeField> getSearchFields(ExtensionDefinition extensionDefinition, String documentTypeName) {
713 //        if (LOG.isDebugEnabled()) {
714 //            LOG.debug("getSearchFields( " + extensionDefinition + ", " + documentTypeName + " )");
715 //        }
716 //        List<Row> searchRows = getSearchingRows(documentTypeName);
717 //        for ( Row row : searchRows ) {
718 //            for ( Field field : row.getFields() ) {
719 //                if ( field.getFieldType().equals(Field.CURRENCY) ) {
720 //                    field.setFieldType(Field.TEXT);
721 //                }
722 //                if ( field.getMaxLength() < 1 ) {
723 //                    field.setMaxLength(100);
724 //                }
725 //            }
726 //        }
727 //        return FieldUtils.convertRowsToAttributeFields(searchRows);
728 //    }
729 }