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