From e8455342e0cb99cded73091b95ab068cfdb39576 Mon Sep 17 00:00:00 2001 From: rfeng Date: Fri, 14 Sep 2012 23:26:38 +0000 Subject: 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 --- .../rest/provider/DataBindingJAXRSWriter.java | 25 +++++- .../databinding/json/jackson/JacksonHelper.java | 91 +++++++++++++++++----- .../json/jackson/Object2JSONTestCase.java | 30 +++++-- 3 files changed, 114 insertions(+), 32 deletions(-) diff --git a/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSWriter.java b/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSWriter.java index 9f3cf7b919..4ee1ff8c92 100644 --- a/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSWriter.java +++ b/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSWriter.java @@ -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 extends DataBindingJAXRSProvider implements MessageBodyWriter { + 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 extends DataBindingJAXRSProvider implemen HTTPContext context = ThreadHTTPContext.getHTTPContext(); if (context != null) { metadata = new HashMap(); - 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 includedFields = tokenize(included); if (includedFields != null) { - metadata.put("includedFields", includedFields); + metadata.put(INCLUDED_FIELDS, includedFields); } Set 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 fieldSet = tokenize(fields); + for (String f : fieldSet) { + if (f.startsWith("-")) { + excludedFields.add(f.substring(1)); + } else { + includedFields.add(f); + } + } } } diff --git a/sca-java-2.x/trunk/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/jackson/JacksonHelper.java b/sca-java-2.x/trunk/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/jackson/JacksonHelper.java index 5d9a4c8e7d..9430a326b2 100644 --- a/sca-java-2.x/trunk/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/jackson/JacksonHelper.java +++ b/sca-java-2.x/trunk/modules/databinding-json/src/main/java/org/apache/tuscany/sca/databinding/json/jackson/JacksonHelper.java @@ -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 included = (Set)context.getMetadata().get("includedFields"); - Set excluded = (Set)context.getMetadata().get("excludedFields"); - Class type = context.getSourceDataType() == null ? null : context.getSourceDataType().getPhysical(); - filter = new TuscanyBeanPropertyFilter(type, included, excluded); + Set included = (Set)context.getMetadata().get(INCLUDED_FIELDS); + Set excluded = (Set)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 includedFields; private Set excludedFields; - public TuscanyBeanPropertyFilter(Class type, Set includedFields, Set excludedFields) { + private Stack path = new Stack(); + + public TuscanyBeanPropertyFilter(Set includedFields, Set 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 path, Set 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; } } diff --git a/sca-java-2.x/trunk/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/jackson/Object2JSONTestCase.java b/sca-java-2.x/trunk/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/jackson/Object2JSONTestCase.java index 6e1312d40a..745937b87e 100644 --- a/sca-java-2.x/trunk/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/jackson/Object2JSONTestCase.java +++ b/sca-java-2.x/trunk/modules/databinding-json/src/test/java/org/apache/tuscany/sca/databinding/json/jackson/Object2JSONTestCase.java @@ -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 included = new HashSet(); + 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 excluded = new HashSet(); + 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 -- cgit v1.2.3