abdera-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jmsn...@apache.org
Subject svn commit: r1200583 [1/5] - in /abdera/abdera2: activities/src/main/java/org/apache/abdera2/activities/client/ activities/src/main/java/org/apache/abdera2/activities/extra/ activities/src/main/java/org/apache/abdera2/activities/io/gson/ activities/src...
Date Thu, 10 Nov 2011 21:48:48 GMT
Author: jmsnell
Date: Thu Nov 10 21:48:45 2011
New Revision: 1200583

URL: http://svn.apache.org/viewvc?rev=1200583&view=rev
Log:
Ok.. major update to the Activity Streams impl... essentially, this makes all of the various AS Object types into immutable, threadsafe classes that follow the simple fluent factory api pattern for constructing. The change allows for much more logical, compact and fluid code and provides for a number of interesting a helpful new capabilities. This is a change that I had wanted to make before and had been slowly moving towards but figured it was time to pull the bandaid off all at once... 

Added:
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASDocument.java   (with props)
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/AlertObject.java   (with props)
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/ErrorObject.java   (contents, props changed)
      - copied, changed from r1187164, abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/protocol/ErrorObject.java
Removed:
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/Generator.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/protocol/ErrorObject.java
Modified:
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesClient.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesClientBatchPusher.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesSession.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/ASContext.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/Extra.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/Jwt.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/PusherCollectionWriter.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/SimpleCollectionWriter.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/io/gson/BaseAdapter.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/io/gson/GsonIO.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASBase.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/AbstractCollectionWriter.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/Activity.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/Collection.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/CollectionWriter.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/IO.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/MediaLink.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/AccountObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/AdditionalEventProperties.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/Address.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/ArticleObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/AudioObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/BadgeObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/BinaryObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/BookObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/BookmarkObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/CommentObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/CreativeWork.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/EmbeddedExperience.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/EventObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/FileObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/GroupObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/ImageObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/Mood.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/MovieObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/NameObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/NoteObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/Objects.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/OfferObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/OrganizationObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/PersonObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/PlaceObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/ProductObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/QuestionObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/ReviewObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/ServiceObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/TvEpisodeObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/TvSeasonObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/TvSeriesObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/VersionObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/VideoObject.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/protocol/AbstractActivitiesCollectionAdapter.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/protocol/AbstractActivitiesProvider.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/protocol/AbstractActivitiesWorkspaceProvider.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/protocol/ActivitiesResponseContext.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/protocol/ProtocolException.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/protocol/basic/BasicAdapter.java
    abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/protocol/managed/FeedConfiguration.java
    abdera/abdera2/common/src/main/java/org/apache/abdera2/common/geo/IsoPosition.java
    abdera/abdera2/common/src/main/java/org/apache/abdera2/common/misc/MoreFunctions.java
    abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/Activities.java
    abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/ExtendingBaseObjectExample.java
    abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/ExtensionExample.java
    abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/GeneratorStreamingExample.java
    abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/GooglePlusExample.java
    abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/MiscellaneousExamples.java
    abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/MyActivitiesAdapter.java
    abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/PusherExample.java
    abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/ReadingListExample.java
    abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/RepliesAndTargetingExample.java
    abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/VersionControlExample.java
    abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/security/JwtExample.java
    abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/activities/FeedToActivityConverter.java
    abdera/abdera2/test/src/main/java/org/apache/abdera2/test/activities/server/AsyncBasicTest.java
    abdera/abdera2/test/src/main/java/org/apache/abdera2/test/activities/server/BasicTest.java
    abdera/abdera2/test/src/main/java/org/apache/abdera2/test/activities/server/SampleBasicAdapter.java

Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesClient.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesClient.java?rev=1200583&r1=1200582&r2=1200583&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesClient.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesClient.java Thu Nov 10 21:48:45 2011
@@ -1,5 +1,6 @@
 package org.apache.abdera2.activities.client;
 
+import org.apache.abdera2.activities.model.ASDocument;
 import org.apache.abdera2.activities.model.ASObject;
 import org.apache.abdera2.activities.model.Activity;
 import org.apache.abdera2.activities.model.Collection;
@@ -31,32 +32,32 @@ public class ActivitiesClient 
     return (T)new ActivitiesSession(this);
   }
 
-  public <T extends Collection<?>>T getCollection(String uri) {
+  public <T extends Collection<?>>ASDocument<T> getCollection(String uri) {
     ActivitiesSession session = newSession();
     return session.<T>getCollection(uri);
   }
   
-  public <T extends Collection<?>>T getCollection(String uri, RequestOptions options) {
+  public <T extends Collection<?>>ASDocument<T> getCollection(String uri, RequestOptions options) {
     ActivitiesSession session = newSession();
     return session.<T>getCollection(uri,options);
   }
   
-  public <T extends Activity>T getActivity(String uri) {
+  public <T extends Activity>ASDocument<T> getActivity(String uri) {
     ActivitiesSession session = newSession();
     return session.<T>getActivity(uri);
   }
   
-  public <T extends Activity>T getActivity(String uri, RequestOptions options) {
+  public <T extends Activity>ASDocument<T> getActivity(String uri, RequestOptions options) {
     ActivitiesSession session = newSession();
     return session.<T>getActivity(uri,options);
   }
   
-  public <T extends ASObject>T getObject(String uri) {
+  public <T extends ASObject>ASDocument<T> getObject(String uri) {
     ActivitiesSession session = newSession();
     return session.<T>getObject(uri);
   }
   
-  public <T extends ASObject>T getObject(String uri, RequestOptions options) {
+  public <T extends ASObject>ASDocument<T> getObject(String uri, RequestOptions options) {
     ActivitiesSession session = newSession();
     return session.<T>getObject(uri,options);
   }

Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesClientBatchPusher.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesClientBatchPusher.java?rev=1200583&r1=1200582&r2=1200583&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesClientBatchPusher.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesClientBatchPusher.java Thu Nov 10 21:48:45 2011
@@ -36,9 +36,11 @@ public class ActivitiesClientBatchPusher
         new Runnable() {
           public void run() {
             try {
-              Collection<T> col = new Collection<T>();
-              col.setItems(t);
-              handle(session.post(iri, col, options));
+              handle(
+                session.post(
+                  iri, 
+                  Collection.<T>makeCollection(t), 
+                  options));
             } catch (Throwable ex) {
               handle(ex);
             }

Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesSession.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesSession.java?rev=1200583&r1=1200582&r2=1200583&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesSession.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/client/ActivitiesSession.java Thu Nov 10 21:48:45 2011
@@ -3,6 +3,7 @@ package org.apache.abdera2.activities.cl
 import javax.activation.MimeType;
 
 import org.apache.abdera2.activities.model.ASBase;
+import org.apache.abdera2.activities.model.ASDocument;
 import org.apache.abdera2.activities.model.ASObject;
 import org.apache.abdera2.activities.model.Activity;
 import org.apache.abdera2.activities.model.Collection;
@@ -38,29 +39,29 @@ public class ActivitiesSession 
     return (ActivitiesClient) client;
   }
 
-  public <T extends Collection<?>>T getCollection(String uri) {
-    return (T)getCollection(uri, this.getDefaultRequestOptions());
+  public <T extends Collection<?>>ASDocument<T> getCollection(String uri) {
+    return this.<T>getCollection(uri, this.getDefaultRequestOptions());
   }
   
   public <T extends ClientResponse>T post(String uri, ASBase base) {
-    return (T)post(uri,base, this.getDefaultRequestOptions());
+    return this.<T>post(uri,base, this.getDefaultRequestOptions());
   }
   
   public <T extends ClientResponse>T post(String uri, ASBase base, RequestOptions options) {
     ActivityEntity entity = new ActivityEntity(base);
-    return (T)post(uri, entity, options);
+    return this.<T>post(uri, entity, options);
   }
 
   public <T extends ClientResponse>T put(String uri, ASBase base) {
-    return (T)put(uri,base, this.getDefaultRequestOptions());
+    return this.<T>put(uri,base, this.getDefaultRequestOptions());
   }
   
   public <T extends ClientResponse>T put(String uri, ASBase base, RequestOptions options) {
     ActivityEntity entity = new ActivityEntity(base);
-    return (T)put(uri, entity, options);
+    return this.<T>put(uri, entity, options);
   }
   
-  public <T extends Collection<?>>T getCollection(String uri, RequestOptions options) {
+  public <T extends Collection<?>>ASDocument<T> getCollection(String uri, RequestOptions options) {
     ClientResponse cr = get(uri, options);
     try {
       if (cr != null) {
@@ -68,8 +69,7 @@ public class ActivitiesSession 
         case SUCCESSFUL:
           try {
             T t = (T)io.readCollection(cr.getReader());
-            setDocProperties(cr,t);
-            return t;
+            return getDoc(cr,t);
           } catch (Throwable t) {
             throw new ProtocolException(601, t.getMessage());
           }
@@ -84,11 +84,11 @@ public class ActivitiesSession 
     }
   }
   
-  public <T extends Activity>T getActivity(String uri) {
-    return (T)getActivity(uri,this.getDefaultRequestOptions());
+  public <T extends Activity>ASDocument<T> getActivity(String uri) {
+    return this.<T>getActivity(uri,this.getDefaultRequestOptions());
   }
   
-  public <T extends Activity>T getActivity(String uri, RequestOptions options) {
+  public <T extends Activity>ASDocument<T> getActivity(String uri, RequestOptions options) {
     ClientResponse cr = get(uri, options);
     try {
       if (cr != null) {
@@ -96,8 +96,7 @@ public class ActivitiesSession 
         case SUCCESSFUL:
           try {
             T t = (T)io.readActivity(cr.getReader());
-            setDocProperties(cr,t);
-            return t;
+            return getDoc(cr,t);
           } catch (Throwable t) {
             throw new ProtocolException(601, t.getMessage());
           }
@@ -112,11 +111,11 @@ public class ActivitiesSession 
     }
   }
   
-  public <T extends ASObject>T getObject(String uri) {
-    return (T)getObject(uri, this.getDefaultRequestOptions());
+  public <T extends ASObject>ASDocument<T> getObject(String uri) {
+    return this.<T>getObject(uri, this.getDefaultRequestOptions());
   }
 
-  public <T extends ASObject>T getObject(String uri, RequestOptions options) {
+  public <T extends ASObject>ASDocument<T> getObject(String uri, RequestOptions options) {
     ClientResponse cr = get(uri, options);
     try {
       if (cr != null) {
@@ -124,8 +123,7 @@ public class ActivitiesSession 
         case SUCCESSFUL:
           try {
             T t = (T)io.readObject(cr.getReader());
-            setDocProperties(cr,t);
-            return t;
+            return getDoc(cr,t);
           } catch (Throwable t) {
             throw new ProtocolException(601, t.getMessage());
           }
@@ -140,21 +138,24 @@ public class ActivitiesSession 
     }
   }
   
-  private void setDocProperties(ClientResponse resp, ASBase base) {
+  private <T extends ASBase>ASDocument<T> getDoc(ClientResponse resp, T base) {
+    ASDocument.Builder<T> builder = 
+      ASDocument.make(base);
     EntityTag etag = resp.getEntityTag();
     if (etag != null)
-        base.setEntityTag(etag);
+        builder.entityTag(etag);
     DateTime lm = resp.getLastModified();
     if (lm != null)
-        base.setLastModified(lm);
+        builder.lastModified(lm);
     MimeType mt = resp.getContentType();
     if (mt != null)
-        base.setContentType(mt.toString());
+        builder.contentType(mt.toString());
     String language = resp.getContentLanguage();
     if (language != null)
-        base.setLanguage(language);
+        builder.language(language);
     String slug = resp.getSlug();
     if (slug != null)
-        base.setSlug(slug);
+        builder.slug(slug);
+    return builder.get();
   }
 }

Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/ASContext.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/ASContext.java?rev=1200583&r1=1200582&r2=1200583&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/ASContext.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/ASContext.java Thu Nov 10 21:48:45 2011
@@ -22,6 +22,10 @@ public final class ASContext 
   private static final long serialVersionUID = 4445623432125049535L;
   private final ASBase base;
   
+  public static ASContext create(ASBase base) {
+    return new ASContext(base);
+  }
+  
   public ASContext(ASBase base) {
     super(false);
     this.base = base;

Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/Extra.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/Extra.java?rev=1200583&r1=1200582&r2=1200583&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/Extra.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/Extra.java Thu Nov 10 21:48:45 2011
@@ -36,7 +36,7 @@ import static com.google.common.base.Pre
 /**
  * Miscellaneous extensions
  */
-@SuppressWarnings("unchecked")
+@SuppressWarnings({"unchecked","rawtypes"})
 public class Extra {
 
   /**
@@ -481,72 +481,72 @@ public class Extra {
   
   
   public static <X extends ASObject>Selector<X> isMe() {
-    return (Selector<X>)sameIdentity(ME());
+    return (Selector<X>)sameIdentity(ME);
   }
   
   public static <X extends ASObject>Selector<X> isSelf() {
-    return (Selector<X>)sameIdentity(SELF());
+    return (Selector<X>)sameIdentity(SELF);
   }
   
   public static <X extends ASObject>Selector<X> isFriends() {
-    return (Selector<X>)sameIdentity(FRIENDS());
+    return (Selector<X>)sameIdentity(FRIENDS);
   }
   
   public static <X extends ASObject>Selector<X> isFriends(String id) {
-    return (Selector<X>)sameIdentity(FRIENDS(id));
+    return (Selector<X>)sameIdentity(FRIENDS(id).get());
   }
   
   public static <X extends ASObject>Selector<X> isNetwork() {
-    return (Selector<X>)sameIdentity(NETWORK());
+    return (Selector<X>)sameIdentity(NETWORK);
   }
   
   public static <X extends ASObject>Selector<X> isAll() {
-    return (Selector<X>)sameIdentity(ALL());
+    return (Selector<X>)sameIdentity(ALL);
   }
   
   public static <X extends ASObject>Selector<X> isPublic() {
-    return (Selector<X>)sameIdentity(PUBLIC());
+    return (Selector<X>)sameIdentity(PUBLIC);
   }
   
   public static <X extends ASObject>Selector<X> isMeOr(ASObject object) {
     Selector<X> s1 = sameIdentity(object);
-    Selector<X> s2 = sameIdentity(ME());
+    Selector<X> s2 = sameIdentity(ME);
     return Selectors.<X>or(s1,s2);
   }
   
   public static <X extends ASObject>Selector<X> isSelfOr(ASObject object) {
     Selector<X> s1 = sameIdentity(object);
-    Selector<X> s2 = sameIdentity(SELF());
+    Selector<X> s2 = sameIdentity(SELF);
     return Selectors.<X>or(s1,s2);
   }
   
   public static <X extends ASObject>Selector<X> isFriendsOr(ASObject object) {
     Selector<X> s1 = sameIdentity(object);
-    Selector<X> s2 = sameIdentity(FRIENDS());
+    Selector<X> s2 = sameIdentity(FRIENDS);
     return Selectors.<X>or(s1,s2);
   }
   
   public static <X extends ASObject>Selector<X> isFriendsOr(String id, ASObject object) {
     Selector<X> s1 = sameIdentity(object);
-    Selector<X> s2 = sameIdentity(FRIENDS(id));
+    Selector<X> s2 = sameIdentity(FRIENDS(id).get());
     return Selectors.<X>or(s1,s2);
   }
   
   public static <X extends ASObject>Selector<X> isNetworkOr(ASObject object) {
     Selector<X> s1 = sameIdentity(object);
-    Selector<X> s2 = sameIdentity(NETWORK());
+    Selector<X> s2 = sameIdentity(NETWORK);
     return Selectors.<X>or(s1,s2);
   }
   
   public static <X extends ASObject>Selector<X> isAllOr(ASObject object) {
     Selector<X> s1 = sameIdentity(object);
-    Selector<X> s2 = sameIdentity(ALL());
+    Selector<X> s2 = sameIdentity(ALL);
     return Selectors.<X>or(s1,s2);
   }
   
   public static <X extends ASObject>Selector<X> isPublicOr(ASObject object) {
     Selector<X> s1 = sameIdentity(object);
-    Selector<X> s2 = sameIdentity(PUBLIC());
+    Selector<X> s2 = sameIdentity(PUBLIC);
     return Selectors.<X>or(s1,s2);
   }
   
@@ -653,7 +653,7 @@ public class Extra {
   public static final Comparator<ASObject> PUBLISHED_COMPARATOR = 
     new PublishedComparator();
   
-  private static class UpdatedComparator 
+  static class UpdatedComparator 
     extends DateTimes.DateTimeComparator<ASObject> {
       public int compare(ASObject a1, ASObject a2) {
         DateTime d1 = a1.getUpdated();
@@ -662,7 +662,7 @@ public class Extra {
       }
   }
   
-  private static class PublishedComparator 
+  static class PublishedComparator 
     extends DateTimes.DateTimeComparator<ASObject> {
       public int compare(ASObject a1, ASObject a2) {
         return innerCompare(
@@ -702,6 +702,64 @@ public class Extra {
     return (M)e.create();
   }
   
+  /**
+   * Uses cglib to create an extension of the base ASObject type
+   * that implements the given interface. All setter/getter methods
+   * on the supplied interface will be mapped to properties on the
+   * underlying ASObject.. for instance, getFoo() and setFoo(..) will
+   * be mapped to a "foo" property
+   */
+  public static <X extends ASBase.Builder,M>M extendBuilder(
+    X object,
+    Class<?> type) {
+    checkNotNull(type);
+    checkNotNull(object);
+    Enhancer e = new Enhancer();
+    if (type.isInterface()) {
+      e.setSuperclass(type);
+      e.setInterfaces(addin(object.getClass().getInterfaces(),type));
+    } else if (ASObject.class.isAssignableFrom(type)) {
+      e.setSuperclass(type);
+    }
+    e.setCallback(new BuilderWrapper(type,object));
+    return (M)e.create();
+  }
+  
+  private static class BuilderWrapper 
+  implements MethodInterceptor {
+  private final Class<?> type;
+  private final ASBase.Builder builder;
+  BuilderWrapper(
+    Class<?> type, 
+    ASBase.Builder builder) {
+    this.type = type;
+    this.builder = builder;
+  }
+  public Object intercept(
+    Object obj, 
+    Method method, 
+    Object[] args,
+    MethodProxy proxy) 
+      throws Throwable {
+      if (method.getDeclaringClass().equals(type)) {
+        boolean setter = 
+          method.getName().matches("[Ss]et.+") || 
+          ((void.class.isAssignableFrom(method.getReturnType()) ||
+           method.getReturnType().isAssignableFrom(type)) && 
+          method.getParameterTypes().length == 1);
+        String name = get_name(method);
+        if (setter) {
+          if (args.length != 1)
+            throw new UnsupportedOperationException();
+          builder.set(name,args[0]);
+          return method.getReturnType().isAssignableFrom(type) ?
+            obj : null; 
+        } else {
+          throw new UnsupportedOperationException();
+        }
+      } else return proxy.invokeSuper(builder, args);
+    }    
+  }
   
   private static class ExtensionWrapper 
     implements MethodInterceptor {
@@ -720,19 +778,20 @@ public class Extra {
       MethodProxy proxy) 
         throws Throwable {
       if (method.getDeclaringClass().equals(type)) {
-        boolean setter = 
-          method.getName().matches("[Ss]et.+") || 
-          (void.class.isAssignableFrom(method.getReturnType()) && 
-          method.getParameterTypes().length == 1);
         String name = get_name(method);
-        if (setter) {
-          if (args.length != 1)
-            throw new UnsupportedOperationException();
-          base.setProperty(name,args[0]);
-          return method.getReturnType().isAssignableFrom(type) ?
-            obj : null; 
-        } else if (method.getParameterTypes().length == 0) {
-          return method.getReturnType().cast(base.getProperty(name));
+        if (method.getParameterTypes().length == 0 && 
+            method.getReturnType() != Void.class) {
+          Object ret = base.getProperty(name);
+          Class<?> retType = method.getReturnType();
+          if (ret instanceof ASBase && 
+              ASBase.class.isAssignableFrom(retType) && 
+              !ret.getClass().equals(ASBase.class) &&
+              !ret.getClass().equals(type)) {
+            ASBase bret = (ASBase) ret;
+            return bret.as((Class<? extends ASBase>)retType);
+          } else {
+            return retType.cast(base.getProperty(name));
+          }
         } else {
           throw new UnsupportedOperationException();
         }
@@ -740,7 +799,7 @@ public class Extra {
     }    
   }
   
-  private static String get_name(Method obj) {   
+  static String get_name(Method obj) {   
     String name = null;
     if (obj.isAnnotationPresent(Name.class))
       name = obj.getAnnotation(Name.class).value();

Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/Jwt.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/Jwt.java?rev=1200583&r1=1200582&r2=1200583&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/Jwt.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/Jwt.java Thu Nov 10 21:48:45 2011
@@ -10,6 +10,7 @@ import org.apache.abdera2.activities.mod
 import org.apache.abdera2.activities.model.IO;
 import org.apache.abdera2.common.security.HashHelper;
 import org.apache.commons.codec.binary.Base64;
+import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * Utility class for Generating/Validating JSON Web Tokens 
@@ -119,18 +120,17 @@ public class Jwt {
   }
   
   public static String generate(IO io, Alg alg, Key key, ASBase claim) {
-    return generate(io,alg,key,claim,null);
+    return generate(io,alg,key,claim,ASBase.make().set("alg", alg).get());
   }
   
   public static String generate(IO io, Alg alg, Key key, byte[] claim) {
-    return generate(io,alg,key,claim,null);
+    return generate(io,alg,key,claim,ASBase.make().set("alg", alg).get());
   }
   
   public static String generate(IO io, Alg alg, Key key, byte[] claim, ASBase header) {
     try {
-      if (header == null) header = new ASBase();
-      if (!header.has("alg"))
-        header.setProperty("alg", alg.toString());
+      checkNotNull(header);
+      checkNotNull(header.getProperty("alg"));
       StringBuilder buf = new StringBuilder();
       String _header = Base64.encodeBase64URLSafeString(io.write(header).getBytes("UTF-8"));
       String _claim = Base64.encodeBase64URLSafeString(claim);

Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/PusherCollectionWriter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/PusherCollectionWriter.java?rev=1200583&r1=1200582&r2=1200583&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/PusherCollectionWriter.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/PusherCollectionWriter.java Thu Nov 10 21:48:45 2011
@@ -1,6 +1,7 @@
 package org.apache.abdera2.activities.extra;
 
 import org.apache.abdera2.activities.model.ASBase;
+import org.apache.abdera2.activities.model.ASBase.Builder;
 import org.apache.abdera2.activities.model.ASObject;
 import org.apache.abdera2.activities.model.CollectionWriter;
 import org.apache.abdera2.common.pusher.Pusher;
@@ -51,5 +52,14 @@ public class PusherCollectionWriter 
   public void complete() {
     // ignored
   }
+
+  public <X extends CollectionWriter> X writeHeader(Builder<?, ?> base) {
+    return writeHeader(base.get());
+  }
+
+  public <X extends CollectionWriter> X writeObject(
+      org.apache.abdera2.activities.model.ASObject.Builder<?, ?> object) {
+    return writeObject(object.get());
+  }
   
 }

Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/SimpleCollectionWriter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/SimpleCollectionWriter.java?rev=1200583&r1=1200582&r2=1200583&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/SimpleCollectionWriter.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/SimpleCollectionWriter.java Thu Nov 10 21:48:45 2011
@@ -8,31 +8,27 @@ import org.apache.abdera2.activities.mod
  * Simple implementation of the CollectionWriter interface that builds
  * an in-memory Collection using the CollectionWriter's streaming interface.
  */
-@SuppressWarnings({"unchecked","rawtypes"})
-public class SimpleCollectionWriter 
+@SuppressWarnings({"unchecked"})
+public class SimpleCollectionWriter<T extends ASObject> 
   extends AbstractCollectionWriter {
 
-  private final Collection collection = new Collection();
+  private final Collection.CollectionBuilder<T> builder = 
+    Collection.makeCollection();
   
   @Override
   protected void write(String name, Object val) {
-    collection.setProperty(name, val);
+    builder.set(name, val);
   }
 
-  @Override
-  protected void startItems() {
-    collection.getItems(true);
-  }
+  protected void startItems() {}
 
-  @Override
   protected void writeItem(ASObject object) {
-    collection.addItem(object);
+    builder.item((T)object);
   }
 
-  @Override
   public void complete() {}
 
-  public <T extends ASObject>Collection<T> getCollection() {
-    return (Collection<T>) collection;
+  public Collection<T> getCollection() {
+    return builder.get();
   }
 }

Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/io/gson/BaseAdapter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/io/gson/BaseAdapter.java?rev=1200583&r1=1200582&r2=1200583&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/io/gson/BaseAdapter.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/io/gson/BaseAdapter.java Thu Nov 10 21:48:45 2011
@@ -18,8 +18,6 @@
 package org.apache.abdera2.activities.io.gson;
 
 import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
@@ -35,6 +33,7 @@ import org.apache.abdera2.common.lang.La
 import org.apache.abdera2.activities.model.*;
 import org.apache.abdera2.activities.model.objects.AccountObject;
 import org.apache.abdera2.activities.model.objects.Address;
+import org.apache.abdera2.activities.model.objects.AlertObject;
 import org.apache.abdera2.activities.model.objects.ArticleObject;
 import org.apache.abdera2.activities.model.objects.AudioObject;
 import org.apache.abdera2.activities.model.objects.BadgeObject;
@@ -42,6 +41,7 @@ import org.apache.abdera2.activities.mod
 import org.apache.abdera2.activities.model.objects.BookObject;
 import org.apache.abdera2.activities.model.objects.BookmarkObject;
 import org.apache.abdera2.activities.model.objects.CommentObject;
+import org.apache.abdera2.activities.model.objects.ErrorObject;
 import org.apache.abdera2.activities.model.objects.EventObject;
 import org.apache.abdera2.activities.model.objects.FileObject;
 import org.apache.abdera2.activities.model.objects.GroupObject;
@@ -63,9 +63,9 @@ import org.apache.abdera2.activities.mod
 import org.apache.abdera2.activities.model.objects.TvSeriesObject;
 import org.apache.abdera2.activities.model.objects.VersionObject;
 import org.apache.abdera2.activities.model.objects.VideoObject;
-import org.apache.abdera2.activities.protocol.ErrorObject;
 import org.joda.time.DateTime;
 
+import com.google.common.collect.ImmutableList;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonDeserializationContext;
 import com.google.gson.JsonElement;
@@ -77,13 +77,15 @@ import com.google.gson.JsonSerialization
 /**
  * (De)serialization of ASBase object
  */
+@SuppressWarnings("rawtypes")
 public class BaseAdapter 
   implements GsonTypeAdapter<ASBase> {
 
   private final Map<String,Class<?>> map = 
     new ConcurrentHashMap<String,Class<?>>();
-  private final Map<String,Class<? extends ASObject>> objsmap =
-    new ConcurrentHashMap<String,Class<? extends ASObject>>();
+  
+  private final Map<String,Class<? extends ASObject.Builder>> objsmap =
+    new ConcurrentHashMap<String,Class<? extends ASObject.Builder>>();
   
   public BaseAdapter() {
     initPropMap();
@@ -132,46 +134,47 @@ public class BaseAdapter 
     
     processType(
       objsmap,map,
-      Address.class,
-      Activity.class,
-      ArticleObject.class,
-      AudioObject.class,
-      BadgeObject.class,
-      BookmarkObject.class,
-      Collection.class,
-      CommentObject.class,
-      EventObject.class,
-      FileObject.class,
-      GroupObject.class,
-      ImageObject.class,
-      NoteObject.class,
-      PersonObject.class,
-      PlaceObject.class,
-      ProductObject.class,
-      QuestionObject.class,
-      ReviewObject.class,
-      ServiceObject.class,
-      VideoObject.class,
-      ErrorObject.class,
-      NameObject.class,
-      AccountObject.class,
-      OrganizationObject.class,
-      BookObject.class,
-      MovieObject.class,
-      OfferObject.class,
-      TvEpisodeObject.class,
-      TvSeasonObject.class,
-      TvSeriesObject.class,
-      VersionObject.class,
-      BinaryObject.class
+      Address.AddressBuilder.class,
+      Activity.ActivityBuilder.class,
+      AlertObject.AlertBuilder.class,
+      ArticleObject.Builder.class,
+      AudioObject.AudioBuilder.class,
+      BadgeObject.Builder.class,
+      BookmarkObject.BookmarkBuilder.class,
+      Collection.CollectionBuilder.class,
+      CommentObject.Builder.class,
+      EventObject.EventBuilder.class,
+      FileObject.FileBuilder.class,
+      GroupObject.Builder.class,
+      ImageObject.ImageBuilder.class,
+      NoteObject.Builder.class,
+      PersonObject.PersonBuilder.class,
+      PlaceObject.PlaceBuilder.class,
+      ProductObject.ProductBuilder.class,
+      QuestionObject.QuestionBuilder.class,
+      ReviewObject.Builder.class,
+      ServiceObject.Builder.class,
+      VideoObject.VideoBuilder.class,
+      ErrorObject.Builder.class,
+      NameObject.NameBuilder.class,
+      AccountObject.AccountBuilder.class,
+      OrganizationObject.OrganizationBuilder.class,
+      BookObject.BookBuilder.class,
+      MovieObject.MovieBuilder.class,
+      OfferObject.OfferBuilder.class,
+      TvEpisodeObject.TvEpisodeBuilder.class,
+      TvSeasonObject.TvSeasonBuilder.class,
+      TvSeriesObject.TvSeriesBuilder.class,
+      VersionObject.VersionBuilder.class,
+      BinaryObject.BinaryBuilder.class
     );
   }
   
-  private static void processType(
-    Map<String,Class<? extends ASObject>> map, 
+  private static <X extends ASObject.Builder>void processType(
+    Map<String,Class<? extends ASObject.Builder>> map, 
     Map<String,Class<?>> propsmap,
-    Class<? extends ASObject>... _classes) {
-    for (Class<? extends ASObject> _class : _classes) {
+    Class<? extends X>... _classes) {
+    for (Class<? extends X> _class : _classes) {
       String name = AnnoUtil.getName(_class);
       map.put(name, _class);
       if (_class.isAnnotationPresent(Properties.class)) {
@@ -185,7 +188,7 @@ public class BaseAdapter 
     }
   }
   
-  public void addObjectMap(Class<? extends ASObject>... _class) {
+  public <X extends ASObject.Builder> void addObjectMap(Class<? extends X>... _class) {
     processType(objsmap,map,_class);
   }
   
@@ -221,74 +224,79 @@ public class BaseAdapter 
     JsonDeserializationContext context) 
       throws JsonParseException {
     JsonObject obj = (JsonObject)el;
-    ASBase base = null;
+    ASBase.Builder<?,?> builder;
     if (type == Collection.class)
-      base = new Collection<ASObject>();
+      builder = Collection.makeCollection();
     else if (type == Activity.class)
-      base = new Activity();
+      builder = Activity.makeActivity();
     else if (type == MediaLink.class)
-      base = new MediaLink();
+      builder = MediaLink.makeMediaLink();
     else if (type == PlaceObject.class)
-      base = new PlaceObject();
+      builder = PlaceObject.makePlace();
     else if (type == Mood.class)
-      base = new Mood();
+      builder = Mood.makeMood();
     else if (type == Address.class)
-      base = new Address();
+      builder = Address.makeAddress();
     else {
       JsonPrimitive ot = obj.getAsJsonPrimitive("objectType");
       if (ot != null) {
         String ots = ot.getAsString();
-        Class<? extends ASObject> _class = objsmap.get(ots);
+        Class<? extends ASObject.Builder> _class = objsmap.get(ots);
         if (_class != null) {
-          base = Discover.locate(_class, _class.getName());
+          builder = Discover.locate(_class, _class.getName());
           try {
-            base = _class.newInstance();
+            builder = _class.getConstructor(String.class).newInstance(ots);
           } catch (Throwable t) {}
           
-        } else base = new ASObject(ots);
+        } else builder = ASObject.makeObject(ots);
       } else {
         if (obj.has("verb") && (obj.has("actor") || obj.has("object") || obj.has("target"))) {
-          base = new Activity();
+          builder = Activity.makeActivity();
         } else if (obj.has("items")) {
-          base = new Collection<ASObject>();
+          builder = Collection.makeCollection();
         } else {
-          base = new ASObject(); // anonymous object
+          builder = ASObject.makeObject(); // anonymous
         }
       }
     }
     for (Entry<String,JsonElement> entry : obj.entrySet()) {
       String name = entry.getKey();
+      if (name.equalsIgnoreCase("objectType")) continue;
       Class<?> _class = map.get(name);
       JsonElement val = entry.getValue();
       if (val.isJsonPrimitive()) {
         if (_class != null) {
-          base.setProperty(name, context.deserialize(val,_class));
+          builder.set(name, context.deserialize(val,_class));
         } else {
           JsonPrimitive prim = val.getAsJsonPrimitive();
           if (prim.isBoolean()) 
-            base.setProperty(name, prim.getAsBoolean());
+            builder.set(name, prim.getAsBoolean());
           else if (prim.isNumber())
-            base.setProperty(name, prim.getAsNumber());
+            builder.set(name, prim.getAsNumber());
           else {
-            base.setProperty(name, prim.getAsString());
+            builder.set(name, prim.getAsString());
           }
         }
       } else if (val.isJsonArray()) {
-        List<Object> list = new ArrayList<Object>();
+        ImmutableList.Builder<Object> list = ImmutableList.builder();
         JsonArray arr = val.getAsJsonArray();
         processArray(arr, _class, context, list);
-        base.setProperty(name, list);
+        builder.set(name, list.build());
       } else if (val.isJsonObject()) {
         if (map.containsKey(name)) {
-          base.setProperty(name, context.deserialize(val, map.get(name)));
+          builder.set(name, context.deserialize(val, map.get(name)));
         } else
-          base.setProperty(name, context.deserialize(val, ASObject.class));
+          builder.set(name, context.deserialize(val, ASObject.class));
       }
     }
-    return base;
+    return builder.get();
   }
 
-  private void processArray(JsonArray arr, Class<?> _class, JsonDeserializationContext context, List<Object> list) {
+  private void processArray(
+    JsonArray arr, 
+    Class<?> _class, 
+    JsonDeserializationContext context, 
+    ImmutableList.Builder<Object> list) {
     for (JsonElement mem : arr) {
       if (mem.isJsonPrimitive()) {
         if (_class != null) {
@@ -306,9 +314,9 @@ public class BaseAdapter 
         list.add(context.deserialize(mem, _class!=null?_class:ASObject.class));
       } else if (mem.isJsonArray()) {
         JsonArray array = mem.getAsJsonArray();
-        List<Object> objs = new ArrayList<Object>();
+        ImmutableList.Builder<Object> objs = ImmutableList.builder();
         processArray(array,_class,context,objs);
-        list.add(objs);
+        list.add(objs.build());
       }
     }
   }

Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/io/gson/GsonIO.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/io/gson/GsonIO.java?rev=1200583&r1=1200582&r2=1200583&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/io/gson/GsonIO.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/io/gson/GsonIO.java Thu Nov 10 21:48:45 2011
@@ -55,31 +55,35 @@ import com.google.gson.stream.JsonWriter
 
 @SuppressWarnings("unchecked")
 public class GsonIO extends IO {
-
-  private final Gson gson;
-  private final BaseAdapter asbs;
   
-  public GsonIO() {
-    this.asbs = new BaseAdapter();
-    this.gson = gson(false,(BaseAdapter)asbs);
-  }
-  
-  public GsonIO(TypeAdapter<?>... adapters) {
-    this.asbs = new BaseAdapter();
-    this.gson = gson(false,asbs, adapters);
-  }
-  
-  public GsonIO(Boolean prettyprint) {
-    this.asbs = new BaseAdapter();
-    this.gson = gson(prettyprint,(BaseAdapter)asbs);
-  }
-  
-  public GsonIO(Boolean prettyprint, TypeAdapter<?>... adapters) {
-    this.asbs = new BaseAdapter();
-    this.gson = gson(prettyprint,asbs, adapters);
+  public static class Builder extends IO.Builder {
+       
+    private final BaseAdapter asbs = new BaseAdapter();
+    
+    public IO get() {
+      return new GsonIO(
+        this,
+        asbs,
+        gson(
+          prettyprint,
+          asbs,
+          adapters.build()));
+    }
+   
+    public Builder property(String name, Class<?> _class) {
+      asbs.addPropertyMap(name, _class);
+      return this;
+    }
+
+    @SuppressWarnings({ "rawtypes" })
+    public <X extends ASObject.Builder> Builder object(
+        Class<? extends X>... _class) {
+      asbs.addObjectMap(_class);
+      return this;
+    }    
   }
   
-  private static Gson gson(Boolean pretty, BaseAdapter asbs, TypeAdapter<?>... adapters) {
+  static Gson gson(Boolean pretty, BaseAdapter asbs, Iterable<TypeAdapter<?>> adapters) {
     GsonBuilder gb = new GsonBuilder();    
     gb.registerTypeHierarchyAdapter(Verb.class, new VerbAdapter());
     gb.registerTypeHierarchyAdapter(Lang.class, new LangAdapter());
@@ -112,6 +116,13 @@ public class GsonIO extends IO {
     return gb.create();
   }
   
+  private final Gson gson;
+  
+  GsonIO(Builder builder, BaseAdapter asbs, Gson gson) {
+    super(builder);
+    this.gson = gson;
+  }
+  
   public String write(ASBase base) {
     return gson.toJson(base);
   }
@@ -159,16 +170,6 @@ public class GsonIO extends IO {
   public MediaLink readMediaLink(String json) {
     return gson.fromJson(json, MediaLink.class);
   }
-
-  @Override
-  public void addPropertyMapping(String name, Class<?> _class) {
-    asbs.addPropertyMap(name, _class);
-  }
-
-  @Override
-  public void addObjectMapping(Class<? extends ASObject>... _class) {
-    asbs.addObjectMap(_class);
-  }
   
   public void writeCollection(
     OutputStream out, 

Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASBase.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASBase.java?rev=1200583&r1=1200582&r2=1200583&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASBase.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASBase.java Thu Nov 10 21:48:45 2011
@@ -17,75 +17,141 @@
  */
 package org.apache.abdera2.activities.model;
 
-import org.joda.time.DateTime;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
-import java.io.Serializable;
 import java.io.Writer;
+import java.lang.reflect.Constructor;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
-
-import javax.activation.MimeType;
+import java.util.Map.Entry;
 
 import org.apache.abdera2.activities.extra.Extra;
-import org.apache.abdera2.activities.model.Generator.Copyable;
-import org.apache.abdera2.common.http.EntityTag;
-import org.apache.abdera2.common.iri.IRI;
 import org.apache.abdera2.common.lang.Lang;
-import org.apache.abdera2.common.mediatype.MimeTypeHelper;
-import org.apache.abdera2.common.mediatype.MimeTypeParseException;
 import org.apache.abdera2.common.misc.ExceptionHelper;
-import org.apache.abdera2.common.misc.MoreFunctions;
+import org.apache.abdera2.common.selector.Selector;
+import org.apache.abdera2.common.selector.AbstractSelector;
 
+import static org.apache.abdera2.common.misc.MoreFunctions.*;
 import static com.google.common.base.Preconditions.*;
 
 import com.google.common.base.Function;
-import com.google.common.collect.Iterators;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import static com.google.common.collect.Maps.filterEntries;
 
 /**
  * Root of the Activity Streams object hierarchy, provides the core property
  * management and can be used to represent simple, untyped objects.
  */
+@SuppressWarnings("unchecked")
 public class ASBase 
-  implements Iterable<String>, Cloneable, Serializable, Copyable {
-
-  private static final long serialVersionUID = -5432906925445653268L;
-  private final Map<String,Object> exts =
-    new HashMap<String,Object>();
+  implements Iterable<String>, Cloneable {
   
-  public ASBase() {}
+  public static ASBuilder make() {
+    return new ASBuilder();
+  }
   
-  protected <T>Iterable<T> checkEmpty(Iterable<T> i) {
-    return i == null ?
-      Collections.<T>emptySet() : i;
+  public static class ASBuilder extends Builder<ASBase,ASBuilder> {
+    public ASBuilder() {
+      super(ASBase.class,ASBuilder.class);
+    }
+    protected ASBuilder(Map<String,Object> map) {
+      super(map,ASBase.class,ASBuilder.class);
+    }    
+  }
+  
+  public static <X extends ASBase, M extends Builder<X,M>>Function<Object[],M> createBuilder(
+      final Class<M> _m) {
+      return new Function<Object[],M>() {
+        public M apply(Object[] input) {
+          try {
+            if (input != null) {
+              Constructor<M> c = _m.getConstructor(Map.class);
+              c.setAccessible(true);
+              return c.newInstance(input);
+            } else {
+              return _m.newInstance();
+            }
+          } catch (Throwable t) {
+            throw ExceptionHelper.propogate(t);
+          }
+        }
+      };
+    }
+  
+  public static abstract class Builder<X extends ASBase, M extends Builder<X,M>>
+    implements Supplier<X> {
+
+    protected final ImmutableMap.Builder<String,Object> map = 
+      ImmutableMap.builder();
+    private final Function<Object[],X> con;
+    private final Function<Object[],M> bld;
+    
+    protected Builder(Class<X> _class, Class<M> _builder) {
+      con = createInstance(_class, Map.class);
+      bld = createBuilder(_builder);
+    }
+        
+    protected Builder(Map<String,Object> map,Class<X> _class, Class<M> _builder) {
+      this(_class,_builder);
+      this.map.putAll(map);
+    }
+    public M set(String name, Object val) {
+      if (val != null)
+        map.put(name,val);
+      return (M)this;
+    }
+    public M lang(String lang) {
+      return lang(new Lang(lang));
+    }
+    public M lang(Lang lang) {
+      set("lang",lang);
+      return (M)this;
+    }
+    protected void preGet() {}
+    public X get() {
+      preGet();
+      return con.apply(array(map.build()));
+    }
+    public <N>N extend(Class<N> as) {
+      checkArgument(as.isInterface(),"Extension is not an interface!");
+      return Extra.extendBuilder(this,as);
+    }
+    public M template() {
+      return bld.apply(array(map.build()));
+    }
   }
+
+  protected final Map<String,Object> exts;
+  private final Function<Object[],?> builder;
   
-  /**
-   * Set the value of the "lang" property. This optionally establishes
-   * a language context for the other properties in this object. It 
-   * is not inherited by contained objects.
-   */
-  public void setLang(Lang lang) {
-    setProperty("lang", lang);
+  public ASBase(Map<String,Object> map) {
+    this.exts = map;
+    this.builder = createBuilder(ASBuilder.class);
+  }
+  
+  protected <X extends ASBase, M extends Builder<X,M>>ASBase(Map<String,Object> map, Class<M> _class, Class<X> _obj) {
+    this.exts = ImmutableMap.copyOf(map);
+    this.builder = createBuilder(_class);
   }
   
-  /**
-   * Gets value of the "lang" property. 
-   */
   public Lang getLang() {
     return getProperty("lang");
   }
   
-  /**
-   * Return the value of the named property
-   */
-  @SuppressWarnings("unchecked")
   public <T>T getProperty(String name) {
     return (T)exts.get(name);
   }
   
+  protected int getPropertyInt(String name) {
+    Object obj = exts.get(name);
+    if (obj instanceof Integer)
+      return (Integer)obj;
+    else return Integer.parseInt(obj.toString());
+  }
+  
   /**
    * Return the value of the named property, using the specified
    * Transform Function to translate the properties value
@@ -95,25 +161,95 @@ public class ASBase 
   }
   
   /**
-   * Set the value of the named property
-   */
-  public void setProperty(String name, Object value) {
-    if (value != null)
-      exts.put(name, value);
-    else if (exts.containsKey(name))
-      exts.remove(name);
-  }
-
-  /**
    * Return a listing of all the properties in this object
    */
   public Iterator<String> iterator() {
-    return Iterators.<String>unmodifiableIterator(exts.keySet().iterator());
+    return exts.keySet().iterator();
+  }
+  
+  public <X extends ASBase, M extends Builder<X,M>>M template() {
+    return (M)builder.apply(array(exts));
+  }
+  
+  public <X extends ASBase, M extends Builder<X,M>>M template(Selector<Map.Entry<String,Object>> predicate) {
+    return (M)builder.apply(array(filterEntries(exts, predicate)));
+  }
+  
+  public <X extends ASBase, M extends Builder<X,M>>M templateWith(ASBase other) {
+    M builder = this.<X,M>template(withoutFields(other));
+    for (String field : other)
+      builder.set(field,other.getProperty(field));
+    return builder;
   }
+  
+  public <X extends ASBase, M extends Builder<X,M>>M templateWith(Map<String,Object> other) {
+    ImmutableMap<String,Object> copy = 
+      other instanceof ImmutableMap ? 
+        (ImmutableMap<String,Object>)other : 
+        ImmutableMap.copyOf(other);
+    M builder = this.<X,M>template(withoutFields(copy.keySet()));
+    for (Map.Entry<String,Object> entry : copy.entrySet())
+      builder.set(entry.getKey(),entry.getValue());
+    return builder;
+  }
+  
+  public static final Selector<Map.Entry<String, Object>> withAllFields = 
+    new AbstractSelector<Map.Entry<String, Object>>(){
+      public boolean select(Object item) {
+        return true;
+      } 
+  };
+  
+  public static final Selector<Map.Entry<String, Object>> withNoFields = 
+    new AbstractSelector<Map.Entry<String, Object>>(){
+      public boolean select(Object item) {
+        return false;
+      } 
+  };
 
+  public static Selector<Map.Entry<String, Object>> withFields(Iterable<String> names) {
+    final ImmutableSet<String> list = ImmutableSet.copyOf(names);
+    return new AbstractSelector<Map.Entry<String, Object>>() {
+      public boolean select(Object item) {
+        Map.Entry<String,Object> entry = (Entry<String, Object>) item;
+        return list.contains(entry.getKey());
+      }
+    };
+  }
+  
+  public static Selector<Map.Entry<String, Object>> withFields(String... names) {
+    final ImmutableSet<String> list = ImmutableSet.copyOf(names);
+    return new AbstractSelector<Map.Entry<String, Object>>() {
+      public boolean select(Object item) {
+        Map.Entry<String,Object> entry = (Entry<String, Object>) item;
+        return list.contains(entry.getKey());
+      }
+    };
+  }
+  
+  public static Selector<Map.Entry<String, Object>> withoutFields(Iterable<String> names) {
+    final ImmutableSet<String> list = ImmutableSet.copyOf(names);
+    return new AbstractSelector<Map.Entry<String, Object>>() {
+      public boolean select(Object item) {
+        Map.Entry<String,Object> entry = (Entry<String, Object>) item;
+        return !list.contains(entry.getKey());
+      }
+    };
+  }
+  
+  public static Selector<Map.Entry<String, Object>> withoutFields(String... names) {
+    final ImmutableSet<String> list = ImmutableSet.copyOf(names);
+    return new AbstractSelector<Map.Entry<String, Object>>() {
+      public boolean select(Object item) {
+        Map.Entry<String,Object> entry = (Entry<String, Object>) item;
+        return !list.contains(entry.getKey());
+      }
+    };
+  }
+  
   @Override
   public int hashCode() {
-    return MoreFunctions.genHashCode(1,exts);
+    return genHashCode(1,exts);
   }
 
   @Override
@@ -142,34 +278,64 @@ public class ASBase 
     try {
       if (type.isAssignableFrom(this.getClass()))
         return type.cast(this);
-      ASBase t = type.newInstance();
-      t.exts.putAll(exts);
-      t.contentType = contentType;
-      t.lastModified = lastModified;
-      t.entityTag = entityTag;
-      t.language = language;
-      t.slug = slug;
-      t.base = base;      
-      return type.cast(t);
+      return createInstance(type,Map.class).apply(array(exts));
     } catch (Throwable t) {
       throw ExceptionHelper.propogate(t);
     }
   }
   
+  /** 
+   * if we already implement the type, just return 
+   * a cast to that type... otherwise, create a 
+   * new instance and copy all the properties over 
+   **/
+  public <T extends ASBase>T as(Class<T> type,Selector<Map.Entry<String, Object>> filter) {
+    try {
+      return createInstance(type,Map.class).apply(array(filterEntries(exts,filter)));
+    } catch (Throwable t) {
+      throw ExceptionHelper.propogate(t);
+    }
+  }
+  
+  @SuppressWarnings("rawtypes")
+  public <T extends ASBase>T as(Class<T> type, ASBase other) {
+    Builder builder = 
+      as(type,withoutFields(other))
+        .template();
+    for (String field : other)
+        builder.set(field,other.getProperty(field));
+    return (T)builder.get();
+  }
+  
+  @SuppressWarnings("rawtypes")
+  public <T extends ASBase>T as(Class<T> type, Map<String,Object> other) {
+    ImmutableMap<String,Object> copy = 
+      other instanceof ImmutableMap ?
+        (ImmutableMap<String,Object>)other :
+        ImmutableMap.copyOf(other);
+    Builder builder = as(type,withoutFields(copy.keySet()))
+      .template();
+    for (Entry<String,Object> entry : copy.entrySet())
+      builder.set(entry.getKey(),entry.getValue());
+    return (T)builder.get();
+  }
+  
   /**
    * Returns this object wrapped with the specified interface.
    * The argument MUST be an interface. This is used as a means
    * of extending the object in a type-safe manner. Instead of 
-   * calling setProperty("foo","bar"), you can define an 
-   * extension interface with the methods setFoo(String m) and 
-   * getFoo().. so that obj.extend(MyExt.class).setFoo("bar") 
-   * will set the "foo" property.
+   * calling getProperty("foo"), you can define an 
+   * extension interface with the methods getFoo()
    */
   public <T>T extend(Class<T> as) {
     checkArgument(as.isInterface(),"Extension is not an interface!");
     return Extra.extend(this,as);
   }
  
+  public boolean has(String name) {
+    return exts.containsKey(name);
+  }
+  
   public String toString() {
     return IO.get().write(this);
   }
@@ -219,112 +385,15 @@ public class ASBase 
   public void writeTo(OutputStream out, TypeAdapter<?>... adapters) {
     writeTo(out,"UTF-8",adapters);
   }
-  
-  /////// DOCUMENT PROPERTIES ///////
-  
-  private MimeType contentType;
-  private DateTime lastModified;
-  private EntityTag entityTag;
-  private Lang language;
-  private String slug;
-  private IRI base;
-  
-  public MimeType getContentType() {
-    return contentType;
-  }
-  
-  public void setContentType(String mimeType) {
-    this.contentType = MimeTypeHelper.unmodifiableMimeType(mimeType);
-  }
-  
-  public void setContentType(MimeType mimeType) {
-    this.contentType = MimeTypeHelper.unmodifiableMimeType(mimeType);
-  }
-  
-  public DateTime getLastModified() {
-    return lastModified;
-  }
-  
-  public void setLastModified(DateTime lastModified) {
-    this.lastModified = lastModified;
-  }
-  
-  public EntityTag getEntityTag() {
-    return entityTag;
-  }
-  
-  public void setEntityTag(EntityTag entityTag) {
-    this.entityTag = entityTag;
-  }
-  
-  public void setEntityTag(String entityTag) {
-    this.entityTag = new EntityTag(entityTag);
-  }
-  
-  public Lang getLanguage() {
-    return language;
-  }
-  
-  public void setLanguage(Lang language) {
-    this.language = language;
-  }
-  
-  public void setLanguage(String language) {
-    this.language = new Lang(language);
-  }
-  
-  public String getSlug() {
-    return slug;
-  }
-  
-  public void setSlug(String slug) {
-    this.slug = slug;
-  }
-  
-  public IRI getBaseUri() {
-    return base;
-  }
-  
-  public void setBaseUri(IRI iri) {
-    this.base = iri;
-  }
-  
-  public void setBaseUri(String iri) {
-    this.base = new IRI(iri);
-  }
-  
-  @SuppressWarnings({ "rawtypes", "unchecked" })
-  public <T extends ASObject>Generator<T> newGenerator() {
-    return (Generator<T>)new Generator(getClass(),this);
-  }
-
-  public Object copy() {
-    try {
-      Class<?> _class = this.getClass();
-      ASBase copy = (ASBase) _class.newInstance();
-      for (String name : this) {
-        // do a potentially deep copy
-        Object val = getProperty(name);
-        copy.setProperty(
-          name,
-          val instanceof Copyable ? 
-            ((Copyable)val).copy() : 
-            val);
-      }
-      copy.contentType = contentType;
-      copy.lastModified = lastModified;
-      copy.entityTag = entityTag;
-      copy.language = language;
-      copy.slug = slug;
-      copy.base = base;
-      return copy;
-    } catch (Throwable t) {
-      throw new RuntimeException();
-    }
+      
+  protected static <T>Iterable<T> checkEmpty(Iterable<T> i) {
+    return i == null ?
+      Collections.<T>emptySet() : i;
   }
   
-  public boolean has(String name) {
-    return exts.containsKey(name);
+  @SuppressWarnings("rawtypes")
+  public Object clone() throws CloneNotSupportedException {
+    return this.<ASBase,Builder>template().get();
   }
 }
 

Added: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASDocument.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASDocument.java?rev=1200583&view=auto
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASDocument.java (added)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASDocument.java Thu Nov 10 21:48:45 2011
@@ -0,0 +1,153 @@
+package org.apache.abdera2.activities.model;
+
+import java.util.Locale;
+
+import javax.activation.MimeType;
+
+import org.apache.abdera2.common.http.EntityTag;
+import org.apache.abdera2.common.iri.IRI;
+import org.apache.abdera2.common.lang.Lang;
+import org.apache.abdera2.common.mediatype.MimeTypeHelper;
+import org.joda.time.DateTime;
+
+import com.google.common.base.Supplier;
+
+public final class ASDocument<T extends ASBase> {
+
+  private final T root;
+  private final MimeType contentType;
+  private final DateTime lastModified;
+  private final EntityTag entityTag;
+  private final Lang language;
+  private final String slug;
+  private final IRI base;
+  
+  @SuppressWarnings("synthetic-access")
+  ASDocument(Builder<T> builder) {
+    this.root = builder.root;
+    this.contentType = builder.contentType;
+    this.lastModified = builder.lastModified;
+    this.entityTag = builder.entityTag;
+    this.language = builder.language;
+    this.slug = builder.slug;
+    this.base = builder.base;
+  }
+  
+  public T getRoot() {
+    return root;
+  }
+  
+  public MimeType getContentType() {
+    return contentType;
+  }
+  
+  public DateTime getLastModified() {
+    return lastModified;
+  }
+  
+  public EntityTag getEntityTag() {
+    return entityTag;
+  }
+  
+  public Lang getLanguage() {
+    return language;
+  }
+  
+  public String getSlug() {
+    return slug;
+  }
+  
+  public IRI getBaseUri() {
+    return base;
+  }
+  
+  public static <T extends ASBase>Builder<T> make() {
+    return new Builder<T>();
+  }
+  
+  public static <T extends ASBase>Builder<T> make(T root) {
+    return new Builder<T>(root);
+  }
+  
+  public static class Builder<T extends ASBase> 
+    implements Supplier<ASDocument<T>> {
+
+    private T root;
+    private MimeType contentType;
+    private DateTime lastModified;
+    private EntityTag entityTag;
+    private Lang language;
+    private String slug;
+    private IRI base;
+    
+    public Builder() {}
+    
+    public Builder(T root) {
+      this.root = root;
+    }
+    
+    public Builder<T> root(T root) {
+      this.root = root;
+      return this;
+    }
+    
+    public Builder<T> contentType(String mt) {
+      this.contentType = MimeTypeHelper.unmodifiableMimeType(mt);
+      return this;
+    }
+    
+    public Builder<T> contentType(MimeType mt) {
+      this.contentType = MimeTypeHelper.unmodifiableMimeType(mt);
+      return this;
+    }
+    
+    public Builder<T> lastModified(DateTime dt) {
+      this.lastModified = dt;
+      return this;
+    }
+    
+    public Builder<T> entityTag(String etag) {
+      this.entityTag = EntityTag.parse(etag);
+      return this;
+    }
+    
+    public Builder<T> entityTag(EntityTag etag) {
+      this.entityTag = etag;
+      return this;
+    }
+    
+    public Builder<T> language(String lang) {
+      this.language = Lang.parse(lang);
+      return this;
+    }
+    
+    public Builder<T> language(Lang lang) {
+      this.language = lang;
+      return this;
+    }
+    
+    public Builder<T> language(Locale locale) {
+      this.language = new Lang(locale);
+      return this;
+    }
+    
+    public Builder<T> slug(String slug) {
+      this.slug = slug;
+      return this;
+    }
+    
+    public Builder<T> base(String iri) {
+      this.base =new IRI(iri);
+      return this;
+    }
+    
+    public Builder<T> base(IRI iri) {
+      this.base = iri;
+      return this;
+    }
+    
+    public ASDocument<T> get() {
+      return new ASDocument<T>(this);
+    }
+  }
+}

Propchange: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASDocument.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message