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.purap.businessobject.lookup;
017    
018    import java.util.Collections;
019    import java.util.List;
020    import java.util.Map;
021    
022    import org.apache.commons.lang.StringUtils;
023    import org.kuali.kfs.vnd.VendorConstants;
024    import org.kuali.kfs.vnd.VendorKeyConstants;
025    import org.kuali.kfs.vnd.VendorPropertyConstants;
026    import org.kuali.rice.kns.bo.BusinessObject;
027    import org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl;
028    import org.kuali.rice.kns.lookup.LookupUtils;
029    import org.kuali.rice.kns.util.BeanPropertyComparator;
030    import org.kuali.rice.kns.util.GlobalVariables;
031    import org.kuali.rice.kns.util.KNSConstants;
032    
033    /**
034     * This lookupable helper service is used to support lookups on the Threshold BO because it deals with the vendor number,
035     * which isn't really a field, but rather a combination of 2 fields.
036     * 
037     * This code mostly copies {@link org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl}, but differs in that this class will
038     * not remove search criteria containing values corresponding to hidden fields.
039     * 
040     */
041    public class ThresholdLookupableHelperService extends AbstractLookupableHelperServiceImpl {
042        
043        public void validateSearchParameters(Map fieldValues) {
044            super.validateSearchParameters(fieldValues);
045            
046            validateVendorNumber(fieldValues);
047        }
048    
049        /**
050         * Validates that the Vendor Number has no more than one dash in it, and does not consist solely of one dash. Then it calls
051         * extractVendorNumberToVendorIds to obtain vendorHeaderGeneratedId and vendorDetailAssignedId and if either one of the ids
052         * cannot be converted to integers, it will add error that the vendor number must be numerics or numerics separated by a dash.
053         * 
054         * @param fieldValues a Map containing only those key-value pairs that have been filled in on the lookup
055         */
056        protected void validateVendorNumber(Map fieldValues) {
057            String vendorNumber = (String) fieldValues.get(VendorPropertyConstants.VENDOR_NUMBER);
058            if (StringUtils.isNotBlank(vendorNumber)) {
059                int dashPos1 = vendorNumber.indexOf(VendorConstants.DASH);
060                if (dashPos1 > -1) { // There's a dash in the number.
061                    if (vendorNumber.indexOf(VendorConstants.DASH, dashPos1 + 1) > -1) { // There can't be more than one.
062                        GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_NUMBER, VendorKeyConstants.ERROR_VENDOR_LOOKUP_VNDR_NUM_TOO_MANY_DASHES);
063                    }
064                    if (vendorNumber.matches("\\-*")) {
065                        GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_NUMBER, VendorKeyConstants.ERROR_VENDOR_LOOKUP_VNDR_NUM_DASHES_ONLY);
066                    }
067                }
068                extractVendorNumberToVendorIds(fieldValues, vendorNumber);
069            }
070        }
071        
072        /**
073         * Parses the vendorNumber string into vendorHeaderGeneratedIdentifier and vendorDetailAssignedIdentifier, validates that both
074         * fields would be able to be converted into integers, if so it will add both fields into the search criterias map in the
075         * fieldValues and remove the vendorNumber from the fieldValues. If the two fields cannot be converted into integers, this
076         * method will add error message to the errorMap in GlobalVariables that the vendor number must be numeric or numerics separated
077         * by a dash.
078         * 
079         * @param fieldValues a Map containing only those key-value pairs that have been filled in on the lookup
080         * @param vendorNumber venodr number String
081         */
082        protected void extractVendorNumberToVendorIds(Map fieldValues, String vendorNumber) {
083            String vendorHeaderGeneratedIdentifier = null;
084            String vendorDetailAssignedIdentifier = null;
085            int indexOfDash = vendorNumber.indexOf(VendorConstants.DASH);
086            if (indexOfDash < 0) {
087                vendorHeaderGeneratedIdentifier = vendorNumber;
088            }
089            else {
090                vendorHeaderGeneratedIdentifier = vendorNumber.substring(0, indexOfDash);
091                vendorDetailAssignedIdentifier = vendorNumber.substring(indexOfDash + 1, vendorNumber.length());
092            }
093            try {
094                if (StringUtils.isNotEmpty(vendorHeaderGeneratedIdentifier)) {
095                    Integer.parseInt(vendorHeaderGeneratedIdentifier);
096                }
097                if (StringUtils.isNotEmpty(vendorDetailAssignedIdentifier)) {
098                    Integer.parseInt(vendorDetailAssignedIdentifier);
099                }
100                fieldValues.remove(VendorPropertyConstants.VENDOR_NUMBER);
101                fieldValues.put(VendorPropertyConstants.VENDOR_HEADER_GENERATED_ID, vendorHeaderGeneratedIdentifier);
102                fieldValues.put(VendorPropertyConstants.VENDOR_DETAIL_ASSIGNED_ID, vendorDetailAssignedIdentifier);
103            }
104            catch (NumberFormatException headerExc) {
105                GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_NUMBER, VendorKeyConstants.ERROR_VENDOR_LOOKUP_VNDR_NUM_NUMERIC_DASH_SEPARATED);
106            }
107        }
108        
109        /**
110         * Uses Lookup Service to provide a basic search.
111         * 
112         * @param fieldValues - Map containing prop name keys and search values
113         *
114         * @return List found business objects
115         * @see org.kuali.rice.kns.lookup.LookupableHelperService#getSearchResults(java.util.Map)
116         */
117        public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {        
118            return getSearchResultsHelper(LookupUtils.forceUppercase(getBusinessObjectClass(), fieldValues), false);
119        }
120        
121    
122        /**
123         * Uses Lookup Service to provide a basic unbounded search.
124         * 
125         * @param fieldValues - Map containing prop name keys and search values
126         * 
127         * @return List found business objects
128         * @see org.kuali.rice.kns.lookup.LookupableHelperService#getSearchResultsUnbounded(java.util.Map)
129         */
130        public List<? extends BusinessObject> getSearchResultsUnbounded(Map<String, String> fieldValues) {
131            return getSearchResultsHelper(LookupUtils.forceUppercase(getBusinessObjectClass(), fieldValues), true);
132        }
133    
134        /**
135         * 
136         * This method does the actual search, with the parameters specified, and returns the result.
137         * 
138         * NOTE that it will not do any upper-casing based on the DD forceUppercase. That is handled through an external call to
139         * LookupUtils.forceUppercase().
140         * 
141         * @param fieldValues A Map of the fieldNames and fieldValues to be searched on.
142         * @param unbounded Whether the results should be bounded or not to a certain max size.
143         * @return A List of search results.
144         * 
145         */
146        @SuppressWarnings("unchecked")
147        protected List<? extends BusinessObject> getSearchResultsHelper(Map<String, String> fieldValues, boolean unbounded) {
148            // pretty much the same code as exists in KualiLookupableHelperServiceImpl, except that we're not removing hidden fields
149    
150            boolean searchUsingOnlyPrimaryKeyValues = getLookupService().allPrimaryKeyValuesPresentAndNotWildcard(getBusinessObjectClass(), fieldValues);
151    
152            setBackLocation(fieldValues.get(KNSConstants.BACK_LOCATION));
153            setDocFormKey(fieldValues.get(KNSConstants.DOC_FORM_KEY));
154            setReferencesToRefresh(fieldValues.get(KNSConstants.REFERENCES_TO_REFRESH));
155            List searchResults = (List) getLookupService().findCollectionBySearchHelper(getBusinessObjectClass(), fieldValues, unbounded);
156            // sort list if default sort column given
157            List defaultSortColumns = getDefaultSortColumns();
158            if (defaultSortColumns.size() > 0) {
159                Collections.sort(searchResults, new BeanPropertyComparator(getDefaultSortColumns(), true));
160            }
161            return searchResults;
162        }
163    }
164