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.inquiry;
017    
018    import java.sql.Date;
019    import java.util.ArrayList;
020    import java.util.HashMap;
021    import java.util.Iterator;
022    import java.util.List;
023    import java.util.Map;
024    import java.util.Properties;
025    
026    import org.kuali.kfs.gl.Constant;
027    import org.kuali.kfs.module.ld.LaborConstants;
028    import org.kuali.kfs.sys.KFSConstants;
029    import org.kuali.kfs.sys.KFSPropertyConstants;
030    import org.kuali.kfs.sys.ObjectUtil;
031    import org.kuali.kfs.sys.businessobject.inquiry.KfsInquirableImpl;
032    import org.kuali.kfs.sys.context.SpringContext;
033    import org.kuali.rice.kns.bo.BusinessObject;
034    import org.kuali.rice.kns.lookup.HtmlData;
035    import org.kuali.rice.kns.lookup.LookupUtils;
036    import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
037    import org.kuali.rice.kns.service.BusinessObjectDictionaryService;
038    import org.kuali.rice.kns.service.DateTimeService;
039    import org.kuali.rice.kns.service.PersistenceStructureService;
040    import org.kuali.rice.kns.util.ObjectUtils;
041    import org.kuali.rice.kns.util.UrlFactory;
042    
043    /**
044     * This class is the template class for the customized inqurable implementations used to generate balance inquiry screens.
045     */
046    public abstract class AbstractLaborInquirableImpl extends KfsInquirableImpl {
047        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AbstractLaborInquirableImpl.class);
048    
049        /**
050         * Helper method to build an inquiry url for a result field.
051         * 
052         * @param businessObject the business object instance to build the urls for
053         * @param attributeName the attribute name which links to an inquirable
054         * @return String url to inquiry
055         */
056        public HtmlData getInquiryUrl(BusinessObject businessObject, String attributeName) {
057            BusinessObjectDictionaryService businessDictionary = SpringContext.getBean(BusinessObjectDictionaryService.class);
058            PersistenceStructureService persistenceStructureService = SpringContext.getBean(PersistenceStructureService.class);
059    
060            HtmlData inquiryHref = new AnchorHtmlData(Constant.EMPTY_STRING, Constant.EMPTY_STRING);
061            String baseUrl = KFSConstants.INQUIRY_ACTION;
062            Properties parameters = new Properties();
063            parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, KFSConstants.START_METHOD);
064    
065            Object attributeValue = null;
066            Class inquiryBusinessObjectClass = null;
067            String attributeRefName = Constant.EMPTY_STRING;
068            boolean isPkReference = false;
069    
070            Map userDefinedAttributeMap = getUserDefinedAttributeMap();
071            boolean isUserDefinedAttribute = userDefinedAttributeMap == null ? false : userDefinedAttributeMap.containsKey(attributeName);
072    
073            // determine the type of the given attribute: user-defined, regular, nested-referenced or primitive reference
074            if (isUserDefinedAttribute) {
075                attributeName = getAttributeName(attributeName);
076                inquiryBusinessObjectClass = getInquiryBusinessObjectClass(attributeName);
077                isPkReference = true;
078            }
079            else if (attributeName.equals(businessDictionary.getTitleAttribute(businessObject.getClass()))) {
080                inquiryBusinessObjectClass = businessObject.getClass();
081                isPkReference = true;
082            }
083            else if (ObjectUtils.isNestedAttribute(attributeName)) {
084                return inquiryHref;
085            }
086            else {
087                Map primitiveReference = LookupUtils.getPrimitiveReference(businessObject, attributeName);
088                if (primitiveReference != null && !primitiveReference.isEmpty()) {
089                    attributeRefName = (String) primitiveReference.keySet().iterator().next();
090                    inquiryBusinessObjectClass = (Class) primitiveReference.get(attributeRefName);
091                }
092                attributeValue = ObjectUtils.getPropertyValue(businessObject, attributeName);
093                attributeValue = (attributeValue == null) ? "" : attributeValue.toString();
094            }
095    
096            // process the business object class if the attribute name is not user-defined
097            if (!isUserDefinedAttribute) {
098                if (isExclusiveFieldToBeALink(attributeName, attributeValue)) {
099                    return inquiryHref;
100                }
101    
102                if (inquiryBusinessObjectClass == null || businessDictionary.isInquirable(inquiryBusinessObjectClass) == null || !businessDictionary.isInquirable(inquiryBusinessObjectClass).booleanValue()) {
103                    return inquiryHref;
104                }
105            }
106            parameters.put(KFSConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, inquiryBusinessObjectClass.getName());
107    
108            List keys = new ArrayList();
109            if (isUserDefinedAttribute) {
110                baseUrl = getBaseUrl();
111                keys = buildUserDefinedAttributeKeyList();
112    
113                parameters.put(KFSConstants.RETURN_LOCATION_PARAMETER, Constant.RETURN_LOCATION_VALUE);
114                parameters.put(KFSConstants.GL_BALANCE_INQUIRY_FLAG, "true");
115                parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, KFSConstants.SEARCH_METHOD);
116                parameters.put(KFSConstants.DOC_FORM_KEY, "88888888");
117            }
118            else if (persistenceStructureService.isPersistable(inquiryBusinessObjectClass)) {
119                keys = persistenceStructureService.listPrimaryKeyFieldNames(inquiryBusinessObjectClass);
120            }
121    
122            // build key value url parameters used to retrieve the business object
123            Map<String,String> inquiryFields = new HashMap<String,String>();
124            if (keys != null) {
125                StringBuffer title = new StringBuffer(Constant.EMPTY_STRING);
126                for (Iterator keyIterator = keys.iterator(); keyIterator.hasNext();) {
127                    String keyName = (String) keyIterator.next();
128    
129                    // convert the key names based on their formats and types
130                    String keyConversion = keyName;
131                    if (ObjectUtils.isNestedAttribute(attributeName)) {
132                        if (isUserDefinedAttribute) {
133                            keyConversion = keyName;
134                        }
135                        else {
136                            keyConversion = ObjectUtils.getNestedAttributePrefix(attributeName) + "." + keyName;
137                        }
138                    }
139                    else {
140                        if (isPkReference) {
141                            keyConversion = keyName;
142                        }
143                        else {
144                            keyConversion = persistenceStructureService.getForeignKeyFieldName(businessObject.getClass(), attributeRefName, keyName);
145                        }
146                    }
147    
148                    Object keyValue = ObjectUtils.getPropertyValue(businessObject, keyConversion);
149                    if(ObjectUtil.getSimpleTypeName(businessObject, keyConversion).equals(Date.class.getSimpleName())) {
150                        Date date = (Date)ObjectUtil.valueOf(Date.class.getSimpleName(), keyValue.toString());
151                        
152                        DateTimeService dateTimeService = SpringContext.getBean(DateTimeService.class);
153                        keyValue = dateTimeService.toDateString(new java.util.Date(date.getTime()));
154                    }
155                    
156                    keyValue = (keyValue == null) ? Constant.EMPTY_STRING : keyValue.toString();
157    
158                    // convert the key value and name into the given ones
159                    Object tempKeyValue = this.getKeyValue(keyName, keyValue);
160                    keyValue = tempKeyValue == null ? keyValue : tempKeyValue;
161    
162                    String tempKeyName = this.getKeyName(keyName);
163                    keyName = tempKeyName == null ? keyName : tempKeyName;
164    
165                    // add the key-value pair into the parameter map
166                    if (keyName != null){
167                        parameters.put(keyName, keyValue);
168                        inquiryFields.put(keyName, keyValue.toString());
169                    }
170                }
171            }
172            
173            // add more customized parameters into the current parameter map
174            if (isUserDefinedAttribute) {
175                addMoreParameters(parameters, attributeName);
176            }
177            return getHyperLink(inquiryBusinessObjectClass, inquiryFields, UrlFactory.parameterizeUrl(baseUrl, parameters));
178        }
179    
180        /**
181         * This method builds the inquiry url for user-defined attribute
182         * 
183         * @return key list
184         */
185        protected abstract List buildUserDefinedAttributeKeyList();
186    
187        /**
188         * This method defines the user-defined attribute map
189         * 
190         * @return the user-defined attribute map
191         */
192        protected abstract Map getUserDefinedAttributeMap();
193    
194        /**
195         * This method finds the matching attribute name of given one
196         * 
197         * @param attributeName the given attribute name
198         * @return the attribute name from the given one
199         */
200        protected abstract String getAttributeName(String attributeName);
201    
202        /**
203         * This method finds the matching the key value of the given one
204         * 
205         * @param keyName the given key name
206         * @param keyValue the given key value
207         * @return the key value from the given key value
208         */
209        protected abstract Object getKeyValue(String keyName, Object keyValue);
210    
211        /**
212         * This method finds the matching the key name of the given one
213         * 
214         * @param keyName the given key name
215         * @return the key value from the given key name
216         */
217        protected abstract String getKeyName(String keyName);
218    
219        /**
220         * This method defines the lookupable implementation attribute name
221         * 
222         * @return the lookupable implementation attribute name
223         */
224        protected abstract String getLookupableImplAttributeName();
225    
226        /**
227         * This method defines the base inquiry url
228         * 
229         * @return the base inquiry url
230         */
231        protected abstract String getBaseUrl();
232    
233        /**
234         * This method gets the class name of the inquiry business object for a given attribute.
235         * 
236         * @return the class name of the inquiry business object for a given attribute
237         */
238        protected abstract Class getInquiryBusinessObjectClass(String attributeName);
239    
240        /**
241         * This method adds more parameters into the curren parameter map
242         * 
243         * @param parameter the current parameter map
244         */
245        protected void addMoreParameters(Properties parameter, String attributeName) {
246            return;
247        }
248    
249        /**
250         * This method determines whether the input name-value pair is exclusive from the processing
251         * 
252         * @param keyName the name of the name-value pair
253         * @param keyValue the value of the name-value pair
254         * @return true if the input key is in the exclusive list; otherwise, false
255         */
256        protected boolean isExclusiveField(Object keyName, Object keyValue) {
257    
258            if (keyName != null && keyValue != null) {
259    
260                if (keyName.equals(KFSPropertyConstants.SUB_ACCOUNT_NUMBER) && keyValue.equals(Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER)) {
261                    return true;
262                }
263                else if (keyName.equals(KFSPropertyConstants.FINANCIAL_SUB_OBJECT_CODE) && keyValue.equals(Constant.CONSOLIDATED_SUB_OBJECT_CODE)) {
264                    return true;
265                }
266                else if (keyName.equals(KFSPropertyConstants.FINANCIAL_OBJECT_TYPE_CODE) && keyValue.equals(Constant.CONSOLIDATED_OBJECT_TYPE_CODE)) {
267                    return true;
268                }
269            }
270            return false;
271        }
272    
273        /**
274         * This method determines whether the input name-value pair is exclusive to be a link
275         * 
276         * @param keyName the name of the name-value pair
277         * @param keyValue the value of the name-value pair
278         * @return true if the input key is in the exclusive list; otherwise, false
279         */
280        protected boolean isExclusiveFieldToBeALink(Object keyName, Object keyValue) {
281    
282            if (keyName != null && keyValue != null) {
283    
284                if (isExclusiveField(keyName, keyValue)) {
285                    return true;
286                }
287                else if (keyName.equals(KFSPropertyConstants.SUB_ACCOUNT_NUMBER) && keyValue.equals(KFSConstants.getDashSubAccountNumber())) {
288                    return true;
289                }
290                else if (keyName.equals(KFSPropertyConstants.FINANCIAL_SUB_OBJECT_CODE) && keyValue.equals(KFSConstants.getDashFinancialSubObjectCode())) {
291                    return true;
292                }
293                else if (keyName.equals(KFSPropertyConstants.PROJECT_CODE) && keyValue.equals(KFSConstants.getDashProjectCode())) {
294                    return true;
295                }
296                else if (keyName.equals(KFSPropertyConstants.POSITION_NUMBER) && keyValue.equals(LaborConstants.getDashPositionNumber())) {
297                    return true;
298                }
299                else if (keyName.equals(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE) && keyValue.equals(LaborConstants.BalanceInquiries.BALANCE_TYPE_AC_AND_A21)) {
300                    return true;
301                }
302            }
303            return false;
304        }
305    }