8.DataMappingConfigurer
/*
* Created on Oct 8, 2013
*
* Copyright 2006 ATPCO Confidential and Proprietary. All Rights Reserved.
*/
package net.atpco.dds.offline.filing.common.datamapper.binder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import javax.annotation.PostConstruct;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import net.atpco.dds.offline.filing.common.datamapper.parser.ClassConfig;
import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;
import org.omg.CORBA.portable.ApplicationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.Resource;
import org.xml.sax.SAXException;
public class DataMappingConfigurer {
private static Logger LOGGER = Logger
.getLogger(DataMappingConfigurer.class);
@Autowired
@Qualifier("properties")
private transient Properties properties;
@Autowired
@Qualifier("dataLoadConfig")
private transient DataLoadConfig dataLoadConfig;
private transient Resource[] configPaths;
private transient final Resource schemaPath;
public DataMappingConfigurer(final Resource[] configPaths,
final Resource schemaPath) {
if (!ArrayUtils.isEmpty(configPaths)) {
this.configPaths = Arrays.copyOf(configPaths, configPaths.length);
}
this.schemaPath = schemaPath;
}
/**
* Load the configuration configured. Make sure the property exist in java
* object and table and columns exist in database.
*
* @param configPaths
* @throws ApplicationException
*/
@PostConstruct
public void load() throws Exception {
if (configPaths == null || configPaths.length == 0) {
return;
}
final List<String> identifiersList = new ArrayList<String>();
for (final Resource resource : configPaths) {
LOGGER.info("Processing the file ..." + resource.getFilename());
final ClassConfig config = parse(resource);
if (!identifiersList.contains(config.getId())) {
identifiersList.add(config.getId());
} else {
throw new Exception("Identifier " + config.getId()
+ " already exist:");
}
config.setSchemaName(properties.getProperty(config
.getSchemaPropName()));
// set the configuration in cache.
dataLoadConfig.setClassConfig(config.getId(), config);
LOGGER.info(config.toString());
}
}
/**
* parse the file and bind it using JAXB
*
* @return
*/
private ClassConfig parse(final Resource resource) {
final SchemaFactory schemaFactory = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Exception exeception;
JAXBElement<ClassConfig> jaxElement = null;
try {
final StreamSource xmlSchema = new StreamSource(
schemaPath.getInputStream());
Schema schema = schemaFactory.newSchema(xmlSchema);
JAXBContext jaxbContext = JAXBContext
.newInstance(ClassConfig.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setSchema(schema);
final StreamSource xml = new StreamSource(resource.getInputStream());
jaxElement = unmarshaller.unmarshal(xml, ClassConfig.class);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
exeception = new Exception("IO");
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
exeception = new Exception("SAX");
} catch (JAXBException e) {
// TODO Auto-generated catch block
e.printStackTrace();
exeception = new Exception("JAXB");
}
return jaxElement.getValue();
}
}
9.DDSDAO
package net.atpco.dds.offline.filing.common.datamapper.binder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
public abstract class DDSDAO {
@Autowired
protected transient NamedParameterJdbcTemplate namedJdbcTemplate;
protected JdbcTemplate getJdbcTemplate() {
return ((JdbcTemplate) this.namedJdbcTemplate.getJdbcOperations());
}
}
10.Invoker
package net.atpco.dds.offline.filing.common.datamapper.binder;
import java.lang.reflect.InvocationTargetException;
public interface Invoker {
Object invoke(Object target, Object[] args) throws IllegalAccessException,
InvocationTargetException;
}
11.MethodInvoker
package net.atpco.dds.offline.filing.common.datamapper.binder;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Responsible for invoking the target methods.
*
* @author atp1axi
* @version 1.0
*
*/
public class MethodInvoker implements Invoker {
private transient final Method method;
public MethodInvoker(final Method method) {
this.method = method;
}
@Override
public Object invoke(final Object target, final Object[] args)
throws IllegalAccessException, InvocationTargetException {
return method.invoke(target, args);
}
}
12.Mode
package net.atpco.dds.offline.filing.common.datamapper.binder;
/**
* Defines the CRUD mode. Currently it supports only insert and update.
*
* @author atp1axi
* @version 1.0
*
*/
public enum Mode {
INSERT, UPDATE;
}
13.Preparable
package net.atpco.dds.offline.filing.common.datamapper.binder;
import net.atpco.dds.offline.filing.common.datamapper.parser.ClassConfig;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
/**
* Responsible for preparing the sql (insert/update)
*
* @author atp1axi
* @version 1.0
*
*/
public interface Preparable {
/**
* Prepare the sql based on the configuration and mode (Insert/update)
*/
String prepareSql(ClassConfig config, Mode mode);
/**
* Prepared the parameter in the form of MapSqlParameterSource which has an option of setting
* the jdbc type.
*
* @param config
* @param object
* @return
*/
MapSqlParameterSource prepareSqlParameter(final Mode mode, final ClassConfig config, final Object object);
}
14.PropertyAccessor
package net.atpco.dds.offline.filing.common.datamapper.binder;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
/**
* Responsible for accessing the properties dynamically.
* It supports all java bean standard(getters and setters), chained method invocation,
* list, map, and arrays.
*
* @author atp1axi
* @version 1.0
*
*/
@Component(value="propertyAccessor")
public class PropertyAccessor {
private static final Object[] NO_ARGUMENTS = new Object[0];
@Autowired
@Qualifier("dataLoadConfig")
private transient DataLoadConfig dataLoadConfig;
/**
* Gets an Object property from a bean. If the property name
* has "." it should navigate to the next property to access the value
*
* @param object
* The bean
* @param name
* The property name
* @return The property value (as an Object)
*/
public Object getObject(final Object object, final String name) {
return getProperty(object, name);
}
/**
* Access the chained property or collections
* @param object
* @param name
* @return
*/
@SuppressWarnings("rawtypes")
private Object getProperty(final Object object, final String name) {
Object value = null;
if (name.indexOf(‘[‘) > -1) {
value = getIndexedProperty(object, name);
} else {
if (object instanceof Map) {
value = ((Map) object).get(name);
} else {
final ClassInfo classCache = dataLoadConfig.getClassInfo(object
.getClass());
final Invoker method = classCache.getGetInvoker(name);
try {
value = method.invoke(object, NO_ARGUMENTS);
} catch (final Exception e) {
}
}
}
return value;
}
/**
* Access the indexed property like List.
* @param object
* @param indexedName
* @return
*/
@SuppressWarnings("rawtypes")
private Object getIndexedProperty(final Object object, final String indexedName) {
Object value = null;
try {
final String name = indexedName.substring(0, indexedName.indexOf(‘[‘));
final int idx = Integer.parseInt(indexedName.substring(
indexedName.indexOf(‘[‘) + 1, indexedName.indexOf(‘]‘)));
final Object list = getProperty(object, name);
if (list instanceof List) {
value = ((List) list).get(idx);
} else if (list instanceof Object[]) {
value = ((Object[]) list)[idx];
} else if (list instanceof char[]) {
value = new Character(((char[]) list)[idx]);
} else if (list instanceof boolean[]) {
//value = new Boolean(((boolean[]) list)[i]);
value = Boolean.valueOf(((boolean[]) list)[idx]);
} else if (list instanceof byte[]) {
value = Byte.valueOf(((byte[]) list)[idx]);
} else if (list instanceof double[]) {
value = Double.valueOf(((double[]) list)[idx]);
} else if (list instanceof float[]) {
value = Float.valueOf(((float[]) list)[idx]);
} else if (list instanceof int[]) {
value = Integer.valueOf(((int[]) list)[idx]);
} else if (list instanceof long[]) {
value = Long.valueOf(((long[]) list)[idx]);
} else {
}
} catch (final Exception e) {
}
return value;
}
}
15.SqlPreparator
package net.atpco.dds.offline.filing.common.datamapper.binder;
import net.atpco.dds.offline.filing.common.datamapper.parser.ClassConfig;
import net.atpco.dds.offline.filing.common.datamapper.parser.PropertyConfig;
import org.apache.log4j.Logger;
import org.omg.CORBA.portable.ApplicationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.SqlParameterValue;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.stereotype.Component;
/**
* Responsible for preparing the sql and their values
*
* @author atp1axi
* @version 1.0
*
*/
@Component("sqlPreparator")
public class SqlPreparator implements Preparable {
private static Logger LOGGER = Logger.getLogger(SqlPreparator.class);
@Autowired
@Qualifier("propertyAccessor")
private transient PropertyAccessor propertyAccessor;
@Autowired
@Qualifier("dataLoadConfig")
private transient DataLoadConfig dataLoadConfig;
@Override
public String prepareSql(final ClassConfig config, final Mode mode) {
String sql = null;
if (Mode.INSERT.equals(mode)) {
sql = prepareInsertSql(config);
} else if (Mode.UPDATE.equals(mode)) {
sql = prepareUpdateSql(config);
}
return sql;
}
/**
* Prepare the insert query. The values will be substituted with the
* property name prepended with colon on it.
*
* @param config
* @return
* @throws ApplicationException
*/
private String prepareInsertSql(final ClassConfig config) {
final StringBuilder sqlBuilder = new StringBuilder(512);
sqlBuilder.append(" INSERT INTO ")
.append(config.getTableName()).append(" ( ");
final StringBuilder keyBuilder = new StringBuilder(512);
final StringBuilder valueBuilder = new StringBuilder(512);
valueBuilder.append(" VALUES ( ");
for (final PropertyConfig pConfig : config.getPropertyConfigs()) {
keyBuilder.append(" ").append(pConfig.getColumnName()).append(",");
valueBuilder.append(":").append(pConfig.getName()).append(",");
}
keyBuilder.replace(keyBuilder.length() - 1, keyBuilder.length(), " ) ");
valueBuilder.replace(valueBuilder.length() - 1, valueBuilder.length(),
" ) ");
sqlBuilder.append(keyBuilder).append(valueBuilder);
LOGGER.info("Query builder : " + sqlBuilder.toString());
return sqlBuilder.toString();
}
/**
* Prepare the update query. The values will be substituted with the
* property name prepended with colon on it.
*
* @param config
* @return
* @throws ApplicationException
*/
private String prepareUpdateSql(final ClassConfig config) {
final StringBuilder sqlBuilder = new StringBuilder(512);
sqlBuilder.append("UPDATE ").append(config.getSchemaName())
.append(config.getTableName()).append(" SET ");
final StringBuilder keyValueBuilder = new StringBuilder(512);
final StringBuilder whereClsBuilder = new StringBuilder(512);
whereClsBuilder.append(" WHERE ");
for (final PropertyConfig pConfig : config.getPropertyConfigs()) {
if ("true".equalsIgnoreCase(pConfig.getIncludeClause())) {
whereClsBuilder.append(" ").append(pConfig.getColumnName())
.append(" = ").append(":").append(pConfig.getName())
.append(" AND ");
} else if (!"CREATE_SYSTEM".equals(pConfig.getName())) {
keyValueBuilder.append(" ").append(pConfig.getColumnName())
.append(" = ").append(":").append(pConfig.getName())
.append(",");
}
}
// remove the comma
keyValueBuilder.delete(keyValueBuilder.length() - 1,
keyValueBuilder.length());
whereClsBuilder.delete(whereClsBuilder.length() - 4,
whereClsBuilder.length());
sqlBuilder.append(keyValueBuilder).append(whereClsBuilder);
return sqlBuilder.toString();
}
@Override
public MapSqlParameterSource prepareSqlParameter(Mode mode,
ClassConfig config, Object object) {
final MapSqlParameterSource parameterSource = new MapSqlParameterSource();
for (final PropertyConfig pConfig : config.getPropertyConfigs()) {
if(Mode.INSERT.equals(mode) && ("CREATE_SYSTEM".equals(pConfig.getName()) ||
"UPDATE_ID".equals(pConfig.getName()))) {
final SqlParameterValue parameterValue = new SqlParameterValue(
dataLoadConfig.getJdbcType(pConfig.getSqlType()), Util.getUserId());
parameterSource.addValue(pConfig.getName(), parameterValue);
continue;
} else if (Mode.UPDATE.equals(mode)) {
//Do not set the create audit column when trying to update.
//Concentrate only to set the update audit column on update mode
if("CREATE_SYSTEM".equals(pConfig.getName())) {
continue;
} else if("UPDATE_SYSTEM".equals(pConfig.getName())) {
final SqlParameterValue parameterValue = new SqlParameterValue(
dataLoadConfig.getJdbcType(pConfig.getSqlType()), "ATPSTYZ");
parameterSource.addValue(pConfig.getName(), parameterValue);
continue;
}
}
Object obj = propertyAccessor.getObject(object, pConfig.getName());
/*if (obj != null
&& DatePart.class.getName().equals(pConfig.getJavaType())) {
obj = ((DatePart) obj).convertToSqlDate();
}*/
final SqlParameterValue parameterValue = new SqlParameterValue(
dataLoadConfig.getJdbcType(pConfig.getSqlType()), obj);
parameterSource.addValue(pConfig.getName(), parameterValue);
}
return parameterSource;
}
}