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.ld.businessobject.lookup;
017    
018    import java.beans.PropertyDescriptor;
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.HashMap;
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.integration.ld.SegmentedBusinessObject;
030    import org.kuali.kfs.module.ld.businessobject.LedgerBalance;
031    import org.kuali.kfs.module.ld.businessobject.inquiry.AbstractLaborInquirableImpl;
032    import org.kuali.kfs.module.ld.businessobject.inquiry.LedgerBalanceForExpenseTransferInquirableImpl;
033    import org.kuali.kfs.module.ld.businessobject.inquiry.PositionDataDetailsInquirableImpl;
034    import org.kuali.kfs.sys.KFSConstants;
035    import org.kuali.kfs.sys.KFSPropertyConstants;
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.bo.PersistableBusinessObject;
041    import org.kuali.rice.kns.datadictionary.mask.Mask;
042    import org.kuali.rice.kns.lookup.HtmlData;
043    import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
044    import org.kuali.rice.kns.util.GlobalVariables;
045    import org.kuali.rice.kns.util.ObjectUtils;
046    import org.kuali.rice.kns.web.comparator.CellComparatorHelper;
047    import org.kuali.rice.kns.web.format.BooleanFormatter;
048    import org.kuali.rice.kns.web.format.Formatter;
049    import org.kuali.rice.kns.web.struts.form.LookupForm;
050    import org.kuali.rice.kns.web.ui.Column;
051    import org.kuali.rice.kns.web.ui.ResultRow;
052    
053    /**
054     * Service implementation of LedgerBalanceForExpenseTransferLookupableHelperService.
055     */
056    
057    public abstract class LedgerBalanceForExpenseTransferLookupableHelperServiceImpl extends LedgerBalanceLookupableHelperServiceImpl {
058        private static final Log LOG = LogFactory.getLog(LedgerBalanceForExpenseTransferLookupableHelperServiceImpl.class);
059    
060        /**
061         * @see org.kuali.rice.kns.lookup.Lookupable#getInquiryUrl(org.kuali.rice.kns.bo.BusinessObject, java.lang.String)
062         */
063        @Override
064        public HtmlData getInquiryUrl(BusinessObject bo, String propertyName) {
065            if (KFSPropertyConstants.POSITION_NUMBER.equals(propertyName)) {
066                LedgerBalance balance = (LedgerBalance) bo;
067                AbstractLaborInquirableImpl positionDataDetailsInquirable = new PositionDataDetailsInquirableImpl();
068    
069                Map<String, String> fieldValues = new HashMap<String, String>();
070                fieldValues.put(propertyName, balance.getPositionNumber());
071    
072                BusinessObject positionData = positionDataDetailsInquirable.getBusinessObject(fieldValues);
073    
074                return positionData == null ? new AnchorHtmlData() : positionDataDetailsInquirable.getInquiryUrl(positionData, propertyName);
075            }
076            return (new LedgerBalanceForExpenseTransferInquirableImpl()).getInquiryUrl(bo, propertyName);
077        }
078    
079        /**
080         * @see org.kuali.kfs.module.ld.businessobject.lookup.LedgerBalanceLookupableHelperServiceImpl#getSearchResults(java.util.Map)
081         */
082        @Override
083        public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {
084            return null;
085        }
086    
087        /**
088         * This method performs the lookup and returns a collection of lookup items
089         * 
090         * @param lookupForm
091         * @param lookupable
092         * @param resultTable
093         * @param bounded
094         * @return
095         */
096        public Collection performLookup(LookupForm lookupForm, Collection resultTable, boolean bounded) {
097            Collection<BusinessObject> displayList;
098    
099            // call search method to get results
100            if (bounded) {
101                displayList = (Collection<BusinessObject>) getSearchResults(lookupForm.getFieldsForLookup());
102            }
103            else {
104                displayList = (Collection<BusinessObject>) getSearchResultsUnbounded(lookupForm.getFieldsForLookup());
105            }
106    
107            List pkNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(getBusinessObjectClass());
108            List returnKeys = getReturnKeys();
109            Person user = GlobalVariables.getUserSession().getPerson();
110            // iterate through result list and wrap rows with return url and action urls
111            for (BusinessObject element : displayList) {
112                LOG.debug("Doing lookup for " + element.getClass());
113                BusinessObjectRestrictions businessObjectRestrictions = getBusinessObjectAuthorizationService().getLookupResultRestrictions(element, user);
114                String returnUrl = 
115                    getReturnUrl(element, lookupForm, returnKeys, businessObjectRestrictions).constructCompleteHtmlTag();
116    
117                if (element instanceof PersistableBusinessObject) {
118                    if (element instanceof SegmentedBusinessObject) {
119                        LOG.debug("segmented property names " + ((SegmentedBusinessObject) element).getSegmentedPropertyNames());
120                        
121                        Collection<Column> columns = getColumns(element, businessObjectRestrictions);
122                        ResultRow row = new ResultRow((List<Column>) columns, returnUrl, getActionUrls(element, pkNames, businessObjectRestrictions));
123    
124                        for (String propertyName : ((SegmentedBusinessObject) element).getSegmentedPropertyNames()) {
125                            columns.add(setupResultsColumn(element, propertyName, businessObjectRestrictions));
126                        }
127                        
128                        row.setObjectId(((PersistableBusinessObject) element).getObjectId());
129                        resultTable.add(row);
130                    }
131                    else {
132                        Collection<Column> columns = getColumns(element, businessObjectRestrictions);
133                        
134                        ResultRow row = new ResultRow((List<Column>) columns, returnUrl, getActionUrls(element, pkNames, businessObjectRestrictions));
135                        row.setObjectId(((PersistableBusinessObject) element).getObjectId());
136                        resultTable.add(row);
137                    }
138                }
139            }
140    
141            return displayList;
142        }
143    
144        /**
145         * @param element
146         * @param attributeName
147         * @return Column
148         */
149        protected Column setupResultsColumn(BusinessObject element, String attributeName, BusinessObjectRestrictions businessObjectRestrictions) {
150            Column col = new Column();
151    
152            col.setPropertyName(attributeName);
153    
154            String columnTitle = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), attributeName);
155            if (StringUtils.isBlank(columnTitle)) {
156                columnTitle = getDataDictionaryService().getCollectionLabel(getBusinessObjectClass(), attributeName);
157            }
158            col.setColumnTitle(columnTitle);
159            col.setMaxLength(getDataDictionaryService().getAttributeMaxLength(getBusinessObjectClass(), attributeName));
160    
161            Class formatterClass = getDataDictionaryService().getAttributeFormatter(getBusinessObjectClass(), attributeName);
162            Formatter formatter = null;
163            if (formatterClass != null) {
164                try {
165                    formatter = (Formatter) formatterClass.newInstance();
166                    col.setFormatter(formatter);
167                }
168                catch (InstantiationException e) {
169                    LOG.error("Unable to get new instance of formatter class: " + formatterClass.getName());
170                    throw new RuntimeException("Unable to get new instance of formatter class: " + formatterClass.getName());
171                }
172                catch (IllegalAccessException e) {
173                    LOG.error("Unable to get new instance of formatter class: " + formatterClass.getName());
174                    throw new RuntimeException("Unable to get new instance of formatter class: " + formatterClass.getName());
175                }
176            }
177    
178            // pick off result column from result list, do formatting
179            String propValue = KFSConstants.EMPTY_STRING;
180            Object prop = ObjectUtils.getPropertyValue(element, attributeName);
181    
182            // set comparator and formatter based on property type
183            Class propClass = null;
184            try {
185                PropertyDescriptor propDescriptor = PropertyUtils.getPropertyDescriptor(element, col.getPropertyName());
186                if (propDescriptor != null) {
187                    propClass = propDescriptor.getPropertyType();
188                }
189            }
190            catch (Exception e) {
191                throw new RuntimeException("Cannot access PropertyType for property " + "'" + col.getPropertyName() + "' " + " on an instance of '" + element.getClass().getName() + "'.", e);
192            }
193    
194            // formatters
195            if (prop != null) {
196                // for Booleans, always use BooleanFormatter
197                if (prop instanceof Boolean) {
198                    formatter = new BooleanFormatter();
199                }
200    
201                if (formatter != null) {
202                    propValue = (String) formatter.format(prop);
203                }
204                else {
205                    propValue = prop.toString();
206                }
207            }
208    
209            // comparator
210            col.setComparator(CellComparatorHelper.getAppropriateComparatorForPropertyClass(propClass));
211            col.setValueComparator(CellComparatorHelper.getAppropriateValueComparatorForPropertyClass(propClass));
212    
213            propValue = super.maskValueIfNecessary(element.getClass(), col.getPropertyName(), propValue, businessObjectRestrictions);
214            col.setPropertyValue(propValue);
215    
216    
217            if (StringUtils.isNotBlank(propValue)) {
218                col.setColumnAnchor(getInquiryUrl(element, col.getPropertyName()));
219            }
220            return col;
221        }
222    
223    
224        /**
225         * Constructs the list of columns for the search results. All properties for the column objects come from the DataDictionary.
226         * 
227         * @param bo
228         * @return Collection<Column>
229         */
230        protected Collection<Column> getColumns(BusinessObject bo, BusinessObjectRestrictions businessObjectRestrictions) {
231            Collection<Column> columns = new ArrayList<Column>();
232    
233            for (String attributeName : getBusinessObjectDictionaryService().getLookupResultFieldNames(getBusinessObjectClass())) {
234                columns.add(setupResultsColumn(bo, attributeName, businessObjectRestrictions));
235            }
236            return columns;
237        }
238    }
239