Revision: 9168
Author: [email protected]
Date: Fri Oct 29 12:46:21 2010
Log: Edited wiki page AutoBean through web user interface.
http://code.google.com/p/google-web-toolkit/source/detail?r=9168
Modified:
/wiki/AutoBean.wiki
=======================================
--- /wiki/AutoBean.wiki Fri Oct 29 12:11:01 2010
+++ /wiki/AutoBean.wiki Fri Oct 29 12:46:21 2010
@@ -66,16 +66,29 @@
== Property types ==
The following types may be used to compose AutoBean interfaces:
- * Primitive types and their boxed counterparts
- * `BigInteger`, `BigDecimal`
- * `java.util.Date`
- * enum types
- * Strings
- * Bean-like interfaces
- * Lists or Sets of any supported property type
+ * Value types:
+ * Primitive types and their boxed counterparts
+ * `BigInteger`, `BigDecimal`
+ * `java.util.Date`
+ * enum types
+ * Strings
+ * Reference types:
+ * Bean-like interfaces
+ * Lists or Sets of any supported property type
+
== !AutoBean ==
+An AutoBean must be parameterized with an interface type (e.g.
`AutoBean<Person>`). This interface type may have any type hierarchy and
need not extend any particular type in order to be usable with AutoBeans.
A distinction is made as to whether or not the target interface is "simple."
+
+A simple interface satisfies the following properties:
+ * Has only getter and setter methods
+ * Any non-property methods must be implemented by a category
+
+A simple AutoBean can be constructed by the AutoBeanFactory without
providing a delegate instance.
+
+If a reference interface is returned from a method in a target interface,
that instance will be automatically wrapped by an AutoBean instance. This
behavior can be disabled by placing a `...@nowrap` annotation on the
AutoBeanFactory.
+
=== accept() ===
The AutoBean controller provides a visitor API to allow the properties of
an AutoBean to be examined by code that has no prior knowledge of the
interface being wrapped.
@@ -102,8 +115,36 @@
== !AutoBeanFactory ==
+Instead of requiring a call to `GWT.create()` for every instance of an
AutoBean, only the `AutoBeanFactory` must be constructed with a call to
`GWT.create()` or `AutoBeanFactoryMagic.create()`. This allows the
AutoBeanFactory to be provided to consuming code by any
dependency-injection pattern desired.
+
+Methods in an AutoBeanFactory interface must return `AutoBean<Foo>`, where
`Foo` is any interface type compatible with AutoBeans. The methods may
optionally declare a single parameter of type `Foo` which allows
construction of an AutoBean around an existing object.
+
+{{{
+interface MyFactory extends AutoBeanFactory {
+ // Factory method for a simple AutoBean
+ AutoBean<Person> person();
+
+ // Factory method for a non-simple type or to wrap an existing instance
+ AutoBean<Person> person(Person toWrap);
+}
+}}}
+
+=== create() ===
+
+The `create()` method accepts a `Class` object of any interface type
reachable from the AutoBeanFactory interface. An optional parameter allows
a delegate object to be supplied that will be wrapped by the returned
AutoBean.
+
== !AutoBeanCodex ==
+The AutoBeanCodex provides general-purpose encoding and decoding of
AutoBeans into a JSON-formatted payload.
+
+=== decode() ===
+
+This method accepts an AutoBeanFactory, a `Class` object representing the
top-level AutoBean interface type to be returned, and a JSON-formatted
payload. The provided AutoBeanFactory must be capable of producing
AutoBeans for all interface types reachable from the provided interface.
+
+=== encode() ===
+
+This method accepts an AutoBean and returns a JSON-formatted string that
contains the properties of the AutoBean and its associated object graph.
+
== !AutoBeanVisitor ==
AutoBeanVisitor is a concrete, no-op, base type that is intended to be
extended by developers that wish to write reflection-like code over an
AutoBean's target interface.
@@ -137,9 +178,14 @@
{ "name" : "John Doe", "address" : { "street" : "1234 Maple
St", "city" : "Nowhere" } }
}}}
-List and Set properties are encoded as JSON lists.
-
-*Below is not yet implemented*
+List and Set properties are encoded as JSON lists. For example, a
`List<Person>` would be encoded as:
+
+{{{
+[ { "name" : "John Doe" } , { "name" : "Jim Smith" } ]
+}}}
+
+* Maps are not yet implemented *
+
Maps are serialized in two forms based on wether or not the key type is a
value or reference type. Value maps are encoded as a typical JSON object.
For example, a `Map<Integer, Foo>` would be encoded as
{{{
{ "1" : { "property" : "value"}, "55" : { "property" : "value" } }
@@ -153,4 +199,50 @@
== Categories ==
+Pure bean interfaces only go so far to producing a useful system. For
example, the `EntityProxy` type used by RequestFactory is an AutoBean
interface, save for the addition of the `stableId()` method. An
AutoBeanFactory can produce non-wrapper (aka "simple") instances of a
non-simple interface if an implementation of any non-property interface is
provided by a category.
+
+{{{
+interface Person {
+ String getName();
+ void setName(String name);
+ boolean marry(Person spouse);
+}
+
+...@category(PersonCategory.class)
+interface MyFactory {
+ // Would be illegal without a category providing an implementation of
doSomething()
+ AutoBean<Person> person();
+}
+
+class PersonCategory {
+ public static boolean marray(AutoBean<Person> instance, Person spouse) {
+ return new Marriage(instance.as(), spouse).accepted();
+ }
+}
+}}}
+
+For any non-property method, the category must declare a public, static
method which has an additional 0-th parameter which accepts the AutoBean
backing the instance. Another example from RequestFactory demonstrating
the implementation of the `stableId()` method:
+
+{{{
+class EntityProxyCategory {
+ EntityProxyId<?> stableId(AutoBean<EntityProxy> instance) {
+ return (EntityProxyId<?>) instance.getTag("stableId");
+}
+}}}
+
+The `...@category` annotation may specify more than one category type. The
first method in the first category whose name matches the non-property
method that is type-assignable will be selected. The parameterization of
the 0-th parameter AutoBean is examined when making this decision.
+
+=== Interceptors ===
+
+A category implementation may additionally declare an interceptor method
to examine and possible replace the return values of all non-void methods
in the target interface:
+
+{{{
+public static <T> T __intercept(AutoBean<?> bean, T returnValue) {
+ // Do stuff
+ return maybeAlteredReturnValue;
+}
+}}}
+
+RequestFactory uses this to make `EntityProxy` objects returned from an
editable object editable.
+
== FAQ ==
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors