/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.module.tem.web;
import static java.lang.Class.forName;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
import org.kuali.kfs.module.tem.businessobject.AccountingDocumentRelationship;
import org.kuali.kfs.module.tem.document.service.AccountingDocumentRelationshipService;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.rice.core.api.util.type.KualiDecimal;
import org.kuali.rice.krad.keyvalues.KeyValuesFinder;
import org.kuali.rice.krad.util.GlobalVariables;
/**
* Full of static methods for JSTL function access.
*
*/
public final class JstlFunctions {
protected static final String SETTING_PARAMS_PROLOG = "Setting params ";
protected static final String PROPERTY_SETTING_EXC_PROLOG = "Could not set property ";
protected static final String IN_PREPOSITION = " in ";
protected static final String VALUES_FINDER_CLASS_EXC_PROLOG = "Could not find valuesFinder class ";
protected static final org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory.getLog(JstlFunctions.class);
private JstlFunctions() {}
/**
* Returns a list of key/value pairs for displaying in an HTML option for a select list. This is a customized approach to retrieving
* key/value data from database based on criteria specified in the <code>params {@link Map}</code><br/>
* <br/>
* Here is an example of how the code is used from a JSP:<br/>
* <code>
* <jsp:useBean id="paramMap" class="java.util.HashMap"/>
<c:set target="${paramMap}" property="forAddedPerson" value="true" />
<kul:checkErrors keyMatch="${proposalPerson}.proposalPersonRoleId" auditMatch="${proposalPerson}.proposalPersonRoleId"/>
<c:set var="roleStyle" value=""/>
<c:if test="${hasErrors==true}">
<c:set var="roleStyle" value="background-color:#FFD5D5"/>
</c:if>
<html:select property="${proposalPerson}.proposalPersonRoleId" tabindex="0" style="${roleStyle}">
<c:forEach items="${krafn:getOptionList('org.kuali.kra.proposaldevelopment.lookup.keyvalue.ProposalPersonRoleValuesFinder', paramMap)}" var="option">
<c:choose>
<c:when test="${KualiForm.document.proposalPersons[personIndex].proposalPersonRoleId == option.key}">
<option value="${option.key}" selected>${option.label}</option>
</c:when>
<c:otherwise>
<option value="${option.key}">${option.label}</option>
</c:otherwise>
</c:choose>
</c:forEach>
</html:select>
</code>
*
*
* @param valuesFinderClassName
* @param params mapped parameters
* @return List of key values
*/
@SuppressWarnings("unchecked")
public static List getOptionList(String valuesFinderClassName, Map params) {
return setupValuesFinder(valuesFinderClassName, params).getKeyValues();
}
/**
* Initiates the values finder by its <code>valuesFinderClassName</code>. First locates the class in the class path. Then,
* creates an instance of it. A <code>{@link Map}</code> of key/values <code>{@link String}</code> instances a is used
* to set properties on the values finder instance. Uses the apache <code>{@link PropertyUtils}</code> class to set properties
* by the name of the key in the <code>{@link Map}</code>.<br/>
* <br/>
* Basically, a new values finder is created. the <code>params</code> parameter is a <code>{@link Map}</code> of arbitrary values
* mapped to properties of the values finder class.<br/>
* <br/>
* Since this is so flexible and the ambiguity of properties referenced in the <code>{@link Map}</code>, a number of exceptions are caught
* if a property cannot be set or if the values finder cannot be instantiated. All of these exceptions are handled within the method. None
* of these exceptions are thrown back.
*
*
* @param valuesFinderClassName
* @param params
* @return KeyValuesFinder
* @see PropertyUtils#setProperty(Object, String, Object)
*/
private static KeyValuesFinder setupValuesFinder(String valuesFinderClassName, Map<String, Object> params) {
KeyValuesFinder retval = getKeyFinder(valuesFinderClassName);
if(LOG.isDebugEnabled()) {
LOG.debug(SETTING_PARAMS_PROLOG + params);
}
addParametersToFinder(params, retval);
return retval;
}
private static void addParametersToFinder(Map<String, Object> params, KeyValuesFinder finder) {
if (finder != null && params != null) {
for (Map.Entry<String, Object> entry : params.entrySet()) {
try {
BeanUtils.setProperty(finder, entry.getKey(), entry.getValue());
// setProperty(finder, entry.getKey(), entry.getValue());
} catch (Exception e) {
warn(PROPERTY_SETTING_EXC_PROLOG + entry.getKey(), e);
e.printStackTrace();
}
}
}
}
private static KeyValuesFinder getKeyFinder(String valuesFinderClassName) {
KeyValuesFinder retval = null;
try {
retval = (KeyValuesFinder) forName(valuesFinderClassName).newInstance();
} catch (ClassNotFoundException e) {
warnAboutValueFinderClassExceptions(valuesFinderClassName, e);
} catch (InstantiationException e) {
warnAboutValueFinderClassExceptions(valuesFinderClassName, e);
} catch (IllegalAccessException e) {
warnAboutValueFinderClassExceptions(valuesFinderClassName, e);
}
return retval;
}
private static void warnAboutValueFinderClassExceptions(String valuesFinderClassName, Exception e) {
warn(VALUES_FINDER_CLASS_EXC_PROLOG + valuesFinderClassName, e);
}
private static void warn(String message, Exception e) {
if (LOG.isWarnEnabled()) {
LOG.warn(new StringBuilder(message).append(IN_PREPOSITION).append(buildTraceMessage(e)));
}
}
/**
* Get the stack trace from a <code>{@link Throwable}</code> and create a log message from it for tracing purposes
*
* @param thrownObj
* @return String log message
*/
private static String buildTraceMessage(Throwable thrownObj) {
StackTraceElement stackTraceElement = thrownObj.getStackTrace()[0];
return new StringBuilder(stackTraceElement.getClassName())
.append("#")
.append(stackTraceElement.getMethodName())
.append(":")
.append(stackTraceElement.getLineNumber())
.append(" ")
.append(thrownObj.getClass().getSimpleName())
.append("\n")
.append(thrownObj.getMessage())
.toString();
}
public static Boolean canDeleteDocumentRelationship(String documentNumber, String relDocumentNumber){
AccountingDocumentRelationshipService accountingDocumentRelationshipService = SpringContext.getBean(AccountingDocumentRelationshipService.class);
List<AccountingDocumentRelationship> adrList = accountingDocumentRelationshipService.find(new AccountingDocumentRelationship(documentNumber, relDocumentNumber));
if(adrList != null && adrList.size() == 1){
return adrList.get(0).getPrincipalId().equals(GlobalVariables.getUserSession().getPerson().getPrincipalId());
}
return false;
}
public static KualiDecimal add(Object a, Object b){
KualiDecimal tempA = new KualiDecimal(0);
KualiDecimal tempB = new KualiDecimal(0);
if (a instanceof Double){
tempA = new KualiDecimal((Double)a);
}
else if (a instanceof Integer){
tempA = new KualiDecimal((Integer)a);
}
else if (a instanceof String){
tempA = new KualiDecimal((String)a);
}
else if (a instanceof KualiDecimal){
tempA = (KualiDecimal)a;
}
if (b instanceof Double){
tempB = new KualiDecimal((Double)b);
}
else if (b instanceof Integer){
tempB = new KualiDecimal((Integer)b);
}
else if (a instanceof String){
tempB = new KualiDecimal((String)b);
}
else if (b instanceof KualiDecimal){
tempB = (KualiDecimal)b;
}
return tempA.add(tempB);
}
}