List<Map>에서 DataSet으로 변환 시 dynamic 하게 컬럼 추가할 수 있도록 변경

This commit is contained in:
ParkSeongMin
2015-12-17 17:38:42 +09:00
parent 5ac3e2db2d
commit 70b1bfa85e
2 changed files with 771 additions and 708 deletions

View File

@@ -1,347 +1,363 @@
package com.nexacro.spring.data.support;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.beans.InvalidPropertyException;
import org.springframework.beans.PropertyAccessException;
import com.nexacro.spring.data.DataSetRowTypeAccessor;
import com.nexacro.spring.data.DataSetSavedDataAccessor;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.util.ReflectionUtil;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.datatype.DataType;
import com.nexacro.xapi.data.datatype.PlatformDataType;
/**
* <p><code>DataSet</code> 데이터를 POJO 혹은 Map 형태의 데이터로 변환히기 위한 추상 클래스이다.
* @author Park SeongMin
* @since 08.11.2015
* @version 1.0
* @see
*/
public class AbstractDataSetConverter extends AbstractListenerHandler {
/***************************************************************************************************/
/************************************** Object -> DataSet ****************************************/
/***************************************************************************************************/
/**
* Map에 존재하는 데이터를 <code>DataSet</code>의 행으로 추가한다.
*
* @param ds
* @param map
* @throws NexacroConvertException
*/
protected void addRowIntoDataSet(DataSet ds, Map map) throws NexacroConvertException {
// ignore null data.
if(map == null) {
return;
}
int newRow = ds.newRow();
Iterator iterator = map.keySet().iterator();
while(iterator.hasNext()) {
Object key = iterator.next();
Object value = map.get(key);
if(!(key instanceof String)) {
throw new NexacroConvertException("must be Map<String, Object> if you use List<Map>. target="+ds.getName());
}
String columnName = (String) key;
if(ignoreSpecfiedColumnName(columnName)) {
continue;
}
// Byte[] 변환
Object object = NexacroConverterHelper.toObject(value);
int columnIndex = ds.indexOfColumn(columnName);
// fire event
object = fireDataSetConvertedValue(ds, object, newRow, columnIndex, false, false);
// add data
ds.set(newRow, columnName, object);
}
}
/**
* bean에 존재하는 데이터를 <code>DataSet</code>의 행으로 추가한다.
*
* @param ds
* @param obj
*/
protected void addRowIntoDataSet(DataSet ds, Object obj) {
if(obj == null) { // ignore null data
return;
}
int newRow = ds.newRow();
NexacroBeanWrapper beanWrapper = NexacroBeanWrapper.createBeanWrapper(obj);
NexacroBeanProperty[] beanProperties = beanWrapper.getProperties();
for(NexacroBeanProperty property: beanProperties) {
// ignore static. constColumn..
if(property.isStatic()) {
continue;
}
String propertyName = property.getPropertyName();
Object propertyValue = beanWrapper.getPropertyValue(property);
// Byte[] 변환
Object object = NexacroConverterHelper.toObject(propertyValue);
int columnIndex = ds.indexOfColumn(propertyName);
// fire event
object = fireDataSetConvertedValue(ds, object, newRow, columnIndex, false, false);
// add data
ds.set(newRow, columnIndex, object);
}
}
/**
* Map의 식별자(key)들을 <code>DataSet</code>의 컬럼으로 추가한다.
* <p>단, 식별자에 해당하는 값이 null인 경우 {@link PlatformDataType#UNDEFINED} 타입으로 지정된다.
* @param ds
* @param map
* @throws NexacroConvertException
*/
protected void addColumnIntoDataSet(DataSet ds, Map map) throws NexacroConvertException {
Iterator iterator = map.keySet().iterator();
while(iterator.hasNext()) {
Object key = iterator.next();
Object value = map.get(key);
if(!(key instanceof String)) {
throw new NexacroConvertException("must be Map<String, Object> if you use List<Map>. target="+ds.getName());
}
String columnName = (String) key;
if(ignoreSpecfiedColumnName(columnName)) {
continue;
}
if(value == null) {
ds.addColumn(columnName, PlatformDataType.UNDEFINED);
continue;
}
// add column
if(!NexacroConverterHelper.isConvertibleType(value.getClass())) {
continue;
}
DataType dataTypeOfValue = NexacroConverterHelper.getDataTypeOfValue(value);
ds.addColumn(columnName, dataTypeOfValue);
}
}
/**
* 입력받은 bean의 멤버필드 정보를 토대로 데이터셋의 <code>DataSet</code>의 컬럼으로 추가한다.
* @param ds
* @param availableFirstData
*/
protected void addColumnIntoDataSet(DataSet ds, Object availableFirstData) {
NexacroBeanWrapper beanWrapper = NexacroBeanWrapper.createBeanWrapper(availableFirstData);
NexacroBeanProperty[] beanProperties = beanWrapper.getProperties();
for(NexacroBeanProperty property: beanProperties) {
String propertyName = property.getPropertyName();
Class<?> propertyType = property.getPropertyType();
if(!NexacroConverterHelper.isConvertibleType(propertyType)) {
continue;
}
DataType dataTypeOfValue = NexacroConverterHelper.getDataType(propertyType);
if(property.isStatic()) {
Object staticValue = beanWrapper.getPropertyValue(property);
// Byte[] 변환
staticValue = NexacroConverterHelper.toObject(staticValue);
int columnIndex = ds.indexOfColumn(propertyName);
// fire event
staticValue = fireDataSetConvertedValue(ds, staticValue, -1, columnIndex, false, false);
ds.addConstantColumn(propertyName, dataTypeOfValue, staticValue);
} else {
ds.addColumn(propertyName, dataTypeOfValue);
}
}
}
/**
* <code>DataSet</code>의 컬럼이름들을 반환한다.
* @param ds
* @return
*/
protected String[] getDataSetColumnNames(DataSet ds) {
int columnCount = ds.getColumnCount();
String[] columnNames = new String[columnCount];
for(int i=0; i<columnNames.length; i++) {
columnNames[i] = ds.getColumn(i).getName();
}
return columnNames;
}
/***************************************************************************************************/
/************************************** DataSet -> Object ****************************************/
/***************************************************************************************************/
/**
* 입력받은 <code>DataSet</code>의 행의 위치(rowIndex)에 해당하는 값을 Map에 저장한다.
* @param dataMap
* @param ds
* @param rowIndex
* @param columnNames
*/
protected void addRowIntoMap(Map<String, Object> dataMap, DataSet ds, int rowIndex, String[] columnNames) {
int rowType = ds.getRowType(rowIndex);
for(int columnIndex=0; columnIndex<columnNames.length; columnIndex++) {
Object object = ds.getObject(rowIndex, columnIndex);
// fire event
object = fireDataSetConvertedValue(ds, object, rowIndex, columnIndex, false, false);
dataMap.put(columnNames[columnIndex], object);
}
// saved data
if(ds.hasSavedRow(rowIndex)) {
Map<String, Object> savedDataRow = new HashMap<String, Object>();
for(int columnIndex=0; columnIndex<columnNames.length; columnIndex++) {
Object object = ds.getSavedData(rowIndex, columnIndex);
// fire event
object = fireDataSetConvertedValue(ds, object, rowIndex, columnIndex, true, false);
savedDataRow.put(columnNames[columnIndex], object);
}
// set saved data
dataMap.put(DataSetSavedDataAccessor.NAME, savedDataRow);
}
// row type
dataMap.put(DataSetRowTypeAccessor.NAME, rowType);
}
/**
* 입력받은 <code>DataSet</code>의 행의 위치(rowIndex)에 해당하는 값을 bean에 저장한다.
* <p>원본데이터와 행의 타입도 저장된다.
* @param beanWrapper
* @param ds
* @param rowIndex
* @throws NexacroConvertException
* @see DataSetRowTypeAccessor
* @see DataSetSavedDataAccessor
*/
protected void addRowAndOrgRowIntoBean(NexacroBeanWrapper beanWrapper, DataSet ds, int rowIndex) throws NexacroConvertException {
boolean isSavedData = false;
boolean isRemovedData = false;
addRowIntoBean(beanWrapper, ds, rowIndex, isSavedData, isRemovedData);
// set saved data
if(ds.hasSavedRow(rowIndex)) {
Object bean = beanWrapper.getInstance();
Class<?> beanType = bean.getClass();
if(ReflectionUtil.isImplemented(beanType, DataSetSavedDataAccessor.class)) {
isSavedData = true;
NexacroBeanWrapper savedBeanWrapper = NexacroBeanWrapper.createBeanWrapper(beanType);
addRowIntoBean(savedBeanWrapper, ds, rowIndex, isSavedData, isRemovedData);
DataSetSavedDataAccessor accessor = (DataSetSavedDataAccessor) bean;
accessor.setData(savedBeanWrapper.getInstance());
}
}
}
/**
* 입력받은 <code>DataSet</code>의 행의 위치(rowIndex)에 해당하는 값을 bean에 저장한다.
* <p>행의 타입(rowType)이 저장된다.
* @param beanWrapper
* @param ds
* @param rowIndex
* @param isSavedData
* @param isRemovedData
* @throws NexacroConvertException
*/
protected void addRowIntoBean(NexacroBeanWrapper beanWrapper,
DataSet ds, int rowIndex, boolean isSavedData, boolean isRemovedData) throws NexacroConvertException {
NexacroBeanProperty[] beanProperties = beanWrapper.getProperties();
for(NexacroBeanProperty property: beanProperties) {
String propertyName = property.getPropertyName();
int columnIndex = ds.indexOfColumn(propertyName);
if(columnIndex == -1) {
continue;
}
Class<?> propertyType = property.getPropertyType();
Object convertDataSetValue =
NexacroConverterHelper.toObjectFromDataSetValue(ds, rowIndex, columnIndex, propertyType, isSavedData, isRemovedData);
// fire event
convertDataSetValue = fireDataSetConvertedValue(ds, convertDataSetValue, rowIndex, columnIndex, isSavedData, isRemovedData);
try {
beanWrapper.setPropertyValue(property, convertDataSetValue);
} catch (InvalidPropertyException e) {
throw new NexacroConvertException(e.getMessage(), e);
} catch (PropertyAccessException e) {
throw new NexacroConvertException(e.getMessage(), e);
} catch (BeansException e) {
throw new NexacroConvertException(e.getMessage(), e);
}
}
Object bean = beanWrapper.getInstance();
Class beanType = bean.getClass();
// row type
if(ReflectionUtil.isImplemented(beanType, DataSetRowTypeAccessor.class)) {
int rowType;
if(isRemovedData) {
rowType = DataSet.ROW_TYPE_DELETED;
} else if(isSavedData){
rowType = DataSet.ROW_TYPE_NORMAL;
} else {
rowType = ds.getRowType(rowIndex);
}
DataSetRowTypeAccessor accessor = (DataSetRowTypeAccessor) bean;
accessor.setRowType(rowType);
}
}
protected boolean ignoreSpecfiedColumnName(String columnName) {
if(DataSetRowTypeAccessor.NAME.equals(columnName) || DataSetSavedDataAccessor.NAME.equals(columnName)) {
// DataSetRowType, DataSetSavedData는 무시한다.
return true;
}
return false;
}
}
package com.nexacro.spring.data.support;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.beans.InvalidPropertyException;
import org.springframework.beans.PropertyAccessException;
import com.nexacro.spring.data.DataSetRowTypeAccessor;
import com.nexacro.spring.data.DataSetSavedDataAccessor;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.util.ReflectionUtil;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.datatype.DataType;
import com.nexacro.xapi.data.datatype.PlatformDataType;
/**
* <p><code>DataSet</code> 데이터를 POJO 혹은 Map 형태의 데이터로 변환히기 위한 추상 클래스이다.
* @author Park SeongMin
* @since 08.11.2015
* @version 1.0
* @see
*/
public class AbstractDataSetConverter extends AbstractListenerHandler {
/***************************************************************************************************/
/************************************** Object -> DataSet ****************************************/
/***************************************************************************************************/
/**
* Map에 존재하는 데이터를 <code>DataSet</code>의 행으로 추가한다.
*
* @param ds
* @param map
* @throws NexacroConvertException
*/
protected void addRowIntoDataSet(DataSet ds, Map map) throws NexacroConvertException {
// ignore null data.
if(map == null) {
return;
}
int newRow = ds.newRow();
Iterator iterator = map.keySet().iterator();
while(iterator.hasNext()) {
Object key = iterator.next();
Object value = map.get(key);
if(!(key instanceof String)) {
throw new NexacroConvertException("must be Map<String, Object> if you use List<Map>. target="+ds.getName());
}
String columnName = (String) key;
if (ignoreSpecfiedColumnName(columnName)) {
continue;
}
// Byte[] 변환
Object object = NexacroConverterHelper.toObject(value);
int columnIndex = ds.indexOfColumn(columnName);
if(columnIndex < 0) {
// flexible map data. 'null' data should be ignored
ds.setChangeStructureWithData(true);
if(!addColumnByMap(ds, columnName, value)) {
continue;
}
}
// fire event
object = fireDataSetConvertedValue(ds, object, newRow, columnIndex, false, false);
// add data
ds.set(newRow, columnName, object);
}
}
/**
* bean에 존재하는 데이터를 <code>DataSet</code>의 행으로 추가한다.
*
* @param ds
* @param obj
*/
protected void addRowIntoDataSet(DataSet ds, Object obj) {
if(obj == null) { // ignore null data
return;
}
int newRow = ds.newRow();
NexacroBeanWrapper beanWrapper = NexacroBeanWrapper.createBeanWrapper(obj);
NexacroBeanProperty[] beanProperties = beanWrapper.getProperties();
for(NexacroBeanProperty property: beanProperties) {
// ignore static. constColumn..
if(property.isStatic()) {
continue;
}
String propertyName = property.getPropertyName();
Object propertyValue = beanWrapper.getPropertyValue(property);
// Byte[] 변환
Object object = NexacroConverterHelper.toObject(propertyValue);
int columnIndex = ds.indexOfColumn(propertyName);
// fire event
object = fireDataSetConvertedValue(ds, object, newRow, columnIndex, false, false);
// add data
ds.set(newRow, columnIndex, object);
}
}
/**
* Map의 식별자(key)들을 <code>DataSet</code>의 컬럼으로 추가한다.
* <p>단, 식별자에 해당하는 값이 null인 경우 {@link PlatformDataType#UNDEFINED} 타입으로 지정된다.
* @param ds
* @param map
* @throws NexacroConvertException
*/
protected void addColumnIntoDataSet(DataSet ds, Map map) throws NexacroConvertException {
Iterator iterator = map.keySet().iterator();
while(iterator.hasNext()) {
Object key = iterator.next();
Object value = map.get(key);
if(!(key instanceof String)) {
throw new NexacroConvertException("must be Map<String, Object> if you use List<Map>. target="+ds.getName());
}
String columnName = (String) key;
boolean isAdded = addColumnByMap(ds, columnName, value);
}
}
/**
* 입력받은 bean의 멤버필드 정보를 토대로 데이터셋의 <code>DataSet</code>의 컬럼으로 추가한다.
* @param ds
* @param availableFirstData
*/
protected void addColumnIntoDataSet(DataSet ds, Object availableFirstData) {
NexacroBeanWrapper beanWrapper = NexacroBeanWrapper.createBeanWrapper(availableFirstData);
NexacroBeanProperty[] beanProperties = beanWrapper.getProperties();
for(NexacroBeanProperty property: beanProperties) {
String propertyName = property.getPropertyName();
Class<?> propertyType = property.getPropertyType();
if(!NexacroConverterHelper.isConvertibleType(propertyType)) {
continue;
}
DataType dataTypeOfValue = NexacroConverterHelper.getDataType(propertyType);
if(property.isStatic()) {
Object staticValue = beanWrapper.getPropertyValue(property);
// Byte[] 변환
staticValue = NexacroConverterHelper.toObject(staticValue);
int columnIndex = ds.indexOfColumn(propertyName);
// fire event
staticValue = fireDataSetConvertedValue(ds, staticValue, -1, columnIndex, false, false);
ds.addConstantColumn(propertyName, dataTypeOfValue, staticValue);
} else {
ds.addColumn(propertyName, dataTypeOfValue);
}
}
}
protected boolean addColumnByMap(DataSet ds, String columnName, Object value) {
if (ignoreSpecfiedColumnName(columnName)) {
return false;
}
if (value == null) {
ds.addColumn(columnName, PlatformDataType.UNDEFINED);
return false;
}
// add column
if (!NexacroConverterHelper.isConvertibleType(value.getClass())) {
return false;
}
DataType dataTypeOfValue = NexacroConverterHelper.getDataTypeOfValue(value);
ds.addColumn(columnName, dataTypeOfValue);
return true;
}
/**
* <code>DataSet</code>의 컬럼이름들을 반환한다.
* @param ds
* @return
*/
protected String[] getDataSetColumnNames(DataSet ds) {
int columnCount = ds.getColumnCount();
String[] columnNames = new String[columnCount];
for(int i=0; i<columnNames.length; i++) {
columnNames[i] = ds.getColumn(i).getName();
}
return columnNames;
}
/***************************************************************************************************/
/************************************** DataSet -> Object ****************************************/
/***************************************************************************************************/
/**
* 입력받은 <code>DataSet</code>의 행의 위치(rowIndex)에 해당하는 값을 Map에 저장한다.
* @param dataMap
* @param ds
* @param rowIndex
* @param columnNames
*/
protected void addRowIntoMap(Map<String, Object> dataMap, DataSet ds, int rowIndex, String[] columnNames) {
int rowType = ds.getRowType(rowIndex);
for(int columnIndex=0; columnIndex<columnNames.length; columnIndex++) {
Object object = ds.getObject(rowIndex, columnIndex);
// fire event
object = fireDataSetConvertedValue(ds, object, rowIndex, columnIndex, false, false);
dataMap.put(columnNames[columnIndex], object);
}
// saved data
if(ds.hasSavedRow(rowIndex)) {
Map<String, Object> savedDataRow = new HashMap<String, Object>();
for(int columnIndex=0; columnIndex<columnNames.length; columnIndex++) {
Object object = ds.getSavedData(rowIndex, columnIndex);
// fire event
object = fireDataSetConvertedValue(ds, object, rowIndex, columnIndex, true, false);
savedDataRow.put(columnNames[columnIndex], object);
}
// set saved data
dataMap.put(DataSetSavedDataAccessor.NAME, savedDataRow);
}
// row type
dataMap.put(DataSetRowTypeAccessor.NAME, rowType);
}
/**
* 입력받은 <code>DataSet</code>의 행의 위치(rowIndex)에 해당하는 값을 bean에 저장한다.
* <p>원본데이터와 행의 타입도 저장된다.
* @param beanWrapper
* @param ds
* @param rowIndex
* @throws NexacroConvertException
* @see DataSetRowTypeAccessor
* @see DataSetSavedDataAccessor
*/
protected void addRowAndOrgRowIntoBean(NexacroBeanWrapper beanWrapper, DataSet ds, int rowIndex) throws NexacroConvertException {
boolean isSavedData = false;
boolean isRemovedData = false;
addRowIntoBean(beanWrapper, ds, rowIndex, isSavedData, isRemovedData);
// set saved data
if(ds.hasSavedRow(rowIndex)) {
Object bean = beanWrapper.getInstance();
Class<?> beanType = bean.getClass();
if(ReflectionUtil.isImplemented(beanType, DataSetSavedDataAccessor.class)) {
isSavedData = true;
NexacroBeanWrapper savedBeanWrapper = NexacroBeanWrapper.createBeanWrapper(beanType);
addRowIntoBean(savedBeanWrapper, ds, rowIndex, isSavedData, isRemovedData);
DataSetSavedDataAccessor accessor = (DataSetSavedDataAccessor) bean;
accessor.setData(savedBeanWrapper.getInstance());
}
}
}
/**
* 입력받은 <code>DataSet</code>의 행의 위치(rowIndex)에 해당하는 값을 bean에 저장한다.
* <p>행의 타입(rowType)이 저장된다.
* @param beanWrapper
* @param ds
* @param rowIndex
* @param isSavedData
* @param isRemovedData
* @throws NexacroConvertException
*/
protected void addRowIntoBean(NexacroBeanWrapper beanWrapper,
DataSet ds, int rowIndex, boolean isSavedData, boolean isRemovedData) throws NexacroConvertException {
NexacroBeanProperty[] beanProperties = beanWrapper.getProperties();
for(NexacroBeanProperty property: beanProperties) {
String propertyName = property.getPropertyName();
int columnIndex = ds.indexOfColumn(propertyName);
if(columnIndex == -1) {
continue;
}
Class<?> propertyType = property.getPropertyType();
Object convertDataSetValue =
NexacroConverterHelper.toObjectFromDataSetValue(ds, rowIndex, columnIndex, propertyType, isSavedData, isRemovedData);
// fire event
convertDataSetValue = fireDataSetConvertedValue(ds, convertDataSetValue, rowIndex, columnIndex, isSavedData, isRemovedData);
try {
beanWrapper.setPropertyValue(property, convertDataSetValue);
} catch (InvalidPropertyException e) {
throw new NexacroConvertException(e.getMessage(), e);
} catch (PropertyAccessException e) {
throw new NexacroConvertException(e.getMessage(), e);
} catch (BeansException e) {
throw new NexacroConvertException(e.getMessage(), e);
}
}
Object bean = beanWrapper.getInstance();
Class beanType = bean.getClass();
// row type
if(ReflectionUtil.isImplemented(beanType, DataSetRowTypeAccessor.class)) {
int rowType;
if(isRemovedData) {
rowType = DataSet.ROW_TYPE_DELETED;
} else if(isSavedData){
rowType = DataSet.ROW_TYPE_NORMAL;
} else {
rowType = ds.getRowType(rowIndex);
}
DataSetRowTypeAccessor accessor = (DataSetRowTypeAccessor) bean;
accessor.setRowType(rowType);
}
}
protected boolean ignoreSpecfiedColumnName(String columnName) {
if(DataSetRowTypeAccessor.NAME.equals(columnName) || DataSetSavedDataAccessor.NAME.equals(columnName)) {
// DataSetRowType, DataSetSavedData는 무시한다.
return true;
}
return false;
}
}

View File

@@ -1,361 +1,408 @@
package com.nexacro.spring.data.support;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import com.nexacro.spring.data.convert.ConvertDefinition;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.data.support.NexacroTestUtil.StaticPropertyBean;
import com.nexacro.spring.data.support.bean.DefaultBean;
import com.nexacro.spring.util.ReflectionUtil;
import com.nexacro.xapi.data.ColumnHeader;
import com.nexacro.xapi.data.ConstantColumnHeader;
import com.nexacro.xapi.data.DataSet;
/**
*
* @author Park SeongMin
* @since 08.04.2015
* @version 1.0
* @see
*/
public class ListToDataSetConverterTest {
private ListToDataSetConverter converter;
@Before
public void setUp() {
converter = new ListToDataSetConverter();
}
@Test
public void testSupportedType() {
Class<?> source;
Class<?> target;
boolean canConvert;
source = List.class;
target = DataSet.class;
canConvert = converter.canConvert(source, target);
Assert.assertTrue(source + " to " + target + " must be converted", canConvert);
// List sub class support.
source = ArrayList.class;
target = DataSet.class;
canConvert = converter.canConvert(source, target);
Assert.assertTrue(source + " to " + target + " must be converted", canConvert);
}
@Test
public void testUnSupportedType() {
Class<?> source;
Class<?> target;
boolean canConvert;
source = Object.class;
target = DataSet.class;
canConvert = converter.canConvert(source, target);
Assert.assertFalse(source + " to " + target + " can not convertible", canConvert);
List list = new ArrayList();
list.add(new Object[]{1, 2});
list.add(new Object[]{3, 4});
ConvertDefinition definition = new ConvertDefinition("ds");
try {
converter.convert(list, definition);
Assert.fail("Object[] is unsupported type.");
} catch (NexacroConvertException e) {
}
}
@Test
public void testConvertListBeanToDataSet() {
List<DefaultBean> defaultBean = NexacroTestUtil.createDefaultBeans();
ConvertDefinition definition = new ConvertDefinition("ds");
Object ds = null;
try {
ds = converter.convert(defaultBean, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(ds instanceof DataSet)) {
Assert.fail("converted object must be implemented DataSet");
}
NexacroTestUtil.compareDefaultDataSet((DataSet) ds);
}
@Test
public void testConvertListMapToDataSet() {
List<Map<String, Object>> defaultMap = NexacroTestUtil.createDefaultMaps();
ConvertDefinition definition = new ConvertDefinition("ds");
Object ds = null;
try {
ds = converter.convert(defaultMap, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(ds instanceof DataSet)) {
Assert.fail("converted object must be implemented DataSet");
}
NexacroTestUtil.compareDefaultDataSet((DataSet) ds);
}
@Test
public void testNullData() {
List list = null;
ConvertDefinition definition = new ConvertDefinition("ds");
DataSet ds = null;
try {
ds = converter.convert(list, definition);
} catch (NexacroConvertException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull("dataset should not be null", ds);
Assert.assertEquals("ds", ds.getName());
}
@Test
public void testStaticColumns() {
StaticPropertyBean staticBean;
double commissionPercent = 10.0d;
List<StaticPropertyBean> staticBeanList = new ArrayList<StaticPropertyBean>();
staticBean = new StaticPropertyBean();
staticBean.setName("tom");
staticBean.setCommissionPercent(commissionPercent);
staticBeanList.add(staticBean);
staticBean = new StaticPropertyBean();
staticBean.setName("david");
staticBeanList.add(staticBean);
ConvertDefinition definition = new ConvertDefinition("ds");
DataSet ds = null;
try {
ds = converter.convert(staticBeanList, definition);
} catch (NexacroConvertException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull("converted list should not be null.", ds);
int columnCount = ds.getColumnCount();
Assert.assertEquals("two columns must be exist.", 2, ds.getColumnCount());
ColumnHeader column = ds.getColumn("name");
Assert.assertFalse(column.isConstant());
column = ds.getColumn("commissionPercent");
Assert.assertTrue(column.isConstant());
ConstantColumnHeader constColumn = (ConstantColumnHeader) column;
// check const column value
Assert.assertEquals(commissionPercent, constColumn.getValue());
Assert.assertEquals("tom", ds.getString(0, "name"));
Assert.assertEquals("david", ds.getString(1, "name"));
}
@Test
public void testUpperCase() {
}
@Test
public void testLowerCase() {
}
//
@Test
public void testNotSupportedRowType() {
}
@Test
public void testNotSupportedSavedData() {
}
@Test
public void testNotSupportedRemovedData() {
}
@Test
public void testListConvert() {
List<DefaultBean> beanList = new ArrayList<DefaultBean>();
// Result result = new Result();
//// List<?> list = result.getList();
//
//
// DefaultBean bean = new DefaultBean();
// beanList.add(bean);
//
// Object[] array = beanList.toArray();
// array[0].getClass();
//
// Class<? extends List> clazz= beanList.getClass();
//
// ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
// System.out.println(parameterizedType.getRawType());
//
// Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
// for(Type type: actualTypeArguments) {
// System.out.println(type);
// }
DefaultBean bean = new DefaultBean();
beanList.add(bean);
System.out.println("key = " + beanList);
Class<?> clazz = beanList.getClass();
System.out.println("clazz = " + clazz);
ParameterizedType superclass = (ParameterizedType) clazz.getGenericSuperclass();
Type[] types = superclass.getActualTypeArguments();
Class<?> actualdataType = null;
if(types != null && types.length >0 && (types[0] instanceof Class<?>) ) {
actualdataType = (Class<?>) (Class<?>) types[0];
}
System.out.println("actualdataType = " + actualdataType);
}
@Test
public void testListType() {
List<DefaultBean> beanList = new ArrayList<DefaultBean>();
Type[] parameterizedTypes = getParameterizedTypes(beanList);
Class<?> class1;
try {
class1 = getClass(parameterizedTypes[0]);
System.out.println(class1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// List<DefaultBean> beanList = new ArrayList<DefaultBean>();
//
// Class<?> class1 = getClass(beanList.getClass());
// System.out.println(class1);
// System.out.println(getClass(class1));
}
private static final String TYPE_CLASS_NAME_PREFIX = "class ";
private static final String TYPE_INTERFACE_NAME_PREFIX = "interface ";
public static String getClassName(Type type) {
if (type==null) {
return "";
}
String className = type.toString();
if (className.startsWith(TYPE_CLASS_NAME_PREFIX)) {
className = className.substring(TYPE_CLASS_NAME_PREFIX.length());
} else if (className.startsWith(TYPE_INTERFACE_NAME_PREFIX)) {
className = className.substring(TYPE_INTERFACE_NAME_PREFIX.length());
}
return className;
}
/**
* Returns the {@code Class} object associated with the given {@link Type}
* depending on its fully qualified name.
*
* @param type the {@code Type} whose {@code Class} is needed.
* @return the {@code Class} object for the class with the specified name.
*
* @throws ClassNotFoundException if the class cannot be located.
*
* @see {@link ReflectionUtil#getClassName(Type)}
*/
public static Class<?> getClass(Type type) throws ClassNotFoundException {
String className = getClassName(type);
if (className==null || className.isEmpty()) {
return null;
}
return Class.forName(className);
}
public static Type[] getParameterizedTypes(Object object) {
Type superclassType = object.getClass().getGenericSuperclass();
if (!ParameterizedType.class.isAssignableFrom(superclassType.getClass())) {
return null;
}
return ((ParameterizedType)superclassType).getActualTypeArguments();
}
// public static Class<?> getClass(Type type) {
// if (type instanceof Class) {
// return (Class) type;
// }
// else if (type instanceof ParameterizedType) {
// return getClass(((ParameterizedType) type).getRawType());
// }
// else if (type instanceof GenericArrayType) {
// Type componentType = ((GenericArrayType) type).getGenericComponentType();
// Class<?> componentClass = getClass(componentType);
// if (componentClass != null ) {
// return Array.newInstance(componentClass, 0).getClass();
// }
// else {
// return null;
// }
// }
// else {
// return null;
// }
// }
private static class Result {
private List<?> list;
public void setList(List<?> list) {
this.list = list;
}
public List<?> getList() {
return null;
}
}
}
package com.nexacro.spring.data.support;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import com.nexacro.spring.data.convert.ConvertDefinition;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.data.support.NexacroTestUtil.StaticPropertyBean;
import com.nexacro.spring.data.support.bean.DefaultBean;
import com.nexacro.spring.util.ReflectionUtil;
import com.nexacro.xapi.data.ColumnHeader;
import com.nexacro.xapi.data.ConstantColumnHeader;
import com.nexacro.xapi.data.DataSet;
/**
*
* @author Park SeongMin
* @since 08.04.2015
* @version 1.0
* @see
*/
public class ListToDataSetConverterTest {
private ListToDataSetConverter converter;
@Before
public void setUp() {
converter = new ListToDataSetConverter();
}
@Test
public void testSupportedType() {
Class<?> source;
Class<?> target;
boolean canConvert;
source = List.class;
target = DataSet.class;
canConvert = converter.canConvert(source, target);
Assert.assertTrue(source + " to " + target + " must be converted", canConvert);
// List sub class support.
source = ArrayList.class;
target = DataSet.class;
canConvert = converter.canConvert(source, target);
Assert.assertTrue(source + " to " + target + " must be converted", canConvert);
}
@Test
public void testUnSupportedType() {
Class<?> source;
Class<?> target;
boolean canConvert;
source = Object.class;
target = DataSet.class;
canConvert = converter.canConvert(source, target);
Assert.assertFalse(source + " to " + target + " can not convertible", canConvert);
List list = new ArrayList();
list.add(new Object[]{1, 2});
list.add(new Object[]{3, 4});
ConvertDefinition definition = new ConvertDefinition("ds");
try {
converter.convert(list, definition);
Assert.fail("Object[] is unsupported type.");
} catch (NexacroConvertException e) {
}
}
@Test
public void testConvertListBeanToDataSet() {
List<DefaultBean> defaultBean = NexacroTestUtil.createDefaultBeans();
ConvertDefinition definition = new ConvertDefinition("ds");
Object ds = null;
try {
ds = converter.convert(defaultBean, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(ds instanceof DataSet)) {
Assert.fail("converted object must be implemented DataSet");
}
NexacroTestUtil.compareDefaultDataSet((DataSet) ds);
}
@Test
public void testConvertListMapToDataSet() {
List<Map<String, Object>> defaultMap = NexacroTestUtil.createDefaultMaps();
ConvertDefinition definition = new ConvertDefinition("ds");
Object ds = null;
try {
ds = converter.convert(defaultMap, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(ds instanceof DataSet)) {
Assert.fail("converted object must be implemented DataSet");
}
NexacroTestUtil.compareDefaultDataSet((DataSet) ds);
}
@Test
public void testConvertListFlexibleMapToDataSet() {
String addColumnName = "otherColumn";
String addData = "otherColumnData";
List<Map<String, Object>> defaultMap = NexacroTestUtil.createDefaultMaps();
Map<String, Object> otherStructureMap = new HashMap<String, Object>();
otherStructureMap.put(addColumnName, addData);
// add other structure map..
defaultMap.add(otherStructureMap);
ConvertDefinition definition = new ConvertDefinition("ds");
Object ds = null;
try {
ds = converter.convert(defaultMap, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(ds instanceof DataSet)) {
Assert.fail("converted object must be implemented DataSet");
}
DataSet convertedDs = (DataSet) ds;
// original column 12, added column 1
int expectedColumnCount = 12 + 1;
int actualColumnCount = convertedDs.getColumnCount();
Assert.assertEquals("other key in the Map column should be added.", expectedColumnCount, actualColumnCount);
ColumnHeader column = convertedDs.getColumn(addColumnName);
Assert.assertNotNull(column);
// original row 2, added row 1
int expectedRowCount = 2 + 1;
int actualRowCount = convertedDs.getRowCount();
Assert.assertEquals(expectedRowCount, actualRowCount);
String addedData = convertedDs.getString(2, addColumnName);
Assert.assertEquals(addData, addedData);
}
@Test
public void testNullData() {
List list = null;
ConvertDefinition definition = new ConvertDefinition("ds");
DataSet ds = null;
try {
ds = converter.convert(list, definition);
} catch (NexacroConvertException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull("dataset should not be null", ds);
Assert.assertEquals("ds", ds.getName());
}
@Test
public void testStaticColumns() {
StaticPropertyBean staticBean;
double commissionPercent = 10.0d;
List<StaticPropertyBean> staticBeanList = new ArrayList<StaticPropertyBean>();
staticBean = new StaticPropertyBean();
staticBean.setName("tom");
staticBean.setCommissionPercent(commissionPercent);
staticBeanList.add(staticBean);
staticBean = new StaticPropertyBean();
staticBean.setName("david");
staticBeanList.add(staticBean);
ConvertDefinition definition = new ConvertDefinition("ds");
DataSet ds = null;
try {
ds = converter.convert(staticBeanList, definition);
} catch (NexacroConvertException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull("converted list should not be null.", ds);
int columnCount = ds.getColumnCount();
Assert.assertEquals("two columns must be exist.", 2, ds.getColumnCount());
ColumnHeader column = ds.getColumn("name");
Assert.assertFalse(column.isConstant());
column = ds.getColumn("commissionPercent");
Assert.assertTrue(column.isConstant());
ConstantColumnHeader constColumn = (ConstantColumnHeader) column;
// check const column value
Assert.assertEquals(commissionPercent, constColumn.getValue());
Assert.assertEquals("tom", ds.getString(0, "name"));
Assert.assertEquals("david", ds.getString(1, "name"));
}
@Test
public void testUpperCase() {
}
@Test
public void testLowerCase() {
}
//
@Test
public void testNotSupportedRowType() {
}
@Test
public void testNotSupportedSavedData() {
}
@Test
public void testNotSupportedRemovedData() {
}
@Test
public void testListConvert() {
List<DefaultBean> beanList = new ArrayList<DefaultBean>();
// Result result = new Result();
//// List<?> list = result.getList();
//
//
// DefaultBean bean = new DefaultBean();
// beanList.add(bean);
//
// Object[] array = beanList.toArray();
// array[0].getClass();
//
// Class<? extends List> clazz= beanList.getClass();
//
// ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
// System.out.println(parameterizedType.getRawType());
//
// Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
// for(Type type: actualTypeArguments) {
// System.out.println(type);
// }
DefaultBean bean = new DefaultBean();
beanList.add(bean);
System.out.println("key = " + beanList);
Class<?> clazz = beanList.getClass();
System.out.println("clazz = " + clazz);
ParameterizedType superclass = (ParameterizedType) clazz.getGenericSuperclass();
Type[] types = superclass.getActualTypeArguments();
Class<?> actualdataType = null;
if(types != null && types.length >0 && (types[0] instanceof Class<?>) ) {
actualdataType = (Class<?>) (Class<?>) types[0];
}
System.out.println("actualdataType = " + actualdataType);
}
@Test
public void testListType() {
List<DefaultBean> beanList = new ArrayList<DefaultBean>();
Type[] parameterizedTypes = getParameterizedTypes(beanList);
Class<?> class1;
try {
class1 = getClass(parameterizedTypes[0]);
System.out.println(class1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// List<DefaultBean> beanList = new ArrayList<DefaultBean>();
//
// Class<?> class1 = getClass(beanList.getClass());
// System.out.println(class1);
// System.out.println(getClass(class1));
}
private static final String TYPE_CLASS_NAME_PREFIX = "class ";
private static final String TYPE_INTERFACE_NAME_PREFIX = "interface ";
public static String getClassName(Type type) {
if (type==null) {
return "";
}
String className = type.toString();
if (className.startsWith(TYPE_CLASS_NAME_PREFIX)) {
className = className.substring(TYPE_CLASS_NAME_PREFIX.length());
} else if (className.startsWith(TYPE_INTERFACE_NAME_PREFIX)) {
className = className.substring(TYPE_INTERFACE_NAME_PREFIX.length());
}
return className;
}
/**
* Returns the {@code Class} object associated with the given {@link Type}
* depending on its fully qualified name.
*
* @param type the {@code Type} whose {@code Class} is needed.
* @return the {@code Class} object for the class with the specified name.
*
* @throws ClassNotFoundException if the class cannot be located.
*
* @see {@link ReflectionUtil#getClassName(Type)}
*/
public static Class<?> getClass(Type type) throws ClassNotFoundException {
String className = getClassName(type);
if (className==null || className.isEmpty()) {
return null;
}
return Class.forName(className);
}
public static Type[] getParameterizedTypes(Object object) {
Type superclassType = object.getClass().getGenericSuperclass();
if (!ParameterizedType.class.isAssignableFrom(superclassType.getClass())) {
return null;
}
return ((ParameterizedType)superclassType).getActualTypeArguments();
}
// public static Class<?> getClass(Type type) {
// if (type instanceof Class) {
// return (Class) type;
// }
// else if (type instanceof ParameterizedType) {
// return getClass(((ParameterizedType) type).getRawType());
// }
// else if (type instanceof GenericArrayType) {
// Type componentType = ((GenericArrayType) type).getGenericComponentType();
// Class<?> componentClass = getClass(componentType);
// if (componentClass != null ) {
// return Array.newInstance(componentClass, 0).getClass();
// }
// else {
// return null;
// }
// }
// else {
// return null;
// }
// }
private static class Result {
private List<?> list;
public void setList(List<?> list) {
this.list = list;
}
public List<?> getList() {
return null;
}
}
}