/*
* 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.service;
import static org.apache.commons.lang.StringUtils.isBlank;
import static org.apache.commons.lang.StringUtils.replace;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.log4j.Logger;
import org.kuali.rice.core.api.util.type.KualiDecimal;
/**
* Interface defining the structure for a CSV flat file record of stuff
*
* @see org.kuali.kfs.module.tem.businessobject.GroupTravelerCsvRecord;
*/
public class CsvRecordFactory<RecordType> {
public static Logger LOG = Logger.getLogger(CsvRecordFactory.class);
final Class<RecordType> recordType;
private Map<String,String> headerMap;
public CsvRecordFactory(final Class<RecordType> recordType) {
this.recordType = recordType;
}
public void setHeaderMap(final Map<String, String> headerMap) {
this.headerMap = headerMap;
}
public Map<String, String> getHeaderMap() {
return this.headerMap;
}
public class CsvRecordInvocationHandler implements InvocationHandler {
protected Map<String, List<Integer>> header;
protected String[] line;
public CsvRecordInvocationHandler(final Map<String, List<Integer>> header, final String[] record) {
setHeader(header);
setRecord(record);
}
protected void setRecord(final String[] record) {
this.line = record;
}
protected void setHeader(final Map<String, List<Integer>> header) {
this.header = header;
}
protected PropertyDescriptor propertyFor(final PropertyDescriptor[] properties, final Method method) {
for (final PropertyDescriptor property: properties) {
if (method.getName().equals(property.getReadMethod().getName())) {
return property;
}
}
return null;
}
protected String headerFor(final PropertyDescriptor property) {
LOG.debug("Checking for header that matches property " + property.getName());
if (headerMap.size() < 1) {
LOG.warn("Your header map is empty. Won't ever resolve any properties");
}
for (final Map.Entry<String,String> entry : headerMap.entrySet()) {
LOG.debug("Checking " + entry.getValue());
if (property.getName().equalsIgnoreCase(entry.getValue())) {
if (header.containsKey(entry.getKey())) {
return entry.getKey();
}
}
}
return null;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
Object retval = null;
final PropertyDescriptor[] properties = PropertyUtils.getPropertyDescriptors(recordType);
final PropertyDescriptor property = propertyFor(properties, method);
final String headerField = headerFor(property);
final List<Integer> columns = header.get(headerField);
StringBuffer value = new StringBuffer();
if (columns != null) {
for (final Integer column : columns) {
value.append(line[column]).append(" ");
}
}
if (KualiDecimal.class.equals(method.getReturnType())) {
if (value == null || isBlank(value.toString())) {
return KualiDecimal.ZERO;
}
retval = new KualiDecimal(convertToBigDecimal(value.toString().trim()));
}
else if (BigDecimal.class.equals(method.getReturnType())) {
if (value == null || isBlank(value.toString())) {
return BigDecimal.ZERO;
}
retval = convertToBigDecimal(value.toString().trim());
}
else if (Boolean.class.equals(method.getReturnType())
|| boolean.class.equals(method.getReturnType())) {
retval = new Boolean(value.toString().trim());
LOG.debug(headerField + " is " + retval);
}
else if (java.sql.Date.class.equals(method.getReturnType())) {
if (!isBlank(value.toString())) {
try {
retval = new java.sql.Date(new SimpleDateFormat("MM/dd/yyyy").parse(value.toString().trim()).getTime());
}
catch (Exception e) {
// Ignore
}
}
}
else {
retval = value.toString().trim();
}
return retval;
}
public BigDecimal convertToBigDecimal(final String toConvert) {
if (isBlank(toConvert)) {
return BigDecimal.ZERO;
}
return new BigDecimal(replace(replace(toConvert, "$", ""), ",", ""));
}
}
public RecordType newInstance(final Map<String, List<Integer>> header, final String[] record) throws Exception {
return (RecordType) Proxy.newProxyInstance(recordType.getClassLoader(),
new Class[] { recordType },
new CsvRecordInvocationHandler(header, record));
}
}