SOLR-2708: Further DocumentObjectBinder cleanup

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1159083 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Christopher John Male 2011-08-18 08:29:26 +00:00
parent 04bd9ae73a
commit 3a9bdecab0
2 changed files with 134 additions and 127 deletions

View File

@ -156,7 +156,7 @@ public class DocumentObjectBinder {
gname = "get" + gname.substring(3); gname = "get" + gname.substring(3);
try { try {
getter = setter.getDeclaringClass().getMethod(gname, (Class[]) null); getter = setter.getDeclaringClass().getMethod(gname, (Class[]) null);
} catch( Exception ex ) { } catch (Exception ex) {
// no getter -- don't worry about it... // no getter -- don't worry about it...
if (type == Boolean.class) { if (type == Boolean.class) {
gname = "is" + setter.getName().substring(3); gname = "is" + setter.getName().substring(3);
@ -183,7 +183,7 @@ public class DocumentObjectBinder {
name = setter.getName(); name = setter.getName();
} }
} }
} else if(annotation.value().indexOf('*') >= 0){ //dynamic fields are annotated as @Field("categories_*") } else if (annotation.value().indexOf('*') >= 0) { //dynamic fields are annotated as @Field("categories_*")
//if the field was annotated as a dynamic field, convert the name into a pattern //if the field was annotated as a dynamic field, convert the name into a pattern
//the wildcard (*) is supposed to be either a prefix or a suffix, hence the use of replaceFirst //the wildcard (*) is supposed to be either a prefix or a suffix, hence the use of replaceFirst
name = annotation.value().replaceFirst("\\*", "\\.*"); name = annotation.value().replaceFirst("\\*", "\\.*");
@ -226,14 +226,14 @@ public class DocumentObjectBinder {
//Raw and primitive types //Raw and primitive types
if (types[1] instanceof Class) { if (types[1] instanceof Class) {
//the value could be multivalued then it is a List, Collection, ArrayList //the value could be multivalued then it is a List, Collection, ArrayList
if(types[1]== Collection.class || types[1] == List.class || types[1] == ArrayList.class){ if (types[1]== Collection.class || types[1] == List.class || types[1] == ArrayList.class) {
type = Object.class; type = Object.class;
isList = true; isList = true;
} else{ } else {
//else assume it is a primitive and put in the source type itself //else assume it is a primitive and put in the source type itself
type = (Class) types[1]; type = (Class) types[1];
} }
} else if( types[1] instanceof ParameterizedType) { //Of all the Parameterized types, only List is supported } else if (types[1] instanceof ParameterizedType) { //Of all the Parameterized types, only List is supported
Type rawType = ((ParameterizedType)types[1]).getRawType(); Type rawType = ((ParameterizedType)types[1]).getRawType();
if(rawType== Collection.class || rawType == List.class || rawType == ArrayList.class){ if(rawType== Collection.class || rawType == List.class || rawType == ArrayList.class){
type = Object.class; type = Object.class;
@ -260,62 +260,64 @@ public class DocumentObjectBinder {
* and <code>Map<String, List<Object>></code> for a dynamic field. The key is all matching fieldName's. * and <code>Map<String, List<Object>></code> for a dynamic field. The key is all matching fieldName's.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Object getFieldValue(SolrDocument sdoc){ private Object getFieldValue(SolrDocument solrDocument) {
Object fieldValue = sdoc.getFieldValue(name); Object fieldValue = solrDocument.getFieldValue(name);
if (fieldValue != null) { if (fieldValue != null) {
//this is not a dynamic field. so return te value //this is not a dynamic field. so return the value
return fieldValue; return fieldValue;
} }
if (dynamicFieldNamePatternMatcher == null) {
return null;
}
//reading dynamic field values //reading dynamic field values
if (dynamicFieldNamePatternMatcher != null) { Map<String, Object> allValuesMap = null;
Map<String, Object> allValuesMap = null; List allValuesList = null;
List allValuesList = null; if (isContainedInMap) {
if (isContainedInMap) { allValuesMap = new HashMap<String, Object>();
allValuesMap = new HashMap<String, Object>(); } else {
} else { allValuesList = new ArrayList();
allValuesList = new ArrayList(); }
}
for (String field : sdoc.getFieldNames()) { for (String field : solrDocument.getFieldNames()) {
if (dynamicFieldNamePatternMatcher.matcher(field).find()) { if (dynamicFieldNamePatternMatcher.matcher(field).find()) {
Object val = sdoc.getFieldValue(field); Object val = solrDocument.getFieldValue(field);
if (val == null) { if (val == null) {
continue; continue;
} }
if (isContainedInMap) { if (isContainedInMap) {
if (isList) { if (isList) {
if (!(val instanceof List)) { if (!(val instanceof List)) {
List al = new ArrayList(); List al = new ArrayList();
al.add(val); al.add(val);
val = al; val = al;
}
} else if (isArray) {
if (!(val instanceof List)) {
Object[] arr= (Object[]) Array.newInstance(type,1);
arr[0] = val;
val= arr;
} else {
val = Array.newInstance(type,((List)val).size());
}
} }
allValuesMap.put(field, val); } else if (isArray) {
} else { if (!(val instanceof List)) {
if (val instanceof Collection) { Object[] arr = (Object[]) Array.newInstance(type, 1);
allValuesList.addAll((Collection) val); arr[0] = val;
val = arr;
} else { } else {
allValuesList.add(val); val = Array.newInstance(type, ((List) val).size());
} }
} }
allValuesMap.put(field, val);
} else {
if (val instanceof Collection) {
allValuesList.addAll((Collection) val);
} else {
allValuesList.add(val);
}
} }
} }
if (isContainedInMap) {
return allValuesMap.isEmpty() ? null : allValuesMap;
} else {
return allValuesList.isEmpty() ? null : allValuesList;
}
} }
return null; if (isContainedInMap) {
return allValuesMap.isEmpty() ? null : allValuesMap;
} else {
return allValuesList.isEmpty() ? null : allValuesList;
}
} }
<T> void inject(T obj, SolrDocument sdoc) { <T> void inject(T obj, SolrDocument sdoc) {
@ -327,7 +329,7 @@ public class DocumentObjectBinder {
if (isArray && !isContainedInMap) { if (isArray && !isContainedInMap) {
List list; List list;
if (val.getClass().isArray()) { if (val.getClass().isArray()) {
set(obj,val); set(obj, val);
return; return;
} else if (val instanceof List) { } else if (val instanceof List) {
list = (List) val; list = (List) val;
@ -335,7 +337,7 @@ public class DocumentObjectBinder {
list = new ArrayList(); list = new ArrayList();
list.add(val); list.add(val);
} }
set(obj, list.toArray((Object[]) Array.newInstance(type,list.size()))); set(obj, list.toArray((Object[]) Array.newInstance(type, list.size())));
} else if (isList && !isContainedInMap) { } else if (isList && !isContainedInMap) {
if (!(val instanceof List)) { if (!(val instanceof List)) {
List list = new ArrayList(); List list = new ArrayList();
@ -353,7 +355,6 @@ public class DocumentObjectBinder {
} }
private void set(Object obj, Object v) { private void set(Object obj, Object v) {
if (v != null && type == ByteBuffer.class && v.getClass() == byte[].class) { if (v != null && type == ByteBuffer.class && v.getClass() == byte[].class) {
v = ByteBuffer.wrap((byte[]) v); v = ByteBuffer.wrap((byte[]) v);

View File

@ -27,6 +27,7 @@ import org.apache.solr.common.SolrInputField;
import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.NamedList;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test;
import java.io.StringReader; import java.io.StringReader;
import java.util.Arrays; import java.util.Arrays;
@ -35,74 +36,81 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
public class TestDocumentObjectBinder extends LuceneTestCase import static org.junit.Assert.*;
{
public class TestDocumentObjectBinder extends LuceneTestCase {
public void testSimple() throws Exception { public void testSimple() throws Exception {
DocumentObjectBinder binder = new DocumentObjectBinder(); DocumentObjectBinder binder = new DocumentObjectBinder();
XMLResponseParser parser = new XMLResponseParser(); XMLResponseParser parser = new XMLResponseParser();
NamedList<Object> nl = null; NamedList<Object> nl = parser.processResponse(new StringReader(xml));
nl = parser.processResponse(new StringReader(xml));
QueryResponse res = new QueryResponse(nl, null); QueryResponse res = new QueryResponse(nl, null);
SolrDocumentList solDocList = res.getResults(); SolrDocumentList solDocList = res.getResults();
List<Item> l = binder.getBeans(Item.class,res.getResults()); List<Item> l = binder.getBeans(Item.class,res.getResults());
Assert.assertEquals(solDocList.size(), l.size()); assertEquals(solDocList.size(), l.size());
Assert.assertEquals(solDocList.get(0).getFieldValue("features"), l.get(0).features); assertEquals(solDocList.get(0).getFieldValue("features"), l.get(0).features);
Item item = new Item(); Item item = new Item();
item.id = "aaa"; item.id = "aaa";
item.categories = new String[] { "aaa", "bbb", "ccc" }; item.categories = new String[] {"aaa", "bbb", "ccc"};
SolrInputDocument out = binder.toSolrInputDocument( item ); SolrInputDocument out = binder.toSolrInputDocument(item);
Assert.assertEquals( item.id, out.getFieldValue( "id" ) ); assertEquals(item.id, out.getFieldValue("id"));
SolrInputField catfield = out.getField( "cat" ); SolrInputField catfield = out.getField("cat");
Assert.assertEquals( 3, catfield.getValueCount() ); assertEquals(3, catfield.getValueCount());
Assert.assertEquals( "[aaa, bbb, ccc]", catfield.getValue().toString() );
// Test the error on not settable stuff... List<String> catValues = (List<String>) catfield.getValue();
NotGettableItem ng = new NotGettableItem(); assertEquals("aaa", catValues.get(0));
ng.setInStock( false ); assertEquals("bbb", catValues.get(1));
try { assertEquals("ccc", catValues.get(2));
out = binder.toSolrInputDocument( ng );
Assert.fail( "Should throw an error" );
}
catch( RuntimeException ex ) {
// ok -- this should happen...
}
} }
public void testSingleVal4Array(){
@Test(expected = BindingException.class)
public void testNoGetterError() {
NotGettableItem notGettableItem = new NotGettableItem();
notGettableItem.setInStock(false);
new DocumentObjectBinder().toSolrInputDocument(notGettableItem);
}
public void testSingleVal4Array() {
DocumentObjectBinder binder = new DocumentObjectBinder(); DocumentObjectBinder binder = new DocumentObjectBinder();
SolrDocumentList solDocList = new SolrDocumentList(); SolrDocumentList solDocList = new SolrDocumentList();
SolrDocument d = new SolrDocument(); SolrDocument d = new SolrDocument();
solDocList.add(d); solDocList.add(d);
d.setField("cat","hello"); d.setField("cat", "hello");
List<Item> l = binder.getBeans(Item.class,solDocList); List<Item> l = binder.getBeans(Item.class, solDocList);
Assert.assertEquals("hello", l.get(0).categories[0]); assertEquals("hello", l.get(0).categories[0]);
} }
public void testDynamicFieldBinding(){ public void testDynamicFieldBinding() {
DocumentObjectBinder binder = new DocumentObjectBinder(); DocumentObjectBinder binder = new DocumentObjectBinder();
XMLResponseParser parser = new XMLResponseParser(); XMLResponseParser parser = new XMLResponseParser();
NamedList<Object> nl = parser.processResponse(new StringReader(xml)); NamedList<Object> nl = parser.processResponse(new StringReader(xml));
QueryResponse res = new QueryResponse(nl, null); QueryResponse res = new QueryResponse(nl, null);
List<Item> l = binder.getBeans(Item.class,res.getResults()); List<Item> l = binder.getBeans(Item.class,res.getResults());
Assert.assertArrayEquals(new String[]{"Mobile Store","iPod Store","CCTV Store"}, l.get(3).getAllSuppliers());
Assert.assertTrue(l.get(3).supplier.containsKey("supplier_1")); assertArrayEquals(new String[]{"Mobile Store", "iPod Store", "CCTV Store"}, l.get(3).getAllSuppliers());
Assert.assertTrue(l.get(3).supplier.containsKey("supplier_2")); assertTrue(l.get(3).supplier.containsKey("supplier_1"));
Assert.assertEquals(2, l.get(3).supplier.size()); assertTrue(l.get(3).supplier.containsKey("supplier_2"));
Assert.assertEquals("[Mobile Store, iPod Store]", l.get(3).supplier.get("supplier_1").toString()); assertEquals(2, l.get(3).supplier.size());
Assert.assertEquals("[CCTV Store]", l.get(3).supplier.get("supplier_2").toString());
List<String> supplierOne = l.get(3).supplier.get("supplier_1");
assertEquals("Mobile Store", supplierOne.get(0));
assertEquals("iPod Store", supplierOne.get(1));
List<String> supplierTwo = l.get(3).supplier.get("supplier_2");
assertEquals("CCTV Store", supplierTwo.get(0));
} }
public void testToAndFromSolrDocument() public void testToAndFromSolrDocument() {
{
Item item = new Item(); Item item = new Item();
item.id = "one"; item.id = "one";
item.inStock = false; item.inStock = false;
item.categories = new String[] { "aaa", "bbb", "ccc" }; item.categories = new String[] {"aaa", "bbb", "ccc"};
item.features = Arrays.asList( item.categories ); item.features = Arrays.asList(item.categories);
List<String> supA = Arrays.asList( new String[] { "supA1", "supA2", "supA3" } ); List<String> supA = Arrays.asList("supA1", "supA2", "supA3");
List<String> supB = Arrays.asList( new String[] { "supB1", "supB2", "supB3"}); List<String> supB = Arrays.asList("supB1", "supB2", "supB3");
item.supplier = new HashMap<String, List<String>>(); item.supplier = new HashMap<String, List<String>>();
item.supplier.put("supplier_supA", supA); item.supplier.put("supplier_supA", supA);
item.supplier.put("supplier_supB", supB); item.supplier.put("supplier_supB", supB);
@ -112,49 +120,48 @@ public class TestDocumentObjectBinder extends LuceneTestCase
item.supplier_simple.put("sup_simple_supB", "supB_val"); item.supplier_simple.put("sup_simple_supB", "supB_val");
DocumentObjectBinder binder = new DocumentObjectBinder(); DocumentObjectBinder binder = new DocumentObjectBinder();
SolrInputDocument doc = binder.toSolrInputDocument( item ); SolrInputDocument doc = binder.toSolrInputDocument(item);
SolrDocumentList docs = new SolrDocumentList(); SolrDocumentList docs = new SolrDocumentList();
docs.add( ClientUtils.toSolrDocument(doc) ); docs.add(ClientUtils.toSolrDocument(doc));
Item out = binder.getBeans( Item.class, docs ).get( 0 ); Item out = binder.getBeans(Item.class, docs).get(0);
Item singleOut = binder.getBean(Item.class, ClientUtils.toSolrDocument(doc)); Item singleOut = binder.getBean(Item.class, ClientUtils.toSolrDocument(doc));
// make sure it came out the same // make sure it came out the same
Assert.assertEquals( item.id, out.id ); assertEquals(item.id, out.id);
Assert.assertEquals( item.inStock, out.inStock ); assertEquals(item.inStock, out.inStock);
Assert.assertEquals( item.categories.length, out.categories.length ); assertEquals(item.categories.length, out.categories.length);
Assert.assertEquals( item.features, out.features ); assertEquals(item.features, out.features);
Assert.assertEquals( supA,out.supplier.get("supplier_supA")); assertEquals(supA, out.supplier.get("supplier_supA"));
Assert.assertEquals( supB, out.supplier.get("supplier_supB")); assertEquals(supB, out.supplier.get("supplier_supB"));
Assert.assertEquals( item.supplier_simple.get("sup_simple_supB"), out.supplier_simple.get("sup_simple_supB")); assertEquals(item.supplier_simple.get("sup_simple_supB"), out.supplier_simple.get("sup_simple_supB"));
Assert.assertEquals( item.id, singleOut.id ); assertEquals(item.id, singleOut.id);
Assert.assertEquals( item.inStock, singleOut.inStock ); assertEquals(item.inStock, singleOut.inStock);
Assert.assertEquals( item.categories.length, singleOut.categories.length ); assertEquals(item.categories.length, singleOut.categories.length);
Assert.assertEquals( item.features, singleOut.features ); assertEquals(item.features, singleOut.features);
Assert.assertEquals( supA, singleOut.supplier.get("supplier_supA")); assertEquals(supA, singleOut.supplier.get("supplier_supA"));
Assert.assertEquals( supB, singleOut.supplier.get("supplier_supB")); assertEquals(supB, singleOut.supplier.get("supplier_supB"));
Assert.assertEquals( item.supplier_simple.get("sup_simple_supB"), out.supplier_simple.get("sup_simple_supB")); assertEquals(item.supplier_simple.get("sup_simple_supB"), out.supplier_simple.get("sup_simple_supB"));
// put back "out" as Bean, to see if both ways work as you would expect // put back "out" as Bean, to see if both ways work as you would expect
// but the Field that "allSuppliers" need to be cleared, as it is just for // but the Field that "allSuppliers" need to be cleared, as it is just for
// retrieving data, not to post data // retrieving data, not to post data
out.allSuppliers = null; out.allSuppliers = null;
SolrInputDocument doc1 = binder.toSolrInputDocument( out ); SolrInputDocument doc1 = binder.toSolrInputDocument(out);
SolrDocumentList docs1 = new SolrDocumentList(); SolrDocumentList docs1 = new SolrDocumentList();
docs1.add( ClientUtils.toSolrDocument(doc1) ); docs1.add(ClientUtils.toSolrDocument(doc1));
Item out1 = binder.getBeans( Item.class, docs1 ).get( 0 ); Item out1 = binder.getBeans(Item.class, docs1).get(0);
Assert.assertEquals( item.id, out1.id ); assertEquals(item.id, out1.id);
Assert.assertEquals( item.inStock, out1.inStock ); assertEquals(item.inStock, out1.inStock);
Assert.assertEquals( item.categories.length, out1.categories.length ); assertEquals(item.categories.length, out1.categories.length);
Assert.assertEquals( item.features, out1.features ); assertEquals(item.features, out1.features);
Assert.assertEquals( item.supplier_simple.get("sup_simple_supB"), out1.supplier_simple.get("sup_simple_supB")); assertEquals(item.supplier_simple.get("sup_simple_supB"), out1.supplier_simple.get("sup_simple_supB"));
Assert.assertEquals( supA,out1.supplier.get("supplier_supA"));
Assert.assertEquals( supB, out1.supplier.get("supplier_supB"));
assertEquals(supA, out1.supplier.get("supplier_supA"));
assertEquals(supB, out1.supplier.get("supplier_supB"));
} }
public static class Item { public static class Item {
@ -173,7 +180,7 @@ public class TestDocumentObjectBinder extends LuceneTestCase
@Field("highway_mileage") @Field("highway_mileage")
int mwyMileage; int mwyMileage;
boolean inStock = false; boolean inStock;
@Field("supplier_*") @Field("supplier_*")
Map<String, List<String>> supplier; Map<String, List<String>> supplier;
@ -184,11 +191,11 @@ public class TestDocumentObjectBinder extends LuceneTestCase
private String[] allSuppliers; private String[] allSuppliers;
@Field("supplier_*") @Field("supplier_*")
public void setAllSuppliers(String[] allSuppliers){ public void setAllSuppliers(String[] allSuppliers) {
this.allSuppliers = allSuppliers; this.allSuppliers = allSuppliers;
} }
public String[] getAllSuppliers(){ public String[] getAllSuppliers() {
return this.allSuppliers; return this.allSuppliers;
} }
@ -198,8 +205,7 @@ public class TestDocumentObjectBinder extends LuceneTestCase
} }
// required if you want to fill SolrDocuments with the same annotaion... // required if you want to fill SolrDocuments with the same annotaion...
public boolean isInStock() public boolean isInStock() {
{
return inStock; return inStock;
} }
} }