From cc478d748c44cdda7455f14000524a3cc1752157 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 16 Apr 2014 15:27:45 -0700 Subject: [PATCH] =?UTF-8?q?Initial=20Checkin=E2=80=A6=20Activity=20Streams?= =?UTF-8?q?=201.0=20Reference=20Implementation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 6 + README.md | 109 + actions/pom.xml | 138 + .../actions/example/Actions.java | 180 ++ .../actions/ActionHandler.java | 343 +++ .../activitystreams/actions/ActionMakers.java | 205 ++ .../actions/ActionObjectAdapter.java | 85 + .../actions/ActionsModule.java | 82 + .../activitystreams/actions/Adapters.java | 46 + .../actions/Authentication.java | 83 + .../actions/EmbedActionHandler.java | 213 ++ .../activitystreams/actions/HtmlForm.java | 161 + .../actions/HttpActionHandler.java | 116 + .../actions/IntentActionHandler.java | 77 + .../activitystreams/actions/Parameter.java | 949 ++++++ .../actions/ParametersValue.java | 152 + .../activitystreams/actions/StylesValue.java | 131 + .../activitystreams/actions/TypedPayload.java | 160 + .../activitystreams/actions/UrlTemplate.java | 176 ++ assembly/assembly.xml | 17 + assembly/pom.xml | 49 + core/TODO.md | 4 + core/pom.xml | 131 + .../activitystreams/examples/Simple.java | 71 + .../activitystreams/examples/Simple2.java | 83 + .../activitystreams/examples/Simple3.java | 89 + .../activitystreams/examples/Simple4.java | 101 + .../activitystreams/examples/Simple5.java | 60 + .../ibm/common/activitystreams/ASObject.java | 2639 +++++++++++++++++ .../common/activitystreams/ActionsValue.java | 213 ++ .../ibm/common/activitystreams/Activity.java | 832 ++++++ .../common/activitystreams/Collection.java | 504 ++++ .../com/ibm/common/activitystreams/IO.java | 614 ++++ .../ibm/common/activitystreams/LinkValue.java | 309 ++ .../ibm/common/activitystreams/Makers.java | 153 + .../com/ibm/common/activitystreams/NLV.java | 257 ++ .../ibm/common/activitystreams/TypeValue.java | 140 + .../ibm/common/activitystreams/ValueType.java | 15 + .../ibm/common/activitystreams/Writable.java | 76 + .../internal/ASObjectAdapter.java | 302 ++ .../activitystreams/internal/Adapter.java | 13 + .../activitystreams/internal/Adapters.java | 315 ++ .../activitystreams/internal/EnumAdapter.java | 107 + .../activitystreams/internal/GsonWrapper.java | 320 ++ .../LazilyParsedNumberComparable.java | 107 + .../internal/LinkValueAdapter.java | 115 + .../activitystreams/internal/Model.java | 513 ++++ .../internal/MultimapAdapter.java | 122 + .../internal/NaturalLanguageValueAdapter.java | 95 + .../activitystreams/internal/Schema.java | 419 +++ .../internal/SimpleAdapter.java | 69 + .../internal/TypeValueAdapter.java | 104 + .../util/AbstractDictionaryObject.java | 284 ++ .../util/AbstractDictionaryObjectAdapter.java | 74 + .../util/AbstractWritable.java | 132 + .../activitystreams/util/Converters.java | 341 +++ .../common/activitystreams/util/Module.java | 12 + .../util/TypeValueResolver.java | 31 + .../activitystreams/test/TestBasics.java | 156 + .../common/activitystreams/test/TestIO.java | 57 + core/src/test/resources/data/1.json | 5 + geo/pom.xml | 144 + .../com/ibm/common/geojson/AS1Position.java | 77 + .../java/com/ibm/common/geojson/Address.java | 93 + .../com/ibm/common/geojson/BoundingBox.java | 254 ++ .../main/java/com/ibm/common/geojson/CRS.java | 122 + .../java/com/ibm/common/geojson/Feature.java | 133 + .../ibm/common/geojson/FeatureCollection.java | 103 + .../com/ibm/common/geojson/GeoMakers.java | 109 + .../com/ibm/common/geojson/GeoObject.java | 172 ++ .../java/com/ibm/common/geojson/Geometry.java | 48 + .../common/geojson/GeometryCollection.java | 107 + .../com/ibm/common/geojson/LineString.java | 161 + .../ibm/common/geojson/MultiLineString.java | 99 + .../com/ibm/common/geojson/MultiPoint.java | 107 + .../com/ibm/common/geojson/MultiPolygon.java | 101 + .../java/com/ibm/common/geojson/Place.java | 92 + .../java/com/ibm/common/geojson/Point.java | 102 + .../java/com/ibm/common/geojson/Polygon.java | 103 + .../java/com/ibm/common/geojson/Position.java | 130 + .../ibm/common/geojson/as2/GeoAdapter.java | 331 +++ .../com/ibm/common/geojson/as2/GeoModule.java | 75 + .../common/geojson/as2/GeoObjectAdapter.java | 64 + legacy/pom.xml | 143 + .../activitystreams/legacy/AudioVisual.java | 61 + .../common/activitystreams/legacy/Binary.java | 161 + .../activitystreams/legacy/Bookmark.java | 52 + .../activitystreams/legacy/Compression.java | 53 + .../common/activitystreams/legacy/Event.java | 118 + .../common/activitystreams/legacy/File.java | 63 + .../common/activitystreams/legacy/Issue.java | 63 + .../activitystreams/legacy/LegacyMakers.java | 158 + .../activitystreams/legacy/LegacyModule.java | 136 + .../legacy/LegacyObjectAdapter.java | 98 + .../activitystreams/legacy/MediaLink.java | 107 + .../legacy/MediaLinkAdapter.java | 64 + .../activitystreams/legacy/Membership.java | 53 + .../activitystreams/legacy/Question.java | 76 + .../common/activitystreams/legacy/Task.java | 175 ++ .../activitystreams/legacy/WithImage.java | 52 + pom.xml | 78 + 101 files changed, 17900 insertions(+) create mode 100644 .gitignore create mode 100755 README.md create mode 100644 actions/pom.xml create mode 100755 actions/src/examples/com/ibm/common/activitystreams/actions/example/Actions.java create mode 100755 actions/src/main/java/com/ibm/common/activitystreams/actions/ActionHandler.java create mode 100755 actions/src/main/java/com/ibm/common/activitystreams/actions/ActionMakers.java create mode 100644 actions/src/main/java/com/ibm/common/activitystreams/actions/ActionObjectAdapter.java create mode 100644 actions/src/main/java/com/ibm/common/activitystreams/actions/ActionsModule.java create mode 100644 actions/src/main/java/com/ibm/common/activitystreams/actions/Adapters.java create mode 100755 actions/src/main/java/com/ibm/common/activitystreams/actions/Authentication.java create mode 100755 actions/src/main/java/com/ibm/common/activitystreams/actions/EmbedActionHandler.java create mode 100755 actions/src/main/java/com/ibm/common/activitystreams/actions/HtmlForm.java create mode 100755 actions/src/main/java/com/ibm/common/activitystreams/actions/HttpActionHandler.java create mode 100755 actions/src/main/java/com/ibm/common/activitystreams/actions/IntentActionHandler.java create mode 100755 actions/src/main/java/com/ibm/common/activitystreams/actions/Parameter.java create mode 100755 actions/src/main/java/com/ibm/common/activitystreams/actions/ParametersValue.java create mode 100755 actions/src/main/java/com/ibm/common/activitystreams/actions/StylesValue.java create mode 100755 actions/src/main/java/com/ibm/common/activitystreams/actions/TypedPayload.java create mode 100755 actions/src/main/java/com/ibm/common/activitystreams/actions/UrlTemplate.java create mode 100644 assembly/assembly.xml create mode 100644 assembly/pom.xml create mode 100644 core/TODO.md create mode 100755 core/pom.xml create mode 100755 core/src/examples/com/ibm/common/activitystreams/examples/Simple.java create mode 100755 core/src/examples/com/ibm/common/activitystreams/examples/Simple2.java create mode 100755 core/src/examples/com/ibm/common/activitystreams/examples/Simple3.java create mode 100755 core/src/examples/com/ibm/common/activitystreams/examples/Simple4.java create mode 100644 core/src/examples/com/ibm/common/activitystreams/examples/Simple5.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/ASObject.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/ActionsValue.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/Activity.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/Collection.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/IO.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/LinkValue.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/Makers.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/NLV.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/TypeValue.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/ValueType.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/Writable.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/internal/ASObjectAdapter.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/internal/Adapter.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/internal/Adapters.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/internal/EnumAdapter.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/internal/GsonWrapper.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/internal/LazilyParsedNumberComparable.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/internal/LinkValueAdapter.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/internal/Model.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/internal/MultimapAdapter.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/internal/NaturalLanguageValueAdapter.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/internal/Schema.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/internal/SimpleAdapter.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/internal/TypeValueAdapter.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/util/AbstractDictionaryObject.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/util/AbstractDictionaryObjectAdapter.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/util/AbstractWritable.java create mode 100755 core/src/main/java/com/ibm/common/activitystreams/util/Converters.java create mode 100644 core/src/main/java/com/ibm/common/activitystreams/util/Module.java create mode 100644 core/src/main/java/com/ibm/common/activitystreams/util/TypeValueResolver.java create mode 100644 core/src/test/java/com/ibm/common/activitystreams/test/TestBasics.java create mode 100644 core/src/test/java/com/ibm/common/activitystreams/test/TestIO.java create mode 100755 core/src/test/resources/data/1.json create mode 100755 geo/pom.xml create mode 100644 geo/src/main/java/com/ibm/common/geojson/AS1Position.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/Address.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/BoundingBox.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/CRS.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/Feature.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/FeatureCollection.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/GeoMakers.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/GeoObject.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/Geometry.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/GeometryCollection.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/LineString.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/MultiLineString.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/MultiPoint.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/MultiPolygon.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/Place.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/Point.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/Polygon.java create mode 100755 geo/src/main/java/com/ibm/common/geojson/Position.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/as2/GeoAdapter.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/as2/GeoModule.java create mode 100644 geo/src/main/java/com/ibm/common/geojson/as2/GeoObjectAdapter.java create mode 100644 legacy/pom.xml create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/AudioVisual.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/Binary.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/Bookmark.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/Compression.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/Event.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/File.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/Issue.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/LegacyMakers.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/LegacyModule.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/LegacyObjectAdapter.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/MediaLink.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/MediaLinkAdapter.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/Membership.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/Question.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/Task.java create mode 100644 legacy/src/main/java/com/ibm/common/activitystreams/legacy/WithImage.java create mode 100644 pom.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d0f6878 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.classpath +.project +.settings +*/.classpath +*/.project +*/.settings diff --git a/README.md b/README.md new file mode 100755 index 0000000..08021c7 --- /dev/null +++ b/README.md @@ -0,0 +1,109 @@ +# Activity Streams 2.0 Reference Implementation + +## Getting Started + +Maven: +```xml + + com.ibm.common + activitystreams + 0.0.1-SNAPSHOT + +``` + +Dependencies: + +* gson 2.2.4 +* guava 16.0.1 +* joda-time 2.3 + +## Creating an Activity statement + +```java +import static com.ibm.common.activitystreams.Makers.activity; +import static com.ibm.common.activitystreams.Makers.object; + +public class Example { + + public static void main(String... args) { + + Activity activity = + activity() + .actor(object("person").id("acct:joe@example.org")) + .object(object("note").content("my note")) + .verb("post") + .get(); + + } + +} +``` + +The library uses a consistent fluent generator pattern to construct all +object types. Once created, objects are immutable. + +## Serializing and Parsing objects + +The library has one job: to make it easy to create and parse Activity +Stream objects that are conformant to the Activity Streams 2.0 +specification. + +The IO object is used to serialize and parse Activity Stream objects. +IO objects are threadsafe and immutable so they can be safely created +once and stored as a static final constant. + +```java +package com.ibm.common.activitystreams; + +import static com.ibm.common.activitystreams.IO.makeDefaultPrettyPrint; +import static com.ibm.common.activitystreams.Makers.activity; +import static com.ibm.common.activitystreams.Makers.object; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +public class Test { + + private static final IO io = makeDefaultPrettyPrint(); + + public static void main(String... args) { + + Activity activity = + activity() + .actor(object("person").id("acct:joe@example.org")) + .object(object("note").content("my note")) + .verb("post") + .get(); + + ByteArrayOutputStream out = + new ByteArrayOutputStream(); + + // Write it out + activity.writeTo(out, io); + + ByteArrayInputStream in = + new ByteArrayInputStream(out.toByteArray()); + + // Read it in + activity = io.readAsActivity(in); + + // Access the properties + TypeValue tv = activity.verb(); + System.out.println(tv.id()); // "post" + + ASObject actor = activity.firstActor(); + System.out.println(actor.id()); // "acct:joe@example.org" + + for (ASObject object : activity.object()) + System.out.println(object.objectType().id()) // "note" + + // iterate all properties + for (String key : activity) + System.out.println(activity.get(key)); + + } + +} + +``` + diff --git a/actions/pom.xml b/actions/pom.xml new file mode 100644 index 0000000..055246c --- /dev/null +++ b/actions/pom.xml @@ -0,0 +1,138 @@ + + 4.0.0 + + com.ibm.common + activitystreams + 0.0.1-SNAPSHOT + + activitystreams-actions + Activity Streams 2.0 - Actions + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + UTF-8 + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + UTF-8 + UTF-8 + UTF-8 + -XDignore.symbol.file + public + + http://www.joda.org/joda-time/apidocs + http://docs.guava-libraries.googlecode.com/git-history/v16.0.1/javadoc/ + + + + + + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + maven-jar-plugin + 2.3.1 + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + + org.apache.felix + maven-bundle-plugin + 2.3.7 + true + + + bundle-manifest + process-classes + + manifest + + + + + + com.ibm.common.activitystreams.actions.* + + com.ibm.common.activitystreams.*, + com.google.gson.*, + com.google.common.*, + org.joda.time.* + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.2.2 + + + assembly.xml + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.apache.felix + maven-bundle-plugin + [2.3.7,) + + manifest + + + + + + + + + + + + + + + + + com.ibm.common + activitystreams-core + 0.0.1-SNAPSHOT + + + \ No newline at end of file diff --git a/actions/src/examples/com/ibm/common/activitystreams/actions/example/Actions.java b/actions/src/examples/com/ibm/common/activitystreams/actions/example/Actions.java new file mode 100755 index 0000000..a7606dd --- /dev/null +++ b/actions/src/examples/com/ibm/common/activitystreams/actions/example/Actions.java @@ -0,0 +1,180 @@ + package com.ibm.common.activitystreams.actions.example; + +import static com.ibm.common.activitystreams.Makers.object; +import static com.ibm.common.activitystreams.actions.ActionMakers.METHOD_POST; +import static com.ibm.common.activitystreams.actions.ActionMakers.TARGET_DIALOG; +import static com.ibm.common.activitystreams.actions.ActionMakers.htmlForm; +import static com.ibm.common.activitystreams.actions.ActionMakers.httpAction; +import static com.ibm.common.activitystreams.actions.ActionMakers.intentAction; +import static com.ibm.common.activitystreams.actions.ActionMakers.parameter; +import static com.ibm.common.activitystreams.actions.ActionMakers.staticEmbedAction; +import static com.ibm.common.activitystreams.actions.ActionMakers.styles; +import static com.ibm.common.activitystreams.actions.ActionMakers.typedPayload; +import static com.ibm.common.activitystreams.actions.ActionMakers.urlTemplate; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.ActionsValue; +import com.ibm.common.activitystreams.IO; +import com.ibm.common.activitystreams.LinkValue; +import com.ibm.common.activitystreams.TypeValue; +import com.ibm.common.activitystreams.ValueType; +import com.ibm.common.activitystreams.actions.ActionsModule; +import com.ibm.common.activitystreams.actions.EmbedActionHandler; +import com.ibm.common.activitystreams.actions.HttpActionHandler; +import com.ibm.common.activitystreams.actions.Parameter; +import com.ibm.common.activitystreams.actions.ParametersValue; +import com.ibm.common.activitystreams.actions.StylesValue; +import com.ibm.common.activitystreams.actions.UrlTemplate; + +/** + */ +public final class Actions { + + private Actions() {} + + private static final IO io = + IO.makeDefaultPrettyPrint(ActionsModule.instance); + + // Set up some common static action handlers... + private static final ASObject httpAction = + httpAction("http://example.org", METHOD_POST) + .auth( + "oauth2", + object() + .set("scopes", + object() + .set( + "scope.key.1", + object().set("description", "foo")))) + .expects( + htmlForm() + .parameter("foo", "http://example.org/FooProperty")) + .expects( + typedPayload("text/json") + .schema("http://foo") + .type("http://schema.org/Foo")) + .returns(typedPayload("text/json")) + .returns(typedPayload("text/html")) + .requires( + "urn:example:some:feature", + "urn:example:some:other:feature") + .prefers( + "urn:example:some:optional-feature") + .target(TARGET_DIALOG) + .get(); + private static final ASObject embedAction = + staticEmbedAction( + "text/plain", + "this is a pretty useless handler") + .style( + styles("print") + .set("height", "100px") + .set("width", "100px") + .get(), + styles("screen") + .set("width", "200px") + .set("height", "200px") + .get() + ) + .get(); + private static final ASObject urlTemplate = + urlTemplate() + .template("http://foo{/path}{?query}") + .parameter("path", "http://example.org/types#string") + .parameter("query", "http://example.org/types#string") + .parameter( + "foo", + parameter() + .required() + .repeated() + .formatInt32() + .minimum(1) + .maximum(3) + .enumVals(1,2,3) + .step(1) + .formatUint32() + .placeholder("(1, 2 or 3)") + ) + .get(); + private static final ASObject intent = + intentAction() + .mediaType("text/plain") + .url("app://com.example.MoviePlayer") + .get(); + + /** + * Method main. + * @param args String[] + * @throws Exception + */ + public static void main(String... args) throws Exception { + + ByteArrayOutputStream out = + new ByteArrayOutputStream(); + + ASObject obj = + object() + .action( + "view", + httpAction, + embedAction, + urlTemplate, + intent) + .action( + "share", + "http://example.org/foo") + .get(); + + io.write(obj,System.out); + + System.out.println("\n\n"); + + io.write( + obj, + out); + + obj = io.read(new ByteArrayInputStream(out.toByteArray())); + + ActionsValue actions = obj.actions(); + for (LinkValue lv : actions.get("view")) { + if (lv instanceof HttpActionHandler) { + HttpActionHandler httpAction = (HttpActionHandler) lv; + System.out.println("Auth: " + httpAction.auth()); + System.out.println("Method: " + httpAction.method()); + System.out.println("URL: " + httpAction.url()); + System.out.println("Target: " + httpAction.target()); + System.out.println("Returns: " + httpAction.returns()); + System.out.println("Expects: " + httpAction.expects()); + System.out.println("Requires: " + httpAction.requires()); + System.out.println("Prefers: " + httpAction.prefers()); + } else if (lv instanceof EmbedActionHandler) { + EmbedActionHandler embed = (EmbedActionHandler) lv; + for (StylesValue style : embed.styles("print")) { + System.out.println(style.get("height")); + System.out.println(style.get("width")); + } + } else if (lv instanceof UrlTemplate) { + UrlTemplate template = (UrlTemplate) lv; + System.out.println(template.template()); + ParametersValue pv = template.parameters(); + for (String s : pv) { + TypeValue param = pv.get(s); + if (param.valueType() == ValueType.SIMPLE) { + System.out.println(s + " = " + param.id()); + } else { + if (param instanceof Parameter) { + Parameter par = (Parameter) param; + System.out.println(s + " = " + par.id() + ", " + par.required() + ", " + par.format() + ", " + par.enumVals()); + } else { + System.out.println(s + " = " + param); + } + } + } + } + } + } + +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/ActionHandler.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/ActionHandler.java new file mode 100755 index 0000000..615bd4c --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/ActionHandler.java @@ -0,0 +1,343 @@ +package com.ibm.common.activitystreams.actions; + +import java.io.Serializable; + +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.LinkValue; + +/** + */ +public abstract class ActionHandler + extends ASObject + implements Serializable { + + /** + */ + @SuppressWarnings("unchecked") + public static abstract class Builder> + extends ASObject.AbstractBuilder { + + private final Authentication.Builder auth = + Authentication.make(); + + /** + * Method confirm. + * @return B + */ + public B confirm() { + return confirm(true); + } + + /** + * Method confirm. + * @param on boolean + * @return B + */ + public B confirm(boolean on) { + set("confirm", on); + return (B)this; + } + + /** + * Method context. + * @param obj ASObject + * @return B + */ + public B context(ASObject obj) { + set("context", obj); + return (B)this; + } + + /** + * Method context. + * @param obj Supplier + * @return B + */ + public B context(Supplier obj) { + return context(obj.get()); + } + + /** + * Method requires. + * @param iri String + * @return B + */ + public B requires(String iri, String... iris) { + requires(LinkValue.SimpleLinkValue.make(iri)); + if (iris != null) + for (String i : iris) + requires(i); + return (B)this; + } + + /** + * Method requires. + * @param lv LinkValue + * @return B + */ + public B requires(LinkValue lv, LinkValue... lvs) { + link("requires", lv); + if (lvs != null) + for (LinkValue i : lvs) + requires(i); + return (B)this; + } + + /** + * Method requires. + * @param lv Supplier + * @return B + */ + public B requires(Supplier lv) { + return requires(lv.get()); + } + + /** + * Method prefers. + * @param iri String + * @return B + */ + public B prefers(String iri, String... iris) { + prefers(LinkValue.SimpleLinkValue.make(iri)); + if (iris != null) + for (String i : iris) + prefers(i); + return (B) this; + } + + /** + * Method prefers. + * @param lv LinkValue + * @return B + */ + public B prefers(LinkValue lv, LinkValue... lvs) { + link("prefers", lv); + if (lvs != null) + for (LinkValue l : lvs) + prefers(l); + return (B)this; + } + + /** + * Method prefers. + * @param lv Supplier + * @return B + */ + public B prefers(Supplier lv) { + return prefers(lv.get()); + } + + /** + * Method expects. + * @param iri String + * @return B + */ + public B expects(String iri, String... iris) { + expects(LinkValue.SimpleLinkValue.make(iri)); + if (iris != null) + for (String i : iris) + expects(i); + return (B)this; + } + + /** + * Method expects. + * @param tv LinkValue + * @return B + */ + public B expects(LinkValue tv, LinkValue... lvs) { + link("expects", tv); + if (lvs != null) + for (LinkValue lv : lvs) + expects(lv); + return (B)this; + } + + /** + * Method expects. + * @param tv Supplier + * @return B + */ + public B expects(Supplier tv) { + return expects(tv.get()); + } + + /** + * Method returns. + * @param iri String + * @return B + */ + public B returns(String iri, String... iris) { + returns(LinkValue.SimpleLinkValue.make(iri)); + if (iris != null) + for (String i : iris) + returns(i); + return (B)this; + } + + /** + * Method returns. + * @param tv LinkValue + * @return B + */ + public B returns(LinkValue tv, LinkValue... lvs) { + link("returns", tv); + if (lvs != null) + for (LinkValue lv : lvs) + returns(lv); + return (B)this; + } + + /** + * Method returns. + * @param tv Supplier + * @return B + */ + public B returns(Supplier tv) { + return returns(tv.get()); + } + + /** + * Method auth. + * @param key String + * @param obj ASObject + * @return B + */ + public B auth(String key, ASObject obj) { + auth.set(key, obj); + return (B)this; + } + + /** + * Method auth. + * @param key String + * @param obj Supplier + * @return B + */ + public B auth(String key, Supplier obj) { + return auth(key, obj.get()); + } + + /** + * Method get. + * @return A + * @see com.google.common.base.Supplier#get() + */ + public A get() { + if (auth.notEmpty()) + set("auth", auth.get()); + return actualGet(); + } + + /** + * Method actualGet. + * @return A + */ + protected abstract A actualGet(); + } + + /** + * Constructor for ActionHandler. + * @param builder Builder + */ + protected ActionHandler(Builder builder) { + super(builder); + } + + /** + * Method confirm. + * @return boolean + */ + public boolean confirm() { + return this.getBoolean("confirm"); + } + + /** + * Method context. + * @return A + */ + public A context() { + return this.get("context"); + } + + /** + * Method expects. + * @return Iterable + */ + public Iterable expects() { + return this.links("expects"); + } + + public Iterable expects(Predicate filter) { + return this.links("expects", filter); + } + + /** + * Method requires. + * @return Iterable + */ + public Iterable requires() { + return this.links("requires"); + } + + public Iterable requires(Predicate filter) { + return this.links("requires", filter); + } + + /** + * Method prefers. + * @return Iterable + */ + public Iterable prefers() { + return this.links("prefers"); + } + + public Iterable prefers(Predicate filter) { + return this.links("prefers", filter); + } + + /** + * Method returns. + * @return Iterable + */ + public Iterable returns() { + return this.links("returns"); + } + + public Iterable returns(Predicate filter) { + return this.links("returns", filter); + } + + /** + * Method auth. + * @return Authentication + */ + public Authentication auth() { + return this.get("auth"); + } + + /** + * Method hasAuth. + * @param key String + * @return boolean + */ + public boolean hasAuth(String key) { + Authentication auth = auth(); + return auth != null ? + auth.has(key) : false; + } + + /** + * Method auth. + * @param key String + * @return A + */ + @SuppressWarnings("unchecked") + public A auth(String key) { + Authentication auth = auth(); + return auth != null ? + (A)auth.get(key) : null; + } +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/ActionMakers.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/ActionMakers.java new file mode 100755 index 0000000..21c9686 --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/ActionMakers.java @@ -0,0 +1,205 @@ +package com.ibm.common.activitystreams.actions; + +import static com.ibm.common.activitystreams.Makers.object; + +import com.ibm.common.activitystreams.ASObject; + +/** + */ +public final class ActionMakers { + + public static final String TARGET_NONE = "NONE"; + public static final String TARGET_DEFAULT = "DEFAULT"; + public static final String TARGET_NEW = "NEW"; + public static final String TARGET_CURRENT = "CURRENT"; + public static final String TARGET_TAB = "TAB"; + public static final String TARGET_DIALOG = "DIALOG"; + public static final String TARGET_MODALDIALOG = "MODALDIALOG"; + public static final String TARGET_FLOAT = "FLOAT"; + public static final String TARGET_SIDEBAR = "SIDEBAR"; + + public static final String METHOD_GET = "GET"; + public static final String METHOD_POST = "POST"; + public static final String METHOD_PUT = "PUT"; + public static final String METHOD_DELETE = "DELETE"; + public static final String METHOD_PATCH = "PATCH"; + + private ActionMakers() {} + + /** + * Method application. + * @return ASObject.Builder + */ + public static ASObject.Builder application() { + return object("application"); + } + + /** + * Method service. + * @return ASObject.Builder + */ + public static ASObject.Builder service() { + return object("service"); + } + + /** + * Method styles. + * @return StylesValue.Builder + */ + public static StylesValue.Builder styles() { + return StylesValue.make(); + } + + /** + * Method styles. + * @param media String + * @return StylesValue.Builder + */ + public static StylesValue.Builder styles(String media) { + return styles().media(media); + } + + /** + * Method httpAction. + * @return HttpActionHandler.Builder + */ + public static HttpActionHandler.Builder httpAction() { + return HttpActionHandler.makeHttpActionHandler(); + } + + /** + * Method httpAction. + * @param url String + * @return HttpActionHandler.Builder + */ + public static HttpActionHandler.Builder httpAction(String url) { + return httpAction().url(url); + } + + /** + * Method httpAction. + * @param url String + * @param method String + * @return HttpActionHandler.Builder + */ + public static HttpActionHandler.Builder httpAction( + String url, + String method) { + return httpAction() + .url(url) + .method(method); + } + + /** + * Method embedAction. + * @return EmbedActionHandler.Builder + */ + public static EmbedActionHandler.Builder embedAction() { + return EmbedActionHandler.makeEmbedActionHandler(); + } + + /** + * Method embedAction. + * @param url String + * @return EmbedActionHandler.Builder + */ + public static EmbedActionHandler.Builder embedAction(String url) { + return embedAction().url(url); + } + + /** + * Method embedAction. + * @param url String + * @param mediaType String + * @return EmbedActionHandler.Builder + */ + public static EmbedActionHandler.Builder embedAction( + String url, + String mediaType) { + return embedAction(url).mediaType(mediaType); + } + + /** + * Method staticEmbedAction. + * @param mediaType String + * @param content String + * @return EmbedActionHandler.Builder + */ + public static EmbedActionHandler.Builder staticEmbedAction( + String mediaType, + String content) { + return embedAction().mediaType(mediaType).content(content); + } + + /** + * Method intentAction. + * @return IntentActionHandler.Builder + */ + public static IntentActionHandler.Builder intentAction() { + return IntentActionHandler.makeIntentActionHandler(); + } + + /** + * Method intentAction. + * @param url String + * @return IntentActionHandler.Builder + */ + public static IntentActionHandler.Builder intentAction(String url) { + return intentAction().url(url); + } + + /** + * Method htmlForm. + * @return HtmlForm.Builder + */ + public static HtmlForm.Builder htmlForm() { + return HtmlForm.makeHtmlForm(); + } + + /** + * Method typedPayload. + * @param mediaType String + * @return TypedPayload.Builder + */ + public static TypedPayload.Builder typedPayload(String mediaType) { + return TypedPayload.makeTypedPayload(mediaType); + } + + public static TypedPayload.Builder typedPayload() { + return TypedPayload.make(); + } + + /** + * Method urlTemplate. + * @return UrlTemplate.Builder + */ + public static UrlTemplate.Builder urlTemplate() { + return UrlTemplate.makeUrlTemplate(); + } + + /** + * Method urlTemplate. + * @param template String + * @return UrlTemplate.Builder + */ + public static UrlTemplate.Builder urlTemplate(String template) { + return urlTemplate().template(template); + } + + /** + * Method parameter. + * @return Parameter.Builder + */ + public static Parameter.Builder parameter() { + return Parameter.makeParameter(); + } + + /** + * Method parameter. + * @param id String + * @return Parameter.Builder + */ + public static Parameter.Builder parameter(String id) { + return parameter().id(id); + } +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/ActionObjectAdapter.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/ActionObjectAdapter.java new file mode 100644 index 0000000..786aaeb --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/ActionObjectAdapter.java @@ -0,0 +1,85 @@ +package com.ibm.common.activitystreams.actions; + +import java.lang.reflect.Type; + +import com.google.common.collect.ImmutableSet; +import com.ibm.common.activitystreams.ASObject.AbstractBuilder; +import com.ibm.common.activitystreams.internal.ASObjectAdapter; +import com.ibm.common.activitystreams.internal.Model; +import com.ibm.common.activitystreams.internal.Schema; + +public final class ActionObjectAdapter + extends ASObjectAdapter { + + ActionObjectAdapter(Schema schema) { + super(schema); + } + + private static final ImmutableSet> knownTypes = + ImmutableSet.>of( + HttpActionHandler.class, + IntentActionHandler.class, + EmbedActionHandler.class, + HtmlForm.class, + UrlTemplate.class, + TypedPayload.class + ); + + @Override + protected boolean knowsType(Type type) { + if (super.knowsType(type)) + return true; + return knownTypes.contains(type); + } + + @Override + protected AbstractBuilder builderFor(Type type) { + if (super.knowsType(type)) + return super.builderFor(type); + if (type == HttpActionHandler.class) + return ActionMakers.httpAction(); + else if (type == IntentActionHandler.class) + return ActionMakers.intentAction(); + else if (type == EmbedActionHandler.class) + return ActionMakers.embedAction(); + else if (type == HtmlForm.class) + return ActionMakers.htmlForm(); + else if (type == UrlTemplate.class) + return ActionMakers.urlTemplate(); + else if (type == TypedPayload.class) + return ActionMakers.typedPayload(); + else return null; + } + + @Override + protected Model modelFor(Type type) { + if (super.knowsType(type)) + return super.modelFor(type); + if (type == HttpActionHandler.class) + return schema().forObjectClassOrType( + HttpActionHandler.Builder.class, + "HttpActionHandler"); + else if (type == IntentActionHandler.class) + return schema().forObjectClassOrType( + IntentActionHandler.Builder.class, + "IntentActionHandler"); + else if (type == EmbedActionHandler.class) + return schema().forObjectClassOrType( + EmbedActionHandler.Builder.class, + "EmbedActionHandler"); + else if (type == HtmlForm.class) + return schema().forObjectClassOrType( + HtmlForm.Builder.class, + "HtmlForm"); + else if (type == UrlTemplate.class) + return schema().forObjectClassOrType( + UrlTemplate.Builder.class, + "UrlTemplate"); + else if (type == TypedPayload.class) + return schema().forObjectClassOrType( + TypedPayload.Builder.class, + "TypedPayload"); + else return null; + } + +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/ActionsModule.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/ActionsModule.java new file mode 100644 index 0000000..8b411a4 --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/ActionsModule.java @@ -0,0 +1,82 @@ +package com.ibm.common.activitystreams.actions; + +import static com.ibm.common.activitystreams.actions.Adapters.AUTH; +import static com.ibm.common.activitystreams.actions.Adapters.PARAMETERS; +import static com.ibm.common.activitystreams.actions.Adapters.STYLES; + +import com.ibm.common.activitystreams.IO.Builder; +import com.ibm.common.activitystreams.internal.Model; +import com.ibm.common.activitystreams.internal.Schema; +import com.ibm.common.activitystreams.util.Module; + +public final class ActionsModule + implements Module { + + public static final Module instance = new ActionsModule(); + + @Override + public void apply(Builder builder, Schema schema) { + + ActionObjectAdapter base = + new ActionObjectAdapter(schema); + + // Register Adapters + builder.hierarchicalAdapter(ActionHandler.class,base) + .hierarchicalAdapter(HttpActionHandler.class,base) + .hierarchicalAdapter(IntentActionHandler.class,base) + .hierarchicalAdapter(EmbedActionHandler.class,base) + .hierarchicalAdapter(HtmlForm.class,base) + .hierarchicalAdapter(UrlTemplate.class,base) + .hierarchicalAdapter(TypedPayload.class,base) + .hierarchicalAdapter(Parameter.class,base) + .hierarchicalAdapter(ParametersValue.class, PARAMETERS) + .hierarchicalAdapter(Authentication.class, AUTH) + .hierarchicalAdapter(StylesValue.class, STYLES); + } + + @Override + public void apply(Schema.Builder builder) { + builder.map("HtmlForm", withParameters.template(HtmlForm.class, HtmlForm.Builder.class)) + .map("parameter", parameter) + .map("TypedPayload", typedPayload) + .map("UrlTemplate", withParameters.template(UrlTemplate.class, UrlTemplate.Builder.class)) + .map("HttpActionHandler", actionHandler.template(HttpActionHandler.class, HttpActionHandler.Builder.class)) + .map("IntentActionHandler", actionHandler.template(IntentActionHandler.class, IntentActionHandler.Builder.class)) + .map("EmbedActionHandler", actionHandler.template(EmbedActionHandler.class, EmbedActionHandler.Builder.class)); + } + + public final static Model actionHandler = + Model + .make("object") + .linkValue( + "expects", + "returns", + "requires", + "prefers") + .object("context") + .as("auth", Authentication.class) + .as("style", StylesValue.class) + .get(); + + + public final static Model withParameters = + Model + .make("object") + .as("parameters", ParametersValue.class) + .get(); + + public final static Model typedPayload = + Model + .make("object") + .linkValue("schema") + .typeValue("type") + .get(); + + public final static Model parameter = + Model + .make("object") + .typeValue("type") + .type(Parameter.class, Parameter.Builder.class) + .get(); + +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/Adapters.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/Adapters.java new file mode 100644 index 0000000..f394a06 --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/Adapters.java @@ -0,0 +1,46 @@ +package com.ibm.common.activitystreams.actions; + +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.TypeValue; +import com.ibm.common.activitystreams.actions.StylesValue.Builder; +import com.ibm.common.activitystreams.internal.Adapter; +import com.ibm.common.activitystreams.util.AbstractDictionaryObjectAdapter; + +final class Adapters { + + private Adapters() {} + + static final Adapter AUTH = + new AbstractDictionaryObjectAdapter + (ASObject.class) { + @Override + protected Authentication.Builder builder() { + return Authentication.make(); + } + }; + + static final Adapter PARAMETERS = + new AbstractDictionaryObjectAdapter + (TypeValue.class) { + @Override + protected ParametersValue.Builder builder() { + return ParametersValue.make(); + } + }; + + static final Adapter STYLES = + new AbstractDictionaryObjectAdapter + (String.class) { + @Override + protected Builder builder() { + return StylesValue.make(); + } + }; + +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/Authentication.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/Authentication.java new file mode 100755 index 0000000..5e68adf --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/Authentication.java @@ -0,0 +1,83 @@ +package com.ibm.common.activitystreams.actions; + +import java.io.Serializable; +import java.util.Map; + +import com.google.common.collect.ImmutableMap; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.util.AbstractDictionaryObject; + +/** + */ +public final class Authentication + extends AbstractDictionaryObject { + + /** + * Method make. + * @return Builder + */ + public static Builder make() { + return new Builder(); + } + + /** + */ + public static final class Builder + extends AbstractDictionaryObject.AbstractBuilder< + ASObject,Authentication,Builder> { + + /** + * Method get. + * @return Authentication + * @see com.google.common.base.Supplier#get() + */ + public Authentication get() { + return new Authentication(this); + } + + } + + /** + * Constructor for Authentication. + * @param builder Builder + */ + protected Authentication(Builder builder) { + super(builder); + } + + /** + * Method get. + * @param key String + * @return A + */ + @SuppressWarnings("unchecked") + public A get(String key) { + return (A)this.getSingle(key); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + implements Serializable { + private static final long serialVersionUID = -1975376657749952999L; + private ImmutableMap map; + SerializedForm(Authentication obj) { + ImmutableMap.Builder builder = + ImmutableMap.builder(); + for (String key : obj) + builder.put(key, obj.get(key)); + this.map = builder.build(); + } + + Object readResolve() + throws java.io.ObjectStreamException { + Authentication.Builder builder = + Authentication.make(); + for (Map.Entry entry : map.entrySet()) + builder.set(entry.getKey(), (ASObject) entry.getValue()); + return builder.get(); + } + } +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/EmbedActionHandler.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/EmbedActionHandler.java new file mode 100755 index 0000000..a3d26ac --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/EmbedActionHandler.java @@ -0,0 +1,213 @@ +package com.ibm.common.activitystreams.actions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.getFirst; +import static com.google.common.collect.Iterables.size; + +import java.io.ObjectStreamException; +import java.io.Serializable; + +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; + +/** + */ +public class EmbedActionHandler + extends ActionHandler + implements Serializable { + + /** + * Method makeEmbedActionHandler. + * @return Builder + */ + public static Builder makeEmbedActionHandler() { + return new Builder(); + } + + /** + */ + public static final class Builder + extends AbstractBuilder { + + public Builder() { + super("EmbedActionHandler"); + } + + /** + * Method getActual. + * @return EmbedActionHandler + */ + protected EmbedActionHandler getActual() { + return new EmbedActionHandler(this); + } + + } + + /** + */ + @SuppressWarnings("unchecked") + public static abstract class AbstractBuilder> + extends ActionHandler.Builder { + + private boolean styleset = false; + private static ImmutableList.Builder styles = + ImmutableList.builder(); + + /** + * Constructor for AbstractBuilder. + * @param objectType String + */ + protected AbstractBuilder(String objectType) { + objectType(objectType); + } + + /** + * Method target. + * @param target String + * @return B + */ + public B target(String target) { + set("target", target); + return (B)this; + } + + /** + * Method style. + * @param style StylesValue + * @return B + */ + public B style(StylesValue style) { + styleset = true; + styles.add(style); + return (B)this; + } + + /** + * Method style. + * @param style Supplier + * @return B + */ + public B style(Supplier style) { + return style(style.get()); + } + + /** + * Method style. + * @param styles StylesValue[] + * @return B + */ + public B style(StylesValue... styles) { + for (StylesValue s : styles) + style(s); + return (B)this; + } + + /** + * Method style. + * @param styles Supplier[] + * @return B + */ + public B style(Supplier... styles) { + for (Supplier s : styles) + style(s); + return (B)this; + } + + /** + * Method actualGet. + * @return A + */ + protected final A actualGet() { + if (styleset) { + ImmutableList val = styles.build(); + if (size(val) == 1) { + set("style", getFirst(val,null)); + } else { + set("style", val); + } + } + return getActual(); + } + + /** + * Method getActual. + * @return A + */ + protected abstract A getActual(); + } + + /** + * Constructor for EmbedActionHandler. + * @param builder AbstractBuilder + */ + protected EmbedActionHandler(AbstractBuilder builder) { + super(builder); + } + + /** + * Method styles. + * @return Iterable + */ + @SuppressWarnings("unchecked") + public Iterable styles() { + Object styles = get("style"); + if (styles instanceof StylesValue) + return ImmutableList.of((StylesValue)styles); + else if (styles instanceof Iterable) + return (Iterable)styles; + else return ImmutableList.of(); + } + + /** + * Method styles. + * @param media String + * @return Iterable + */ + public Iterable styles(final String media) { + checkNotNull(media); + return styles(new Predicate() { + public boolean apply(StylesValue style) { + return media.equalsIgnoreCase(style.media()); + } + }); + } + + /** + * Method styles. + * @param matcher Predicate + * @return Iterable + */ + public Iterable styles(Predicate matcher) { + return filter(styles(), matcher); + } + + /** + * Method target. + * @return String + */ + public String target() { + return getString( + "target", + ActionMakers.TARGET_DEFAULT); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(EmbedActionHandler obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected EmbedActionHandler.Builder builder() { + return ActionMakers.embedAction(); + } + } +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/HtmlForm.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/HtmlForm.java new file mode 100755 index 0000000..520c19d --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/HtmlForm.java @@ -0,0 +1,161 @@ +package com.ibm.common.activitystreams.actions; + +import static com.ibm.common.activitystreams.Makers.object; +import static com.ibm.common.activitystreams.Makers.type; + +import java.io.ObjectStreamException; + +import com.google.common.base.Supplier; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.TypeValue; + +/** + */ +public final class HtmlForm + extends ASObject { + + /** + * Method makeHtmlForm. + * @return Builder + */ + public static Builder makeHtmlForm() { + return new Builder(); + } + + /** + */ + public static final class Builder + extends ASObject.AbstractBuilder { + + private final ParametersValue.Builder params = + ParametersValue.make(); + + private Builder() { + objectType("HtmlForm"); + mediaType("application/x-www-form-urlencoded"); + } + + /** + * Method parameter. + * @param name String + * @param iri String + * @return Builder + */ + public Builder parameter( + String name, + String iri) { + params.set(name, type(iri)); + return this; + } + + /** + * Method parameter. + * @param name String + * @param iri String + * @param required boolean + * @return Builder + */ + public Builder parameter( + String name, + String iri, + boolean required) { + return parameter( + name, + object() + .id(iri) + .set("required", required)); + } + + /** + * Method parameter. + * @param name String + * @param iri String + * @param required boolean + * @param value Object + * @return Builder + */ + public Builder parameter( + String name, + String iri, + boolean required, + Object value) { + return parameter( + name, + object() + .id(iri) + .set("required", required) + .set("value", value)); + } + + /** + * Method parameter. + * @param name String + * @param lv TypeValue + * @return Builder + */ + public Builder parameter( + String name, + TypeValue lv) { + params.set(name, lv); + return this; + } + + /** + * Method parameter. + * @param name String + * @param lv Supplier + * @return Builder + */ + public Builder parameter( + String name, + Supplier lv) { + return parameter(name, lv.get()); + } + + /** + * Method get. + * @return HtmlForm + * @see com.google.common.base.Supplier#get() + */ + public HtmlForm get() { + if (params.notEmpty()) + set("parameters", params.get()); + return new HtmlForm(this); + } + + } + + /** + * Constructor for HtmlForm. + * @param builder Builder + */ + private HtmlForm(Builder builder) { + super(builder); + } + + /** + * Method parameters. + * @return ParametersValue + */ + public ParametersValue parameters() { + return this.get("parameters"); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(HtmlForm obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected HtmlForm.Builder builder() { + return ActionMakers.htmlForm(); + } + } +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/HttpActionHandler.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/HttpActionHandler.java new file mode 100755 index 0000000..c6165d3 --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/HttpActionHandler.java @@ -0,0 +1,116 @@ +package com.ibm.common.activitystreams.actions; + +import java.io.ObjectStreamException; + + +/** + */ +public class HttpActionHandler + extends ActionHandler { + + /** + * Method makeHttpActionHandler. + * @return Builder + */ + public static Builder makeHttpActionHandler() { + return new Builder(); + } + + /** + */ + public static final class Builder + extends AbstractBuilder { + + public Builder() { + super("HttpActionHandler"); + } + + /** + * Method actualGet. + * @return HttpActionHandler + */ + protected HttpActionHandler actualGet() { + return new HttpActionHandler(this); + } + + } + + /** + */ + @SuppressWarnings("unchecked") + public static abstract class AbstractBuilder + > + extends ActionHandler.Builder { + /** + * Constructor for AbstractBuilder. + * @param objectType String + */ + protected AbstractBuilder(String objectType) { + objectType(objectType); + } + + /** + * Method method. + * @param method String + * @return B + */ + public B method(String method) { + set("method", method); + return (B)this; + } + + /** + * Method target. + * @param target String + * @return B + */ + public B target(String target) { + set("target", target); + return (B)this; + } + } + + /** + * Constructor for HttpActionHandler. + * @param builder AbstractBuilder + */ + protected HttpActionHandler(AbstractBuilder builder) { + super(builder); + } + + /** + * Method method. + * @return String + */ + public String method() { + return this.getString("method"); + } + + /** + * Method target. + * @return String + */ + public String target() { + return has("target") ? + this.get("target") : + ActionMakers.TARGET_DEFAULT; + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(HttpActionHandler obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected HttpActionHandler.Builder builder() { + return ActionMakers.httpAction(); + } + } +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/IntentActionHandler.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/IntentActionHandler.java new file mode 100755 index 0000000..8716559 --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/IntentActionHandler.java @@ -0,0 +1,77 @@ +package com.ibm.common.activitystreams.actions; + +import java.io.ObjectStreamException; + + +/** + */ +public class IntentActionHandler + extends ActionHandler { + + /** + * Method makeIntentActionHandler. + * @return Builder + */ + public static Builder makeIntentActionHandler() { + return new Builder(); + } + + /** + */ + public static final class Builder + extends AbstractBuilder { + + public Builder() { + super("IntentActionHandler"); + } + + /** + * Method actualGet. + * @return IntentActionHandler + */ + protected IntentActionHandler actualGet() { + return new IntentActionHandler(this); + } + + } + + /** + */ + public static abstract class AbstractBuilder + > + extends ActionHandler.Builder { + /** + * Constructor for AbstractBuilder. + * @param objectType String + */ + protected AbstractBuilder(String objectType) { + objectType(objectType); + } + } + + /** + * Constructor for IntentActionHandler. + * @param builder AbstractBuilder + */ + protected IntentActionHandler(AbstractBuilder builder) { + super(builder); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(IntentActionHandler obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected IntentActionHandler.Builder builder() { + return ActionMakers.intentAction(); + } + } +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/Parameter.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/Parameter.java new file mode 100755 index 0000000..1491124 --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/Parameter.java @@ -0,0 +1,949 @@ +package com.ibm.common.activitystreams.actions; + +import java.io.ObjectStreamException; +import java.util.regex.Pattern; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.NLV; +import com.ibm.common.activitystreams.TypeValue; + +/** + */ +public class Parameter + extends ASObject { + + /** + */ + public static enum Format { + OTHER(null), + BOOLEAN("boolean"), + INT32("int32"), + INT64("int64"), + UINT32("uint32"), + UINT64("uint64"), + DOUBLE("double"), + FLOAT("float"), + BYTE("byte"), + DATE("date"), + DATETIME("date-time"), + DURATION("duration"), + LANG("lang"), + URI("uri"), + IRI("iri") + ; + + private final String label; + + /** + * Constructor for Format. + * @param label String + */ + Format(String label) { + this.label = label; + } + + /** + * Method select. + * @param label String + * @return Format + */ + private static Format select(String label) { + try { + if (label == null) + return Format.OTHER; + label = label.toUpperCase().replaceAll("-", ""); + return valueOf(label); + } catch (Throwable t) { + return Format.OTHER; + } + } + } + + /** + * Method makeParameter. + * @return Builder + */ + public static Builder makeParameter() { + return new Builder(); + } + + /** + */ + public static final class Builder + extends AbstractBuilder { + + /** + * Method get. + * @return Parameter + * @see com.google.common.base.Supplier#get() + */ + public Parameter get() { + return new Parameter(this); + } + + } + + /** + */ + public static abstract class AbstractBuilder

> + extends ASObject.AbstractBuilder { + + protected AbstractBuilder() { + objectType("parameter"); + } + + /** + * Method placeholder. + * @param val String + * @return B + */ + public B placeholder(String val) { + return this._nlv("placeholder", val); + } + + /** + * Method placeholder. + * @param nlv NLV + * @return B + */ + public B placeholder(NLV nlv) { + return this._nlv("placeholder", nlv); + } + + /** + * Method placeholder. + * @param nlv Supplier + * @return B + */ + public B placeholder(Supplier nlv) { + return this._nlv("placeholder", nlv); + } + + /** + * Method placeholder. + * @param lang String + * @param val String + * @return B + */ + public B placeholder(String lang, String val) { + return this._nlv("placeholder", lang, val); + } + + /** + * Method type. + * @param iri String + * @return B + */ + public B type(String iri) { + return type(TypeValue.SimpleTypeValue.make(iri)); + } + + /** + * Method type. + * @param tv TypeValue + * @return B + */ + public B type(TypeValue tv) { + return set("type", tv); + } + + /** + * Method type. + * @param tv Supplier + * @return B + */ + public B type(Supplier tv) { + return type(tv.get()); + } + + /** + * Method required. + * @param on boolean + * @return B + */ + public B required(boolean on) { + return set("required", on); + } + + /** + * Method repeated. + * @param on boolean + * @return B + */ + public B repeated(boolean on) { + return set("repeated", on); + } + + /** + * Method required. + * @return B + */ + public B required() { + return required(true); + } + + /** + * Method repeated. + * @return B + */ + public B repeated() { + return repeated(true); + } + + /** + * Method value. + * @param value Object + * @return B + */ + public B value(Object value) { + return set("value", value); + } + + /** + * Method defaultValue. + * @param value Object + * @return B + */ + public B defaultValue(Object value) { + return set("default", value); + } + + /** + * Method format. + * @param format Format + * @return B + */ + @SuppressWarnings("unchecked") + public B format(Format format) { + if (format == Format.OTHER) + return (B)this; + return format(format.label); + } + + /** + * Method formatInt32. + * @return B + */ + public B formatInt32() { + return format(Format.INT32); + } + + /** + * Method formatInt64. + * @return B + */ + public B formatInt64() { + return format(Format.INT64); + } + + /** + * Method formatUint32. + * @return B + */ + public B formatUint32() { + return format(Format.UINT32); + } + + /** + * Method formatUint64. + * @return B + */ + public B formatUint64() { + return format(Format.UINT64); + } + + /** + * Method formatDouble. + * @return B + */ + public B formatDouble() { + return format(Format.DOUBLE); + } + + /** + * Method formatFloat. + * @return B + */ + public B formatFloat() { + return format(Format.FLOAT); + } + + /** + * Method formatByte. + * @return B + */ + public B formatByte() { + return format(Format.BYTE); + } + + /** + * Method formatDate. + * @return B + */ + public B formatDate() { + return format(Format.DATE); + } + + /** + * Method formatDateTime. + * @return B + */ + public B formatDateTime() { + return format(Format.DATETIME); + } + + /** + * Method formatDuration. + * @return B + */ + public B formatDuration() { + return format(Format.DURATION); + } + + /** + * Method formatLang. + * @return B + */ + public B formatLang() { + return format(Format.LANG); + } + + /** + * Method formatUri. + * @return B + */ + public B formatUri() { + return format(Format.URI); + } + + /** + * Method formatIri. + * @return B + */ + public B formatIri() { + return format(Format.IRI); + } + + /** + * Method format. + * @param format String + * @return B + */ + public B format(String format) { + return set("format", format); + } + + /** + * Method pattern. + * @param pattern Pattern + * @return B + */ + public B pattern(Pattern pattern) { + return pattern(pattern.pattern()); + } + + /** + * Method pattern. + * @param pattern String + * @return B + */ + public B pattern(String pattern) { + return set("pattern", pattern); + } + + /** + * Method minimum. + * @param min String + * @return B + */ + public B minimum(String min) { + return set("minimum", min); + } + + /** + * Method maximum. + * @param max String + * @return B + */ + public B maximum(String max) { + return set("maximum", max); + } + + /** + * Method minimum. + * @param min int + * @return B + */ + public B minimum(int min) { + return set("minimum", min); + } + + /** + * Method maximum. + * @param max int + * @return B + */ + public B maximum(int max) { + return set("maximum", max); + } + + /** + * Method minimum. + * @param min long + * @return B + */ + public B minimum(long min) { + return set("minimum", min); + } + + /** + * Method maximum. + * @param max long + * @return B + */ + public B maximum(long max) { + return set("maximum", max); + } + + /** + * Method minimum. + * @param min short + * @return B + */ + public B minimum(short min) { + return set("minimum", min); + } + + /** + * Method maximum. + * @param max short + * @return B + */ + public B maximum(short max) { + return set("maximum", max); + } + + /** + * Method minimum. + * @param min double + * @return B + */ + public B minimum(double min) { + return set("minimum", min); + } + + /** + * Method maximum. + * @param max double + * @return B + */ + public B maximum(double max) { + return set("maximum", max); + } + + /** + * Method minimum. + * @param min float + * @return B + */ + public B minimum(float min) { + return set("minimum", min); + } + + /** + * Method maximum. + * @param max float + * @return B + */ + public B maximum(float max) { + return set("maximum", max); + } + + /** + * Method step. + * @param step int + * @return B + */ + public B step(int step) { + return set("step", step); + } + + /** + * Method step. + * @param step long + * @return B + */ + public B step(long step) { + return set("step", step); + } + + /** + * Method step. + * @param step short + * @return B + */ + public B step(short step) { + return set("step", step); + } + + /** + * Method step. + * @param step double + * @return B + */ + public B step(double step) { + return set("step", step); + } + + /** + * Method step. + * @param step float + * @return B + */ + public B step(float step) { + return set("step", step); + } + + /** + * Method enumVals. + * @param vals Object[] + * @return B + */ + public B enumVals(Object... vals) { + return set("enum", ImmutableList.copyOf(vals)); + } + + } + + /** + * Constructor for Parameter. + * @param builder Builder + */ + protected Parameter(Builder builder) { + super(builder); + } + + /** + * Method required. + * @return boolean + */ + public boolean required() { + return getBoolean("required"); + } + + /** + * Method repeated. + * @return boolean + */ + public boolean repeated() { + return getBoolean("repeated"); + } + + /** + * Method value. + * @return O + */ + public O value() { + return this.get("value"); + } + + /** + * Method value. + * @param defaultValue O + * @return O + */ + public O value(O defaultValue) { + return this.get("value", defaultValue); + } + + /** + * Method defaultValue. + * @return O + */ + public O defaultValue() { + return this.get("default"); + } + + /** + * Method defaultValue. + * @param defaultValue O + * @return O + */ + public O defaultValue(O defaultValue) { + return this.get("default", defaultValue); + } + + /** + * Method formatString. + * @return String + */ + public String formatString() { + return getString("format"); + } + + /** + * Method format. + * @return Format + */ + public Format format() { + return Format.select(getString("format")); + } + + /** + * Method pattern. + * @return String + */ + public String pattern() { + return getString("pattern"); + } + + /** + * Method maximum. + * @return String + */ + public String maximum() { + return getString("maximum"); + } + + /** + * Method minimum. + * @return String + */ + public String minimum() { + return getString("minimum"); + } + + /** + * Method maximumInt. + * @return int + */ + public int maximumInt() { + return getInt("maximum"); + } + + /** + * Method minimumInt. + * @return int + */ + public int minimumInt() { + return getInt("minimum"); + } + + /** + * Method maximumLong. + * @return long + */ + public long maximumLong() { + return getLong("maximum"); + } + + /** + * Method minimumLong. + * @return long + */ + public long minimumLong() { + return getLong("minimum"); + } + + /** + * Method maximumShort. + * @return short + */ + public short maximumShort() { + return getShort("maximum"); + } + + /** + * Method minimumShort. + * @return short + */ + public short minimumShort() { + return getShort("minimum"); + } + + /** + * Method maximumDouble. + * @return double + */ + public double maximumDouble() { + return getDouble("maximum"); + } + + /** + * Method minimumDouble. + * @return double + */ + public double minimumDouble() { + return getDouble("minimum"); + } + + /** + * Method maximumFloat. + * @return float + */ + public float maximumFloat() { + return getFloat("maximum"); + } + + /** + * Method minimumFloat. + * @return float + */ + public float minimumFloat() { + return getFloat("minimum"); + } + + /** + * Method maximum. + * @param defaultValue String + * @return String + */ + public String maximum(String defaultValue) { + return getString("maximum", defaultValue); + } + + /** + * Method minimum. + * @param defaultValue String + * @return String + */ + public String minimum(String defaultValue) { + return getString("minimum", defaultValue); + } + + /** + * Method maximumInt. + * @param defaultValue int + * @return int + */ + public int maximumInt(int defaultValue) { + return getInt("maximum", defaultValue); + } + + /** + * Method minimumInt. + * @param defaultValue int + * @return int + */ + public int minimumInt(int defaultValue) { + return getInt("minimum", defaultValue); + } + + /** + * Method maximumLong. + * @param defaultValue long + * @return long + */ + public long maximumLong(long defaultValue) { + return getLong("maximum", defaultValue); + } + + /** + * Method minimumLong. + * @param defaultValue long + * @return long + */ + public long minimumLong(long defaultValue) { + return getLong("minimum", defaultValue); + } + + /** + * Method maximumShort. + * @param defaultValue short + * @return short + */ + public short maximumShort(short defaultValue) { + return getShort("maximum", defaultValue); + } + + /** + * Method minimumShort. + * @param defaultValue short + * @return short + */ + public short minimumShort(short defaultValue) { + return getShort("minimum", defaultValue); + } + + /** + * Method maximumDouble. + * @param defaultValue double + * @return double + */ + public double maximumDouble(double defaultValue) { + return getDouble("maximum", defaultValue); + } + + /** + * Method minimumDouble. + * @param defaultValue double + * @return double + */ + public double minimumDouble(double defaultValue) { + return getDouble("minimum", defaultValue); + } + + /** + * Method maximumFloat. + * @param defaultValue float + * @return float + */ + public float maximumFloat(float defaultValue) { + return getFloat("maximum", defaultValue); + } + + /** + * Method minimumFloat. + * @param defaultValue float + * @return float + */ + public float minimumFloat(float defaultValue) { + return getFloat("minimum", defaultValue); + } + + /** + * Method stepInt. + * @return int + */ + public int stepInt() { + return getInt("step"); + } + + /** + * Method stepInt. + * @param defaultValue int + * @return int + */ + public int stepInt(int defaultValue) { + return getInt("step", defaultValue); + } + + /** + * Method stepLong. + * @return long + */ + public long stepLong() { + return getLong("step"); + } + + /** + * Method getLong. + * @param defaultValue long + * @return long + */ + public long getLong(long defaultValue) { + return getLong("step", defaultValue); + } + + /** + * Method stepShort. + * @return short + */ + public short stepShort() { + return getShort("step"); + } + + /** + * Method stepShort. + * @param defaultValue short + * @return short + */ + public short stepShort(short defaultValue) { + return getShort("step", defaultValue); + } + + /** + * Method stepDouble. + * @return double + */ + public double stepDouble() { + return getDouble("step"); + } + + /** + * Method stepDouble. + * @param defaultValue double + * @return double + */ + public double stepDouble(double defaultValue) { + return getDouble("step", defaultValue); + } + + /** + * Method stepFloat. + * @return float + */ + public float stepFloat() { + return getFloat("step"); + } + + /** + * Method stepFloat. + * @param defaultValue float + * @return float + */ + public float stepFloat(float defaultValue) { + return getFloat("step", defaultValue); + } + + /** + * Method enumVals. + * @return Iterable + */ + public Iterable enumVals() { + return this.>get("enum"); + } + + /** + * Method type. + * @return T + */ + public T type() { + return this.get("type"); + } + + /** + * Method placeholder. + * @return NLV + */ + public NLV placeholder() { + return this.get("placeholder"); + } + + /** + * Method placeholderString. + * @return String + */ + public String placeholderString() { + return _nlv("placeholder"); + } + + /** + * Method placeholderString. + * @param lang String + * @return String + */ + public String placeholderString(String lang) { + return _nlv("placeholder", lang); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(Parameter obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected Parameter.Builder builder() { + return ActionMakers.parameter(); + } + } +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/ParametersValue.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/ParametersValue.java new file mode 100755 index 0000000..70edfb4 --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/ParametersValue.java @@ -0,0 +1,152 @@ +package com.ibm.common.activitystreams.actions; + +import java.io.Serializable; +import java.util.Map; + +import com.google.common.collect.ImmutableMap; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.TypeValue; +import com.ibm.common.activitystreams.ValueType; +import com.ibm.common.activitystreams.util.AbstractDictionaryObject; + +/** + * The value of the "parameters" property... + * @author james + * @version $Revision: 1.0 $ + */ +public final class ParametersValue + extends AbstractDictionaryObject + implements Serializable { + + /** + * Method make. + + * @return Builder */ + public static Builder make() { + return new Builder(); + } + + + /** + * @author james + * @version $Revision: 1.0 $ + */ + public static final class Builder + extends AbstractDictionaryObject.AbstractBuilder + { + + /** + * Method set. + * @param param String + * @param iri String + + * @return Builder */ + public Builder set(String param, String iri) { + return super.set( + param, + TypeValue.SimpleTypeValue.make(iri)); + } + + /** + * Method get. + + + * @return ParametersValue * @see com.google.common.base.Supplier#get() */ + public ParametersValue get() { + return new ParametersValue(this); + } + + } + + /** + * Constructor for ParametersValue. + * @param builder Builder + */ + ParametersValue(Builder builder) { + super(builder); + } + + /** + * Method get. + * @param param String + + * @return TypeValue */ + @SuppressWarnings("unchecked") + public T get(String param) { + return (T)super.getSingle(param); + } + + /** + * Method id. + * @param param String + * @return String + */ + public String id(String param) { + TypeValue tv = get(param); + return tv != null ? tv.id() : null; + } + + /** + * Method required. + * @param param String + * @return boolean + */ + public boolean required(String param) { + TypeValue tv = get(param); + if (tv == null) + return false; + if (tv.valueType() == ValueType.SIMPLE) + return true; + ASObject obj = (ASObject) tv; + return obj.getBoolean("required", true); + } + + /** + * Method value. + * @param param String + * @param defaultValue O + * @return O + */ + public O value(String param, O defaultValue) { + TypeValue tv = get(param); + if (tv == null || tv.valueType() == ValueType.SIMPLE) + return defaultValue; + ASObject obj = (ASObject) tv; + return obj.get("value", defaultValue); + } + + /** + * Method value. + * @param param String + * @return O + */ + public O value(String param) { + return value(param,null); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + implements Serializable { + private static final long serialVersionUID = -1975376657749952999L; + private ImmutableMap map; + SerializedForm(ParametersValue obj) { + ImmutableMap.Builder builder = + ImmutableMap.builder(); + for (String key : obj) + builder.put(key, obj.get(key)); + this.map = builder.build(); + } + + Object readResolve() + throws java.io.ObjectStreamException { + ParametersValue.Builder builder = + ParametersValue.make(); + for (Map.Entry entry : map.entrySet()) + builder.set(entry.getKey(), (TypeValue) entry.getValue()); + return builder.get(); + } + } +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/StylesValue.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/StylesValue.java new file mode 100755 index 0000000..52c4e5c --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/StylesValue.java @@ -0,0 +1,131 @@ +package com.ibm.common.activitystreams.actions; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.io.Serializable; +import java.util.Map; + +import com.google.common.collect.ImmutableMap; +import com.ibm.common.activitystreams.TypeValue; +import com.ibm.common.activitystreams.util.AbstractDictionaryObject; + +/** + * The value of the "parameters" property... + * @author james + * @version $Revision: 1.0 $ + */ +public final class StylesValue + extends AbstractDictionaryObject + implements Serializable { + + /** + * Method make. + + * @return Builder */ + public static Builder make() { + return new Builder(); + } + + + /** + * @author james + * @version $Revision: 1.0 $ + */ + public static final class Builder + extends AbstractDictionaryObject.AbstractBuilder + { + + /** + * Method media. + * @param query String + * @return Builder + */ + public Builder media(String query) { + return super.set("media", query); + } + + /** + * Method set. + + + + * @param name String + * @param value String + * @return Builder */ + public Builder set(String name, String value) { + checkArgument(!name.equalsIgnoreCase("query")); + return super.set(name, value); + } + + /** + * Method get. + + + * @return ParametersValue * @see com.google.common.base.Supplier#get() */ + public StylesValue get() { + return new StylesValue(this); + } + + } + + /** + * Constructor for ParametersValue. + * @param builder Builder + */ + StylesValue(Builder builder) { + super(builder); + } + + /** + * Method media. + * @return String + */ + public String media() { + return getSingle("media"); + } + + /** + * Method get. + * @param key String + * @return String + */ + public String get(String key) { + return super.getSingle(key); + } + + /** + * Method get. + * @param key String + * @param defaultValue String + * @return String + */ + public String get(String key, String defaultValue) { + return super.getSingle(key, defaultValue); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + implements Serializable { + private static final long serialVersionUID = -1975376657749952999L; + private ImmutableMap map; + SerializedForm(StylesValue obj) { + ImmutableMap.Builder builder = + ImmutableMap.builder(); + for (String key : obj) + builder.put(key, obj.get(key)); + this.map = builder.build(); + } + + Object readResolve() + throws java.io.ObjectStreamException { + StylesValue.Builder builder = + StylesValue.make(); + for (Map.Entry entry : map.entrySet()) + builder.set(entry.getKey(), entry.getValue()); + return builder.get(); + } + } +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/TypedPayload.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/TypedPayload.java new file mode 100755 index 0000000..cfb5449 --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/TypedPayload.java @@ -0,0 +1,160 @@ +package com.ibm.common.activitystreams.actions; + +import java.io.ObjectStreamException; + +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.net.MediaType; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.LinkValue; +import com.ibm.common.activitystreams.TypeValue; + +/** + */ +public final class TypedPayload + extends ASObject { + + /** + * Method makeTypedPayload. + * @param mediaType MediaType + * @return Builder + */ + public static Builder makeTypedPayload(MediaType mediaType) { + return new Builder().mediaType(mediaType); + } + + /** + * Method makeTypedPayload. + * @param mediaType String + * @return Builder + */ + public static Builder makeTypedPayload(String mediaType) { + return new Builder().mediaType(mediaType); + } + + public static Builder make() { + return new Builder(); + } + + /** + */ + public static final class Builder + extends ASObject.AbstractBuilder { + + private Builder() { + objectType("TypedPayload"); + } + + /** + * Method schema. + * @param iri String + * @return Builder + */ + public Builder schema(String iri) { + return schema(LinkValue.SimpleLinkValue.make(iri)); + } + + /** + * Method schema. + * @param lv LinkValue + * @return Builder + */ + public Builder schema(LinkValue lv) { + return link("schema", lv); + } + + /** + * Method schema. + * @param lv Supplier + * @return Builder + */ + public Builder schema(Supplier lv) { + return schema(lv.get()); + } + + /** + * Method type. + * @param iri String + * @return Builder + */ + public Builder type(String iri) { + return type(TypeValue.SimpleTypeValue.make(iri)); + } + + /** + * Method type. + * @param tv TypeValue + * @return Builder + */ + public Builder type(TypeValue tv) { + return set("type", tv); + } + + /** + * Method type. + * @param tv Supplier + * @return Builder + */ + public Builder type(Supplier tv) { + return type(tv.get()); + } + + /** + * Method get. + * @return TypedPayload + * @see com.google.common.base.Supplier#get() + */ + public TypedPayload get() { + return new TypedPayload(this); + } + + } + + /** + * Constructor for TypedPayload. + * @param builder Builder + */ + private TypedPayload(Builder builder) { + super(builder); + } + + /** + * Method schema. + * @return L + */ + public Iterable schema() { + return this.links("schema"); + } + + public Iterable schema(Predicate filter) { + return this.links("schema", filter); + } + + /** + * Method type. + * @return TypeValue + */ + public TypeValue type() { + return this.get("type"); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + private String mediaType; + protected SerializedForm(TypedPayload obj) { + super(obj); + this.mediaType = obj.mediaType().toString(); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected TypedPayload.Builder builder() { + return ActionMakers.typedPayload(mediaType); + } + } +} diff --git a/actions/src/main/java/com/ibm/common/activitystreams/actions/UrlTemplate.java b/actions/src/main/java/com/ibm/common/activitystreams/actions/UrlTemplate.java new file mode 100755 index 0000000..d29e0e3 --- /dev/null +++ b/actions/src/main/java/com/ibm/common/activitystreams/actions/UrlTemplate.java @@ -0,0 +1,176 @@ +package com.ibm.common.activitystreams.actions; + +import static com.ibm.common.activitystreams.Makers.type; +import static com.ibm.common.activitystreams.Makers.object; + +import java.io.ObjectStreamException; + +import com.google.common.base.Supplier; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.TypeValue; + +/** + */ +public final class UrlTemplate + extends ASObject { + + /** + * Method makeUrlTemplate. + * @return Builder + */ + public static Builder makeUrlTemplate() { + return new Builder(); + } + + /** + */ + public static final class Builder + extends ASObject.AbstractBuilder { + + private final ParametersValue.Builder params = + ParametersValue.make(); + + private Builder() { + objectType("UrlTemplate"); + } + + /** + * Method template. + * @param template String + * @return Builder + */ + public Builder template(String template) { + set("template", template); + return this; + } + + /** + * Method parameter. + * @param name String + * @param iri String + * @return Builder + */ + public Builder parameter(String name, String iri) { + params.set(name, type(iri)); + return this; + } + + /** + * Method parameter. + * @param name String + * @param iri String + * @param required boolean + * @return Builder + */ + public Builder parameter( + String name, + String iri, + boolean required) { + return parameter( + name, + object() + .id(iri) + .set("required", required)); + } + + /** + * Method parameter. + * @param name String + * @param iri String + * @param required boolean + * @param value Object + * @return Builder + */ + public Builder parameter( + String name, + String iri, + boolean required, + Object value) { + return parameter( + name, + object() + .id(iri) + .set("required", required) + .set("value", value)); + } + + /** + * Method parameter. + * @param name String + * @param lv TypeValue + * @return Builder + */ + public Builder parameter( + String name, + TypeValue lv) { + params.set(name, lv); + return this; + } + + /** + * Method parameter. + * @param name String + * @param lv Supplier + * @return Builder + */ + public Builder parameter( + String name, + Supplier lv) { + return parameter(name, lv.get()); + } + + /** + * Method get. + * @return UrlTemplate + * @see com.google.common.base.Supplier#get() + */ + public UrlTemplate get() { + if (params.notEmpty()) + set("parameters", params.get()); + return new UrlTemplate(this); + } + + } + + /** + * Constructor for UrlTemplate. + * @param builder Builder + */ + private UrlTemplate(Builder builder) { + super(builder); + } + + /** + * Method parameters. + * @return ParametersValue + */ + public ParametersValue parameters() { + return this.get("parameters"); + } + + /** + * Method template. + * @return String + */ + public String template() { + return this.getString("template"); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(UrlTemplate obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected UrlTemplate.Builder builder() { + return ActionMakers.urlTemplate(); + } + } +} diff --git a/assembly/assembly.xml b/assembly/assembly.xml new file mode 100644 index 0000000..9b35761 --- /dev/null +++ b/assembly/assembly.xml @@ -0,0 +1,17 @@ + + bin + + tar.gz + zip + + false + + + + + * + + false + + + \ No newline at end of file diff --git a/assembly/pom.xml b/assembly/pom.xml new file mode 100644 index 0000000..846818f --- /dev/null +++ b/assembly/pom.xml @@ -0,0 +1,49 @@ + + 4.0.0 + + com.ibm.common + activitystreams + 0.0.1-SNAPSHOT + + assembly + Activity Streams 2.0 - Assembly + pom + + + com.ibm.common + activitystreams-core + 0.0.1-SNAPSHOT + + + com.ibm.common + activitystreams-actions + 0.0.1-SNAPSHOT + + + com.ibm.common + activitystreams-geo + 0.0.1-SNAPSHOT + + + com.ibm.common + activitystreams-legacy + 0.0.1-SNAPSHOT + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.2.2 + + + assembly.xml + + + + + + + \ No newline at end of file diff --git a/core/TODO.md b/core/TODO.md new file mode 100644 index 0000000..936f070 --- /dev/null +++ b/core/TODO.md @@ -0,0 +1,4 @@ +# Development Todo's + +1. Migrate from GSON to Jackson for JSON parsing +2. Improve Schema/PropertyMap implementation diff --git a/core/pom.xml b/core/pom.xml new file mode 100755 index 0000000..3866b60 --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,131 @@ + + + + com.ibm.common + activitystreams + 0.0.1-SNAPSHOT + + + 4.0.0 + activitystreams-core + jar + + Activity Streams 2.0 - Core + http://github.org/opensocial/activitystreams + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + UTF-8 + + + + + com.google.code.gson + gson + + + com.google.guava + guava + + + joda-time + joda-time + + + + junit + junit + test + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + UTF-8 + UTF-8 + UTF-8 + -XDignore.symbol.file + public + + http://www.joda.org/joda-time/apidocs + http://docs.guava-libraries.googlecode.com/git-history/v16.0.1/javadoc/ + + + + + + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + maven-jar-plugin + 2.3.1 + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + + org.apache.felix + maven-bundle-plugin + 2.3.7 + true + + + bundle-manifest + process-classes + + manifest + + + + + + com.ibm.common.activitystreams.* + + com.google.gson.*, + com.google.common.*, + org.joda.time.* + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.2.2 + + + assembly.xml + + + + + + + + + diff --git a/core/src/examples/com/ibm/common/activitystreams/examples/Simple.java b/core/src/examples/com/ibm/common/activitystreams/examples/Simple.java new file mode 100755 index 0000000..0d5a04b --- /dev/null +++ b/core/src/examples/com/ibm/common/activitystreams/examples/Simple.java @@ -0,0 +1,71 @@ +package com.ibm.common.activitystreams.examples; + +import static com.ibm.common.activitystreams.IO.makeDefaultPrettyPrint; +import static com.ibm.common.activitystreams.Makers.activity; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import com.ibm.common.activitystreams.Activity; +import com.ibm.common.activitystreams.IO; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +public final class Simple { + + // The IO object handles all of the reading and writing of the object + private static final IO io = makeDefaultPrettyPrint(); + + private Simple() {} + + /** + * Method main. + * @param args String[] + + * @throws Exception */ + public static void main(String... args) throws Exception { + + // Demonstrates the creation and parsing of a simple Activity Object + + + // Create the Activity... The API uses a Fluent Generator pattern + Activity activity = + activity() + .verb("post") + .actor("acct:joe@example.org") + .object("http://example.net/posts/1") + .get(); + + + // The Activity object is immutable... + System.out.println(activity.verb()); + System.out.println(activity.actor()); + System.out.println(activity.object()); + + // let's write it out to our outputstream + ByteArrayOutputStream out = + new ByteArrayOutputStream(); + activity.writeTo(out, io); + + // now let's parse it back in + ByteArrayInputStream in = + new ByteArrayInputStream( + out.toByteArray()); + + activity = io.readAsActivity(in); + + // We get back the same thing... + System.out.println(activity.verb()); + System.out.println(activity.actor()); + System.out.println(activity.object()); + + // If you want to see what was serialized, + // simply write out to stdout... + activity.writeTo(System.out, io); + + + } + +} diff --git a/core/src/examples/com/ibm/common/activitystreams/examples/Simple2.java b/core/src/examples/com/ibm/common/activitystreams/examples/Simple2.java new file mode 100755 index 0000000..10c7ce8 --- /dev/null +++ b/core/src/examples/com/ibm/common/activitystreams/examples/Simple2.java @@ -0,0 +1,83 @@ +package com.ibm.common.activitystreams.examples; + +/** + * The Makers class includes a bunch of static generator + * methods that are easiest to use when imported statically + */ +import static com.ibm.common.activitystreams.IO.makeDefaultPrettyPrint; +import static com.ibm.common.activitystreams.Makers.activity; +import static com.ibm.common.activitystreams.Makers.object; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import com.ibm.common.activitystreams.Activity; +import com.ibm.common.activitystreams.IO; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +public final class Simple2 { + + + // The IO object handles all of the reading and writing of the object + private static final IO io = makeDefaultPrettyPrint(); + + + private Simple2() {} + + /** + * Method main. + * @param args String[] + + * @throws Exception */ + public static void main(String... args) throws Exception { + + // Demonstrates the creation and parsing of a simple Activity Object + + // (we'll use this to store the output...) + ByteArrayOutputStream out = + new ByteArrayOutputStream(); + + // Create the Activity... The API uses a Fluent Generator pattern + Activity activity = + activity() + .verb("post") + .actor( + object("person") + .id("acct:joe@example.com") + .displayName("Joe Smith") + ) + .object( + object("note") + .id("http://example.net/posts/1") + .title("This is the title")) + .get(); + + // The Activity object is immutable... + System.out.println(activity.verb()); + System.out.println(activity.actor()); + System.out.println(activity.object()); + + // let's write it out to our outputstream + activity.writeTo(out, io); + + // now let's parse it back in + ByteArrayInputStream in = + new ByteArrayInputStream( + out.toByteArray()); + + activity = io.readAsActivity(in); + + // We get back the same thing... + System.out.println(activity.verb()); + System.out.println(activity.actor()); + System.out.println(activity.object()); + + // If you want to see what was serialized, + // simply write out to stdout... + activity.writeTo(System.out, io); + } + +} diff --git a/core/src/examples/com/ibm/common/activitystreams/examples/Simple3.java b/core/src/examples/com/ibm/common/activitystreams/examples/Simple3.java new file mode 100755 index 0000000..751f9d2 --- /dev/null +++ b/core/src/examples/com/ibm/common/activitystreams/examples/Simple3.java @@ -0,0 +1,89 @@ +package com.ibm.common.activitystreams.examples; + +/** + * The Makers class includes a bunch of static generator + * methods that are easiest to use when imported statically + */ +import static com.ibm.common.activitystreams.IO.makeDefaultPrettyPrint; +import static com.ibm.common.activitystreams.Makers.*; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import com.ibm.common.activitystreams.Activity; +import com.ibm.common.activitystreams.IO; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +public final class Simple3 { + + // The IO object handles all of the reading and writing of the object + private static final IO io = makeDefaultPrettyPrint(); + + private Simple3() {} + + /** + * Method main. + * @param args String[] + + * @throws Exception */ + public static void main(String... args) throws Exception { + + // Demonstrates the creation and parsing of a simple Activity Object + + // (we'll use this to store the output...) + ByteArrayOutputStream out = + new ByteArrayOutputStream(); + + // Create the Activity... The API uses a Fluent Generator pattern + Activity activity = + activity() + .verb("post") + .actor( + object() + .objectType( + object() + .id("http://schema.example.net/Person") + .displayName("Person") + .alias("person")) + .id("acct:joe@example.com") + .displayName("Joe Smith") + ) + .object( + object("note") + .id("http://example.net/posts/1") + .title( + nlv() + .set("en", "This is the title") + .set("fr", "C'est le titre")) + ) + .get(); + + // The Activity object is immutable... + System.out.println(activity.verb()); + System.out.println(activity.actor()); + System.out.println(activity.object()); + + // let's write it out to our outputstream + activity.writeTo(out, io); + + // now let's parse it back in + ByteArrayInputStream in = + new ByteArrayInputStream( + out.toByteArray()); + + activity = io.readAsActivity(in); + + // We get back the same thing... + System.out.println(activity.verb()); + System.out.println(activity.actor()); + System.out.println(activity.object()); + + // If you want to see what was serialized, + // simply write out to stdout... + activity.writeTo(System.out, io); + } + +} diff --git a/core/src/examples/com/ibm/common/activitystreams/examples/Simple4.java b/core/src/examples/com/ibm/common/activitystreams/examples/Simple4.java new file mode 100755 index 0000000..16177f7 --- /dev/null +++ b/core/src/examples/com/ibm/common/activitystreams/examples/Simple4.java @@ -0,0 +1,101 @@ +package com.ibm.common.activitystreams.examples; + +/** + * The Makers class includes a bunch of static generator + * methods that are easiest to use when imported statically + */ +import static com.ibm.common.activitystreams.Activity.Audience.CC; +import static com.ibm.common.activitystreams.Activity.Audience.TO; +import static com.ibm.common.activitystreams.Makers.activity; +import static com.ibm.common.activitystreams.Makers.nlv; +import static com.ibm.common.activitystreams.Makers.object; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import com.ibm.common.activitystreams.Activity; +import com.ibm.common.activitystreams.IO; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +public final class Simple4 { + + private Simple4() {} + + /** + * Method main. + * @param args String[] + + * @throws Exception */ + public static void main(String... args) throws Exception { + + // Demonstrates the creation and parsing of a simple Activity Object + + // (we'll use this to store the output...) + ByteArrayOutputStream out = + new ByteArrayOutputStream(); + + // The IO object handles all of the reading and writing of the object + IO io = IO.make().prettyPrint().get(); + + // Create the Activity... The API uses a Fluent Generator pattern + Activity activity = + activity() + .verb("post") + .actor( + object() + .objectType( + object() + .id("http://schema.example.net/Person") + .displayName("Person") + .alias("person")) + .id("acct:joe@example.com") + .displayName("Joe Smith") + ) + .object( + object("note") + .id("http://example.net/posts/1") + .title( + nlv() + .set("en", "This is the title") + .set("fr", "C'est le titre")) + ) + .audience(TO, + "urn:social:everyone", + "acct:mary@example.net") + .audience(CC, + "urn:social:extended") + .action("embed", "http://xml.example.org/foo") + .pending() + .get(); + + // The Activity object is immutable... + System.out.println(activity.verb()); + System.out.println(activity.actor()); + System.out.println(activity.object()); + System.out.println(activity.status()); + + // let's write it out to our outputstream + activity.writeTo(out, io); + + // now let's parse it back in + ByteArrayInputStream in = + new ByteArrayInputStream( + out.toByteArray()); + + activity = io.readAsActivity(in); + + // We get back the same thing... + System.out.println(activity.verb()); + System.out.println(activity.actor()); + System.out.println(activity.object()); + System.out.println(activity.status()); + + // If you want to see what was serialized, + // simply write out to stdout... + activity.writeTo(System.out, io); + } + +} diff --git a/core/src/examples/com/ibm/common/activitystreams/examples/Simple5.java b/core/src/examples/com/ibm/common/activitystreams/examples/Simple5.java new file mode 100644 index 0000000..4776bee --- /dev/null +++ b/core/src/examples/com/ibm/common/activitystreams/examples/Simple5.java @@ -0,0 +1,60 @@ +package com.ibm.common.activitystreams.examples; + +import static com.ibm.common.activitystreams.Makers.activity; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import com.ibm.common.activitystreams.Activity; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +public final class Simple5 { + + private Simple5() {} + + /** + * Method main. + * @param args String[] + + * @throws Exception */ + public static void main(String... args) throws Exception { + + // Create the Activity... The API uses a Fluent Generator pattern + Activity activity = + activity() + .verb("post") + .actor("acct:joe@example.org") + .object("http://example.net/posts/1") + .action("like", "http://example.org/actions/like") + .updatedNow() + .get(); + + + // The Activity object is immutable... + System.out.println(activity.verb()); + System.out.println(activity.actor()); + System.out.println(activity.object()); + + // Activity objects are serializable + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(out); + oos.writeObject(activity); + + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(in); + + activity = (Activity) ois.readObject(); + + System.out.println(activity.verb()); + System.out.println(activity.actor()); + System.out.println(activity.object()); + System.out.println(activity.actions().get("like")); + System.out.println(activity.updated()); + } + +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/ASObject.java b/core/src/main/java/com/ibm/common/activitystreams/ASObject.java new file mode 100755 index 0000000..e0f8771 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/ASObject.java @@ -0,0 +1,2639 @@ +package com.ibm.common.activitystreams; + +import static com.google.common.base.Enums.getIfPresent; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Throwables.propagate; +import static com.google.common.collect.ImmutableList.of; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.getFirst; +import static com.google.common.collect.Maps.difference; +import static com.google.common.collect.Maps.newLinkedHashMap; +import static com.google.common.net.MediaType.parse; +import static com.ibm.common.activitystreams.Makers.linkValue; +import static com.ibm.common.activitystreams.Makers.linkValues; +import static com.ibm.common.activitystreams.Makers.nlv; +import static com.ibm.common.activitystreams.Makers.type; +import static com.ibm.common.activitystreams.util.Converters.toBoolean; +import static com.ibm.common.activitystreams.util.Converters.toDateTime; +import static com.ibm.common.activitystreams.util.Converters.toDouble; +import static com.ibm.common.activitystreams.util.Converters.toDuration; +import static com.ibm.common.activitystreams.util.Converters.toFloat; +import static com.ibm.common.activitystreams.util.Converters.toInt; +import static com.ibm.common.activitystreams.util.Converters.toInterval; +import static com.ibm.common.activitystreams.util.Converters.toLong; +import static com.ibm.common.activitystreams.util.Converters.toPeriod; +import static com.ibm.common.activitystreams.util.Converters.toShort; +import static java.lang.Math.ceil; +import static java.lang.Math.floor; +import static org.joda.time.DateTimeZone.UTC; +import static org.joda.time.Duration.standardSeconds; + +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; + +import org.joda.time.DateTime; +import org.joda.time.Duration; +import org.joda.time.Interval; +import org.joda.time.Period; +import org.joda.time.ReadableDuration; +import org.joda.time.ReadablePeriod; + +import com.google.common.base.Converter; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.google.common.net.MediaType; +import com.ibm.common.activitystreams.NLV.MapNLV; +import com.ibm.common.activitystreams.NLV.SimpleNLV; +import com.ibm.common.activitystreams.util.AbstractWritable; + +/** + * The Base for all Activity Streams objects. + * + *

Creating an object:

+ *
+ *   import static com.ibm.common.activitystreams.Makers.object;
+ * 
+ *   ASObject obj = object()
+ *     .id("urn:example:object:1")
+ *     .displayName("My Note")
+ *     .objectType("note")
+ *     .content("en", "This is my note in english")
+ *     .get();
+ * 
+ * @author james + * @version $Revision: 1.0 $ + */ +@SuppressWarnings("unchecked") +public class ASObject + extends AbstractWritable + implements Iterable, LinkValue, TypeValue, Serializable { + + /** + * Builder for concrete ASObject instances + */ + public static class Builder + extends AbstractBuilder { + /** + * Returns the built ASObject instance + * @return ASObject + * @see com.google.common.base.Supplier#get() + **/ + public ASObject get() { + return new ASObject(this); + } + } + + /** + * Verifies that the rating value is within the proper range + * @param d double + * @return double + **/ + private static double checkRating(double d) { + checkArgument(floor(d) >= 1 && ceil(d) <= 5); + return d; + } + + /** + * Verifies that the value is non-negative + * @param i int + * @return int + **/ + private static int checkNotNegative(int i) { + checkArgument(i >= 0); + return i; + } + + /** + * Method checkNotNegative. + * @param l long + * @return long + */ + private static long checkNotNegative(long l) { + checkArgument(l >= 0); + return l; + } + + /** + * Method convLocale. + * @param locale Locale + * @return String + **/ + private static String convLocale(Locale locale) { + return checkNotNull(locale).toString().replaceAll("_", "-"); + } + + private static final String DEFAULT_LOCALE = + convLocale(Locale.getDefault()); + + /** + * Abstract base builder for ASObject instances. + */ + public static abstract class AbstractBuilder + > + extends AbstractWritable.AbstractWritableBuilder + implements Supplier, Writable { + + private final Map map = + newLinkedHashMap(); + private final ActionsValue.Builder actions = + Makers.actions(); + + /** + * Method _dt. + * @param key String + * @param dt DateTime + * @return B + **/ + protected B _dt(String key, DateTime dt) { + return set(key, dt); + } + + /** + * Method _dt. + * @param key String + * @param dt String + * @return B + **/ + protected B _dt(String key, String dt) { + return _dt(key, DateTime.parse(dt)); + } + + /** + * Method _dtNow. + * @param key String + * @return B + **/ + protected B _dtNow(String key) { + return _dt(key, DateTime.now(UTC)); + } + + /** + * Method _dtFromNow. + * @param key String + * @param duration Duration + * @return B + **/ + protected B _dtFromNow(String key, ReadableDuration duration) { + return _dt(key, DateTime.now(UTC).plus(duration)); + } + + /** + * Method _dtFromNow. + * @param key String + * @param period ReadablePeriod + * @return B + **/ + protected B _dtFromNow(String key, ReadablePeriod period) { + return _dt(key, DateTime.now(UTC).plus(period)); + } + + /** + * Method _dtFromNow. + * @param key String + * @param v long + * @param unit TimeUnit + * @return B + **/ + protected B _dtFromNow(String key, long v, TimeUnit unit) { + return _dtFromNow(key, toDuration(v,unit)); + } + + /** + * Method _dtFrom. + * @param key String + * @param dt DateTime + * @param duration Duration + * @return B + **/ + protected B _dtFrom(String key, DateTime dt, ReadableDuration duration) { + return _dt(key, dt.plus(duration)); + } + + /** + * Method _dtFrom. + * @param key String + * @param dt DateTime + * @param period ReadablePeriod + * @return B + */ + protected B _dtFrom(String key, DateTime dt, ReadablePeriod period) { + return _dt(key, dt.plus(period)); + } + + /** + * Method _dtFrom. + * @param key String + * @param dt DateTime + * @param v long + * @param unit TimeUnit + * @return B + **/ + protected B _dtFrom(String key, DateTime dt, long v, TimeUnit unit) { + return _dtFrom(key, dt, toDuration(v,unit)); + } + + /** + * Set the published timestamp + * @param dt DateTime + * @return B + **/ + public B published(DateTime dt) { + return _dt("published", dt); + } + + /** + * Set the published timestamp equal to the current time + * @return B + **/ + public B publishedNow() { + return _dtNow("published"); + } + + /** + * Set the published timestamp as a given duration from the current time. + * For instance: + *
+     * // Published one day ago
+     * ASObject obj = Makers.object()
+     *   .publishedFromNow(Duration.standardDays(-1))
+     *   .get();
+     * 
+     * @param duration Duration
+     * @return B 
+     **/
+    public B publishedFromNow(ReadableDuration duration) {
+      return _dtFromNow("published", duration);
+    }
+    
+    /**
+     * Set the published timestamp as a given period of time from the current time
+     * 
+     * // Published one day ago
+     * ASObject obj = Makers.object()
+     *   .publishedFromNow(Period.days(-1))
+     *   .get();
+     * 
+     * @param period ReadablePeriod
+     * @return B 
+     **/
+    public B publishedFromNow(ReadablePeriod period) {
+      return _dtFromNow("published", period);
+    }
+    
+    /**
+     * Set the published timestamp as a given period of time from the current time
+     * @param v long
+     * @param unit TimeUnit
+     * @return B 
+     **/
+    public B publishedFromNow(long v, TimeUnit unit) {
+      return _dtFromNow("published", v, unit);
+    }
+    
+    /**
+     * Set the updated timestamp
+     * @param dt DateTime
+     * @return B 
+     **/
+    public B updated(DateTime dt) {
+      return _dt("updated", dt);
+    }
+    
+    /**
+     * Set the updated timestamp equal to the current time
+     * @return B 
+     **/
+    public B updatedNow() {
+      return _dtNow("updated");
+    }
+    
+    /**
+     * Set the updated timestamp as a given duration from the current time.
+     * For instance:
+     * 
+     * // Published one day ago
+     * ASObject obj = Makers.object()
+     *   .updatedFromNow(Duration.standardDays(-1))
+     *   .get();
+     * 
+     * @param duration Duration
+     * @return B
+     **/
+    public B updatedFromNow(ReadableDuration duration) {
+      return _dtFromNow("updated", duration);
+    }
+    
+    /**
+     * Set the updated timestamp as a given period from the current time.
+     * For instance:
+     * 
+     * // Published one day ago
+     * ASObject obj = Makers.object()
+     *   .updatedFromNow(Period.days(-1))
+     *   .get();
+     * 
+     * @param period ReadablePeriod
+     * @return B
+     **/
+    public B updatedFromNow(ReadablePeriod period) {
+      return _dtFromNow("updated", period);
+    }
+    
+    /**
+     * Set the updated timestamp as a given period from the current time
+     * @param v long
+     * @param unit TimeUnit
+     * @return B 
+     **/
+    public B updatedFromNow(long v, TimeUnit unit) {
+      return _dtFromNow("updated", v, unit);
+    }
+    
+    /**
+     * Set the start time
+     * @param dt DateTime
+     * @return B 
+     **/
+    public B startTime(DateTime dt) {
+      return _dt("startTime", dt);
+    }
+    
+    /**
+     * Set the startTime timestamp as a given duration from the current time.
+     * For instance:
+     * 
+     * // Published one day ago
+     * ASObject obj = Makers.object()
+     *   .startTimeFromNow(Duration.standardDays(-1))
+     *   .get();
+     * 
+     * @param duration Duration
+     * @return B 
+     **/
+    public B startTimeFromNow(ReadableDuration duration) {
+      return _dtFromNow("startTime", duration);
+    }
+    
+    /**
+     * Set the startTime timestamp as a given period from the current time.
+     * For instance:
+     * 
+     * // Published one day ago
+     * ASObject obj = Makers.object()
+     *   .startTimeFromNow(Period.days(-1))
+     *   .get();
+     * 
+     * @param period ReadablePeriod
+     * @return B 
+     **/
+    public B startTimeFromNow(ReadablePeriod period) {
+      return _dtFromNow("startTime", period);
+    }
+    
+    /**
+     * Set the startTime timestamp as a given period from the current time.
+     * @param v long
+     * @param unit TimeUnit
+     * @return B 
+     **/
+    public B startTimeFromNow(long v, TimeUnit unit) {
+      return _dtFromNow("startTime", v, unit);
+    }
+    
+    /**
+     * Set the start time to the current time
+     * @return B 
+     **/
+    public B startTimeNow() {
+      return _dtNow("startTime");
+    }
+    
+    /**
+     * Set the end time
+     * @param dt DateTime
+     * @return B
+     **/
+    public B endTime(DateTime dt) {
+      return _dt("endTime", dt);
+    }
+    
+    /**
+     * Set the endTime timestamp as a given duration from the current time.
+     * For instance:
+     * 
+     * // Published one day ago
+     * ASObject obj = Makers.object()
+     *   .startTimeFromNow(Duration.standardDays(-1))
+     *   .get();
+     * 
+     * @param duration Duration
+     * @return B 
+     **/
+    public B endTimeFromNow(ReadableDuration duration) {
+      return _dtFromNow("endTime", duration);
+    }
+    
+    /**
+     * Set the endTime timestamp as a given period from the current time.
+     * For instance:
+     * 
+     * // Published one day ago
+     * ASObject obj = Makers.object()
+     *   .startTimeFromNow(Period.days(-1))
+     *   .get();
+     * 
+     * @param period ReadablePeriod
+     * @return B
+     **/
+    public B endTimeFromNow(ReadablePeriod period) {
+      return _dtFromNow("endTime", period);
+    }
+    
+    /**
+     * Set the endTime timestamp as a given period from the current time
+     * @param v long
+     * @param unit TimeUnit
+     * @return B 
+     **/
+    public B endTimeFromNow(long v, TimeUnit unit) {
+      return _dtFromNow("endTime", v, unit);
+    }
+    
+    /**
+     * Set the end time 
+     * @return B
+     **/
+    public B endTimeNow() {
+      return _dtNow("endTimeNow");
+    }
+    
+    /**
+     * Set the rating as a value in the range 0.00-1.00;
+     * @param d double
+     * @return B 
+     * @throws IllegalArgumentException if the value is not 
+     *         within the proper range 
+     **/
+    public B rating(double d) {
+      return set("rating", checkRating(d));
+    }
+    
+    /**
+     * Set the duration
+     * @param s int
+     * @return B 
+     * @throws IllegalArgumentException if the value 
+     *         is less than zero 
+     **/
+    public B duration(long s) {
+      return duration(standardSeconds(checkNotNegative(s)));
+    }
+    
+    /**
+     * Set the duration as a Joda-Time Duration
+     * @param d Duration
+     * @return B 
+     **/
+    public B duration(ReadableDuration d) {
+      return set("duration", d);
+    }
+    
+    /**
+     * Set the duration as a Joda-Time Period
+     * @param period ReadablePeriod
+     * @return B
+     */
+    public B duration(ReadablePeriod period) {
+      return duration(period.toPeriod().toStandardDuration());
+    }
+    
+    /**
+     * Set the duration
+     * @param v long
+     * @param unit TimeUnit
+     * @return B 
+     **/
+    public B duration(long v, TimeUnit unit) {
+      return duration(toDuration(v,unit));
+    }
+    
+    /**
+     * Set the duration as a given period of time from the given reference
+     * @param p ReadablePeriod
+     * @param dt DateTime
+     * @return B
+     */
+    public B durationFrom(ReadablePeriod p, DateTime dt) {
+      return duration(p.toPeriod().toDurationFrom(dt));
+    }
+    
+    /**
+     * Set the duration as a given period of time from the current time
+     * @param p ReadablePeriod
+     * @return B
+     */
+    public B durationFromNow(ReadablePeriod p) {
+      return duration(p.toPeriod().toDurationFrom(DateTime.now(UTC)));
+    }
+    
+    /**
+     * Set the height of the object in terms of number of device-independent
+     * pixels.
+     * @param h int
+     * @return B 
+     **/
+    public B height(int h) {
+      return set("height", checkNotNegative(h));
+    }
+    
+    /**
+     * Set the width of the object in terms of number of device-independent
+     * pixels.
+     * @param h int
+     * @return B 
+     **/
+    public B width(int h) {
+      return set("width", checkNotNegative(h));
+    }
+    
+    /**
+     * Set the MIME Media Type of the object
+     * @param mt String
+     * @return B 
+     **/
+    public B mediaType(String mt) {
+      return mediaType(parse(mt));
+    }
+    
+    /**
+     * Set the MIME Media Type of the object
+     * @param mt com.google.common.net.MediaType
+     * @return B 
+     **/
+    public B mediaType(MediaType mt) {
+      return set("mediaType", mt);
+    }
+    
+    /**
+     * Set the link relation
+     * @param rel String
+     * @return B 
+     **/
+    public B rel(String rel) {
+      return set("rel", rel);
+    }
+    
+    /**
+     * An objects alias is an alternative to it's "id".
+     * @param iri String
+     * @return B 
+     **/
+    public B alias(String iri) {
+      return set("alias", iri);
+    }
+    
+    /**
+     * Add an attachment
+     * @param url String
+     * @return B 
+     **/
+    public B attachments(String url, String... urls) {
+      if (url != null)
+        link("attachments", linkValue(url));
+      if (urls != null)
+        for (String u : urls)
+          link("attachments", linkValue(u));
+      return (B)this;
+    }
+  
+    /**
+     * Add an attachment.
+     * @param link LinkValue
+     * @return B 
+     **/
+    public B attachments(LinkValue link, LinkValue... links) {
+      if (link != null)
+        link("attachments", link);
+      if (links != null) 
+        for (LinkValue l : links)
+          link("attachments", l);
+      return (B)this;
+    }
+    
+    /**
+     * Add an attachment
+     * @param link Supplier
+     * @return B 
+     **/
+    public B attachments(Supplier link) {
+      return link("attachments", link.get());
+    }
+    
+    /**
+     * Set the author
+     * @param url String
+     * @return B 
+     **/
+    public B author(String url, String... urls) {
+      if (url != null)
+        link("author", linkValue(url));
+      if (urls != null) 
+        for (String u : urls)
+          link("author", linkValue(u));
+      return (B)this;
+    }
+  
+    /**
+     * Set the author
+     * @param link LinkValue
+     * @return B 
+     **/
+    public B author(LinkValue link, LinkValue... links) {
+      if (link != null)
+        link("author", link);
+      if (links != null)
+        for (LinkValue l : links)
+          link("author", l);
+      return (B)this;
+    }
+  
+    /**
+     * Set the author
+     * @param link Supplier
+     * @return B 
+     **/
+    public B author(Supplier link) {
+      return link("author", link.get());
+    }
+
+    /**
+     * Add a duplicate
+     * @param url String
+     * @return B 
+     **/
+    public B duplicates(String url, String... urls) {
+      if (url != null)
+        link("duplicates", linkValue(url));
+      if (urls != null)
+        for (String u : urls)
+          link("duplicates", linkValue(u));
+      return (B)this;
+    }
+  
+    /**
+     * Add a duplicate
+     * @param link LinkValue
+     * @return B 
+     **/
+    public B duplicates(LinkValue link, LinkValue... links) {
+      if (link != null)
+        link("duplicates", link);
+      if (links != null)
+        for (LinkValue l : links)
+          link("duplicates", l);
+      return (B)this;
+    }
+  
+    /**
+     * Add a duplicate
+     * @param link Supplier
+     * @return B 
+     **/
+    public B duplicates(Supplier link) {
+      return link("duplicates", link.get());
+    }
+
+    /**
+     * Set the icon
+     * @param url String
+     * @return B
+     **/
+    public B icon(String url, String... urls) {
+      if (url != null)
+        link("icon", linkValue(url));
+      if (urls != null)
+        for (String u : urls)
+          link("icon", linkValue(u));
+      return (B)this;
+    }
+  
+    /**
+     * Set the icon
+     * @param link LinkValue
+     * @return B */
+    public B icon(LinkValue link, LinkValue... links) {
+      if (link != null)
+        link("icon", link);
+      if (links != null)
+        for (LinkValue l : links)
+          link("icon", l);
+      return (B)this;
+    }
+  
+    /**
+     * Set the icon
+     * @param link Supplier
+     * @return B */
+    public B icon(Supplier link) {
+      return link("icon", link.get());
+    }
+
+    /**
+     * Set the image
+     * @param url String   
+     * @return B */
+    public B image(String url, String... urls) {
+      if (url != null)
+        link("image", linkValue(url));
+      if (urls != null)
+        for (String u : urls)
+          link("image", linkValue(u));
+      return (B)this;
+    }
+  
+    /**
+     * Set the image.
+     * @param link LinkValue 
+     * @return B */
+    public B image(LinkValue link, LinkValue... links) {
+      if (link != null)
+        link("image", link);
+      if (links != null)
+        for (LinkValue l : links)
+          link("image", l);
+      return (B)this;
+    }
+  
+    /**
+     * Set the image
+     * @param link Supplier 
+     * @return B */
+    public B image(Supplier link) {
+      return link("image", link.get());
+    }
+    
+    /**
+     * Set the location
+     * @param url String
+     * @return B */
+    public B location(String url, String... urls) {
+      if (url != null)
+        link("location", linkValue(url));
+      if (urls != null)
+        for (String u : urls)
+          link("location", linkValue(u));
+      return (B)this;
+    }
+  
+    /**
+     * Set the location
+     * @param link LinkValue  
+     * @return B */
+    public B location(LinkValue link, LinkValue... links) {
+      if (link != null)
+        link("location", link);
+      if (links != null)
+        for (LinkValue u : links)
+          link("location", u);
+      return (B)this;
+    }
+  
+    /**
+     * Set the location
+     * @param link Supplier  
+     * @return B */
+    public B location(Supplier link) {
+      return link("location", link.get());
+    }
+    
+    /**
+     * Set the generator
+     * @param url String  
+     * @return B */
+    public B generator(String url, String... urls) {
+      if (url != null)
+        link("generator", linkValue(url));
+      if (urls != null)
+        for (String u : urls)
+          link("generator", linkValue(u));
+      return (B)this;
+    }
+  
+    /**
+     * Set the generator
+     * @param link LinkValue 
+     * @return B */
+    public B generator(LinkValue link, LinkValue... links) {
+      if (link != null)
+        link("generator", link);
+      if (links != null)
+        for (LinkValue u : links)
+          link("generator", u);
+      return (B)this;
+    }
+  
+    /**
+     * Set the generator.
+     * @param link Supplier  
+     * @return B */
+    public B generator(Supplier link) {
+      return link("generator", link.get());
+    }
+    
+    /**
+     * Set the provider
+     * @param url String   
+     * @return B */
+    public B provider(String url, String... urls) {
+      if (url != null)
+        link("provider", linkValue(url));
+      if (urls != null)
+        for (String u : urls)
+          link("provider", linkValue(u));
+      return (B)this;
+    }
+  
+    /**
+     * Set the provider
+     * @param link LinkValue  
+     * @return B */
+    public B provider(LinkValue link, LinkValue... links) {
+      if (link != null)
+        link("provider", link);
+      if (links != null)
+        for (LinkValue l : links)
+          link("provider",l);
+      return (B)this;
+    }
+  
+    /**
+     * Set the provider
+     * @param link Supplier 
+     * @return B */
+    public B provider(Supplier link) {
+      return link("provider", link.get());
+    }
+    
+    /**
+     * Add a tag
+     * @param url String 
+     * @return B */
+    public B tags(String url, String... urls) {
+      if (url != null)
+        link("tags", linkValue(url));
+      if (urls != null)
+        for (String u : urls)
+          link("tags", linkValue(u));
+      return (B)this;
+    }
+  
+    /**
+     * Add a tag
+     * @param link LinkValue  
+     * @return B */
+    public B tags(LinkValue link, LinkValue... links) {
+      if (link != null)
+        link("tags", link);
+      if (links != null)
+        for (LinkValue l : links)
+          link("tags", l);
+      return (B)this;
+    }
+  
+    /**
+     * Add a tag
+     * @param link Supplier  
+     * @return B */
+    public B tags(Supplier link) {
+      return link("tags", link.get());
+    }
+
+    /**
+     * Add in-reply-to
+     * @param url String  
+     * @return B 
+     **/
+    public B inReplyTo(String url, String... urls) {
+      if (url != null)
+        link("inReplyTo", linkValue(url));
+      if (urls != null)
+        for (String u : urls)
+          link("inReplyTo", linkValue(u));
+      return (B)this;
+    }
+  
+    /**
+     * Add in-reply-to
+     * @param link LinkValue   
+     * @return B */
+    public B inReplyTo(LinkValue link, LinkValue... links) {
+      if (link != null)
+        link("inReplyTo", link);
+      if (links != null)
+        for (LinkValue l : links)
+          link("inReplyTo", l);
+      return (B)this;
+    }
+  
+    /**
+     * Add in-reply-to
+     * @param link Supplier 
+     * @return B 
+     **/
+    public B inReplyTo(Supplier link) {
+      return link("inReplyTo", link.get());
+    }
+    
+    /**
+     * Add a replies collection
+     * @param collection Collection 
+     * @return B */
+    public B replies(Collection collection) {
+      return set("replies", collection);
+    }
+    
+    /**
+     * Add a replies collection
+     * @param collection Supplier
+     * @return B */
+    public B replies(Supplier collection) {
+      return set("replies", collection.get());
+    }
+     
+    /**
+     * Set the ID
+     * @param iri String
+     * @return B 
+     **/
+    public B id(String iri) {
+      return set("id", iri);
+    }
+  
+    /**
+     * Set the objectType
+     * @param iri String
+     * @return B 
+     **/
+    public B objectType(String iri) {
+      return set("objectType", type(iri));
+    }
+    
+    /**
+     * Set the objectType
+     * @param tv TypeValue
+     * @return B 
+     **/
+    public B objectType(TypeValue tv) {
+      return set("objectType", tv);
+    }
+    
+    /**
+     * Set the objectType
+     * @param tv Supplier
+     * @return B 
+     **/
+    public B objectType(Supplier tv) {
+      return objectType(tv.get());
+    }
+  
+    /**
+     * Set the language
+     * @param lang String 
+     * @return B 
+     **/
+    public B language(String lang) {
+      return set("language", lang);
+    }
+  
+    /**
+     * Set the displayName
+     * @param name String 
+     * @return B 
+     **/
+    public B displayName(String name) {
+      return _nlv("displayName", name);
+    }
+  
+    /**
+     * Set the displayName
+     * @param nlv NLV  
+     * @return B 
+     **/
+    public B displayName(NLV nlv) {
+      return _nlv("displayName", nlv);
+    }
+  
+    /**
+     * Set the displayName
+     * @param nlv Supplier 
+     * @return B 
+     **/
+    public B displayName(Supplier nlv) {
+      return _nlv("displayName", nlv);
+    }
+  
+    /**
+     * Set the displayName
+     * @param lang String
+     * @param name String   
+     * @return B 
+     **/
+    public B displayName(String lang, String name) {
+      return _nlv("displayName",lang, name);
+    }
+  
+    /**
+     * Set the displayName
+     * @param map Map   
+     * @return B 
+     **/
+    public B displayName(Map map) {
+      return _nlv("displayName", map);
+    }
+
+    /**
+     * Set the content
+     * @param name String    
+     * @return B 
+     **/
+    public B content(String name) {
+      return _nlv("content", name);
+    }
+  
+    /**
+     * Set the content
+     * @param nlv NLV 
+     * @return B 
+     **/
+    public B content(NLV nlv) {
+      return _nlv("content", nlv);
+    }
+  
+    /**
+     * Set the content
+     * @param nlv Supplier
+     * @return B 
+     **/
+    public B content(Supplier nlv) {
+      return _nlv("content", nlv);
+    }
+  
+    /**
+     * Set the content
+     * @param lang String
+     * @param name String
+     * @return B 
+     **/
+    public B content(String lang, String name) {
+      return _nlv("content",lang, name);
+    }
+  
+    /**
+     * Set the content
+     * @param map Map
+     * @return B 
+     **/
+    public B content(Map map) {
+      return _nlv("content", map);
+    }
+
+    /**
+     * Set the summary
+     * @param name String
+     * @return B 
+     **/
+    public B summary(String name) {
+      return _nlv("summary", name);
+    }
+  
+    /**
+     * Set the summary
+     * @param nlv NLV
+     * @return B 
+     **/
+    public B summary(NLV nlv) {
+      return _nlv("summary", nlv);
+    }
+  
+    /**
+     * Set the summary
+     * @param nlv Supplier
+     * @return B 
+     **/
+    public B summary(Supplier nlv) {
+      return _nlv("summary", nlv);
+    }
+  
+    /**
+     * Set the summary
+     * @param lang String
+     * @param name String
+     * @return B 
+     **/
+    public B summary(String lang, String name) {
+      return _nlv("summary",lang, name);
+    }
+    
+    /**
+     * Set the summary
+     * @param map Map
+     * @return B 
+     **/
+    public B summary(Map map) {
+      return _nlv("summary", map);
+    }
+
+    /**
+     * Set the title
+     * @param name String
+     * @return B 
+     **/
+    public B title(String name) {
+      return _nlv("title", name);
+    }
+  
+    /**
+     * Set the title
+     * @param nlv NLV
+     * @return B 
+     **/
+    public B title(NLV nlv) {
+      return _nlv("title", nlv);
+    }
+  
+    /**
+     * Set the title
+     * @param nlv Supplier
+     * @return B 
+     **/
+    public B title(Supplier nlv) {
+      return _nlv("title", nlv);
+    }
+  
+    /**
+     * Set the title
+     * @param lang String
+     * @param value String
+     * @return B 
+     **/
+    public B title(String lang, String value) {
+      return _nlv("title",lang, value);
+    }
+  
+    /**
+     * Set the title
+     * @param map Map
+     * @return B 
+     **/
+    public B title(Map map) {
+      return _nlv("title", map);
+    }
+    
+    /**
+     * Add an action handler
+     * @param verb String
+     * @param iri String
+     * @return B
+     */
+    public B action(String verb, String iri, String... iris) {
+      if (iri != null)
+        actions.set(verb, iri);
+      if (iris != null)
+        for (String i : iris)
+          actions.set(verb, i);
+      return (B)this;
+    }
+    
+    /**
+     * Add an action handler
+     * @param verb String
+     * @param lv LinkValue
+     * @return B
+     */
+    public B action(String verb, LinkValue lv, LinkValue... links) {
+      if (lv != null)
+        actions.set(verb, lv);
+      if (links != null)
+        for (LinkValue l : links)
+          actions.set(verb, l);
+      return (B)this;
+    }
+    
+    /**
+     * Add an action handler
+     * @param verb String
+     * @param lv Supplier
+     * @return B
+     */
+    public B action(String verb, Supplier lv) {
+      return action(verb, lv.get());
+    }
+        
+    /**
+     * Method _nlv.
+     * @param key String
+     * @param value String
+     * @return B
+     **/
+    protected B _nlv(String key, String value) {
+      return set(key, nlv(value));
+    }
+  
+    /**
+     * Method _nlv.
+     * @param key String
+     * @param nlv NLV
+     * @return B 
+     **/
+    protected B _nlv(String key, NLV nlv) {
+      return set(key, nlv);
+    }
+  
+    /**
+     * Method _nlv.
+     * @param key String
+     * @param nlv Supplier
+     * @return B 
+     **/
+    protected B _nlv(String key, Supplier nlv) {
+      return set(key, nlv.get());
+    }
+  
+    /**
+     * Method _nlv.
+     * @param key String
+     * @param map Map
+     * @return B 
+     **/
+    protected B _nlv(String key, Map map) {
+      for (Map.Entry entry : map.entrySet())
+        _nlv(key,entry.getKey(),entry.getValue());
+      return (B)this;
+    }
+    
+    /**
+     * Method _nlv.
+     * @param key String
+     * @param lang String
+     * @param value String
+     * @return B 
+     **/
+    protected B _nlv(String key, String lang, String value) {
+      if (map.containsKey(key)) {
+        Object obj = map.get(key);
+        if (obj instanceof NLV) {
+          NLV nlv = (NLV) obj;
+          switch(nlv.valueType()) {
+          case SIMPLE:
+            String l = (String) map.get("language");
+            if (l == null)
+              l = DEFAULT_LOCALE;
+            NLV.MapNLV.Builder b = 
+              Makers.nlv();
+            if (lang.equals(l))
+              b.set(lang, value);
+            else
+              b.set(l, ((NLV.SimpleNLV)obj).value())
+                 .set(lang, value);
+            return set(key, b);
+          case OBJECT:
+            return set(key, 
+              Makers.nlv()
+                .from((NLV.MapNLV)obj, lang)
+                .set(lang, value)); 
+          default:
+            throw new IllegalArgumentException();
+          }
+        } else if (obj instanceof NLV.MapNLV.Builder) {
+          ((NLV.MapNLV.Builder) obj).set(lang, value);
+          return (B)this;
+        }
+      }
+      set(key, Makers.nlv().set(lang,value));      
+      return (B)this;
+    }
+    
+    /**
+     * Set the "url"
+     * @param url String
+     * @return B 
+     **/
+    public B url(String url, String... urls) {
+      if (url != null)
+        link("url", linkValue(url));
+      if (urls != null)
+        for (String u : urls)
+          link("url", linkValue(u));
+      return (B)this;
+    }
+    
+    /**
+     * Set the "url"
+     * @param link Supplier
+     * @return B 
+     **/
+    public B url(Supplier link) {
+      return url(link.get());
+    }
+  
+    /**
+     * Set the "url"
+     * @param link LinkValue
+     * @return B 
+     **/
+    public B url(LinkValue link, LinkValue... links) {
+      if (link != null)
+        link("url", link);
+      if (links != null)
+        for (LinkValue l : links)
+          link("url", l);
+      return (B)this;
+    }
+    
+    /**
+     * Add a link
+     * @param name String
+     * @param url String
+     * @return B 
+     **/
+    public B link(String name, String url) {
+      return link(name, linkValue(url));
+    }
+    
+    /**
+     * Add a link
+     * @param name String
+     * @param link LinkValue   
+     * @return B 
+     **/
+    public B link(String name, LinkValue link) {
+      if (link == null)
+        return (B)this;
+      Object obj = map.get(name);
+      if (link.valueType() != ValueType.ARRAY) {
+        if (obj instanceof LinkValue)
+          link = 
+            ((LinkValue) obj).valueType() == ValueType.ARRAY ?
+              linkValues()
+                .add((LinkValue.ArrayLinkValue)obj)
+                .add(link)
+                .get() :
+              linkValues()
+                .add((LinkValue)obj, link)
+                .get();
+        map.put(name, link);
+      } else set(name, link);
+      return (B)this;
+    }
+  
+    /**
+     * Add a link
+     * @param name String
+     * @param link Supplier
+     * @return B 
+     **/
+    public B link(String name, Supplier link) {
+      return link(name,link.get());
+    }
+
+    /**
+     * Add a link
+     * @param name String
+     * @param links Object[]
+     * @return B 
+     **/
+    protected B link(String name, Object... links) {
+      if (links == null) return (B)this;
+      ArrayLinkValue.Builder b = 
+        ArrayLinkValue.make();
+      for (Object obj : links)
+        _add(b, obj);
+      return link(name,b.get());
+    }
+    
+    /**
+     * Method _add.
+     * @param builder ArrayLinkValue.Builder
+     * @param obj Object
+     */
+    private void _add(ArrayLinkValue.Builder builder, Object obj) {
+      if (obj == null)
+        return;
+      else if (obj instanceof String)
+        builder.add((String)obj);
+      else if (obj instanceof ASObject)
+        builder.add((ASObject)obj);
+      else if (obj instanceof Supplier)
+        _add(builder,((Supplier)obj).get());
+      else throw new IllegalArgumentException();
+    }
+  
+    /**
+     * Set a property
+     * @param key String
+     * @param value V
+     * @return B 
+     **/
+    public B set(String key, Object value) {
+      if (value == null) 
+        return (B)this;
+      if (value instanceof Supplier)
+        map.put(key, ((Supplier)value).get());
+      else
+        map.put(key, value);
+      return (B)this;
+    }
+    
+    /**
+     * Set a property
+     * @param key String
+     * @param value Supplier
+     * @return B 
+     **/
+    public B set(String key, Supplier value) {
+      try {
+        return value == null ?
+          (B)this : set(key,value.get());
+      } catch (Throwable t) {
+        throw propagate(t);
+      }
+    }
+    
+    /**
+     * Set a property from a given callable
+     * @param key String
+     * @param value Callable
+     * @return B 
+     **/
+    public B set(String key, Callable value) {
+      try {
+        return value == null ?
+          (B)this : 
+          set(key,value.call());
+      } catch (Throwable t) {
+        throw propagate(t);
+      }
+    }
+    
+    /**
+     * Set the scope
+     * @param url String
+     * @return B 
+     **/
+    public B scope(String url, String... urls) {
+      if (url != null)
+        link("scope", linkValue(url));
+      if (urls != null)
+        for (String u : urls)
+          link("scope", linkValue(u));
+      return (B)this;
+    }
+  
+    /**
+     * Set the scope
+     * @param link LinkValue
+     * @return B 
+     **/
+    public B scope(LinkValue link, LinkValue... links) {
+      if (link != null)
+        link("scope", link);
+      if (links != null)
+        for (LinkValue l : links)
+          link("scope", l);
+      return (B)this;
+    }
+  
+    /**
+     * Set the scope
+     * @param link Supplier
+    
+     * @return B */
+    public B scope(Supplier link) {
+      return link("scope", link.get());
+    }   
+  }
+  
+  protected final ImmutableMap map;
+  private transient int hash = 1;
+  
+  /**
+   * Constructor for ASObject.
+   * @param builder ASObject.AbstractBuilder
+   */
+  public ASObject(ASObject.AbstractBuilder builder) {
+    super(builder);
+    if (builder.actions.notEmpty())
+      builder.map.put("actions", builder.actions.get());
+    this.map = ImmutableMap.copyOf(builder.map);
+  }
+  
+  /**
+   * Returns true if the given property exists, does not 
+   * determine if the value is non-null
+   * @param key String
+   * @return boolean 
+   **/
+  public boolean has(String key) {
+    return map.containsKey(key);
+  }
+  
+  /**
+   * Return the value of the property if it exists, null otherwise
+   * @param key String
+   * @return V 
+   **/
+  public V get(String key) {
+    return this._get(key).orNull();
+  }
+  
+  /**
+   * Return the value of the property if it exists, casting to a DateTime
+   * object.
+   * @param key String
+   * @return DateTime
+   */
+  public DateTime getDateTime(String key) {
+    return this.get(key,toDateTime,Optional.absent()).orNull();
+  }
+  
+  /**
+   * Return the value of the property if it exists, converting the value
+   * to the given Enum class. 
+   * @param key String
+   * @param _enumClass Class
+   * @return E
+   */
+  public >E getEnum(String key, Class _enumClass) {
+    return getEnum(key, _enumClass, (E)null);
+  }
+  
+  /**
+   * Method getEnum.
+   * @param key String
+   * @param _enumClass Class
+   * @param or E
+   * @return E
+   */
+  public >E getEnum(String key, Class _enumClass, E or) {
+    String val = getString(key);
+    Optional op = getIfPresent(_enumClass, val);
+    return or != null ?
+      op.or(or) : op.orNull();
+  }
+  
+  /**
+   * Return the value of the property if it exists, casting to a String
+   * object.
+   * @param key String
+   * @return String
+   */
+  public String getString(String key) {
+    return getString(key, null);
+  }
+  
+  /**
+   * Method getDuration.
+   * @param key String
+   * @return Duration
+   */
+  public Duration getDuration(String key) {
+    return this.get(key, toDuration, Optional.absent()).orNull();
+  }
+  
+  /**
+   * Method getPeriod.
+   * @param key String
+   * @return Period
+   */
+  public Period getPeriod(String key) {
+    return this.get(key, toPeriod, Optional.absent()).orNull();
+  }
+  
+  /**
+   * Method getInterval.
+   * @param key String
+   * @return Interval
+   */
+  public Interval getInterval(String key) {
+    return this.get(key, toInterval, Optional.absent()).orNull();
+  }
+  
+  /**
+   * Return the value of the property as a string if it exists or defaultValue if 
+   * it does not. 
+   * @param key String
+   * @param defaultValue String
+   * @return String
+   */
+  public String getString(String key, String defaultValue) {
+    return defaultValue != null ?
+      this._get(key).or(defaultValue) :
+      this._get(key).orNull();
+  }
+  
+  /**
+   * Return the value of the property as an int if it exists or 0 if it does not.
+   * @param key String
+   * @return int
+   */
+  public int getInt(String key) {
+    return getInt(key, 0);
+  }
+  
+  /**
+   * Return the value of the property as an int if it exists or defaultValue if
+   * it does not
+   * @param key String
+   * @param defaultValue int
+   * @return int
+   */
+  public int getInt(String key, int defaultValue) {
+    return get(key, toInt, Optional.absent()).or(defaultValue);
+  }
+  
+  /**
+   * Return the value of the property as a long if it exists or 0 if it does not
+   * @param key String
+   * @return long
+   */
+  public long getLong(String key) {
+    return getLong(key,0L);
+  }
+  
+  /**
+   * Return the value of the property as a long if it exists or defaultValue if
+   * it does not
+   * @param key String
+   * @param defaultValue long
+   * @return long
+   */
+  public long getLong(String key, long defaultValue) {
+    return get(key, toLong, Optional.absent()).or(defaultValue);
+  }
+  
+  /**
+   * Return the value of the property as a double if it exists, or 0.0 if it
+   * does not
+   * @param key String
+   * @return double
+   */
+  public double getDouble(String key) {
+    return getDouble(key, 0.0);
+  }
+  
+  /**
+   * Return the value of the property as a double if it exists or defaultValue
+   * if it does not
+   * @param key String
+   * @param defaultValue double
+   * @return double
+   */
+  public double getDouble(String key, double defaultValue) {
+    return get(key, toDouble, Optional.absent()).or(defaultValue);
+  }
+  
+  /**
+   * Return the value of the property as a float if it exists or 0f if it 
+   * does not
+   * @param key String
+   * @return float
+   */
+  public float getFloat(String key) {
+    return getFloat(key, 0f);
+  }
+  
+  /**
+   * Return the value of the property as a float if it exists or defaultValue
+   * if it does not
+   * @param key String
+   * @param defaultValue float
+   * @return float
+   */
+  public float getFloat(String key, float defaultValue) {
+    return get(key, toFloat, Optional.absent()).or(defaultValue);
+  }
+  
+  /**
+   * Return the value of the property as a short if it exists or 0 if it 
+   * does not
+   * @param key String
+   * @return short
+   */
+  public short getShort(String key) {
+    return getShort(key,(short)0);
+  }
+  
+  /**
+   * Return the value of the property as a short if it exists or defaultValue
+   * if it does not
+   * @param key String
+   * @param defaultValue short
+   * @return short
+   */
+  public short getShort(String key, short defaultValue) {
+    return get(key, toShort, Optional.absent()).or(defaultValue);
+  }
+  
+  /**
+   * return the value of the property as a boolean if it exists or false 
+   * if it does not
+   * @param key String
+   * @return boolean
+   */
+  public boolean getBoolean(String key) {
+    return getBoolean(key,false);
+  }
+  
+  /**
+   * Return the value of the property as a boolean if it exists or defaultValue
+   * if it does not
+   * @param key String
+   * @param defaultValue boolean
+   * @return boolean
+   */
+  public boolean getBoolean(
+    String key, 
+    boolean defaultValue) {
+      return get(key, toBoolean, Optional.absent()).or(defaultValue);
+  }
+  
+  /**
+   * Method _get.
+   * @param key String
+   * @return Optional
+   */
+  private Optional _get(String key) {
+    return Optional.fromNullable((V)map.get(key));
+  }
+  
+  /**
+   * Method _get.
+   * @param key String
+   * @param transform Function
+   * @return Optional
+   */
+  private Optional _get(String key, Function transform) {
+    return this._get(key).transform(transform);
+  }
+  
+  /**
+   * Return the value if it exists or defaultValue if it does not
+   * @param key String
+   * @param defaultValue V
+   * @return V 
+   **/
+  public V get(String key, V defaultValue) {
+    return defaultValue != null ?
+      this._get(key).or(defaultValue) :
+      this._get(key).orNull();
+  }
+  
+  /**
+   * Returns the value of the property, transformed using the given function
+   * @param key String
+   * @param transform Function
+   * @return V2 
+   **/
+  public V2 get(String key, Function transform, V2 defaultValue) {
+    return this._get(key,transform).or(defaultValue);
+  }
+  
+  /**
+   * Returns the value of the given property converted using the given converter
+   * @param key String
+   * @param converter Converter
+   * @return V2
+   */
+  public V2 get(String key, Converter converter) {
+    return this._get(key,converter).orNull();
+  }
+  
+  /**
+   * Returns the value of the property if it exists or defaultValue if it
+   * does not
+   * @param key String
+   * @param def V2
+   * @param transform Function
+   * @return V2 
+   **/
+  public V2 get(String key, V2 def, Function transform) {
+    return this._get(key,transform).or(def);
+  }
+
+  /**
+   * Returns an iterator listing all of the properties defined on this object
+   * @return Iterator 
+   * @see java.lang.Iterable#iterator() 
+   **/
+  public Iterator iterator() {
+    return map.keySet().iterator();
+  }
+  
+  /**
+   * Return this objects identifier
+   * @return String 
+   * @see com.ibm.common.activitystreams.TypeValue#id() 
+   **/
+  public String id() {
+    return this.getString("id");
+  }
+  
+  /**
+   * Return the objectType
+   * @return T 
+   **/
+  public T objectType() {
+    return this.get("objectType");
+  }
+  
+  /**
+   * Return this object's type identifier as a string
+   * @return String 
+   **/
+  public String objectTypeString() {
+    return typeValueAsString("objectType");
+  }
+  
+  /**
+   * Method typeValueAsString.
+   * @param name String
+   * @return String 
+   **/
+  protected String typeValueAsString(String name) {
+    TypeValue tv = this.get(name);
+    return tv != null ? tv.id() : null;
+  }
+  
+  /**
+   * Return this object's language context
+   * @return String 
+   **/
+  public String language() {
+    return this.getString("language");
+  }
+  
+  /**
+   * Return this objects displayName as an NLV object
+   * @return NLV 
+   **/
+  public NLV displayName() {
+    return this.get("displayName");
+  }
+  
+  /**
+   * Return this objects displayName
+   * @return String 
+   **/
+  public String displayNameString() {
+    return _nlv("displayName");
+  }
+  
+  /**
+   * Method displayNameString.
+   * @param lang String
+   * @return String 
+   **/
+  public String displayNameString(String lang) {
+    return _nlv("displayName", lang);
+  }
+  
+  /**
+   * Method _nlv.
+   * @param key String
+   * @return String 
+   **/
+  protected String _nlv(String key) {
+    String lang = language();
+    return _nlv(key, lang != null ? lang : DEFAULT_LOCALE);
+  }
+  
+  /**
+   * Method _nlv.
+   * @param key String
+   * @param lang String
+   * @return String 
+   **/
+  protected String _nlv(String key, String lang) {
+    NLV nlv = 
+      this.get(key);
+    switch(nlv.valueType()) {
+    case SIMPLE:
+      NLV.SimpleNLV sim = 
+        (SimpleNLV) nlv;
+      String l = language();
+      return l == null || Objects.equal(l,lang) ? sim.value() : null;
+    case OBJECT:
+      NLV.MapNLV map = 
+       (MapNLV) nlv;
+      return map.value(lang);
+    default:
+      return null;
+    } 
+  }
+  
+  /**
+   * Return this objects URL LinkValues
+   * @return java.util.Iterable<LinkValue> 
+   **/
+  public Iterable url() {
+    return links("url");
+  }
+  
+  /**
+   * Return the matching URL LinkValues
+   * @return java.util.Iterable<LinkValue>
+   **/
+  public Iterable url(Predicate test) {
+    return links("url", test);
+  }
+  
+  /**
+   * Return this objects first URL LinkValue
+   * @return LinkValue
+   */
+  public LinkValue firstUrl() {
+    return firstLink("url");
+  }
+  
+  /**
+   * Return this objects first matching LinkValue
+   * @param test
+   * @return LinkValue
+   */
+  public LinkValue firstMatchingUrl(Predicate test) {
+    return firstMatchingLink("url", test);
+  }
+  
+  /**
+   * Return this object's mediaType
+   * @return MediaType 
+   **/
+  public MediaType mediaType() {
+    return this.get("mediaType");
+  }
+  
+  /**
+   * Returns the value of this objects's rel property
+   * @return String 
+   **/
+  public String rel() {
+    return this.getString("rel");
+  }
+  
+  /**
+   * Returns this value of this object's alias property
+   * @return String 
+   **/
+  public String alias() {
+    return this.getString("alias");
+  }
+  
+  /**
+   * Return the given set of links
+   * @param name String
+   * @return java.util.Iterable 
+   **/
+  protected Iterable links(String name) {
+    LinkValue lv = this.get(name);
+    if (lv == null) return of();
+    return lv.valueType() == ValueType.ARRAY ?
+      (Iterable)lv : of(lv);
+  }
+  
+  protected Iterable links(
+    String name, 
+    Predicate test) {
+      return filter(links(name), test);
+  }
+  
+  protected LinkValue firstLink(String name) {
+    return getFirst(links(name), null);
+  }
+  
+  protected LinkValue firstMatchingLink(
+    String name, 
+    Predicate test) {
+      return getFirst(links(name,test), null);
+  }
+  
+  /**
+   * Return the set of attachments
+   * @return java.util.Iterable 
+   **/
+  public Iterable attachments() {
+    return links("attachments");
+  }
+  
+  /**
+   * Return the matching set of attachments;
+   * @param test
+   * @return java.util.Iterable<LinkValue>
+   */
+  public Iterable attachments(Predicate test) {
+    return links("attachments", test);
+  }
+  
+  /**
+   * Return the first attachment for this object
+   * @return LinkValue
+   */
+  public LinkValue firstAttachment() {
+    return firstLink("attachments");
+  }
+  
+  /**
+   * Return the first matching attachment
+   * @param test
+   * @return LinkValue
+   */
+  public LinkValue firstMatchingAttachment(Predicate test) {
+    return firstMatchingLink("attachments", test);
+  }
+  
+  /**
+   * Return this authors of this object
+   * @return java.util.Iterable 
+   **/
+  public Iterable author() {
+    return links("author");
+  }
+  
+  /**
+   * Return the matching authors of this object
+   * @return java.util.Iterable
+   */
+  public Iterable author(Predicate test) {
+    return links("author", test);
+  }
+  
+  /**
+   * Return the first author
+   * @return LinkValue
+   */
+  public LinkValue firstAuthor() {
+    return firstLink("author");
+  }
+  
+  /**
+   * Return the first matching author
+   * @param test
+   * @return LinkValue
+   */
+  public LinkValue firstMatchingAuthor(Predicate test) {
+    return firstMatchingLink("author", test);
+  }
+  
+  /**
+   * Return the collection of duplicates for this object
+   * @return java.util.Iterable 
+   **/
+  public Iterable duplicates() {
+    return links("duplicates");
+  }
+  
+  /**
+   * Return the matching duplicates
+   * @param test
+   * @return java.util.Iterable<LinkValue>
+   */
+  public Iterable duplicates(Predicate test) {
+    return links("duplicates", test);
+  }
+  
+  /**
+   * Return the first duplicate
+   * @return LinkValue
+   */
+  public LinkValue firstDuplicate() {
+    return firstLink("duplicates");
+  }
+  
+  /**
+   * Return the first matching duplicate
+   * @param test
+   * @return LinkValue
+   */
+  public LinkValue firstMatchingDuplicate(Predicate test) {
+    return firstMatchingLink("duplicates", test);
+  }
+  
+  /**
+   * Return the icons for this object
+   * @return java.util.Iterable */
+  public Iterable icon() {
+    return links("icon");
+  }
+  
+  /**
+   * Return the matching icons for this object
+   * @return java.util.Iterable
+   */
+  public Iterable icon(Predicate test) {
+    return links("icon", test);
+  }
+  
+  /**
+   * Return the first icon
+   * @return LinkValue
+   */
+  public LinkValue firstIcon() {
+    return firstLink("icon");
+  }
+  
+  /**
+   * Return thie first matching icon
+   * @param test
+   * @return LinkValue
+   */
+  public LinkValue firstMatchingIcon(Predicate test) {
+    return firstMatchingLink("icon", test);
+  }
+  
+  /**
+   * Return the image for this object
+   * @return java.util.Iterable
+   **/
+  public Iterable image() {
+    return links("image");
+  }
+  
+  /**
+   * Return the matching images for this object
+   * @param test
+   * @return java.util.Iterable
+   */
+  public Iterable image(Predicate test) {
+    return links("image", test);
+  }
+  
+  /**
+   * Return the first image
+   * @return LinkValue
+   */
+  public LinkValue firstImage() {
+    return firstLink("image");
+  }
+  
+  /**
+   * Return the first matching image
+   * @param test
+   * @return LinkValue
+   */
+  public LinkValue firstMatchingImage(Predicate test) {
+    return firstMatchingLink("image", test);
+  }
+  
+  /**
+   * Return the location associated with this object
+   * @return java.util.Iterable 
+   **/
+  public Iterable location() {
+    return links("location");
+  }
+  
+  /**
+   * Return the matching locations associated with this object
+   * @param test
+   * @return java.util.Iterable
+   */
+  public Iterable location(Predicate test) {
+    return links("location", test);
+  }
+  
+  /**
+   * Return the first location associated with this object
+   * @return LinkValue
+   */
+  public LinkValue firstLocation() {
+    return firstLink("location");
+  }
+  
+  /**
+   * Return the first matching location associated with this object
+   * @param test
+   * @return LinkValue
+   */
+  public LinkValue firstMatchingLocation(Predicate test) {
+    return firstMatchingLink("location", test);
+  }
+  
+  /**
+   * Return the generators for this object
+   * @return java.util.Iterable 
+   **/
+  public Iterable generator() {
+    return links("generator");
+  }
+  
+  /**
+   * Return the matching generators for this object
+   * @return java.util.Iterable
+   */
+  public Iterable generator(Predicate test) {
+    return links("generator", test);
+  }
+  
+  /**
+   * Return the first generator for this object
+   * @return LinkValue
+   */
+  public LinkValue firstGenerator() {
+    return firstLink("generator");
+  }
+  
+  /**
+   * Return the first matching generator for this object
+   * @param test
+   * @return LinkValue
+   */
+  public LinkValue firstMatchingGenerator(Predicate test) {
+    return firstMatchingLink("generator", test);
+  }
+  
+  /**
+   * Return the providers for this object
+   * @return java.util.Iterable 
+   **/
+  public Iterable provider() {
+    return links("provider");
+  }
+  
+  /**
+   * Return the matching providers for this object
+   * @return java.util.Iterable
+   */
+  public Iterable provider(Predicate test) {
+    return links("provider", test);
+  }
+  
+  /**
+   * Return the first provider for this object
+   * @return LinkValue
+   */
+  public LinkValue firstProvider() {
+    return firstLink("provider");
+  }
+  
+  /**
+   * Return the first matching providers for this object
+   * @param test
+   * @return LinkValue
+   */
+  public LinkValue firstMatchingProvider(Predicate test) {
+    return firstMatchingLink("provider", test);
+  }
+  
+  /**
+   * Return the tags for this object
+   * @return java.util.Iterable 
+   **/
+  public Iterable tags() {
+    return links("tags");
+  }
+  
+  /**
+   * Return the matching tags for this object
+   * @return java.util.Iterable
+   */
+  public Iterable tags(Predicate test) {
+    return links("tags", test);
+  }
+  
+  /**
+   * Return the first tag for this object
+   * @return LinkValue
+   */
+  public LinkValue firstTag() {
+    return firstLink("tags");
+  }
+  
+  /**
+   * Return this first matching tag for this object
+   * @param test
+   * @return LinkValue
+   */
+  public LinkValue firstMatchingTag(Predicate test) {
+    return firstMatchingLink("tags", test);
+  }
+  
+  /**
+   * Return the inReplyTo links for this object
+   * @return java.util.Iterable 
+   **/
+  public Iterable inReplyTo() {
+    return links("inReplyTo");
+  }
+  
+  /**
+   * Return the matching inReplyTo links for this object
+   * @return java.util.Iterable
+   */
+  public Iterable inReplyTo(Predicate test) {
+    return links("inReplyTo", test);
+  }
+  
+  /**
+   * Return the first inReplyTo link for this object
+   * @return LinkValue
+   */
+  public LinkValue firstInReplyTo() {
+    return firstLink("inReplyTo");
+  }
+  
+  /**
+   * Return the first matching inReplyTo link for this object
+   * @param test
+   * @return LinkValue
+   */
+  public LinkValue firstMatchingInReplyTo(Predicate test) {
+    return firstMatchingLink("inReplyTo", test);
+  }
+  
+  /**
+   * Return the content of this object
+   * @return NLV 
+   **/
+  public NLV content() {
+    return this.get("content");
+  }
+  
+  /**
+   * Return the content of this object
+   * @return String 
+   **/
+  public String contentString() {
+    return _nlv("content");
+  }
+  
+  /**
+   * Return the content of this object for the given language
+   * @param lang String
+   * @return String */
+  public String contentString(String lang) {
+    return _nlv("content", lang);
+  }
+  
+  /**
+   * Return the title of this object
+   * @return NLV 
+   **/
+  public NLV title() {
+    return this.get("title");
+  }
+  
+  /**
+   * Return the title of this object
+   * @return String 
+   **/
+  public String titleString() {
+    return _nlv("title");
+  }
+  
+  /**
+   * Return the title of this object for the given language
+   * @param lang String
+   * @return String 
+   **/
+  public String titleString(String lang) {
+    return _nlv("title", lang);
+  }
+  
+  /**
+   * Return the summary of this object
+   * @return NLV 
+   **/
+  public NLV summary() {
+    return this.get("summary");
+  }
+  
+  /**
+   * Return the summary of this object
+   * @return String 
+   **/
+  public String summaryString() {
+    return _nlv("summary");
+  }
+  
+  /**
+   * Return the summary of this object for the given language
+   * @param lang String
+   * @return String */
+  public String summaryString(String lang) {
+    return _nlv("summary", lang);
+  }
+  
+  /**
+   * Return the published timestamp for this object
+   * @return DateTime */
+  public DateTime published() {
+    return this.getDateTime("published");
+  }
+  
+  /**
+   * Return the updated timestamp for this object
+   * @return DateTime 
+   **/
+  public DateTime updated() {
+    return this.getDateTime("updated");
+  }
+  
+  /**
+   * Return the startTime timestamp for this object
+   * @return DateTime 
+   **/
+  public DateTime startTime() {
+    return this.getDateTime("startTime");
+  }
+  
+  /**
+   * Return the endTime timestamp for this object
+   * @return DateTime 
+   **/
+  public DateTime endTime() {
+    return this.getDateTime("endTime");
+  }
+  
+  /**
+   * Return the rating property for this object
+   * @return double 
+   **/
+  public double rating() {
+    return checkRating(getDouble("rating"));
+  }
+  
+  /**
+   * Return the duration of this object
+   * @return Duration 
+   **/
+  public Duration duration() {
+    return this.get("duration", toDuration, Optional.absent()).orNull();
+  }
+  
+  /**
+   * Return the height of this object in device independent pixels
+   * @return int 
+   **/
+  public int height() {
+    return checkNotNegative(getInt("height"));
+  }
+  
+  /**
+   * Return the width of this object in device independent pixels
+   * @return int 
+   **/
+  public int width() {
+    return checkNotNegative(getInt("width"));
+  }
+  
+  /**
+   * Return the replies collection for this object
+   * @return Collection */
+  public Collection replies() {
+    return this.get("replies");
+  }
+  
+  /**
+   * Return the actions collection for this object
+   * @return ActionsValue 
+   */
+  public ActionsValue actions() {
+    return this.get("actions");
+  }
+  
+  /**
+   * Return the scope
+   * @return java.util.Iterable 
+   **/
+  public Iterable scope() {
+    return links("scope");
+  }
+  
+  /**
+   * Return the matching scope items
+   * @return java.util.Iterable
+   */
+  public Iterable scope(Predicate test) {
+    return links("scope", test);
+  }
+  
+  /**
+   * Return the first scope item
+   * @return LinkValue
+   */
+  public LinkValue firstScope() {
+    return firstLink("scope");
+  }
+  
+  /**
+   * Return the first matching scope item
+   * @param test
+   * @return LinkValue
+   */
+  public LinkValue firstMatchingScope(Predicate test) {
+    return firstMatchingLink("scope", test);
+  }
+
+  @Override
+  public int hashCode() {
+    if (hash == 1)
+      hash = Objects.hashCode(map);
+    return hash;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj)
+      return true;
+    if (obj == null)
+      return false;
+    if (getClass() != obj.getClass())
+      return false;
+    ASObject other = (ASObject) obj;
+    return 
+      difference(map, other.map)
+        .areEqual();
+  }
+  
+  /**
+   * Return the valueType of this object (always returns ValueType.OBJECT)
+   * @return ValueType
+   * @see com.ibm.common.activitystreams.LinkValue#valueType()
+   */
+  public ValueType valueType() {
+    return ValueType.OBJECT;
+  }
+  
+  
+  // Java Serialization support... 
+  
+  Object writeReplace() throws java.io.ObjectStreamException {
+    return new SerializedForm(this);
+  }
+  
+  private static class SerializedForm 
+    extends AbstractSerializedForm {
+    protected SerializedForm(ASObject obj) {
+      super(obj);
+    }
+    private static final long serialVersionUID = -1975376657749952999L;
+    protected ASObject.Builder builder() {
+      return Makers.object();
+    }
+    Object readResolve() throws ObjectStreamException {
+      return super.doReadResolve();
+    }
+  }
+  
+  protected static abstract class AbstractSerializedForm 
+    implements Serializable {
+    private static final long serialVersionUID = -801787904013409277L;
+    private ImmutableMap map;
+    protected AbstractSerializedForm(A obj) {      
+      this.map = ImmutableMap.copyOf(Maps.transformValues(obj.map, SerializableTransform));
+    }
+    protected abstract ASObject.AbstractBuilder builder();
+    protected Object doReadResolve() 
+      throws java.io.ObjectStreamException {
+        ASObject.AbstractBuilder builder = builder();
+        for (Map.Entry entry : map.entrySet()) {
+          Object obj = entry.getValue();
+          if (obj instanceof SerializableMediaType)
+            obj = ((SerializableMediaType)obj).mediaType();
+          builder.set(entry.getKey(), obj);
+        }
+        return builder.get();
+    }
+  }
+  
+  private static final Function SerializableTransform = 
+    new Function() {
+      public Object apply(Object input) {
+        if (input instanceof MediaType)
+          input = new SerializableMediaType((MediaType) input);
+        return input;
+      }
+    };
+  
+  private static final class SerializableMediaType 
+    implements Serializable {
+    private static final long serialVersionUID = -3162545492169619570L;
+    private String mediaType;
+    SerializableMediaType(MediaType mt) {
+      this.mediaType = mt.toString();
+    }
+    MediaType mediaType() {
+      return MediaType.parse(mediaType);
+    }
+  }
+}
diff --git a/core/src/main/java/com/ibm/common/activitystreams/ActionsValue.java b/core/src/main/java/com/ibm/common/activitystreams/ActionsValue.java
new file mode 100755
index 0000000..f92060d
--- /dev/null
+++ b/core/src/main/java/com/ibm/common/activitystreams/ActionsValue.java
@@ -0,0 +1,213 @@
+package com.ibm.common.activitystreams;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.ibm.common.activitystreams.util.AbstractDictionaryObject;
+
+/**
+ * 

The value of the "actions" property... used to map potential verbs + * with objects capable of "handling" those verbs. Each of the keys + * must be a valid verb (either a token or an absolute IRI).

+ * + *

Specifying Actions while creating AS Objects:

+ * + *
+ * import static com.ibm.common.activitystreams.Makers.object;
+ * import static com.ibm.common.activitystreams.Makers.actions;
+ * import static com.ibm.common.activitystreams.actions.ActionMakers.intentAction;
+ * ...
+ * 
+ * ASObject obj = object()
+ *   .action("like", "http://example.org/like-action")
+ *   .action("follow", intentAction())
+ *   .get();
+ * 
+ * + *

Accessing Actions when consuming AS Objects:

+ * + *
+ * ActionsValue actions = obj.actions();
+ * for (LinkValue lv : actions.get("like")) {
+ *   ...
+ * }
+ * 
+ * + *

The Actions object itself is a JSON Dictonary that maps + * verb identifiers to a Link Value that contains one or more + * Action Handlers. A call to the get(...) method returns an + * Iterable of Simple or Object LinkValue instances representing + * each of the associated Action Handlers.

+ * + *

A Serialized Activity Stream object with Actions: + *

+ * {
+ *   "objectType": "note",
+ *   "displayName": "My Note",
+ *   "actions": { 
+ *     "like": "http://example.org/like-action",
+ *     "follow": {
+ *       "objectType": "IntentActionHandler",
+ *       "displayName": "Follow updates to this note!"
+ *     }
+ *   }
+ * }
+ * 
+ * + * @author james + * @version $Revision: 1.0 $ + */ +public final class ActionsValue + extends AbstractDictionaryObject + implements Serializable { + + /** + * Builder for ActionsValue objects. + *
+   *   Makers.actions()
+   *     .set("like", "http://example.org/like-action")
+   *     .set("follow", ActionMakers.intentAction())
+   *     .get();
+   * 
+ */ + public static final class Builder + extends AbstractDictionaryObject.AbstractBuilder + { + + protected Builder() {} + + /** + * Add an action handler for the given verb. + * Calling this multiple times results in + * multiple action handlers. + * @param verb String + * @param iri String + * @return Builder + */ + public Builder set(String verb, String iri) { + return set( + verb, + LinkValue.SimpleLinkValue.make(iri)); + } + + @Override + public Builder set(String key, LinkValue x) { + return super.link(key, x); + } + + @Override + public Builder set(String key, Supplier x) { + return super.link(key, x); + } + + /** + * Get the built ActionsValue instance + * @return ParametersValue + * @see com.google.common.base.Supplier#get() + **/ + public ActionsValue get() { + return new ActionsValue(this); + } + + } + + private ActionsValue(Builder builder) { + super(builder); + } + + /** + * Get all Action Handlers associated with the given verb. + * @param verb String + * @return java.util.Iterable + */ + public Iterable get(String verb) { + return super.getIterable(verb); + } + + /** + * Get all Action Handlers associated with the given verb + * that satisfy the given filter + * @param verb String + * @param filter Predicate + * @return java.util.Iterable + */ + public Iterable get( + String verb, + Predicate filter) { + return super.getIterable(verb, filter); + } + + /** + * Get all Action Handlers associated with the given verb, + * transformed using the given Transform function + * @param verb String + * @param transform Function + * @return java.util.Iterable + */ + public Iterable get( + String verb, + Function transform) { + return super.getIterable(verb, transform); + } + + /** + * Get all Action Handlers associated with the given verb, + * filtered using the given Predicate and transformed + * using the given Transform function. + * @param verb String + * @param filter Predicate + * @param transform Function + * @return java.util.Iterable + */ + public Iterable get( + String verb, + Predicate filter, + Function transform) { + return super.getIterable(verb, filter, transform); + } + + /** + * True if there is at least one Action Handler associated + * with the given verb + * @param verb String + * @return boolean + */ + public boolean hasAtLeastOne(String verb) { + return super.hasAtLeastOne(verb); + } + + // Java serialization support + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + implements Serializable { + private static final long serialVersionUID = -1975376657749952999L; + private ImmutableMap map; + SerializedForm(ActionsValue obj) { + ImmutableMap.Builder builder = + ImmutableMap.builder(); + for (String key : obj) + builder.put(key, obj.get(key)); + this.map = builder.build(); + } + @SuppressWarnings("unchecked") + Object readResolve() + throws java.io.ObjectStreamException { + ActionsValue.Builder builder = + Makers.actions(); + for (Map.Entry entry : map.entrySet()) { + Iterable list = (Iterable) entry.getValue(); + for (LinkValue link : list) + builder.set(entry.getKey(), link); + } + return builder.get(); + } + } +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/Activity.java b/core/src/main/java/com/ibm/common/activitystreams/Activity.java new file mode 100755 index 0000000..b805684 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/Activity.java @@ -0,0 +1,832 @@ +package com.ibm.common.activitystreams; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.lang.Math.floor; +import static java.lang.Math.ceil; +import static com.ibm.common.activitystreams.Makers.linkValue; +import static com.ibm.common.activitystreams.Makers.type; + +import java.io.ObjectStreamException; +import java.io.Serializable; + +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; + + +/** + * An Activity Streams 2.0 Activity + * + *

Creating an Activity:

+ *
+ *   import static com.ibm.common.activitystreams.Makers.activity;
+ *   import static com.ibm.common.activitystreams.Makers.object;
+ *   ...
+ * 
+ *   Activity activity = activity()
+ *     .actor("acct:joe@example.org")
+ *     .verb("post")
+ *     .object(object().content("This is a note"))
+ *     .get();
+ * 
+ * + *

Consuming an Activity:

+ *
+ *   Activity activity = IO.makeDefault().readAsActivity(...);
+ *   
+ *   System.out.println(activity.verbAsString());   
+ *   ASObject actor = activity.firstActor();
+ *   ASObject object = activity.firstObject();
+ * 
+ * + * @author james + * @version $Revision: 1.0 $ + */ +public class Activity + extends ASObject + implements Serializable { + + public static enum Audience { + /** + * Primary public audience + **/ + TO, + /** + * Primary private audience + **/ + BTO, + /** + * Secondary public audience + **/ + CC, + /** + * Secondary private audience + **/ + BCC, + /** + * Public origin + **/ + FROM, + /** + * Private origin + **/ + BFROM; + + private final String label; + + private Audience() { + this.label = name().toLowerCase(); + } + + /** + * Returns the "from" target(s) + * @return java.util.Iterable<LinkValue>*/ + private Iterable get( + Activity activity) { + return activity.links(label); + } + + private Iterable get( + Activity activity, + Predicate filter) { + return activity.links(label, filter); + } + + private LinkValue first(Activity activity) { + return activity.firstLink(label); + } + + private LinkValue firstMatching( + Activity activity, + Predicate test) { + return activity.firstMatchingLink(label, test); + } + } + + public static enum Status { + /** The Activity is tentatively scheduled to begin **/ + TENTATIVE, + /** The Activity is scheduled to begin **/ + PENDING, + /** The Activity has been completed **/ + COMPLETED, + /** The Activity has been canceled or aborted **/ + CANCELED, + /** The Activity is currently active **/ + ACTIVE, + /** The Activity has been voided. **/ + VOIDED, + OTHER + } + + /** + * + * Builder for concrete Activity object instances. + * + * @author james + * @version $Revision: 1.0 $ + */ + public static final class Builder + extends Activity.AbstractBuilder { + + /** + * Get the built Activity object + * @return Activity + * @see com.google.common.base.Supplier#get() + */ + public Activity get() { + return new Activity(this); + } + + } + + /** + * Ensures that the priority value is within the acceptable range (0.0-1.0) + * @param d double + * @return double + */ + private static double checkPriority(double d) { + checkArgument(floor(d) >= 0 && ceil(d) >= 1); + return d; + } + + /** + * Abstract builder for Activity classes. This is defined this way + * to make it easier to build extensions of the Activity class. + * @author james + * @version $Revision: 1.0 $ + */ + @SuppressWarnings("unchecked") + public static abstract class AbstractBuilder +
> + extends ASObject.AbstractBuilder { + + /** + * Set the Activity status property. + * @param status Status + * @return B + */ + public B status(Status status) { + if (status != null) + set("status", status); + return (B)this; + } + + /** + * Mark the status of this activity as being "voided" + * @return B + */ + public B voided() { + return status(Status.VOIDED); + } + + /** + * Mark the status of this activity as being "tentative" + * @return B + */ + public B tentative() { + return status(Status.TENTATIVE); + } + + /** + * Mark the status of this activity as being "pending" + * @return B + */ + public B pending() { + return status(Status.PENDING); + } + + /** + * Mark the status of this activity as being "active" + * @return B + */ + public B active() { + return status(Status.ACTIVE); + } + + /** + * Mark the status of this activity as being "canceled" + * @return B + */ + public B canceled() { + return status(Status.CANCELED); + } + + /** + * Mark the status of this activity as being "completed" + * @return B + */ + public B completed() { + return status(Status.COMPLETED); + } + + /** + * Set the verb for this activity + * @param iri String + * @return B + */ + public B verb(String iri) { + set("verb", type(iri)); + return (B)this; + } + + /** + * Set the verb for this activity + * @param tv TypeValue + * @return B + */ + public B verb(TypeValue tv) { + set("verb", tv); + return (B)this; + } + + /** + * Set the verb for this activity + * @param tv Supplier + * @return B + */ + public B verb(Supplier tv) { + return verb(tv.get()); + } + + /** + * Set a participant that indirectly contributed to the activity. + * @param url String + * @return B + **/ + public B participant(String url, String... urls) { + if (url != null) + link("participant", linkValue(url)); + if (urls != null) + for (String u : urls) + link("participant", linkValue(u)); + return (B)this; + } + + /** + * Set a participant that indirectly contributed to the activity + * @param link LinkValue + * @return B + */ + public B participant(LinkValue link, LinkValue... links) { + if (link != null) + link("participant", link); + if (links != null) + for (LinkValue l : links) + link("participant", l); + return (B)this; + } + + /** + * Set a participant that indirectly contributed to the activity + * @param link Supplier + * @return B + */ + public B participant(Supplier link) { + return link("participant", link.get()); + } + + /** + * Set the instrument used to complete the activity + * @param url String + * @return B + */ + public B instrument(String url, String... urls) { + if (url != null) + link("instrument", linkValue(url)); + if (urls != null) + for (String u : urls) + link("instument", linkValue(u)); + return (B)this; + } + + /** + * Set the instrument used to complete the activity + * @param link LinkValue + * @return B + */ + public B instrument(LinkValue link, LinkValue... links) { + if (link != null) + link("instrument", link); + if (links != null) + for (LinkValue l : links) + link("instrument", l); + return (B)this; + } + + /** + * Set the instrument used to complete the activity + * @param link Supplier + * @return B + */ + public B instrument(Supplier link) { + return link("instrument", link.get()); + } + + /** + * Set the primary actor/agent for this activity + * @param url String + * @return B + */ + public B actor(String url, String... urls) { + if (url != null) + link("actor", linkValue(url)); + if (urls != null) + for (String u : urls) + link("actor", linkValue(u)); + return (B)this; + } + + /** + * Set the primary actor/agent for this activity + * @param link LinkValue + * @return B + */ + public B actor(LinkValue link, LinkValue... links) { + if (link != null) + link("actor", link); + if (links != null) + for (LinkValue l : links) + link("actor", l); + return (B)this; + } + + /** + * Set the actor + * @param link Supplier + * @return B + */ + public B actor(Supplier link) { + return link("actor", link.get()); + } + + /** + * Set the direct object of this activity (the object that has been + * or will be acted upon) + * @param url String + * @return B + */ + public B object(String url, String... urls) { + if (url != null) + link("object", linkValue(url)); + if (urls != null) + for (String u : urls) + link("object", linkValue(u)); + return (B)this; + } + + /** + * Set the direct object of this activity (the object that has been + * or will be acted upon) + * @param link LinkValue + * @return B + */ + public B object(LinkValue link, LinkValue... links) { + if (link != null) + link("object", link); + if (links != null) + for (LinkValue l : links) + link("object", l); + return (B)this; + } + + /** + * Set the direct object of this activity (the object that has been + * or will be acted upon) + * @param link Supplier + * @return B + */ + public B object(Supplier link) { + return link("object", link.get()); + } + + /** + * Set an object that is indirectly affected by the activity + * @param url String + * @return B + */ + public B target(String url, String... urls) { + if (url != null) + link("target", linkValue(url)); + if (urls != null) + for (String u : urls) + link("target", linkValue(u)); + return (B)this; + } + + /** + * Set an object that is indirectly affected by the activity + * @param link LinkValue + * @return B + */ + public B target(LinkValue link, LinkValue... links) { + if (link != null) + link("target", link); + if (links != null) + for (LinkValue l : links) + link("target", l); + return (B)this; + } + + /** + * Set an object that is indirectly affected by the activity + * @param link Supplier + * @return B + */ + public B target(Supplier link) { + return link("target", link.get()); + } + + /** + * Set a URI that describes the result of this activity + * @param url String + * @return B + */ + public B result(String url, String... urls) { + if (url != null) + link("result", linkValue(url)); + if (urls != null) + for (String u : urls) + link("result", linkValue(u)); + return (B)this; + } + + /** + * Set an object that describes the result of this activity + * @param link LinkValue + * @return B + */ + public B result(LinkValue link, LinkValue... links) { + if (link != null) + link("result", link); + if (links != null) + for (LinkValue l : links) + link("result", l); + return (B)this; + } + + /** + * Set an object that describes the result of this activity + * @param link Supplier + * @return B + */ + public B result(Supplier link) { + return link("result", link.get()); + } + + /** + * Set the audience for this activity + * @param audience + * @param url + * @param urls + * @return B + */ + public B audience(Audience audience, String url, String... urls) { + link(audience.label, linkValue(url)); + for (String u : urls) + link(audience.label, u); + return (B)this; + } + + /** + * Set the audience for this activity + * @param audience + * @param link + * @param links + * @return B + */ + public B audience(Audience audience, LinkValue link, LinkValue... links) { + link(audience.label, link); + for (LinkValue lv : links) + link(audience.label, lv); + return (B)this; + } + + /** + * Set the audience for this activity + * @param audience + * @param link + * @return B + */ + public B audience(Audience audience, Supplier link) { + return link(audience.label, link); + } + + /** + * Set the priority as value in the range 0.00 to 1.00. + * Value will be checked to ensure it is within the valid range. + * The value SHOULD be limited to two decimal places but the + * number of decimals will not be checked. + * @param d double + * @return B + * @throws IllegalArgumentException if the value is not within 0.00-1.00 + */ + public B priority(double d) { + return set("priority", checkPriority(d)); + } + } + + Activity(Activity.AbstractBuilder builder) { + super(builder); + } + + /** + * returns the verb as TypeValue object + * @return T + **/ + public T verb() { + return this.get("verb"); + } + + /** + * Returns the verb as a string + * @return String + **/ + public String verbString() { + return typeValueAsString("verb"); + } + + /** + * Return the participant(s) + * @return java.util.Iterable<LinkValue> + **/ + public Iterable participant() { + return links("participant"); + } + + /** + * Return the matching participant(s) + * @param filter + * @return java.util.Iterable + */ + public Iterable participant(Predicate filter) { + return links("participant", filter); + } + + /** + * Return the first paticipant + * @return LinkValue + */ + public LinkValue firstParticipant() { + return firstLink("participant"); + } + + /** + * Return the first matching participant + * @param test + * @return LinkValue + */ + public LinkValue firstMatchingParticipant(Predicate test) { + return firstMatchingLink("participan", test); + } + + /** + * Return the instrument(s) + * @return java.util.Iterable<LinkValue> + **/ + public Iterable instrument() { + return links("instrument"); + } + + /** + * Return the matching instrument(s) + * @param filter + * @return java.util.Iterable + */ + public Iterable instrument(Predicate filter) { + return links("instrument", filter); + } + + /** + * Return the first instrument + * @return LinkValue + */ + public LinkValue firstInstrument() { + return firstLink("instrument"); + } + + /** + * Return the first matching instrument + * @param test + * @return LinkValue + */ + public LinkValue firstMatchingInstrument(Predicate test) { + return firstMatchingLink("instrument", test); + } + + /** + * Returns the actor(s) + * @return java.util.Iterable<LinkValue> + **/ + public Iterable actor() { + return links("actor"); + } + + /** + * Return the matching actor(s) + * @param filter + * @return java.util.Iterable + */ + public Iterable actor(Predicate filter) { + return links("actor", filter); + } + + /** + * Return the first actor + * @return LinkValue + */ + public LinkValue firstActor() { + return firstLink("actor"); + } + + /** + * Return the first matching actor + * @param test + * @return LinkValue + */ + public LinkValue firstMatchingActor(Predicate test) { + return firstMatchingLink("actor", test); + } + + /** + * Returns the object(s) + * @return java.util.Iterable<LinkValue> + **/ + public Iterable object() { + return links("object"); + } + + /** + * Return the matching object(s) + * @param filter + * @return java.util.Iterable + */ + public Iterable object(Predicate filter) { + return links("object", filter); + } + + /** + * Return the first object + * @return LinkValue + */ + public LinkValue firstObject() { + return firstLink("object"); + } + + /** + * Return the first matching object + * @param test + * @return LinkValue + */ + public LinkValue firstMatchingObject(Predicate test) { + return firstMatchingLink("object", test); + } + + /** + * Returns the target(s) + * @return java.util.Iterable<LinkValue> + **/ + public Iterable target() { + return links("target"); + } + + /** + * Return the matching target(s) + * @param filter + * @return java.util.Iterable + */ + public Iterable target(Predicate filter) { + return links("target", filter); + } + + /** + * Return the first target + * @return LinkValue + */ + public LinkValue firstTarget() { + return firstLink("target"); + } + + /** + * Return the first matching target + * @param test + * @return LinkValue + */ + public LinkValue firstMatchingTarget(Predicate test) { + return firstMatchingLink("target", test); + } + + /** + * Returns the result(s) + * @return java.util.Iterable<LinkValue> + **/ + public Iterable result() { + return links("result"); + } + + /** + * Returns the matching result(s) + * @param filter + * @return java.util.Iterable<LinkValue> + */ + public Iterable result(Predicate filter) { + return links("result", filter); + } + + /** + * Return the first result + * @return LinkValue + */ + public LinkValue firstResult() { + return firstLink("result"); + } + + /** + * Return the first matching result + * @param test + * @return LinkValue + */ + public LinkValue firstMatchingResult(Predicate test) { + return firstMatchingLink("result", test); + } + + /** + * Returns the priority. + * @return double + * @throws IllegalArgumentException if the priority is not within + * the range 0.00-1.00 + **/ + public double priority() { + return checkPriority(getDouble("priority")); + } + + /** + * Return the audience for this activity + * @param audience + * @return java.util.Iterable<LinkValue> + */ + public Iterable audience( + Audience audience) { + return audience.get(this); + } + + /** + * Return the audience for this activity + * @param audience + * @param filter + * @return java.util.Iterable<LinkValue> + */ + public Iterable audience( + Audience audience, + Predicate filter) { + return audience.get(this,filter); + } + + /** + * Return the first audience for this activity + * @param audience + * @return LinkValue + */ + public LinkValue firstAudience(Audience audience) { + return audience.first(this); + } + + /** + * Return the first matching audience for this activity + * @param audience + * @param test + * @return LinkValue + */ + public LinkValue firstMatchingAudience( + Audience audience, + Predicate test) { + return audience.firstMatching(this, test); + } + + /** + * Return the status of this activity + * @return Status + */ + public Status status() { + return get("status"); + } + + // Java Serialization Support + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + protected SerializedForm(Activity obj) { + super(obj); + } + private static final long serialVersionUID = -1975376657749952999L; + protected Activity.Builder builder() { + return Makers.activity(); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + } +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/Collection.java b/core/src/main/java/com/ibm/common/activitystreams/Collection.java new file mode 100755 index 0000000..d9e7129 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/Collection.java @@ -0,0 +1,504 @@ +package com.ibm.common.activitystreams; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.ibm.common.activitystreams.Makers.linkValue; +import static com.google.common.collect.Iterables.filter; + +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.concurrent.TimeUnit; + +import org.joda.time.DateTime; +import org.joda.time.ReadableDuration; +import org.joda.time.ReadablePeriod; + +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +/** + * + * An Activity Streams collection object + * + *
+ *   import static com.ibm.common.activitystreams.Makers.collection;
+ *   import static com.ibm.common.activitystreams.Makers.object;
+ *   ...
+ * 
+ *   Collection collection = collection()
+ *     .items(object()...)
+ *     .items(object()...)
+ *     .get();
+ * 
+ * + * @author james + * @version $Revision: 1.0 $ + */ +@SuppressWarnings("unchecked") +public class Collection + extends ASObject + implements Serializable { + + /** Standardized Paging Links **/ + public static enum Page { + /** + * Reference to the first page in the logical set + **/ + FIRST, + /** + * Reference to the next page in the logical set + **/ + NEXT, + /** + * Reference to the final page in the logical set + * **/ + LAST, + /** + * Reference to the previous page in the logical set + **/ + PREVIOUS, + /** + * Reference to the previous page in the logical set (treated as an alias for "previous") + * @deprecated Use Page.PREVIOUS instead + **/ + PREV, + /** + * Reference to the page containing the most recently published/updated + * items in the logical set + **/ + CURRENT, + /** + * Reference to this page + **/ + SELF; + + private final String label; + private Page() { + this.label = name().toLowerCase(); + } + + private String checkPrev(Collection col, String or) { + if (this == PREVIOUS) { + if (!col.has(label) && col.has(PREV.label)) + return PREV.label; + } else if (this == PREV) { + if (!col.has(label) && col.has(PREVIOUS.label)) + return PREVIOUS.label; + } + return or; + } + + private Iterable links(Collection col) { + return col.links(checkPrev(col,label)); + } + + private Iterable links( + Collection col, + Predicate filter) { + return col.links(checkPrev(col,label), filter); + } + + private LinkValue first(Collection col) { + return col.firstLink(checkPrev(col,label)); + } + + private LinkValue firstMatching( + Collection col, + Predicate filter) { + return col.firstMatchingLink(checkPrev(col,label), filter); + } + } + + /** + * @author james + * @version $Revision: 1.0 $ + */ + public static final class Builder + extends Collection.AbstractBuilder { + + /** + * Method create. + * @return Collection */ + protected Collection create() { + return new Collection(this); + } + + } + + /** + * @author james + * @version $Revision: 1.0 $ + */ + public static abstract class AbstractBuilder +
> + extends ASObject.AbstractBuilder { + + protected final ImmutableList.Builder list = + ImmutableList.builder(); + + /** + * Method create. + * @return A + **/ + protected abstract A create(); + + /** + * Method get. + * @return A + * @see com.google.common.base.Supplier#get() + **/ + public A get() { + set("items", list.build()); + return create(); + } + + /** + * Add items to this collection + * @param objs java.util.Iterable + * @return B + */ + public B items(Iterable objs) { + if (objs == null) + return (B)this; + for (ASObject obj : objs) + items(obj); + return (B)this; + } + + /** + * Add items to this collection + * @param obj ASObject The object to add + * @param objs ASObject[] Additional objects to add (vararg) + * @return B + **/ + public B items(ASObject obj, ASObject... objs) { + if (obj == null) + return (B)this; + list.add(obj); + if (objs != null) + for (ASObject o : objs) + list.add(o); + return (B)this; + } + + /** + * Add an item to this collection + * @param obj com.google.common.base.Supplier + * @return B + **/ + public B items(Supplier obj) { + if (obj == null) + return (B)this; + items(obj.get()); + return (B)this; + } + + /** + * Set the total number of items (must be non-negative) + * @param i int + * @return B + **/ + public B totalItems(int i) { + checkArgument(i >= 0); + set("totalItems", i); + return (B)this; + } + + /** + * Set the number of items per page (must be non-negative) + * @param i int + * @return B + **/ + public B itemsPerPage(int i) { + checkArgument(i >= 0); + set("itemsPerPage", i); + return (B)this; + } + + /** + * Set the starting index (must be non-negative) + * @param i int + * @return B + **/ + public B startIndex(int i) { + checkArgument(i >= 0); + set("startIndex", i); + return (B)this; + } + + /** + * Specify that the collection contains items updated after the specified time + * @param dt DateTime + * @return B + **/ + public B itemsAfter(DateTime dt) { + return _dt("itemsAfter", dt); + } + + /** + * Specify that the collection contains items updated after right now + * @return B + */ + public B itemsAfterNow() { + return _dtNow("itemsAfter"); + } + + /** + * Specify that the collection contains items updated a specific duration after now + * @param duration Duration + * @return B + */ + public B itemsAfterFromNow(ReadableDuration duration) { + return _dtFromNow("itemsAfter", duration); + } + + /** + * Specify that the collection contains items updated a specific period after now + * @param period + * @return B + */ + public B itemsAfterFromNow(ReadablePeriod period) { + return _dtFromNow("itemsAfter", period); + } + + /** + * Specify that the collection contains items updated a specific duration after now + * @param v long + * @param unit TimeUnit + * @return B + **/ + public B itemsAfterFromNow(long v, TimeUnit unit) { + return _dtFromNow("itemsAfter", v, unit); + } + + /** + * Specify that the collection contains items updated before a specific time + * @param dt DateTime + * @return B + **/ + public B itemsBefore(DateTime dt) { + return _dt("itemsBefore", dt); + } + + /** + * Specify that the collection contains items updated before now + * @return B + */ + public B itemsBeforeNow() { + return _dtNow("itemsBefore"); + } + + /** + * Specify that the collection contains items updated a specific duration + * before now + * @param duration Duration + * @return B + */ + public B itemsBeforeFromNow(ReadableDuration duration) { + return _dtFromNow("itemsBefore", duration); + } + + /** + * Specify that the collection contains items updated a specific period + * before now + * @param period + * @return B + */ + public B itemsBeforeFromNow(ReadablePeriod period) { + return _dtFromNow("itemsBefore", period); + } + + /** + * Method itemsBeforeFromNow. + * @param v long + * @param unit TimeUnit + * @return B + **/ + public B itemsBeforeFromNow(long v, TimeUnit unit) { + return _dtFromNow("itemsBefore", v, unit); + } + + /** + * Adds a paging link + *
+     *   Collection collection = Makers.collection()
+     *     .pageLink(Page.NEXT, "http://example.org")
+     *     .get();
+     * 
+ * @param page + * @param url + * @return B + */ + public B pageLink(Page page, String url) { + return link(page.label, linkValue(url)); + } + + /** + * Adds a paging link + * @param page + * @param link + * @return B + */ + public B pageLink(Page page, LinkValue link) { + return link(page.label, link); + } + + /** + * Adds a paging link + * @param page + * @param link + * @return B + */ + public B pageLink(Page page, Supplier link) { + return link(page.label, link); + } + + } + + /** + * Constructor for Collection. + * @param builder Collection.AbstractBuilder + */ + Collection(Collection.AbstractBuilder builder) { + super(builder); + } + + /** + * Returns the total number of items + * @return int + **/ + public int totalItems() { + return getInt("totalItems"); + } + + /** + * If not null, indicates that the collection only contains items + * updated after the given instant + * @return DateTime + **/ + public DateTime itemsAfter() { + return this.getDateTime("itemsAfter"); + } + + /** + * If not null, indicates that the collection only contains items + * updated before the given instant + * @return DateTime + * */ + public DateTime itemsBefore() { + return this.getDateTime("itemsBefore"); + } + + /** + * Returns the number of items per page + * @return int + **/ + public int itemsPerPage() { + return this.getInt("itemsPerPage"); + } + + /** + * Returns the start index for this page + * @return int + **/ + public int startIndex() { + return this.getInt("startIndex"); + } + + /** + * Returns a listing of Paging links that + * exist on this collection + * @return Iterable<Page> + */ + public Iterable pages() { + ImmutableSet.Builder pages = + ImmutableSet.builder(); + for (Page page : Page.values()) + if (has(page.label)) + pages.add(page); + return pages.build(); + } + + /** + * Returns a listing of Paging LinkValues + * @param page Page The type of paging link to return + * @return Iterable<LinkValue> + */ + public Iterable pageLink( + Page page) { + return page.links(this); + } + + /** + * Returns a listing of Paging LinkValues + * @param page Page The type of paging link to return + * @param filter Predicate A filter + * @return Iterable<LinkValue> + */ + public Iterable pageLink( + Page page, + Predicate filter) { + return page.links(this,filter); + } + + /** + * Returns the first matching paging LinkValue + * @param page Page The type of paging link to return + * @return LinkValue + */ + public LinkValue firstPageLink( + Page page) { + return page.first(this); + } + + /** + * Returns the first matching paging LinkValue + * @param page Page the type of paging link to return + * @param test com.google.common.base.Predicate a filter + * @return LinkValue + */ + public LinkValue firstMatchingPageLink( + Page page, + Predicate test) { + return page.firstMatching(this,test); + } + + /** + * Returns the collection of items + * @return java.util.Iterable
+ **/ + public Iterable items() { + return this.>get("items"); + } + + /** + * Returns a filtered collection of items + * @param filter com.google.common.base.Predicate filter + * @return java.util.Iterable + */ + public Iterable items( + Predicate filter) { + return filter(this.items(), filter); + } + + // Java Serialization Support + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + protected SerializedForm(Collection obj) { + super(obj); + } + private static final long serialVersionUID = -1975376657749952999L; + protected Collection.Builder builder() { + return Makers.collection(); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + } +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/IO.java b/core/src/main/java/com/ibm/common/activitystreams/IO.java new file mode 100755 index 0000000..c88c498 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/IO.java @@ -0,0 +1,614 @@ +package com.ibm.common.activitystreams; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableSet; +import com.ibm.common.activitystreams.internal.Adapter; +import com.ibm.common.activitystreams.internal.GsonWrapper; +import com.ibm.common.activitystreams.internal.Schema; +import com.ibm.common.activitystreams.util.Module; + +/** + * The IO object is responsible for serializing and deserializing + * Activity Stream objects. Instances of IO should be created and + * defined statically. IO instances are threadsafe and immutable + * once created. + * + *

You can choose to use one of the default IO instances:

+ * + *
+ *   public static final IO io = IO.makeDefault();
+ *   
+ *   public static final IO prettyIo = IO.makeDefaultPrettyPrint();
+ * 
+ * + *

Or you can use the IO.Builder to construct and configure your + * own IO instance with custom adapters, object properties and + * type mappings:

+ * + *
+ *   import static 
+ * 
+ *   public static final IO io = 
+ *   IO.make()
+ *     .schema(
+ *       Makers.makeSchema().map(
+ *         Schema.object.template()
+ *           .as("foo", Foo.class)))
+ *     .adapter(Foo.class, new MyFooAdapter())
+ *     .get();
+ * 
+ * + *

Once created, you can use IO instances to parse Activity Streams + * documents:

+ * + *
+ *  InputStream in = ...
+ *  Activity activity = io.readAsActivity(in);
+ * 
+ * + *

Or can use the IO instance to serialize:

+ * + *
+ *   OutputStream out = ...
+ *   Activity activity = ...
+ *   activity.writeTo(out, io);
+ * 
+ * + * @author james + * @version $Revision: 1.0 $ + */ +public final class IO { + + /** + * Create a new IO.Builder + * @return Builder */ + public static Builder make() { + return new Builder(); + } + + /** + * Create a new IO.Builder that uses the given schema + * @param schema Schema + * @return IO + */ + public static IO makeWithSchema(Schema schema) { + return make().schema(schema).get(); + } + + /** + * Create a new IO.Builder that uses the given schema + * @param schema Supplier + * @return IO + */ + public static IO makeWithSchema(Supplier schema) { + return makeWithSchema(schema.get()); + } + + /** + * Make or return the default IO instance + * @return IO + **/ + public static IO makeDefault(Module... modules) { + IO.Builder builder = make(); + if (modules != null) + for (Module mod : modules) + builder.using(mod); + return builder.get(); + } + + /** + * Make or return a default IO instance with Pretty Print enabled + * @return IO + */ + public static IO makeDefaultPrettyPrint(Module... modules) { + IO.Builder builder = make().prettyPrint(); + if (modules != null) + for (Module mod : modules) + builder.using(mod); + return builder.get(); + } + + public static class Builder + implements Supplier { + + private final GsonWrapper.Builder inner = + GsonWrapper.make(); + private Schema schema; + private final ImmutableSet.Builder modules = + ImmutableSet.builder(); + + public Builder using(Module module) { + modules.add(module); + return this; + } + + public Builder typeValueResolver(Function resolver) { + inner.typeValueResolver(resolver); + return this; + } + + /** + * Turn pretty print on or off + * @param on boolean + * @return Builder + **/ + public Builder prettyPrint(boolean on) { + inner.prettyPrint(on); + return this; + } + + /** + * Turn pretty print on + * @return Builder + **/ + public Builder prettyPrint() { + return prettyPrint(true); + } + + /** + * Add an adapter + * @param type Class + * @param adapter Adapter + * @return Builder + **/ + public Builder adapter( + Class type, + Adapter adapter) { + inner.adapter(type, adapter); + return this; + } + + /** + * Add an adapter + * @param type Class<? extends T> + * @return Builder + */ + public Builder adapter( + Class type) { + return adapter(type,null); + } + + /** + * Add an adapter + * @param type Class<? extends T> + * @return Builder + */ + public Builder hierarchicalAdapter( + Class type) { + return hierarchicalAdapter(type,null); + } + + /** + * Add an adapter. + * @param type Class + * @param adapter Adapter + * @param hier boolean + * @return Builder + **/ + public Builder hierarchicalAdapter( + Class type, + Adapter adapter) { + inner.adapter(type, adapter, true); + return this; + } + + /** + * Set the schema + * @param schema Schema + * @return Builder + **/ + public Builder schema(Schema schema) { + //inner.schema(schema); + this.schema = schema; + return this; + } + + /** + * Set the schema. + * @param schema Supplier + * @return Builder + **/ + public Builder schema(Supplier schema) { + return schema(schema.get()); + } + + public IO get() { + Iterable mods = modules.build(); + Schema schema = this.schema; + if (schema == null) { + Schema.Builder builder = Schema.make(); + for (Module mod : mods) + mod.apply(builder); + schema = builder.get(); + } + inner.schema(schema); + for (Module module : modules.build()) + module.apply(this, schema); + return new IO(this); + } + } + + private final GsonWrapper gson; + + protected IO(Builder builder) { + this.gson = + builder.inner.get(); + } + + /** + * Write the given object + * @param w Writable + * @return String + */ + public String write(Writable w) { + StringWriter sw = new StringWriter(); + w.writeTo(sw,this); + return sw.toString(); + } + + /** + * Asynchronously write the given object + * @param w + * @param executor + * @return java.util.concurrent.Future<String> + */ + public Future write( + final Writable w, + ExecutorService executor) { + return executor.submit( + new Callable() { + public String call() throws Exception { + return write(w); + } + } + ); + } + + /** + * Write the object to the given outputstream + * @param w Writable + * @param out OutputStream + */ + public void write(Writable w, OutputStream out) { + gson.write(w,out); + } + + /** + * Asychronously write the object to the given output stream + * @param w + * @param out + * @param executor + * @return java.util.concurrent.Future<?> + */ + public Future write( + final Writable w, + final OutputStream out, + ExecutorService executor) { + return executor.submit( + new Runnable() { + public void run() { + write(w, out); + } + } + ); + } + + /** + * Asychronously write the object to the given writer + * @param w + * @param out + * @param executor + * @return java.util.concurrent.Future<?> + */ + public Future write( + final Writable w, + final Writer out, + ExecutorService executor) { + return executor.submit( + new Runnable() { + public void run() { + write(w, out); + } + } + ); + } + + /** + * Write the object to the given writer + * @param w Writable + * @param out Writer + */ + public void write(Writable w, Writer out) { + gson.write(w,out); + } + + /** + * Asynchronously read the given input stream and + * return a parsed object of the given type + * @param in + * @param type + * @param executor + * @return java.util.concurrent.Future<A extends ASObject> + */ + public
Future readAs( + final InputStream in, + final Class type, + ExecutorService executor) { + return executor.submit( + new Callable() { + public A call() throws Exception { + return readAs(in, type); + } + } + ); + } + + /** + * Read the given input stream and return a parsed object + * of the given type + * @param in InputStream + * @param type Class + * @return A */ + public A readAs( + InputStream in, + Class type) { + return gson.readAs(in, type); + } + + /** + * Asynchronously read the given reader and return a parsed + * object of the given type + * @param in + * @param type + * @param executor + * @return java.util.concurrent.Future<A extends ASObject> + */ + public Future readAs( + final Reader in, + final Class type, + ExecutorService executor) { + return executor.submit( + new Callable() { + public A call() throws Exception { + return readAs(in, type); + } + } + ); + } + + /** + * Read the given reader and return a parsed object of the given type + * @param in Reader + * @param type Class + * @return A */ + public A readAs( + Reader in, + Class type) { + return gson.readAs(in, type); + } + + /** + * Asynchronously read the given string and return a parsed object of + * the given type + * @param in + * @param type + * @param executor + * @return java.util.concurrent.Future<A extends ASObject> + */ + public Future readAs( + final String in, + final Class type, + ExecutorService executor) { + return executor.submit( + new Callable() { + public A call() throws Exception { + return readAs(in, type); + } + } + ); + } + + /** + * Read the given string and return a parsed object of the given type + * @param in String + * @param type Class + * @return A + */ + public A readAs( + String in, + Class type) { + return readAs(new StringReader(in),type); + } + + /** + * Asynchronously read the given string + * @param in + * @param executor + * @return java.util.concurrent.Future<ASObject> + */ + public Future read(String in, ExecutorService executor) { + return read(new StringReader(in), executor); + } + + /** + * Read the given string + * @param in String + * @return ASObject + */ + public ASObject read(String in) { + return read(new StringReader(in)); + } + + /** + * Asynchronously read the given inputstream + * @param in + * @param executor + * @return java.util.concurrent.Future<ASObject> + */ + public Future read(InputStream in, ExecutorService executor) { + return readAs(in, ASObject.class, executor); + } + + /** + * Asynchronously read the given reader + * @param in + * @param executor + * @return java.util.concurrent.Future<ASObject> + */ + public Future read(Reader in, ExecutorService executor) { + return readAs(in, ASObject.class, executor); + } + + /** + * Read the given input stream. + * @param in InputStream + * @return ASObject + **/ + public ASObject read(InputStream in) { + return readAs(in, ASObject.class); + } + + /** + * Return the given input stream + * @param in InputStream + * @return A + */ + @SuppressWarnings("unchecked") + public A readAs(InputStream in) { + return (A)read(in); + } + + /** + * Read the given string as an Activity object + * @param in String + * @return Activity + */ + public Activity readAsActivity(String in) { + return readAsActivity(new StringReader(in)); + } + + /** + * Asynchronously read the given string as an Activity object + * @param in + * @param executor + * @return java.util.concurrent.Future<Activity> + */ + public Future readAsActivity(String in, ExecutorService executor) { + return readAsActivity(new StringReader(in), executor); + } + + /** + * Asynchronously read the given inputstream as an Activity object + * @param in + * @param executor + * @return java.util.concurrent.Future<Activity> + */ + public Future readAsActivity(InputStream in, ExecutorService executor) { + return readAs(in, Activity.class, executor); + } + + /** + * Asynchronously read the given reader as an Activity object + * @param in + * @param executor + * @return java.util.concurrent.Future<Activity> + */ + public Future readAsActivity(Reader in, ExecutorService executor) { + return readAs(in, Activity.class, executor); + } + + /** + * Asynchronously read the given string as a Collection object + * @param in + * @param executor + * @return java.util.concurrent.Future<Collection> + */ + public Future readAsCollection(String in, ExecutorService executor) { + return readAsCollection(new StringReader(in), executor); + } + + /** + * Asynchronously read the given input stream as a Collection object + * @param in + * @param executor + * @return java.util.concurrent.Future<Collection> + */ + public Future readAsCollection(InputStream in, ExecutorService executor) { + return readAs(in, Collection.class, executor); + } + + /** + * Asynchronously read the given reader as a Collection object + * @param in + * @param executor + * @return java.util.concurrent.Future<Collection> + */ + public Future readAsCollection(Reader in, ExecutorService executor) { + return readAs(in, Collection.class, executor); + } + + /** + * Read the given inputstream as an Activity. + * @param in InputStream + * @return Activity + **/ + public Activity readAsActivity(InputStream in) { + return readAs(in, Activity.class); + } + + /** + * Read the given string as a Collection. + * @param in InputStream + * @return Collection + **/ + public Collection readAsCollection(String in) { + return readAsCollection(new StringReader(in)); + } + + /** + * Read the given inputstream as a Collection. + * @param in InputStream + * @return Collection + **/ + public Collection readAsCollection(InputStream in) { + return readAs(in, Collection.class); + } + + /** + * Read the given reader + * @param in + * @return ASObject + */ + public ASObject read(Reader in) { + return readAs(in, ASObject.class); + } + + /** + * Read the given reader as an Activity + * @param in Reader + * @return Activity + **/ + public Activity readAsActivity(Reader in) { + return readAs(in, Activity.class); + } + + /** + * Read the given reader as a Collection + * @param in Reader + * @return Collection + **/ + public Collection readAsCollection(Reader in) { + return readAs(in, Collection.class); + } +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/LinkValue.java b/core/src/main/java/com/ibm/common/activitystreams/LinkValue.java new file mode 100755 index 0000000..35a3b05 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/LinkValue.java @@ -0,0 +1,309 @@ +package com.ibm.common.activitystreams; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.io.Serializable; +import java.util.Iterator; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.ibm.common.activitystreams.util.AbstractWritable; + +/** + * An Activity Streams 2.0 Link Value. + * + *

In Actvity Streams 2.0, Link Values can take one of three possible + * forms:

+ * + *
    + *
  • A String containing an absolute IRI
  • + *
  • An Activity String object
  • + *
  • An Array containing a mix of Strings or Objects
  • + *
+ * + *

For instance, the following are all valid examples of Link Values:

+ * + *
+ *   {
+ *     "actor": "acct:joe@example.org"
+ *   }
+ *   
+ *   {
+ *     "actor": {
+ *       "objectType": "person",
+ *       "id": "acct:sally@example.org"
+ *     }
+ *   }
+ *   
+ *   {
+ *     "actor": [
+ *       "acct:joe@example.org",
+ *       {
+ *         "objectType": "person",
+ *         "id": "acct:sally@example.org"
+ *       }
+ *     ]
+ *   }
+ * 
+ * + *

The LinkValue interface provides a minimal abstraction over these + * value options. Developers will have to check the ValueType of the LinkValue + * (or do an instanceof check) in order to determine which kind of value + * they are working with.

+ * + *
+ *   Activity activity = ...;
+ *   Iterable actors = activity.actor();
+ *   for (LinkValue actor : actors) {
+ *     switch(actor.valueType()) {
+ *     case SIMPLE:
+ *       SimpleLinkValue s = (SimpleLinkValue)actor;
+ *       //...
+ *       break;
+ *     case OBJECT:
+ *       ASObject obj = (ASObject)actor;
+ *       //...
+ *       break;
+ *     }
+ *   }
+ * 
+ * + *

Methods that return Iterable will never include an instance + * of ArrayLinkValue as one of the Iterable values

+ * + * @author james + * @version $Revision: 1.0 $ + */ +public interface LinkValue + extends Writable, Serializable { + + /** + * Returns the LinkValue type + * @return ValueType + */ + ValueType valueType(); + + /** + * A "Simple Link Value" is a string with a relative or absolute + * URI or IRI value. + */ + public static final class SimpleLinkValue + extends AbstractWritable + implements LinkValue, Serializable { + + /** + * Creates a new builder + * @return Builder + **/ + public static Builder make() { + return new Builder(); + } + + /** + * Creates a new instance + * @param url String + * @return LinkValue + **/ + public static LinkValue make(String url) { + return new SimpleLinkValue.Builder().url(url).get(); + } + + public static final class Builder + extends AbstractWritable.AbstractWritableBuilder { + + private String iri; + + /** + * Set the url + * @param iri String + * @return Builder + **/ + public Builder url(String iri) { + this.iri = iri; + return this; + } + + /** + * Method get. + * @return SimpleLinkValue + * @see com.google.common.base.Supplier#get() + **/ + public SimpleLinkValue get() { + return new SimpleLinkValue(this); + } + } + + private final String iri; + + SimpleLinkValue(SimpleLinkValue.Builder builder) { + super(builder); + this.iri = builder.iri; + } + + /** + * Return the url + * @return String + */ + public String url() { + return iri; + } + + public String toString() { + return iri; + } + + public ValueType valueType() { + return ValueType.SIMPLE; + } + + // Java Serialization Support + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + implements Serializable { + private static final long serialVersionUID = -1975376657749952999L; + private String iri; + SerializedForm(SimpleLinkValue obj) { + this.iri = obj.iri; + } + Object readResolve() + throws java.io.ObjectStreamException { + return Makers.linkValue(iri); + } + } + + } + + /** + * An Array Link value is a JSON Array of one or more Simple or Object + * Link Values. Array Link Values MUST NOT contain nested arrays. + */ + public static final class ArrayLinkValue + extends AbstractWritable + implements Iterable, LinkValue, Serializable { + + /** + * Create a new builder + * @return ArrayLinkValue.Builder + **/ + public static ArrayLinkValue.Builder make() { + return new ArrayLinkValue.Builder(); + } + + public static class Builder + extends AbstractWritable.AbstractWritableBuilder { + + private final ImmutableList.Builder links = + ImmutableList.builder(); + + /** + * Add one or more items + * @param value String + * @param values String[] + * @return Builder */ + public Builder add(String value, String... values) { + if (value != null) + add(SimpleLinkValue.make(value)); + if (values != null) + for (String v : values) + add(SimpleLinkValue.make(v)); + return this; + } + + /** + * Add one or more link values + * @param links Iterable + * @return Builder */ + public Builder add(Iterable links) { + for (LinkValue l : links) + add(l); + return this; + } + + /** + * Add one or more link values + * @param values LinkValue[] + * @return Builder */ + public Builder add(LinkValue value, LinkValue... values) { + if (value != null) { + checkArgument(value.valueType() != ValueType.ARRAY); + links.add(value); + } + if (values != null) + for (LinkValue v : values) { + checkArgument(v.valueType() != ValueType.ARRAY); + links.add(v); + } + return this; + } + + /** + * Add a link value + * @param value Supplier + * @return Builder */ + public Builder add(Supplier value) { + LinkValue val = value.get(); + checkArgument(val.valueType() != ValueType.ARRAY); + links.add(val); + return this; + } + + /** + * Method get. + * @return ArrayLinkValue + * @see com.google.common.base.Supplier#get() + **/ + public ArrayLinkValue get() { + return new ArrayLinkValue(this); + } + + } + + private final ImmutableList links; + + ArrayLinkValue(ArrayLinkValue.Builder builder) { + super(builder); + this.links = builder.links.build(); + } + + /** + * Method iterator. + * @return Iterator + * @see java.lang.Iterable#iterator() + **/ + public Iterator iterator() { + return links.iterator(); + } + + public String toString() { + return links.toString(); + } + + public ValueType valueType() { + return ValueType.ARRAY; + } + + // Java Serialization Support + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + implements Serializable { + private static final long serialVersionUID = -1975376657749952999L; + private ImmutableList list; + SerializedForm(ArrayLinkValue obj) { + this.list = obj.links; + } + Object readResolve() + throws java.io.ObjectStreamException { + return Makers.linkValues().add(list); + } + } + + } +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/Makers.java b/core/src/main/java/com/ibm/common/activitystreams/Makers.java new file mode 100755 index 0000000..ec334e8 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/Makers.java @@ -0,0 +1,153 @@ +package com.ibm.common.activitystreams; + +import java.util.Map; + +import static com.google.common.collect.ImmutableMap.copyOf; +import com.ibm.common.activitystreams.internal.Schema; + +/** + * Utility class for creating Makers for all of the various objects. + */ +public final class Makers { + + private Makers() {} + + /** + * Make a new ActionsValue.Builder + * @return ParametersValue.Builder + **/ + public static ActionsValue.Builder actions() { + return new ActionsValue.Builder(); + } + + /** + * Make a new Schema.Builder + * @return Schema.Builder + */ + public static Schema.Builder schema() { + return Schema.make(); + } + + /** + * Make a new IO.builder + * @return IO.Builder + **/ + public static IO.Builder io() { + return IO.make(); + } + + /** + * Make a new Activity.Builder + * @return Activity.Builder + **/ + public static Activity.Builder activity() { + return new Activity.Builder(); + } + + /** + * Make a new Collection.Builder + * @return Collection.Builder + **/ + public static Collection.Builder collection() { + return new Collection.Builder(); + } + + /** + * Make a new ASObject.Builder + * @return ASObject.Builder + **/ + public static ASObject.Builder object() { + return new ASObject.Builder(); + } + + /** + * Make a new ASObject.Builder with a specific objectType + * @param type String + * @return ASObject.Builder + **/ + public static ASObject.Builder object(String type) { + return object().objectType(type); + } + + /** + * Return an Object from the given Map + * @param map + * @return ASObject + */ + public static ASObject objectFrom(Map map) { + ASObject.Builder builder = object(); + for (Map.Entry entry : copyOf(map).entrySet()) + builder.set(entry.getKey(), entry.getValue()); + return builder.get(); + } + + /** + * Make a new ASObject.Builder + * @param type TypeValue + * @return ASObject.Builder + **/ + public static ASObject.Builder object(TypeValue type) { + return object().objectType(type); + } + + /** + * Make a new TypeValue + * @param iri String + * @return TypeValue + **/ + public static TypeValue type(String iri) { + return TypeValue.SimpleTypeValue.make(iri); + } + + /** + * Make a new LinkValue + * @param iri String + * @return LinkValue + **/ + public static LinkValue linkValue(String iri) { + return LinkValue.SimpleLinkValue.make(iri); + } + + /** + * Make a new ArrayLinkValue.Builder + * @return LinkValue.ArrayLinkValue.Builder + **/ + public static LinkValue.ArrayLinkValue.Builder linkValues() { + return LinkValue.ArrayLinkValue.make(); + } + + /** + * Make a new MapNLV.Builder + * @return NLV.MapNLV.Builder + **/ + public static NLV.MapNLV.Builder nlv() { + return NLV.MapNLV.make(); + } + + /** + * Make a new SimpleNLV value + * @param val String + * @return NLV.SimpleNLV + **/ + public static NLV.SimpleNLV nlv(String val) { + return NLV.SimpleNLV.make(val); + } + + /** + * Make a new verb ASObject.Builder + * @param id String + * @return ASObject.Builder + */ + public static ASObject.Builder verb(String id) { + return object("verb").id(id); + } + + /** + * Make a new objectType ASObject.Builder + * @param id String + * @return ASObject.Builder + */ + public static ASObject.Builder objectType(String id) { + return object("objectType").id(id); + } +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/NLV.java b/core/src/main/java/com/ibm/common/activitystreams/NLV.java new file mode 100755 index 0000000..7bbe0cf --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/NLV.java @@ -0,0 +1,257 @@ +package com.ibm.common.activitystreams; + +import static com.google.common.collect.Maps.difference; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.Map; + +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableMap; +import com.ibm.common.activitystreams.util.AbstractWritable; + + +/** + * An Activity Streams 2.0 Natural Language Value... + * + *

The value is either a simple string or an object + * with multiple Language-Tag keys and values...

+ * + *
+ *   {
+ *     "objectType": "note",
+ *     "displayName": {
+ *       "en": "My Title In English",
+ *       "fr": "Mon titre en français"
+ *     }
+ *   }
+ * 
+ * + *

+ * ASObject obj = ... + * System.out.println(obj.displayNameString("en")); + * System.out.println(obj.displayNameString("fr")); + * + * NLV nlv = obj.displayName(); + * switch(nlv.valueType()) { + * case SIMPLE: + * SimpleNLV s = (SimpleNLV)nlv; + * ... + * break; + * case OBJECT: + * MapNLV m = (MapNLV)nlv; + * ... + * break; + * } + *

+ * + * @author james + * @version $Revision: 1.0 $ + */ +public interface NLV + extends Writable, Serializable { + + /** + * Returns the value type. Either ValueType.SIMPLE or ValueType.OBJECT + * @return ValueType + */ + ValueType valueType(); + + public static final class SimpleNLV + extends AbstractWritable + implements NLV, Serializable { + + /** + * Create a new builder + * @return Builder */ + public static Builder make() { + return new Builder(); + } + + /** + * Create a new instance + * @param value String + * @return SimpleNLV */ + public static SimpleNLV make(String value) { + return make().value(value).get(); + } + + private final String val; + + SimpleNLV(Builder builder) { + super(builder); + this.val = builder.val; + } + + /** + * Return the value + * @return String + **/ + public String value() { + return val; + } + + @Override + public int hashCode() { + return Objects.hashCode(val); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SimpleNLV other = (SimpleNLV) obj; + return Objects.equal(val, other.val); + } + + public String toString() { + return val; + } + + public static final class Builder + extends AbstractWritable.AbstractWritableBuilder { + + private String val; + + public Builder value(String val) { + this.val = val; + return this; + } + + public SimpleNLV get() { + return new SimpleNLV(this); + } + + } + + public ValueType valueType() { + return ValueType.SIMPLE; + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + implements Serializable { + private static final long serialVersionUID = -1975376657749952999L; + private String value; + SerializedForm(SimpleNLV obj) { + this.value = obj.val; + } + Object readResolve() + throws java.io.ObjectStreamException { + return Makers.nlv(value); + } + } + + } + + public static final class MapNLV + extends AbstractWritable + implements NLV, Iterable { + + public static Builder make() { + return new Builder(); + } + + private final ImmutableMap vals; + private transient int hash = 1; + + MapNLV(Builder builder) { + super(builder); + this.vals = builder.vals.build(); + } + + public String value(String lang) { + return vals.get(lang); + } + + public boolean has(String lang) { + return vals.containsKey(lang); + } + + @Override + public int hashCode() { + if (hash == 1) + hash = Objects.hashCode(vals); + return hash; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + MapNLV other = (MapNLV) obj; + return + difference(vals, other.vals) + .areEqual(); + + } + + public Iterator iterator() { + return vals.keySet().iterator(); + } + + public static final class Builder + extends AbstractWritable.AbstractWritableBuilder { + + private final ImmutableMap.Builder vals = + ImmutableMap.builder(); + + public Builder from(MapNLV other, String lang) { + for (String l : other) + if (!l.equalsIgnoreCase(lang)) + set(l, other.value(l)); + return this; + } + + public Builder set(String lang, String val) { + vals.put(lang,val); + return this; + } + + public MapNLV get() { + return new MapNLV(this); + } + + } + + public ValueType valueType() { + return ValueType.OBJECT; + } + + public Map toMap() { + return vals; + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + implements Serializable { + private static final long serialVersionUID = -1975376657749952999L; + private ImmutableMap map; + SerializedForm(MapNLV obj) { + this.map = obj.vals; + } + Object readResolve() + throws java.io.ObjectStreamException { + NLV.MapNLV.Builder builder = + Makers.nlv(); + for (Map.Entry entry : map.entrySet()) + builder.set(entry.getKey(), entry.getValue()); + return builder.get(); + } + } + } + +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/TypeValue.java b/core/src/main/java/com/ibm/common/activitystreams/TypeValue.java new file mode 100755 index 0000000..788be95 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/TypeValue.java @@ -0,0 +1,140 @@ +package com.ibm.common.activitystreams; + +import java.io.Serializable; + +import com.ibm.common.activitystreams.util.AbstractWritable; + +/** + * In Activity Streams 2.0, the "objectType" and "verb" properties, + * as well as several other properties, are defined as "Type Values". + * A "Type Value" can be either a simple token string, an absolute + * IRI string, or an ASObject. + * + *
+ *   {
+ *     "verb": "post"
+ *   }
+ *   
+ *   {
+ *     "verb": "urn:example:verbs:foo"
+ *   }
+ *   
+ *   {
+ *     "verb": {
+ *       "id": "urn:example:verbs:foo",
+ *       "displayName": "Foo"
+ *     }
+ *   }
+ * 
+ * + *

The TypeValue interface provides a minimal abstraction + * over these possible values. Developers should check valueType + * to determine which type of TypeValue they are working with.

+ * + *
+ *   Activity activity = ...
+ *   TypeValue tv = activity.verb();
+ *   
+ *   System.out.println(tv.id());
+ *   
+ *   switch(tv.valueType()) {
+ *   case SIMPLE:
+ *     SimpleTypeValue s = (SimpleTypeValue)tv;
+ *     ...
+ *     break;
+ *   case OBJECT:
+ *     ASObject o (ASObject)tv;
+ *     ...
+ *     break;
+ *   }
+ * 
+ * + * @author james + * @version $Revision: 1.0 $ + */ +public interface TypeValue + extends Writable, Serializable { + + /** + * Return the type value identifier + * @return String + */ + String id(); + + ValueType valueType(); + + public static final class SimpleTypeValue + extends AbstractWritable + implements TypeValue, Serializable { + + public static Builder make() { + return new SimpleTypeValue.Builder(); + } + + public static TypeValue make(String url) { + return make().url(url).get(); + } + + public static final class Builder + extends AbstractWritable.AbstractWritableBuilder { + + private String iri; + + /** + * Set the url + * @param iri String + * @return Builder + **/ + public Builder url(String iri) { + this.iri = iri; + return this; + } + + public SimpleTypeValue get() { + return new SimpleTypeValue(this); + } + + } + + private final String iri; + + SimpleTypeValue(SimpleTypeValue.Builder builder) { + super(builder); + this.iri = builder.iri; + } + + /** + * Return the type value identifier + * @return String + * @see com.ibm.common.activitystreams.TypeValue#id() */ + public String id() { + return iri; + } + + public String toString() { + return iri; + } + + public ValueType valueType() { + return ValueType.SIMPLE; + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + implements Serializable { + private static final long serialVersionUID = -1975376657749952999L; + private String iri; + SerializedForm(SimpleTypeValue obj) { + this.iri = obj.iri; + } + Object readResolve() + throws java.io.ObjectStreamException { + return Makers.type(iri); + } + } + } + +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/ValueType.java b/core/src/main/java/com/ibm/common/activitystreams/ValueType.java new file mode 100755 index 0000000..56c8259 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/ValueType.java @@ -0,0 +1,15 @@ +package com.ibm.common.activitystreams; + +/** + * Used for TypeValue, LinkValue and NLV interfaces to distinguish + * between the possible value options. + * + * LinkValue.valueType() can return SIMPLE, OBJECT or ARRAY + * TypeValue.valueType() can return SIMPLE or OBJECT + * NLV.valueType() can return SIMPLE or OBJECT + */ +public enum ValueType { + SIMPLE, + OBJECT, + ARRAY; +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/Writable.java b/core/src/main/java/com/ibm/common/activitystreams/Writable.java new file mode 100755 index 0000000..345f1a6 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/Writable.java @@ -0,0 +1,76 @@ +package com.ibm.common.activitystreams; + +import java.io.OutputStream; +import java.io.Writer; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +/** + * Base interface for all objects that serialize to IO object instances + * @author james + * @version $Revision: 1.0 $ + */ +public interface Writable { + + /** + * Write the object to the output stream using the default IO instance + * @param out OutputStream + */ + void writeTo(OutputStream out); + + /** + * Asynchronously write the object to the output stream using the + * default IO instance + * @param out + * @param executor + * @return Future<?> + */ + Future writeTo(OutputStream out, ExecutorService executor); + + /** + * Write the object to the Writer using the default IO instance + * @param out Writer + */ + void writeTo(Writer out); + + /** + * Asynchronously write the object to the writer using the default IO instance + * @param out + * @param executor + * @return Future<?> + */ + Future writeTo(Writer out, ExecutorService executor); + + /** + * Write the object to the output stream using the given IO instance + * @param out OutputStream + * @param io IO + */ + void writeTo(OutputStream out, IO io); + + /** + * Asynchronously write the object to the output stream using the given + * IO instance. + * @param out + * @param io + * @param executor + * @return Future<?> + */ + Future writeTo(OutputStream out, IO io, ExecutorService executor); + + /** + * Write the object to the writer using the given IO instance + * @param out Writer + * @param io IO + */ + void writeTo(Writer out, IO io); + + /** + * Asynchronously write the object to the writer using the given IO instance + * @param out + * @param io + * @param executor + * @return Future<?> + */ + Future writeTo(Writer out, IO io, ExecutorService executor); +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/internal/ASObjectAdapter.java b/core/src/main/java/com/ibm/common/activitystreams/internal/ASObjectAdapter.java new file mode 100755 index 0000000..3eb2776 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/internal/ASObjectAdapter.java @@ -0,0 +1,302 @@ +package com.ibm.common.activitystreams.internal; + + +import static com.google.common.collect.ImmutableList.builder; +import static com.ibm.common.activitystreams.Makers.activity; +import static com.ibm.common.activitystreams.Makers.collection; +import static com.ibm.common.activitystreams.Makers.object; + +import java.lang.reflect.Type; +import java.util.Map.Entry; + +import com.google.common.base.Converter; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.Activity; +import com.ibm.common.activitystreams.Collection; +import com.ibm.common.activitystreams.LinkValue; +import com.ibm.common.activitystreams.Makers; +import com.ibm.common.activitystreams.TypeValue; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +public class ASObjectAdapter + extends Adapter { + + private final Schema schema; + + protected Schema schema() { + return schema; + } + + /** + * Constructor for ASObjectAdapter. + * @param schema Schema + */ + protected ASObjectAdapter(Schema schema) { + this.schema = schema; + } + + /** + * Method serialize. + * @param obj ASObject + * @param type Type + * @param context JsonSerializationContext + + * @return JsonElement */ + public final JsonElement serialize( + ASObject obj, + Type type, + JsonSerializationContext context) { + JsonObject el = + new JsonObject(); + for (String key : obj) { + Object val = obj.get(key); + if (val != null) { + el.add( + key, + context.serialize( + val, + val.getClass())); + } + } + return el; + + } + + private static final ImmutableSet knownTypes = + ImmutableSet.of( + Collection.class, + Activity.class); + + protected boolean knowsType(Type type) { + return knownTypes.contains(type); + } + + protected ASObject.AbstractBuilder builderFor(Type type) { + if (type == Collection.class) + return collection(); + else if (type == Activity.class) + return activity(); + else return null; + } + + protected Model modelFor(Type type) { + if (type == Collection.class) + return schema.forObjectClassOrType( + Collection.Builder.class, + "collection"); + else if (type == Activity.class) + return schema.forObjectClassOrType( + Activity.Builder.class, + "activity"); + else return null; + } + + /** + * Method deserialize. + * @param element JsonElement + * @param type Type + * @param context JsonDeserializationContext + * @return ASObject + * @throws JsonParseException + * @see com.google.gson.JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext) + **/ + public final ASObject deserialize( + JsonElement element, + Type type, + JsonDeserializationContext context) + throws JsonParseException { + + JsonObject obj = (JsonObject)element; + ASObject.AbstractBuilder builder = null; + Model propMap = null; + TypeValue tv = null; + + if (knowsType(type)) { + builder = builderFor(type); + propMap = modelFor(type); + } else { + if (obj.has("objectType")) { + tv = context.deserialize( + obj.get("objectType"), + TypeValue.class); + @SuppressWarnings("rawtypes") + Class _class = + schema.builderForObjectTypeOrClass(tv.id(), (Class)type); + if (_class != null) { + propMap = schema.forObjectClassOrType(_class, tv.id()); + if (!_class.isInterface()) { + try { + builder = _class.getConstructor(String.class).newInstance(tv.id()); + } catch (Throwable t) { + try { + builder = _class.newInstance(); + builder.set("objectType", tv); + } catch (Throwable t2) { + builder = Makers.object(tv); + } + } + } else + builder = Makers.object(tv); + } else { + builder = Makers.object(tv); + propMap = schema.forObjectClassOrType( + ASObject.Builder.class, tv.id()); + } + } else { + if (obj.has("verb") && + (obj.has("actor") || + obj.has("object") || + obj.has("target"))) { + builder = activity(); + propMap = schema.forObjectClassOrType( + Activity.Builder.class, "activity"); + } else if (obj.has("items")) { + builder = collection(); + propMap = schema.forObjectClassOrType( + Collection.Builder.class, + "collection"); + } else { + @SuppressWarnings("rawtypes") + Class _class = + schema.builderFor((Class)type); + if (_class != null) { + if (!_class.isInterface()) { + try { + builder = _class.newInstance(); + } catch (Throwable t) { + builder = object(); + } + } else builder = object(); + } + if (builder == null) + builder = object(); // anonymous + propMap = schema.forObjectClass(builder.getClass()); + propMap = propMap != null ? + propMap : + schema.forObjectClass( + ASObject.Builder.class); + } + } + } + + for (Entry entry : obj.entrySet()) { + String name = entry.getKey(); + if (name.equalsIgnoreCase("objectType")) continue; + Class _class = propMap.get(name); + JsonElement val = entry.getValue(); + if (val.isJsonPrimitive()) + builder.set( + name, + _class != null ? + context.deserialize(val,_class) : + primConverter.convert(val.getAsJsonPrimitive())); + else if (val.isJsonArray()) + builder.set( + name, + LinkValue.class.isAssignableFrom(_class!=null?_class:Object.class) ? + context.deserialize(val, LinkValue.class) : + convert( + val.getAsJsonArray(), + _class, + context, + builder())); + else if (val.isJsonObject()) + builder.set( + name, + context.deserialize( + val, + propMap.has(name) ? + propMap.get(name): + ASObject.class)); + } + return builder.get(); + + } + + /** + * Method convert. + * @param arr JsonArray + * @param _class Class + * @param context JsonDeserializationContext + * @param list ImmutableList.Builder + * @return ImmutableList + */ + private ImmutableList convert( + JsonArray arr, + Class _class, + JsonDeserializationContext context, + ImmutableList.Builder list) { + processArray(arr, _class, context, list); + return list.build(); + } + + /** + * Method processArray. + * @param arr JsonArray + * @param _class Class + * @param context JsonDeserializationContext + * @param list ImmutableList.Builder + */ + private void processArray( + JsonArray arr, + Class _class, + JsonDeserializationContext context, + ImmutableList.Builder list) { + for (JsonElement mem : arr) { + if (mem.isJsonPrimitive()) + list.add( + _class != null ? + context.deserialize(mem,_class) : + primConverter.convert( + mem.getAsJsonPrimitive())); + else if (mem.isJsonObject()) + list.add( + context.deserialize( + mem, + _class != null ? + _class : + ASObject.class)); + else if (mem.isJsonArray()) + list.add( + convert( + mem.getAsJsonArray(), + _class, + context, + builder())); + } + } + + public static final Converter primConverter = + new Converter() { + @Override + protected JsonPrimitive doBackward(Object a) { + if (a instanceof Boolean) + return new JsonPrimitive((Boolean)a); + else if (a instanceof Number) + return new JsonPrimitive((Number)a); + else + return new JsonPrimitive(a.toString()); + } + @Override + protected Object doForward(JsonPrimitive b) { + if (b.isBoolean()) + return b.getAsBoolean(); + else if (b.isNumber()) + return b.getAsNumber(); + else + return b.getAsString(); + } + }; +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/internal/Adapter.java b/core/src/main/java/com/ibm/common/activitystreams/internal/Adapter.java new file mode 100755 index 0000000..dc8b5b5 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/internal/Adapter.java @@ -0,0 +1,13 @@ +package com.ibm.common.activitystreams.internal; + +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonSerializer; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +public abstract class Adapter + implements JsonSerializer, JsonDeserializer { + +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/internal/Adapters.java b/core/src/main/java/com/ibm/common/activitystreams/internal/Adapters.java new file mode 100755 index 0000000..039dcd1 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/internal/Adapters.java @@ -0,0 +1,315 @@ +package com.ibm.common.activitystreams.internal; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.Iterables.getFirst; +import static com.google.common.collect.Iterables.size; + +import static com.ibm.common.activitystreams.Makers.actions; +import static com.ibm.common.activitystreams.Makers.linkValues; +import static com.ibm.common.activitystreams.internal.ASObjectAdapter.primConverter; + +import java.lang.reflect.Type; +import java.util.Date; +import java.util.Map; + +import org.joda.time.DateTime; +import org.joda.time.Duration; +import org.joda.time.Interval; +import org.joda.time.Period; +import org.joda.time.format.ISODateTimeFormat; + +import com.google.common.base.Optional; +import com.google.common.base.Throwables; +import com.google.common.collect.BoundType; +import com.google.common.collect.ImmutableTable; +import com.google.common.collect.Range; +import com.google.common.collect.Table; +import com.google.common.net.MediaType; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.internal.LazilyParsedNumber; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.ActionsValue; +import com.ibm.common.activitystreams.LinkValue; +import com.ibm.common.activitystreams.util.AbstractDictionaryObjectAdapter; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +final class Adapters { + + private Adapters() {} + + /** + * Method forEnum. + * @param _enumClass Class + * @return EnumAdapter + */ + static >EnumAdapter forEnum(Class _enumClass) { + return new EnumAdapter(_enumClass); + } + + /** + * Method forEnum. + * @param _enumClass Class + * @param or E + * @return EnumAdapter + */ + static >EnumAdapter forEnum(Class _enumClass, E or) { + return new EnumAdapter(_enumClass,or); + } + + static final Adapter NLV = + new NaturalLanguageValueAdapter(); + + static final Adapter ACTIONS = + new AbstractDictionaryObjectAdapter + (LinkValue.class) { + public JsonElement serialize( + ActionsValue actions, + Type type, + JsonSerializationContext context) { + JsonObject obj = new JsonObject(); + for (String verb : actions) { + Iterable links = + actions.get(verb); + obj.add( + verb, + context.serialize( + size(links) == 1 ? // if there's only one, serialize just 1 + getFirst(links,null) : // otherwise, serialize the list + linkValues().add(links).get(), + LinkValue.class)); + } + return obj; + } + @Override + protected ActionsValue.Builder builder() { + return actions(); + } + }; + + static final Adapter> ITERABLE = + new Adapter>() { + + public JsonElement serialize( + Iterable i, + Type type, + JsonSerializationContext context) { + JsonArray ary = new JsonArray(); + for (Object obj : i) + ary.add(context.serialize(obj, obj.getClass())); + return ary; + } + + public Iterable deserialize(JsonElement arg0, Type arg1, + JsonDeserializationContext arg2) throws JsonParseException { + return null; // handled elsewhere + } + + }; + + static final Adapter DATE = + new SimpleAdapter() { + protected String serialize(Date t) { + return ISODateTimeFormat.dateTime().print(new DateTime(t)); + } + public Date apply(String v) { + return DateTime.parse(v).toDate(); + } + }; + + static final Adapter DATETIME = + new SimpleAdapter() { + protected String serialize(DateTime t) { + return ISODateTimeFormat.dateTime().print(t); + } + public DateTime apply(String v) { + return DateTime.parse(v); + } + }; + + static final Adapter DURATION = + new SimpleAdapter() { + public Duration apply(String v) { + return Duration.parse(v); + } + }; + + static final Adapter PERIOD = + new SimpleAdapter() { + public Period apply(String v) { + return Period.parse(v); + } + }; + + static final Adapter INTERVAL = + new SimpleAdapter() { + public Interval apply(String v) { + return Interval.parse(v); + } + }; + + static final Adapter MIMETYPE = + new SimpleAdapter() { + public MediaType apply(String v) { + return MediaType.parse(v); + } + }; + + static final MultimapAdapter MULTIMAP = + new MultimapAdapter(); + + + static final Adapter> RANGE = + new Adapter>() { + + public JsonElement serialize( + Range src, + Type typeOfSrc, + JsonSerializationContext context) { + JsonObject el = new JsonObject(); + el.add("lower", makeBound(src.lowerBoundType(),src.lowerEndpoint(),context)); + el.add("upper", makeBound(src.upperBoundType(),src.upperEndpoint(),context)); + return el; + } + + private JsonElement makeBound( + BoundType type, + Object val, + JsonSerializationContext context) { + JsonObject obj = new JsonObject(); + obj.add("type", context.serialize(type.name().toLowerCase())); + obj.add("endpoint", context.serialize(val)); + return obj; + } + + @SuppressWarnings("rawtypes") + public Range deserialize( + JsonElement json, + Type typeOfT, + JsonDeserializationContext context) + throws JsonParseException { + checkArgument(json.isJsonObject()); + try { + JsonObject obj = json.getAsJsonObject(); + JsonObject upper = obj.getAsJsonObject("upper"); + JsonObject lower = obj.getAsJsonObject("lower"); + BoundType ubt = bt(upper.getAsJsonPrimitive("type")); + BoundType lbt = bt(lower.getAsJsonPrimitive("type")); + Object ub = des(upper.get("endpoint"),context); + Object lb = des(lower.get("endpoint"),context); + return Range.range((Comparable)lb, lbt, (Comparable)ub, ubt); + } catch (Throwable t) { + throw Throwables.propagate(t); + } + } + + private Object des(JsonElement val, JsonDeserializationContext context) { + if (val.isJsonArray()) + return MultimapAdapter.arraydes(val.getAsJsonArray(), context); + else if (val.isJsonObject()) + return context.deserialize(val, ASObject.class); + else if (val.isJsonPrimitive()) { + Object v = primConverter.convert(val.getAsJsonPrimitive()); + if (v instanceof LazilyParsedNumber) + v = new LazilyParsedNumberComparable((LazilyParsedNumber) v); + return v; + } + else + return null; + } + + private BoundType bt(JsonPrimitive p) { + try { + return BoundType.valueOf(p.toString()); + } catch (Throwable t) { + return BoundType.CLOSED; + } + } + }; + + static final Adapter> OPTIONAL = + new Adapter>() { + public JsonElement serialize( + Optional src, + Type typeOfSrc, + JsonSerializationContext context) { + return context.serialize(src.orNull()); + } + public Optional deserialize( + JsonElement json, + Type typeOfT, + JsonDeserializationContext context) + throws JsonParseException { + return null; + } + }; + + static final Adapter> TABLE = + new Adapter>() { + + public JsonElement serialize( + Table src, + Type typeOfSrc, + JsonSerializationContext context) { + + JsonObject obj = new JsonObject(); + for (Table.Cell cell : src.cellSet()) { + String r = cell.getRowKey().toString(); + String c = cell.getColumnKey().toString(); + JsonObject rowobj = null; + if (!obj.has(r)) { + rowobj = new JsonObject(); + obj.add(r, rowobj); + } else { + rowobj = obj.getAsJsonObject(r); + } + Object val = cell.getValue(); + if (val != null) + rowobj.add(c, context.serialize(val,val.getClass())); + } + + return obj; + } + + public Table deserialize( + JsonElement json, + Type typeOfT, + JsonDeserializationContext context) + throws JsonParseException { + ImmutableTable.Builder table = + ImmutableTable.builder(); + checkArgument(json.isJsonObject()); + JsonObject obj = json.getAsJsonObject(); + for (Map.Entry rowentry : obj.entrySet()) { + String row = rowentry.getKey(); + JsonElement cell = rowentry.getValue(); + checkArgument(cell.isJsonObject()); + for (Map.Entry cellentry : cell.getAsJsonObject().entrySet()) { + String ckey = cellentry.getKey(); + JsonElement val = cellentry.getValue(); + Object desval = null; + if (val.isJsonArray()) + desval = MultimapAdapter.arraydes(val.getAsJsonArray(),context); + else if (val.isJsonObject()) + desval = context.deserialize(val, ASObject.class); + else if (val.isJsonPrimitive()) + desval = primConverter.convert(val.getAsJsonPrimitive()); + if (desval != null) + table.put(row,ckey,desval); + } + } + return table.build(); + } + + }; +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/internal/EnumAdapter.java b/core/src/main/java/com/ibm/common/activitystreams/internal/EnumAdapter.java new file mode 100755 index 0000000..37cf097 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/internal/EnumAdapter.java @@ -0,0 +1,107 @@ +package com.ibm.common.activitystreams.internal; +import static com.google.common.base.Enums.stringConverter; +import static com.google.common.base.Preconditions.checkArgument; +import static com.ibm.common.activitystreams.util.Converters.stringConverter; +import static com.ibm.common.activitystreams.util.Converters.toLowerConverter; +import static com.ibm.common.activitystreams.util.Converters.toUpperConverter; + +import java.lang.reflect.Type; + +import com.google.common.base.Converter; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +public final class EnumAdapter> + extends Adapter { + + protected static final Converter toLower = + toLowerConverter(); + protected static final Converter toUpper = + toUpperConverter(); + + private final Converter des; + private final Converter ser; + /** + * Constructor for EnumAdapter. + * @param _enumClass Class + */ + public EnumAdapter(Class _enumClass) { + this(_enumClass, stringConverter(_enumClass)); + } + + /** + * Constructor for EnumAdapter + + + * @param _enumClass Class + * @param or E + */ + public EnumAdapter(Class _enumClass, E or) { + this(_enumClass, stringConverter(_enumClass,or)); + } + + /** + * Constructor for EnumAdapter. + * @param _enumClass Class + + * @param c Converter + */ + public EnumAdapter( + Class _enumClass, + Converter c) { + super(); + this.des = toUpper.andThen(c); + this.ser = c.reverse().andThen(toLower); + } + + /** + * Method serialize. + * @param src E + * @param typeOfSrc Type + * @param context JsonSerializationContext + * @return JsonElement + */ + public JsonElement serialize( + E src, + Type typeOfSrc, + JsonSerializationContext context) { + return context.serialize(ser.convert(src)); + } + + /** + * Method deserialize. + * @param json JsonElement + * @param typeOfT Type + * @param context JsonDeserializationContext + * @return E + * @throws JsonParseException + * @see com.google.gson.JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext) + */ + public E deserialize( + JsonElement json, + Type typeOfT, + JsonDeserializationContext context) + throws JsonParseException { + checkArgument(json.isJsonPrimitive()); + JsonPrimitive jp = json.getAsJsonPrimitive(); + checkArgument(jp.isString()); + return des.convert(jp.getAsString()); + } + + /** + * Method convert. + * @param s String + * @return E + */ + protected E convert(String s) { + return des.convert(s); + } + +} \ No newline at end of file diff --git a/core/src/main/java/com/ibm/common/activitystreams/internal/GsonWrapper.java b/core/src/main/java/com/ibm/common/activitystreams/internal/GsonWrapper.java new file mode 100755 index 0000000..63e11d0 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/internal/GsonWrapper.java @@ -0,0 +1,320 @@ +package com.ibm.common.activitystreams.internal; + +import static com.google.gson.internal.bind.TypeAdapters.NUMBER; +import static com.ibm.common.activitystreams.internal.Adapters.DATE; +import static com.ibm.common.activitystreams.internal.Adapters.DATETIME; +import static com.ibm.common.activitystreams.internal.Adapters.NLV; +import static com.ibm.common.activitystreams.internal.Adapters.TABLE; +import static com.ibm.common.activitystreams.internal.Adapters.OPTIONAL; +import static com.ibm.common.activitystreams.internal.Adapters.ACTIONS; +import static com.ibm.common.activitystreams.internal.Adapters.DURATION; +import static com.ibm.common.activitystreams.internal.Adapters.INTERVAL; +import static com.ibm.common.activitystreams.internal.Adapters.ITERABLE; +import static com.ibm.common.activitystreams.internal.Adapters.MIMETYPE; +import static com.ibm.common.activitystreams.internal.Adapters.MULTIMAP; +import static com.ibm.common.activitystreams.internal.Adapters.RANGE; +import static com.ibm.common.activitystreams.internal.Adapters.PERIOD; +import static com.ibm.common.activitystreams.internal.Adapters.forEnum; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.StringWriter; +import java.io.Writer; +import java.util.Date; + +import org.joda.time.DateTime; +import org.joda.time.ReadableDuration; +import org.joda.time.ReadableInterval; +import org.joda.time.ReadablePeriod; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Multimap; +import com.google.common.collect.Range; +import com.google.common.collect.Table; +import com.google.common.net.MediaType; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.internal.LazilyParsedNumber; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.ActionsValue; +import com.ibm.common.activitystreams.Activity; +import com.ibm.common.activitystreams.Collection; +import com.ibm.common.activitystreams.LinkValue; +import com.ibm.common.activitystreams.NLV; +import com.ibm.common.activitystreams.TypeValue; +import com.ibm.common.activitystreams.Writable; +import com.ibm.common.activitystreams.util.TypeValueResolver; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +public final class GsonWrapper { + + /** + * Method make. + + * @return Builder */ + public static final Builder make() { + return new Builder(); + } + + /** + * @author james + * @version $Revision: 1.0 $ + */ + public static final class Builder + implements Supplier { + + private String charset = "UTF-8"; + private boolean pretty; + private Schema schema = null; // default + private ImmutableList.Builder> adapters = + ImmutableList.builder(); + private Function typeValueResolver = + TypeValueResolver.DEFAULT_INSTANCE; + + public Builder typeValueResolver(Function resolver) { + this.typeValueResolver = resolver; + return this; + } + + /** + * Method charset. + * @param charset String + + * @return Builder */ + public Builder charset(String charset) { + this.charset = charset; + return this; + } + + /** + * Method schema. + * @param schema Schema + + * @return Builder */ + public Builder schema(Schema schema) { + this.schema = schema; + return this; + } + + /** + * Method adapter. + * @param type Class + * @param adapter Adapter + + * @return Builder */ + public Builder adapter( + Class type, + Adapter adapter) { + return adapter(type,adapter,false); + } + + /** + * Method adapter. + * @param type Class + * @param adapter Adapter + * @param hier boolean + + * @return Builder */ + public Builder adapter( + Class type, + Adapter adapter, + boolean hier) { + adapters.add(new AdapterEntry(type,adapter,hier)); + return this; + } + + /** + * Method prettyPrint. + * @param on boolean + + * @return Builder */ + public Builder prettyPrint(boolean on) { + this.pretty = on; + return this; + } + + /** + * Method prettyPrint. + + * @return Builder */ + public Builder prettyPrint() { + return prettyPrint(true); + } + + /** + * Method get. + + + * @return GsonWrapper * @see com.google.common.base.Supplier#get() */ + public GsonWrapper get() { + return new GsonWrapper(this); + } + + } + + /** + * @author james + * @version $Revision: 1.0 $ + */ + private final static class AdapterEntry { + private final Class type; + private final Adapter adapter; + private final boolean hier; + /** + * Constructor for AdapterEntry. + * @param type Class + * @param adapter Adapter + * @param hier boolean + */ + AdapterEntry( + Class type, + Adapter adapter, + boolean hier) { + this.type = type; + this.adapter = adapter; + this.hier = hier; + } + } + + private final Gson gson; + private final String charset; + + /** + * Constructor for GsonWrapper. + * @param builder Builder + */ + protected GsonWrapper(Builder builder) { + Schema schema = + builder.schema != null ? + builder.schema : + Schema.make().get(); + ASObjectAdapter base = + new ASObjectAdapter(schema); + GsonBuilder b = initGsonBuilder(builder,schema,base); + for (AdapterEntry entry : builder.adapters.build()) { + if (entry.hier) + b.registerTypeHierarchyAdapter( + entry.type, + entry.adapter!=null ? + entry.adapter : base); + else + b.registerTypeAdapter( + entry.type, + entry.adapter!=null ? + entry.adapter:base); + } + if (builder.pretty) + b.setPrettyPrinting(); + this.gson = b.create(); + this.charset = builder.charset; + } + + /** + * Method initGsonBuilder. + * @param builder Builder + + * @return GsonBuilder */ + private static GsonBuilder initGsonBuilder( + Builder builder, + Schema schema, + ASObjectAdapter base) { + return new GsonBuilder() + .registerTypeHierarchyAdapter(TypeValue.class, new TypeValueAdapter(schema, builder.typeValueResolver)) + .registerTypeHierarchyAdapter(LinkValue.class, new LinkValueAdapter(schema)) + .registerTypeHierarchyAdapter(NLV.class, NLV) + .registerTypeHierarchyAdapter(Iterable.class, ITERABLE) + .registerTypeHierarchyAdapter(ActionsValue.class, ACTIONS) + .registerTypeHierarchyAdapter(Optional.class, OPTIONAL) + .registerTypeHierarchyAdapter(Range.class, RANGE) + .registerTypeHierarchyAdapter(Table.class, TABLE) + .registerTypeHierarchyAdapter(LazilyParsedNumber.class, NUMBER) + .registerTypeHierarchyAdapter(LazilyParsedNumberComparable.class, NUMBER) + .registerTypeHierarchyAdapter(ASObject.class, base) + .registerTypeHierarchyAdapter(Collection.class, base) + .registerTypeHierarchyAdapter(Activity.class, base) + .registerTypeHierarchyAdapter(ReadableDuration.class, DURATION) + .registerTypeHierarchyAdapter(ReadablePeriod.class, PERIOD) + .registerTypeHierarchyAdapter(ReadableInterval.class, INTERVAL) + .registerTypeAdapter( + Activity.Status.class, + forEnum( + Activity.Status.class, + Activity.Status.OTHER)) + .registerTypeAdapter(Date.class, DATE) + .registerTypeAdapter(DateTime.class, DATETIME) + .registerTypeAdapter(MediaType.class, MIMETYPE) + .registerTypeHierarchyAdapter(Multimap.class, MULTIMAP) + ; + } + + /** + * Method write. + * @param w Writable + * @param out OutputStream + */ + public void write(Writable w, OutputStream out) { + try { + OutputStreamWriter wout = + new OutputStreamWriter(out, charset); + gson.toJson(w,wout); + wout.flush(); + } catch (Throwable t) { + throw Throwables.propagate(t); + } + } + + /** + * Method write. + * @param w Writable + * @param out Writer + */ + public void write(Writable w, Writer out) { + gson.toJson(w,out); + } + + /** + * Method write. + * @param w Writable + + * @return String */ + public String write(Writable w) { + StringWriter sw = + new StringWriter(); + write(w,sw); + return sw.toString(); + } + + /** + * Method readAs. + * @param in InputStream + * @param type Class + + * @return A */ + public A readAs(InputStream in, Class type) { + try { + return readAs(new InputStreamReader(in, charset), type); + } catch (Throwable t) { + throw Throwables.propagate(t); + } + } + + /** + * Method readAs. + * @param in Reader + * @param type Class + + * @return A */ + public A readAs(Reader in, Class type) { + return (A)gson.fromJson(in, type); + } +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/internal/LazilyParsedNumberComparable.java b/core/src/main/java/com/ibm/common/activitystreams/internal/LazilyParsedNumberComparable.java new file mode 100755 index 0000000..d4ac061 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/internal/LazilyParsedNumberComparable.java @@ -0,0 +1,107 @@ +package com.ibm.common.activitystreams.internal; + +import java.io.ObjectStreamException; + +import com.google.common.primitives.Longs; +import com.google.gson.internal.LazilyParsedNumber; + +/** + */ +final class LazilyParsedNumberComparable + extends Number + implements Comparable { + private static final long serialVersionUID = 761729254455440231L; + private final LazilyParsedNumber inner; + /** + * Constructor for LazilyParsedNumberComparable. + * @param inner LazilyParsedNumber + */ + public LazilyParsedNumberComparable(LazilyParsedNumber inner) { + this.inner = inner; + } + /** + * Method compareTo. + * @param o Number + * @return int + */ + public int compareTo(Number o) { + return Longs.compare(inner.longValue(), o.longValue()); + } + + /** + * Method doubleValue. + * @return double + */ + public double doubleValue() { + return inner.doubleValue(); + } + + /** + * Method floatValue. + * @return float + */ + public float floatValue() { + return inner.floatValue(); + } + + /** + * Method intValue. + * @return int + */ + public int intValue() { + return inner.intValue(); + } + + /** + * Method longValue. + * @return long + */ + public long longValue() { + return inner.longValue(); + } + /** + * Method byteValue. + * @return byte + */ + public byte byteValue() { + return inner.byteValue(); + } + /** + * Method shortValue. + * @return short + */ + public short shortValue() { + return inner.shortValue(); + } + /** + * Method equals. + * @param obj Object + * @return boolean + */ + public boolean equals(Object obj) { + return inner.equals(obj); + } + /** + * Method hashCode. + * @return int + */ + public int hashCode() { + return inner.hashCode(); + } + /** + * Method toString. + * @return String + */ + public String toString() { + return inner.toString(); + } + + /** + * Method writeReplace. + * @return Object + * @throws ObjectStreamException + */ + private Object writeReplace() throws ObjectStreamException { + return inner; + } +} \ No newline at end of file diff --git a/core/src/main/java/com/ibm/common/activitystreams/internal/LinkValueAdapter.java b/core/src/main/java/com/ibm/common/activitystreams/internal/LinkValueAdapter.java new file mode 100755 index 0000000..40a8fb8 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/internal/LinkValueAdapter.java @@ -0,0 +1,115 @@ +package com.ibm.common.activitystreams.internal; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.ibm.common.activitystreams.Makers.linkValue; +import static com.ibm.common.activitystreams.Makers.linkValues; + +import java.lang.reflect.Type; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.LinkValue; +import com.ibm.common.activitystreams.LinkValue.SimpleLinkValue; +import com.ibm.common.activitystreams.TypeValue; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +final class LinkValueAdapter + extends Adapter { + + private final Schema schema; + + /** + * Constructor for LinkValueAdapter. + * @param schema Schema + */ + public LinkValueAdapter(Schema schema) { + this.schema = schema; + } + + /** + * Method serialize. + * @param value LinkValue + * @param type Type + * @param context JsonSerializationContext + + * @return JsonElement */ + public JsonElement serialize( + LinkValue value, + Type type, + JsonSerializationContext context) { + switch(value.valueType()) { + case SIMPLE: + LinkValue.SimpleLinkValue simple = (SimpleLinkValue) value; + return context.serialize(simple.url(), String.class); + case ARRAY: + return context.serialize(value, Iterable.class); + case OBJECT: + return context.serialize(value, ASObject.class); + default: + throw new IllegalArgumentException(); + } + } + + /** + * Method deserialize. + * @param el JsonElement + * @param type Type + * @param context JsonDeserializationContext + + + + * @return LinkValue * @throws JsonParseException * @see com.google.gson.JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext) */ + public LinkValue deserialize( + JsonElement el, + Type type, + JsonDeserializationContext context) + throws JsonParseException { + checkArgument( + el.isJsonArray() || + el.isJsonObject() || + el.isJsonPrimitive()); + if (el.isJsonArray()) { + LinkValue.ArrayLinkValue.Builder builder = + linkValues(); + for (JsonElement aryel : el.getAsJsonArray()) + builder.add( + context.deserialize( + aryel, + LinkValue.class)); + return builder.get(); + } else if (el.isJsonObject()) { + JsonObject obj = el.getAsJsonObject(); + if (obj.has("objectType")) { + TypeValue tv = + context.deserialize( + obj.get("objectType"), + TypeValue.class); + Model pMap = + schema.forObjectType(tv.id()); + return context.deserialize( + el, + pMap != null && pMap.type() != null ? + pMap.type() : + ASObject.class); + } else { + return context.deserialize( + el, + ASObject.class); + } + } else { + JsonPrimitive prim = + el.getAsJsonPrimitive(); + checkArgument(prim.isString()); + return linkValue(prim.getAsString()); + } + } + +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/internal/Model.java b/core/src/main/java/com/ibm/common/activitystreams/internal/Model.java new file mode 100755 index 0000000..012861f --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/internal/Model.java @@ -0,0 +1,513 @@ +/** + * IBM Activity Streams + * Author: jasnell@us.ibm.com + * License: Apache v2.0 + */ +package com.ibm.common.activitystreams.internal; +import java.lang.reflect.Type; +import java.util.Map; + +import org.joda.time.DateTime; +import org.joda.time.ReadableDuration; +import org.joda.time.ReadableInterval; +import org.joda.time.ReadablePeriod; + +import com.google.common.base.Objects; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.ASObject.AbstractBuilder; +import com.ibm.common.activitystreams.LinkValue; +import com.ibm.common.activitystreams.NLV; +import com.ibm.common.activitystreams.TypeValue; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +public final class Model { + + final String parent; + final ImmutableMap properties; + final Type _default; + final Type _type; + final Type _builder; + private transient Schema schema; + + /** + * Method schema. + * @param schema Schema + */ + protected void schema(Schema schema) { + this.schema = schema; + } + + /** + * Method make. + + * @return Builder */ + public static Builder make() { + return make(null); + } + + /** + * Method make. + * @param parent String + + * @return Builder */ + public static Builder make(String parent) { + return new Builder().parent(parent); + } + + /** + * @author james + * @version $Revision: 1.0 $ + */ + public static final class Builder + implements Supplier { + + Type _type; + Type _builder; + Type _default = null; + String parent = null; + + final Map properties = + Maps.newHashMap(); + + Builder() {} + + /** + * Constructor for Builder. + * @param template PropertyMap + */ + Builder(Model template) { + this.parent = template.parent; + this._default = template._default; + this._type = template._type; + this._builder = template._builder; + this.properties.putAll(template.properties); + } + + /** + * Method withDefault. + * @param _default Class + * @return Builder + **/ + public Builder withDefault(Class _default) { + this._default = _default; + return this; + } + + /** + * Method type. + * @param _type Class + * @param _builder Class + * @return Builder + **/ + @SuppressWarnings("unchecked") + public Builder type( + Class _type, Class _builder) { + this._type = (Class) _type; + this._builder = (Class>) _builder; + return this; + } + + + /** + * Method parent. + * @param parent String + * @return Builder + **/ + public Builder parent(String parent) { + this.parent = parent; + return this; + } + + /** + * Method naturalLanguageValue. + * @param name String + * @return Builder + **/ + public Builder naturalLanguageValue(String name) { + return as(name, NLV.class); + } + + /** + * Method naturalLanguageValue. + * @param names String[] + * @return Builder + **/ + public Builder naturalLanguageValue(String... names) { + for (String name : names) + naturalLanguageValue(name); + return this; + } + + /** + * Method object. + * @param name String + * @return Builder + **/ + public Builder object(String name) { + return as(name, ASObject.class); + } + + /** + * Method object. + * @param names String[] + * @return Builder + **/ + public Builder object(String... names) { + for (String name : names) + object(name); + return this; + } + + /** + * Method integer. + * @param name String + * @return Builder + **/ + public Builder integer(String name) { + return as(name, Integer.class); + } + + /** + * Method integer. + * @param names String[] + * @return Builder + **/ + public Builder integer(String... names) { + for (String name : names) + integer(name); + return this; + } + + /** + * Method doub. + * @param name String + * @return Builder + **/ + public Builder doub(String name) { + return as(name, Double.class); + } + + /** + * Method doub. + * @param names String[] + * @return Builder + **/ + public Builder doub(String... names) { + for (String name : names) + doub(name); + return this; + } + + /** + * Method doub. + * @param name String + * @return Builder + **/ + public Builder floatValue(String name) { + return as(name, Float.class); + } + + /** + * Method doub. + * @param names String[] + * @return Builder + **/ + public Builder floatValue(String... names) { + for (String name : names) + floatValue(name); + return this; + } + + /** + * Method string. + * @param name String + * @return Builder + **/ + public Builder string(String name) { + return as(name, String.class); + } + + /** + * Method string. + * @param names String[] + * @return Builder + **/ + public Builder string(String... names) { + for (String name : names) + string(name); + return this; + } + + /** + * Method linkValue. + * @param name String + * @return Builder + **/ + public Builder linkValue(String name) { + return as(name, LinkValue.class); + } + + /** + * Method linkValue. + * @param names String[] + * @return Builder + **/ + public Builder linkValue(String... names) { + for (String name : names) + linkValue(name); + return this; + } + + /** + * Method dateTime. + * @param name String + * @return Builder + **/ + public Builder dateTime(String name) { + return as(name, DateTime.class); + } + + /** + * Method dateTime. + * @param names String[] + * @return Builder + **/ + public Builder dateTime(String... names) { + for (String name : names) + dateTime(name); + return this; + } + + /** + * Method duration. + * @param name String + * @return Builder + */ + public Builder duration(String name) { + return as(name, ReadableDuration.class); + } + + /** + * Method duration. + * @param names String[] + * @return Builder + */ + public Builder duration(String... names) { + for (String name : names) + duration(name); + return this; + } + + /** + * Method period. + * @param name String + * @return Builder + */ + public Builder period(String name) { + return as (name, ReadablePeriod.class); + } + + /** + * Method period. + * @param names String[] + * @return Builder + */ + public Builder period(String... names) { + for (String name: names) + period(name); + return this; + } + + /** + * Method interval. + * @param name String + * @return Builder + */ + public Builder interval(String name) { + return as(name, ReadableInterval.class); + } + + /** + * Method interval. + * @param names String[] + * @return Builder + */ + public Builder interval(String... names) { + for (String name: names) + interval(name); + return this; + } + + /** + * Method typeValue. + * @param name String + + * @return Builder */ + public Builder typeValue(String name) { + return as(name, TypeValue.class); + } + + /** + * Method typeValue. + * @param names String[] + + * @return Builder */ + public Builder typeValue(String... names) { + for (String name : names) + typeValue(name); + return this; + } + + /** + * Method as. + * @param name String + * @param _class Class + + * @return Builder */ + public Builder as(String name, Class _class) { + this.properties.put(name,_class); + return this; + } + + /** + * Method get. + + + * @return PropertyMap * @see com.google.common.base.Supplier#get() */ + public Model get() { + return new Model(this); + } + + } + + /** + * Constructor for PropertyMap. + * @param builder Builder + */ + Model(Builder builder) { + this.parent = builder.parent; + this.properties = ImmutableMap.copyOf(builder.properties); + this._default = builder._default; + this._type = builder._type; + this._builder = builder._builder; + } + + /** + * Method parentPropertyMap. + + * @return PropertyMap */ + protected Model parentPropertyMap() { + if (schema == null) + return null; + if (parent == null) + return null; + return schema.forObjectClassOrType( + ASObject.Builder.class, + parent.equals("object") ? null : parent); + } + + /** + * Method get. + * @param name String + + * @return Class */ + @SuppressWarnings("unchecked") + public T get(String name) { + Model parent = parentPropertyMap(); + return (T)(properties.containsKey(name) ? + properties.get(name) : + parent != null && _default == null ? + parent.get(name) : _default); + } + + /** + * Method containsKey. + * @param name String + + * @return boolean */ + public boolean has(String name) { + Model parent = parentPropertyMap(); + return properties.containsKey(name) ? + true : parent != null ? + parent.has(name) : false; + } + + /** + * Method type. + + * @return Class */ + @SuppressWarnings("unchecked") + public Class type() { + return (Class) _type; + } + + /** + * Method builder. + + * @return Class> */ + @SuppressWarnings("unchecked") + public Class> builder() { + return (Class>) _builder; + } + + /** + * Method toString. + + * @return String */ + public String toString() { + return Objects.toStringHelper(Model.class) + .omitNullValues() + .add("Parent", parent) + .add("Properties", properties) + .toString(); + } + + /** + * Method template. + + * @return Builder */ + public Builder template() { + return new Builder(this); + } + + /** + * Method template. + * @param _type Class + * @param _builder Class + + * @return PropertyMap */ + public > Model template( + Class _type, Class _builder) { + return template().type(_type,_builder).get(); + } + + /** + * Method set. + * @param name String + * @param type Class + + * @return PropertyMap */ + public Model set(String name, Class type) { + return template() + .as(name, type) + .get(); + } + + /** + * Method set. + * @param map Map> + + * @return PropertyMap */ + public Model set(Map> map) { + Builder builder = template(); + for (Map.Entry> entry : map.entrySet()) + builder.as(entry.getKey(),entry.getValue()); + return builder.get(); + } +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/internal/MultimapAdapter.java b/core/src/main/java/com/ibm/common/activitystreams/internal/MultimapAdapter.java new file mode 100755 index 0000000..0f190b4 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/internal/MultimapAdapter.java @@ -0,0 +1,122 @@ +package com.ibm.common.activitystreams.internal; + +import static com.google.common.collect.Iterables.getFirst; +import static com.google.common.collect.Iterables.size; + +import static com.ibm.common.activitystreams.internal.ASObjectAdapter.primConverter; + +import java.lang.reflect.Type; +import java.util.Map; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.ibm.common.activitystreams.ASObject; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +@SuppressWarnings({"rawtypes","unchecked"}) +final class MultimapAdapter + extends Adapter { + + /** + * Method getAdaptedClass. + + * @return Class */ + public Class getAdaptedClass() { + return Multimap.class; + } + + /** + * Method serialize. + * @param src Multimap + * @param typeOfSrc Type + * @param context JsonSerializationContext + + * @return JsonElement */ + public JsonElement serialize( + Multimap src, + Type typeOfSrc, + JsonSerializationContext context) { + JsonObject obj = new JsonObject(); + for (Object key : src.keySet()) { + Iterable vals = src.get(key); + if (size(vals) == 1) { + Object f = getFirst(vals, null); + if (f != null) + obj.add(key.toString(), context.serialize(f, f.getClass())); + } else { + obj.add(key.toString(), context.serialize(vals, Iterable.class)); + } + } + return obj; + } + + /** + * Method arraydes. + * @param array JsonArray + * @param context JsonDeserializationContext + + * @return ImmutableList */ + protected static ImmutableList arraydes( + JsonArray array, + JsonDeserializationContext context) { + ImmutableList.Builder builder = + ImmutableList.builder(); + for (JsonElement child : array) + if (child.isJsonArray()) + builder.add(arraydes(child.getAsJsonArray(),context)); + else if (child.isJsonObject()) + builder.add(context.deserialize(child, ASObject.class)); + else if (child.isJsonPrimitive()) + builder.add(primConverter.convert(child.getAsJsonPrimitive())); + return builder.build(); + } + + /** + * Method deserialize. + * @param json JsonElement + * @param typeOfT Type + * @param context JsonDeserializationContext + + + + * @return Multimap * @throws JsonParseException * @see com.google.gson.JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext) */ + public Multimap deserialize( + JsonElement json, + Type typeOfT, + JsonDeserializationContext context) + throws JsonParseException { + ImmutableMultimap.Builder mm = + ImmutableMultimap.builder(); + JsonObject obj = json.getAsJsonObject(); + for (Map.Entry entry : obj.entrySet()) { + String key = entry.getKey(); + JsonElement val = entry.getValue(); + if (val.isJsonArray()) { + for (JsonElement el : val.getAsJsonArray()) { + if (el.isJsonArray()) + mm.put(key, arraydes(el.getAsJsonArray(),context)); + else if (el.isJsonObject()) + mm.put(key, context.deserialize(el, ASObject.class)); + else if (el.isJsonPrimitive()) + mm.put(key,primConverter.convert(el.getAsJsonPrimitive())); + } + } else if (val.isJsonObject()) { + mm.put(key, context.deserialize(val, ASObject.class)); + } else if (val.isJsonPrimitive()) { + mm.put(key, primConverter.convert(val.getAsJsonPrimitive())); + } + } + return mm.build(); + } + +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/internal/NaturalLanguageValueAdapter.java b/core/src/main/java/com/ibm/common/activitystreams/internal/NaturalLanguageValueAdapter.java new file mode 100755 index 0000000..80996f6 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/internal/NaturalLanguageValueAdapter.java @@ -0,0 +1,95 @@ +package com.ibm.common.activitystreams.internal; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.lang.reflect.Type; +import java.util.Map.Entry; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.ibm.common.activitystreams.NLV; +import com.ibm.common.activitystreams.NLV.MapNLV; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +final class NaturalLanguageValueAdapter + extends Adapter { + + /** + * Method serialize. + * @param nlv NLV + * @param type Type + * @param context JsonSerializationContext + + * @return JsonElement */ + public JsonElement serialize( + NLV nlv, + Type type, + JsonSerializationContext context) { + JsonElement el = null; + switch (nlv.valueType()) { + case SIMPLE: + el = context.serialize(((NLV.SimpleNLV)nlv).value()); + break; + case OBJECT: + NLV.MapNLV map = + (MapNLV) nlv; + JsonObject obj = new JsonObject(); + for (String lang : map) + obj.addProperty( + lang.toString(), + map.value(lang)); + el = obj; + break; + default: + } + return el; + } + + /** + * Method deserialize. + * @param element JsonElement + * @param type1 Type + * @param context JsonDeserializationContext + + + + * @return NLV * @throws JsonParseException * @see com.google.gson.JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext) */ + public NLV deserialize( + JsonElement element, + Type type1, + JsonDeserializationContext context) + throws JsonParseException { + checkArgument( + element.isJsonPrimitive() || + element.isJsonObject()); + if (element.isJsonPrimitive()) { + JsonPrimitive prim = + element.getAsJsonPrimitive(); + checkArgument(prim.isString()); + return NLV.SimpleNLV.make( + prim.getAsString()); + } else { + try { + JsonObject obj = + element.getAsJsonObject(); + NLV.MapNLV.Builder builder = + NLV.MapNLV.make(); + for (Entry entry : obj.entrySet()) + builder.set( + entry.getKey(), + entry.getValue().getAsString()); + return builder.get(); + } catch (Throwable t) { + throw new IllegalArgumentException(); + } + } + } + +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/internal/Schema.java b/core/src/main/java/com/ibm/common/activitystreams/internal/Schema.java new file mode 100755 index 0000000..e646c86 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/internal/Schema.java @@ -0,0 +1,419 @@ +/** + * IBM Activity Streams + * Author: jasnell@us.ibm.com + * License: Apache v2.0 + */ +package com.ibm.common.activitystreams.internal; +import static com.google.common.base.Objects.toStringHelper; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.HashBiMap.create; +import static com.google.common.collect.Iterables.addAll; +import static com.google.common.collect.Maps.newHashMap; +import static com.google.common.collect.Sets.newHashSet; + +import java.util.Map; +import java.util.Set; + +import org.joda.time.Duration; + +import com.google.common.base.Converter; +import com.google.common.base.Supplier; +import com.google.common.collect.BiMap; +import com.google.common.collect.ImmutableBiMap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.net.MediaType; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.ActionsValue; +import com.ibm.common.activitystreams.Activity; +import com.ibm.common.activitystreams.Collection; + +/** + * @TODO: The Schema mechanism needs to be revisited and reworked + * to be much more efficient. + * @author james + * @version $Revision: 1.0 $ + */ +@SuppressWarnings("rawtypes") +public final class Schema { + + /** + * @author james + * @version $Revision: 1.0 $ + */ + public static final class Builder + implements Supplier { + + final Map objectTypeMap = + newHashMap(); + final Map> builderMap = + newHashMap(); + final Map,Model> objectClassMap = + newHashMap(); + final BiMap, Class> classMap = + create(100); + final Set> adapters = + newHashSet(); + + Builder() {} + + /** + * Constructor for Builder. + * @param template Schema + */ + Builder(Schema template) { + this.objectTypeMap.putAll(template.objectTypeMap); + this.builderMap.putAll(template.builderMap); + this.objectClassMap.putAll(template.objectClassMap); + this.classMap.putAll(template.classMap); + this.adapters.addAll(template.adapters); + } + + /** + * Method adapter. + * @param _enumClass Class + + * @return Builder */ + public >Builder adapter( + Class _enumClass) { + return adapter(new EnumAdapter(_enumClass)); + } + + /** + * Method adapter. + * @param _enumClass Class + + + * @param c Converter + * @return Builder */ + public >Builder adapter( + Class _enumClass, + Converter c) { + return adapter(new EnumAdapter(_enumClass,c)); + } + + /** + * Method adapter + * @param _enumClass Class + * @param or E + * @return Builder + */ + public >Builder adapter( + Class _enumClass, E or) { + return adapter(new EnumAdapter(_enumClass,or)); + } + + /** + * Method adapter. + * @param adapter Adapter + + * @return Builder */ + public Builder adapter(Adapter adapter) { + this.adapters.add(adapter); + return this; + } + + /** + * Method adapter. + * @param adapters Adapter[] + + * @return Builder */ + public Builder adapter(Adapter... adapters) { + if (adapters == null) return this; + for (Adapter a : adapters) + adapter(a); + return this; + } + + /** + * Method adapter. + * @param adapters Iterable> + + * @return Builder */ + public Builder adapter(Iterable> adapters) { + if (adapters == null) return this; + addAll(this.adapters, adapters); + return this; + } + + /** + * Method map. + * @param objectType String + * @param propertyMap Supplier + + * @return Builder */ + public Builder map(String objectType, Supplier propertyMap) { + return map(objectType, propertyMap.get()); + } + + /** + * Method map. + * @param propertyMap Supplier + + * @return Builder */ + public Builder map(Supplier propertyMap) { + return map(null,propertyMap); + } + + /** + * Method map. + * @param propertyMap PropertyMap + + * @return Builder */ + public Builder map(Model propertyMap) { + return map(null, propertyMap); + } + + /** + * Method map. + * @param objectType String + * @param propertyMap PropertyMap + + * @return Builder */ + public Builder map(String objectType, Model propertyMap) { + checkNotNull(propertyMap); + Class> _builder = propertyMap.builder(); + Class _type = propertyMap.type(); + if (objectType != null) objectTypeMap.put(objectType, propertyMap); + if (objectType != null && _builder != null) + builderMap.put(objectType,_builder); + if (_builder != null) objectClassMap.put(_builder, propertyMap); + if (_builder != null && _type != null) + classMap.put(_type,_builder); + return this; + } + + /** + * Method get. + + + * @return Schema * @see com.google.common.base.Supplier#get() */ + public Schema get() { + return new Schema(this); + } + + } + + final ImmutableMap objectTypeMap; + final ImmutableMap, Model> objectClassMap; + final ImmutableMap> builderMap; + final ImmutableBiMap, Class> classMap; + final ImmutableSet> adapters; + + /** + * Constructor for Schema. + * @param builder Builder + */ + Schema(Builder builder) { + this.objectClassMap = ImmutableMap.copyOf(builder.objectClassMap); + this.objectTypeMap = ImmutableMap.copyOf(builder.objectTypeMap); + this.builderMap = ImmutableMap.copyOf(builder.builderMap); + this.adapters = ImmutableSet.copyOf(builder.adapters); + this.classMap = ImmutableBiMap.copyOf(builder.classMap); + + for (Model pmap : objectTypeMap.values()) + pmap.schema(this); + for (Model pmap : objectClassMap.values()) + pmap.schema(this); + + } + + /** + * Method adapters. + + * @return Iterable> */ + public Iterable> adapters() { + return adapters; + } + + /** + * Method builderForObjectTypeOrClass. + * @param ots String + * @param _class Class + + * @return Class */ + public Class builderForObjectTypeOrClass(String ots, Class _class) { + Class _builder = builderFor(ots); + return _builder != null ? + _builder : builderFor(_builder); + } + + /** + * Method builderFor. + * @param _class Class + + * @return Class */ + public Class builderFor(Class _class) { + if (_class == null) return null; + return classMap.get(_class); + } + + /** + * Method classFor. + * @param _builder Class + + * @return Class */ + public Class classFor(Class _builder) { + if (_builder == null) return null; + return classMap.inverse().get(_builder); + } + + /** + * Method builderFor. + * @param ots String + + * @return Class */ + public Class builderFor(String ots) { + if (ots == null) return null; + return builderMap.get(ots); + } + + /** + * Method forObjectType. + * @param objectType String + + * @return PropertyMap */ + public Model forObjectType(String objectType) { + return objectTypeMap.get(objectType); + } + + /** + * Method forObjectClass. + * @param _class Class + + * @return PropertyMap */ + public Model forObjectClass(Class _class) { + return objectClassMap.get(_class); + } + + /** + * Method forObjectClassOrType. + * @param _class Class + * @param objectType String + + * @return PropertyMap */ + public Model forObjectClassOrType(Class _class, String objectType) { + Model pm = forObjectClass(_class); + return pm != null ? pm : forObjectType(objectType); + } + + /** + * Method template. + + * @return Builder */ + public Builder template() { + return new Builder(this); + } + + /** + * Method toString. + + * @return String */ + public String toString() { + return toStringHelper(Schema.class) + .add("Object Types", objectTypeMap) + .add("Object Classes", objectClassMap) + .toString(); + } + + public final static Model object = + Model + .make() + .type( + ASObject.class, + ASObject.Builder.class) + .typeValue( + "objectType") + .linkValue( + "attachments", + "author", + "duplicates", + "icon", + "image", + "location", + "inReplyTo", + "tags", + "url", + "generator", + "provider", + "scope" + ) + .dateTime( + "published", + "updated", + "startTime", + "endTime") + .naturalLanguageValue( + "summary", + "title", + "content", + "displayName") + .as("language", String.class) + .as("actions", ActionsValue.class) + .string("id", "rel", "alias") + .doub("rating") + .integer("height", "width") + .as("mediaType", MediaType.class) + .as("duration", Duration.class) + .get(); + + public final static Model activity = + Model + .make("object") + .type( + Activity.class, + Activity.Builder.class) + .typeValue("verb") + .linkValue( + "actor", + "participant", + "instrument", + "object", + "target", + "result", + "to", + "bto", + "cc", + "bcc") + .doub("priority") + .as("status", Activity.Status.class) + .get(); + + public final static Model collection = + Model + .make("object") + .type( + Collection.class, + Collection.Builder.class) + .dateTime( + "itemsBefore", + "itemsAfter") + .linkValue( + "first", + "last", + "prev", + "next", + "current", + "self") + .object("items") + .integer( + "startIndex", + "itemsPerPage", + "totalItems") + .get(); + + /** + * Method make. + + * @return Schema.Builder */ + public static Schema.Builder make() { + return + new Builder() + .map(null, object) + .map("activity", activity) + .map("collection", collection); + } + + public static final Schema DEFAULT_SCHEMA = make().get(); + +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/internal/SimpleAdapter.java b/core/src/main/java/com/ibm/common/activitystreams/internal/SimpleAdapter.java new file mode 100755 index 0000000..b742219 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/internal/SimpleAdapter.java @@ -0,0 +1,69 @@ + +package com.ibm.common.activitystreams.internal; + +import java.lang.reflect.Type; + +import com.google.common.base.Function; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +public abstract class SimpleAdapter + extends Adapter + implements Function { + + /** + * Method serialize. + * @param t T + * @param type Type + * @param context JsonSerializationContext + + + * @return JsonElement * @see com.google.gson.JsonSerializer#serialize(T, Type, JsonSerializationContext) */ + public JsonElement serialize( + T t, + Type type, + JsonSerializationContext context) { + return context.serialize(serialize(t)); + } + + /** + * Method serialize. + * @param t T + + * @return String */ + protected String serialize(T t) { + return t != null ? t.toString() : null; + } + + /** + * Method deserialize. + * @param v String + + * @return T */ + protected T deserialize(String v) { + return apply(v); + } + + /** + * Method deserialize. + * @param json JsonElement + * @param type Type + * @param context JsonDeserializationContext + + + + * @return T * @throws JsonParseException * @see com.google.gson.JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext) */ + public T deserialize( + JsonElement json, + Type type, + JsonDeserializationContext context) + throws JsonParseException { + return deserialize(json.getAsJsonPrimitive().getAsString()); + } +} \ No newline at end of file diff --git a/core/src/main/java/com/ibm/common/activitystreams/internal/TypeValueAdapter.java b/core/src/main/java/com/ibm/common/activitystreams/internal/TypeValueAdapter.java new file mode 100755 index 0000000..784bc29 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/internal/TypeValueAdapter.java @@ -0,0 +1,104 @@ +package com.ibm.common.activitystreams.internal; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.ibm.common.activitystreams.Makers.type; + +import java.lang.reflect.Type; + +import com.google.common.base.Function; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.TypeValue; +import com.ibm.common.activitystreams.ValueType; + +/** + * @author james + * @version $Revision: 1.0 $ + */ +final class TypeValueAdapter + extends Adapter { + + private final Schema schema; + private final Function resolver; + + /** + * Constructor for TypeValueAdapter. + * @param schema Schema + */ + public TypeValueAdapter( + Schema schema, + Function resolver) { + this.schema = schema; + this.resolver = resolver; + } + + /** + * Method serialize. + * @param value TypeValue + * @param type Type + * @param context JsonSerializationContext + + * @return JsonElement */ + public JsonElement serialize( + TypeValue value, + Type type, + JsonSerializationContext context) { + boolean simple = value.valueType() == ValueType.SIMPLE; + return context.serialize( + simple ? value.id() : value, + simple ? String.class : ASObject.class + ); + } + + /** + * Method deserialize. + * @param el JsonElement + * @param type Type + * @param context JsonDeserializationContext + + + + * @return TypeValue * @throws JsonParseException * @see com.google.gson.JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext) */ + public TypeValue deserialize( + JsonElement el, + Type type, + JsonDeserializationContext context) + throws JsonParseException { + checkArgument( + el.isJsonPrimitive() || + el.isJsonObject()); + if (el.isJsonPrimitive()) { + JsonPrimitive prim = + el.getAsJsonPrimitive(); + checkArgument(prim.isString()); + return resolver.apply(type(prim.getAsString())); + } else { + JsonObject obj = el.getAsJsonObject(); + if (obj.has("objectType")) { + TypeValue tv = + context.deserialize( + obj.get("objectType"), + TypeValue.class); + Model pMap = + schema.forObjectType(tv.id()); + return resolver.apply( + context.deserialize( + el, + pMap.type() != null ? + pMap.type() : + ASObject.class)); + } else { + return resolver.apply( + context.deserialize( + el, + ASObject.class)); + } + } + } + +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/util/AbstractDictionaryObject.java b/core/src/main/java/com/ibm/common/activitystreams/util/AbstractDictionaryObject.java new file mode 100755 index 0000000..2c804e6 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/util/AbstractDictionaryObject.java @@ -0,0 +1,284 @@ +package com.ibm.common.activitystreams.util; + +import static com.google.common.collect.ImmutableList.of; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.size; +import static com.google.common.collect.Iterables.transform; +import static com.google.common.collect.Maps.difference; +import static com.ibm.common.activitystreams.Makers.linkValue; +import static com.ibm.common.activitystreams.Makers.linkValues; + +import java.util.Iterator; +import java.util.Map; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.LinkValue; +import com.ibm.common.activitystreams.ValueType; +import com.ibm.common.activitystreams.LinkValue.ArrayLinkValue; + +/** + * Utility abstract base used for objects that are JSON + * dictionaries as opposed to full Activity Stream objects. + * @author james + * @version $Revision: 1.0 $ + */ +public abstract class AbstractDictionaryObject + extends AbstractWritable + implements Iterable { + + public static abstract class AbstractBuilder + , B extends AbstractBuilder> + extends AbstractWritable.AbstractWritableBuilder { + + protected final Map map = + Maps.newHashMap(); + private boolean isempty = true; + + /** + * Returns true if items have been added + * @return boolean + */ + public boolean notEmpty() { + return !isempty; + } + + /** + * Sets an item in this dictionary object + * @param key String + * @param x X + * @return B + */ + @SuppressWarnings("unchecked") + public B set(String key, X x) { + if (x != null) { + map.put(key,x); + isempty = false; + } + return (B)this; + } + + /** + * Sets an item in this dictionary object + * @param key String + * @param x Supplier + * @return B + */ + public B set( + String key, + Supplier x) { + return set(key, x.get()); + } + + /** + * Add a link + * @param name String + * @param url String + * @return B + **/ + protected B link(String name, String url) { + return link(name, linkValue(url)); + } + + /** + * Add a link + * @param name String + * @param link LinkValue + * @return B + **/ + @SuppressWarnings("unchecked") + protected B link(String name, LinkValue link) { + if (link == null) + return (B)this; + isempty = false; + Object obj = map.get(name); + if (link.valueType() != ValueType.ARRAY) { + if (obj instanceof LinkValue) + link = + ((LinkValue) obj).valueType() == ValueType.ARRAY ? + linkValues() + .add((LinkValue.ArrayLinkValue)obj) + .add(link) + .get() : + linkValues() + .add((LinkValue)obj, link) + .get(); + map.put(name, (X) link); + } else map.put(name, (X)link); + return (B)this; + } + + /** + * Add a link + * @param name String + * @param link Supplier + * @return B + **/ + public B link(String name, Supplier link) { + return link(name,link.get()); + } + + /** + * Add a link + * @param name String + * @param links Object[] + * @return B + **/ + @SuppressWarnings("unchecked") + protected B link(String name, Object... links) { + if (links == null) return (B)this; + ArrayLinkValue.Builder b = + ArrayLinkValue.make(); + for (Object obj : links) + _add(b, obj); + return link(name,b.get()); + } + + /** + * Method _add. + * @param builder ArrayLinkValue.Builder + * @param obj Object + */ + private void _add(ArrayLinkValue.Builder builder, Object obj) { + if (obj == null) + return; + else if (obj instanceof String) + builder.add((String)obj); + else if (obj instanceof ASObject) + builder.add((ASObject)obj); + else if (obj instanceof Supplier) + _add(builder,((Supplier)obj).get()); + else throw new IllegalArgumentException(); + } + + } + + private final ImmutableMap map; + private transient int hash = 1; + + /** + * @param builder AbstractBuilder + */ + protected AbstractDictionaryObject(AbstractBuilder builder) { + super(builder); + this.map = ImmutableMap.copyOf(builder.map); + } + + /** + * Method getSingle. + * @param key String + * @return X + */ + protected X getSingle(String key) { + return map.get(key); + } + + /** + * Method getSingle. + * @param key String + * @param defaultValue X + * @return X + */ + protected X getSingle(String key, X defaultValue) { + X ret = getSingle(key); + return ret != null ? ret : defaultValue; + } + + /** + * Method getIterable. + * @param key String + * @return Iterable + */ + @SuppressWarnings("unchecked") + protected Iterable getIterable(String key) { + X x = map.get(key); + return x instanceof Iterable ? + (Iterable)x : + of(x); + } + + /** + * Method getIterable. + * @param key String + * @param filter Predicate + * @return Iterable + */ + protected Iterable getIterable( + String key, + Predicate filter) { + return filter(getIterable(key), filter); + } + + /** + * Method getIterable. + * @param key String + * @param transform Function + * @return Iterable + */ + protected Iterable getIterable( + String key, + Function transform) { + return transform(getIterable(key), transform); + } + + /** + * Method getIterable. + * @param key String + * @param filter Predicate + * @param transform Function + * @return Iterable + */ + protected Iterable getIterable( + String key, + Predicate filter, + Function transform) { + return transform(filter(getIterable(key),filter),transform); + } + + public Iterator iterator() { + return map.keySet().iterator(); + } + + /** + * Returns true if the verb appears in the ActionsValue object + * @param key String + * @return boolean */ + public boolean has(String key) { + return map.containsKey(key); + } + + /** + * Returns true if the verb appears in the ActionsValue object + * and there is at least one handler in the value. + * @param key String + * @return boolean + */ + protected boolean hasAtLeastOne(String key) { + return has(key) && size(getIterable(key)) > 0; + } + + public int hashCode() { + if (hash == 1) + hash = map.hashCode(); + return hash; + } + + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AbstractDictionaryObject other = + (AbstractDictionaryObject) obj; + return difference(map,other.map).areEqual(); + } + +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/util/AbstractDictionaryObjectAdapter.java b/core/src/main/java/com/ibm/common/activitystreams/util/AbstractDictionaryObjectAdapter.java new file mode 100755 index 0000000..1c26433 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/util/AbstractDictionaryObjectAdapter.java @@ -0,0 +1,74 @@ +package com.ibm.common.activitystreams.util; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.lang.reflect.Type; +import java.util.Map.Entry; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.ibm.common.activitystreams.internal.Adapter; + +/** + * Abstract base GSON Serializer for AbstractDictionaryObject + * instances. + * @author james + * @version $Revision: 1.0 $ + */ +public abstract class AbstractDictionaryObjectAdapter + , + B extends AbstractDictionaryObject.AbstractBuilder> + extends Adapter { + + private final Class klass; + + /** + * Constructor for AbstractDictionaryObjectAdapter. + * @param klass Class + */ + protected AbstractDictionaryObjectAdapter(Class klass) { + this.klass = klass; + } + + public JsonElement serialize( + X x, + Type type, + JsonSerializationContext context) { + JsonObject obj = new JsonObject(); + for (String key : x) + obj.add( + key, + context.serialize( + x.getSingle(key), + klass)); + return obj; + } + + public X deserialize( + JsonElement element, + Type type1, + JsonDeserializationContext context) + throws JsonParseException { + checkArgument(element.isJsonObject()); + try { + JsonObject obj = + element.getAsJsonObject(); + B builder = builder(); + for (Entry entry : obj.entrySet()) + builder.set( + entry.getKey(), + context.deserialize( + entry.getValue(), + klass)); + return builder.get(); + } catch (Throwable t) { + t.printStackTrace(); + throw new IllegalArgumentException(); + } + } + + protected abstract B builder(); +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/util/AbstractWritable.java b/core/src/main/java/com/ibm/common/activitystreams/util/AbstractWritable.java new file mode 100755 index 0000000..894a2b2 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/util/AbstractWritable.java @@ -0,0 +1,132 @@ +package com.ibm.common.activitystreams.util; + +import static com.ibm.common.activitystreams.IO.makeDefault; + +import java.io.OutputStream; +import java.io.StringWriter; +import java.io.Writer; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +import com.google.common.base.Supplier; +import com.ibm.common.activitystreams.IO; +import com.ibm.common.activitystreams.Writable; + +/** + * Utility base class for Writable instances. + * @author james + * @version $Revision: 1.0 $ + */ +public abstract class AbstractWritable + implements Writable { + + public static abstract class AbstractWritableBuilder + > + implements Supplier { + + private IO io = null; + + /** + * Set the IO instance that should be used + * by default for writing instances of this + * object. + */ + @SuppressWarnings("unchecked") + public B writeUsing(IO io) { + this.io = io; + return (B)this; + } + + public void writeTo(OutputStream out) { + get().writeTo(out); + } + + public Future writeTo(OutputStream out, ExecutorService executor) { + return get().writeTo(out,executor); + } + + public void writeTo(Writer out) { + get().writeTo(out); + } + + public Future writeTo(Writer out, ExecutorService executor) { + return get().writeTo(out,executor); + } + + + public void writeTo(OutputStream out, IO io) { + get().writeTo(out,io); + } + + public Future writeTo(OutputStream out, IO io, ExecutorService executor) { + return get().writeTo(out, io, executor); + } + + public void writeTo(Writer out, IO io) { + get().writeTo(out,io); + } + + public Future writeTo(Writer out, IO io, ExecutorService executor) { + return get().writeTo(out, io, executor); + } + + } + + private final IO io; + + protected AbstractWritable(AbstractWritableBuilder b) { + this.io = b.io != null ? b.io : makeDefault(); + } + + public void writeTo(OutputStream out) { + writeTo(out,io); + } + + public Future writeTo(OutputStream out, ExecutorService executor) { + return writeTo(out, io, executor); + } + + public void writeTo(OutputStream out, IO io) { + io.write(this,out); + } + + public Future writeTo(OutputStream out, IO io, ExecutorService executor) { + return io.write(this,out,executor); + } + + public void writeTo(Writer out) { + writeTo(out, io); + } + + public Future writeTo(Writer out, ExecutorService executor) { + return writeTo(out, io, executor); + } + + public void writeTo(Writer out, IO io) { + io.write(this,out); + } + + public Future writeTo(Writer out, IO io, ExecutorService executor) { + return io.write(this, out, executor); + } + + public String toString(IO io) { + StringWriter sw = + new StringWriter(); + io.write(this, sw); + return sw.toString(); + } + + public Future toString(ExecutorService executor) { + return io.write(this, executor); + } + + public Future toString(IO io, ExecutorService executor) { + return io.write(this, executor); + } + + public String toString() { + return toString(io); + } + +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/util/Converters.java b/core/src/main/java/com/ibm/common/activitystreams/util/Converters.java new file mode 100755 index 0000000..0c9a928 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/util/Converters.java @@ -0,0 +1,341 @@ +package com.ibm.common.activitystreams.util; + +import static com.google.common.base.Enums.getIfPresent; +import static com.google.common.base.Optional.absent; +import static com.google.common.base.Optional.fromNullable; +import static com.google.common.base.Optional.of; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.joda.time.Duration.millis; +import static org.joda.time.Duration.standardDays; +import static org.joda.time.Duration.standardHours; +import static org.joda.time.Duration.standardMinutes; +import static org.joda.time.Duration.standardSeconds; + +import java.util.Date; +import java.util.Locale; +import java.util.concurrent.TimeUnit; + +import org.joda.time.DateTime; +import org.joda.time.Duration; +import org.joda.time.Interval; +import org.joda.time.Period; + +import com.google.common.base.Converter; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.primitives.Doubles; +import com.google.common.primitives.Floats; +import com.google.common.primitives.Ints; +import com.google.common.primitives.Longs; + +public final class Converters { + + private Converters() {} + + /** + * Method toDuration. + * @param v long + * @param unit TimeUnit + * @return Duration + */ + public static Duration toDuration(long v, TimeUnit unit) { + switch(unit) { + case NANOSECONDS: + return millis(v / 1000 / 1000); + case MICROSECONDS: + return millis(v / 1000); + case MILLISECONDS: + return millis(v); + case SECONDS: + return standardSeconds(v); + case MINUTES: + return standardMinutes(v); + case HOURS: + return standardHours(v); + case DAYS: + return standardDays(v); + default: + throw new IllegalArgumentException(); + } + } + + /** + * Method tryParseShort. + * @param input String + * @return Short + */ + private static Short tryParseShort(String input) { + try { + return Short.parseShort(input); + } catch (Throwable t) { + return null; + } + } + + /** + * Method tryParseBoolean. + * @param input String + * @return Boolean + */ + private static Boolean tryParseBoolean(String input) { + try { + return Boolean.parseBoolean(input); + } catch (Throwable t) { + return null; + } + } + + /** + * Method tryParseDateTime. + * @param input String + * @return DateTime + */ + private static DateTime tryParseDateTime(String input) { + try { + return DateTime.parse(input); + } catch (Throwable t) { + return null; + } + } + + /** + * Method tryParseDuration. + * @param input String + * @return Duration + */ + private static Duration tryParseDuration(String input) { + try { + return Period.parse(input).toDurationFrom(DateTime.now()); + } catch (Throwable t) { + return null; + } + } + + /** + * Method tryParsePeriod. + * @param input String + * @return Period + */ + private static Period tryParsePeriod(String input) { + try { + return Period.parse(input); + } catch (Throwable t) { + return null; + } + } + + /** + * Method tryParseInterval. + * @param input String + * @return Interval + */ + private static Interval tryParseInterval(String input) { + try { + return Interval.parse(input); + } catch (Throwable t) { + return null; + } + } + + public static final Function> toInterval = + new Function>() { + public Optional apply(Object input) { + Optional ret = absent(); + if (input != null) + ret = input instanceof Interval ? + of((Interval)input) : + fromNullable(tryParseInterval(input.toString())); + return ret; + } + + }; + + public static final Function> toDuration = + new Function>() { + + public Optional apply(Object input) { + Optional ret = absent(); + if (input != null) + ret = input instanceof Duration ? + of((Duration)input) : + input instanceof Number ? + of(standardSeconds(((Number)input).longValue())) : + fromNullable(tryParseDuration(input.toString())); + return ret; + } + + }; + + public static final Function> toPeriod = + new Function>() { + public Optional apply(Object input) { + Optional ret = absent(); + if (input != null) + ret = input instanceof Period ? + of((Period)input) : + fromNullable(tryParsePeriod(input.toString())); + return ret; + } + }; + + public static final Function> toDateTime = + new Function>() { + public Optional apply(Object input) { + Optional ret = absent(); + if (input != null) + ret = input instanceof DateTime ? + of((DateTime)input) : + input instanceof Date ? + of(new DateTime((Date)input)) : + input instanceof Number ? + of(new DateTime(((Number)input).longValue())) : + fromNullable(tryParseDateTime(input.toString())); + return ret; + } + + }; + + public static final Function> toBoolean = + new Function>() { + public Optional apply(Object input) { + Optional ret = absent(); + if (input != null) + ret = input instanceof Boolean ? + of((Boolean)input) : + input instanceof Number ? + of(((Number)input).intValue() != 0) : + fromNullable(tryParseBoolean(input.toString())); + return ret; + } + }; + + public static final Function> toShort = + new Function>() { + public Optional apply(Object input) { + Optional ret = absent(); + if (input != null) + ret = input instanceof Number ? + of(((Number) input).shortValue()) : + fromNullable(tryParseShort(input.toString())); + return ret; + } + }; + + public static final Function> toInt = + new Function>() { + public Optional apply(Object input) { + Optional ret = absent(); + if (input != null) + ret = input instanceof Number ? + of(((Number) input).intValue()) : + fromNullable(Ints.tryParse(input.toString())); + return ret; + } + }; + + public static final Function> toLong = + new Function>() { + public Optional apply(Object input) { + Optional ret = absent(); + if (input != null) + ret = input instanceof Number ? + of(((Number) input).longValue()) : + fromNullable(Longs.tryParse(input.toString())); + return ret; + } + }; + + public static final Function> toDouble = + new Function>() { + public Optional apply(Object input) { + Optional ret = absent(); + if (input != null) + ret = input instanceof Number ? + of(((Number) input).doubleValue()) : + fromNullable(Doubles.tryParse(input.toString())); + return ret; + } + }; + + public static final Function> toFloat = + new Function>() { + public Optional apply(Object input) { + Optional ret = absent(); + if (input != null) + ret = input instanceof Number ? + of(((Number) input).floatValue()) : + fromNullable(Floats.tryParse(input.toString())); + return ret; + } + }; + + /** + * Method stringConverter. + * @param enumClass Class + * @param or E + * @return Converter + */ + public static > Converter stringConverter( + final Class enumClass, + final E or) { + return new Converter() { + + @Override + protected String doBackward(E e) { + return checkNotNull(e).name(); + } + + @Override + protected E doForward(String s) { + return getIfPresent(enumClass, s).or(or); + } + + }; + } + + /** + * Method toUpperConverter. + * @return Converter + */ + public static Converter toUpperConverter() { + return toLowerConverter().reverse(); + } + + /** + * Method toUpperConverter. + * @param locale Locale + * @return Converter + */ + public static Converter toUpperConverter(Locale locale) { + return toLowerConverter(locale).reverse(); + } + + /** + * Method toLowerConverter. + * @return Converter + */ + public static Converter toLowerConverter() { + return toLowerConverter(Locale.getDefault()); + } + + /** + * Method toLowerConverter. + * @param locale Locale + * @return Converter + */ + public static Converter toLowerConverter(final Locale locale) { + return new Converter() { + + @Override + protected String doForward(String a) { + return a.toLowerCase(locale); + } + + @Override + protected String doBackward(String b) { + return b.toUpperCase(locale); + } + + }; + } +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/util/Module.java b/core/src/main/java/com/ibm/common/activitystreams/util/Module.java new file mode 100644 index 0000000..90be54c --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/util/Module.java @@ -0,0 +1,12 @@ +package com.ibm.common.activitystreams.util; + +import com.ibm.common.activitystreams.IO; +import com.ibm.common.activitystreams.internal.Schema; + +public interface Module { + + void apply(Schema.Builder builder); + + void apply(IO.Builder builder, Schema schema); + +} diff --git a/core/src/main/java/com/ibm/common/activitystreams/util/TypeValueResolver.java b/core/src/main/java/com/ibm/common/activitystreams/util/TypeValueResolver.java new file mode 100644 index 0000000..f080547 --- /dev/null +++ b/core/src/main/java/com/ibm/common/activitystreams/util/TypeValueResolver.java @@ -0,0 +1,31 @@ +package com.ibm.common.activitystreams.util; + +import com.google.common.base.Function; +import com.ibm.common.activitystreams.TypeValue; + +/** + * A TypeValue resolver is used to optionally replace TypeValue + * instances. Typically, this would be used to exchange simple + * string TypeValue's with their object equivalents (if one is + * available). + * + * The replacement can be performed during parsing by setting a + * TypeValueResolver on the IO.Builder. This should be done + * carefully, however, as the resolver could negatively impact + * parsing performance depending on how it is implemented. + * + * @author james + */ +public interface TypeValueResolver + extends Function { + + public static final TypeValueResolver DEFAULT_INSTANCE = + new DefaultTypeValueResolver(); + + public static final class DefaultTypeValueResolver + implements TypeValueResolver { + public TypeValue apply(TypeValue tv) { + return tv; + } + } +} diff --git a/core/src/test/java/com/ibm/common/activitystreams/test/TestBasics.java b/core/src/test/java/com/ibm/common/activitystreams/test/TestBasics.java new file mode 100644 index 0000000..f69a08d --- /dev/null +++ b/core/src/test/java/com/ibm/common/activitystreams/test/TestBasics.java @@ -0,0 +1,156 @@ +package com.ibm.common.activitystreams.test; + +import static org.junit.Assert.*; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.joda.time.DateTime; +import org.joda.time.Period; +import org.junit.Test; + +import com.google.common.collect.Iterables; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.ActionsValue; +import com.ibm.common.activitystreams.Activity; +import com.ibm.common.activitystreams.IO; +import com.ibm.common.activitystreams.LinkValue; +import com.ibm.common.activitystreams.LinkValue.SimpleLinkValue; +import com.ibm.common.activitystreams.Makers; +import com.ibm.common.activitystreams.NLV; +import com.ibm.common.activitystreams.NLV.MapNLV; +import com.ibm.common.activitystreams.ValueType; + +public final class TestBasics { + + @Test + public void testObject() { + + ASObject obj = + Makers.object() + .id("urn:example:test") + .title("This is a test") + .action("like", "http://example.org/actions/like") + .get(); + + assertNotNull(obj); + + assertEquals("urn:example:test", obj.id()); + assertEquals("This is a test", obj.titleString()); + + ActionsValue actions = obj.actions(); + Iterable lvs = actions.get("like"); + LinkValue lv = Iterables.getFirst(lvs, null); + assertEquals(ValueType.SIMPLE, lv.valueType()); + SimpleLinkValue slv = (SimpleLinkValue) lv; + assertEquals("http://example.org/actions/like", slv.url()); + + } + + @Test + public void testLanguageContext() { + ASObject obj = + Makers.object() + .language("en") + .title("en", "Foo") + .title("fr", "Bar") + .get(); + assertEquals("Foo", obj.titleString("en")); + assertEquals("Bar", obj.titleString("fr")); + + NLV nlv = obj.title(); + assertEquals(ValueType.OBJECT, nlv.valueType()); + + MapNLV map = (MapNLV) nlv; + assertTrue(map.has("en")); + assertTrue(map.has("fr")); + assertEquals("Foo", map.value("en")); + assertEquals("Bar", map.value("fr")); + } + + @Test + public void testDateTimes() { + DateTime now = DateTime.now(); + ASObject obj = + Makers.object() + .updated(now) + .published(now) + .startTime(now.minus(Period.days(1))) + .endTime(now.plus(Period.days(1))) + .get(); + assertNotNull(obj.updated()); + assertNotNull(obj.published()); + assertNotNull(obj.startTime()); + assertNotNull(obj.endTime()); + assertEquals(now, obj.updated()); + assertEquals(now, obj.published()); + assertTrue(now.isAfter(obj.startTime())); + assertTrue(now.isBefore(obj.endTime())); + } + + @Test + public void testSerialization() + throws IOException, + ClassNotFoundException { + + ASObject obj = + Makers.object() + .id("urn:example:test") + .title("This is a test") + .action("like", "http://example.org/actions/like") + .get(); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(out); + oos.writeObject(obj); + + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(in); + obj = (ASObject) ois.readObject(); + + assertNotNull(obj); + + assertEquals("urn:example:test", obj.id()); + assertEquals("This is a test", obj.titleString()); + + ActionsValue actions = obj.actions(); + Iterable lvs = actions.get("like"); + LinkValue lv = Iterables.getFirst(lvs, null); + assertEquals(ValueType.SIMPLE, lv.valueType()); + SimpleLinkValue slv = (SimpleLinkValue) lv; + assertEquals("http://example.org/actions/like", slv.url()); + + } + + @Test + public void testRoundTrip() { + Activity activity = + Makers.activity() + .verb("post") + .actor("acct:joe@example.org") + .object("http://example.org/1", "http://example.org/2") + .get(); + ByteArrayOutputStream out = + new ByteArrayOutputStream(); + activity.writeTo(out); + ByteArrayInputStream in = + new ByteArrayInputStream(out.toByteArray()); + activity = IO.makeDefault().readAsActivity(in); + + assertEquals("post", activity.verb().id()); + assertEquals("acct:joe@example.org", ((SimpleLinkValue)activity.firstActor()).url()); + + Iterable lvs = activity.object(); + + LinkValue lv = Iterables.get(lvs, 0); + assertEquals("http://example.org/1", ((SimpleLinkValue)lv).url()); + + lv = Iterables.get(lvs, 1); + assertEquals("http://example.org/2", ((SimpleLinkValue)lv).url()); + } + + +} diff --git a/core/src/test/java/com/ibm/common/activitystreams/test/TestIO.java b/core/src/test/java/com/ibm/common/activitystreams/test/TestIO.java new file mode 100644 index 0000000..48ceeba --- /dev/null +++ b/core/src/test/java/com/ibm/common/activitystreams/test/TestIO.java @@ -0,0 +1,57 @@ +package com.ibm.common.activitystreams.test; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.joda.time.DateTime; +import org.junit.Test; + +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.Activity; +import com.ibm.common.activitystreams.Collection; +import com.ibm.common.activitystreams.IO; +import com.ibm.common.activitystreams.internal.Schema; + +public final class TestIO { + + @Test + public void testIO() { + IO.Builder iobuilder = IO.make(); + assertNotNull(iobuilder); + IO io = iobuilder.get(); + assertNotNull(io); + } + + @Test + public void testIO2() { + final String in = "{\"a\":1,\"b\":2}"; + final String out = "{\n \"a\": 1,\n \"b\": 2\n}"; + IO io = IO.makeDefaultPrettyPrint(); + assertNotNull(io); + assertTrue(io.read(in).toString(io).equals(out)); + } + + @Test + public void testIO3() { + final String in = "{\"a\":1,\"b\":2}"; + IO io = IO.makeDefault(); + assertTrue(io.read(in) instanceof ASObject); + assertTrue(io.readAs(in,Activity.class) instanceof Activity); + assertTrue(io.readAs(in,Collection.class) instanceof Collection); + assertTrue(io.readAsActivity(in) instanceof Activity); + assertTrue(io.readAsCollection(in) instanceof Collection); + } + + @Test + public void testSchema() { + Schema schema = + Schema.make() + .map("foo", Schema.object.template().dateTime("bar")) + .get(); + IO io = IO.make().schema(schema).get(); + ASObject obj = + io.read( + "{\"objectType\":\"foo\",\"bar\":\"2013-12-12T12:12:12Z\"}"); + assertTrue(obj.get("bar") instanceof DateTime); + } +} diff --git a/core/src/test/resources/data/1.json b/core/src/test/resources/data/1.json new file mode 100755 index 0000000..e106cd5 --- /dev/null +++ b/core/src/test/resources/data/1.json @@ -0,0 +1,5 @@ +{ + "verb": "post", + "actor": "urn:example:person:joe", + "object": "http://example.org/posts/1" +} \ No newline at end of file diff --git a/geo/pom.xml b/geo/pom.xml new file mode 100755 index 0000000..4767a5a --- /dev/null +++ b/geo/pom.xml @@ -0,0 +1,144 @@ + + 4.0.0 + + com.ibm.common + activitystreams + 0.0.1-SNAPSHOT + + activitystreams-geo + Activity Streams 2.0 - GeoJSON + + + A GeoJSON Implementation that can be used standalone or with the IBM + Activity Streams 2.0 Reference Implementation + + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + UTF-8 + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + UTF-8 + UTF-8 + UTF-8 + -XDignore.symbol.file + public + + http://www.joda.org/joda-time/apidocs + http://docs.guava-libraries.googlecode.com/git-history/v16.0.1/javadoc/ + + + + + + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + maven-jar-plugin + 2.3.1 + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + + org.apache.felix + maven-bundle-plugin + 2.3.7 + true + + + bundle-manifest + process-classes + + manifest + + + + + + com.ibm.common.geojson.* + + com.ibm.common.activitystreams.*, + com.google.gson.*, + com.google.common.*, + org.joda.time.* + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.2.2 + + + assembly.xml + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.apache.felix + maven-bundle-plugin + [2.3.7,) + + manifest + + + + + + + + + + + + + + + + + com.ibm.common + activitystreams-core + 0.0.1-SNAPSHOT + + + + \ No newline at end of file diff --git a/geo/src/main/java/com/ibm/common/geojson/AS1Position.java b/geo/src/main/java/com/ibm/common/geojson/AS1Position.java new file mode 100644 index 0000000..57d0c23 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/AS1Position.java @@ -0,0 +1,77 @@ +package com.ibm.common.geojson; + +import static com.google.common.primitives.Floats.max; +import static com.google.common.primitives.Floats.min; + +import java.io.ObjectStreamException; + +import com.ibm.common.activitystreams.ASObject; + +/** + * Represents an Activity Streams 1.0 style position object + * @author james + * @deprecated Use Position + */ +public final class AS1Position + extends ASObject { + + public static final class Builder + extends ASObject.AbstractBuilder { + + Builder() { + objectType("position"); + } + + public Builder latitude(float latitude) { + return set("latitude", max(0f,min(90.0f,latitude))); + } + + public Builder longitude(float longitude) { + return set("longitude", max(-180.0f,min(180.0f,longitude))); + } + + public Builder altitude(float altitude) { + return set("altitude", altitude); + } + + @Override + public AS1Position get() { + return new AS1Position(this); + } + + } + + private AS1Position(Builder builder) { + super(builder); + } + + public float latitude() { + return max(0f,min(90.0f,getFloat("latitude"))); + } + + public float longitude() { + return max(-180.0f,min(180.0f,getFloat("longitude"))); + } + + public float altitude() { + return getFloat("altitude"); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(AS1Position obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected AS1Position.Builder builder() { + return GeoMakers.as1Position(); + } + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/Address.java b/geo/src/main/java/com/ibm/common/geojson/Address.java new file mode 100644 index 0000000..59507a0 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/Address.java @@ -0,0 +1,93 @@ +package com.ibm.common.geojson; + +import java.io.ObjectStreamException; + +import com.ibm.common.activitystreams.ASObject; + +public final class Address + extends ASObject { + + public static final class Builder + extends ASObject.AbstractBuilder { + + Builder() { + objectType("address"); + } + + public Builder formatted(String formatted) { + return set("formatted", formatted); + } + + public Builder streetAddress(String streetAddress) { + return set("streetAddress", streetAddress); + } + + public Builder locality(String locality) { + return set("locality", locality); + } + + public Builder region(String region) { + return set("region", region); + } + + public Builder postalCode(String postalCode) { + return set("postalCode", postalCode); + } + + public Builder country(String country) { + return set("country", country); + } + + @Override + public Address get() { + return new Address(this); + } + + } + + private Address(Builder builder) { + super(builder); + } + + public String formatted() { + return getString("formatted"); + } + + public String streetAddress() { + return getString("streetAddress"); + } + + public String locality() { + return getString("locality"); + } + + public String region() { + return getString("region"); + } + + public String postalCode() { + return getString("postalCode"); + } + + public String country() { + return getString("country"); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm
{ + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(Address obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected Address.Builder builder() { + return GeoMakers.address(); + } + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/BoundingBox.java b/geo/src/main/java/com/ibm/common/geojson/BoundingBox.java new file mode 100644 index 0000000..2522a64 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/BoundingBox.java @@ -0,0 +1,254 @@ +package com.ibm.common.geojson; + +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.Iterator; + +import com.google.common.base.Objects; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Iterables; + +public final class BoundingBox + implements Iterable, Serializable { + + public static final class Builder + implements Supplier { + + private final ImmutableList.Builder bounds = + ImmutableList.builder(); + + public Builder add(float value) { + this.bounds.add(value); + return this; + } + + public Builder add(float... values) { + if (values != null) + for (float v : values) + this.bounds.add(v); + return this; + } + + @Override + public BoundingBox get() { + return new BoundingBox(this); + } + + } + + private final ImmutableList bounds; + + BoundingBox(Builder builder) { + this.bounds = builder.bounds.build(); + } + + @Override + public Iterator iterator() { + return bounds.iterator(); + } + + public String toString() { + return Objects.toStringHelper(BoundingBox.class) + .addValue(bounds) + .toString(); + } + + private static BoundingBox buildBoundingBox( + ImmutableSortedSet xs, + ImmutableSortedSet ys, + ImmutableSortedSet zs) { + BoundingBox.Builder bbox = + new BoundingBox.Builder() + .add(xs.first()) + .add(ys.first()); + if (!zs.isEmpty()) + bbox.add(zs.first()); + bbox.add(xs.last()); + bbox.add(ys.last()); + if (!zs.isEmpty()) + bbox.add(zs.last()); + return bbox.get(); + } + + protected static BoundingBox calculateBoundingBoxLineStrings(Iterable lineStrings) { + ImmutableSortedSet.Builder xset = + ImmutableSortedSet.naturalOrder(); + ImmutableSortedSet.Builder yset = + ImmutableSortedSet.naturalOrder(); + ImmutableSortedSet.Builder zset = + ImmutableSortedSet.naturalOrder(); + for (LineString ls : lineStrings) { + for (Position p : ls) { + xset.add(p.northing()); + yset.add(p.easting()); + if (p.hasAltitude()) + zset.add(p.altitude()); + } + } + return buildBoundingBox( + xset.build(), + yset.build(), + zset.build()); + } + + public static BoundingBox calculateBoundingBoxPolygons(Iterable polygons) { + ImmutableSortedSet.Builder xset = + ImmutableSortedSet.naturalOrder(); + ImmutableSortedSet.Builder yset = + ImmutableSortedSet.naturalOrder(); + ImmutableSortedSet.Builder zset = + ImmutableSortedSet.naturalOrder(); + for (Polygon polygon : polygons) { + for (LineString line : polygon) { + for (Position pos : line) { + xset.add(pos.northing()); + yset.add(pos.easting()); + if (pos.hasAltitude()) + zset.add(pos.altitude()); + } + } + } + return buildBoundingBox( + xset.build(), + yset.build(), + zset.build()); + } + + protected static BoundingBox calculateBoundingBoxPositions(Iterable positions) { + ImmutableSortedSet.Builder xset = + ImmutableSortedSet.naturalOrder(); + ImmutableSortedSet.Builder yset = + ImmutableSortedSet.naturalOrder(); + ImmutableSortedSet.Builder zset = + ImmutableSortedSet.naturalOrder(); + for (Position pos : positions) { + xset.add(pos.northing()); + yset.add(pos.easting()); + if (pos.hasAltitude()) + zset.add(pos.altitude()); + } + return buildBoundingBox( + xset.build(), + yset.build(), + zset.build()); + } + + protected static BoundingBox calculateBoundingBox(Position position) { + BoundingBox.Builder bbox = + new BoundingBox.Builder(); + bbox.add(position.northing()); + bbox.add(position.easting()); + if (position.hasAltitude()) + bbox.add(position.altitude()); + return bbox.get(); + } + + private static void addValues( + ImmutableSortedSet.Builder xset, + ImmutableSortedSet.Builder yset, + ImmutableSortedSet.Builder zset, + Iterable positions) { + for (Position position : positions) { + xset.add(position.northing()); + yset.add(position.easting()); + if (position.hasAltitude()) + zset.add(position.altitude()); + } + } + + private static void addValuesLineString( + ImmutableSortedSet.Builder xset, + ImmutableSortedSet.Builder yset, + ImmutableSortedSet.Builder zset, + Iterable lines) { + for (LineString ls : lines) { + addValues(xset,yset,zset,ls); + } + } + + private static void addValuesPolygon( + ImmutableSortedSet.Builder xset, + ImmutableSortedSet.Builder yset, + ImmutableSortedSet.Builder zset, + Iterable polygons) { + for (Polygon poly : polygons) { + addValuesLineString(xset,yset,zset,poly); + } + } + + protected static BoundingBox calculateBoundingBox(Geometry geometry) { + return calculateBoundingBoxGeometries( + ImmutableList.>of(geometry)); + } + + @SuppressWarnings("unchecked") + protected static BoundingBox calculateBoundingBoxGeometries( + Iterable> geometries) { + ImmutableSortedSet.Builder xset = + ImmutableSortedSet.naturalOrder(); + ImmutableSortedSet.Builder yset = + ImmutableSortedSet.naturalOrder(); + ImmutableSortedSet.Builder zset = + ImmutableSortedSet.naturalOrder(); + for (Geometry geo : geometries) { + switch(geo.type()) { + case POINT: + Point point = (Point) geo; + Position position = Iterables.getFirst(point.coordinates(),null); + xset.add(position.northing()); + yset.add(position.easting()); + if (position.hasAltitude()) + zset.add(position.altitude()); + break; + case LINESTRING: + case MULTIPOINT: + addValues(xset,yset,zset,(Iterable)geo); + break; + case MULTILINESTRING: + case POLYGON: + addValuesLineString(xset,yset,zset,(Iterable)geo); + break; + case MULTIPOLYGON: + addValuesPolygon(xset,yset,zset,(Iterable)geo); + break; + default: + break; + } + } + return buildBoundingBox( + xset.build(), + yset.build(), + zset.build()); + } + + protected static BoundingBox calculateBoundingBoxFeatures(Iterable features) { + ImmutableList.Builder> list = + ImmutableList.builder(); + for (Feature feature : features) { + Geometry geometry = feature.geometry(); + if (geometry != null) + list.add(geometry); + } + return calculateBoundingBoxGeometries(list.build()); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm implements Serializable { + private static final long serialVersionUID = -2060301713159936285L; + private ImmutableList bounds; + protected SerializedForm(BoundingBox obj) { + this.bounds = obj.bounds; + } + Object readResolve() throws ObjectStreamException { + BoundingBox.Builder builder = + new BoundingBox.Builder(); + builder.bounds.addAll(bounds); + return builder.get(); + } + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/CRS.java b/geo/src/main/java/com/ibm/common/geojson/CRS.java new file mode 100644 index 0000000..56fab04 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/CRS.java @@ -0,0 +1,122 @@ +package com.ibm.common.geojson; + +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.Iterator; +import java.util.Map; + +import com.google.common.base.Objects; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; + +public final class CRS + implements Iterable, Serializable { + + public static final class Builder implements Supplier { + + private String type; + private ImmutableMap.Builder properties = + ImmutableMap.builder(); + + public Builder type(String type) { + this.type = type; + return this; + } + + public Builder set(String name, Object value) { + this.properties.put(name,value); + return this; + } + + public Builder set(Map properties) { + this.properties.putAll(properties); + return this; + } + + public CRS get() { + return new CRS(this); + } + + } + + private final String type; + private final Map properties; + + CRS(Builder builder) { + this.type = builder.type; + this.properties = builder.properties.build(); + } + + public String toString() { + return Objects.toStringHelper(CRS.class) + .addValue(type) + .addValue(properties) + .toString(); + } + + public int size() { + return properties.size(); + } + + public String type() { + return type; + } + + public Map properties() { + return properties; + } + + @SuppressWarnings("unchecked") + public T get(String name) { + return (T)properties.get(name); + } + + public T get(String name, T defaultValue) { + T t = this.get(name); + return t != null ? t : defaultValue; + } + + public boolean has(String name) { + return properties.containsKey(name); + } + + @Override + public Iterator iterator() { + return properties.keySet().iterator(); + } + + public static final CRS named(String name) { + return new CRS.Builder() + .type("name") + .set("name",name) + .get(); + } + + public static final CRS linked(String href, String type) { + return new CRS.Builder() + .type("link") + .set("href", href) + .set("type", type) + .get(); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm implements Serializable { + private static final long serialVersionUID = -2060301713159936285L; + private String type; + private Map properties; + protected SerializedForm(CRS obj) { + this.type = obj.type; + this.properties = obj.properties; + } + Object readResolve() throws ObjectStreamException { + CRS.Builder builder = new CRS.Builder(); + builder.type(type); + builder.properties.putAll(properties); + return builder.get(); + } + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/Feature.java b/geo/src/main/java/com/ibm/common/geojson/Feature.java new file mode 100644 index 0000000..1ce16dd --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/Feature.java @@ -0,0 +1,133 @@ +package com.ibm.common.geojson; + +import static com.ibm.common.geojson.BoundingBox.calculateBoundingBox; + +import java.io.ObjectStreamException; +import java.util.Iterator; +import java.util.Map; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; + +public final class Feature + extends GeoObject + implements Iterable { + + public static final class Builder + extends GeoObject.Builder { + + private final ImmutableMap.Builder properties = + ImmutableMap.builder(); + + public Builder() { + type(GeoObject.Type.FEATURE); + } + + public Builder geometry(Geometry geometry) { + return set("geometry", geometry); + } + + public Builder geometry(Supplier> geometry) { + return geometry(geometry.get()); + } + + public Builder property(String name, Object value) { + this.properties.put(name, value); + return this; + } + + protected Builder properties(Map properties) { + properties.putAll(properties); + return this; + } + + public Builder id(String id) { + return set("id", id); + } + + @Override + public Feature doGet() { + set("properties", properties.build()); + return new Feature(this); + } + + } + + Feature(Builder builder) { + super(builder); + } + + public >G geometry() { + return this.get("geometry"); + } + + public Map properties() { + return this.>get( + "properties", + ImmutableMap.of()); + } + + public String id() { + return this.get("id"); + } + + @SuppressWarnings("unchecked") + public T getProperty(String name) { + return (T) properties().get(name); + } + + public T getProperty(String name, T defaultValue) { + T t = this.getProperty(name); + return t != null ? t : defaultValue; + } + + public boolean has(String name) { + return properties().containsKey(name); + } + + @Override + public Iterator iterator() { + return properties().keySet().iterator(); + } + + @Override + protected Feature makeWithBoundingBox() { + return new Feature.Builder() + .from(this) + .properties(this.properties()) + .boundingBox( + calculateBoundingBox(geometry())).get(); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936281L; + protected SerializedForm(Feature obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return doReadResolve(); + } + @SuppressWarnings("unchecked") + @Override + protected boolean handle( + Builder builder, + String key, + Object val) { + if ("properties".equals(key)) { + Map props = (Map) val; + builder.properties.putAll(props); + return true; + } + return false; + } + @Override + protected Builder builder() { + return new Feature.Builder(); + } + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/FeatureCollection.java b/geo/src/main/java/com/ibm/common/geojson/FeatureCollection.java new file mode 100644 index 0000000..36159a4 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/FeatureCollection.java @@ -0,0 +1,103 @@ +package com.ibm.common.geojson; + +import static com.ibm.common.geojson.BoundingBox.calculateBoundingBoxFeatures; + +import java.io.ObjectStreamException; +import java.util.Iterator; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + +public final class FeatureCollection + extends GeoObject + implements Iterable { + + public static final class Builder + extends GeoObject.Builder { + + private final ImmutableList.Builder list = + ImmutableList.builder(); + + public Builder() { + type(GeoObject.Type.FEATURECOLLECTION); + } + + public Builder add(Iterable features) { + list.addAll(features); + return this; + } + + public Builder add(Feature feature, Feature... features) { + list.add(feature); + if (features != null) + list.add(features); + return this; + } + + public Builder add(Supplier feature) { + return add(feature.get()); + } + + @Override + public void preGet() { + set("features", list.build()); + } + + @Override + public FeatureCollection doGet() { + return new FeatureCollection(this); + } + + } + + FeatureCollection(Builder builder) { + super(builder); + } + + public Iterable features() { + return this.>get( + "features", + ImmutableList.of()); + } + + public int size() { + return Iterables.size(features()); + } + + public Feature get(int idx) { + return Iterables.get(features(),idx); + } + + public Iterator iterator() { + return features().iterator(); + } + + @Override + protected FeatureCollection makeWithBoundingBox() { + return new FeatureCollection.Builder() + .from(this) + .add(this) + .boundingBox(calculateBoundingBoxFeatures(this)) + .get(); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936281L; + protected SerializedForm(FeatureCollection obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return doReadResolve(); + } + @Override + protected FeatureCollection.Builder builder() { + return GeoMakers.featureCollection(); + } + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/GeoMakers.java b/geo/src/main/java/com/ibm/common/geojson/GeoMakers.java new file mode 100644 index 0000000..65b7630 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/GeoMakers.java @@ -0,0 +1,109 @@ +package com.ibm.common.geojson; + +@SuppressWarnings("deprecation") +public final class GeoMakers { + + private GeoMakers() {} + + public static Place.Builder place() { + return new Place.Builder(); + } + + /** @deprecated **/ + public static AS1Position.Builder as1Position() { + return new AS1Position.Builder(); + } + + /** @deprecated **/ + public static AS1Position as1Position( + float latitude, + float longitude, + float altitude) { + return as1Position() + .longitude(longitude) + .latitude(latitude) + .altitude(altitude) + .get(); + } + + /** @deprecated **/ + public static AS1Position as1Position( + Position position) { + return as1Position( + position.northing(), + position.easting(), + position.altitude()); + } + + public static Position position( + AS1Position position) { + return position( + position.latitude(), + position.longitude(), + position.altitude()); + } + + public static Address.Builder address() { + return new Address.Builder(); + } + + public static Position position(float x, float y) { + return GeoObject.position(x,y); + } + + public static Position position(float x, float y, float z) { + return GeoObject.position(x, y, z); + } + + public static Point point(float x, float y) { + return point().position(x,y).get(); + } + + public static Point point(float x, float y, float z) { + return point().position(x, y, z).get(); + } + + public static Point point(Position position) { + return point().position(position).get(); + } + + public static Point.Builder point() { + return new Point.Builder(); + } + + public static MultiPoint.Builder multipoint() { + return new MultiPoint.Builder(); + } + + public static LineString.Builder linestring() { + return new LineString.Builder(); + } + + public static LineString.Builder linearRing() { + return linestring().linearRing(); + } + + public static Feature.Builder feature() { + return new Feature.Builder(); + } + + public static FeatureCollection.Builder featureCollection() { + return new FeatureCollection.Builder(); + } + + public static GeometryCollection.Builder geometryCollection() { + return new GeometryCollection.Builder(); + } + + public static MultiLineString.Builder multiLineString() { + return new MultiLineString.Builder(); + } + + public static MultiPolygon.Builder multiPolygon() { + return new MultiPolygon.Builder(); + } + + public static Polygon.Builder polygon() { + return new Polygon.Builder(); + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/GeoObject.java b/geo/src/main/java/com/ibm/common/geojson/GeoObject.java new file mode 100644 index 0000000..3d6ee45 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/GeoObject.java @@ -0,0 +1,172 @@ +package com.ibm.common.geojson; + +import java.io.Serializable; +import java.util.Map; + +import com.google.common.base.Objects; +import com.google.common.base.Supplier; + +import static com.google.common.collect.ImmutableMap.copyOf; +import static com.google.common.collect.Maps.newLinkedHashMap; + +@SuppressWarnings("unchecked") +public abstract class GeoObject> + implements Serializable { + + private static final long serialVersionUID = 8852811044366213922L; + + public static enum Type { + POINT, + MULTIPOINT, + LINESTRING, + MULTILINESTRING, + POLYGON, + MULTIPOLYGON, + GEOMETRYCOLLECTION, + FEATURE, + FEATURECOLLECTION + } + + public static abstract class Builder + , B extends Builder> + implements Supplier { + + protected boolean withBoundingBox = false; + protected Type type; + protected Map data = + newLinkedHashMap(); + + public B calculateBoundingBox() { + this.withBoundingBox = true; + return (B)this; + } + + protected B from(GeoObject geo) { + data.putAll(geo.data); + return (B)this; + } + + public B type(Type type) { + this.type = type; + return (B)this; + } + + public B crs(CRS crs) { + return set("crs", crs); + } + + public B boundingBox(BoundingBox bbox) { + return set("bbox", bbox); + } + + public B set(String name, Object val) { + if (val != null) + this.data.put(name,val); + else if (this.data.containsKey(name)) + this.data.remove(name); + return (B)this; + } + + public final G get() { + preGet(); + G g = doGet(); + return withBoundingBox ? g.withBoundingBox() : g; + } + + protected void preGet() {} + + protected abstract G doGet(); + } + + final Type type; + final Map data; + + protected GeoObject(Builder builder) { + this.type = builder.type; + this.data = copyOf(builder.data); + } + + public Type type() { + return type; + } + + public T get(String name) { + return (T)data.get(name); + } + + public T get(String name, T defaultValue) { + T val = get(name); + return val != null ? val : defaultValue; + } + + public boolean has(String name) { + return data.containsKey(name); + } + + public CRS crs() { + return this.get("crs", null); + } + + public BoundingBox boundingBox() { + return this.get("bbox", null); + } + + public final G withBoundingBox() { + return has("bbox") ? + (G)this : makeWithBoundingBox(); + } + + protected abstract G makeWithBoundingBox(); + + public static final Position position(float x, float y) { + return new Position.Builder() + .northing(x) + .easting(y) + .get(); + } + + public static final Position position(float x, float y, float z) { + return new Position.Builder() + .northing(x) + .easting(y) + .altitude(z) + .get(); + } + + public String toString() { + return Objects.toStringHelper(GeoObject.class) + .add("type", type) + .add("data", data) + .toString(); + } + + protected static abstract class AbstractSerializedForm + , B extends GeoObject.Builder> + implements Serializable { + private static final long serialVersionUID = -1950126276150975248L; + private Type type; + private Map data; + AbstractSerializedForm(G obj) { + this.type = obj.type(); + this.data = obj.data; + } + protected Object doReadResolve() { + B builder = builder(); + builder.type(type); + for (Map.Entry entry : data.entrySet()) { + String key = entry.getKey(); + Object val = entry.getValue(); + if (!handle(builder, key,val)) + builder.data.put(key,val); + } + return builder.get(); + } + protected boolean handle( + B builder, + String key, + Object val) { + return false; + } + protected abstract B builder(); + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/Geometry.java b/geo/src/main/java/com/ibm/common/geojson/Geometry.java new file mode 100644 index 0000000..6ed0ec6 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/Geometry.java @@ -0,0 +1,48 @@ +package com.ibm.common.geojson; + +import com.google.common.collect.ImmutableList; + +public abstract class Geometry, M> + extends GeoObject + implements Iterable { + + private static final long serialVersionUID = -6184360762496309625L; + + protected Geometry(Builder builder) { + super(builder); + } + + public static abstract class CoordinateGeometry, M,P> + extends Geometry { + + private static final long serialVersionUID = -6502745908455054826L; + + protected static abstract class Builder + , B extends Builder> + extends GeoObject.Builder { + + protected abstract P coordinates(); + + public void preGet() { + set("coordinates", coordinates()); + } + + protected abstract C doGet(); + } + + protected CoordinateGeometry(Builder builder) { + super(builder); + } + + @SuppressWarnings("unchecked") + public Iterable coordinates() { + Object o = get("coordinates"); + if (o instanceof Iterable) + return (Iterable)o; + else + return ImmutableList.of((M)o); + } + + } + +} diff --git a/geo/src/main/java/com/ibm/common/geojson/GeometryCollection.java b/geo/src/main/java/com/ibm/common/geojson/GeometryCollection.java new file mode 100644 index 0000000..8329faa --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/GeometryCollection.java @@ -0,0 +1,107 @@ +package com.ibm.common.geojson; + +import static com.ibm.common.geojson.BoundingBox.calculateBoundingBoxGeometries; + +import java.io.ObjectStreamException; +import java.util.Iterator; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + +public final class GeometryCollection + extends Geometry> { + + public static final class Builder + extends GeoObject.Builder { + + private final ImmutableList.Builder> list = + ImmutableList.builder(); + + public Builder() { + type(GeoObject.Type.GEOMETRYCOLLECTION); + } + + public Builder add(Geometry geometry, Geometry... geometries) { + list.add(geometry); + if (geometries != null) + list.add(geometries); + return this; + } + + public Builder add(Iterable> geometries) { + list.addAll(geometries); + return this; + } + + @Override + public void preGet() { + set("geometries", list.build()); + } + + @Override + public GeometryCollection doGet() { + return new GeometryCollection(this); + } + } + + GeometryCollection(Builder builder) { + super(builder); + } + + public Iterable> geometries() { + return this.>>get( + "geometries", + ImmutableList.>of()); + } + + public int size() { + return Iterables.size(geometries()); + } + + @SuppressWarnings("unchecked") + public >G get(int idx) { + return (G)Iterables.get(geometries(),idx); + } + + public Iterator> iterator() { + return geometries().iterator(); + } + + @Override + public GeometryCollection makeWithBoundingBox() { + return new GeometryCollection.Builder() + .from(this) + .add(this) + .boundingBox(calculateBoundingBoxGeometries(this)) + .get(); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936281L; + protected SerializedForm(GeometryCollection obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return doReadResolve(); + } + @SuppressWarnings("unchecked") + @Override + protected boolean handle(Builder builder, String key, Object val) { + if ("geometries".equals(key)) { + Iterable> list = (Iterable>) val; + builder.list.addAll(list); + return true; + } + return false; + } + @Override + protected GeometryCollection.Builder builder() { + return GeoMakers.geometryCollection(); + } + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/LineString.java b/geo/src/main/java/com/ibm/common/geojson/LineString.java new file mode 100644 index 0000000..2359ad9 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/LineString.java @@ -0,0 +1,161 @@ +package com.ibm.common.geojson; + +import static com.ibm.common.geojson.BoundingBox.calculateBoundingBoxPositions; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.Iterables.concat; +import static com.google.common.collect.Iterables.getFirst; +import static com.google.common.collect.Iterables.size; +import static java.lang.String.format; + +import java.io.ObjectStreamException; +import java.util.Iterator; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.ibm.common.geojson.Geometry.CoordinateGeometry; + +public final class LineString + extends CoordinateGeometry> { + + public static final class Builder + extends CoordinateGeometry.Builder,LineString, Builder> { + + private final ImmutableList.Builder positions = + ImmutableList.builder(); + private boolean ring; + private final boolean nocheck; + + public Builder() { + nocheck = false; + type(Type.LINESTRING); + } + + private Builder(boolean nocheck) { + this.nocheck = nocheck; + type(Type.LINESTRING); + } + + public Builder linearRing() { + return linearRing(true); + } + + public Builder linearRing(boolean on) { + this.ring = on; + return this; + } + + public Builder add(Position position, Position... positions) { + this.positions.add(position); + if (positions != null) + for (Position pos : positions) + add(pos); + return this; + } + + public Builder add(float x, float y) { + return add(GeoObject.position(x, y)); + } + + public Builder add(Supplier position) { + return add(position.get()); + } + + public Builder add(Iterable positions) { + this.positions.addAll(positions); + return this; + } + + public Builder add(float x, float y, float z) { + return add(GeoObject.position(x,y,z)); + } + + public LineString doGet() { + return new LineString(this); + } + + @Override + protected Iterable coordinates() { + return positions.build(); + } + + } + + private final boolean ring; + + protected LineString( + Builder builder) { + super(builder); + this.ring = builder.ring; + int min = ring?3:2; + checkArgument( + builder.nocheck || + size(coordinates()) >= min, + format( + "A LineString that %s a LinearRing MUST consist of at least %d positions", + ring?"is":"is not", + min)); + } + + public boolean linearRing() { + return ring; + } + + @Override + public Iterable coordinates() { + Iterable pos = super.coordinates(); + if (!ring) + return pos; + else { + return size(pos) > 0 ? + concat(pos,ImmutableList.of(getFirst(pos,null))) : + ImmutableList.of(); + } + } + + @Override + public Iterator iterator() { + return coordinates().iterator(); + } + + @Override + public LineString makeWithBoundingBox() { + return new LineString.Builder() + .from(this) + .add(this) + .boundingBox(calculateBoundingBoxPositions(this)) + .get(); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936281L; + boolean ring; + protected SerializedForm(LineString obj) { + super(obj); + this.ring = obj.ring; + } + Object readResolve() throws ObjectStreamException { + return doReadResolve(); + } + @SuppressWarnings("unchecked") + @Override + protected boolean handle(Builder builder, String key, Object val) { + if ("coordinates".equals(key)) { + Iterable list = (Iterable) val; + builder.positions.addAll(list); + return true; + } + return false; + } + @Override + protected LineString.Builder builder() { + Builder builder = new Builder(true); + builder.ring = ring; + return builder; + } + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/MultiLineString.java b/geo/src/main/java/com/ibm/common/geojson/MultiLineString.java new file mode 100644 index 0000000..f36a7ae --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/MultiLineString.java @@ -0,0 +1,99 @@ +package com.ibm.common.geojson; + +import static com.ibm.common.geojson.BoundingBox.calculateBoundingBoxLineStrings; + +import java.io.ObjectStreamException; +import java.util.Iterator; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.ibm.common.geojson.Geometry.CoordinateGeometry; + +public final class MultiLineString + extends CoordinateGeometry> { + + public static final class Builder + extends CoordinateGeometry.Builder, MultiLineString, Builder> { + + private final ImmutableList.Builder strings = + ImmutableList.builder(); + + public Builder() { + type(Type.MULTILINESTRING); + } + + public Builder add(LineString line, LineString... lines) { + this.strings.add(line); + if (lines != null) + for (LineString l : lines) + add(l); + return this; + } + + public Builder add(Supplier line) { + return add(line.get()); + } + + public Builder add(Iterable lines) { + this.strings.addAll(lines); + return this; + } + + public MultiLineString doGet() { + return new MultiLineString(this); + } + + @Override + protected Iterable coordinates() { + return strings.build(); + } + + } + + protected MultiLineString( + Builder builder) { + super(builder); + } + + @Override + public Iterator iterator() { + return coordinates().iterator(); + } + + @Override + protected MultiLineString makeWithBoundingBox() { + return new MultiLineString.Builder() + .from(this) + .add(this) + .boundingBox( + calculateBoundingBoxLineStrings(this)).get(); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936281L; + protected SerializedForm(MultiLineString obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return doReadResolve(); + } + @SuppressWarnings("unchecked") + protected boolean handle(Builder builder, String key, Object val) { + if ("coordinates".equals(key)) { + Iterable list = (Iterable) val; + builder.strings.addAll(list); + return true; + } + return false; + } + @Override + protected MultiLineString.Builder builder() { + return GeoMakers.multiLineString(); + } + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/MultiPoint.java b/geo/src/main/java/com/ibm/common/geojson/MultiPoint.java new file mode 100644 index 0000000..895eae3 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/MultiPoint.java @@ -0,0 +1,107 @@ +package com.ibm.common.geojson; + +import java.io.ObjectStreamException; +import java.util.Iterator; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.ibm.common.geojson.Geometry.CoordinateGeometry; + +import static com.ibm.common.geojson.BoundingBox.calculateBoundingBoxPositions; + +public final class MultiPoint + extends CoordinateGeometry> { + + public static final class Builder + extends CoordinateGeometry.Builder,MultiPoint,Builder> { + + protected ImmutableList.Builder list = + ImmutableList.builder(); + + public Builder() { + type(GeoObject.Type.MULTIPOINT); + } + + public Builder add(Position position, Position... positions) { + list.add(position); + if (positions != null) + list.add(positions); + return this; + } + + public Builder add(Iterable positions) { + list.addAll(positions); + return this; + } + + public Builder add(Supplier pos) { + return add(pos.get()); + } + + public Builder add(float x, float y) { + return add(GeoObject.position(x, y)); + } + + public Builder add(float x, float y, float z) { + return add(GeoObject.position(x,y,z)); + } + + @Override + protected Iterable coordinates() { + return list.build(); + } + + @Override + public MultiPoint doGet() { + return new MultiPoint(this); + } + + } + + protected MultiPoint( + Builder builder) { + super(builder); + } + + @Override + public Iterator iterator() { + return coordinates().iterator(); + } + + @Override + protected MultiPoint makeWithBoundingBox() { + return new MultiPoint.Builder() + .from(this) + .add(this) + .boundingBox(calculateBoundingBoxPositions(this)).get(); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936281L; + protected SerializedForm(MultiPoint obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return doReadResolve(); + } + @SuppressWarnings("unchecked") + @Override + protected boolean handle(Builder builder, String key, Object val) { + if ("coordinates".equals(key)) { + Iterable list = (Iterable) val; + builder.list.addAll(list); + return true; + } + return false; + } + @Override + protected MultiPoint.Builder builder() { + return GeoMakers.multipoint(); + } + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/MultiPolygon.java b/geo/src/main/java/com/ibm/common/geojson/MultiPolygon.java new file mode 100644 index 0000000..36885e1 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/MultiPolygon.java @@ -0,0 +1,101 @@ +package com.ibm.common.geojson; + +import static com.ibm.common.geojson.BoundingBox.calculateBoundingBoxPolygons; + +import java.io.ObjectStreamException; +import java.util.Iterator; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.ibm.common.geojson.Geometry.CoordinateGeometry; + +public final class MultiPolygon + extends CoordinateGeometry>{ + + public static final class Builder + extends CoordinateGeometry.Builder, MultiPolygon, Builder> { + + private final ImmutableList.Builder strings = + ImmutableList.builder(); + + public Builder() { + type(Type.MULTIPOLYGON); + } + + public Builder add(Polygon poly, Polygon... polys) { + // TODO: Check hole requirement + this.strings.add(poly); + if (polys != null) + for (Polygon l : polys) + add(l); + return this; + } + + public Builder add(Supplier poly) { + return add(poly.get()); + } + + public Builder add(Iterable polygons) { + this.strings.addAll(polygons); + return this; + } + + public MultiPolygon doGet() { + return new MultiPolygon(this); + } + + @Override + protected Iterable coordinates() { + return strings.build(); + } + + } + + protected MultiPolygon( + Builder builder) { + super(builder); + } + + @Override + public Iterator iterator() { + return coordinates().iterator(); + } + + @Override + protected MultiPolygon makeWithBoundingBox() { + return new MultiPolygon.Builder() + .from(this) + .add(this) + .boundingBox(calculateBoundingBoxPolygons(this)) + .get(); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936281L; + protected SerializedForm(MultiPolygon obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return doReadResolve(); + } + @SuppressWarnings("unchecked") + @Override + protected boolean handle(Builder builder, String key, Object val) { + if ("coordinates".equals(key)) { + Iterable list = (Iterable) val; + builder.strings.addAll(list); + return true; + } + return false; + } + @Override + protected MultiPolygon.Builder builder() { + return GeoMakers.multiPolygon(); + } + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/Place.java b/geo/src/main/java/com/ibm/common/geojson/Place.java new file mode 100644 index 0000000..f156042 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/Place.java @@ -0,0 +1,92 @@ +package com.ibm.common.geojson; + +import java.io.ObjectStreamException; + +import com.google.common.base.Supplier; +import com.ibm.common.activitystreams.ASObject; + +public final class Place extends ASObject { + + public static final class Builder + extends ASObject.AbstractBuilder { + + Builder() { + objectType("place"); + } + + public Builder address(Address address) { + return set("address", address); + } + + public Builder address(Supplier
address) { + return address(address.get()); + } + + @SuppressWarnings("deprecation") + public Builder position(AS1Position position) { + return set("position", position); + } + + @SuppressWarnings("deprecation") + public Builder position(Supplier position) { + return position(position.get()); + } + + @SuppressWarnings("deprecation") + public Builder position( + float latitude, + float longitude, + float altitude) { + return position(GeoMakers.as1Position(latitude, longitude, altitude)); + } + + public Builder geo(GeoObject geo) { + return set("geo", geo); + } + + public Builder geo(Supplier> geo) { + return geo(geo.get()); + } + + @Override + public Place get() { + return new Place(this); + } + + } + + private Place(Builder builder) { + super(builder); + } + + public Address address() { + return this.
get("address"); + } + + @SuppressWarnings("deprecation") + public AS1Position position() { + return this.get("position"); + } + + public >G geo() { + return this.get("geo"); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(Place obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected Place.Builder builder() { + return GeoMakers.place(); + } + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/Point.java b/geo/src/main/java/com/ibm/common/geojson/Point.java new file mode 100644 index 0000000..8c87387 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/Point.java @@ -0,0 +1,102 @@ +package com.ibm.common.geojson; + +import java.io.ObjectStreamException; +import java.util.Iterator; + +import com.google.common.base.Supplier; + +import static com.google.common.collect.Iterables.getFirst; +import static com.ibm.common.geojson.BoundingBox.calculateBoundingBox; + +import com.ibm.common.geojson.Geometry.CoordinateGeometry; + +public final class Point + extends CoordinateGeometry { + + public static final class Builder + extends CoordinateGeometry.Builder { + + protected Position position; + + public Builder() { + type(GeoObject.Type.POINT); + } + + public Builder position(float x, float y, float z) { + this.position = GeoObject.position(x, y, z); + return this; + } + + public Builder position(float x, float y) { + this.position = GeoObject.position(x,y); + return this; + } + + public Builder position(Position position) { + this.position = position; + return this; + } + + public Builder position(Supplier position) { + return position(position.get()); + } + + @Override + protected Position coordinates() { + return position; + } + + @Override + public Point doGet() { + return new Point(this); + } + + } + + Point(Builder builder) { + super(builder); + } + + @Override + public Iterator iterator() { + return coordinates().iterator(); + } + + + @Override + protected Point makeWithBoundingBox() { + Position pos = getFirst(coordinates(),null); + return new Point.Builder() + .from(this) + .position(pos) + .boundingBox(calculateBoundingBox(pos)) + .get(); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936281L; + protected SerializedForm(Point obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return doReadResolve(); + } + @Override + protected boolean handle(Builder builder, String key, Object val) { + if ("coordinates".equals(key)) { + builder.position = (Position) val; + return true; + } + return false; + } + @Override + protected Point.Builder builder() { + return GeoMakers.point(); + } + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/Polygon.java b/geo/src/main/java/com/ibm/common/geojson/Polygon.java new file mode 100644 index 0000000..f299dd3 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/Polygon.java @@ -0,0 +1,103 @@ +package com.ibm.common.geojson; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.ibm.common.geojson.BoundingBox.calculateBoundingBoxLineStrings; + +import java.io.ObjectStreamException; +import java.util.Iterator; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.ibm.common.geojson.Geometry.CoordinateGeometry; + +public final class Polygon + extends CoordinateGeometry> { + + public static final class Builder + extends CoordinateGeometry.Builder, Polygon, Builder> { + + private final ImmutableList.Builder strings = + ImmutableList.builder(); + + public Builder() { + type(Type.POLYGON); + } + + public Builder add(LineString line, LineString... lines) { + checkArgument(line.linearRing(), "Polygon coordinates MUST be Linear Rings"); + // TODO: Check hole requirement + this.strings.add(line); + if (lines != null) + for (LineString l : lines) + add(l); + return this; + } + + public Builder add(Supplier line) { + return add(line.get()); + } + + public Builder add(Iterable lines) { + this.strings.addAll(lines); + return this; + } + + public Polygon doGet() { + return new Polygon(this); + } + + @Override + protected Iterable coordinates() { + return strings.build(); + } + + } + + protected Polygon( + Builder builder) { + super(builder); + } + + @Override + public Iterator iterator() { + return coordinates().iterator(); + } + + @Override + protected Polygon makeWithBoundingBox() { + return new Polygon.Builder() + .from(this) + .add(this) + .boundingBox( + calculateBoundingBoxLineStrings(this)).get(); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936281L; + protected SerializedForm(Polygon obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return doReadResolve(); + } + @SuppressWarnings("unchecked") + @Override + protected boolean handle(Builder builder, String key, Object val) { + if ("coordinates".equals(key)) { + Iterable list = (Iterable) val; + builder.strings.addAll(list); + return true; + } + return false; + } + @Override + protected Polygon.Builder builder() { + return GeoMakers.polygon(); + } + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/Position.java b/geo/src/main/java/com/ibm/common/geojson/Position.java new file mode 100755 index 0000000..5d29670 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/Position.java @@ -0,0 +1,130 @@ +package com.ibm.common.geojson; + +import static com.google.common.primitives.Floats.concat; +import static com.google.common.primitives.Floats.toArray; + +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.Arrays; +import java.util.Iterator; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.google.common.primitives.Floats; + +public final class Position + implements Iterable, Serializable { + + public static final class Builder + implements Supplier { + + private float x,y,z; + private boolean hasz = false; + private ImmutableList.Builder rest = + ImmutableList.builder(); + + public Builder northing(float x) { + this.x = x; + return this; + } + + public Builder easting(float y) { + this.y = y; + return this; + } + + public Builder altitude(float z) { + this.hasz = true; + this.z = z; + return this; + } + + public Builder additional(float m) { + this.rest.add(m); + return this; + } + + public Position get() { + return new Position(this); + } + + } + + private final float x,y,z; + private final boolean hasz; + private final float[] rest; + + Position(Builder builder) { + this.x = builder.x; + this.y = builder.y; + this.z = builder.z; + this.hasz = builder.hasz; + this.rest = toArray(builder.rest.build()); + } + + public float northing() { + return x; + } + + public float easting() { + return y; + } + + public float altitude() { + return z; + } + + public boolean hasAltitude() { + return hasz; + } + + public int size() { + return values().length; + } + + private float[] values() { + return hasz? + concat(new float[] {x,y,z}, rest) : + concat(new float[] {x,y}, rest); + } + + public String toString() { + return Arrays.toString(values()); + } + + @Override + public Iterator iterator() { + return Floats.asList(values()).iterator(); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm implements Serializable { + private static final long serialVersionUID = -2060301713159936285L; + private float x,y,z; + private boolean hasz; + private float[] rest; + protected SerializedForm(Position obj) { + this.x = obj.x; + this.y = obj.y; + this.z = obj.z; + this.hasz = obj.hasz; + this.rest = obj.rest; + } + Object readResolve() throws ObjectStreamException { + Position.Builder position = + new Position.Builder() + .northing(x) + .easting(y) + .altitude(z); + position.hasz = this.hasz; + if (rest != null) + for (float f : rest) + position.additional(f); + return position.get(); + } + + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/as2/GeoAdapter.java b/geo/src/main/java/com/ibm/common/geojson/as2/GeoAdapter.java new file mode 100644 index 0000000..13ce9f6 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/as2/GeoAdapter.java @@ -0,0 +1,331 @@ +package com.ibm.common.geojson.as2; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.Map; + +import com.google.common.base.Enums; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.ibm.common.activitystreams.internal.Adapter; +import com.ibm.common.geojson.BoundingBox; +import com.ibm.common.geojson.CRS; +import com.ibm.common.geojson.Feature; +import com.ibm.common.geojson.FeatureCollection; +import com.ibm.common.geojson.GeoMakers; +import com.ibm.common.geojson.GeoObject; +import com.ibm.common.geojson.Geometry; +import com.ibm.common.geojson.Geometry.CoordinateGeometry; +import com.ibm.common.geojson.GeometryCollection; +import com.ibm.common.geojson.LineString; +import com.ibm.common.geojson.MultiLineString; +import com.ibm.common.geojson.MultiPoint; +import com.ibm.common.geojson.MultiPolygon; +import com.ibm.common.geojson.Point; +import com.ibm.common.geojson.Polygon; +import com.ibm.common.geojson.Position; + +@SuppressWarnings("rawtypes") +public class GeoAdapter + extends Adapter { + + @Override + public JsonElement serialize( + GeoObject geo, + Type type, + JsonSerializationContext context) { + + JsonObject obj = new JsonObject(); + obj.add("type", context.serialize(geo.type(),GeoObject.Type.class)); + switch(geo.type()) { + case POINT: + case MULTIPOINT: + case LINESTRING: + case MULTILINESTRING: + case MULTIPOLYGON: + case POLYGON: + CoordinateGeometry c = + (CoordinateGeometry) geo; + obj.add( + "coordinates", + context.serialize( + c.coordinates(), + Iterable.class)); + break; + case GEOMETRYCOLLECTION: + GeometryCollection gc = + (GeometryCollection)geo; + obj.add( + "geometries", + context.serialize( + gc.geometries(), + Iterable.class)); + break; + case FEATURE: + Feature feature = + (Feature) geo; + if (feature.id() != null) + obj.addProperty("id", feature.id()); + Geometry geometry = feature.geometry(); + Map properties = feature.properties(); + if (geometry != null) + obj.add( + "geometry", + context.serialize(feature.geometry())); + if (properties != null) + obj.add( + "properties", + context.serialize(properties)); + break; + case FEATURECOLLECTION: + FeatureCollection fc = + (FeatureCollection)geo; + obj.add( + "features", + context.serialize( + fc.features(), + Iterable.class)); + break; + default: + break; + + } + if (geo.boundingBox() != null) { + BoundingBox bb = geo.boundingBox(); + obj.add("bbox", context.serialize(bb, Iterable.class)); + } + if (geo.crs() != null) { + CRS crs = geo.crs(); + JsonObject crsobj = new JsonObject(); + crsobj.addProperty("name", crs.type()); + if (crs.size() > 0) + crsobj.add( + "properties", + context.serialize(crs.properties())); + obj.add("crs", crsobj); + } + return obj; + } + + private Position toPosition(float[] pos) { + Position.Builder b = + new Position.Builder(); + for (int n = 0; n < pos.length; n++) { + if (n == 0) b.northing(pos[n]); + else if (n == 1) b.easting(pos[n]); + else if (n == 2) b.altitude(pos[n]); + else b.additional(pos[n]); + } + return b.get(); + } + + @Override + public GeoObject deserialize( + JsonElement element, + Type type, + JsonDeserializationContext context) + throws JsonParseException { + GeoObject.Builder geo = null; + checkArgument(element.isJsonObject()); + JsonObject obj = element.getAsJsonObject(); + checkArgument(obj.has("type")); + GeoObject.Type et = + Enums.getIfPresent( + GeoObject.Type.class, + obj.get("type").getAsString().toUpperCase()).orNull(); + checkArgument(et != null); + switch(et) { + case FEATURE: + geo = GeoMakers.feature(); + break; + case FEATURECOLLECTION: + geo = GeoMakers.featureCollection(); + type = Feature.class; + break; + case GEOMETRYCOLLECTION: + geo = GeoMakers.geometryCollection(); + type = Geometry.class; + break; + case LINESTRING: + geo = GeoMakers.linestring(); + type = Position.class; + break; + case MULTILINESTRING: + geo = GeoMakers.multiLineString(); + type = LineString.class; + break; + case MULTIPOINT: + geo = GeoMakers.multipoint(); + type = Position.class; + break; + case MULTIPOLYGON: + geo = GeoMakers.multiPolygon(); + type = Polygon.class; + break; + case POINT: + geo = GeoMakers.point(); + type = null; + break; + case POLYGON: + geo = GeoMakers.polygon(); + type = LineString.class; + break; + } + + for (Map.Entry entry : obj.entrySet()) { + JsonElement el = entry.getValue(); + String name = entry.getKey(); + if ("crs".equals(name)) { + CRS.Builder cb = new CRS.Builder(); + JsonObject o = el.getAsJsonObject(); + if (o.has("type")) + cb.type(o.get("type").getAsString()); + if (o.has("properties")) { + JsonObject p = o.get("properties").getAsJsonObject(); + for (Map.Entry e : p.entrySet()) { + cb.set(e.getKey(), context.deserialize(e.getValue(), Object.class)); + } + } + geo.crs(cb.get()); + } else if ("properties".equals(name)) { + geo.set( + "properties", + context.deserialize( + el, + Map.class)); + } else if ("bbox".equals(name)) { + BoundingBox.Builder bb = + new BoundingBox.Builder(); + float[] points = context.deserialize(el, float[].class); + bb.add(points); + geo.boundingBox(bb.get()); + } else if ("features".equals(name)) { + Feature[] features = context.deserialize(el, Feature[].class); + FeatureCollection.Builder fcb = (FeatureCollection.Builder)geo; + for (Feature f : features) + fcb.add(f); + } else if ("coordinates".equals(name)) { + switch(et) { + case LINESTRING: { + LineString.Builder lsb = (LineString.Builder) geo; + float[][] positions = context.deserialize(el, float[][].class); + boolean ring = ring(positions); + if (ring) + lsb.linearRing(); + for (int n = 0; n < positions.length; n++) { + if (!ring || (ring && n < positions.length - 1)) + lsb.add(toPosition(positions[n])); + } + break; + } + case MULTIPOINT: { + MultiPoint.Builder lsb = (MultiPoint.Builder) geo; + float[][] positions = context.deserialize(el, float[][].class); + for (float[] pos : positions) + lsb.add(toPosition(pos)); + break; + } + case MULTILINESTRING: { + MultiLineString.Builder mlb = (MultiLineString.Builder) geo; + float[][][] positions = context.deserialize(el, float[][][].class); + for (float[][] lines : positions) { + LineString.Builder lsb = + GeoMakers.linestring(); + boolean ring = ring(lines); + if (ring) + lsb.linearRing(); + for (int n = 0; n < lines.length; n++) { + if (!ring || (ring && n < lines.length - 1)) + lsb.add(toPosition(lines[n])); + } + for (float[] pos : lines) + lsb.add(toPosition(pos)); + mlb.add(lsb); + } + break; + } + case POLYGON: { + Polygon.Builder mlb = (Polygon.Builder) geo; + float[][][] positions = context.deserialize(el, float[][][].class); + for (float[][] lines : positions) { + LineString.Builder lsb = + GeoMakers.linestring(); + for (float[] pos : lines) + lsb.add(toPosition(pos)); + mlb.add(lsb); + } + break; + } + case MULTIPOLYGON: { + MultiPolygon.Builder mpb = (MultiPolygon.Builder) geo; + float[][][][] positions = context.deserialize(el, float[][][][].class); + for (float[][][] polygons : positions) { + Polygon.Builder pb = GeoMakers.polygon(); + for (float[][] lines : polygons) { + LineString.Builder lsb = + GeoMakers.linestring(); + for (float[] pos : lines) + lsb.add(toPosition(pos)); + pb.add(lsb); + } + mpb.add(pb); + } + break; + } + case POINT: + Point.Builder pb = (Point.Builder)geo; + float[] position = context.deserialize(el, float[].class); + pb.position(toPosition(position)); + break; + default: + break; + } + } else if ("geometries".equals(name)) { + Geometry[] geos = context.deserialize(el, Geometry[].class); + GeometryCollection.Builder fcb = (GeometryCollection.Builder)geo; + for (Geometry g : geos) + fcb.add(g); + } else { + if (el.isJsonArray()) { + geo.set(name, context.deserialize(el, Object.class)); + } else if (el.isJsonObject()) { + geo.set(name, context.deserialize(el, GeoObject.class)); + } else if (el.isJsonPrimitive()) { + JsonPrimitive p = el.getAsJsonPrimitive(); + if (p.isBoolean()) + geo.set(name, p.getAsBoolean()); + else if (p.isNumber()) + geo.set(name, p.getAsNumber()); + else if (p.isString()) + geo.set(name, p.getAsString()); + } + } + } + + return geo.get(); + } + + private static boolean ring(float[][] line) { + return ring(first(line),last(line)); + } + + private static boolean ring(float[] p1, float[] p2) { + return Arrays.equals(p1,p2); + } + + private static float[] first(float[][] line) { + if (line.length == 0) return null; + return line[0]; + } + + private static float[] last(float[][] line) { + if (line.length == 0) return null; + return line[line.length - 1]; + } +} diff --git a/geo/src/main/java/com/ibm/common/geojson/as2/GeoModule.java b/geo/src/main/java/com/ibm/common/geojson/as2/GeoModule.java new file mode 100644 index 0000000..1625089 --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/as2/GeoModule.java @@ -0,0 +1,75 @@ +package com.ibm.common.geojson.as2; + +import com.ibm.common.activitystreams.IO; +import com.ibm.common.activitystreams.internal.EnumAdapter; +import com.ibm.common.activitystreams.internal.Model; +import com.ibm.common.activitystreams.internal.Schema; +import com.ibm.common.activitystreams.internal.Schema.Builder; +import com.ibm.common.activitystreams.util.Module; +import com.ibm.common.geojson.AS1Position; +import com.ibm.common.geojson.Address; +import com.ibm.common.geojson.GeoObject; +import com.ibm.common.geojson.Place; + +@SuppressWarnings("deprecation") +public final class GeoModule + implements Module { + + public static final Module instance = + new GeoModule(); + + public static final Model place = + Schema.object.template() + .type(Place.class, Place.Builder.class) + .as("geo", GeoObject.class) + .as("address", Address.class) + .as("position", AS1Position.class) + .get(); + + public static final Model address = + Schema.object.template() + .type(Address.class, Address.Builder.class) + .string( + "country", + "formatted", + "locality", + "postalCode", + "region", + "streetAddress") + .get(); + + public static final Model as1Position = + Schema.object.template() + .type(AS1Position.class, AS1Position.Builder.class) + .floatValue( + "latitude", + "longitude", + "altitude") + .get(); + + @Override + public void apply( + Builder builder) { + builder.map("place", place) + .map("address", address) + .map("position", as1Position); + } + + @Override + public void apply( + IO.Builder builder, + Schema schema) { + final GeoObjectAdapter base = + new GeoObjectAdapter(schema); + final GeoAdapter geo = + new GeoAdapter(); + builder.hierarchicalAdapter(Place.class, base) + .hierarchicalAdapter(Address.class, base) + .hierarchicalAdapter(AS1Position.class, base) + .hierarchicalAdapter(GeoObject.class, geo) + .hierarchicalAdapter( + GeoObject.Type.class, + new EnumAdapter(GeoObject.Type.class)); + } + +} diff --git a/geo/src/main/java/com/ibm/common/geojson/as2/GeoObjectAdapter.java b/geo/src/main/java/com/ibm/common/geojson/as2/GeoObjectAdapter.java new file mode 100644 index 0000000..9a976dd --- /dev/null +++ b/geo/src/main/java/com/ibm/common/geojson/as2/GeoObjectAdapter.java @@ -0,0 +1,64 @@ +package com.ibm.common.geojson.as2; + +import java.lang.reflect.Type; + +import com.google.common.collect.ImmutableSet; +import com.ibm.common.activitystreams.ASObject.AbstractBuilder; +import com.ibm.common.activitystreams.internal.ASObjectAdapter; +import com.ibm.common.activitystreams.internal.Model; +import com.ibm.common.activitystreams.internal.Schema; +import com.ibm.common.geojson.AS1Position; +import com.ibm.common.geojson.Address; +import com.ibm.common.geojson.GeoMakers; +import com.ibm.common.geojson.Place; + +@SuppressWarnings("deprecation") +public class GeoObjectAdapter + extends ASObjectAdapter { + + protected GeoObjectAdapter(Schema schema) { + super(schema); + } + + private static final ImmutableSet knownTypes = + ImmutableSet.of(Address.class,AS1Position.class,Place.class); + + @Override + protected boolean knowsType(Type type) { + if (super.knowsType(type)) + return true; + return knownTypes.contains(type); + } + + @Override + protected AbstractBuilder builderFor(Type type) { + if (super.knowsType(type)) + return super.builderFor(type); + if (type == Address.class) { + return GeoMakers.address(); + } else if (type == AS1Position.class) { + return GeoMakers.as1Position(); + } else if (type == Place.class) { + return GeoMakers.place(); + } else return null; + } + + @Override + protected Model modelFor(Type type) { + if (super.knowsType(type)) + return super.modelFor(type); + if (type == Address.class) { + return schema().forObjectClassOrType( + Address.Builder.class, + "address"); + } else if (type == AS1Position.class) { + return schema().forObjectClassOrType( + AS1Position.Builder.class, + "position"); + } else if (type == Place.class) { + return schema().forObjectClassOrType( + Place.Builder.class, + "place"); + } else return null; + } +} diff --git a/legacy/pom.xml b/legacy/pom.xml new file mode 100644 index 0000000..25e6f3f --- /dev/null +++ b/legacy/pom.xml @@ -0,0 +1,143 @@ + + 4.0.0 + + com.ibm.common + activitystreams + 0.0.1-SNAPSHOT + + activitystreams-legacy + Activity Streams 2.0 - Legacy objectTypes + + + Implementation of Legacy Activity Streams 1.0 objectTypes for + use with the Activity Streams 2.0 Reference Implementation + + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + UTF-8 + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + UTF-8 + UTF-8 + UTF-8 + -XDignore.symbol.file + public + + http://www.joda.org/joda-time/apidocs + http://docs.guava-libraries.googlecode.com/git-history/v16.0.1/javadoc/ + + + + + + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + maven-jar-plugin + 2.3.1 + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + + org.apache.felix + maven-bundle-plugin + 2.3.7 + true + + + bundle-manifest + process-classes + + manifest + + + + + + com.ibm.common.activitystreams.legacy.* + + com.ibm.common.activitystreams.*, + com.google.gson.*, + com.google.common.*, + org.joda.time.* + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.2.2 + + + assembly.xml + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.apache.felix + maven-bundle-plugin + [2.3.7,) + + manifest + + + + + + + + + + + + + + + + + com.ibm.common + activitystreams-core + 0.0.1-SNAPSHOT + + + \ No newline at end of file diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/AudioVisual.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/AudioVisual.java new file mode 100644 index 0000000..975c161 --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/AudioVisual.java @@ -0,0 +1,61 @@ +package com.ibm.common.activitystreams.legacy; + +import java.io.ObjectStreamException; + +import com.google.common.base.Supplier; +import com.ibm.common.activitystreams.ASObject; + +public final class AudioVisual + extends ASObject { + + public static final class Builder + extends ASObject.AbstractBuilder { + + public Builder embedCode(String embed) { + return set("embedCode", embed); + } + + public Builder stream(MediaLink mediaLink) { + return set("stream", mediaLink); + } + + public Builder stream(Supplier mediaLink) { + return stream(mediaLink.get()); + } + + public AudioVisual get() { + return new AudioVisual(this); + } + + } + + private AudioVisual(Builder builder) { + super(builder); + } + + public String embedCode() { + return getString("embedCode"); + } + + public MediaLink stream() { + return this.get("stream"); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(AudioVisual obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected AudioVisual.Builder builder() { + return new Builder(); + } + } +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Binary.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Binary.java new file mode 100644 index 0000000..433d268 --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Binary.java @@ -0,0 +1,161 @@ +package com.ibm.common.activitystreams.legacy; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectStreamException; +import java.io.OutputStream; +import java.io.StringReader; +import java.io.StringWriter; + +import com.google.common.hash.Hashing; +import com.google.common.hash.HashingInputStream; +import com.google.common.hash.HashingOutputStream; +import com.google.common.io.BaseEncoding; +import com.google.common.net.MediaType; +import com.ibm.common.activitystreams.ASObject; + +public final class Binary + extends ASObject { + + public static final class Builder + extends ASObject.AbstractBuilder { + + Builder() { + objectType("binary"); + } + + public Builder data( + InputStream in) + throws IOException { + return data(in,null); + } + + public Builder gzipData(InputStream in) throws IOException { + return data(in, Compression.GZipCompression); + } + + public Builder deflateData(InputStream in) throws IOException { + return data(in, Compression.DeflateCompression); + } + + public Builder data( + InputStream in, + Compression compression) + throws IOException { + StringWriter writer = new StringWriter(); + OutputStream out = + BaseEncoding.base64Url().encodingStream(writer); + if (compression != null) + out = compression.compressor(out); + HashingOutputStream hout = + new HashingOutputStream( + Hashing.md5(), out); + byte[] buf = new byte[1024]; + int r = -1; + long size = 0; + while((r = in.read(buf)) > -1) { + hout.write(buf,0,r); + size += r; + } + set("length", size); + if (compression != null) { + set("compression", compression.label()); + compression.finish(out); + } + hout.close(); + set("md5", hout.hash().toString()); + return set("data",writer.toString()); + } + + public Builder md5(String md5) { + return set("md5", md5); + } + + public Builder fileUrl(String fileUrl) { + return set("fileUrl", fileUrl); + } + + @Override + public Builder mediaType(MediaType mt) { + return set("mimeType", mt); + } + + public Binary get() { + return new Binary(this); + } + + } + + private Binary(Builder builder) { + super(builder); + } + + public String fileUrl() { + return getString("fileUrl"); + } + + public long length() { + return getLong("length"); + } + + public String compression() { + return getString("compression"); + } + + public boolean isGzip() { + return "gzip".equalsIgnoreCase(compression()); + } + + public boolean isDeflate() { + return "deflate".equalsIgnoreCase(compression()); + } + + public String md5() { + return getString("md5"); + } + + public String data() { + return getString("data"); + } + + public InputStream read() throws IOException { + Compression compression = + isGzip() ? Compression.GZipCompression : + isDeflate() ? Compression.DeflateCompression : + null; + return read(compression); + } + + public InputStream read(Compression compression) throws IOException { + StringReader reader = new StringReader(data()); + InputStream in = BaseEncoding.base64Url().decodingStream(reader); + if (compression != null) + in = compression.decompressor(in); + if (has("md5")) + in = new HashingInputStream(Hashing.md5(),in); + return in; + } + + @Override + public MediaType mediaType() { + return this.get("mimeType"); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(Binary obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected Binary.Builder builder() { + return new Builder(); + } + } +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Bookmark.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Bookmark.java new file mode 100644 index 0000000..8964392 --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Bookmark.java @@ -0,0 +1,52 @@ +package com.ibm.common.activitystreams.legacy; + +import java.io.ObjectStreamException; + +import com.ibm.common.activitystreams.ASObject; + +public class Bookmark + extends ASObject { + + public static final class Builder + extends ASObject.AbstractBuilder { + + Builder() { + objectType("bookmark"); + } + + public Builder targetUrl(String url) { + return set("targetUrl", url); + } + + public Bookmark get() { + return new Bookmark(this); + } + + } + + private Bookmark(Builder builder) { + super(builder); + } + + public String targetUrl() { + return getString("targetUrl"); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(Bookmark obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected Bookmark.Builder builder() { + return new Builder(); + } + } +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Compression.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Compression.java new file mode 100644 index 0000000..4105551 --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Compression.java @@ -0,0 +1,53 @@ +package com.ibm.common.activitystreams.legacy; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.DeflaterInputStream; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +public interface Compression { + String label(); + O compressor(OutputStream wrap) throws IOException; + I decompressor(InputStream in) throws IOException; + void finish(OutputStream out) throws IOException; + + public static final Compression GZipCompression = + new Compression() { + public String label() { + return "gzip"; + } + public GZIPOutputStream compressor(OutputStream wrap) throws IOException { + return new GZIPOutputStream(wrap); + } + public GZIPInputStream decompressor(InputStream in) throws IOException { + return new GZIPInputStream(in); + } + public void finish(OutputStream out) throws IOException { + if (out instanceof GZIPOutputStream) + ((GZIPOutputStream)out).finish(); + } + }; + + public static final Compression DeflateCompression = + new Compression() { + public String label() { + return "deflate"; + } + public DeflaterOutputStream compressor(OutputStream wrap) + throws IOException { + return new DeflaterOutputStream(wrap); + } + public DeflaterInputStream decompressor(InputStream in) + throws IOException { + return new DeflaterInputStream(in); + } + public void finish(OutputStream out) throws IOException { + if (out instanceof DeflaterOutputStream) + ((DeflaterOutputStream)out).finish(); + } + }; + +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Event.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Event.java new file mode 100644 index 0000000..01b0092 --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Event.java @@ -0,0 +1,118 @@ +package com.ibm.common.activitystreams.legacy; + +import java.io.ObjectStreamException; + +import com.google.common.base.Supplier; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.Collection; + +public class Event + extends ASObject { + + public static final class Builder + extends ASObject.AbstractBuilder { + + Builder() { + objectType("event"); + } + + public Builder attendedBy(Collection collection) { + return set("attendedBy", collection); + } + + public Builder attendedBy(Supplier collection) { + return attendedBy(collection.get()); + } + + public Builder attending(Collection collection) { + return set("attending", collection); + } + + public Builder attending(Supplier collection) { + return attending(collection.get()); + } + + public Builder invited(Collection collection) { + return set("invited", collection); + } + + public Builder invited(Supplier collection) { + return invited(collection.get()); + } + + public Builder maybeAttending(Collection collection) { + return set("maybeAttending", collection); + } + + public Builder maybeAttending(Supplier collection) { + return maybeAttending(collection.get()); + } + + public Builder notAttendedBy(Collection collection) { + return set("notAttendedBy", collection); + } + + public Builder notAttendedBy(Supplier collection) { + return notAttendedBy(collection.get()); + } + + public Builder notAttending(Collection collection) { + return set("notAttending", collection); + } + + public Builder notAttending(Supplier collection) { + return notAttending(collection.get()); + } + + public Event get() { + return new Event(this); + } + + } + + private Event(Builder builder) { + super(builder); + } + + public Collection attendedBy() { + return this.get("attendedBy"); + } + + public Collection attending() { + return this.get("attending"); + } + + public Collection invited() { + return this.get("invited"); + } + + public Collection maybeAttending() { + return this.get("maybeAttending"); + } + + public Collection notAttendedBy() { + return this.get("notAttendedBy"); + } + + public Collection notAttending() { + return this.get("notAttending"); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(Event obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected Event.Builder builder() { + return new Builder(); + } + } +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/File.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/File.java new file mode 100644 index 0000000..393c59a --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/File.java @@ -0,0 +1,63 @@ +package com.ibm.common.activitystreams.legacy; + +import java.io.ObjectStreamException; + +import com.google.common.net.MediaType; +import com.ibm.common.activitystreams.ASObject; + +public class File + extends ASObject { + + public static final class Builder + extends ASObject.AbstractBuilder { + + Builder() { + objectType("file"); + } + + public Builder fileUrl(String url) { + return set("fileUrl", url); + } + + @Override + public Builder mediaType(MediaType mt) { + return set("mimeType", mt); + } + + public File get() { + return new File(this); + } + + } + + private File(Builder builder) { + super(builder); + } + + @Override + public MediaType mediaType() { + return this.get("mimeType"); + } + + public String fileUrl() { + return getString("fileUrl"); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(File obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected File.Builder builder() { + return new Builder(); + } + } +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Issue.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Issue.java new file mode 100644 index 0000000..ec08769 --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Issue.java @@ -0,0 +1,63 @@ +package com.ibm.common.activitystreams.legacy; + +import java.io.ObjectStreamException; + +import com.google.common.collect.ImmutableList; +import com.ibm.common.activitystreams.ASObject; + +public class Issue + extends ASObject { + + public static final class Builder + extends ASObject.AbstractBuilder { + + Builder() { + objectType("issue"); + } + + public Builder types(String type, String... types) { + ImmutableList.Builder list = + ImmutableList.builder(); + if (type != null) + list.add(type); + if (types != null) + list.add(types); + return types(list.build()); + } + + public Builder types(Iterable types) { + return set("types", types); + } + + public Issue get() { + return new Issue(this); + } + + } + + private Issue(Builder builder) { + super(builder); + } + + public Iterable types() { + return this.>get("types"); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(Issue obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected Issue.Builder builder() { + return new Builder(); + } + } +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/LegacyMakers.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/LegacyMakers.java new file mode 100644 index 0000000..4eb9dae --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/LegacyMakers.java @@ -0,0 +1,158 @@ +package com.ibm.common.activitystreams.legacy; + +import com.ibm.common.activitystreams.ASObject; +import static com.ibm.common.activitystreams.Makers.object; + +public final class LegacyMakers { + + private LegacyMakers() {} + + public static Binary.Builder binary() { + return new Binary.Builder(); + } + + public static Task.Builder task() { + return new Task.Builder(); + } + + public static WithImage.Builder withImage() { + return new WithImage.Builder(); + } + + public static Question.Builder question() { + return new Question.Builder(); + } + + public static WithImage.Builder product() { + return new WithImage.Builder().objectType("product"); + } + + public static WithImage.Builder image() { + return new WithImage.Builder().objectType("image"); + } + + public static File.Builder file() { + return new File.Builder(); + } + + public static Bookmark.Builder bookmark() { + return new Bookmark.Builder(); + } + + public static Bookmark bookmark(String targetUrl) { + return bookmark().targetUrl(targetUrl).get(); + } + + public static Membership.Builder role() { + return new Membership.Builder().objectType("role"); + } + + public static Membership.Builder group() { + return new Membership.Builder().objectType("group"); + } + + public static Issue.Builder issue() { + return new Issue.Builder(); + } + + public static Membership.Builder membership() { + return new Membership.Builder(); + } + + public static Event.Builder event() { + return new Event.Builder(); + } + + public static MediaLink.Builder mediaLink() { + return new MediaLink.Builder(); + } + + public static MediaLink mediaLink(String url) { + return mediaLink().url(url).get(); + } + + public static ASObject.Builder permission() { + return object("permission"); + } + + public static AudioVisual.Builder video() { + return new AudioVisual.Builder().objectType("video"); + } + + public static AudioVisual.Builder audioVisual() { + return new AudioVisual.Builder(); + } + + public static AudioVisual.Builder audio() { + return new AudioVisual.Builder().objectType("audio"); + } + + public static ASObject.Builder alert() { + return object("alert"); + } + + public static ASObject.Builder application() { + return object("application"); + } + + public static ASObject.Builder article() { + return object("article"); + } + + public static ASObject.Builder badge() { + return object("badge"); + } + + public static ASObject.Builder comment() { + return object("comment"); + } + + public static ASObject.Builder device() { + return object("device"); + } + + public static ASObject.Builder game() { + return object("game"); + } + + public static ASObject.Builder job() { + return object("job"); + } + + public static ASObject.Builder note() { + return object("note"); + } + + public static ASObject.Builder offer() { + return object("offer"); + } + + public static ASObject.Builder organization() { + return object("organization"); + } + + public static ASObject.Builder page() { + return object("page"); + } + + public static ASObject.Builder person() { + return object("person"); + } + + public static ASObject.Builder process() { + return object("process"); + } + + public static ASObject.Builder review() { + return object("review"); + } + + public static ASObject.Builder service() { + return object("service"); + } + + public static Membership.Builder team() { + return new Membership.Builder().objectType("team"); + } + +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/LegacyModule.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/LegacyModule.java new file mode 100644 index 0000000..a47a7b2 --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/LegacyModule.java @@ -0,0 +1,136 @@ +package com.ibm.common.activitystreams.legacy; + +import java.lang.reflect.Type; + +import com.google.common.net.MediaType; +import com.ibm.common.activitystreams.Collection; +import com.ibm.common.activitystreams.IO; +import com.ibm.common.activitystreams.internal.Model; +import com.ibm.common.activitystreams.internal.Schema; +import com.ibm.common.activitystreams.internal.Schema.Builder; +import com.ibm.common.activitystreams.util.Module; + +public class LegacyModule + implements Module { + + public static final Module instance = new LegacyModule(); + + public static final Model binary = + Schema.object.template() + .type(Binary.class, Binary.Builder.class) + .string("compression", "md5", "data", "fileUrl") + .as("mimeType", MediaType.class) + .integer("length") + .get(); + + public static final Model audioVisual = + Schema.object.template() + .type(AudioVisual.class, AudioVisual.Builder.class) + .string("embedCode") + .as("stream", MediaLink.class) + .get(); + + public static final Model withImage = + Schema.object.template() + .type(WithImage.class, WithImage.Builder.class) + .as("fullImage", MediaLink.class) + .get(); + + public static final Model bookmark = + Schema.object.template() + .type(Bookmark.class, Bookmark.Builder.class) + .string("targetUrl") + .get(); + + public static final Model event = + Schema.object.template() + .type(Event.class, Event.Builder.class) + .as("attendedBy", Collection.class) + .as("attending", Collection.class) + .as("invited", Collection.class) + .as("maybeAttending", Collection.class) + .as("notAttendedBy", Collection.class) + .as("notAttending", Collection.class) + .get(); + + public static final Model membership = + Schema.object.template() + .type(Membership.class, Membership.Builder.class) + .as("members", Collection.class) + .get(); + + public static final Model file = + Schema.object.template() + .type(File.class, File.Builder.class) + .string("fileUrl") + .as("mimeType", MediaType.class) + .get(); + + public static final Model issue = + Schema.object.template() + .type(Issue.class, Issue.Builder.class) + .string("types") + .get(); + + public static final Model question = + Schema.object.template() + .type(Question.class, Question.Builder.class) + .linkValue("options") + .get(); + + public static final Model task = + Schema.object.template() + .type(Task.class, Task.Builder.class) + .object("actor", "object") + .dateTime("by") + .as("required", Boolean.class) + .string("verb") + .as("prerequisites", Task.class) + .as("supersedes", Task.class) + .get(); + + public void apply(Builder builder) { + builder.map("alert", Schema.object) + .map("binary", binary) + .map("application", Schema.object) + .map("article", Schema.object) + .map("audio", audioVisual) + .map("badge", Schema.object) + .map("bookmark",bookmark) + .map("comment", Schema.object) + .map("device", Schema.object) + .map("event", event) + .map("file", file) + .map("game", Schema.object) + .map("group", membership) + .map("image", withImage) + .map("issue", issue) + .map("job", Schema.object) + .map("note", Schema.object) + .map("offer", Schema.object) + .map("organization", Schema.object) + .map("page", Schema.object) + .map("person", Schema.object) + .map("process", Schema.object) + .map("product", Schema.object) + .map("question", question) + .map("review", Schema.object) + .map("role", membership) + .map("service", Schema.object) + .map("team", membership) + .map("video", audioVisual) + ; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void apply( + IO.Builder builder, + Schema schema) { + LegacyObjectAdapter base = + new LegacyObjectAdapter(schema); + builder.adapter(MediaLink.class, new MediaLinkAdapter()); + for (Type type : LegacyObjectAdapter.knownTypes) + builder.hierarchicalAdapter((Class)type, base); + } + +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/LegacyObjectAdapter.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/LegacyObjectAdapter.java new file mode 100644 index 0000000..302cf12 --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/LegacyObjectAdapter.java @@ -0,0 +1,98 @@ +package com.ibm.common.activitystreams.legacy; + +import java.lang.reflect.Type; + +import com.google.common.collect.ImmutableSet; +import com.ibm.common.activitystreams.ASObject.AbstractBuilder; +import com.ibm.common.activitystreams.internal.ASObjectAdapter; +import com.ibm.common.activitystreams.internal.Model; +import com.ibm.common.activitystreams.internal.Schema; +import static com.ibm.common.activitystreams.Makers.object; + +public class LegacyObjectAdapter + extends ASObjectAdapter { + + protected LegacyObjectAdapter(Schema schema) { + super(schema); + } + + @SuppressWarnings("unchecked") + public static final ImmutableSet knownTypes = + ImmutableSet.of( + Binary.class, + AudioVisual.class, + Bookmark.class, + Event.class, + File.class, + Issue.class, + Membership.class, + Question.class, + Task.class, + WithImage.class); + + @Override + protected boolean knowsType(Type type) { + if (super.knowsType(type)) + return true; + return knownTypes.contains(type); + } + + @Override + protected AbstractBuilder builderFor(Type type) { + if (super.knowsType(type)) + return super.builderFor(type); + if (knowsType(type)) { + if (type == AudioVisual.class) + return LegacyMakers.audioVisual(); + else if (type == Binary.class) + return LegacyMakers.binary(); + else if (type == Bookmark.class) + return LegacyMakers.bookmark(); + else if (type == Event.class) + return LegacyMakers.event(); + else if (type == File.class) + return LegacyMakers.file(); + else if (type == Issue.class) + return LegacyMakers.issue(); + else if (type == Membership.class) + return LegacyMakers.membership(); + else if (type == Question.class) + return LegacyMakers.question(); + else if (type == Task.class) + return LegacyMakers.task(); + else if (type == WithImage.class) + return LegacyMakers.withImage(); + else return object(); + } else return null; + } + + @Override + protected Model modelFor(Type type) { + if (super.knowsType(type)) + return super.modelFor(type); + if (knowsType(type)) { + if (type == AudioVisual.class) + return LegacyModule.audioVisual; + else if (type == Bookmark.class) + return LegacyModule.bookmark; + else if (type == Binary.class) + return LegacyModule.binary; + else if (type == Event.class) + return LegacyModule.event; + else if (type == File.class) + return LegacyModule.file; + else if (type == Issue.class) + return LegacyModule.issue; + else if (type == Membership.class) + return LegacyModule.membership; + else if (type == Question.class) + return LegacyModule.question; + else if (type == Task.class) + return LegacyModule.task; + else if (type == WithImage.class) + return LegacyModule.withImage; + else return Schema.object; + } else return null; + } + +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/MediaLink.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/MediaLink.java new file mode 100644 index 0000000..6391b68 --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/MediaLink.java @@ -0,0 +1,107 @@ +package com.ibm.common.activitystreams.legacy; + +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.Iterator; +import java.util.Map; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.ibm.common.activitystreams.util.AbstractWritable; + +public final class MediaLink + extends AbstractWritable + implements Iterable, Serializable { + + public static final class Builder + extends AbstractWritableBuilder + implements Supplier { + + private Map map = + Maps.newHashMap(); + + public Builder duration(int duration) { + map.put("duration", duration); + return this; + } + + public Builder height(int height) { + map.put("height", height); + return this; + } + + public Builder width(int width) { + map.put("width", width); + return this; + } + + public Builder url(String url) { + map.put("url", url); + return this; + } + + public Builder set(String key, Object val) { + map.put(key,val); + return this; + } + + public MediaLink get() { + return new MediaLink(this); + } + + } + + private final ImmutableMap map; + + private MediaLink(Builder builder) { + super(builder); + this.map = ImmutableMap.copyOf(builder.map); + } + + public String url() { + return (String)map.get("url"); + } + + public int duration() { + return (Integer)map.get("duration"); + } + + public int height() { + return (Integer)map.get("height"); + } + + public int width() { + return (Integer)map.get("width"); + } + + @SuppressWarnings("unchecked") + public T get(String key) { + return (T)map.get(key); + } + + public Iterator iterator() { + return map.keySet().iterator(); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + implements Serializable { + private static final long serialVersionUID = -2060301713159936285L; + + private ImmutableMap map; + + protected SerializedForm(MediaLink obj) { + this.map = obj.map; + } + Object readResolve() throws ObjectStreamException { + MediaLink.Builder builder = + new Builder(); + builder.map.putAll(map); + return builder.get(); + } + } +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/MediaLinkAdapter.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/MediaLinkAdapter.java new file mode 100644 index 0000000..8e9ad47 --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/MediaLinkAdapter.java @@ -0,0 +1,64 @@ +package com.ibm.common.activitystreams.legacy; + +import java.lang.reflect.Type; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.ibm.common.activitystreams.ASObject; +import static com.ibm.common.activitystreams.internal.ASObjectAdapter.primConverter; +import com.ibm.common.activitystreams.internal.Adapter; + +public final class MediaLinkAdapter + extends Adapter { + + public JsonElement serialize( + MediaLink src, + Type typeOfSrc, + JsonSerializationContext context) { + JsonObject el = new JsonObject(); + for (String key : src) { + Object val = src.get(key); + if (val != null) + el.add(key, context.serialize(val, val.getClass())); + } + return el; + } + + public MediaLink deserialize( + JsonElement json, + Type typeOfT, + JsonDeserializationContext context) + throws JsonParseException { + + checkArgument(json.isJsonObject()); + JsonObject obj = (JsonObject) json; + MediaLink.Builder builder = + LegacyMakers.mediaLink(); + for (Map.Entry entry : obj.entrySet()) { + String name = entry.getKey(); + JsonElement val = entry.getValue(); + if (val.isJsonPrimitive()) + builder.set( + name, + primConverter.convert(val.getAsJsonPrimitive())); + else if (val.isJsonArray()) + builder.set( + name, + context.deserialize(val, Iterable.class)); + else if (val.isJsonObject()) + builder.set( + name, + context.deserialize( + val, + ASObject.class)); + } + return builder.get(); + } + +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Membership.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Membership.java new file mode 100644 index 0000000..57cc804 --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Membership.java @@ -0,0 +1,53 @@ +package com.ibm.common.activitystreams.legacy; + +import java.io.ObjectStreamException; + +import com.google.common.base.Supplier; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.Collection; + +public class Membership extends ASObject { + + public static final class Builder + extends ASObject.AbstractBuilder { + + public Builder members(Collection collection) { + return set("members", collection); + } + + public Builder members(Supplier collection) { + return members(collection.get()); + } + + public Membership get() { + return new Membership(this); + } + + } + + private Membership(Builder builder) { + super(builder); + } + + public Collection members() { + return this.get("members"); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(Membership obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected Membership.Builder builder() { + return new Builder(); + } + } +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Question.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Question.java new file mode 100644 index 0000000..81d0c9d --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Question.java @@ -0,0 +1,76 @@ +package com.ibm.common.activitystreams.legacy; + +import java.io.ObjectStreamException; + +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.LinkValue; + +public class Question extends ASObject { + + public static final class Builder + extends ASObject.AbstractBuilder { + + Builder() { + objectType("question"); + } + + public Builder option(String url, String... urls) { + if (url != null) + link("options", url); + if (urls != null) + for (String u : urls) + link("options", u); + return this; + } + + public Builder option(LinkValue link, LinkValue... links) { + if (link != null) + link("options", link); + if (links != null) + for (LinkValue l : links) + link("options", l); + return this; + } + + public Builder option(Supplier link) { + return option(link.get()); + } + + public Question get() { + return new Question(this); + } + + } + + public Question(Builder builder) { + super(builder); + } + + public Iterable options() { + return links("options"); + } + + public Iterable options(Predicate filter) { + return links("options", filter); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(Question obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected Question.Builder builder() { + return new Builder(); + } + } +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Task.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Task.java new file mode 100644 index 0000000..9bbcd5f --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/Task.java @@ -0,0 +1,175 @@ +package com.ibm.common.activitystreams.legacy; + +import static com.google.common.collect.Iterables.transform; + +import java.io.ObjectStreamException; + +import org.joda.time.DateTime; +import org.joda.time.ReadableDuration; +import org.joda.time.ReadablePeriod; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.ibm.common.activitystreams.ASObject; +import com.ibm.common.activitystreams.LinkValue; + +public class Task + extends ASObject { + + public static final class Builder + extends ASObject.AbstractBuilder { + + Builder() { + objectType("task"); + } + + public Builder actor(ASObject actor) { + return set("actor", actor); + } + + public Builder actor(Supplier actor) { + return actor(actor.get()); + } + + public Builder object(ASObject object) { + return set("object", object); + } + + public Builder object(Supplier object) { + return object(object.get()); + } + + public Builder prerequisites(Task task, Task... tasks) { + if (task != null) + link("prerequisites",task); + if (tasks != null) + for (Task t : tasks) + link("prerequisites", t); + return this; + } + + public Builder prerequisites(Supplier task) { + return prerequisites(task.get()); + } + + public Builder supersedes(Task task, Task... tasks) { + if (task != null) + link("supersedes",task); + if (tasks != null) + for (Task t : tasks) + link("supersedes", t); + return this; + } + + public Builder supersedes(Supplier task) { + return supersedes(task.get()); + } + + public Builder required(boolean on) { + return set("required", on); + } + + public Builder required() { + return required(true); + } + + public Builder verb(String verb) { + return set("verb", verb); + } + + public Builder by(DateTime dt) { + return this._dt("by", dt); + } + + public Builder byNow() { + return this._dtNow("by"); + } + + public Builder byFromNow(ReadableDuration duration) { + return this._dtFromNow("by", duration); + } + + public Builder byFromNow(ReadablePeriod period) { + return this._dtFromNow("by", period); + } + + public Builder by(DateTime dt, ReadableDuration duration) { + return this._dtFrom("by", dt, duration); + } + + public Builder by(DateTime dt, ReadablePeriod period) { + return this._dtFrom("by", dt, period); + } + + public Task get() { + return new Task(this); + } + + } + + private Task(Builder builder) { + super(builder); + } + + public A actor() { + return this.get("actor"); + } + + public A object() { + return this.get("object"); + } + + public DateTime by() { + return getDateTime("by"); + } + + public String verb() { + return getString("verb"); + } + + public boolean required() { + return getBoolean("required"); + } + + public Iterable supersedes() { + return transform(links("supersedes",filter), transformer); + } + + public Iterable prerequisites() { + return transform(links("prerequisites",filter), transformer); + } + + private static final Predicate filter = + new Predicate() { + public boolean apply(LinkValue input) { + return input instanceof Task; + } + }; + + private static final Function transformer = + new Function() { + public Task apply(LinkValue input) { + return (Task)input; + } + + }; + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(Task obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected Task.Builder builder() { + return new Builder(); + } + } +} diff --git a/legacy/src/main/java/com/ibm/common/activitystreams/legacy/WithImage.java b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/WithImage.java new file mode 100644 index 0000000..8dee624 --- /dev/null +++ b/legacy/src/main/java/com/ibm/common/activitystreams/legacy/WithImage.java @@ -0,0 +1,52 @@ +package com.ibm.common.activitystreams.legacy; + +import java.io.ObjectStreamException; + +import com.google.common.base.Supplier; +import com.ibm.common.activitystreams.ASObject; + +public class WithImage extends ASObject { + + public static final class Builder + extends ASObject.AbstractBuilder { + + public Builder fullImage(MediaLink link) { + return set("fullImage", link); + } + + public Builder fullImage(Supplier link) { + return fullImage(link.get()); + } + + public WithImage get() { + return new WithImage(this); + } + + } + + private WithImage(Builder builder) { + super(builder); + } + + public MediaLink fullImage() { + return this.get("fullImage"); + } + + Object writeReplace() throws java.io.ObjectStreamException { + return new SerializedForm(this); + } + + private static class SerializedForm + extends AbstractSerializedForm { + private static final long serialVersionUID = -2060301713159936285L; + protected SerializedForm(WithImage obj) { + super(obj); + } + Object readResolve() throws ObjectStreamException { + return super.doReadResolve(); + } + protected WithImage.Builder builder() { + return new Builder(); + } + } +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..0fb4ffe --- /dev/null +++ b/pom.xml @@ -0,0 +1,78 @@ + + 4.0.0 + com.ibm.common + activitystreams + 0.0.1-SNAPSHOT + pom + Activity Streams 2.0 Java Reference Implementation + + + + jasnell + James M Snell + jasnell@us.ibm.com + IBM + http://www.ibm.com + + owner + developer + + -8 + + + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + IBM + http://www.ibm.com + + + scm:http://github.com/opensocial/activitystreams + http://github.com/opensocial/activitystreams + + + + UTF-8 + + + + core + actions + geo + assembly + legacy + + + + + com.google.code.gson + gson + 2.2.4 + + + com.google.guava + guava + 16.0.1 + + + joda-time + joda-time + 2.3 + + + + junit + junit + 4.11 + test + + + +