DATADOC-98 - Fixes for multi-dimensional arrays and lists as properties.
This commit is contained in:
@@ -61,6 +61,7 @@ import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.model.PersistentEntity;
|
||||
import org.springframework.data.mapping.model.PersistentProperty;
|
||||
import org.springframework.data.mapping.model.PreferredConstructor;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
@@ -205,9 +206,11 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
|
||||
if (null != applicationContext) {
|
||||
spelCtx.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
||||
}
|
||||
String[] keySet = dbo.keySet().toArray(new String[]{});
|
||||
for (String key : keySet) {
|
||||
spelCtx.setVariable(key, dbo.get(key));
|
||||
if (!(dbo instanceof BasicDBList)) {
|
||||
String[] keySet = dbo.keySet().toArray(new String[]{});
|
||||
for (String key : keySet) {
|
||||
spelCtx.setVariable(key, dbo.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
final List<String> ctorParamNames = new ArrayList<String>();
|
||||
@@ -215,18 +218,21 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
|
||||
public Object getParameterValue(PreferredConstructor.Parameter parameter) {
|
||||
String name = parameter.getName();
|
||||
Class<?> type = parameter.getType();
|
||||
ClassTypeInformation typeInfo = new ClassTypeInformation(type);
|
||||
Object obj = dbo.get(name);
|
||||
|
||||
ctorParamNames.add(name);
|
||||
if (obj instanceof DBRef) {
|
||||
ctorParamNames.add(name);
|
||||
return read(type, ((DBRef) obj).fetch());
|
||||
} else if (obj instanceof BasicDBList) {
|
||||
BasicDBList objAsDbList = (BasicDBList) obj;
|
||||
List<?> l = unwrapList(objAsDbList, type);
|
||||
return conversionService.convert(l, parameter.getRawType());
|
||||
} else if (obj instanceof DBObject) {
|
||||
ctorParamNames.add(name);
|
||||
return read(type, ((DBObject) obj));
|
||||
} else if (null != obj && obj.getClass().isAssignableFrom(type)) {
|
||||
ctorParamNames.add(name);
|
||||
return obj;
|
||||
} else if (null != obj) {
|
||||
ctorParamNames.add(name);
|
||||
return conversionService.convert(obj, type);
|
||||
}
|
||||
|
||||
@@ -300,7 +306,7 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
|
||||
|
||||
if (null == entity) {
|
||||
// Must not have explictly added this entity yet
|
||||
entity = mappingContext.addPersistentEntity(obj.getClass());
|
||||
entity = mappingContext.addPersistentEntity(obj.getClass());
|
||||
if (null == entity) {
|
||||
// We can't map this entity for some reason
|
||||
throw new MappingException("Unable to map entity " + obj);
|
||||
@@ -310,7 +316,7 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
|
||||
// Write the ID
|
||||
final PersistentProperty idProperty = entity.getIdProperty();
|
||||
if (!dbo.containsField("_id") && null != idProperty) {
|
||||
Object idObj = null;
|
||||
Object idObj;
|
||||
try {
|
||||
idObj = MappingBeanHelper.getProperty(obj, idProperty, Object.class, useFieldAccessOnly);
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -327,13 +333,13 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Write the properties
|
||||
entity.doWithProperties(new PropertyHandler() {
|
||||
public void doWithPersistentProperty(PersistentProperty prop) {
|
||||
String name = prop.getName();
|
||||
Class<?> type = prop.getType();
|
||||
Object propertyObj = null;
|
||||
Object propertyObj;
|
||||
try {
|
||||
propertyObj = MappingBeanHelper.getProperty(obj, prop, type, useFieldAccessOnly);
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -355,7 +361,7 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
|
||||
public void doWithAssociation(Association association) {
|
||||
PersistentProperty inverseProp = association.getInverse();
|
||||
Class<?> type = inverseProp.getType();
|
||||
Object propertyObj = null;
|
||||
Object propertyObj;
|
||||
try {
|
||||
propertyObj = MappingBeanHelper.getProperty(obj, inverseProp, type, useFieldAccessOnly);
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -419,8 +425,25 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
|
||||
DBRef dbRef = createDBRef(propObjItem, dbref);
|
||||
dbList.add(dbRef);
|
||||
} else if (type.isArray() && MappingBeanHelper.isSimpleType(type.getComponentType())) {
|
||||
dbList.add(propObjItem);
|
||||
} else if (MappingBeanHelper.isSimpleType(propObjItem.getClass())) {
|
||||
dbList.add(propObjItem);
|
||||
} else if (propObjItem instanceof List) {
|
||||
List<?> propObjColl = (List<?>) propObjItem;
|
||||
ClassTypeInformation typeInfo = new ClassTypeInformation(propObjItem.getClass());
|
||||
while (typeInfo.isCollectionLike()) {
|
||||
typeInfo = new ClassTypeInformation(typeInfo.getComponentType().getType());
|
||||
}
|
||||
if (MappingBeanHelper.isSimpleType(typeInfo.getType())) {
|
||||
dbList.add(propObjColl);
|
||||
} else {
|
||||
BasicDBList propNestedDbList = new BasicDBList();
|
||||
for (Object propNestedObjItem : propObjColl) {
|
||||
BasicDBObject propDbObj = new BasicDBObject();
|
||||
write(propNestedObjItem, propDbObj);
|
||||
propNestedDbList.add(propDbObj);
|
||||
}
|
||||
dbList.add(propNestedDbList);
|
||||
}
|
||||
} else if (MappingBeanHelper.isSimpleType(propObjItem.getClass())) {
|
||||
dbList.add(propObjItem);
|
||||
} else {
|
||||
BasicDBObject propDbObj = new BasicDBObject();
|
||||
@@ -558,15 +581,15 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
|
||||
return Array.newInstance(prop.getComponentType(), 0);
|
||||
} else if (prop.isCollection() && dbObj instanceof BasicDBList) {
|
||||
BasicDBList dbObjList = (BasicDBList) dbObj;
|
||||
Object[] items = (Object[]) Array.newInstance(prop.getComponentType(), dbObjList.size());
|
||||
List<Object> items = new LinkedList<Object>();
|
||||
for (int i = 0; i < dbObjList.size(); i++) {
|
||||
Object dbObjItem = dbObjList.get(i);
|
||||
if (dbObjItem instanceof DBRef) {
|
||||
items[i] = read(prop.getComponentType(), ((DBRef) dbObjItem).fetch());
|
||||
items.add(read(prop.getComponentType(), ((DBRef) dbObjItem).fetch()));
|
||||
} else if (dbObjItem instanceof DBObject) {
|
||||
items[i] = read(prop.getComponentType(), (DBObject) dbObjItem);
|
||||
items.add(read(prop.getComponentType(), (DBObject) dbObjItem));
|
||||
} else {
|
||||
items[i] = dbObjItem;
|
||||
items.add(dbObjItem);
|
||||
}
|
||||
}
|
||||
List<Object> itemsToReturn = new LinkedList<Object>();
|
||||
@@ -612,25 +635,23 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
|
||||
}
|
||||
}
|
||||
|
||||
protected <T> List<?> unwrapList(BasicDBList dbList, Class<T> targetType) {
|
||||
List<Object> rootList = new LinkedList<Object>();
|
||||
for (int i = 0; i < dbList.size(); i++) {
|
||||
Object obj = dbList.get(i);
|
||||
if (obj instanceof BasicDBList) {
|
||||
rootList.add(unwrapList((BasicDBList) obj, targetType));
|
||||
} else if (obj instanceof DBObject) {
|
||||
rootList.add(read(targetType, (DBObject) obj));
|
||||
} else {
|
||||
rootList.add(obj);
|
||||
}
|
||||
}
|
||||
return rootList;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
initializeConverters();
|
||||
}
|
||||
|
||||
protected class PersistentPropertyWrapper {
|
||||
private final PersistentProperty property;
|
||||
private final DBObject target;
|
||||
|
||||
public PersistentPropertyWrapper(PersistentProperty property, DBObject target) {
|
||||
this.property = property;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public PersistentProperty getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public DBObject getTarget() {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,31 +25,34 @@ import org.apache.commons.logging.LogFactory;
|
||||
*/
|
||||
public class LoggingEventListener<MongoMappingEvent> extends AbstractMappingEventListener {
|
||||
|
||||
private Log log = LogFactory.getLog(getClass());
|
||||
private Log log = LogFactory.getLog(getClass());
|
||||
|
||||
@Override
|
||||
public void onBeforeConvert(Object source) {
|
||||
log.info("onBeforeConvert: " + source);
|
||||
}
|
||||
@Override
|
||||
public void onBeforeConvert(Object source) {
|
||||
log.info("onBeforeConvert: " + source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBeforeSave(Object source, DBObject dbo) {
|
||||
log.info("onBeforeSave: " + source + ", " + dbo);
|
||||
}
|
||||
@Override
|
||||
public void onBeforeSave(Object source, DBObject dbo) {
|
||||
try {
|
||||
log.info("onBeforeSave: " + source + ", " + dbo);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterSave(Object source, DBObject dbo) {
|
||||
log.info("onAfterSave: " + source + ", " + dbo);
|
||||
}
|
||||
@Override
|
||||
public void onAfterSave(Object source, DBObject dbo) {
|
||||
log.info("onAfterSave: " + source + ", " + dbo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterLoad(DBObject dbo) {
|
||||
log.info("onAfterLoad: " + dbo);
|
||||
}
|
||||
@Override
|
||||
public void onAfterLoad(DBObject dbo) {
|
||||
log.info("onAfterLoad: " + dbo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterConvert(DBObject dbo, Object source) {
|
||||
log.info("onAfterConvert: " + dbo + ", " + source);
|
||||
}
|
||||
@Override
|
||||
public void onAfterConvert(DBObject dbo, Object source) {
|
||||
log.info("onAfterConvert: " + dbo + ", " + source);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@ public class MappingTests {
|
||||
"personmapproperty",
|
||||
"personpojo",
|
||||
"personcustomidname",
|
||||
"personmultidimarrays",
|
||||
"personmulticollection",
|
||||
"person1",
|
||||
"person2",
|
||||
"account"
|
||||
@@ -262,4 +264,39 @@ public class MappingTests {
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiDimensionalArrayProperties() {
|
||||
String[][] grid = new String[][]{
|
||||
new String[]{"1", "2", "3", "4"},
|
||||
new String[]{"5", "6", "7", "8"},
|
||||
new String[]{"9", "10", "11", "12"}
|
||||
};
|
||||
PersonMultiDimArrays p = new PersonMultiDimArrays(123, "Multi", "Dimensional", grid);
|
||||
|
||||
template.insert(p);
|
||||
List<PersonMultiDimArrays> result = template.find(new Query(Criteria.where("ssn").is(123)), PersonMultiDimArrays.class);
|
||||
assertThat(result.size(), is(1));
|
||||
|
||||
assertThat(result.get(0).getGrid().length, is(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiDimensionalCollectionProperties() {
|
||||
List<List<String>> grid = new ArrayList<List<String>>();
|
||||
ArrayList<String> inner = new ArrayList<String>();
|
||||
inner.add("1");
|
||||
inner.add("2");
|
||||
inner.add("3");
|
||||
inner.add("4");
|
||||
grid.add(inner);
|
||||
|
||||
PersonMultiCollection p = new PersonMultiCollection(321, "Multi Dim", "Collections", grid);
|
||||
template.insert(p);
|
||||
|
||||
List<PersonMultiCollection> result = template.find(new Query(Criteria.where("ssn").is(321)), PersonMultiCollection.class);
|
||||
assertThat(result.size(), is(1));
|
||||
|
||||
assertThat(result.get(0).getGrid().size(), is(1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.mongodb.mapping;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
*/
|
||||
public class PersonMultiCollection extends BasePerson {
|
||||
|
||||
private List<List<String>> grid;
|
||||
|
||||
public PersonMultiCollection(Integer ssn, String firstName, String lastName, List<List<String>> grid) {
|
||||
super(ssn, firstName, lastName);
|
||||
this.grid = grid;
|
||||
}
|
||||
|
||||
public List<List<String>> getGrid() {
|
||||
return grid;
|
||||
}
|
||||
|
||||
public void setGrid(List<List<String>> grid) {
|
||||
this.grid = grid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.mongodb.mapping;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
*/
|
||||
public class PersonMultiDimArrays extends BasePerson {
|
||||
|
||||
private String[][] grid;
|
||||
|
||||
public PersonMultiDimArrays(Integer ssn, String firstName, String lastName, String[][] grid) {
|
||||
super(ssn, firstName, lastName);
|
||||
this.grid = grid;
|
||||
}
|
||||
|
||||
public String[][] getGrid() {
|
||||
return grid;
|
||||
}
|
||||
|
||||
public void setGrid(String[][] grid) {
|
||||
this.grid = grid;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user