You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2016/08/27 15:38:25 UTC
[6/8] incubator-juneau git commit: Tweak new name 'Transform' into
'BeanFilter' and 'PojoSwap'
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
index 68c9341..a22242b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
@@ -56,7 +56,7 @@ public final class MsgPackParser extends InputStreamParser {
BeanContext bc = session.getBeanContext();
if (nt == null)
nt = (ClassMeta<T>)object();
- PojoTransform<T,Object> transform = (PojoTransform<T,Object>)nt.getPojoTransform();
+ PojoSwap<T,Object> transform = (PojoSwap<T,Object>)nt.getPojoSwap();
ClassMeta<?> ft = nt.getTransformedClassMeta();
session.setCurrentClass(ft);
@@ -182,7 +182,7 @@ public final class MsgPackParser extends InputStreamParser {
}
if (transform != null && o != null)
- o = transform.normalize(o, nt);
+ o = transform.unswap(o, nt);
if (outer != null)
setParent(nt, o, outer);
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
index cd734b8..8795869 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
@@ -78,9 +78,9 @@ public class MsgPackSerializer extends OutputStreamSerializer {
addClassAttr = (session.isAddClassAttrs() && ! eType.equals(aType));
// Transform if necessary
- PojoTransform transform = aType.getPojoTransform(); // The transform
+ PojoSwap transform = aType.getPojoSwap(); // The transform
if (transform != null) {
- o = transform.transform(o);
+ o = transform.swap(o);
// If the transform's getTransformedClass() method returns Object, we need to figure out
// the actual type now.
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/package.html b/juneau-core/src/main/java/org/apache/juneau/package.html
index 8b3d585..ca30bd5 100644
--- a/juneau-core/src/main/java/org/apache/juneau/package.html
+++ b/juneau-core/src/main/java/org/apache/juneau/package.html
@@ -157,10 +157,10 @@
BeanContext beanContext = BeanContext.<jsf>DEFAULT</jsf>;
<jc>// Create a context from scratch with your own settings.</jc>
- beanContext = <jk>new</jk> BeanContext().addTransforms(DateTransform.ISO8601DT.<jk>class</jk>);
+ beanContext = <jk>new</jk> BeanContext().addTransforms(DateSwap.ISO8601DT.<jk>class</jk>);
<jc>// Clone and modify an existing context.</jc>
- beanContext = BeanContext.<jsf>DEFAULT</jsf>.clone().addTransforms(DateTransform.ISO8601DT.<jk>class</jk>);
+ beanContext = BeanContext.<jsf>DEFAULT</jsf>.clone().addTransforms(DateSwap.ISO8601DT.<jk>class</jk>);
</p>
<p>
The {@link org.apache.juneau.BeanContext} class is a highly-customizable class.
@@ -204,7 +204,7 @@
Using the <ja>@Bean</ja> and <ja>@BeanProperty</ja> annotations, it's also possible to include non-standard properties (for example, getters or setters with non-standard names), or override the names of properties (for example, {@code "Name"} or {@code "fullName"} instead of {@code "name"}).
</p>
<p>
- It should be noted that the {@link org.apache.juneau.transform.BeanTransform} class can also be used to exclude properties from beans.
+ It should be noted that the {@link org.apache.juneau.transform.BeanFilter} class can also be used to exclude properties from beans.
However, only the annotations can be used to include non-standard properties or override property names.
</p>
<p>
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java b/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
index 1a1bd79..9a858b1 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
@@ -94,10 +94,10 @@ import org.apache.juneau.utils.*;
* </tr>
* </table>
* <p>
- * In addition, any class types with {@link PojoTransform PojoTransforms} associated with them on the registered
+ * In addition, any class types with {@link PojoSwap PojoSwaps} associated with them on the registered
* {@link #getBeanContext() beanContext} can also be passed in.
* <p>
- * For example, if the {@link CalendarTransform} transform is used to generalize {@code Calendar} objects to {@code String} objects. When registered
+ * For example, if the {@link CalendarSwap} transform is used to generalize {@code Calendar} objects to {@code String} objects. When registered
* with this parser, you can construct {@code Calendar} objects from {@code Strings} using the following syntax...
* <p class='bcode'>
* Calendar c = parser.parse(<js>"'Sun Mar 03 04:05:06 EST 2001'"</js>, GregorianCalendar.<jk>class</jk>);
@@ -579,7 +579,7 @@ public abstract class Parser extends CoreApi {
if (type == null)
type = (ClassMeta<T>)object();
- PojoTransform transform = type.getPojoTransform();
+ PojoSwap transform = type.getPojoSwap();
ClassMeta<?> gType = type.getTransformedClassMeta();
Object o = s;
@@ -600,7 +600,7 @@ public abstract class Parser extends CoreApi {
}
if (transform != null)
- o = transform.normalize(o, type);
+ o = transform.unswap(o, type);
return (T)o;
}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
index 0e810b8..4b86852 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
@@ -56,7 +56,7 @@ import org.apache.juneau.*;
*
* <jc>// Change settings on parsers simultaneously</jc>
* g.setProperty(BeanContext.<jsf>BEAN_beansRequireSerializable</jsf>, <jk>true</jk>)
- * .addTransforms(CalendarTransform.ISO8601DT.<jk>class</jk>)
+ * .addTransforms(CalendarSwap.ISO8601DT.<jk>class</jk>)
* .lock();
*
* <jc>// Find the appropriate parser by Content-Type</jc>
@@ -254,7 +254,7 @@ public final class ParserGroup extends Lockable {
/**
* Shortcut for calling {@link Parser#addTransforms(Class[])} on all parsers in this group.
*
- * @param classes The classes to add bean transforms for to the underlying bean context of all parsers in this group.
+ * @param classes The classes to add bean filters for to the underlying bean context of all parsers in this group.
* @throws LockedException If {@link #lock()} was called on this object.
* @return This object (for method chaining).
*/
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
index 36ab2b8..e3aeda1 100644
--- a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
@@ -34,7 +34,7 @@ import org.apache.juneau.transform.*;
* Essentially just converts plain text to POJOs via static <code>fromString()</code> or <code>valueOf()</code>, or
* through constructors that take a single string argument.
* <p>
- * Also parses objects using a transform if the object class has an {@link PojoTransform PojoTransform<?,String>} transform defined on it.
+ * Also parses objects using a transform if the object class has an {@link PojoSwap PojoSwap<?,String>} transform defined on it.
*
*
* <h6 class='topic'>Configurable properties</h6>
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
index fd916f3..6be54ea 100644
--- a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
@@ -32,7 +32,7 @@ import org.apache.juneau.transform.*;
* <p>
* Essentially converts POJOs to plain text using the <code>toString()</code> method.
* <p>
- * Also serializes objects using a transform if the object class has an {@link PojoTransform PojoTransform<?,String>} transform defined on it.
+ * Also serializes objects using a transform if the object class has an {@link PojoSwap PojoSwap<?,String>} transform defined on it.
*
*
* <h6 class='topic'>Configurable properties</h6>
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
index 926075e..ef35199 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
@@ -56,7 +56,7 @@ import org.apache.juneau.*;
*
* <jc>// Change settings for all serializers in the group and lock it.</jc>
* g.setProperty(SerializerContext.<jsf>SERIALIZER_useIndentation</jsf>, <jk>true</jk>)
- * .addTransforms(CalendarTransform.ISO8601DT.<jk>class</jk>)
+ * .addTransforms(CalendarSwap.ISO8601DT.<jk>class</jk>)
* .lock();
*
* <jc>// Find the appropriate serializer by Accept type</jc>
@@ -277,7 +277,7 @@ public final class SerializerGroup extends Lockable {
/**
* Shortcut for calling {@link Serializer#addTransforms(Class[])} on all serializers in this group.
*
- * @param classes The classes to add bean transforms for to the underlying bean context of all serializers in this group.
+ * @param classes The classes to add bean filters for to the underlying bean context of all serializers in this group.
* @throws LockedException If {@link #lock()} was called on this object.
* @return This object (for method chaining).
*/
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
index 0749066..f7d070a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
@@ -537,10 +537,10 @@ public class SerializerSession extends Session {
public final Object generalize(Object o, ClassMeta<?> type) throws SerializeException {
if (o == null)
return null;
- PojoTransform f = (type == null || type.isObject() ? getBeanContext().getClassMeta(o.getClass()).getPojoTransform() : type.getPojoTransform());
+ PojoSwap f = (type == null || type.isObject() ? getBeanContext().getClassMeta(o.getClass()).getPojoSwap() : type.getPojoSwap());
if (f == null)
return o;
- return f.transform(o);
+ return f.swap(o);
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilter.java b/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilter.java
new file mode 100644
index 0000000..bf502b7
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilter.java
@@ -0,0 +1,70 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.juneau.transform;
+
+import java.util.*;
+
+import org.apache.juneau.annotation.*;
+
+/**
+ * Bean filter constructed from a {@link Bean @Bean} annotation found on a class.
+ * <p>
+ * <b>*** Internal class - Not intended for external use ***</b>
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ * @param <T> The class type that this transform applies to.
+ */
+public final class AnnotationBeanFilter<T> extends BeanFilter<T> {
+
+ /**
+ * Constructor.
+ *
+ * @param annotatedClass The class found to have a {@link Bean @Bean} annotation.
+ * @param annotations The {@link Bean @Bean} annotations found on the class and all parent classes in child-to-parent order.
+ */
+ public AnnotationBeanFilter(Class<T> annotatedClass, List<Bean> annotations) {
+ super(annotatedClass);
+
+ ListIterator<Bean> li = annotations.listIterator(annotations.size());
+ while (li.hasPrevious()) {
+ Bean b = li.previous();
+
+ if (b.properties().length > 0 && getProperties() == null)
+ setProperties(b.properties());
+
+ if (b.sort())
+ setSortProperties(true);
+
+ if (b.excludeProperties().length > 0)
+ setExcludeProperties(b.excludeProperties());
+
+ setPropertyNamer(b.propertyNamer());
+
+ if (b.interfaceClass() != Object.class)
+ setInterfaceClass(b.interfaceClass());
+
+ if (b.stopClass() != Object.class)
+ setStopClass(b.stopClass());
+
+ if (! b.subTypeProperty().isEmpty()) {
+ setSubTypeProperty(b.subTypeProperty());
+
+ LinkedHashMap<Class<?>,String> subTypes = new LinkedHashMap<Class<?>,String>();
+ for (BeanSubType bst : b.subTypes())
+ subTypes.put(bst.type(), bst.id());
+
+ setSubTypes(subTypes);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanTransform.java b/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanTransform.java
deleted file mode 100644
index a6bc86f..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanTransform.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/***************************************************************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
- * to you 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.apache.juneau.transform;
-
-import java.util.*;
-
-import org.apache.juneau.annotation.*;
-
-/**
- * Bean transform constructed from a {@link Bean @Bean} annotation found on a class.
- * <p>
- * <b>*** Internal class - Not intended for external use ***</b>
- *
- * @author James Bognar (james.bognar@salesforce.com)
- * @param <T> The class type that this transform applies to.
- */
-public final class AnnotationBeanTransform<T> extends BeanTransform<T> {
-
- /**
- * Constructor.
- *
- * @param annotatedClass The class found to have a {@link Bean @Bean} annotation.
- * @param annotations The {@link Bean @Bean} annotations found on the class and all parent classes in child-to-parent order.
- */
- public AnnotationBeanTransform(Class<T> annotatedClass, List<Bean> annotations) {
- super(annotatedClass);
-
- ListIterator<Bean> li = annotations.listIterator(annotations.size());
- while (li.hasPrevious()) {
- Bean b = li.previous();
-
- if (b.properties().length > 0 && getProperties() == null)
- setProperties(b.properties());
-
- if (b.sort())
- setSortProperties(true);
-
- if (b.excludeProperties().length > 0)
- setExcludeProperties(b.excludeProperties());
-
- setPropertyNamer(b.propertyNamer());
-
- if (b.interfaceClass() != Object.class)
- setInterfaceClass(b.interfaceClass());
-
- if (b.stopClass() != Object.class)
- setStopClass(b.stopClass());
-
- if (! b.subTypeProperty().isEmpty()) {
- setSubTypeProperty(b.subTypeProperty());
-
- LinkedHashMap<Class<?>,String> subTypes = new LinkedHashMap<Class<?>,String>();
- for (BeanSubType bst : b.subTypes())
- subTypes.put(bst.type(), bst.id());
-
- setSubTypes(subTypes);
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilter.java b/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilter.java
new file mode 100644
index 0000000..1538d0a
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilter.java
@@ -0,0 +1,526 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.juneau.transform;
+
+import java.beans.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+
+/**
+ * Parent class for all bean filters.
+ * <p>
+ * Bean filters are used to control aspects of how beans are handled during serialization and parsing.
+ * <p>
+ * This class can be considered a programmatic equivalent to using the {@link Bean @Bean} annotation on bean classes.
+ * Thus, it can be used to perform the same function as the <code>@Bean</code> annotation when you don't have
+ * the ability to annotate those classes (e.g. you don't have access to the source code).
+ * <p>
+ * Note that value returned by the {@link Transform#forClass()} method is automatically determined through reflection
+ * when the no-arg constructor is used.
+ *
+ * <p>
+ * When defining bean filters, you can either call the setters in the contructor, or override getters.
+ *
+ * <h6 class='topic'>Example</h6>
+ * <p class='bcode'>
+ * <jc>// Create our serializer with a filter.</jc>
+ * WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(AddressFilter.<jk>class</jk>);
+ *
+ * Address a = <jk>new</jk> Address();
+ * String json = s.serialize(a); <jc>// Serializes only street, city, state.</jc>
+ *
+ * <jc>// Filter class defined via setters</jc>
+ * <jk>public class</jk> AddressFilter <jk>extends</jk> BeanFilter<Address> {
+ * <jk>public</jk> AddressFilter() {
+ * setProperties(<js>"street"</js>,<js>"city"</js>,<js>"state"</js>);
+ * }
+ * }
+ *
+ * <jc>// Filter class defined by overriding getters</jc>
+ * <jk>public class</jk> AddressFilter <jk>extends</jk> BeanFilter<Address> {
+ * <jk>public</jk> String[] getProperties() {
+ * <jk>return new</jk> String[]{<js>"street"</js>,<js>"city"</js>,<js>"state"</js>};
+ * }
+ * }
+ * </p>
+ * <p>
+ * The examples in this class use the setters approach.
+ *
+ * <h6 class='topic'>Additional information</h6>
+ * See {@link org.apache.juneau.transform} for more information.
+ *
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ * @param <T> The class type that this filter applies to.
+ */
+public abstract class BeanFilter<T> extends Transform {
+
+ private String[] properties, excludeProperties;
+ private LinkedHashMap<Class<?>, String> subTypes;
+ private String subTypeAttr;
+ private Class<? extends PropertyNamer> propertyNamer;
+ private Class<?> interfaceClass, stopClass;
+ private boolean sortProperties;
+
+ /**
+ * Constructor that determines the for-class value using reflection.
+ */
+ @SuppressWarnings("unchecked")
+ public BeanFilter() {
+ super();
+ this.type = TransformType.BEAN;
+
+ Class<?> c = this.getClass().getSuperclass();
+ Type t = this.getClass().getGenericSuperclass();
+ while (c != BeanFilter.class) {
+ t = c.getGenericSuperclass();
+ c = c.getSuperclass();
+ }
+
+ // Attempt to determine the T and G classes using reflection.
+ if (t instanceof ParameterizedType) {
+ ParameterizedType pt = (ParameterizedType)t;
+ Type[] pta = pt.getActualTypeArguments();
+ if (pta.length > 0) {
+ Type nType = pta[0];
+ if (nType instanceof Class)
+ this.forClass = (Class<T>)nType;
+
+ else
+ throw new RuntimeException("Unsupported parameter type: " + nType);
+ }
+ }
+ }
+
+ /**
+ * Constructor that specifies the for-class explicitly.
+ * <p>
+ * This constructor only needs to be called when the class type cannot be inferred through reflection.
+ *
+ * <dl>
+ * <dt>Example:</dt>
+ * <dd>
+ * <p class='bcode'>
+ * <jk>public class</jk> SomeArbitraryFilter <jk>extends</jk> BeanFilter<?> {
+ * <jk>public</jk> SomeArbitraryFiter(Class<?> forClass) {
+ * <jk>super</jk>(forClass);
+ * ...
+ * }
+ * }
+ * </p>
+ * </dd>
+ * </dl>
+ *
+ * @param forClass The class that this bean filter applies to.
+ */
+ public BeanFilter(Class<T> forClass) {
+ super(forClass);
+ this.type = TransformType.BEAN;
+ }
+
+ /**
+ * Returns the set and order of names of properties associated with a bean class.
+ *
+ * @see #setProperties(String...)
+ * @return The name of the properties associated with a bean class, or <jk>null</jk> if all bean properties should be used.
+ */
+ public String[] getProperties() {
+ return properties;
+ }
+
+ /**
+ * Specifies the set and order of names of properties associated with a bean class.
+ * <p>
+ * The order specified is the same order that the entries will be returned by the {@link BeanMap#entrySet()} and related methods.
+ * <p>
+ * This method is an alternative to using the {@link Bean#properties()} annotation on a class.
+ *
+ * <dl>
+ * <dt>Example:</dt>
+ * <dd>
+ * <p class='bcode'>
+ * <jc>// Create our serializer with a filter.</jc>
+ * WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(AddressFilter.<jk>class</jk>);
+ *
+ * Address a = <jk>new</jk> Address();
+ * String json = s.serialize(a); <jc>// Serializes only street, city, state.</jc>
+ *
+ * <jc>// Transform class</jc>
+ * <jk>public class</jk> AddressFilter <jk>extends</jk> BeanFilter<Address> {
+ * <jk>public</jk> AddressFilter() {
+ * setProperties(<js>"street"</js>,<js>"city"</js>,<js>"state"</js>);
+ * }
+ * }
+ * </p>
+ * </dd>
+ * </dl>
+ *
+ * @param properties The name of the properties associated with a bean class.
+ * @return This object (for method chaining).
+ */
+ public BeanFilter<T> setProperties(String...properties) {
+ this.properties = properties;
+ return this;
+ }
+
+ /**
+ * Same as {@link #setProperties(String[])} but pass in a comma-delimited list of values.
+ *
+ * @param properties A comma-delimited list of properties.
+ * @return This object (for method chaining).
+ */
+ public BeanFilter<T> setProperties(String properties) {
+ return setProperties(StringUtils.split(properties, ','));
+ }
+
+ /**
+ * Returns <jk>true</jk> if the properties defined on this bean class should be ordered alphabetically.
+ * <p>
+ * This method is only used when the {@link #getProperties()} method returns <jk>null</jk>.
+ * Otherwise, the ordering of the properties in the returned value is used.
+ *
+ * @see #setSortProperties(boolean)
+ * @return <jk>true</jk> if bean properties should be sorted.
+ */
+ public boolean isSortProperties() {
+ return sortProperties;
+ }
+
+ /**
+ * Specifies whether the properties on this bean should be ordered alphabetically.
+ * <p>
+ * This method is ignored if the {@link #getProperties()} method does not return <jk>null</jk>.
+ * <p>
+ * This method is an alternative to using the {@link Bean#sort()} annotation on a class.
+ *
+ * @param sortProperties The new value for the sort properties property.
+ * @return This object (for method chaining).
+ */
+ public BeanFilter<T> setSortProperties(boolean sortProperties) {
+ this.sortProperties = sortProperties;
+ return this;
+ }
+
+ /**
+ * Returns the list of properties to ignore on a bean.
+ *
+ * @see #setExcludeProperties(String...)
+ * @return The name of the properties to ignore on a bean, or <jk>null</jk> to not ignore any properties.
+ */
+ public String[] getExcludeProperties() {
+ return excludeProperties;
+ }
+
+ /**
+ * Specifies a list of properties to ignore on a bean.
+ * <p>
+ * This method is an alternative to using the {@link Bean#excludeProperties()} annotation on a class.
+ *
+ * <dl>
+ * <dt>Example:</dt>
+ * <dd>
+ * <p class='bcode'>
+ * <jc>// Create our serializer with a filter.</jc>
+ * WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(NoCityOrStateFilter.<jk>class</jk>);
+ *
+ * Address a = <jk>new</jk> Address();
+ * String json = s.serialize(a); <jc>// Excludes city and state.</jc>
+ *
+ * <jc>// Transform class</jc>
+ * <jk>public class</jk> NoCityOrStateFilter <jk>extends</jk> BeanFilter<Address> {
+ * <jk>public</jk> AddressFilter() {
+ * setExcludeProperties(<js>"city"</js>,<js>"state"</js>);
+ * }
+ * }
+ * </p>
+ * </dd>
+ * </dl>
+ *
+ * @param excludeProperties The name of the properties to ignore on a bean class.
+ * @return This object (for method chaining).
+ */
+ public BeanFilter<T> setExcludeProperties(String...excludeProperties) {
+ this.excludeProperties = excludeProperties;
+ return this;
+ }
+
+ /**
+ * Same as {@link #setExcludeProperties(String[])} but pass in a comma-delimited list of values.
+ *
+ * @param excludeProperties A comma-delimited list of properties to eclipse.
+ * @return This object (for method chaining).
+ */
+ public BeanFilter<T> setExcludeProperties(String excludeProperties) {
+ return setExcludeProperties(StringUtils.split(excludeProperties, ','));
+ }
+
+ /**
+ * Returns the {@link PropertyNamer} associated with the bean to tailor the names of bean properties.
+ *
+ * @see #setPropertyNamer(Class)
+ * @return The property namer class, or <jk>null</jk> if no property namer is associated with this bean property.
+ */
+ public Class<? extends PropertyNamer> getPropertyNamer() {
+ return propertyNamer;
+ }
+
+ /**
+ * Associates a {@link PropertyNamer} with this bean to tailor the names of the bean properties.
+ * <p>
+ * Property namers are used to transform bean property names from standard form to some other form.
+ * For example, the {@link PropertyNamerDashedLC} will convert property names to dashed-lowercase, and
+ * these will be used as attribute names in JSON, and element names in XML.
+ * <p>
+ * This method is an alternative to using the {@link Bean#propertyNamer()} annotation on a class.
+ *
+ * @param propertyNamer The property namer class.
+ * @return This object (for method chaining).
+ */
+ public BeanFilter<T> setPropertyNamer(Class<? extends PropertyNamer> propertyNamer) {
+ this.propertyNamer = propertyNamer;
+ return this;
+ }
+
+ /**
+ * Returns the name of the sub type property associated with the bean class.
+ *
+ * @see #setSubTypeProperty(String)
+ * @return The sub type property name, or <jk>null</jk> if bean has no subtypes defined.
+ */
+ public String getSubTypeProperty() {
+ return subTypeAttr;
+ }
+
+ /**
+ * Defines a virtual property on a superclass that identifies bean subtype classes.
+ * <p>
+ * In the following example, the abstract class has two subclasses that are differentiated
+ * by a property called <code>subType</code>
+ *
+ * <p class='bcode'>
+ * <jc>// Abstract superclass</jc>
+ * <jk>public abstract class</jk> A {
+ * <jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>;
+ * }
+ *
+ * <jc>// Subclass 1</jc>
+ * <jk>public class</jk> A1 <jk>extends</jk> A {
+ * <jk>public</jk> String <jf>f1</jf>;
+ * }
+ *
+ * <jc>// Subclass 2</jc>
+ * <jk>public class</jk> A2 <jk>extends</jk> A {
+ * <jk>public</jk> String <jf>f2</jf>;
+ * }
+ *
+ * <jc>// Transform for defining subtypes</jc>
+ * <jk>public class</jk> ATransform <jk>extends</jk> BeanFilter<A> {
+ * <jk>public</jk> ATransform() {
+ * setSubTypeProperty(<js>"subType"</js>);
+ * addSubType(Al.<jk>class</jk>, <js>"A1"</js>);
+ * addSubType(A2.<jk>class</jk>, <js>"A2"</js>);
+ * }
+ * }
+ * </p>
+ * <p>
+ * The following shows what happens when serializing a subclassed object to JSON:
+ * <p class='bcode'>
+ * JsonSerializer s = <jk>new</jk> JsonSerializer().addTransforms(ATransform.<jk>class</jk>);
+ * A1 a1 = <jk>new</jk> A1();
+ * a1.<jf>f1</jf> = <js>"f1"</js>;
+ * String r = s.serialize(a1);
+ * <jsm>assertEquals</jsm>(<js>"{subType:'A1',f1:'f1',f0:'f0'}"</js>, r);
+ * </p>
+ * <p>
+ * The following shows what happens when parsing back into the original object.
+ * <p class='bcode'>
+ * JsonParser p = <jk>new</jk> JsonParser().addTransforms(ATransform.<jk>class</jk>);
+ * A a = p.parse(r, A.<jk>class</jk>);
+ * <jsm>assertTrue</jsm>(a <jk>instanceof</jk> A1);
+ * </p>
+ * <p>
+ * This method is an alternative to using the {@link Bean#subTypeProperty()} annotation on a class.
+ *
+ * @param subTypeAttr The name of the attribute representing the subtype.
+ * @return This object (for method chaining).
+ */
+ public BeanFilter<T> setSubTypeProperty(String subTypeAttr) {
+ this.subTypeAttr = subTypeAttr;
+ return this;
+ }
+
+ /**
+ * Returns the subtypes associated with the bean class.
+ *
+ * @see #setSubTypeProperty(String)
+ * @return The set of sub types associated with this bean class, or <jk>null</jk> if bean has no subtypes defined.
+ */
+ public LinkedHashMap<Class<?>, String> getSubTypes() {
+ return subTypes;
+ }
+
+ /**
+ * Specifies the set of subclasses of this bean class in addition to a string identifier for that subclass.
+ *
+ * @see #setSubTypeProperty(String)
+ * @param subTypes the map of subtype classes to subtype identifier strings.
+ * @return This object (for method chaining).
+ */
+ public BeanFilter<T> setSubTypes(LinkedHashMap<Class<?>, String> subTypes) {
+ this.subTypes = subTypes;
+ return this;
+ }
+
+ /**
+ * Convenience method for adding a single subtype in leu of using {@link #setSubTypes(LinkedHashMap)} in one call.
+ *
+ * @see #setSubTypeProperty(String)
+ * @param c The subtype class.
+ * @param id The subtype identifier string for the specified subtype class.
+ * @return This object (for method chaining).
+ */
+ public BeanFilter<T> addSubType(Class<?> c, String id) {
+ if (subTypes == null)
+ subTypes = new LinkedHashMap<Class<?>, String>();
+ subTypes.put(c, id);
+ return this;
+ }
+
+ /**
+ * Returns the interface class associated with this class.
+ *
+ * @see #setInterfaceClass(Class)
+ * @return The interface class associated with this class, or <jk>null</jk> if no interface class is associated.
+ */
+ public Class<?> getInterfaceClass() {
+ return interfaceClass;
+ }
+
+ /**
+ * Identifies a class to be used as the interface class for this and all subclasses.
+ * <p>
+ * Functionally equivalent to using the {@link Bean#interfaceClass()} annotation.
+ * <p>
+ * When specified, only the list of properties defined on the interface class will be used during serialization.
+ * Additional properties on subclasses will be ignored.
+ * <p class='bcode'>
+ * <jc>// Parent class</jc>
+ * <jk>public abstract class</jk> A {
+ * <jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>;
+ * }
+ *
+ * <jc>// Sub class</jc>
+ * <jk>public class</jk> A1 <jk>extends</jk> A {
+ * <jk>public</jk> String <jf>f1</jf> = <js>"f1"</js>;
+ * }
+ *
+ * <jc>// Transform class</jc>
+ * <jk>public class</jk> ATransform <jk>extends</jk> BeanFilter<A> {
+ * <jk>public</jk> ATransform() {
+ * setInterfaceClass(A.<jk>class</jk>);
+ * }
+ * }
+ *
+ * JsonSerializer s = new JsonSerializer().addTransforms(ATransform.<jk>class</jk>);
+ * A1 a1 = <jk>new</jk> A1();
+ * String r = s.serialize(a1);
+ * <jsm>assertEquals</jsm>(<js>"{f0:'f0'}"</js>, r); <jc>// Note f1 is not serialized</jc>
+ * </p>
+ * <p>
+ * Note that this filter can be used on the parent class so that it filters to all child classes,
+ * or can be set individually on the child classes.
+ * <p>
+ * This method is an alternative to using the {@link Bean#interfaceClass()}} annotation.
+ *
+ * @param interfaceClass The interface class.
+ * @return This object (for method chaining).
+ */
+ public BeanFilter<T> setInterfaceClass(Class<?> interfaceClass) {
+ this.interfaceClass = interfaceClass;
+ return this;
+ }
+
+ /**
+ * Returns the stop class associated with this class.
+ *
+ * @see #setStopClass(Class)
+ * @return The stop class associated with this class, or <jk>null</jk> if no stop class is associated.
+ */
+ public Class<?> getStopClass() {
+ return stopClass;
+ }
+
+ /**
+ * Identifies a stop class for this class and all subclasses.
+ * <p>
+ * Functionally equivalent to using the {@link Bean#stopClass()} annotation.
+ * <p>
+ * Identical in purpose to the stop class specified by {@link Introspector#getBeanInfo(Class, Class)}.
+ * Any properties in the stop class or in its baseclasses will be ignored during analysis.
+ * <p>
+ * For example, in the following class hierarchy, instances of <code>C3</code> will include property <code>p3</code>, but
+ * not <code>p1</code> or <code>p2</code>.
+ * <p class='bcode'>
+ * <jk>public class</jk> C1 {
+ * <jk>public int</jk> getP1();
+ * }
+ *
+ * <jk>public class</jk> C2 <jk>extends</jk> C1 {
+ * <jk>public int</jk> getP2();
+ * }
+ *
+ * <ja>@Bean</ja>(stopClass=C2.<jk>class</jk>)
+ * <jk>public class</jk> C3 <jk>extends</jk> C2 {
+ * <jk>public int</jk> getP3();
+ * }
+ * </p>
+ *
+ * @param stopClass The stop class.
+ * @return This object (for method chaining).
+ */
+ public BeanFilter<T> setStopClass(Class<?> stopClass) {
+ this.stopClass = stopClass;
+ return this;
+ }
+
+ /**
+ * Subclasses can override this property to convert property values to some other
+ * object just before serialization.
+ *
+ * @param bean The bean from which the property was read.
+ * @param name The property name.
+ * @param value The value just extracted from calling the bean getter.
+ * @return The value to serialize. Default is just to return the existing value.
+ */
+ public Object readProperty(Object bean, String name, Object value) {
+ return value;
+ }
+
+ /**
+ * Subclasses can override this property to convert property values to some other
+ * object just before calling the bean setter.
+ *
+ * @param bean The bean from which the property was read.
+ * @param name The property name.
+ * @param value The value just parsed.
+ * @return <jk>true</jk> if we set the property, <jk>false</jk> if we should allow the
+ * framework to call the setter.
+ */
+ public boolean writeProperty(Object bean, String name, Object value) {
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/BeanTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/BeanTransform.java b/juneau-core/src/main/java/org/apache/juneau/transform/BeanTransform.java
deleted file mode 100644
index f0b9f3c..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/transform/BeanTransform.java
+++ /dev/null
@@ -1,526 +0,0 @@
-/***************************************************************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
- * to you 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.apache.juneau.transform;
-
-import java.beans.*;
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.annotation.*;
-import org.apache.juneau.internal.*;
-
-/**
- * Parent class for all bean transforms.
- * <p>
- * Bean transforms are used to control aspects of how beans are handled during serialization and parsing.
- * <p>
- * This class can be considered a programmatic equivalent to using the {@link Bean @Bean} annotation on bean classes.
- * Thus, it can be used to perform the same function as the <code>@Bean</code> annotation when you don't have
- * the ability to annotate those classes (e.g. you don't have access to the source code).
- * <p>
- * Note that value returned by the {@link Transform#forClass()} method is automatically determined through reflection
- * when the no-arg constructor is used.
- *
- * <p>
- * When defining bean transforms, you can either call the setters in the contructor, or override getters.
- *
- * <h6 class='topic'>Example</h6>
- * <p class='bcode'>
- * <jc>// Create our serializer with a transform.</jc>
- * WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(AddressTransform.<jk>class</jk>);
- *
- * Address a = <jk>new</jk> Address();
- * String json = s.serialize(a); <jc>// Serializes only street, city, state.</jc>
- *
- * <jc>// Transform class defined via setters</jc>
- * <jk>public class</jk> AddressTransform <jk>extends</jk> BeanTransform<Address> {
- * <jk>public</jk> AddressTransform() {
- * setProperties(<js>"street"</js>,<js>"city"</js>,<js>"state"</js>);
- * }
- * }
- *
- * <jc>// Transform class defined by overriding getters</jc>
- * <jk>public class</jk> AddressTransform <jk>extends</jk> BeanTransform<Address> {
- * <jk>public</jk> String[] getProperties() {
- * <jk>return new</jk> String[]{<js>"street"</js>,<js>"city"</js>,<js>"state"</js>};
- * }
- * }
- * </p>
- * <p>
- * The examples in this class use the setters approach.
- *
- * <h6 class='topic'>Additional information</h6>
- * See {@link org.apache.juneau.transform} for more information.
- *
- *
- * @author James Bognar (james.bognar@salesforce.com)
- * @param <T> The class type that this transform applies to.
- */
-public abstract class BeanTransform<T> extends Transform {
-
- private String[] properties, excludeProperties;
- private LinkedHashMap<Class<?>, String> subTypes;
- private String subTypeAttr;
- private Class<? extends PropertyNamer> propertyNamer;
- private Class<?> interfaceClass, stopClass;
- private boolean sortProperties;
-
- /**
- * Constructor that determines the for-class value using reflection.
- */
- @SuppressWarnings("unchecked")
- public BeanTransform() {
- super();
- this.type = TransformType.BEAN;
-
- Class<?> c = this.getClass().getSuperclass();
- Type t = this.getClass().getGenericSuperclass();
- while (c != BeanTransform.class) {
- t = c.getGenericSuperclass();
- c = c.getSuperclass();
- }
-
- // Attempt to determine the T and G classes using reflection.
- if (t instanceof ParameterizedType) {
- ParameterizedType pt = (ParameterizedType)t;
- Type[] pta = pt.getActualTypeArguments();
- if (pta.length > 0) {
- Type nType = pta[0];
- if (nType instanceof Class)
- this.forClass = (Class<T>)nType;
-
- else
- throw new RuntimeException("Unsupported parameter type: " + nType);
- }
- }
- }
-
- /**
- * Constructor that specifies the for-class explicitly.
- * <p>
- * This constructor only needs to be called when the class type cannot be inferred through reflection.
- *
- * <dl>
- * <dt>Example:</dt>
- * <dd>
- * <p class='bcode'>
- * <jk>public class</jk> SomeArbitraryTransform <jk>extends</jk> BeanTransform<?> {
- * <jk>public</jk> SomeArbitraryTransform(Class<?> forClass) {
- * <jk>super</jk>(forClass);
- * ...
- * }
- * }
- * </p>
- * </dd>
- * </dl>
- *
- * @param forClass The class that this bean transform applies to.
- */
- public BeanTransform(Class<T> forClass) {
- super(forClass);
- this.type = TransformType.BEAN;
- }
-
- /**
- * Returns the set and order of names of properties associated with a bean class.
- *
- * @see #setProperties(String...)
- * @return The name of the properties associated with a bean class, or <jk>null</jk> if all bean properties should be used.
- */
- public String[] getProperties() {
- return properties;
- }
-
- /**
- * Specifies the set and order of names of properties associated with a bean class.
- * <p>
- * The order specified is the same order that the entries will be returned by the {@link BeanMap#entrySet()} and related methods.
- * <p>
- * This method is an alternative to using the {@link Bean#properties()} annotation on a class.
- *
- * <dl>
- * <dt>Example:</dt>
- * <dd>
- * <p class='bcode'>
- * <jc>// Create our serializer with a transform.</jc>
- * WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(AddressTransform.<jk>class</jk>);
- *
- * Address a = <jk>new</jk> Address();
- * String json = s.serialize(a); <jc>// Serializes only street, city, state.</jc>
- *
- * <jc>// Transform class</jc>
- * <jk>public class</jk> AddressTransform <jk>extends</jk> BeanTransform<Address> {
- * <jk>public</jk> AddressTransform() {
- * setProperties(<js>"street"</js>,<js>"city"</js>,<js>"state"</js>);
- * }
- * }
- * </p>
- * </dd>
- * </dl>
- *
- * @param properties The name of the properties associated with a bean class.
- * @return This object (for method chaining).
- */
- public BeanTransform<T> setProperties(String...properties) {
- this.properties = properties;
- return this;
- }
-
- /**
- * Same as {@link #setProperties(String[])} but pass in a comma-delimited list of values.
- *
- * @param properties A comma-delimited list of properties.
- * @return This object (for method chaining).
- */
- public BeanTransform<T> setProperties(String properties) {
- return setProperties(StringUtils.split(properties, ','));
- }
-
- /**
- * Returns <jk>true</jk> if the properties defined on this bean class should be ordered alphabetically.
- * <p>
- * This method is only used when the {@link #getProperties()} method returns <jk>null</jk>.
- * Otherwise, the ordering of the properties in the returned value is used.
- *
- * @see #setSortProperties(boolean)
- * @return <jk>true</jk> if bean properties should be sorted.
- */
- public boolean isSortProperties() {
- return sortProperties;
- }
-
- /**
- * Specifies whether the properties on this bean should be ordered alphabetically.
- * <p>
- * This method is ignored if the {@link #getProperties()} method does not return <jk>null</jk>.
- * <p>
- * This method is an alternative to using the {@link Bean#sort()} annotation on a class.
- *
- * @param sortProperties The new value for the sort properties property.
- * @return This object (for method chaining).
- */
- public BeanTransform<T> setSortProperties(boolean sortProperties) {
- this.sortProperties = sortProperties;
- return this;
- }
-
- /**
- * Returns the list of properties to ignore on a bean.
- *
- * @see #setExcludeProperties(String...)
- * @return The name of the properties to ignore on a bean, or <jk>null</jk> to not ignore any properties.
- */
- public String[] getExcludeProperties() {
- return excludeProperties;
- }
-
- /**
- * Specifies a list of properties to ignore on a bean.
- * <p>
- * This method is an alternative to using the {@link Bean#excludeProperties()} annotation on a class.
- *
- * <dl>
- * <dt>Example:</dt>
- * <dd>
- * <p class='bcode'>
- * <jc>// Create our serializer with a transform.</jc>
- * WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(NoCityOrStateTransform.<jk>class</jk>);
- *
- * Address a = <jk>new</jk> Address();
- * String json = s.serialize(a); <jc>// Excludes city and state.</jc>
- *
- * <jc>// Transform class</jc>
- * <jk>public class</jk> NoCityOrStateTransform <jk>extends</jk> BeanTransform<Address> {
- * <jk>public</jk> AddressTransform() {
- * setExcludeProperties(<js>"city"</js>,<js>"state"</js>);
- * }
- * }
- * </p>
- * </dd>
- * </dl>
- *
- * @param excludeProperties The name of the properties to ignore on a bean class.
- * @return This object (for method chaining).
- */
- public BeanTransform<T> setExcludeProperties(String...excludeProperties) {
- this.excludeProperties = excludeProperties;
- return this;
- }
-
- /**
- * Same as {@link #setExcludeProperties(String[])} but pass in a comma-delimited list of values.
- *
- * @param excludeProperties A comma-delimited list of properties to eclipse.
- * @return This object (for method chaining).
- */
- public BeanTransform<T> setExcludeProperties(String excludeProperties) {
- return setExcludeProperties(StringUtils.split(excludeProperties, ','));
- }
-
- /**
- * Returns the {@link PropertyNamer} associated with the bean to tailor the names of bean properties.
- *
- * @see #setPropertyNamer(Class)
- * @return The property namer class, or <jk>null</jk> if no property namer is associated with this bean property.
- */
- public Class<? extends PropertyNamer> getPropertyNamer() {
- return propertyNamer;
- }
-
- /**
- * Associates a {@link PropertyNamer} with this bean to tailor the names of the bean properties.
- * <p>
- * Property namers are used to transform bean property names from standard form to some other form.
- * For example, the {@link PropertyNamerDashedLC} will convert property names to dashed-lowercase, and
- * these will be used as attribute names in JSON, and element names in XML.
- * <p>
- * This method is an alternative to using the {@link Bean#propertyNamer()} annotation on a class.
- *
- * @param propertyNamer The property namer class.
- * @return This object (for method chaining).
- */
- public BeanTransform<T> setPropertyNamer(Class<? extends PropertyNamer> propertyNamer) {
- this.propertyNamer = propertyNamer;
- return this;
- }
-
- /**
- * Returns the name of the sub type property associated with the bean class.
- *
- * @see #setSubTypeProperty(String)
- * @return The sub type property name, or <jk>null</jk> if bean has no subtypes defined.
- */
- public String getSubTypeProperty() {
- return subTypeAttr;
- }
-
- /**
- * Defines a virtual property on a superclass that identifies bean subtype classes.
- * <p>
- * In the following example, the abstract class has two subclasses that are differentiated
- * by a property called <code>subType</code>
- *
- * <p class='bcode'>
- * <jc>// Abstract superclass</jc>
- * <jk>public abstract class</jk> A {
- * <jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>;
- * }
- *
- * <jc>// Subclass 1</jc>
- * <jk>public class</jk> A1 <jk>extends</jk> A {
- * <jk>public</jk> String <jf>f1</jf>;
- * }
- *
- * <jc>// Subclass 2</jc>
- * <jk>public class</jk> A2 <jk>extends</jk> A {
- * <jk>public</jk> String <jf>f2</jf>;
- * }
- *
- * <jc>// Transform for defining subtypes</jc>
- * <jk>public class</jk> ATransform <jk>extends</jk> BeanTransform<A> {
- * <jk>public</jk> ATransform() {
- * setSubTypeProperty(<js>"subType"</js>);
- * addSubType(Al.<jk>class</jk>, <js>"A1"</js>);
- * addSubType(A2.<jk>class</jk>, <js>"A2"</js>);
- * }
- * }
- * </p>
- * <p>
- * The following shows what happens when serializing a subclassed object to JSON:
- * <p class='bcode'>
- * JsonSerializer s = <jk>new</jk> JsonSerializer().addTransforms(ATransform.<jk>class</jk>);
- * A1 a1 = <jk>new</jk> A1();
- * a1.<jf>f1</jf> = <js>"f1"</js>;
- * String r = s.serialize(a1);
- * <jsm>assertEquals</jsm>(<js>"{subType:'A1',f1:'f1',f0:'f0'}"</js>, r);
- * </p>
- * <p>
- * The following shows what happens when parsing back into the original object.
- * <p class='bcode'>
- * JsonParser p = <jk>new</jk> JsonParser().addTransforms(ATransform.<jk>class</jk>);
- * A a = p.parse(r, A.<jk>class</jk>);
- * <jsm>assertTrue</jsm>(a <jk>instanceof</jk> A1);
- * </p>
- * <p>
- * This method is an alternative to using the {@link Bean#subTypeProperty()} annotation on a class.
- *
- * @param subTypeAttr The name of the attribute representing the subtype.
- * @return This object (for method chaining).
- */
- public BeanTransform<T> setSubTypeProperty(String subTypeAttr) {
- this.subTypeAttr = subTypeAttr;
- return this;
- }
-
- /**
- * Returns the subtypes associated with the bean class.
- *
- * @see #setSubTypeProperty(String)
- * @return The set of sub types associated with this bean class, or <jk>null</jk> if bean has no subtypes defined.
- */
- public LinkedHashMap<Class<?>, String> getSubTypes() {
- return subTypes;
- }
-
- /**
- * Specifies the set of subclasses of this bean class in addition to a string identifier for that subclass.
- *
- * @see #setSubTypeProperty(String)
- * @param subTypes the map of subtype classes to subtype identifier strings.
- * @return This object (for method chaining).
- */
- public BeanTransform<T> setSubTypes(LinkedHashMap<Class<?>, String> subTypes) {
- this.subTypes = subTypes;
- return this;
- }
-
- /**
- * Convenience method for adding a single subtype in leu of using {@link #setSubTypes(LinkedHashMap)} in one call.
- *
- * @see #setSubTypeProperty(String)
- * @param c The subtype class.
- * @param id The subtype identifier string for the specified subtype class.
- * @return This object (for method chaining).
- */
- public BeanTransform<T> addSubType(Class<?> c, String id) {
- if (subTypes == null)
- subTypes = new LinkedHashMap<Class<?>, String>();
- subTypes.put(c, id);
- return this;
- }
-
- /**
- * Returns the interface class associated with this class.
- *
- * @see #setInterfaceClass(Class)
- * @return The interface class associated with this class, or <jk>null</jk> if no interface class is associated.
- */
- public Class<?> getInterfaceClass() {
- return interfaceClass;
- }
-
- /**
- * Identifies a class to be used as the interface class for this and all subclasses.
- * <p>
- * Functionally equivalent to using the {@link Bean#interfaceClass()} annotation.
- * <p>
- * When specified, only the list of properties defined on the interface class will be used during serialization.
- * Additional properties on subclasses will be ignored.
- * <p class='bcode'>
- * <jc>// Parent class</jc>
- * <jk>public abstract class</jk> A {
- * <jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>;
- * }
- *
- * <jc>// Sub class</jc>
- * <jk>public class</jk> A1 <jk>extends</jk> A {
- * <jk>public</jk> String <jf>f1</jf> = <js>"f1"</js>;
- * }
- *
- * <jc>// Transform class</jc>
- * <jk>public class</jk> ATransform <jk>extends</jk> BeanTransform<A> {
- * <jk>public</jk> ATransform() {
- * setInterfaceClass(A.<jk>class</jk>);
- * }
- * }
- *
- * JsonSerializer s = new JsonSerializer().addTransforms(ATransform.<jk>class</jk>);
- * A1 a1 = <jk>new</jk> A1();
- * String r = s.serialize(a1);
- * <jsm>assertEquals</jsm>(<js>"{f0:'f0'}"</js>, r); <jc>// Note f1 is not serialized</jc>
- * </p>
- * <p>
- * Note that this transform can be used on the parent class so that it transforms to all child classes,
- * or can be set individually on the child classes.
- * <p>
- * This method is an alternative to using the {@link Bean#interfaceClass()}} annotation.
- *
- * @param interfaceClass The interface class.
- * @return This object (for method chaining).
- */
- public BeanTransform<T> setInterfaceClass(Class<?> interfaceClass) {
- this.interfaceClass = interfaceClass;
- return this;
- }
-
- /**
- * Returns the stop class associated with this class.
- *
- * @see #setStopClass(Class)
- * @return The stop class associated with this class, or <jk>null</jk> if no stop class is associated.
- */
- public Class<?> getStopClass() {
- return stopClass;
- }
-
- /**
- * Identifies a stop class for this class and all subclasses.
- * <p>
- * Functionally equivalent to using the {@link Bean#stopClass()} annotation.
- * <p>
- * Identical in purpose to the stop class specified by {@link Introspector#getBeanInfo(Class, Class)}.
- * Any properties in the stop class or in its baseclasses will be ignored during analysis.
- * <p>
- * For example, in the following class hierarchy, instances of <code>C3</code> will include property <code>p3</code>, but
- * not <code>p1</code> or <code>p2</code>.
- * <p class='bcode'>
- * <jk>public class</jk> C1 {
- * <jk>public int</jk> getP1();
- * }
- *
- * <jk>public class</jk> C2 <jk>extends</jk> C1 {
- * <jk>public int</jk> getP2();
- * }
- *
- * <ja>@Bean</ja>(stopClass=C2.<jk>class</jk>)
- * <jk>public class</jk> C3 <jk>extends</jk> C2 {
- * <jk>public int</jk> getP3();
- * }
- * </p>
- *
- * @param stopClass The stop class.
- * @return This object (for method chaining).
- */
- public BeanTransform<T> setStopClass(Class<?> stopClass) {
- this.stopClass = stopClass;
- return this;
- }
-
- /**
- * Subclasses can override this property to convert property values to some other
- * object just before serialization.
- *
- * @param bean The bean from which the property was read.
- * @param name The property name.
- * @param value The value just extracted from calling the bean getter.
- * @return The value to serialize. Default is just to return the existing value.
- */
- public Object readProperty(Object bean, String name, Object value) {
- return value;
- }
-
- /**
- * Subclasses can override this property to convert property values to some other
- * object just before calling the bean setter.
- *
- * @param bean The bean from which the property was read.
- * @param name The property name.
- * @param value The value just parsed.
- * @return <jk>true</jk> if we set the property, <jk>false</jk> if we should allow the
- * framework to call the setter.
- */
- public boolean writeProperty(Object bean, String name, Object value) {
- return false;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanFilter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanFilter.java b/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanFilter.java
new file mode 100644
index 0000000..2e9f95c
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanFilter.java
@@ -0,0 +1,39 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.juneau.transform;
+
+import org.apache.juneau.*;
+
+
+/**
+ * Simple bean filter that simply identifies a class to be used as an interface
+ * class for all child classes.
+ * <p>
+ * These objects are created when you pass in non-<code>Transform</code> classes to {@link ContextFactory#addToProperty(String,Object)},
+ * and are equivalent to adding a <code><ja>@Bean</ja>(interfaceClass=Foo.<jk>class</jk>)</code> annotation on the <code>Foo</code> class.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ * @param <T> The class type that this transform applies to.
+ */
+public class InterfaceBeanFilter<T> extends BeanFilter<T> {
+
+ /**
+ * Constructor.
+ *
+ * @param interfaceClass The class to use as an interface on all child classes.
+ */
+ public InterfaceBeanFilter(Class<T> interfaceClass) {
+ super(interfaceClass);
+ setInterfaceClass(interfaceClass);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanTransform.java b/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanTransform.java
deleted file mode 100644
index 5f281f3..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanTransform.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/***************************************************************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
- * to you 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.apache.juneau.transform;
-
-import org.apache.juneau.*;
-
-
-/**
- * Simple bean transform that simply identifies a class to be used as an interface
- * class for all child classes.
- * <p>
- * These objects are created when you pass in non-<code>Transform</code> classes to {@link ContextFactory#addToProperty(String,Object)},
- * and are equivalent to adding a <code><ja>@Bean</ja>(interfaceClass=Foo.<jk>class</jk>)</code> annotation on the <code>Foo</code> class.
- *
- * @author James Bognar (james.bognar@salesforce.com)
- * @param <T> The class type that this transform applies to.
- */
-public class InterfaceBeanTransform<T> extends BeanTransform<T> {
-
- /**
- * Constructor.
- *
- * @param interfaceClass The class to use as an interface on all child classes.
- */
- public InterfaceBeanTransform(Class<T> interfaceClass) {
- super(interfaceClass);
- setInterfaceClass(interfaceClass);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java b/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java
new file mode 100644
index 0000000..3bde495
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java
@@ -0,0 +1,265 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.juneau.transform;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.serializer.*;
+
+/**
+ * Used to convert non-serializable objects to a serializable form.
+ *
+ *
+ * <h6 class='topic'>Description</h6>
+ * <p>
+ * <code>PojoSwaps</code> are used to extend the functionality of the serializers and parsers to be able to handle POJOs
+ * that aren't automatically handled by the serializers or parsers. For example, JSON does not have a standard
+ * representation for rendering dates. By defining a special {@code Date} swap and associating it with a serializer and
+ * parser, you can convert a {@code Date} object to a {@code String} during serialization, and convert that {@code String} object back into
+ * a {@code Date} object during parsing.
+ * <p>
+ * Swaps MUST declare a public no-arg constructor so that the bean context can instantiate them.
+ * <p>
+ * <code>PojoSwaps</code> are associated with instances of {@link BeanContext BeanContexts} by passing the swap class to
+ * the {@link CoreApi#addTransforms(Class...)} method.<br>
+ * When associated with a bean context, fields of the specified type will automatically be converted when the
+ * {@link BeanMap#get(Object)} or {@link BeanMap#put(String, Object)} methods are called.<br>
+ * <p>
+ * <code>PojoSwaps</code> have two parameters:
+ * <ol>
+ * <li>{@code <T>} - The normal representation of an object.
+ * <li>{@code <S>} - The swapped representation of an object.
+ * </ol>
+ * <br>
+ * {@link Serializer Serializers} use swaps to convert objects of type T into objects of type S, and on calls to {@link BeanMap#get(Object)}.<br>
+ * {@link Parser Parsers} use swaps to convert objects of type S into objects of type T, and on calls to {@link BeanMap#put(String,Object)}.
+ *
+ *
+ * <h6 class='topic'>Swap Class Type {@code <S>}</h6>
+ * <p>
+ * The swapped object representation of an object must be an object type that the serializers can
+ * natively convert to JSON (or language-specific equivalent). The list of valid transformed types are as follows...
+ * <ul class='spaced-list'>
+ * <li>{@link String}
+ * <li>{@link Number}
+ * <li>{@link Boolean}
+ * <li>{@link Collection} containing anything on this list.
+ * <li>{@link Map} containing anything on this list.
+ * <li>A java bean with properties of anything on this list.
+ * <li>An array of anything on this list.
+ * </ul>
+ *
+ *
+ * <h6 class='topic'>Normal Class Type {@code <T>}</h6>
+ * <p>
+ * The normal object representation of an object.<br>
+ *
+ *
+ * <h6 class='topic'>One-way vs. Two-way Serialization</h6>
+ * <p>
+ * Note that while there is a unified interface for handling swaps during both serialization and parsing,
+ * in many cases only one of the {@link #swap(Object)} or {@link #unswap(Object, ClassMeta)} methods will be defined
+ * because the swap is one-way. For example, a swap may be defined to convert an {@code Iterator} to a {@code ObjectList}, but
+ * it's not possible to unswap an {@code Iterator}. In that case, the {@code generalize(Object}} method would
+ * be implemented, but the {@code narrow(ObjectMap)} object would not, and the swap would be associated on
+ * the serializer, but not the parser. Also, you may choose to serialize objects like {@code Dates} to readable {@code Strings},
+ * in which case it's not possible to reparse it back into a {@code Date}, since there is no way for the {@code Parser} to
+ * know it's a {@code Date} from just the JSON or XML text.
+ *
+ *
+ * <h6 class='topic'>Additional information</h6>
+ * See {@link org.apache.juneau.transform} for more information.
+ *
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ * @param <T> The normal form of the class.
+ * @param <S> The swapped form of the class.
+ */
+public abstract class PojoSwap<T,S> extends Transform {
+
+ /** Represents no transform. */
+ public static class NULL extends PojoSwap<Object,Object> {}
+
+ Class<T> normalClass;
+ Class<S> transformedClass;
+ ClassMeta<S> transformedClassMeta;
+
+ /**
+ * Constructor.
+ */
+ @SuppressWarnings("unchecked")
+ protected PojoSwap() {
+ super();
+
+ Class<?> c = this.getClass().getSuperclass();
+ Type t = this.getClass().getGenericSuperclass();
+ while (c != PojoSwap.class) {
+ t = c.getGenericSuperclass();
+ c = c.getSuperclass();
+ }
+
+ // Attempt to determine the T and G classes using reflection.
+ if (t instanceof ParameterizedType) {
+ ParameterizedType pt = (ParameterizedType)t;
+ Type[] pta = pt.getActualTypeArguments();
+ if (pta.length == 2) {
+ Type nType = pta[0];
+ if (nType instanceof Class) {
+ this.normalClass = (Class<T>)nType;
+
+ // <byte[],x> ends up containing a GenericArrayType, so it has to
+ // be handled as a special case.
+ } else if (nType instanceof GenericArrayType) {
+ Class<?> cmpntType = (Class<?>)((GenericArrayType)nType).getGenericComponentType();
+ this.normalClass = (Class<T>)Array.newInstance(cmpntType, 0).getClass();
+
+ // <Class<?>,x> ends up containing a ParameterizedType, so just use the raw type.
+ } else if (nType instanceof ParameterizedType) {
+ this.normalClass = (Class<T>)((ParameterizedType)nType).getRawType();
+
+ } else
+ throw new RuntimeException("Unsupported parameter type: " + nType);
+ if (pta[1] instanceof Class)
+ this.transformedClass = (Class<S>)pta[1];
+ else if (pta[1] instanceof ParameterizedType)
+ this.transformedClass = (Class<S>)((ParameterizedType)pta[1]).getRawType();
+ else
+ throw new RuntimeException("Unexpected transformed class type: " + pta[1].getClass().getName());
+ }
+ }
+ }
+
+ /**
+ * Constructor for when the normal and transformed classes are already known.
+ *
+ * @param normalClass The normal class (cannot be serialized).
+ * @param transformedClass The transformed class (serializable).
+ */
+ protected PojoSwap(Class<T> normalClass, Class<S> transformedClass) {
+ this.normalClass = normalClass;
+ this.transformedClass = transformedClass;
+ }
+
+ /**
+ * If this transform is to be used to serialize non-serializable POJOs, it must implement this method.
+ * <p>
+ * The object must be converted into one of the following serializable types:
+ * <ul class='spaced-list'>
+ * <li>{@link String}
+ * <li>{@link Number}
+ * <li>{@link Boolean}
+ * <li>{@link Collection} containing anything on this list.
+ * <li>{@link Map} containing anything on this list.
+ * <li>A java bean with properties of anything on this list.
+ * <li>An array of anything on this list.
+ * </ul>
+ *
+ * @param o The object to be transformed.
+ * @return The transformed object.
+ * @throws SerializeException If a problem occurred trying to convert the output.
+ */
+ public S swap(T o) throws SerializeException {
+ throw new SerializeException("Generalize method not implemented on transform ''{0}''", this.getClass().getName());
+ }
+
+ /**
+ * If this transform is to be used to reconstitute POJOs that aren't true Java beans, it must implement this method.
+ *
+ * @param f The transformed object.
+ * @param hint If possible, the parser will try to tell you the object type being created. For example,
+ * on a serialized date, this may tell you that the object being created must be of type {@code GregorianCalendar}.<br>
+ * This may be <jk>null</jk> if the parser cannot make this determination.
+ * @return The narrowed object.
+ * @throws ParseException If this method is not implemented.
+ */
+ public T unswap(S f, ClassMeta<?> hint) throws ParseException {
+ throw new ParseException("Narrow method not implemented on transform ''{0}''", this.getClass().getName());
+ }
+
+ /**
+ * Returns the T class, the normalized form of the class.
+ *
+ * @return The normal form of this class.
+ */
+ public Class<T> getNormalClass() {
+ return normalClass;
+ }
+
+ /**
+ * Returns the G class, the generialized form of the class.
+ * <p>
+ * Subclasses must override this method if the generialized class is {@code Object},
+ * meaning it can produce multiple generialized forms.
+ *
+ * @return The transformed form of this class.
+ */
+ public Class<S> getTransformedClass() {
+ return transformedClass;
+ }
+
+ /**
+ * Returns the {@link ClassMeta} of the transformed class type.
+ * This value is cached for quick lookup.
+ *
+ * @return The {@link ClassMeta} of the transformed class type.
+ */
+ public ClassMeta<S> getTransformedClassMeta() {
+ if (transformedClassMeta == null)
+ transformedClassMeta = beanContext.getClassMeta(transformedClass);
+ return transformedClassMeta;
+ }
+
+ /**
+ * Checks if the specified object is an instance of the normal class defined on this transform.
+ *
+ * @param o The object to check.
+ * @return <jk>true</jk> if the specified object is a subclass of the normal class defined on this transform.
+ * <jk>null</jk> always return <jk>false</jk>.
+ */
+ public boolean isNormalObject(Object o) {
+ if (o == null)
+ return false;
+ return ClassUtils.isParentClass(normalClass, o.getClass());
+ }
+
+ /**
+ * Checks if the specified object is an instance of the transformed class defined on this transform.
+ *
+ * @param o The object to check.
+ * @return <jk>true</jk> if the specified object is a subclass of the transformed class defined on this transform.
+ * <jk>null</jk> always return <jk>false</jk>.
+ */
+ public boolean isTransformedObject(Object o) {
+ if (o == null)
+ return false;
+ return ClassUtils.isParentClass(transformedClass, o.getClass());
+ }
+
+ //--------------------------------------------------------------------------------
+ // Overridden methods
+ //--------------------------------------------------------------------------------
+
+ @Override /* Transform */
+ public Class<?> forClass() {
+ return normalClass;
+ }
+
+ @Override /* Object */
+ public String toString() {
+ return getClass().getSimpleName() + '<' + getNormalClass().getSimpleName() + "," + getTransformedClass().getSimpleName() + '>';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/PojoTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/PojoTransform.java b/juneau-core/src/main/java/org/apache/juneau/transform/PojoTransform.java
deleted file mode 100644
index 4d41b3f..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/transform/PojoTransform.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/***************************************************************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
- * to you 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.apache.juneau.transform;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.internal.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.serializer.*;
-
-/**
- * Used to convert non-serializable objects to a serializable form.
- *
- *
- * <h6 class='topic'>Description</h6>
- * <p>
- * <code>PojoTransforms</code> are used to extend the functionality of the serializers and parsers to be able to handle POJOs
- * that aren't automatically handled by the serializers or parsers. For example, JSON does not have a standard
- * representation for rendering dates. By defining a special {@code Date} transform and associating it with a serializer and
- * parser, you can convert a {@code Date} object to a {@code String} during serialization, and convert that {@code String} object back into
- * a {@code Date} object during parsing.
- * <p>
- * Object transforms MUST declare a public no-arg constructor so that the bean context can instantiate them.
- * <p>
- * <code>PojoTransforms</code> are associated with instances of {@link BeanContext BeanContexts} by passing the transform class to
- * the {@link CoreApi#addTransforms(Class...)} method.<br>
- * When associated with a bean context, fields of the specified type will automatically be converted when the
- * {@link BeanMap#get(Object)} or {@link BeanMap#put(String, Object)} methods are called.<br>
- * <p>
- * <code>PojoTransforms</code> have two parameters:
- * <ol>
- * <li>{@code <F>} - The transformed representation of an object.
- * <li>{@code <T>} - The normal representation of an object.
- * </ol>
- * <br>
- * {@link Serializer Serializers} use object transforms to convert objects of type T into objects of type F, and on calls to {@link BeanMap#get(Object)}.<br>
- * {@link Parser Parsers} use object transforms to convert objects of type F into objects of type T, and on calls to {@link BeanMap#put(String,Object)}.
- *
- *
- * <h6 class='topic'>Transformed Class Type {@code <T>}</h6>
- * <p>
- * The transformed object representation of an object must be an object type that the serializers can
- * natively convert to JSON (or language-specific equivalent). The list of valid transformed types are as follows...
- * <ul class='spaced-list'>
- * <li>{@link String}
- * <li>{@link Number}
- * <li>{@link Boolean}
- * <li>{@link Collection} containing anything on this list.
- * <li>{@link Map} containing anything on this list.
- * <li>A java bean with properties of anything on this list.
- * <li>An array of anything on this list.
- * </ul>
- *
- *
- * <h6 class='topic'>Normal Class Type {@code <N>}</h6>
- * <p>
- * The normal object representation of an object.<br>
- *
- *
- * <h6 class='topic'>One-way vs. Two-way Serialization</h6>
- * <p>
- * Note that while there is a unified interface for handling transforming during both serialization and parsing,
- * in many cases only one of the {@link #transform(Object)} or {@link #normalize(Object, ClassMeta)} methods will be defined
- * because the transform is one-way. For example, a transform may be defined to convert an {@code Iterator} to a {@code ObjectList}, but
- * it's not possible to untransform an {@code Iterator}. In that case, the {@code generalize(Object}} method would
- * be implemented, but the {@code narrow(ObjectMap)} object would not, and the transform would be associated on
- * the serializer, but not the parser. Also, you may choose to serialize objects like {@code Dates} to readable {@code Strings},
- * in which case it's not possible to reparse it back into a {@code Date}, since there is no way for the {@code Parser} to
- * know it's a {@code Date} from just the JSON or XML text.
- *
- *
- * <h6 class='topic'>Additional information</h6>
- * See {@link org.apache.juneau.transform} for more information.
- *
- *
- * @author James Bognar (james.bognar@salesforce.com)
- * @param <N> The normal form of the class.
- * @param <T> The transformed form of the class.
- */
-public abstract class PojoTransform<N,T> extends Transform {
-
- /** Represents no transform. */
- public static class NULL extends PojoTransform<Object,Object> {}
-
- Class<N> normalClass;
- Class<T> transformedClass;
- ClassMeta<T> transformedClassMeta;
-
- /**
- * Constructor.
- */
- @SuppressWarnings("unchecked")
- protected PojoTransform() {
- super();
-
- Class<?> c = this.getClass().getSuperclass();
- Type t = this.getClass().getGenericSuperclass();
- while (c != PojoTransform.class) {
- t = c.getGenericSuperclass();
- c = c.getSuperclass();
- }
-
- // Attempt to determine the T and G classes using reflection.
- if (t instanceof ParameterizedType) {
- ParameterizedType pt = (ParameterizedType)t;
- Type[] pta = pt.getActualTypeArguments();
- if (pta.length == 2) {
- Type nType = pta[0];
- if (nType instanceof Class) {
- this.normalClass = (Class<N>)nType;
-
- // <byte[],x> ends up containing a GenericArrayType, so it has to
- // be handled as a special case.
- } else if (nType instanceof GenericArrayType) {
- Class<?> cmpntType = (Class<?>)((GenericArrayType)nType).getGenericComponentType();
- this.normalClass = (Class<N>)Array.newInstance(cmpntType, 0).getClass();
-
- // <Class<?>,x> ends up containing a ParameterizedType, so just use the raw type.
- } else if (nType instanceof ParameterizedType) {
- this.normalClass = (Class<N>)((ParameterizedType)nType).getRawType();
-
- } else
- throw new RuntimeException("Unsupported parameter type: " + nType);
- if (pta[1] instanceof Class)
- this.transformedClass = (Class<T>)pta[1];
- else if (pta[1] instanceof ParameterizedType)
- this.transformedClass = (Class<T>)((ParameterizedType)pta[1]).getRawType();
- else
- throw new RuntimeException("Unexpected transformed class type: " + pta[1].getClass().getName());
- }
- }
- }
-
- /**
- * Constructor for when the normal and transformed classes are already known.
- *
- * @param normalClass The normal class (cannot be serialized).
- * @param transformedClass The transformed class (serializable).
- */
- protected PojoTransform(Class<N> normalClass, Class<T> transformedClass) {
- this.normalClass = normalClass;
- this.transformedClass = transformedClass;
- }
-
- /**
- * If this transform is to be used to serialize non-serializable POJOs, it must implement this method.
- * <p>
- * The object must be converted into one of the following serializable types:
- * <ul class='spaced-list'>
- * <li>{@link String}
- * <li>{@link Number}
- * <li>{@link Boolean}
- * <li>{@link Collection} containing anything on this list.
- * <li>{@link Map} containing anything on this list.
- * <li>A java bean with properties of anything on this list.
- * <li>An array of anything on this list.
- * </ul>
- *
- * @param o The object to be transformed.
- * @return The transformed object.
- * @throws SerializeException If a problem occurred trying to convert the output.
- */
- public T transform(N o) throws SerializeException {
- throw new SerializeException("Generalize method not implemented on transform ''{0}''", this.getClass().getName());
- }
-
- /**
- * If this transform is to be used to reconstitute POJOs that aren't true Java beans, it must implement this method.
- *
- * @param f The transformed object.
- * @param hint If possible, the parser will try to tell you the object type being created. For example,
- * on a serialized date, this may tell you that the object being created must be of type {@code GregorianCalendar}.<br>
- * This may be <jk>null</jk> if the parser cannot make this determination.
- * @return The narrowed object.
- * @throws ParseException If this method is not implemented.
- */
- public N normalize(T f, ClassMeta<?> hint) throws ParseException {
- throw new ParseException("Narrow method not implemented on transform ''{0}''", this.getClass().getName());
- }
-
- /**
- * Returns the T class, the normalized form of the class.
- *
- * @return The normal form of this class.
- */
- public Class<N> getNormalClass() {
- return normalClass;
- }
-
- /**
- * Returns the G class, the generialized form of the class.
- * <p>
- * Subclasses must override this method if the generialized class is {@code Object},
- * meaning it can produce multiple generialized forms.
- *
- * @return The transformed form of this class.
- */
- public Class<T> getTransformedClass() {
- return transformedClass;
- }
-
- /**
- * Returns the {@link ClassMeta} of the transformed class type.
- * This value is cached for quick lookup.
- *
- * @return The {@link ClassMeta} of the transformed class type.
- */
- public ClassMeta<T> getTransformedClassMeta() {
- if (transformedClassMeta == null)
- transformedClassMeta = beanContext.getClassMeta(transformedClass);
- return transformedClassMeta;
- }
-
- /**
- * Checks if the specified object is an instance of the normal class defined on this transform.
- *
- * @param o The object to check.
- * @return <jk>true</jk> if the specified object is a subclass of the normal class defined on this transform.
- * <jk>null</jk> always return <jk>false</jk>.
- */
- public boolean isNormalObject(Object o) {
- if (o == null)
- return false;
- return ClassUtils.isParentClass(normalClass, o.getClass());
- }
-
- /**
- * Checks if the specified object is an instance of the transformed class defined on this transform.
- *
- * @param o The object to check.
- * @return <jk>true</jk> if the specified object is a subclass of the transformed class defined on this transform.
- * <jk>null</jk> always return <jk>false</jk>.
- */
- public boolean isTransformedObject(Object o) {
- if (o == null)
- return false;
- return ClassUtils.isParentClass(transformedClass, o.getClass());
- }
-
- //--------------------------------------------------------------------------------
- // Overridden methods
- //--------------------------------------------------------------------------------
-
- @Override /* Transform */
- public Class<?> forClass() {
- return normalClass;
- }
-
- @Override /* Object */
- public String toString() {
- return getClass().getSimpleName() + '<' + getNormalClass().getSimpleName() + "," + getTransformedClass().getSimpleName() + '>';
- }
-}