You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@abdera.apache.org by jm...@apache.org on 2011/11/04 23:42:12 UTC
svn commit: r1197810 - in /abdera/abdera2:
activities/src/main/java/org/apache/abdera2/activities/extra/
activities/src/main/java/org/apache/abdera2/activities/model/
activities/src/main/java/org/apache/abdera2/activities/model/objects/
common/src/main...
Author: jmsnell
Date: Fri Nov 4 22:42:11 2011
New Revision: 1197810
URL: http://svn.apache.org/viewvc?rev=1197810&view=rev
Log: (empty)
Added:
abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/EmbeddedExperience.java (contents, props changed)
- copied, changed from r1187164, abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/EmbeddedExperience.java
abdera/abdera2/common/src/main/java/org/apache/abdera2/common/misc/MapRed.java (with props)
abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/MapRedExample.java (with props)
Removed:
abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/EmbeddedExperience.java
Modified:
abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/extra/Extra.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/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/IO.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/MiscellaneousExamples.java
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=1197810&r1=1197809&r2=1197810&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 Fri Nov 4 22:42:11 2011
@@ -2,6 +2,7 @@ package org.apache.abdera2.activities.ex
import java.lang.reflect.Method;
import java.util.Comparator;
+import java.util.Set;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
@@ -571,9 +572,17 @@ public class Extra {
public static final Equivalence<ASObject> IDENTITY_EQUIVALENCE = identity();
/**
+ * Equivalence instance that can be used to check the equivalence of two
+ * ASObjects
+ */
+ public static final Equivalence<ASObject> IDENTITY_WITH_DUPLICATES_EQUIVALENCE = identityWithDuplicates();
+
+ /**
* Two ASObject's are considered equivalent in identity if
* they share the same objectType and id property
- * values.
+ * values. Note: This implementation does not yet take
+ * the downstreamDuplicates and upstreamDuplicates properties
+ * into account when determining equivalence.
*/
private static Equivalence<ASObject> identity() {
return new Equivalence<ASObject>() {
@@ -587,9 +596,16 @@ public class Extra {
if (!aot.equalsIgnoreCase(bot)) return false;
String aid = a.getId();
String bid = b.getId();
- if (bothAreNull(aid,bid)) return true;
if (onlyOneIsNull(aid,bid)) return false;
- if (!aid.equals(bid)) return false;
+ if (neitherIsNull(aid,bid)) {
+ if (aid.equals(bid)) return true;
+ else return false;
+ }
+ String adn = a.getDisplayName();
+ String bdn = b.getDisplayName();
+ if (bothAreNull(adn,bdn)) return true;
+ if (onlyOneIsNull(adn,bdn)) return false;
+ if (!adn.equals(bdn)) return false;
return true;
}
protected int doHash(ASObject t) {
@@ -605,6 +621,33 @@ public class Extra {
};
}
+ private static Equivalence<ASObject> identityWithDuplicates() {
+ return new Equivalence<ASObject>() {
+ protected boolean doEquivalent(ASObject a, ASObject b) {
+ if (IDENTITY_EQUIVALENCE.equivalent(a, b))
+ return true;
+ Iterable<String> aids = a.getKnownIds();
+ Iterable<String> bids = b.getKnownIds();
+ Iterable<String> cids =
+ Iterables.filter(
+ aids, Predicates.in((Set<String>)bids));
+ // if cids is empty, it's not a duplicate, so return false
+ // if cids isn't empty, they are likely duplicates, return true
+ return !Iterables.isEmpty(cids);
+ }
+ protected int doHash(ASObject t) {
+ String id = t.getId();
+ String objectType = t.getObjectType();
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result
+ + ((objectType == null) ? 0 : objectType.hashCode());
+ return result;
+ }
+ };
+ }
+
public static final Comparator<ASObject> UPDATED_COMPARATOR =
new UpdatedComparator();
public static final Comparator<ASObject> PUBLISHED_COMPARATOR =
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=1197810&r1=1197809&r2=1197810&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 Fri Nov 4 22:42:11 2011
@@ -38,6 +38,7 @@ import org.apache.abdera2.common.mediaty
import static com.google.common.base.Preconditions.*;
import com.google.common.base.Function;
+import com.google.common.collect.Iterators;
/**
* Root of the Activity Streams object hierarchy, provides the core property
@@ -57,23 +58,41 @@ public class ASBase
Collections.<T>emptySet() : i;
}
+ /**
+ * 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);
}
+ /**
+ * 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);
}
+ /**
+ * Return the value of the named property, using the specified
+ * Transform Function to translate the properties value
+ */
public <T,R>R getProperty(String name, Function<T,R> transform) {
return (R)transform.apply(this.<T>getProperty(name));
}
+ /**
+ * Set the value of the named property
+ */
public void setProperty(String name, Object value) {
if (value != null)
exts.put(name, value);
@@ -81,8 +100,11 @@ public class ASBase
exts.remove(name);
}
+ /**
+ * Return a listing of all the properties in this object
+ */
public Iterator<String> iterator() {
- return exts.keySet().iterator();
+ return Iterators.<String>unmodifiableIterator(exts.keySet().iterator());
}
@Override
Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASObject.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASObject.java?rev=1197810&r1=1197809&r2=1197810&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASObject.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/ASObject.java Fri Nov 4 22:42:11 2011
@@ -21,10 +21,12 @@ import org.joda.time.DateTime;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.apache.abdera2.activities.extra.Extra;
+import org.apache.abdera2.activities.model.objects.EmbeddedExperience;
import org.apache.abdera2.activities.model.objects.Mood;
import org.apache.abdera2.activities.model.objects.PersonObject;
import org.apache.abdera2.activities.model.objects.PlaceObject;
@@ -32,6 +34,8 @@ import org.apache.abdera2.common.anno.An
import org.apache.abdera2.common.iri.IRI;
import org.apache.abdera2.common.selector.Selector;
+import com.google.common.collect.Iterables;
+
/**
* Base class for all Activity Streams Objects.
*/
@@ -70,28 +74,48 @@ public class ASObject extends ASBase {
setObjectType(objectType);
}
+ /**
+ * Returns the value of the "attachments" property
+ */
public Iterable<ASObject> getAttachments() {
return checkEmpty((Iterable<ASObject>)getProperty(ATTACHMENTS));
}
- public void setAttachments(Set<ASObject> attachments) {
- setProperty(ATTACHMENTS, attachments);
+ /**
+ * Sets the value of the attachments property... note... internally, the
+ * list of attachments does not allow for duplicate entries so the collection
+ * passed in is changed to a LinkedHashSet, maintaining the order of the
+ * entries but eliminating duplicates.
+ */
+ public void setAttachments(java.util.Collection<ASObject> attachments) {;
+ setProperty(ATTACHMENTS, new LinkedHashSet<ASObject>(attachments));
}
+ /**
+ * Adds an attachment to the "attachments" property.
+ */
public void addAttachment(ASObject... attachments) {
Set<ASObject> list = getProperty(ATTACHMENTS);
if (list == null) {
- list = new HashSet<ASObject>();
+ list = new LinkedHashSet<ASObject>();
setProperty(ATTACHMENTS, list);
}
for (ASObject attachment : attachments)
list.add(attachment);
}
+ /**
+ * Return the author of this object
+ */
public <E extends ASObject>E getAuthor() {
return (E)getProperty(AUTHOR);
}
+ /**
+ * Return the author of this object, if the author has not been
+ * set and create==true, creates a default PersonObject and
+ * returns that.
+ */
public <E extends ASObject>E getAuthor(boolean create) {
ASObject obj = getAuthor();
if (obj == null && create) {
@@ -101,43 +125,88 @@ public class ASObject extends ASBase {
return (E)obj;
}
+ /**
+ * Set the author of the object
+ */
public void setAuthor(ASObject author) {
setProperty(AUTHOR, author);
}
+ /**
+ * Set the author of the object
+ */
public <E extends ASObject>E setAuthor(String displayName) {
ASObject obj = getAuthor(true);
obj.setDisplayName(displayName);
return (E)obj;
}
+ /**
+ * Get the content of the object
+ */
public String getContent() {
return getProperty(CONTENT);
}
+ /**
+ * Set the content of the object
+ */
public void setContent(String content) {
setProperty(CONTENT, content);
}
+ /**
+ * Get the displayName of the object
+ */
public String getDisplayName() {
return getProperty(DISPLAYNAME);
}
+ /**
+ * Set the displayName of the object
+ */
public void setDisplayName(String displayName) {
setProperty(DISPLAYNAME, displayName);
}
+ /**
+ * Return the list of downstream duplicate ids for this object.
+ * When an object is redistributed by third parties, the value of the "id"
+ * property may change. When such changes do occur, it becomes difficult
+ * to track duplicate versions of the same object. The "downstreamDuplicates"
+ * and "upstreamDuplicates" properties on the object can be used to track
+ * modifications that occur in the "id" of the object in order to make
+ * duplication detection easier
+ */
public Iterable<String> getDownstreamDuplicates() {
return checkEmpty((Iterable<String>)getProperty(DOWNSTREAMDUPLICATES));
}
+ /**
+ * Set the list of downstream duplicate ids for this object.
+ * When an object is redistributed by third parties, the value of the "id"
+ * property may change. When such changes do occur, it becomes difficult
+ * to track duplicate versions of the same object. The "downstreamDuplicates"
+ * and "upstreamDuplicates" properties on the object can be used to track
+ * modifications that occur in the "id" of the object in order to make
+ * duplication detection easier
+ */
public void setDownstreamDuplicates(Set<String> downstreamDuplicates) {
setProperty(DOWNSTREAMDUPLICATES, downstreamDuplicates);
}
+ /**
+ * Add an entry to the list of downstream duplicate ids for this object.
+ * When an object is redistributed by third parties, the value of the "id"
+ * property may change. When such changes do occur, it becomes difficult
+ * to track duplicate versions of the same object. The "downstreamDuplicates"
+ * and "upstreamDuplicates" properties on the object can be used to track
+ * modifications that occur in the "id" of the object in order to make
+ * duplication detection easier
+ */
public void addDownstreamDuplicate(String... duplicates) {
Set<String> downstreamDuplicates = getProperty(DOWNSTREAMDUPLICATES);
if (downstreamDuplicates == null) {
@@ -148,77 +217,167 @@ public class ASObject extends ASBase {
downstreamDuplicates.add(downstreamDuplicate);
}
+ /**
+ * Get the id of this object
+ */
public String getId() {
return getProperty(ID);
}
+ /**
+ * Set the id of this object
+ */
public void setId(String id) {
setProperty(ID, id);
}
+ /**
+ * Get the "image" property
+ */
public MediaLink getImage() {
return getProperty(IMAGE);
}
+ /**
+ * Set the "image" property
+ */
public void setImage(MediaLink image) {
setProperty(IMAGE, image);
-
}
+ /**
+ * Set the "image" property
+ */
+ public void setImage(String uri) {
+ if (uri == null)
+ setImage((MediaLink)null);
+ else {
+ MediaLink link = getImage();
+ if (link == null) {
+ link = new MediaLink();
+ setProperty(IMAGE,link);
+ }
+ link.setUrl(uri);
+ }
+ }
+
+ /**
+ * Set the "image" property
+ */
+ public void setImage(IRI uri) {
+ setImage(uri != null ? uri.toString() : null);
+ }
+
+ /**
+ * Get the objectType
+ */
public String getObjectType() {
return getProperty(OBJECTTYPE);
}
+ /**
+ * Set the objectType
+ */
public void setObjectType(String objectType) {
- if (objectType != null && ASObject.class.getSimpleName().equalsIgnoreCase(objectType))
+ if (objectType != null &&
+ ASObject.class.getSimpleName().equalsIgnoreCase(objectType))
objectType = null;
setProperty(OBJECTTYPE, objectType);
-
}
+ /**
+ * Get the "published" datetime
+ */
public DateTime getPublished() {
return getProperty(PUBLISHED);
}
+ /**
+ * Set the "published" datetime
+ */
public void setPublished(DateTime published) {
setProperty(PUBLISHED, published);
}
+ /**
+ * Set the "published" property to the current date, time and default timezone
+ */
public void setPublishedNow() {
setPublished(DateTime.now());
}
+ /**
+ * Get the "summary" property
+ */
public String getSummary() {
return getProperty(SUMMARY);
}
+ /**
+ * Set the "summary" property
+ */
public void setSummary(String summary) {
setProperty(SUMMARY, summary);
-
}
+ /**
+ * Get the "updated" property
+ */
public DateTime getUpdated() {
return getProperty(UPDATED);
}
+ /**
+ * Set the "updated" property
+ */
public void setUpdated(DateTime updated) {
setProperty(UPDATED, updated);
}
+ /**
+ * Set the "updated" property to the current date,time and default timezone
+ */
public void setUpdatedNow() {
setUpdated(DateTime.now());
}
+ /**
+ * Return the list of upstream duplicate ids for this object.
+ * When an object is redistributed by third parties, the value of the "id"
+ * property may change. When such changes do occur, it becomes difficult
+ * to track duplicate versions of the same object. The "downstreamDuplicates"
+ * and "upstreamDuplicates" properties on the object can be used to track
+ * modifications that occur in the "id" of the object in order to make
+ * duplication detection easier
+ */
public Iterable<String> getUpstreamDuplicates() {
return checkEmpty((Iterable<String>)getProperty(UPSTREAMDUPLICATES));
}
+ /**
+ * Set the list of upstream duplicate ids for this object.
+ * When an object is redistributed by third parties, the value of the "id"
+ * property may change. When such changes do occur, it becomes difficult
+ * to track duplicate versions of the same object. The "downstreamDuplicates"
+ * and "upstreamDuplicates" properties on the object can be used to track
+ * modifications that occur in the "id" of the object in order to make
+ * duplication detection easier
+ */
public void setUpstreamDuplicates(Set<String> upstreamDuplicates) {
setProperty(UPSTREAMDUPLICATES, upstreamDuplicates);
}
+ /**
+ * Add to the list of upstream duplicate ids for this object.
+ * When an object is redistributed by third parties, the value of the "id"
+ * property may change. When such changes do occur, it becomes difficult
+ * to track duplicate versions of the same object. The "downstreamDuplicates"
+ * and "upstreamDuplicates" properties on the object can be used to track
+ * modifications that occur in the "id" of the object in order to make
+ * duplication detection easier
+ */
public void addUpstreamDuplicate(String... duplicates) {
Set<String> upstreamDuplicates = getProperty(UPSTREAMDUPLICATES);
if (upstreamDuplicates == null) {
@@ -229,19 +388,31 @@ public class ASObject extends ASBase {
upstreamDuplicates.add(upstreamDuplicate);
}
-
+ /**
+ * Get the url of this object
+ */
public IRI getUrl() {
return getProperty(URL);
}
+ /**
+ * Set the url of this object
+ */
public void setUrl(IRI url) {
setProperty(URL,url);
}
+ /**
+ * Get the collection of objects this object is considered a response to
+ */
public Iterable<ASObject> getInReplyTo() {
return checkEmpty((Iterable<ASObject>)getProperty(INREPLYTO));
}
+ /**
+ * Get the collection of objects this object is considered a response to
+ * using the specified selector to filter the results
+ */
public Iterable<ASObject> getInReplyTo(Selector<ASObject> selector) {
List<ASObject> list= new ArrayList<ASObject>();
for (ASObject obj : getInReplyTo())
@@ -250,57 +421,92 @@ public class ASObject extends ASBase {
return list;
}
- public void setInReplyTo(Set<ASObject> inReplyTo) {
- setProperty(INREPLYTO, inReplyTo);
+ /**
+ * Set the collection of objects this object is considered a response to.
+ * Note that duplicates are removed
+ */
+ public void setInReplyTo(java.util.Collection<ASObject> inReplyTo) {
+ setProperty(INREPLYTO, new LinkedHashSet<ASObject>(inReplyTo));
}
+ /**
+ * Add a new object this object is considered a response to
+ */
public void addInReplyTo(ASObject... inReplyTos) {
Set<ASObject> list = getProperty(INREPLYTO);
if (list == null) {
- list = new HashSet<ASObject>();
+ list = new LinkedHashSet<ASObject>();
setProperty(INREPLYTO, list);
}
for (ASObject inReplyTo : inReplyTos)
list.add(inReplyTo);
}
+ /**
+ * Get the "location" property
+ */
public PlaceObject getLocation() {
return getProperty(LOCATION);
}
+ /**
+ * Set the "location" property
+ */
public void setLocation(PlaceObject location) {
setProperty(LOCATION, location);
location.setObjectType(null);
}
+ /**
+ * Get the "mood" property
+ */
public Mood getMood() {
return getProperty(MOOD);
}
+ /**
+ * Set the "mood" property
+ */
public void setMood(Mood mood) {
setProperty(MOOD, mood);
}
+ /**
+ * Get the "source" property
+ */
public <E extends ASObject>E getSource() {
return (E)getProperty(SOURCE);
}
+ /**
+ * Set the "source" property
+ */
public void setSource(ASObject source) {
setProperty(SOURCE, source);
}
+ /**
+ * Get the collection of tags for this object
+ */
public Iterable<ASObject> getTags() {
- return getProperty(TAGS);
+ return checkEmpty((Iterable<ASObject>)getProperty(TAGS));
}
- public void setTags(Set<ASObject> tags) {
- setProperty(TAGS, tags);
+ /**
+ * Set the collection of tags for this object. Duplicates
+ * will be removed.
+ */
+ public void setTags(java.util.Collection<ASObject> tags) {
+ setProperty(TAGS, new LinkedHashSet<ASObject>(tags));
}
+ /**
+ * Add an object to the collection of tags for this object
+ */
public void addTag(ASObject... tags) {
Set<ASObject> list = getProperty(TAGS);
if (list == null) {
- list = new HashSet<ASObject>();
+ list = new LinkedHashSet<ASObject>();
setProperty(TAGS, list);
}
for (ASObject tag : tags)
@@ -323,10 +529,16 @@ public class ASObject extends ASBase {
setProperty(EMBED,embed);
}
+ /**
+ * Get the "rating" property
+ */
public double getRating() {
return (Double)getProperty(RATING);
}
+ /**
+ * Set the "rating" property
+ */
public void setRating(double rating) {
setProperty(RATING, rating);
}
@@ -424,6 +636,22 @@ public class ASObject extends ASBase {
return Extra.sameIdentity(this).apply(obj);
}
+ /**
+ * Returns a union of all known IDs for this object.. specifically,
+ * this is a union of the "id", "downstreamDuplicates" and "upstreamDuplicates"
+ * properties
+ */
+ public Iterable<String> getKnownIds() {
+ Set<String> list = new LinkedHashSet<String>();
+ if (has("id")) list.add(getId());
+ Iterables.addAll(list, checkEmpty(getDownstreamDuplicates()));
+ Iterables.addAll(list, checkEmpty(getUpstreamDuplicates()));
+ return list;
+ }
+
+ /**
+ * Begins creating a new object using the fluent factory api
+ */
public static <X extends ASObjectGenerator<T>,T extends ASObject>X make() {
return (X)new ASObjectGenerator<T>();
}
Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/Activity.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/Activity.java?rev=1197810&r1=1197809&r2=1197810&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/Activity.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/Activity.java Fri Nov 4 22:42:11 2011
@@ -57,8 +57,18 @@ public class Activity extends ASObject {
public static final String URL = "url";
public static final String VERB = "verb";
+ /**
+ * Used to specify the target audience for an Activity.
+ */
public enum Audience {
- TO, BTO, CC, BCC;
+ /** Identifies the public primary target audience of the Activity **/
+ TO,
+ /** Identifies the private primary target audience of the Activity **/
+ BTO,
+ /** Identifies the public secondary target audience of the Activity **/
+ CC,
+ /** Identifies the private secondary target audience of the Activity **/
+ BCC;
String label() {
return name().toLowerCase();
}
@@ -97,6 +107,12 @@ public class Activity extends ASObject {
return getProperty(ACTOR);
}
+ /**
+ * Returns the Actor Object... if an actor object
+ * does not yet exist and create==true, a default
+ * PersonObject will be created and set as the
+ * object and returned.
+ */
public <E extends ASObject>E getActor(boolean create) {
ASObject obj = getActor();
if (obj == null && create) {
@@ -106,28 +122,54 @@ public class Activity extends ASObject {
return (E)obj;
}
+ /**
+ * Set the Actor for this Activity.
+ */
public void setActor(ASObject actor) {
setProperty(ACTOR, actor);
}
+ /**
+ * Set the Actor's displayName for this activity.
+ * If the Actor has not yet been set, a default
+ * PersonObject will be created with the specified
+ * displayName. If the Actor object has already
+ * been set, this will change the displayName to
+ * that specified.
+ */
public <E extends ASObject>E setActor(String displayName) {
ASObject obj = getActor(true);
obj.setDisplayName(displayName);
return (E)obj;
}
+ /**
+ * Return the value of the "content" property for this activity
+ */
public String getContent() {
return getProperty(CONTENT);
}
+ /**
+ * Set the value of the "content" property for this activity
+ */
public void setContent(String content) {
setProperty(CONTENT, content);
}
+ /**
+ * Return the ASObject value of the "generator" property for this
+ * activity.
+ */
public <E extends ASObject>E getGenerator() {
return (E)getProperty(GENERATOR);
}
+ /**
+ * Return the ASObject value for the "generator" property for this
+ * activity. If the generator has not yet been set and create==true,
+ * a default ServiceObject will be created, set and returned.
+ */
public <E extends ASObject>E getGenerator(boolean create) {
ASObject obj = getGenerator();
if (obj == null && create) {
@@ -137,56 +179,134 @@ public class Activity extends ASObject {
return (E)obj;
}
+ /**
+ * Set the value of the "generator" property for this Activity
+ */
public void setGenerator(ASObject generator) {
setProperty(GENERATOR, generator);
}
+ /**
+ * Set the value of the "generator" properties displayName.
+ * If the generator has not yet been set, a default ServiceObject
+ * will be created, set and returned. Otherwise, the displayName
+ * of the existing object will be changed to that specified.
+ */
public <E extends ASObject>E setGenerator(String displayName) {
ASObject obj = getGenerator(true);
obj.setDisplayName(displayName);
return (E)obj;
}
+ /**
+ * Return the value of the "icon" property
+ */
public MediaLink getIcon() {
return getProperty(ICON);
}
+ /**
+ * Set the value of the "icon" property
+ */
public void setIcon(MediaLink icon) {
setProperty(ICON, icon);
}
+ /**
+ * Set the value of the "icon" property. If the
+ * property has not yet been set, the MediaLink
+ * will be created.
+ */
+ public void setIcon(String uri) {
+ if (uri == null)
+ setProperty(ICON,null);
+ else {
+ MediaLink link = getIcon();
+ if (link == null) {
+ link = new MediaLink();
+ setIcon(link);
+ }
+ link.setUrl(uri);
+ }
+ }
+
+ /**
+ * Set the value of the "icon" property. If the
+ * property has not yet been set, the MediaLink
+ * will be created.
+ */
+ public void setIcon(IRI uri) {
+ setIcon(uri != null ? uri.toString() : null);
+ }
+
+ /**
+ * Get the value of the "id" property
+ */
public String getId() {
return getProperty(ID);
}
+ /**
+ * Set the value of the "id" property
+ */
public void setId(String id) {
setProperty(ID, id);
}
+ /**
+ * set the value of the "id" property
+ */
+ public void setId(IRI id) {
+ setId(id != null ? id.toString() : null);
+ }
+
+ /**
+ * Get the Activities Object property
+ */
public <E extends ASObject>E getObject() {
return (E)getProperty(OBJECT);
}
+ /**
+ * Set the Activities Object property
+ */
public void setObject(ASObject object) {
setProperty(OBJECT, object);
}
+ /**
+ * Get the value of the Activities "published" property
+ */
public DateTime getPublished() {
return getProperty(PUBLISHED);
}
+ /**
+ * Set the value of the Activities "published" property
+ */
public void setPublished(DateTime published) {
setProperty(PUBLISHED, published);
}
+ /**
+ * Set the value of the Activities "published" property using the current date, time and default timezone
+ */
public void setPublishedNow() {
setPublished(DateTime.now());
}
+ /**
+ * Get the value of the Activities "provider" property
+ */
public <E extends ASObject>E getProvider() {
return (E)getProperty(PROVIDER);
}
+ /**
+ * Set the value of the Activities "provider" property.
+ * If the value has not yet been set, a default ServiceObject
+ * will be created, set and returned
+ */
public <E extends ASObject>E getProvider(boolean create) {
ASObject obj = getProvider();
if (obj == null && create) {
@@ -196,104 +316,207 @@ public class Activity extends ASObject {
return (E)obj;
}
+ /**
+ * Set the value of the Activities "provider" property
+ */
public void setProvider(ASObject provider) {
setProperty(PROVIDER, provider);
}
+ /**
+ * Set the displayName of the Activities "provider" property.
+ * If the object has not yet been created, a default
+ * ServiceObject will be created, otherwise the displayName
+ * will be changed to the provided value
+ */
public <E extends ASObject>E setProvider(String displayName) {
ASObject obj = getProvider(true);
obj.setDisplayName(displayName);
return (E)obj;
}
+ /**
+ * Get the value of Activities "target" property
+ */
public <E extends ASObject>E getTarget() {
return (E)getProperty(TARGET);
}
+ /**
+ * Set the value of the Activities "target" property
+ */
public void setTarget(ASObject target) {
setProperty(TARGET, target);
-
}
+ /**
+ * Get the value of the "title" property
+ */
public String getTitle() {
return getProperty(TITLE);
}
+ /**
+ * Set the value of the "title" property
+ */
public void setTitle(String title) {
setProperty(TITLE, title);
}
+ /**
+ * Get the value of the "updated" property
+ */
public DateTime getUpdated() {
return getProperty(UPDATED);
}
+ /**
+ * Set the value of the "updated" property
+ */
public void setUpdated(DateTime updated) {
setProperty(UPDATED, updated);
}
+ /**
+ * Set the value of the "updated" property to the current date, time and default timezone
+ */
public void setUpdatedNow() {
setUpdated(DateTime.now());
}
+ /**
+ * Get the value of the "url" property
+ */
public IRI getUrl() {
return getProperty(URL);
}
+ /**
+ * Set the value of the "url" property
+ */
public void setUrl(IRI url) {
setProperty(URL, url);
}
+ /**
+ * Get the value of the "verb" property
+ */
public Verb getVerb() {
return getProperty(VERB);
}
+ /**
+ * Set the value of the "verb" property
+ */
public void setVerb(Verb verb) {
setProperty(VERB, verb);
}
+
+ /**
+ * Set the value of the "verb" property
+ */
+ public void setVerb(String verb) {
+ setVerb(verb != null ? Verb.get(verb) : null);
+ }
- @Override
+ /**
+ * Get the value of the "author" property.. for Activity
+ * objects, the "author" property is mapped to the "actor"
+ * property in order to avoid duplication of content.
+ * If you want to get the actual "author" property, use
+ * getProperty("author")...
+ */
public <E extends ASObject>E getAuthor() {
return (E)getActor();
}
+ /**
+ * Set the value of the "author" property.. for Activity
+ * objects, the "author" property is mapped to the "actor"
+ * property in orde to avoid duplication of content.
+ * If you want to set the actual "author" property, use
+ * setProperty("author",val)
+ */
public <E extends ASObject>E getAuthor(boolean create) {
return (E)getActor(create);
}
- @Override
+ /**
+ * Set the value of the "author" property.. for Activity
+ * objects, the "author" property is mapped to the "actor"
+ * property in orde to avoid duplication of content.
+ * If you want to set the actual "author" property, use
+ * setProperty("author",val)
+ */
public void setAuthor(ASObject author) {
setActor(author);
}
+ /**
+ * Set the value of the "author" property.. for Activity
+ * objects, the "author" property is mapped to the "actor"
+ * property in order to avoid duplication of content.
+ * If you want to set the actual "author" property, use
+ * setProperty("author",val)
+ */
public <E extends ASObject>E setAuthor(String displayName) {
return (E)setActor(displayName);
}
- @Override
+ /**
+ * Get the "displayName" property. For Activity objects, the
+ * "displayName" property is mapped to the "title" property.
+ * If you want to get the actual "displayName" property,
+ * us getProperty("displayName")
+ */
public String getDisplayName() {
return getTitle();
}
- @Override
+ /**
+ * Set the "displayName" property. For Activity objects, the
+ * "displayName" property is mapped to the "title" property.
+ * If you want to set the actual "displayName" property,
+ * us setProperty("displayName",val)
+ */
public void setDisplayName(String displayName) {
setTitle(displayName);
}
- @Override
+ /**
+ * Get the "image" property. For Activity objects, the
+ * "image" property is mapped to the "icon" property.
+ * If you want to get the actual "image" property,
+ * us getProperty("image")
+ */
public MediaLink getImage() {
return getIcon();
}
- @Override
+ /**
+ * Set the "image" property. For Activity objects, the
+ * "image" property is mapped to the "icon" property.
+ * If you want to set the actual "image" property,
+ * us setProperty("image",val)
+ */
public void setImage(MediaLink image) {
setIcon(image);
}
+ /**
+ * Get the specified target audience for the activity
+ */
public Iterable<ASObject> getAudience(Audience audience) {
return checkEmpty((Iterable<ASObject>)getProperty(audience.label()));
}
+ /**
+ * Get the specified target audience for the activity using the
+ * specified selector as a filter to limit the results. This
+ * can be used, for instance, to quickly determine if a particular
+ * entity is included in the audience of the activity
+ */
public Iterable<ASObject> getAudience(Audience audience, Selector<ASObject> selector) {
List<ASObject> list = new ArrayList<ASObject>();
for (ASObject obj : getAudience(audience))
@@ -302,10 +525,18 @@ public class Activity extends ASObject {
return list;
}
+ /**
+ * Set the target audience for the activity
+ */
public void setAudience(Audience audience, Set<ASObject> set) {
setProperty(audience.label(), set);
}
+ /**
+ * Add one or more entities to the target audience of the activity.
+ * Unlike setAudience, this will not overwrite the existing audience
+ * property values.
+ */
public void addAudience(Audience audience, ASObject... objs) {
Set<ASObject> list = getProperty(audience.label());
if (list == null) {
@@ -316,6 +547,9 @@ public class Activity extends ASObject {
list.add(obj);
}
+ /**
+ * Begin creating a new Activity object using the fluent factory API
+ */
public static <T extends Activity>ActivityGenerator<T> makeActivity() {
return new ActivityGenerator<T>();
}
Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/Collection.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/Collection.java?rev=1197810&r1=1197809&r2=1197810&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/Collection.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/Collection.java Fri Nov 4 22:42:11 2011
@@ -44,32 +44,55 @@ public class Collection<T extends ASObje
public static final String ITEMS = "items";
public static final String OBJECT_TYPES = "objectTypes";
+ /**
+ * Return the value of the "totalItems" property... this does not
+ * necessarily reflect the actual number of items in the "items"
+ * iterator.
+ */
public int getTotalItems() {
return (Integer)getProperty(TOTAL_ITEMS);
}
+ /**
+ * Set the value of the "totalItems" property
+ */
public Collection<T> setTotalItems(int totalItems) {
setProperty(TOTAL_ITEMS, totalItems);
return this;
}
+ /**
+ * Get the url of this collection
+ */
public IRI getUrl() {
return getProperty(URL);
}
+ /**
+ * Set the url of this collection
+ */
public void setUrl(IRI url) {
setProperty(URL, url);
}
- @SuppressWarnings("unchecked")
+ /**
+ * Get the list of objectTypes expected to be found in this collection
+ */
public Iterable<String> getObjectTypes() {
- return checkEmpty((Iterable<String>)getProperty(OBJECT_TYPES));
+ return checkEmpty(this.<Iterable<String>>getProperty(OBJECT_TYPES));
}
- public void setObjectTypes(Set<String> types) {
- setProperty(OBJECT_TYPES,types);
+ /**
+ * Set the list of objectTypes expected to be found in this collection
+ */
+ public void setObjectTypes(java.util.Collection<String> types) {
+ setProperty(OBJECT_TYPES,new LinkedHashSet<String>(types));
}
+ /**
+ * Add a new objectType to the list of objectTypes expected to be found
+ * in this collection
+ */
public void addObjectType(String... objectTypes) {
Set<String> list = getProperty(OBJECT_TYPES);
if (list == null) {
@@ -80,6 +103,9 @@ public class Collection<T extends ASObje
list.add(objectType);
}
+ /**
+ * get the items collection using the specified selector as a filter
+ */
public Iterable<T> getItems(Selector<T> selector) {
List<T> list = new ArrayList<T>();
for (T item : getItems())
@@ -88,11 +114,19 @@ public class Collection<T extends ASObje
return list;
}
+ /**
+ * get the items contained in this collection
+ */
@SuppressWarnings("unchecked")
public Iterable<T> getItems() {
return checkEmpty((Iterable<T>)getProperty(ITEMS));
}
+ /**
+ * Get the items contained in this collection. If no "items"
+ * property exists, a new LinkedHashSet will be created, set
+ * and returned if create == true;
+ */
public Iterable<T> getItems(boolean create) {
Iterable<T> items = getItems();
if (items == null && create) {
@@ -102,17 +136,32 @@ public class Collection<T extends ASObje
return items;
}
- public void setItems(Set<T> items) {
+ /**
+ * Set the items in this collection, overwriting the existing value.
+ * setting this will change the value of the "totalItems" property
+ * to reflect the number of items passed in.
+ */
+ public void setItems(java.util.Collection<T> items) {
setProperty(ITEMS, new LinkedHashSet<T>(items));
setTotalItems(items.size());
}
+ /**
+ * Set the items in this collection, overwriting the existing value.
+ * setting this will change the value of the "totalItems" property
+ * to reflect the number of items passed in.
+ */
public void setItems(Iterable<T> items) {
Set<T> set = new LinkedHashSet<T>();
for (T item : items) set.add(item);
setItems(set);
}
+ /**
+ * Add an item to this collection
+ * setting this will change the value of the "totalItems" property
+ * to reflect the number of items passed in.
+ */
public void addItem(T... items) {
Set<T> list = getProperty(ITEMS);
if (list == null) {
@@ -124,6 +173,9 @@ public class Collection<T extends ASObje
setTotalItems(list.size());
}
+ /**
+ * Begin making a new collection object using the fluent factory api
+ */
public static <T extends ASObject>CollectionGenerator<T> makeCollection() {
return new CollectionGenerator<T>();
}
Modified: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/IO.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/IO.java?rev=1197810&r1=1197809&r2=1197810&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/IO.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/IO.java Fri Nov 4 22:42:11 2011
@@ -24,6 +24,9 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
import org.apache.abdera2.common.Discover;
import org.apache.abdera2.common.anno.AnnoUtil;
@@ -169,13 +172,51 @@ public abstract class IO {
public abstract MediaLink readMediaLink(Reader reader);
public abstract MediaLink readMediaLink(String json);
- public static IO get(TypeAdapter<?>... adapters) {
- String defaultImpl =
- AnnoUtil.getDefaultImplementation(IO.class);
- return Discover.locate(
- IO.class,
- defaultImpl,
- (Object)adapters);
+ private static class CacheKey {
+ private final int hash;
+ CacheKey(TypeAdapter<?>[] adapters) {
+ this.hash = Arrays.hashCode(adapters);
+ }
+ public int hashCode() {
+ return hash;
+ }
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ CacheKey other = (CacheKey) obj;
+ if (hash != other.hash)
+ return false;
+ return true;
+ }
+ }
+ private static final Map<CacheKey,IO> map =
+ new HashMap<CacheKey,IO>();
+
+ private static synchronized IO get_cached(TypeAdapter<?>... adapters) {
+ return map.get(new CacheKey(adapters));
+ }
+
+ private static synchronized void set_cached(IO io, TypeAdapter<?>... adapters) {
+ map.put(new CacheKey(adapters),io);
+ }
+
+ public static IO get(TypeAdapter<?>... adapters) {
+ IO io = get_cached(adapters);
+ if (io == null) {
+ String defaultImpl =
+ AnnoUtil.getDefaultImplementation(IO.class);
+ io = Discover.locate(
+ IO.class,
+ defaultImpl,
+ (Object)adapters);
+ if (io != null)
+ set_cached(io,adapters);
+ }
+ return io;
}
public void writeCollection(
Copied: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/EmbeddedExperience.java (from r1187164, abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/EmbeddedExperience.java)
URL: http://svn.apache.org/viewvc/abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/EmbeddedExperience.java?p2=abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/EmbeddedExperience.java&p1=abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/EmbeddedExperience.java&r1=1187164&r2=1197810&rev=1197810&view=diff
==============================================================================
--- abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/EmbeddedExperience.java (original)
+++ abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/EmbeddedExperience.java Fri Nov 4 22:42:11 2011
@@ -1,7 +1,10 @@
-package org.apache.abdera2.activities.model;
+package org.apache.abdera2.activities.model.objects;
import java.util.Map;
+import org.apache.abdera2.activities.model.ASBase;
+import org.apache.abdera2.activities.model.ASObject;
+import org.apache.abdera2.activities.model.Generator;
import org.apache.abdera2.common.iri.IRI;
/**
Propchange: abdera/abdera2/activities/src/main/java/org/apache/abdera2/activities/model/objects/EmbeddedExperience.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/misc/MapRed.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/misc/MapRed.java?rev=1197810&view=auto
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/misc/MapRed.java (added)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/misc/MapRed.java Fri Nov 4 22:42:11 2011
@@ -0,0 +1,695 @@
+package org.apache.abdera2.common.misc;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+import com.google.common.base.Equivalence;
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
+
+/**
+ * Provides lightweight, standalone MapReduce functionality without
+ * requiring Hadoop. This is intended to provide *BASIC* support for
+ * *SIMPLE* MapReduce operations on *SMALL* datasets. If you need
+ * more intensive support, then Hadoop MapReduce is obviously the
+ * better option.
+ *
+ * The MapRed class provides an number of methods for creating and
+ * composing MapReduce operations and bridges those with the Guava
+ * Libraries interfaces. For instance, using the various compose()
+ * methods, it is possible to create a com.google.common.base.Function
+ * that wraps a complete MapReduce operation with a single call to
+ * Function.apply().
+ *
+ * Heavy use of Generics makes proper set up a bit tricky and complicated,
+ * but once created, the MapReduce functions are immutable and threadsafe
+ * and can safely be stored as static final variables used throughout
+ * an application.
+ *
+ * A number of common basic Mapper and Reducer objects are also provided.
+ */
+public final class MapRed {
+
+ private MapRed() {}
+
+ /**
+ * Begin constructing the input to a MapReduce Function using a
+ * fluent factory API.. e.g.
+ * <pre>
+ * MapRed.PairBuilder<Void,Activity> gen =
+ * MapRed
+ * .<Void,String>make()
+ * .pair(null, "a")
+ * .pair(null, "b")
+ * .pair(null, "c");
+ * </pre>
+ *
+ * The PairBuilder.get() method return an Iterable of MapRed.Pair
+ * objects. That Iterable is used as the input to the MapReduce Function..
+ * e.g.
+ *
+ * <pre>
+ * Function<Iterable<Pair<Void,String>>,Iterable<Pair<String,Iterable<Integer>>>> f1 = ...
+ * Iterable<Pair<String,Iterable<Integer>>> res = f1.apply(gen.get());
+ * </pre>
+ *
+ * By default, the Function, and the wrapped MapReduce operation, executes
+ * within the current thread and blocks until completion. If you need async
+ * operation.. first, you should consider whether you need a full MapReduce
+ * implementation like Hadoop, or, you can use wrap the Function in a
+ * MoreFunctions.FutureFunction... e.g.
+ *
+ * <pre>
+ * ExecutorService exec =
+ * MoreExecutors.getExitingExecutorService(
+ * (ThreadPoolExecutor) Executors.newCachedThreadPool());
+ *
+ * Function<
+ * Iterable<MapRed.Pair<Void, Activity>>,
+ * Future<Iterable<MapRed.Pair<Integer,Iterable<String>>>>> ff =
+ * MoreFunctions.<
+ * Iterable<MapRed.Pair<Void, Activity>>,
+ * Iterable<MapRed.Pair<Integer,Iterable<String>>>>futureFunction(f3,exec);
+ * </pre>
+ *
+ * Note, again, the tricky use of generics but defining things in this way
+ * ensures type-safety throughout the operation. The FutureFunction.apply()
+ * will submit the operation to the provided Executor and return a Future
+ * whose value will be set once the operation completes. For greater control
+ * over the execution, you can call MoreFunctions.functionTask(...) to get
+ * a FutureTask instance that you can submit the ExecutorService yourself.
+ */
+ public static <K,V>PairBuilder<K,V> make() {
+ return new PairBuilder<K,V>();
+ }
+
+ public static class PairBuilder<K,V> implements Supplier<Iterable<Pair<K,V>>>, PairReader<K,V> {
+ private final List<Pair<K,V>> list =
+ new ArrayList<Pair<K,V>>();
+ public PairBuilder<K,V> pair(K k, V v) {
+ list.add(MapRed.<K,V>pair(k,v));
+ return this;
+ }
+ public Iterable<Pair<K, V>> get() {
+ return list;
+ }
+ public Iterator<Pair<K, V>> iterator() {
+ return get().iterator();
+ }
+ }
+
+ public static <K,V>Iterable<Pair<K,V>> pairs(Map<K,V> map) {
+ List<Pair<K,V>> list = new ArrayList<Pair<K,V>>();
+ for (Map.Entry<K,V> entry : map.entrySet())
+ list.add(pair(entry.getKey(),entry.getValue()));
+ return list;
+ }
+
+ public static <K,V>Pair<K,V> pair(K k, V v) {
+ return new Pair<K,V>(k,v);
+ }
+
+ public static class Pair<K,V> {
+ private K key;
+ private V val;
+ public Pair(K key, V val) {
+ this.key = key;
+ this.val = val;
+ }
+ public K key() {
+ return key;
+ }
+ public V val() {
+ return val;
+ }
+ }
+
+ public static interface Reducer<K2,V2,K3,V3> {
+ void reduce(
+ K2 key,
+ Iterator<V2> vals,
+ Collector<K3,V3> context);
+ }
+
+ public static interface Mapper<K1,V1,K2,V2> {
+ void map(K1 key, V1 val, Collector<K2,V2> context);
+ }
+
+ public static interface Collector<K,V> {
+ void collect(K key, V val);
+ }
+
+ public static interface PairReader<K,V> extends Iterable<Pair<K,V>> {}
+
+ public static interface MapperFunction<K1,V1,K2,V2>
+ extends Function<Iterable<Pair<K1,V1>>,Iterable<Pair<K2,Iterable<V2>>>> {}
+
+ public static interface ReducerFunction<K1,V1,K2,V2>
+ extends Function<Iterable<Pair<K1,Iterable<V1>>>,Iterable<Pair<K2,Iterable<V2>>>> {}
+
+ public static <K1,V1,K2,V2,K3,V3>Function<Iterable<Pair<K1,V1>>,Iterable<Pair<K3,Iterable<V3>>>> compose(
+ Mapper<K1,V1,K2,V2> mapper,
+ Reducer<K2,V2,K3,V3> reducer) {
+ return Functions.compose(asFunction(reducer),asFunction(mapper));
+ }
+
+ public static <K1,V1,K2,V2,K3,V3>Function<Iterable<Pair<K1,V1>>,Iterable<Pair<K3,Iterable<V3>>>> compose(
+ Mapper<K1,V1,K2,V2> mapper,
+ Reducer<K2,V2,K2,V2> combiner,
+ Reducer<K2,V2,K3,V3> reducer) {
+ return Functions
+ .compose(
+ asFunction(reducer),
+ Functions
+ .compose(
+ asFunction(combiner),
+ asFunction(mapper)));
+ }
+
+ public static <K1,V1,K2,V2,V3>Function<Iterable<Pair<K1,V1>>,Iterable<Pair<K2,Iterable<V3>>>> compose(
+ Mapper<K1,V1,K2,V2> mapper,
+ Reducer<K2,V2,K2,V3> reducer,
+ Comparator<K2> comparator) {
+ return Functions.compose(asFunction(reducer,comparator),asFunction(mapper,comparator));
+ }
+
+ public static <K1,V1,K2,V2,K3,V3>Function<Iterable<Pair<K1,V1>>,Iterable<Pair<K3,Iterable<V3>>>> compose(
+ Mapper<K1,V1,K2,V2> mapper,
+ Reducer<K2,V2,K3,V3> reducer,
+ Comparator<K2> comparator,
+ Comparator<K3> comparator2) {
+ return Functions.compose(asFunction(reducer,comparator2),asFunction(mapper,comparator));
+ }
+
+ public static <K1,V1,K2,V2,K3,V3>Function<Iterable<Pair<K1,V1>>,Iterable<Pair<K3,Iterable<V3>>>> compose(
+ Mapper<K1,V1,K2,V2> mapper,
+ Reducer<K2,V2,K2,V2> combiner,
+ Reducer<K2,V2,K3,V3> reducer,
+ Comparator<K2> comparator,
+ Comparator<K3> comparator2) {
+ return Functions
+ .compose(
+ asFunction(reducer, comparator2),
+ Functions
+ .compose(
+ asFunction(combiner, comparator),
+ asFunction(mapper,comparator)));
+ }
+
+ public static <K1,V1,K2,V2,V3>Function<Iterable<Pair<K1,V1>>,Iterable<Pair<K2,Iterable<V3>>>> compose(
+ Mapper<K1,V1,K2,V2> mapper,
+ Reducer<K2,V2,K2,V2> combiner,
+ Reducer<K2,V2,K2,V3> reducer,
+ Comparator<K2> comparator) {
+ return Functions
+ .compose(
+ asFunction(reducer, comparator),
+ Functions
+ .compose(
+ asFunction(combiner, comparator),
+ asFunction(mapper,comparator)));
+ }
+
+ public static <K1,V1,K2,V2,K3,V3>Function<Iterable<Pair<K1,V1>>,Iterable<Pair<K3,Iterable<V3>>>> compose(
+ MapperFunction<K1,V1,K2,V2> mapper,
+ ReducerFunction<K2,V2,K3,V3> reducer) {
+ return Functions.compose(reducer,mapper);
+ }
+
+ public static <K1,V1,K2,V2,K3,V3>Function<Iterable<Pair<K1,V1>>,Iterable<Pair<K3,Iterable<V3>>>> compose(
+ MapperFunction<K1,V1,K2,V2> mapper,
+ ReducerFunction<K2,V2,K2,V2> combiner,
+ ReducerFunction<K2,V2,K3,V3> reducer) {
+ return Functions
+ .compose(
+ reducer,
+ Functions
+ .compose(
+ combiner,
+ mapper));
+ }
+
+ public static <K1,V1,K2,V2>MapperFunction<K1,V1,K2,V2> asFunction(
+ final Mapper<K1,V1,K2,V2> mapper) {
+ return asFunction(mapper,false);
+ }
+
+ public static <K1,V1,K2,V2>MapperFunction<K1,V1,K2,V2> asFunction(
+ final Mapper<K1,V1,K2,V2> mapper,
+ final Comparator<K2> comparator) {
+ return asFunction(mapper,false, comparator);
+ }
+
+ public static <K1,V1,K2,V2>MapperFunction<K1,V1,K2,V2> asFunction(
+ final Mapper<K1,V1,K2,V2> mapper,
+ final boolean nulls) {
+ return new MapperFunction<K1,V1,K2,V2>() {
+ public Iterable<Pair<K2,Iterable<V2>>> apply(Iterable<Pair<K1,V1>> input) {
+ SimpleCollector<K2,V2> context = new SimpleCollector<K2,V2>(nulls);
+ List<Pair<K2, Iterable<V2>>> list = new ArrayList<Pair<K2, Iterable<V2>>>();
+ for (Pair<K1, V1> entry : input)
+ mapper.map(entry.key(), entry.val(), context);
+ for (Map.Entry<K2, Iterable<V2>> entry : context.collected())
+ list.add(pair(entry.getKey(), entry.getValue()));
+ return list;
+ }
+ };
+ }
+
+ public static <K1,V1,K2,V2>MapperFunction<K1,V1,K2,V2> asFunction(
+ final Mapper<K1,V1,K2,V2> mapper,
+ final boolean nulls,
+ final Comparator<K2> comparator) {
+ return new MapperFunction<K1,V1,K2,V2>() {
+ public Iterable<Pair<K2,Iterable<V2>>> apply(Iterable<Pair<K1,V1>> input) {
+ SimpleCollector<K2,V2> context = new SimpleCollector<K2,V2>(nulls,comparator);
+ List<Pair<K2, Iterable<V2>>> list = new ArrayList<Pair<K2, Iterable<V2>>>();
+ for (Pair<K1, V1> entry : input)
+ mapper.map(entry.key(), entry.val(), context);
+ for (Map.Entry<K2, Iterable<V2>> entry : context.collected())
+ list.add(pair(entry.getKey(), entry.getValue()));
+ return list;
+ }
+ };
+ }
+
+ public static <K1,V1,K2,V2>ReducerFunction<K1,V1,K2,V2> asFunction(
+ final Reducer<K1,V1,K2,V2> reducer) {
+ return asFunction(reducer,false);
+ }
+
+ public static <K1,V1,K2,V2>ReducerFunction<K1,V1,K2,V2> asFunction(
+ final Reducer<K1,V1,K2,V2> reducer,
+ final Comparator<K2> comparator) {
+ return asFunction(reducer,false, comparator);
+ }
+
+ public static <K1,V1,K2,V2>ReducerFunction<K1,V1,K2,V2> asFunction(
+ final Reducer<K1,V1,K2,V2> reducer,
+ final boolean nulls,
+ final Comparator<K2> comparator) {
+ return new ReducerFunction<K1,V1,K2,V2>() {
+ public Iterable<Pair<K2,Iterable<V2>>> apply(Iterable<Pair<K1,Iterable<V1>>> input) {
+ SimpleCollector<K2,V2> context = new SimpleCollector<K2,V2>(nulls, comparator);
+ List<Pair<K2, Iterable<V2>>> list = new ArrayList<Pair<K2, Iterable<V2>>>();
+ for (Pair<K1, Iterable<V1>> entry : input)
+ reducer.reduce(entry.key(), entry.val().iterator(), context);
+ for (Map.Entry<K2, Iterable<V2>> entry : context.collected())
+ list.add(pair(entry.getKey(), entry.getValue()));
+ return list;
+ }
+ };
+ }
+
+ public static <K1,V1,K2,V2>ReducerFunction<K1,V1,K2,V2> asFunction(
+ final Reducer<K1,V1,K2,V2> reducer,
+ final boolean nulls) {
+ return new ReducerFunction<K1,V1,K2,V2>() {
+ public Iterable<Pair<K2,Iterable<V2>>> apply(Iterable<Pair<K1,Iterable<V1>>> input) {
+ SimpleCollector<K2,V2> context = new SimpleCollector<K2,V2>(nulls);
+ List<Pair<K2, Iterable<V2>>> list = new ArrayList<Pair<K2, Iterable<V2>>>();
+ for (Pair<K1, Iterable<V1>> entry : input)
+ reducer.reduce(entry.key(), entry.val().iterator(), context);
+ for (Map.Entry<K2, Iterable<V2>> entry : context.collected())
+ list.add(pair(entry.getKey(), entry.getValue()));
+ return list;
+ }
+ };
+ }
+
+ public static <K,V>Mapper<K,V,V,K> invertMapper() {
+ return new Mapper<K,V,V,K>() {
+ public void map(K key, V val, Collector<V, K> context) {
+ context.collect(val, key);
+ }
+ };
+ }
+
+ public static <K,V>Reducer<K,V,V,K> invertReducer() {
+ return new Reducer<K,V,V,K>() {
+ public void reduce(K key, Iterator<V> vals, Collector<V, K> context) {
+ while(vals.hasNext())
+ context.collect(vals.next(), key);
+ }
+ };
+ }
+
+ public static <K,V>Mapper<K,V,K,V> identityMapper() {
+ return new Mapper<K,V,K,V>() {
+ public void map(K key, V val, Collector<K, V> context) {
+ context.collect(key, val);
+ }
+ };
+ }
+
+ public static <K,V>Reducer<K,V,K,V> identityReducer() {
+ return new Reducer<K,V,K,V>() {
+ public void reduce(K key, Iterator<V> vals, Collector<K, V> context) {
+ while(vals.hasNext())
+ context.collect(key,vals.next());
+ }
+ };
+ }
+
+ public static <K,V>Mapper<K,V,K,V> identityMapper(
+ final Predicate<V> predicate) {
+ return new Mapper<K,V,K,V>() {
+ public void map(K key, V val, Collector<K, V> context) {
+ if (predicate.apply(val))
+ context.collect(key, val);
+ }
+ };
+ }
+
+ public static <K,V>Reducer<K,V,K,V> identityReducer(
+ final Predicate<V> predicate) {
+ return new Reducer<K,V,K,V>() {
+ public void reduce(K key, Iterator<V> vals, Collector<K, V> context) {
+ while(vals.hasNext()) {
+ V val = vals.next();
+ if (predicate.apply(val))
+ context.collect(key,val);
+ }
+ }
+ };
+ }
+
+ public static <K,V1,V2>Mapper<K,V1,K,V2> functionMapper(
+ final Function<V1,V2> transform) {
+ return new Mapper<K,V1,K,V2>() {
+ public void map(K key, V1 val, Collector<K,V2> context) {
+ context.collect(key, transform.apply(val));
+ }
+ };
+ }
+
+ public static <K,V1,V2>Reducer<K,V1,K,V2> functionReducer(
+ final Function<Iterator<V1>,V2> transform) {
+ return new Reducer<K,V1,K,V2>() {
+ public void reduce(K key, Iterator<V1> vals, Collector<K, V2> context) {
+ context.collect(key, transform.apply(vals));
+ }
+ };
+ }
+
+ public static <K,V1,V2>Mapper<K,V1,K,V2> functionMapper(
+ final Function<V1,V2> transform,
+ final Predicate<V1> predicate) {
+ return new Mapper<K,V1,K,V2>() {
+ public void map(K key, V1 val, Collector<K,V2> context) {
+ if (predicate.apply(val))
+ context.collect(key, transform.apply(val));
+ }
+ };
+ }
+
+ public static <K1,V1,K2,V2>Mapper<K1,V1,K2,V2> functionMapper(
+ final Function<K1,K2> keyTransform,
+ final Function<V1,V2> valTransform) {
+ return new Mapper<K1,V1,K2,V2>() {
+ public void map(K1 key, V1 val, Collector<K2, V2> context) {
+ context.collect(keyTransform.apply(key),valTransform.apply(val));
+ }
+ };
+ }
+
+ public static <K1,V1,K2,V2>Reducer<K1,V1,K2,V2> functionReducer(
+ final Function<K1,K2> keyTransform,
+ final Function<Iterator<V1>,V2> valTransform) {
+ return new Reducer<K1,V1,K2,V2>() {
+ public void reduce(K1 key, Iterator<V1> vals, Collector<K2, V2> context) {
+ context.collect(keyTransform.apply(key), valTransform.apply(vals));
+ }
+ };
+ }
+
+ public static <K1,V1,K2,V2>Mapper<K1,V1,K2,V2> functionMapper(
+ final Function<K1,K2> keyTransform,
+ final Function<V1,V2> valTransform,
+ final Predicate<V1> predicate) {
+ return new Mapper<K1,V1,K2,V2>() {
+ public void map(K1 key, V1 val, Collector<K2, V2> context) {
+ if (predicate.apply(val))
+ context.collect(keyTransform.apply(key),valTransform.apply(val));
+ }
+ };
+ }
+
+ public static <K,V>Reducer<K,V,K,Integer> countingReducer() {
+ return new Reducer<K,V,K,Integer>() {
+ public void reduce(K key, Iterator<V> vals, Collector<K, Integer> context) {
+ context.collect(key, Iterators.size(vals));
+ }
+ };
+ }
+
+ public static <K,V>Reducer<K,V,K,V> noDuplicatesReducer() {
+ return new Reducer<K,V,K,V>() {
+ final Set<V> set = new LinkedHashSet<V>();
+ public void reduce(K key, Iterator<V> vals, Collector<K, V> context) {
+ while(vals.hasNext()) {
+ V v = vals.next();
+ if (!set.contains(v)) {
+ context.collect(key, v);
+ set.add(v);
+ }
+ }
+ }
+ };
+ }
+
+ public static <K,V>Reducer<K,V,K,V> noEquivalentsReducer(
+ final Equivalence<V> equivalence) {
+ return new Reducer<K,V,K,V>() {
+ final Set<V> set = new LinkedHashSet<V>();
+ public void reduce(K key, Iterator<V> vals, Collector<K, V> context) {
+ while(vals.hasNext()) {
+ V v = vals.next();
+ Predicate<V> ve = equivalence.equivalentTo(v);
+ try {
+ Iterables.find(set, ve);
+ } catch (NoSuchElementException e) {
+ context.collect(key,v);
+ set.add(v);
+ }
+ }
+ }
+ };
+ }
+
+ /**
+ * A PartitionFunction is responsible for taking an input Iterable and
+ * splitting it into multiple sub-iterables.
+ */
+ public static interface PartitionFunction<T>
+ extends Function<Iterable<T>,Iterable<Iterable<T>>> {}
+
+ /**
+ * A CombinerFunction is responsible for taking multiple Iterables and
+ * combining them into a single Iterable.
+ */
+ public static interface CombinerFunction<T>
+ extends Function<Iterable<Iterable<T>>,Iterable<T>> {}
+
+ /**
+ * Return the default basic PartitionFunction that splits the
+ * input Iterable into multiple unmodifiable Iterables of the
+ * given size (the final iterable may be smaller)
+ */
+ public static <T>PartitionFunction<T> partitioner(final int size) {
+ return new PartitionFunction<T>() {
+ public Iterable<Iterable<T>> apply(Iterable<T> input) {
+ Iterable<List<T>> i = Iterables.<T>partition(input, size);
+ List<Iterable<T>> l = new ArrayList<Iterable<T>>();
+ Iterables.addAll(l, i);
+ return Iterables.unmodifiableIterable(l);
+ }
+ };
+ }
+
+ /**
+ * Return the default CombinerFunction that concats the
+ * given Iterables into a single Iterable without resorting.
+ * (e.g. and Iterable of [["a","b"],["d","c"]] would be
+ * combined into a single Iterable ["a","b","d","c"]
+ */
+ public static <T>CombinerFunction<T> combiner() {
+ return new CombinerFunction<T>() {
+ public Iterable<T> apply(Iterable<Iterable<T>> input) {
+ return Iterables.concat(input);
+ }
+ };
+ }
+
+ /**
+ * Returns a CombinerFunction that concats the
+ * given Iterables into a single Iterable without resorting,
+ * with all duplicates removed.
+ * (e.g. and Iterable of [["a","b"],["d","c","b"]] would be
+ * combined into a single Iterable ["a","b","d","c"]
+ */
+ public static <T>CombinerFunction<T> uniqueCombiner() {
+ return new CombinerFunction<T>() {
+ public Iterable<T> apply(Iterable<Iterable<T>> input) {
+ Iterable<T> c = Iterables.concat(input);
+ LinkedHashSet<T> l = new LinkedHashSet<T>();
+ Iterables.addAll(l, c);
+ return l;
+ }
+ };
+ }
+
+ /**
+ * Return the default CombinerFunction that concats the
+ * given Iterables into a single Iterable using the specified
+ * Comparator for sorting. If Comparator is null, no sorting
+ * will be performed
+ * (e.g. and Iterable of [["a","b"],["d","c"]] would be
+ * combined into a single Iterable ["a","b","c","d"]
+ */
+ public static <T>CombinerFunction<T> sortingCombiner(final Comparator<T> order) {
+ return new CombinerFunction<T>() {
+ public Iterable<T> apply(Iterable<Iterable<T>> input) {
+ Iterable<T> i = Iterables.concat(input);
+ List<T> l = new ArrayList<T>();
+ Iterables.addAll(l, i);
+ if (order != null)
+ Collections.sort(l,order);
+ return l;
+ }
+ };
+ }
+
+ /**
+ * Return the default CombinerFunction that concats the
+ * given Iterables into a single Iterable using the natural
+ * order of the elements for sorting
+ * (e.g. and Iterable of [["a","b"],["d","c"]] would be
+ * combined into a single Iterable ["a","b","c","d"]
+ */
+ public static <T extends Comparable<T>>CombinerFunction<T> sortingCombiner() {
+ return new CombinerFunction<T>() {
+ public Iterable<T> apply(Iterable<Iterable<T>> input) {
+ Iterable<T> i = Iterables.concat(input);
+ List<T> l = new ArrayList<T>();
+ Iterables.addAll(l, i);
+ Collections.<T>sort(l);
+ return l;
+ }
+ };
+ }
+
+
+ /**
+ * Return the default CombinerFunction that concats the
+ * given Iterables into a single Iterable using the specified
+ * Comparator for sorting. If Comparator is null, no sorting
+ * will be performed
+ * (e.g. and Iterable of [["a","b"],["d","c"]] would be
+ * combined into a single Iterable ["a","b","c","d"]
+ */
+ public static <T>CombinerFunction<T> uniqueSortingCombiner(final Comparator<T> order) {
+ return new CombinerFunction<T>() {
+ public Iterable<T> apply(Iterable<Iterable<T>> input) {
+ Iterable<T> i = Iterables.concat(input);
+ Set<T> l = new ConcurrentSkipListSet<T>(order);
+ Iterables.addAll(l, i);
+ return l;
+ }
+ };
+ }
+
+ /**
+ * Return the default CombinerFunction that concats the
+ * given Iterables into a single Iterable using the natural
+ * order of the elements for sorting
+ * (e.g. and Iterable of [["a","b"],["d","c"]] would be
+ * combined into a single Iterable ["a","b","c","d"]
+ */
+ public static <T extends Comparable<T>>CombinerFunction<T> uniqueSortingCombiner() {
+ return new CombinerFunction<T>() {
+ public Iterable<T> apply(Iterable<Iterable<T>> input) {
+ Iterable<T> i = Iterables.concat(input);
+ Set<T> l = new ConcurrentSkipListSet<T>();
+ Iterables.addAll(l, i);
+ return l;
+ }
+ };
+ }
+
+ /**
+ * Return the default collector impl
+ */
+ public static <K,V>Collector<K,V> collector(boolean nulls, Comparator<K> order) {
+ return new SimpleCollector<K,V>(nulls,order);
+ }
+
+ /**
+ * Return the default collector impl
+ */
+ public static <K,V>Collector<K,V> collector(boolean nulls) {
+ return new SimpleCollector<K,V>(nulls);
+ }
+
+ /**
+ * Return the default collector impl
+ */
+ public static <K,V>Collector<K,V> collector(Comparator<K> order) {
+ return new SimpleCollector<K,V>(false,order);
+ }
+
+ /**
+ * Return the default collector impl
+ */
+ public static <K,V>Collector<K,V> collector() {
+ return new SimpleCollector<K,V>(false);
+ }
+
+ public static class SimpleCollector<K,V>
+ implements MapRed.Collector<K, V> {
+
+ private final Map<K,Iterable<V>> map;
+ private final boolean collectNulls;
+ public SimpleCollector() {
+ this(false);
+ }
+ public SimpleCollector(boolean nulls) {
+ this.collectNulls = nulls;
+ map = new ConcurrentSkipListMap<K,Iterable<V>>();
+ }
+ public SimpleCollector(Comparator<K> comparator) {
+ this(false,comparator);
+ }
+ public SimpleCollector(boolean nulls, Comparator<K> comparator) {
+ this.collectNulls = nulls;
+ map = comparator != null ?
+ new ConcurrentSkipListMap<K,Iterable<V>>(comparator) :
+ new ConcurrentSkipListMap<K,Iterable<V>>();
+ }
+ public void collect(K key, V val) {
+ if (!collectNulls && val == null) return;
+ List<V> set = (List<V>) map.get(key);
+ if (set == null) {
+ set = new ArrayList<V>();
+ map.put(key,set);
+ }
+ set.add(val);
+ }
+ public Iterable<Map.Entry<K,Iterable<V>>> collected() {
+ return Collections.<Map.Entry<K,Iterable<V>>>unmodifiableSet(map.entrySet());
+ }
+ }
+}
Propchange: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/misc/MapRed.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/misc/MoreFunctions.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/misc/MoreFunctions.java?rev=1197810&r1=1197809&r2=1197810&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/misc/MoreFunctions.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/misc/MoreFunctions.java Fri Nov 4 22:42:11 2011
@@ -6,6 +6,10 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
import org.apache.abdera2.common.Discover;
@@ -14,6 +18,7 @@ import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.ListenableFutureTask;
public class MoreFunctions {
@@ -356,4 +361,62 @@ public class MoreFunctions {
}
}
};
+
+ public static final Function<String,Integer> parseInt =
+ new Function<String,Integer>() {
+ public Integer apply(String input) {
+ try {
+ return (input != null) ? Integer.valueOf(input) : -1;
+ } catch (NumberFormatException e) {
+ return -1;
+ }
+ }
+ };
+
+ public static final Function<String,Short> parseShort =
+ new Function<String,Short>() {
+ public Short apply(String input) {
+ try {
+ return (input != null) ? Short.valueOf(input) : -1;
+ } catch (NumberFormatException e) {
+ return -1;
+ }
+ }
+ };
+
+ public static <I,O>Function<I,Future<O>> futureFunction(
+ Function<I,O> function,
+ ExecutorService exec) {
+ return new FutureFunction<I,O>(function,exec);
+ }
+
+ public static <I,O>FutureTask<O> functionTask(
+ final Function<I,O> function,
+ final I input) {
+ return ListenableFutureTask.<O>create(
+ new Callable<O>() {
+ public O call() throws Exception {
+ return function.apply(input);
+ }
+ }
+ );
+ }
+
+ public static class FutureFunction<I,O>
+ implements Function<I,Future<O>> {
+ final Function<I,O> inner;
+ final ExecutorService exec;
+ public FutureFunction(
+ Function<I,O> inner,
+ ExecutorService exec) {
+ this.inner = inner;
+ this.exec = exec;
+ }
+ public Future<O> apply(final I input) {
+ FutureTask<O> task = functionTask(inner,input);
+ exec.submit(task);
+ return task;
+ }
+ }
+
}
Added: abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/MapRedExample.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/MapRedExample.java?rev=1197810&view=auto
==============================================================================
--- abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/MapRedExample.java (added)
+++ abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/MapRedExample.java Fri Nov 4 22:42:11 2011
@@ -0,0 +1,132 @@
+package org.apache.abdera2.examples.activities;
+
+import static com.google.common.util.concurrent.MoreExecutors.getExitingExecutorService;
+import static org.apache.abdera2.common.misc.MapRed.asFunction;
+import static org.apache.abdera2.common.misc.MapRed.compose;
+
+import java.io.ByteArrayOutputStream;
+import java.io.StringReader;
+import java.net.URL;
+import java.util.Collections;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.activities.model.ASObject;
+import org.apache.abdera2.activities.model.Activity;
+import org.apache.abdera2.activities.model.Collection;
+import org.apache.abdera2.activities.model.IO;
+import org.apache.abdera2.common.misc.MapRed;
+import org.apache.abdera2.common.misc.MoreFunctions;
+import org.apache.abdera2.common.misc.MapRed.Collector;
+import org.apache.abdera2.common.misc.MapRed.Mapper;
+import org.apache.abdera2.common.misc.MapRed.Pair;
+import org.apache.abdera2.common.misc.MapRed.PairBuilder;
+import org.apache.abdera2.common.misc.MapRed.ReducerFunction;
+import org.apache.abdera2.model.Document;
+import org.apache.abdera2.model.Feed;
+import org.apache.abdera2.parser.Parser;
+import org.apache.abdera2.parser.ParserOptions;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+
+/**
+ * A basic example showing the use of the org.apache.abdera2.common.misc.MapRed
+ * lightweight MapReduce functionality. This class is designed to provide a
+ * general purpose, *lightweight*, *basic*, *simple* MapReduce capability
+ * designed around working with relatively *small* data sets for basic analysis
+ * operations. It is NOT designed to provide an alternative to a full MapReduce
+ * implementation such as Hadoop.
+ *
+ * The MapRed class has been tightly integrated with the Guava Libraries
+ * Function interface to make it possible to encapsulate a mapreduce
+ * operation within a single Function object.
+ *
+ * In this example, we first pull an Atom feed and convert that into an
+ * Activity Streams. Second, we prepare the input data for the
+ * MapReduce operation which is composed statically and stored in a
+ * final static Function variable. Third, we invoke the Function with
+ * the input data asynchronously using an ExecutorService. The main
+ * thread waits for the operation to complete, then iterates the output,
+ * which, in this case, is a summarizaton of the total number of posts
+ * per author in the original Atom feed.
+ */
+public class MapRedExample {
+ // Prepare the various functions and store them as static final variables
+
+ private final static Function<
+ Iterable<Pair<Void, Activity>>,
+ Iterable<Pair<String, Iterable<Integer>>>> f1 =
+ compose(
+ new MyMapper(),
+ MapRed.<String,ASObject>countingReducer()
+ );
+
+ private final static ReducerFunction<String,Integer,Integer,String> f2 =
+ asFunction(MapRed.<String,Integer>invertReducer(),
+ Collections.<Integer>reverseOrder());
+
+ private final static Function<
+ Iterable<Pair<Void, Activity>>,
+ Iterable<Pair<Integer,Iterable<String>>>> f3 =
+ Functions.compose(f2,f1);
+
+ private final static ExecutorService exec =
+ getExitingExecutorService(
+ (ThreadPoolExecutor) Executors.newCachedThreadPool());
+
+ private final static Function<
+ Iterable<Pair<Void, Activity>>,
+ Future<Iterable<Pair<Integer,Iterable<String>>>>> ff =
+ MoreFunctions.<
+ Iterable<Pair<Void, Activity>>,
+ Iterable<Pair<Integer,Iterable<String>>>>futureFunction(f3,exec);
+
+ public static void main(String... args) throws Exception {
+ // Read the Atom Feed
+ Abdera abdera = Abdera.getInstance();
+ URL url = new URL("http://planet.intertwingly.net/atom.xml");
+ Parser parser = abdera.getParser();
+ ParserOptions options = parser.getDefaultParserOptions();
+ options.setCharset("UTF-8");
+ Document<Feed> doc = abdera.getParser().parse(url.openStream(),url.toString(),options);
+ Feed feed = doc.getRoot();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ feed.writeTo("activity", out);
+
+ // Converted it to an Activity Stream
+ String r = new String(out.toByteArray(),"UTF-8");
+ Collection<Activity> col = IO.get().readCollection(new StringReader(r));
+
+ // Prepare the input data
+ PairBuilder<Void,Activity> gen =
+ MapRed
+ .<Void,Activity>make();
+ for (Activity activity : col.getItems())
+ gen.pair(null, activity);
+
+ // The Function ff is asynchronous... we apply it, then call get on
+ // the returned Future to wait the result. The mapreduce operation
+ // occurs in a different thread and sets the value of the Future
+ // when it is complete
+ for (Pair<Integer,Iterable<String>> entry : ff.apply(gen).get())
+ System.out.println(
+ entry.key() + "=" + entry.val());
+
+
+ }
+
+ static class MyMapper
+ implements Mapper<Void,Activity,String,ASObject> {
+ public void map(
+ Void key,
+ Activity val,
+ Collector<String,ASObject> context) {
+ String ot = val.getActor().getDisplayName();
+ context.collect(ot!=null?ot:"", val.getActor());
+ }
+ }
+}
Propchange: abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/MapRedExample.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/MiscellaneousExamples.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/MiscellaneousExamples.java?rev=1197810&r1=1197809&r2=1197810&view=diff
==============================================================================
--- abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/MiscellaneousExamples.java (original)
+++ abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/activities/MiscellaneousExamples.java Fri Nov 4 22:42:11 2011
@@ -1,6 +1,7 @@
package org.apache.abdera2.examples.activities;
import org.apache.abdera2.activities.extra.ASContext;
+import org.apache.abdera2.activities.extra.Extra;
import org.apache.abdera2.activities.model.Activity;
import org.apache.abdera2.activities.model.Collection;
import org.apache.abdera2.common.templates.Template;
@@ -9,6 +10,45 @@ public class MiscellaneousExamples {
public static void main(String... args) throws Exception {
+ // Every object and activity has an "id" property.. when
+ // an object gets passed around through multiple parties,
+ // the "id" of the object may change but the object itself
+ // stays the same. The changing id can make it difficult to
+ // detect duplicates of the same object so the Activity
+ // Streams specification provides two properties called
+ // "downstreamDuplicates" and "upstreamDuplicates", both of
+ // which are arrays that can be used to record to known
+ // id's of a single object. A basic equals() check on the
+ // Activity cannot determine if the objects are actually
+ // duplicates with different ids. For that, we provide
+ // two alternative Equivalence functions, one that bases
+ // it's decision solely on the values of the "id" properties,
+ // and another that properly compares all known ids recorded
+ // using the "id", "downstreamDuplicates" and "upsteamDuplicates"
+ // property values.
+
+ // first we create two activities that have different "id" values,
+ // but share common values in their downstream and upstream duplicates.
+ // basically, we're saying that an object with the "id":"baz" is a
+ // known derivative of the first Activity object we create with "id":"foo",
+ // and we're saying that an Activity with the "id":"bar" is itself a
+ // derivative of "id":"baz" .... so even those our two activities
+ // do not know about each other directly, we can related the two
+ // and detect that they are likely duplicates of one another
+
+ Activity a1 = new Activity();
+ a1.setId("foo");
+ a1.addDownstreamDuplicate("baz");
+
+ Activity a2 = new Activity();
+ a2.setId("bar");
+ a2.addUpstreamDuplicate("baz");
+
+ System.out.println(Extra.IDENTITY_EQUIVALENCE.equivalent(a1, a2)); // false
+ System.out.println(Extra.IDENTITY_WITH_DUPLICATES_EQUIVALENCE.equivalent(a1, a2)); // true
+
+
+
// Working with URI Templates.. the ASContext class
// provides a URI Template Context implementation
// that wraps an Activity Streams object, making it