001: /*
002: * Copyright 2006-2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.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/ecl1.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.module.gl.web.inquirable;
017:
018: import java.util.ArrayList;
019: import java.util.Iterator;
020: import java.util.List;
021: import java.util.Map;
022: import java.util.Properties;
023:
024: import org.apache.commons.lang.StringUtils;
025: import org.kuali.core.bo.BusinessObject;
026: import org.kuali.core.datadictionary.AttributeDefinition;
027: import org.kuali.core.datadictionary.AttributeReferenceDefinition;
028: import org.kuali.core.datadictionary.DataDictionaryEntryBase;
029: import org.kuali.core.lookup.LookupUtils;
030: import org.kuali.core.service.BusinessObjectDictionaryService;
031: import org.kuali.core.service.DataDictionaryService;
032: import org.kuali.core.service.PersistenceStructureService;
033: import org.kuali.core.util.ObjectUtils;
034: import org.kuali.core.util.UrlFactory;
035: import org.kuali.kfs.KFSConstants;
036: import org.kuali.kfs.KFSPropertyConstants;
037: import org.kuali.kfs.context.SpringContext;
038: import org.kuali.kfs.inquiry.KfsInquirableImpl;
039: import org.kuali.module.chart.bo.KualiSystemCode;
040: import org.kuali.module.gl.bo.AccountBalance;
041: import org.kuali.module.gl.util.BusinessObjectFieldConverter;
042: import org.kuali.module.gl.web.Constant;
043:
044: /**
045: * This class is the template class for the customized inqurable implementations used to generate balance inquiry screens.
046: */
047: public abstract class AbstractGLInquirableImpl extends
048: KfsInquirableImpl {
049: private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
050: .getLogger(AbstractGLInquirableImpl.class);
051:
052: /**
053: * Helper method to build an inquiry url for a result field.
054: *
055: * @param businessObject the business object instance to build the urls for
056: * @param attributeName the attribute name which links to an inquirable
057: * @return String url to inquiry
058: */
059: public String getInquiryUrl(BusinessObject businessObject,
060: String attributeName) {
061: BusinessObjectDictionaryService businessDictionary = SpringContext
062: .getBean(BusinessObjectDictionaryService.class);
063: PersistenceStructureService persistenceStructureService = SpringContext
064: .getBean(PersistenceStructureService.class);
065:
066: String baseUrl = KFSConstants.INQUIRY_ACTION;
067: Properties parameters = new Properties();
068: parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER,
069: KFSConstants.START_METHOD);
070:
071: Object attributeValue = null;
072: Class inquiryBusinessObjectClass = null;
073: String attributeRefName = "";
074: boolean isPkReference = false;
075:
076: Map userDefinedAttributeMap = getUserDefinedAttributeMap();
077: boolean isUserDefinedAttribute = userDefinedAttributeMap == null ? false
078: : userDefinedAttributeMap.containsKey(attributeName);
079:
080: // determine the type of the given attribute: user-defined, regular, nested-referenced or primitive reference
081: if (isUserDefinedAttribute) {
082: attributeName = getAttributeName(attributeName);
083: inquiryBusinessObjectClass = getInquiryBusinessObjectClass(attributeName);
084: isPkReference = true;
085: } else if (attributeName.equals(businessDictionary
086: .getTitleAttribute(businessObject.getClass()))) {
087: inquiryBusinessObjectClass = businessObject.getClass();
088: isPkReference = true;
089: } else if (ObjectUtils.isNestedAttribute(attributeName)) {
090: if (!"financialObject.financialObjectType.financialReportingSortCode"
091: .equals(attributeName)) {
092: inquiryBusinessObjectClass = LookupUtils
093: .getNestedReferenceClass(businessObject,
094: attributeName);
095: } else {
096: return "";
097: }
098: } else {
099: Map primitiveReference = LookupUtils.getPrimitiveReference(
100: businessObject, attributeName);
101: if (primitiveReference != null
102: && !primitiveReference.isEmpty()) {
103: attributeRefName = (String) primitiveReference.keySet()
104: .iterator().next();
105: inquiryBusinessObjectClass = (Class) primitiveReference
106: .get(attributeRefName);
107: }
108: attributeValue = ObjectUtils.getPropertyValue(
109: businessObject, attributeName);
110: attributeValue = (attributeValue == null) ? ""
111: : attributeValue.toString();
112: }
113:
114: // process the business object class if the attribute name is not user-defined
115: if (!isUserDefinedAttribute) {
116: if (isExclusiveField(attributeName, attributeValue)) {
117: return "";
118: }
119:
120: if (inquiryBusinessObjectClass == null
121: || businessDictionary
122: .isInquirable(inquiryBusinessObjectClass) == null
123: || !businessDictionary.isInquirable(
124: inquiryBusinessObjectClass).booleanValue()) {
125: return "";
126: }
127:
128: if (KualiSystemCode.class
129: .isAssignableFrom(inquiryBusinessObjectClass)) {
130: inquiryBusinessObjectClass = KualiSystemCode.class;
131: }
132: }
133: parameters.put(KFSConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE,
134: inquiryBusinessObjectClass.getName());
135:
136: List keys = new ArrayList();
137: if (isUserDefinedAttribute) {
138: baseUrl = getBaseUrl();
139: keys = buildUserDefinedAttributeKeyList();
140:
141: parameters.put(KFSConstants.RETURN_LOCATION_PARAMETER,
142: Constant.RETURN_LOCATION_VALUE);
143: parameters
144: .put(KFSConstants.GL_BALANCE_INQUIRY_FLAG, "true");
145: parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER,
146: KFSConstants.SEARCH_METHOD);
147: parameters.put(KFSConstants.DOC_FORM_KEY, "88888888");
148:
149: // add more customized parameters into the current parameter map
150: addMoreParameters(parameters, attributeName);
151: } else if (persistenceStructureService
152: .isPersistable(inquiryBusinessObjectClass)) {
153: keys = persistenceStructureService
154: .listPrimaryKeyFieldNames(inquiryBusinessObjectClass);
155: }
156:
157: // build key value url parameters used to retrieve the business object
158: if (keys != null) {
159: for (Iterator keyIterator = keys.iterator(); keyIterator
160: .hasNext();) {
161: String keyName = (String) keyIterator.next();
162:
163: // convert the key names based on their formats and types
164: String keyConversion = keyName;
165: if (ObjectUtils.isNestedAttribute(attributeName)) {
166: if (isUserDefinedAttribute) {
167: keyConversion = keyName;
168: } else {
169: keyConversion = ObjectUtils
170: .getNestedAttributePrefix(attributeName)
171: + "." + keyName;
172: }
173: } else {
174: if (isPkReference) {
175: keyConversion = keyName;
176: } else {
177: keyConversion = persistenceStructureService
178: .getForeignKeyFieldName(businessObject
179: .getClass(), attributeRefName,
180: keyName);
181: }
182: }
183:
184: Object keyValue = ObjectUtils.getPropertyValue(
185: businessObject, keyConversion);
186: keyValue = (keyValue == null) ? "" : keyValue
187: .toString();
188:
189: // convert the key value and name into the given ones
190: Object tempKeyValue = this .getKeyValue(keyName,
191: keyValue);
192: keyValue = tempKeyValue == null ? keyValue
193: : tempKeyValue;
194:
195: String tempKeyName = this .getKeyName(keyName);
196: keyName = tempKeyName == null ? keyName : tempKeyName;
197:
198: // add the key-value pair into the parameter map
199: if (keyName != null)
200: parameters.put(keyName, keyValue);
201: }
202: }
203:
204: // Hack to make this work. I don't know why it doesn't pick up the whole primary key for these. The last big change to
205: // KualiInquirableImpl
206: // broke all of this
207: if (businessObject instanceof AccountBalance) {
208: AccountBalance ab = (AccountBalance) businessObject;
209: if ("financialObject.financialObjectLevel.financialConsolidationObject.finConsolidationObjectCode"
210: .equals(attributeName)) {
211: parameters.put(
212: KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, ab
213: .getChartOfAccountsCode());
214: } else if ("financialObject.financialObjectLevel.financialObjectLevelCode"
215: .equals(attributeName)) {
216: parameters.put(
217: KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, ab
218: .getChartOfAccountsCode());
219: }
220: }
221:
222: return UrlFactory.parameterizeUrl(baseUrl, parameters);
223: }
224:
225: /**
226: * This method builds the inquiry url for user-defined attribute
227: *
228: * @return a List of attribute keys for the inquiry url
229: */
230: protected abstract List buildUserDefinedAttributeKeyList();
231:
232: /**
233: * This method defines the user-defined attribute map
234: *
235: * @return the user-defined attribute map
236: */
237: protected abstract Map getUserDefinedAttributeMap();
238:
239: /**
240: * This method finds the matching attribute name of given one
241: *
242: * @param attributeName the given attribute name
243: * @return the attribute name from the given one
244: */
245: protected abstract String getAttributeName(String attributeName);
246:
247: /**
248: * This method finds the matching the key value of the given one
249: *
250: * @param keyName the given key name
251: * @param keyValue the given key value
252: * @return the key value from the given key value
253: */
254: protected abstract Object getKeyValue(String keyName,
255: Object keyValue);
256:
257: /**
258: * This method finds the matching the key name of the given one
259: *
260: * @param keyName the given key name
261: * @return the key value from the given key name
262: */
263: protected abstract String getKeyName(String keyName);
264:
265: /**
266: * This method defines the lookupable implementation attribute name
267: *
268: * @return the lookupable implementation attribute name
269: */
270: protected abstract String getLookupableImplAttributeName();
271:
272: /**
273: * This method defines the base inquiry url
274: *
275: * @return the base inquiry url
276: */
277: protected abstract String getBaseUrl();
278:
279: /**
280: * This method gets the class name of the inquiry business object for a given attribute.
281: *
282: * @return the class name of the inquiry business object for a given attribute
283: */
284: protected abstract Class getInquiryBusinessObjectClass(
285: String attributeName);
286:
287: /**
288: * This method adds more parameters into the curren parameter map
289: *
290: * @param parameter the current parameter map
291: */
292: protected abstract void addMoreParameters(Properties parameter,
293: String attributeName);
294:
295: /**
296: * This method determines whether the input name-value pair is exclusive from the processing
297: *
298: * @param keyName the name of the name-value pair
299: * @param keyValue the value of the name-value pair
300: * @return true if the input key is in the exclusive list; otherwise, false
301: */
302: protected boolean isExclusiveField(Object keyName, Object keyValue) {
303:
304: if (keyName != null && keyValue != null) {
305: String convertedKeyName = BusinessObjectFieldConverter
306: .convertFromTransactionPropertyName(keyName
307: .toString());
308:
309: if (convertedKeyName
310: .equals(KFSPropertyConstants.SUB_ACCOUNT_NUMBER)
311: && keyValue
312: .equals(Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER)) {
313: return true;
314: } else if (convertedKeyName
315: .equals(KFSPropertyConstants.SUB_OBJECT_CODE)
316: && keyValue
317: .equals(Constant.CONSOLIDATED_SUB_OBJECT_CODE)) {
318: return true;
319: } else if (convertedKeyName
320: .equals(KFSPropertyConstants.OBJECT_TYPE_CODE)
321: && keyValue
322: .equals(Constant.CONSOLIDATED_OBJECT_TYPE_CODE)) {
323: return true;
324: }
325: if (convertedKeyName
326: .equals(KFSPropertyConstants.SUB_ACCOUNT_NUMBER)
327: && keyValue.equals(KFSConstants
328: .getDashSubAccountNumber())) {
329: return true;
330: } else if (convertedKeyName
331: .equals(KFSPropertyConstants.SUB_OBJECT_CODE)
332: && keyValue.equals(KFSConstants
333: .getDashFinancialSubObjectCode())) {
334: return true;
335: } else if (convertedKeyName
336: .equals(KFSPropertyConstants.PROJECT_CODE)
337: && keyValue.equals(KFSConstants
338: .getDashProjectCode())) {
339: return true;
340: }
341: }
342: return false;
343: }
344:
345: /**
346: * This method recovers the values of the given keys
347: *
348: * @param fieldValues unconsolidated values
349: * @param keyName a key name that may be in the fieldValues map
350: * @param keyValue a key value that may be in the fieldValues map
351: * @return the original value for a previously consolidated value
352: */
353: protected String recoverFieldValueFromConsolidation(
354: Map fieldValues, Object keyName, Object keyValue) {
355: if (fieldValues == null || keyName == null || keyValue == null) {
356: return Constant.EMPTY_STRING;
357: }
358:
359: Map convertedFieldValues = BusinessObjectFieldConverter
360: .convertFromTransactionFieldValues(fieldValues);
361: String convertedKeyName = BusinessObjectFieldConverter
362: .convertFromTransactionPropertyName(keyName.toString());
363:
364: if (convertedKeyName
365: .equals(KFSPropertyConstants.SUB_ACCOUNT_NUMBER)
366: && keyValue
367: .equals(Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER)) {
368: return this .getValueFromFieldValues(convertedFieldValues,
369: keyName);
370: } else if (convertedKeyName
371: .equals(KFSPropertyConstants.SUB_OBJECT_CODE)
372: && keyValue
373: .equals(Constant.CONSOLIDATED_SUB_OBJECT_CODE)) {
374: return this .getValueFromFieldValues(convertedFieldValues,
375: keyName);
376: } else if (convertedKeyName
377: .equals(KFSPropertyConstants.OBJECT_TYPE_CODE)
378: && keyValue
379: .equals(Constant.CONSOLIDATED_OBJECT_TYPE_CODE)) {
380: return this .getValueFromFieldValues(convertedFieldValues,
381: keyName);
382: }
383:
384: return Constant.EMPTY_STRING;
385: }
386:
387: /**
388: * Utility method to get the value of the given key from the field values
389: *
390: * @param fieldValues a Map of key values
391: * @param keyName the name of the key to retrieve the value from
392: * @return the value for the key, or, if not found, an empty String
393: */
394: private String getValueFromFieldValues(Map fieldValues,
395: Object keyName) {
396: String keyValue = Constant.EMPTY_STRING;
397:
398: if (fieldValues.containsKey(keyName)) {
399: keyValue = (String) fieldValues.get(keyName);
400: }
401: return keyValue;
402: }
403:
404: /**
405: * This takes a map of field values and then returns it without processing it, making this a sort
406: * of identity method for Maps
407: *
408: * @param fieldValues field values to return to the user
409: * @return the Map you sent in as a parameter
410: */
411: public Map getFieldValues(Map fieldValues) {
412: return fieldValues;
413: }
414:
415: /**
416: * Given the nested name of an attribute in an object, returns the class that attribute will return
417: *
418: * @param businessObject the business object to find the propery class for
419: * @param attributeName the nested name of the attribute to find the class for
420: * @return the class of the nested attribute
421: */
422: public Class getNestedInquiryBusinessObjectClass(
423: BusinessObject businessObject, String attributeName) {
424: // TODO: not finished
425: Class inquiryBusinessObjectClass = null;
426: String entryName = businessObject.getClass().getName();
427: LOG.debug("businessObject: " + entryName);
428: LOG.debug("attributeName: " + attributeName);
429:
430: DataDictionaryService dataDictionary = SpringContext
431: .getBean(DataDictionaryService.class);
432: AttributeDefinition attributeDefinition = null;
433:
434: if (StringUtils.isBlank(attributeName)) {
435: throw new IllegalArgumentException(
436: "invalid (blank) attributeName");
437: }
438:
439: DataDictionaryEntryBase entry = (DataDictionaryEntryBase) dataDictionary
440: .getDataDictionary()
441: .getDictionaryObjectEntry(entryName);
442: if (entry != null) {
443: attributeDefinition = entry
444: .getAttributeDefinition(attributeName);
445: inquiryBusinessObjectClass = LookupUtils
446: .getNestedReferenceClass(businessObject,
447: attributeName);
448: }
449:
450: if (attributeDefinition instanceof AttributeReferenceDefinition) {
451: AttributeReferenceDefinition attributeReferenceDefinition = (AttributeReferenceDefinition) attributeDefinition;
452: LOG
453: .debug("Source Classname = "
454: + attributeReferenceDefinition
455: .getSourceClassName());
456: LOG.debug("Source Attribute = "
457: + attributeReferenceDefinition
458: .getSourceAttributeName());
459:
460: try {
461: inquiryBusinessObjectClass = Class
462: .forName(attributeReferenceDefinition
463: .getSourceClassName());
464: } catch (Exception e) {
465: throw new IllegalArgumentException(
466: "fail to construct a Class");
467: }
468: }
469:
470: return inquiryBusinessObjectClass;
471: }
472: }
|