Enhance the partial read support so that we can use the full property names in the object tree

git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1384975 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
rfeng 2012-09-14 23:26:38 +00:00
parent 2b5427b858
commit e8455342e0
3 changed files with 114 additions and 32 deletions

View file

@ -49,6 +49,10 @@ import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.WILDCARD})
public class DataBindingJAXRSWriter<T> extends DataBindingJAXRSProvider implements MessageBodyWriter<T> {
public static final String FIELDS = "fields";
public static final String EXCLUDED_FIELDS = "excludedFields";
public static final String INCLUDED_FIELDS = "includedFields";
public DataBindingJAXRSWriter(ExtensionPointRegistry registry) {
super(registry);
}
@ -99,15 +103,28 @@ public class DataBindingJAXRSWriter<T> extends DataBindingJAXRSProvider implemen
HTTPContext context = ThreadHTTPContext.getHTTPContext();
if (context != null) {
metadata = new HashMap<String, Object>();
String included = context.getHttpRequest().getParameter("includedFields");
String excluded = context.getHttpRequest().getParameter("excludedFields");
String included = context.getHttpRequest().getParameter(INCLUDED_FIELDS);
String excluded = context.getHttpRequest().getParameter(EXCLUDED_FIELDS);
Set<String> includedFields = tokenize(included);
if (includedFields != null) {
metadata.put("includedFields", includedFields);
metadata.put(INCLUDED_FIELDS, includedFields);
}
Set<String> excludedFields = tokenize(excluded);
if (excludedFields != null) {
metadata.put("excludedFields", excludedFields);
metadata.put(EXCLUDED_FIELDS, excludedFields);
}
// The syntax is fields=f1,f2,-f3
String fields = (String)context.getHttpRequest().getParameter(FIELDS);
if (fields != null) {
Set<String> fieldSet = tokenize(fields);
for (String f : fieldSet) {
if (f.startsWith("-")) {
excludedFields.add(f.substring(1));
} else {
includedFields.add(f);
}
}
}
}

View file

@ -25,7 +25,9 @@ import java.io.OutputStream;
import java.io.Reader;
import java.io.StringWriter;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@ -62,10 +64,17 @@ import org.json.JSONObject;
import com.fasterxml.jackson.module.jsonorg.JsonOrgModule;
/**
*
* Helper class for Jackson
*/
public class JacksonHelper {
public static final String TUSCANY_FILTER = "tuscanyFilter";
public static final String EXCLUDED_FIELDS = "excludedFields";
public static final String INCLUDED_FIELDS = "includedFields";
private final static SimpleBeanPropertyFilter DEFAULT_FILTER = SimpleBeanPropertyFilter.serializeAllExcept();
/**
* The default instance of Jackson ObjectMapper
*/
public final static ObjectMapper MAPPER = createMapper();
private final static JsonFactory FACTORY = new MappingJsonFactory(createMapper());
@ -123,7 +132,7 @@ public class JacksonHelper {
@Override
public Object findFilterId(AnnotatedClass annotatedClass) {
Object filterId = super.findFilterId(annotatedClass);
return filterId == null ? "tuscanyFilter" : filterId;
return filterId == null ? TUSCANY_FILTER : filterId;
}
};
@ -136,7 +145,7 @@ public class JacksonHelper {
.withSerializationInclusion(JsonSerialize.Inclusion.NON_NULL)
.withDateFormat(StdDateFormat.getBlueprintISO8601Format()));
mapper.setFilters(new SimpleFilterProvider().addFilter("tuscanyFilter", DEFAULT_FILTER));
mapper.setFilters(new SimpleFilterProvider().addFilter(TUSCANY_FILTER, DEFAULT_FILTER));
return mapper;
}
@ -253,21 +262,22 @@ public class JacksonHelper {
public static FilterProvider configureFilterProvider(TransformationContext context) {
SimpleBeanPropertyFilter filter = DEFAULT_FILTER;
if (context != null) {
Set<String> included = (Set<String>)context.getMetadata().get("includedFields");
Set<String> excluded = (Set<String>)context.getMetadata().get("excludedFields");
Class<?> type = context.getSourceDataType() == null ? null : context.getSourceDataType().getPhysical();
filter = new TuscanyBeanPropertyFilter(type, included, excluded);
Set<String> included = (Set<String>)context.getMetadata().get(INCLUDED_FIELDS);
Set<String> excluded = (Set<String>)context.getMetadata().get(EXCLUDED_FIELDS);
// Class<?> type = context.getSourceDataType() == null ? null : context.getSourceDataType().getPhysical();
filter = new TuscanyBeanPropertyFilter(included, excluded);
}
FilterProvider filters = new SimpleFilterProvider().addFilter("tuscanyFilter", filter);
FilterProvider filters = new SimpleFilterProvider().addFilter(TUSCANY_FILTER, filter);
return filters;
}
private static class TuscanyBeanPropertyFilter extends SimpleBeanPropertyFilter {
private Class<?> type;
private Set<String> includedFields;
private Set<String> excludedFields;
public TuscanyBeanPropertyFilter(Class<?> type, Set<String> includedFields, Set<String> excludedFields) {
private Stack<String> path = new Stack<String>();
public TuscanyBeanPropertyFilter(Set<String> includedFields, Set<String> excludedFields) {
if (includedFields == null) {
includedFields = Collections.emptySet();
}
@ -276,7 +286,6 @@ public class JacksonHelper {
}
this.includedFields = includedFields;
this.excludedFields = excludedFields;
this.type = type;
}
@Override
@ -284,18 +293,58 @@ public class JacksonHelper {
JsonGenerator jgen,
SerializerProvider provider,
BeanPropertyWriter writer) throws Exception {
/*
// First check if the type matches and skip the filtering if the type is different
if (type != null && writer.getMember().getDeclaringClass() != type) {
writer.serializeAsField(bean, jgen, provider);
return;
path.push(writer.getName());
try {
// System.out.println(path);
if (matches(path, includedFields, true)) {
writer.serializeAsField(bean, jgen, provider);
} else if (includedFields.isEmpty() && !matches(path, excludedFields, false)) {
writer.serializeAsField(bean, jgen, provider);
}
} finally {
path.pop();
}
*/
if (includedFields.contains(writer.getName())) {
writer.serializeAsField(bean, jgen, provider);
} else if (includedFields.isEmpty() && !excludedFields.contains(writer.getName())) {
writer.serializeAsField(bean, jgen, provider);
}
/**
* Check the target string is a prefix of the source separated by .
* @param source
* @param target
* @return
*/
private boolean isPrefix(String source, String target) {
int index = source.indexOf(target);
if (index == -1) {
return false;
}
if (target.length() == source.length() || source.charAt(target.length()) == '.') {
return true;
}
return false;
}
/**
* Check if the path matches the one of the patterns
* @param path
* @param patterns
* @param included
* @return
*/
private boolean matches(Stack<String> path, Set<String> patterns, boolean included) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < path.size(); i++) {
builder.append(path.get(i));
if (i != path.size() - 1) {
builder.append(".");
}
}
String qname = builder.toString();
for (String p : patterns) {
if ((included && isPrefix(p, qname)) || ((!included) && isPrefix(qname, p))) {
return true;
}
}
return false;
}
}

View file

@ -23,13 +23,16 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import junit.framework.Assert;
import org.apache.tuscany.sca.databinding.TransformationContext;
import org.apache.tuscany.sca.databinding.impl.TransformationContextImpl;
import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
import org.json.JSONObject;
import org.junit.Test;
/**
@ -263,21 +266,34 @@ public class Object2JSONTestCase {
me.setDate(new Date());
YourBean you = new YourBean();
you.setId(123);
you.setName(null);
you.setName("You");
me.setYou(you);
Object2JSON t1 = new Object2JSON();
TransformationContext context = new TransformationContextImpl();
context.getMetadata().put("includedFields", Collections.singleton("name"));
Set<String> included = new HashSet<String>();
included.add("name");
included.add("you.name");
// included.add("you.id");
context.getMetadata().put("includedFields", included);
Object result = t1.transform(me, context);
System.out.println(result);
Assert.assertTrue(result.toString().contains("name"));
Assert.assertFalse(result.toString().contains("age"));
JSONObject json = new JSONObject(result.toString());
Assert.assertTrue(json.has("name"));
Assert.assertTrue(json.has("you"));
Assert.assertTrue(json.getJSONObject("you").has("name"));
Assert.assertFalse(json.getJSONObject("you").has("id"));
context = new TransformationContextImpl();
context.getMetadata().put("excludedFields", Collections.singleton("name"));
Set<String> excluded = new HashSet<String>();
excluded.add("you.name");
excluded.add("age");
context.getMetadata().put("excludedFields", excluded);
result = t1.transform(me, context);
System.out.println(result);
Assert.assertFalse(result.toString().contains("name"));
Assert.assertTrue(result.toString().contains("age"));
json = new JSONObject(result.toString());
Assert.assertTrue(json.has("name"));
Assert.assertTrue(json.has("you"));
Assert.assertTrue(json.getJSONObject("you").has("id"));
Assert.assertFalse(json.getJSONObject("you").has("name"));
}
@Test