001    /*
002     * Copyright 2011 The Kuali Foundation.
003     * 
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     * http://www.opensource.org/licenses/ecl2.php
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.kfs.module.ar.businessobject.lookup;
017    
018    import java.beans.PropertyDescriptor;
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.Collections;
022    import java.util.List;
023    import java.util.Map;
024    
025    import org.apache.commons.beanutils.PropertyUtils;
026    import org.apache.commons.lang.StringUtils;
027    import org.apache.commons.logging.Log;
028    import org.apache.commons.logging.LogFactory;
029    import org.kuali.kfs.module.ar.businessobject.CustomerInvoiceWriteoffLookupResult;
030    import org.kuali.kfs.module.ar.businessobject.inquiry.CustomerInvoiceWriteoffLookupResultInquirableImpl;
031    import org.kuali.kfs.module.ar.document.CustomerInvoiceDocument;
032    import org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService;
033    import org.kuali.kfs.module.ar.document.service.CustomerInvoiceWriteoffDocumentService;
034    import org.kuali.kfs.module.ar.web.ui.CustomerInvoiceWriteoffLookupResultRow;
035    import org.kuali.kfs.sys.KFSConstants;
036    import org.kuali.kfs.sys.context.SpringContext;
037    import org.kuali.rice.kim.bo.Person;
038    import org.kuali.rice.kns.authorization.BusinessObjectRestrictions;
039    import org.kuali.rice.kns.bo.BusinessObject;
040    import org.kuali.rice.kns.datadictionary.mask.Mask;
041    import org.kuali.rice.kns.lookup.CollectionIncomplete;
042    import org.kuali.rice.kns.lookup.HtmlData;
043    import org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl;
044    import org.kuali.rice.kns.util.GlobalVariables;
045    import org.kuali.rice.kns.util.ObjectUtils;
046    import org.kuali.rice.kns.util.comparator.BeanPropertyComparator;
047    import org.kuali.rice.kns.web.comparator.CellComparatorHelper;
048    import org.kuali.rice.kns.web.format.BooleanFormatter;
049    import org.kuali.rice.kns.web.format.Formatter;
050    import org.kuali.rice.kns.web.struts.form.LookupForm;
051    import org.kuali.rice.kns.web.ui.Column;
052    import org.kuali.rice.kns.web.ui.ResultRow;
053    
054    public class CustomerInvoiceWriteoffLookupResultLookupableHelperServiceImpl extends KualiLookupableHelperServiceImpl {
055    
056        private CustomerInvoiceDocumentService customerInvoiceDocumentService;
057        private CustomerInvoiceWriteoffDocumentService customerInvoiceWriteoffDocumentService;
058    
059        private static final Log LOG = LogFactory.getLog(CustomerInvoiceWriteoffLookupResultLookupableHelperServiceImpl.class);
060    
061        /**
062         * This method performs the lookup and returns a collection of lookup items
063         * 
064         * @param lookupForm
065         * @param kualiLookupable
066         * @param resultTable
067         * @param bounded
068         * @return
069         */
070        @Override
071        public Collection performLookup(LookupForm lookupForm, Collection resultTable, boolean bounded) {
072            Collection<BusinessObject> displayList;
073    
074            // call search method to get results
075            if (bounded) {
076                displayList = (Collection<BusinessObject>) getSearchResults(lookupForm.getFieldsForLookup());
077            }
078            else {
079                displayList = (Collection<BusinessObject>) getSearchResultsUnbounded(lookupForm.getFieldsForLookup());
080            }
081            List pkNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(getBusinessObjectClass());
082            List returnKeys = getReturnKeys();
083            Person user = GlobalVariables.getUserSession().getPerson();
084            
085            // iterate through result list and wrap rows with return url and action urls
086            for (BusinessObject element : displayList) {
087                LOG.debug("Doing lookup for " + element.getClass());
088    
089                CustomerInvoiceWriteoffLookupResult result = ((CustomerInvoiceWriteoffLookupResult) element);
090                List<String> customerInvoiceDocumentAttributesForDisplay = result.getCustomerInvoiceDocumentAttributesForDisplay();
091                
092                BusinessObjectRestrictions businessObjectRestrictions = getBusinessObjectAuthorizationService().getLookupResultRestrictions(result, user);
093                //add list of customer invoice document sub rows
094                List<ResultRow> subResultRows = new ArrayList<ResultRow>();
095                for (CustomerInvoiceDocument customerInvoiceDocument : result.getCustomerInvoiceDocuments()) {
096    
097                    List<Column> subResultColumns = new ArrayList<Column>();
098                    
099                    for (String propertyName : customerInvoiceDocumentAttributesForDisplay) {
100                        subResultColumns.add(setupResultsColumn(customerInvoiceDocument, propertyName, businessObjectRestrictions));
101                    }
102                    
103                    ResultRow subResultRow = new ResultRow((List<Column>) subResultColumns, "", "");
104                    subResultRow.setObjectId(customerInvoiceDocument.getObjectId());
105                    subResultRows.add(subResultRow);
106                }
107                
108                //create main customer header row
109                Collection<Column> columns = getColumns(element, businessObjectRestrictions);
110                HtmlData returnUrl = getReturnUrl(element, lookupForm, returnKeys, businessObjectRestrictions);
111                CustomerInvoiceWriteoffLookupResultRow row = 
112                    new CustomerInvoiceWriteoffLookupResultRow((List<Column>) columns, subResultRows, 
113                            returnUrl.constructCompleteHtmlTag(), getActionUrls(element, pkNames, businessObjectRestrictions));
114                resultTable.add(row);
115            }
116    
117            return displayList;
118        }
119        
120        /**
121         * @see org.kuali.core.lookup.Lookupable#getSearchResults(java.util.Map)
122         */
123        @Override
124        public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {
125    
126            setBackLocation((String) fieldValues.get(KFSConstants.BACK_LOCATION));
127            setDocFormKey((String) fieldValues.get(KFSConstants.DOC_FORM_KEY));
128            Collection searchResultsCollection = customerInvoiceWriteoffDocumentService.getCustomerInvoiceDocumentsForInvoiceWriteoffLookup(fieldValues);
129    
130            return this.buildSearchResultList(searchResultsCollection, new Long(searchResultsCollection.size()));
131        }
132    
133        /**
134         * build the search result list from the given collection and the number of all qualified search results
135         * 
136         * @param searchResultsCollection the given search results, which may be a subset of the qualified search results
137         * @param actualSize the number of all qualified search results
138         * @return the serach result list with the given results and actual size
139         */
140        protected List buildSearchResultList(Collection searchResultsCollection, Long actualSize) {
141            CollectionIncomplete results = new CollectionIncomplete(searchResultsCollection, actualSize);
142    
143            // sort list if default sort column given
144            List searchResults = (List) results;
145            List defaultSortColumns = getDefaultSortColumns();
146            if (defaultSortColumns.size() > 0) {
147                Collections.sort(results, new BeanPropertyComparator(defaultSortColumns, true));
148            }
149            return searchResults;
150        }
151    
152        /**
153         * @param element
154         * @param attributeName
155         * @return Column
156         */
157        protected Column setupResultsColumn(BusinessObject element, String attributeName, BusinessObjectRestrictions businessObjectRestrictions) {
158            Column col = new Column();
159    
160            col.setPropertyName(attributeName);
161            
162    
163            String columnTitle = getDataDictionaryService().getAttributeLabel(element.getClass(), attributeName);
164            if (StringUtils.isBlank(columnTitle)) {
165                columnTitle = getDataDictionaryService().getCollectionLabel(element.getClass(), attributeName);
166            }
167            col.setColumnTitle(columnTitle);
168            col.setMaxLength(getDataDictionaryService().getAttributeMaxLength(element.getClass(), attributeName));
169    
170            Class formatterClass = getDataDictionaryService().getAttributeFormatter(element.getClass(), attributeName);
171            Formatter formatter = null;
172            if (formatterClass != null) {
173                try {
174                    formatter = (Formatter) formatterClass.newInstance();
175                    col.setFormatter(formatter);
176                }
177                catch (InstantiationException e) {
178                    LOG.error("Unable to get new instance of formatter class: " + formatterClass.getName());
179                    throw new RuntimeException("Unable to get new instance of formatter class: " + formatterClass.getName());
180                }
181                catch (IllegalAccessException e) {
182                    LOG.error("Unable to get new instance of formatter class: " + formatterClass.getName());
183                    throw new RuntimeException("Unable to get new instance of formatter class: " + formatterClass.getName());
184                }
185            }
186    
187            // pick off result column from result list, do formatting
188            String propValue = KFSConstants.EMPTY_STRING;
189            Object prop = ObjectUtils.getPropertyValue(element, attributeName);
190    
191            // set comparator and formatter based on property type
192            Class propClass = null;
193            try {
194                PropertyDescriptor propDescriptor = PropertyUtils.getPropertyDescriptor(element, col.getPropertyName());
195                if (propDescriptor != null) {
196                    propClass = propDescriptor.getPropertyType();
197                }
198            }
199            catch (Exception e) {
200                throw new RuntimeException("Cannot access PropertyType for property " + "'" + col.getPropertyName() + "' " + " on an instance of '" + element.getClass().getName() + "'.", e);
201            }
202    
203            // formatters
204            if (prop != null) {
205                // for Booleans, always use BooleanFormatter
206                if (prop instanceof Boolean) {
207                    formatter = new BooleanFormatter();
208                }
209    
210                if (formatter != null) {
211                    propValue = (String) formatter.format(prop);
212                }
213                else {
214                    propValue = prop.toString();
215                }
216            }
217    
218            // comparator
219            col.setComparator(CellComparatorHelper.getAppropriateComparatorForPropertyClass(propClass));
220            col.setValueComparator(CellComparatorHelper.getAppropriateValueComparatorForPropertyClass(propClass));
221            propValue = super.maskValueIfNecessary(element.getClass(), col.getPropertyName(), propValue, businessObjectRestrictions);
222            col.setPropertyValue(propValue);
223    
224            if (StringUtils.isNotBlank(propValue)) {
225                col.setColumnAnchor(getInquiryUrl(element, col.getPropertyName()));
226            }
227            return col;
228        }
229    
230    
231        /**
232         * Constructs the list of columns for the search results. All properties for the column objects come from the DataDictionary.
233         * 
234         * @param bo
235         * @return Collection<Column>
236         */
237        protected Collection<Column> getColumns(BusinessObject bo, BusinessObjectRestrictions businessObjectRestrictions) {
238            Collection<Column> columns = new ArrayList<Column>();
239    
240            for (String attributeName : getBusinessObjectDictionaryService().getLookupResultFieldNames(bo.getClass())) {
241                columns.add(setupResultsColumn(bo, attributeName, businessObjectRestrictions));
242            }
243            return columns;
244        }
245        
246        /**
247         * Since there aren't that many fields for inquiry, just deal with each of them one by one for this lookup
248         * 
249         * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getInquiryUrl(org.kuali.rice.kns.bo.BusinessObject, java.lang.String)
250         */
251        @Override
252        public HtmlData getInquiryUrl(BusinessObject bo, String propertyName) {
253            return (new CustomerInvoiceWriteoffLookupResultInquirableImpl()).getInquiryUrl(bo, propertyName);
254        }
255    
256        @Override
257        /*
258         * TODO Figure out what to really send here...
259         */
260        public List getReturnKeys() {
261            return new ArrayList();
262        }
263    
264        public CustomerInvoiceDocumentService getCustomerInvoiceDocumentService() {
265            return customerInvoiceDocumentService;
266        }
267    
268        public void setCustomerInvoiceDocumentService(CustomerInvoiceDocumentService customerInvoiceDocumentService) {
269            this.customerInvoiceDocumentService = customerInvoiceDocumentService;
270        }
271        
272        public CustomerInvoiceWriteoffDocumentService getCustomerInvoiceWriteoffDocumentService() {
273            return customerInvoiceWriteoffDocumentService;
274        }
275    
276        public void setCustomerInvoiceWriteoffDocumentService(CustomerInvoiceWriteoffDocumentService customerInvoiceWriteoffDocumentService) {
277            this.customerInvoiceWriteoffDocumentService = customerInvoiceWriteoffDocumentService;
278        }
279        
280    
281    }
282