streams-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sblack...@apache.org
Subject [1/6] incubator-streams git commit: streams-verbs and streams-filters
Date Tue, 31 Mar 2015 23:19:09 GMT
Repository: incubator-streams
Updated Branches:
  refs/heads/master b99b54656 -> a76e0ecb8


streams-verbs and streams-filters


Project: http://git-wip-us.apache.org/repos/asf/incubator-streams/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-streams/commit/0b2ba6cb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-streams/tree/0b2ba6cb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-streams/diff/0b2ba6cb

Branch: refs/heads/master
Commit: 0b2ba6cb6f145605b48a1275299d797cb6375163
Parents: b99b546
Author: sblackmon <sblackmon@w2odigital.com>
Authored: Tue Dec 16 10:39:11 2014 -0600
Committer: Steve Blackmon (@steveblackmon) <sblackmon@apache.org>
Committed: Sun Mar 29 15:35:46 2015 -0500

----------------------------------------------------------------------
 pom.xml                                         |   1 +
 streams-components/pom.xml                      |   1 +
 streams-components/streams-filters/pom.xml      |  74 +++++++
 .../streams/filters/VerbDefinitionFilter.java   |  96 ++++++++++
 .../filters/test/VerbDefinitionFilterTest.java  | 192 +++++++++++++++++++
 .../src/test/resources/actor.json               |   9 +
 .../src/test/resources/follow.json              |  12 ++
 .../src/test/resources/object.json              |   9 +
 .../src/test/resources/post.json                |  12 ++
 .../src/test/resources/provider.json            |   9 +
 .../src/test/resources/targetrequired.json      |  12 ++
 streams-verbs/README.md                         |  16 ++
 streams-verbs/pom.xml                           | 148 ++++++++++++++
 .../verbs/ObjectCombinationGenericOrdering.java |  55 ++++++
 .../ObjectCombinationSpecificOrdering.java      |  63 ++++++
 .../streams/verbs/VerbDefinitionResolver.java   | 117 +++++++++++
 .../verbs/VerbDefinitionTemplateUtil.java       |  44 +++++
 .../src/main/jsonschema/verb-definition.json    |  94 +++++++++
 streams-verbs/src/main/resources/delete.json    |  16 ++
 streams-verbs/src/main/resources/follow.json    |  16 ++
 streams-verbs/src/main/resources/post.json      |  16 ++
 streams-verbs/src/main/resources/share.json     |  16 ++
 .../ObjectCombinationGenericOrderingTest.java   |  22 +++
 .../ObjectCombinationSpecificOrderingTest.java  |  31 +++
 .../verbs/VerbDefinitionResolverTest.java       |  90 +++++++++
 .../verbs/VerbDefinitionTemplateTest.java       |  67 +++++++
 .../streams/verbs/VerbDefinitionTest.java       |  44 +++++
 streams-verbs/src/test/resources/activities.txt |   4 +
 streams-verbs/src/test/resources/actor.json     |   9 +
 streams-verbs/src/test/resources/do.json        |  14 ++
 streams-verbs/src/test/resources/follow.json    |  12 ++
 streams-verbs/src/test/resources/nofields.json  |  15 ++
 streams-verbs/src/test/resources/object.json    |   9 +
 streams-verbs/src/test/resources/post.json      |  15 ++
 streams-verbs/src/test/resources/provider.json  |   9 +
 35 files changed, 1369 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index e9086f2..3512770 100644
--- a/pom.xml
+++ b/pom.xml
@@ -232,6 +232,7 @@
         <module>streams-pojo-extensions</module>
         <module>streams-runtimes</module>
         <module>streams-util</module>
+        <module>streams-verbs</module>
     </modules>
 
     <packaging>pom</packaging>

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-components/pom.xml
----------------------------------------------------------------------
diff --git a/streams-components/pom.xml b/streams-components/pom.xml
index 539795a..e22ab40 100644
--- a/streams-components/pom.xml
+++ b/streams-components/pom.xml
@@ -36,6 +36,7 @@
 
     <modules>
         <module>streams-converters</module>
+ 	<module>streams-filters</module>
         <module>streams-http</module>
     </modules>
 

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-components/streams-filters/pom.xml
----------------------------------------------------------------------
diff --git a/streams-components/streams-filters/pom.xml b/streams-components/streams-filters/pom.xml
new file mode 100644
index 0000000..47f5d6d
--- /dev/null
+++ b/streams-components/streams-filters/pom.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.streams</groupId>
+        <artifactId>streams-components</artifactId>
+        <version>0.2-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>streams-filters</artifactId>
+
+    <name>streams-filters</name>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.streams</groupId>
+            <artifactId>streams-config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.typesafe</groupId>
+            <artifactId>config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streams</groupId>
+            <artifactId>streams-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streams</groupId>
+            <artifactId>streams-pojo</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streams</groupId>
+            <artifactId>streams-verbs</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <sourceDirectory>src/main/java</sourceDirectory>
+        <testSourceDirectory>src/test/java</testSourceDirectory>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+        </resources>
+        <testResources>
+            <testResource>
+                <directory>src/test/resources</directory>
+            </testResource>
+        </testResources>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-components/streams-filters/src/main/java/org/apache/streams/filters/VerbDefinitionFilter.java
----------------------------------------------------------------------
diff --git a/streams-components/streams-filters/src/main/java/org/apache/streams/filters/VerbDefinitionFilter.java b/streams-components/streams-filters/src/main/java/org/apache/streams/filters/VerbDefinitionFilter.java
new file mode 100644
index 0000000..3bd0cc4
--- /dev/null
+++ b/streams-components/streams-filters/src/main/java/org/apache/streams/filters/VerbDefinitionFilter.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.streams.filters;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Lists;
+import org.apache.streams.jackson.StreamsJacksonMapper;
+import org.apache.streams.core.StreamsDatum;
+import org.apache.streams.core.StreamsProcessor;
+import org.apache.streams.pojo.json.Activity;
+import org.apache.streams.pojo.json.ActivityObject;
+import org.apache.streams.verbs.ObjectCombination;
+import org.apache.streams.verbs.VerbDefinition;
+import org.apache.streams.verbs.VerbDefinitionResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+
+public class VerbDefinitionFilter implements StreamsProcessor {
+
+    private static final String STREAMS_ID = "LinkResolverProcessor";
+    private static final Logger LOGGER = LoggerFactory.getLogger(VerbDefinitionFilter.class);
+
+    protected Set<VerbDefinition> verbDefinitionSet;
+    protected VerbDefinitionResolver resolver;
+
+    public VerbDefinitionFilter() {
+        // get with reflection
+    }
+
+    public VerbDefinitionFilter(Set<VerbDefinition> verbDefinitionSet) {
+        this();
+        this.verbDefinitionSet = verbDefinitionSet;
+    }
+
+    @Override
+    public List<StreamsDatum> process(StreamsDatum entry) {
+
+        List<StreamsDatum> result = Lists.newArrayList();
+
+        LOGGER.debug("{} filtering {}", STREAMS_ID, entry.getDocument().getClass());
+
+        Activity activity;
+
+        Preconditions.checkArgument(entry.getDocument() instanceof Activity);
+
+        activity = (Activity) entry.getDocument();
+
+        boolean match = false;
+        for( VerbDefinition verbDefinition : verbDefinitionSet)
+            if( verbDefinition.getValue() != null &&
+                verbDefinition.getValue().equals(activity.getVerb()))
+                for (ObjectCombination objectCombination : verbDefinition.getObjects())
+                    if (VerbDefinitionResolver.filter(activity, objectCombination) == true)
+                        match = true;
+
+        if( match == true )
+            result.add(entry);
+
+        return result;
+    }
+
+    @Override
+    public void prepare(Object o) {
+        if( verbDefinitionSet != null)
+            resolver = new VerbDefinitionResolver(verbDefinitionSet);
+        else resolver = new VerbDefinitionResolver();
+        Preconditions.checkNotNull(resolver);
+    }
+
+    @Override
+    public void cleanUp() {
+        // noOp
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-components/streams-filters/src/test/java/org/apache/streams/filters/test/VerbDefinitionFilterTest.java
----------------------------------------------------------------------
diff --git a/streams-components/streams-filters/src/test/java/org/apache/streams/filters/test/VerbDefinitionFilterTest.java b/streams-components/streams-filters/src/test/java/org/apache/streams/filters/test/VerbDefinitionFilterTest.java
new file mode 100644
index 0000000..235fd7d
--- /dev/null
+++ b/streams-components/streams-filters/src/test/java/org/apache/streams/filters/test/VerbDefinitionFilterTest.java
@@ -0,0 +1,192 @@
+package org.apache.streams.filters.test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.Sets;
+import org.apache.streams.core.StreamsDatum;
+import org.apache.streams.filters.VerbDefinitionFilter;
+import org.apache.streams.jackson.StreamsJacksonMapper;
+import org.apache.streams.pojo.json.Activity;
+import org.apache.streams.verbs.VerbDefinition;
+import org.apache.streams.verbs.VerbDefinitionResolver;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.List;
+
+/**
+ * Tests for {$link: org.apache.streams.verbs.VerbDefinitionResolver}
+ */
+public class VerbDefinitionFilterTest {
+
+    ObjectMapper mapper = new StreamsJacksonMapper();
+
+    /**
+     * Test verb match filter alone
+     */
+    @Test
+    public void testVerbMatchFilter() throws Exception {
+        VerbDefinition definition = mapper.readValue(VerbDefinitionFilterTest.class.getResourceAsStream("/post.json"), VerbDefinition.class);
+        VerbDefinitionFilter filter = new VerbDefinitionFilter(Sets.newHashSet(definition));
+        filter.prepare(null);
+        StreamsDatum datum1 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"notpost\"}\n", Activity.class));
+        List<StreamsDatum> result1 = filter.process(datum1);
+        assert result1.size() == 0;
+        StreamsDatum datum2 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\"}\n", Activity.class));
+        List<StreamsDatum> result2 = filter.process(datum2);
+        assert result2.size() == 1;
+    }
+    /**
+     * Test provider filter, if provider has wrong type it should not pass
+     */
+    @Test
+    public void testProviderFilter() throws Exception {
+        VerbDefinition definition = mapper.readValue(VerbDefinitionFilterTest.class.getResourceAsStream("/provider.json"), VerbDefinition.class);
+        VerbDefinitionFilter filter = new VerbDefinitionFilter(Sets.newHashSet(definition));
+        filter.prepare(null);
+        StreamsDatum datum1 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"provider\":{\"id\":\"providerId\",\"objectType\":\"product\"}}\n", Activity.class));
+        List<StreamsDatum> result1 = filter.process(datum1);
+        assert result1.size() == 0;
+        StreamsDatum datum2 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"provider\":{\"id\":\"providerId\",\"objectType\":\"application\"}}\n\n", Activity.class));
+        List<StreamsDatum> result2 = filter.process(datum2);
+        assert result2.size() == 1;
+    }
+
+    /**
+     * Test actor filter, if actor isn't present it should not pass
+     */
+    @Test
+    public void testActorFilter() throws Exception {
+        VerbDefinition definition = mapper.readValue(VerbDefinitionFilterTest.class.getResourceAsStream("/actor.json"), VerbDefinition.class);
+        VerbDefinitionFilter filter = new VerbDefinitionFilter(Sets.newHashSet(definition));
+        filter.prepare(null);
+        StreamsDatum datum1 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"actor\":{\"id\":\"actorId\",\"objectType\":\"page\"}}\n", Activity.class));
+        List<StreamsDatum> result1 = filter.process(datum1);
+        assert result1.size() == 0;
+        StreamsDatum datum2 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"actor\":{\"id\":\"actorId\",\"objectType\":\"person\"}}}\n\n", Activity.class));
+        List<StreamsDatum> result2 = filter.process(datum2);
+        assert result2.size() == 1;
+
+    }
+
+    /**
+     * Test object filter, if object doesn't have a type it should not pass
+     */
+    @Test
+    public void testObjectFilter() throws Exception {
+        VerbDefinition definition = mapper.readValue(VerbDefinitionFilterTest.class.getResourceAsStream("/object.json"), VerbDefinition.class);
+        VerbDefinitionFilter filter = new VerbDefinitionFilter(Sets.newHashSet(definition));
+        filter.prepare(null);
+        StreamsDatum datum1 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"object\":{\"id\":\"objectId\"}}\n", Activity.class));
+        List<StreamsDatum> result1 = filter.process(datum1);
+        assert result1.size() == 0;
+        StreamsDatum datum2 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"object\":{\"id\":\"objectId\",\"objectType\":\"task\"}}}\n\n", Activity.class));
+        List<StreamsDatum> result2 = filter.process(datum2);
+        assert result2.size() == 1;
+    }
+
+    /**
+     * Test actor and object filter together
+     */
+    @Test
+    public void testMultiFilter() throws Exception {
+        VerbDefinition definition = mapper.readValue(VerbDefinitionFilterTest.class.getResourceAsStream("/follow.json"), VerbDefinition.class);
+        VerbDefinitionFilter filter = new VerbDefinitionFilter(Sets.newHashSet(definition));
+        filter.prepare(null);
+        StreamsDatum datum1 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"follow\",\"actor\":{\"id\":\"actorId\",\"objectType\":\"page\"}}}\n", Activity.class));
+        List<StreamsDatum> result1 = filter.process(datum1);
+        assert result1.size() == 0;
+        StreamsDatum datum2 = new StreamsDatum(mapper.readValue("{\"id\":\"2\",\"verb\":\"follow\",\"object\":{\"id\":\"objectId\",\"objectType\":\"page\"}}}\n", Activity.class));
+        List<StreamsDatum> result2 = filter.process(datum2);
+        assert result2.size() == 0;
+        StreamsDatum datum3 = new StreamsDatum(mapper.readValue("{\"id\":\"3\",\"verb\":\"follow\",\"actor\":{\"id\":\"actorId\",\"objectType\":\"page\"},\"object\":{\"id\":\"objectId\",\"objectType\":\"page\"}}}\n", Activity.class));
+        List<StreamsDatum> result3 = filter.process(datum3);
+        assert result3.size() == 1;
+
+    }
+
+    /**
+     * Test targetRequired
+     */
+    @Test
+    public void testTargetRequired() throws Exception {
+        VerbDefinition definition = mapper.readValue(VerbDefinitionFilterTest.class.getResourceAsStream("/targetrequired.json"), VerbDefinition.class);
+        VerbDefinitionFilter filter = new VerbDefinitionFilter(Sets.newHashSet(definition));
+        filter.prepare(null);
+        StreamsDatum datum1 = new StreamsDatum(mapper.readValue("{\"id\":\"id\",\"verb\":\"post\",\"object\":{\"id\":\"objectId\",\"objectType\":\"task\"}}\n", Activity.class));
+        List<StreamsDatum> result1 = filter.process(datum1);
+        assert result1.size() == 0;
+        StreamsDatum datum2 = new StreamsDatum(mapper.readValue("{\"id\":\"id\",\"verb\":\"post\",\"target\":{\"id\":\"targetId\",\"objectType\":\"group\"}}\n", Activity.class));
+        List<StreamsDatum> result2 = filter.process(datum2);
+        assert result2.size() == 1;
+    }
+
+    /**
+     * Test that wildcard verb definition matches every item
+     */
+    @Test
+    public void testAllWildcard() throws Exception {
+        VerbDefinition definition = mapper.readValue(VerbDefinitionFilterTest.class.getResourceAsStream("/post.json"), VerbDefinition.class);
+        VerbDefinitionFilter filter = new VerbDefinitionFilter(Sets.newHashSet(definition));
+        filter.prepare(null);
+        StreamsDatum datum1 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"notpost\"}\n", Activity.class));
+        List<StreamsDatum> result1 = filter.process(datum1);
+        assert result1.size() == 0;
+        StreamsDatum datum2 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\"}\n", Activity.class));
+        List<StreamsDatum> result2 = filter.process(datum2);
+        assert result2.size() == 1;
+        StreamsDatum datum3 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"provider\":{\"id\":\"providerId\",\"objectType\":\"product\"}}\n", Activity.class));
+        List<StreamsDatum> result3 = filter.process(datum3);
+        assert result3.size() == 1;
+        StreamsDatum datum4 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"provider\":{\"id\":\"providerId\",\"objectType\":\"application\"}}\n\n", Activity.class));
+        List<StreamsDatum> result4 = filter.process(datum4);
+        assert result4.size() == 1;
+        StreamsDatum datum5 = new StreamsDatum(mapper.readValue("{\"id\":\"id\",\"verb\":\"post\",\"object\":{\"id\":\"objectId\",\"objectType\":\"task\"}}\n", Activity.class));
+        List<StreamsDatum> result5 = filter.process(datum5);
+        assert result5.size() == 1;
+        StreamsDatum datum6 = new StreamsDatum(mapper.readValue("{\"id\":\"id\",\"verb\":\"post\",\"target\":{\"id\":\"targetId\",\"objectType\":\"group\"}}\n", Activity.class));
+        List<StreamsDatum> result6 = filter.process(datum6);
+        assert result6.size() == 1;
+        StreamsDatum datum7 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"actor\":{\"id\":\"actorId\",\"objectType\":\"page\"}}\n", Activity.class));
+        List<StreamsDatum> result7 = filter.process(datum7);
+        assert result7.size() == 1;
+    }
+
+    /**
+     * Test that multiple verb definitions chain properly
+     */
+    @Test
+    public void testAllMultipleDefinition() throws Exception {
+        VerbDefinition provider = mapper.readValue(VerbDefinitionFilterTest.class.getResourceAsStream("/provider.json"), VerbDefinition.class);
+        VerbDefinition actor = mapper.readValue(VerbDefinitionFilterTest.class.getResourceAsStream("/actor.json"), VerbDefinition.class);
+        VerbDefinition object = mapper.readValue(VerbDefinitionFilterTest.class.getResourceAsStream("/object.json"), VerbDefinition.class);
+        VerbDefinition target = mapper.readValue(VerbDefinitionFilterTest.class.getResourceAsStream("/targetrequired.json"), VerbDefinition.class);
+        VerbDefinition follow = mapper.readValue(VerbDefinitionFilterTest.class.getResourceAsStream("/follow.json"), VerbDefinition.class);
+        VerbDefinitionFilter filter = new VerbDefinitionFilter(Sets.newHashSet(provider,actor,object,target,follow));
+        filter.prepare(null);
+        StreamsDatum datum1 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"notpost\"}\n", Activity.class));
+        List<StreamsDatum> result1 = filter.process(datum1);
+        assert result1.size() == 0;
+        StreamsDatum datum2 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\"}\n", Activity.class));
+        List<StreamsDatum> result2 = filter.process(datum2);
+        assert result2.size() == 1;
+        StreamsDatum datum3 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"provider\":{\"id\":\"providerId\",\"objectType\":\"product\"}}\n", Activity.class));
+        List<StreamsDatum> result3 = filter.process(datum3);
+        assert result3.size() == 1;
+        StreamsDatum datum4 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"provider\":{\"id\":\"providerId\",\"objectType\":\"application\"}}\n\n", Activity.class));
+        List<StreamsDatum> result4 = filter.process(datum4);
+        assert result4.size() == 1;
+        StreamsDatum datum5 = new StreamsDatum(mapper.readValue("{\"id\":\"id\",\"verb\":\"post\",\"object\":{\"id\":\"objectId\",\"objectType\":\"task\"}}\n", Activity.class));
+        List<StreamsDatum> result5 = filter.process(datum5);
+        assert result5.size() == 1;
+        StreamsDatum datum6 = new StreamsDatum(mapper.readValue("{\"id\":\"id\",\"verb\":\"post\",\"target\":{\"id\":\"targetId\",\"objectType\":\"group\"}}\n", Activity.class));
+        List<StreamsDatum> result6 = filter.process(datum6);
+        assert result6.size() == 1;
+        StreamsDatum datum7 = new StreamsDatum(mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"actor\":{\"id\":\"actorId\",\"objectType\":\"page\"}}\n", Activity.class));
+        List<StreamsDatum> result7 = filter.process(datum7);
+        assert result7.size() == 1;
+        StreamsDatum datum9 = new StreamsDatum(mapper.readValue("{\"id\":\"3\",\"verb\":\"follow\",\"actor\":{\"id\":\"actorId\",\"objectType\":\"page\"},\"object\":{\"id\":\"objectId\",\"objectType\":\"page\"}}}\n", Activity.class));
+        List<StreamsDatum> result9 = filter.process(datum9);
+        assert result9.size() == 1;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-components/streams-filters/src/test/resources/actor.json
----------------------------------------------------------------------
diff --git a/streams-components/streams-filters/src/test/resources/actor.json b/streams-components/streams-filters/src/test/resources/actor.json
new file mode 100644
index 0000000..9db498a
--- /dev/null
+++ b/streams-components/streams-filters/src/test/resources/actor.json
@@ -0,0 +1,9 @@
+{
+    "id": "http://incubator.streams.apache.org/verbs/test/targetrequired",
+    "value": "post",
+    "objects": [
+        {
+            "actor": "person"
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-components/streams-filters/src/test/resources/follow.json
----------------------------------------------------------------------
diff --git a/streams-components/streams-filters/src/test/resources/follow.json b/streams-components/streams-filters/src/test/resources/follow.json
new file mode 100644
index 0000000..06d14fe
--- /dev/null
+++ b/streams-components/streams-filters/src/test/resources/follow.json
@@ -0,0 +1,12 @@
+{
+    "id": "http://incubator.streams.apache.org/verbs/test/targetrequired",
+    "value": "follow",
+    "objects": [
+        {
+            "actorRequired": "true",
+            "actor": "page",
+            "object": "page",
+            "objectRequired": "true"
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-components/streams-filters/src/test/resources/object.json
----------------------------------------------------------------------
diff --git a/streams-components/streams-filters/src/test/resources/object.json b/streams-components/streams-filters/src/test/resources/object.json
new file mode 100644
index 0000000..e4f8a3a
--- /dev/null
+++ b/streams-components/streams-filters/src/test/resources/object.json
@@ -0,0 +1,9 @@
+{
+    "id": "http://incubator.streams.apache.org/verbs/test/targetrequired",
+    "value": "post",
+    "objects": [
+        {
+            "object": "task"
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-components/streams-filters/src/test/resources/post.json
----------------------------------------------------------------------
diff --git a/streams-components/streams-filters/src/test/resources/post.json b/streams-components/streams-filters/src/test/resources/post.json
new file mode 100644
index 0000000..bef9deb
--- /dev/null
+++ b/streams-components/streams-filters/src/test/resources/post.json
@@ -0,0 +1,12 @@
+{
+    "id": "http://incubator.streams.apache.org/verbs/test/post",
+    "value": "post",
+    "objects": [
+        {
+            "actor": "*",
+            "object": "*",
+            "provider": "*",
+            "target": "*"
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-components/streams-filters/src/test/resources/provider.json
----------------------------------------------------------------------
diff --git a/streams-components/streams-filters/src/test/resources/provider.json b/streams-components/streams-filters/src/test/resources/provider.json
new file mode 100644
index 0000000..928b219
--- /dev/null
+++ b/streams-components/streams-filters/src/test/resources/provider.json
@@ -0,0 +1,9 @@
+{
+    "id": "http://incubator.streams.apache.org/verbs/test/targetrequired",
+    "value": "post",
+    "objects": [
+        {
+            "provider": "application"
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-components/streams-filters/src/test/resources/targetrequired.json
----------------------------------------------------------------------
diff --git a/streams-components/streams-filters/src/test/resources/targetrequired.json b/streams-components/streams-filters/src/test/resources/targetrequired.json
new file mode 100644
index 0000000..57f6911
--- /dev/null
+++ b/streams-components/streams-filters/src/test/resources/targetrequired.json
@@ -0,0 +1,12 @@
+{
+    "id": "http://incubator.streams.apache.org/verbs/test/targetrequired",
+    "value": "post",
+    "objects": [
+        {
+            "actor": "*",
+            "object": "*",
+            "target": "*",
+            "targetRequired": "true"
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/README.md
----------------------------------------------------------------------
diff --git a/streams-verbs/README.md b/streams-verbs/README.md
new file mode 100644
index 0000000..bb05f2b
--- /dev/null
+++ b/streams-verbs/README.md
@@ -0,0 +1,16 @@
+streams-verbs
+=================
+
+An "Object Combination" a description of what types of actor, object
+and target objects are typically expected to be used with a
+particular verb.
+
+streams-verbs performs registration and enforcement of activity 
+stream verb definitions, restricting the type of activities deemed
+valid across the stream or upon application of a filtering component.
+
+A recommended baseline set of verb definitions are available and can be
+activated by including streams-verbs resources on your classpath.
+
+https://raw.github.com/activitystreams/activity-streams-verb-definition/master/activity-streams-verb-definition.txt
+

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/pom.xml
----------------------------------------------------------------------
diff --git a/streams-verbs/pom.xml b/streams-verbs/pom.xml
new file mode 100644
index 0000000..60bbc64
--- /dev/null
+++ b/streams-verbs/pom.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.streams</groupId>
+        <artifactId>streams-project</artifactId>
+        <version>0.2-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>streams-verbs</artifactId>
+
+    <name>streams-verbs</name>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.jsonschema2pojo</groupId>
+            <artifactId>jsonschema2pojo-core</artifactId>
+            <type>jar</type>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.streams</groupId>
+            <artifactId>streams-pojo</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-joda</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>joda-time</groupId>
+            <artifactId>joda-time</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>nz.net.ultraq.jaxb</groupId>
+            <artifactId>jaxb-utilities</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.antlr</groupId>
+            <artifactId>stringtemplate</artifactId>
+            <version>4.0.2</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <sourceDirectory>src/main/java</sourceDirectory>
+        <testSourceDirectory>src/test/java</testSourceDirectory>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+        </resources>
+        <testResources>
+            <testResource>
+                <directory>src/test/resources</directory>
+            </testResource>
+        </testResources>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>add-source</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>target/generated-sources/jsonschema2pojo</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.jsonschema2pojo</groupId>
+                <artifactId>jsonschema2pojo-maven-plugin</artifactId>
+                <configuration>
+                    <addCompileSourceRoot>true</addCompileSourceRoot>
+                    <generateBuilders>true</generateBuilders>
+                    <sourcePaths>
+                        <sourcePath>src/main/jsonschema</sourcePath>
+                    </sourcePaths>
+                    <outputDirectory>target/generated-sources/jsonschema2pojo</outputDirectory>
+                    <targetPackage>org.apache.streams.verbs</targetPackage>
+                    <useLongIntegers>true</useLongIntegers>
+                    <useJodaDates>true</useJodaDates>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/main/java/org/apache/streams/verbs/ObjectCombinationGenericOrdering.java
----------------------------------------------------------------------
diff --git a/streams-verbs/src/main/java/org/apache/streams/verbs/ObjectCombinationGenericOrdering.java b/streams-verbs/src/main/java/org/apache/streams/verbs/ObjectCombinationGenericOrdering.java
new file mode 100644
index 0000000..69f55df
--- /dev/null
+++ b/streams-verbs/src/main/java/org/apache/streams/verbs/ObjectCombinationGenericOrdering.java
@@ -0,0 +1,55 @@
+package org.apache.streams.verbs;
+
+import com.google.common.collect.Ordering;
+
+/**
+ * Orders ObjectCombinations from most specific to most general, without regard
+ * for degree of match to any specific Activity.
+ */
+public class ObjectCombinationGenericOrdering extends Ordering<ObjectCombination> {
+
+    public ObjectCombinationGenericOrdering() {}
+
+    @Override
+    public int compare(ObjectCombination left, ObjectCombination right) {
+        if( wildcardCount(left) < wildcardCount(right))
+            return -1;
+        if( wildcardCount(left) > wildcardCount(right))
+            return 1;
+        if( !wildcard(left.getActor()) && wildcard(right.getActor()))
+            return -1;
+        if( wildcard(left.getActor()) && !wildcard(right.getActor()))
+            return 1;
+        if( !wildcard(left.getObject()) && wildcard(right.getObject()))
+            return -1;
+        if( wildcard(left.getObject()) && !wildcard(right.getObject()))
+            return 1;
+        if( !wildcard(left.getTarget()) && wildcard(right.getTarget()))
+            return -1;
+        if( wildcard(left.getTarget()) && !wildcard(right.getTarget()))
+            return 1;
+        if( !wildcard(left.getProvider()) && wildcard(right.getProvider()))
+            return -1;
+        if( wildcard(left.getProvider()) && !wildcard(right.getProvider()))
+            return 1;
+        return 0;
+    }
+
+    public int wildcardCount(ObjectCombination objectCombination) {
+        int wildcardCount = 0;
+        if( wildcard(objectCombination.getActor()))
+            wildcardCount++;
+        if( wildcard(objectCombination.getObject()))
+            wildcardCount++;
+        if( wildcard(objectCombination.getTarget()))
+            wildcardCount++;
+        if( wildcard(objectCombination.getProvider()))
+            wildcardCount++;
+        return wildcardCount;
+    }
+
+    public boolean wildcard(String pattern) {
+        if( pattern.equals("*")) return true;
+        else return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/main/java/org/apache/streams/verbs/ObjectCombinationSpecificOrdering.java
----------------------------------------------------------------------
diff --git a/streams-verbs/src/main/java/org/apache/streams/verbs/ObjectCombinationSpecificOrdering.java b/streams-verbs/src/main/java/org/apache/streams/verbs/ObjectCombinationSpecificOrdering.java
new file mode 100644
index 0000000..f7837a6
--- /dev/null
+++ b/streams-verbs/src/main/java/org/apache/streams/verbs/ObjectCombinationSpecificOrdering.java
@@ -0,0 +1,63 @@
+package org.apache.streams.verbs;
+
+import com.google.common.collect.Ordering;
+import org.apache.streams.pojo.json.Activity;
+import org.apache.streams.pojo.json.ActivityObject;
+
+/**
+ * Orders ObjectCombinations from most specific to most general, in context of
+ * degree of match to a specified Activity.
+ */
+public class ObjectCombinationSpecificOrdering extends Ordering<ObjectCombination> {
+
+    private Activity activity;
+
+    public ObjectCombinationSpecificOrdering(Activity activity) {
+        this.activity = activity;
+    }
+
+    @Override
+    public int compare(ObjectCombination left, ObjectCombination right) {
+        if( matchCount(left) < matchCount(right))
+            return 1;
+        if( matchCount(left) > matchCount(right))
+            return -1;
+        if( !match(activity.getActor(), left.getActor()) && match(activity.getActor(), right.getActor()))
+            return 1;
+        if( match(activity.getActor(), left.getActor()) && !match(activity.getActor(), right.getActor()))
+            return -1;
+        if( !match(activity.getObject(), left.getObject()) && match(activity.getObject(), right.getObject()))
+            return 1;
+        if( match(activity.getObject(), left.getObject()) && !match(activity.getObject(), right.getObject()))
+            return -1;
+        if( !match(activity.getTarget(), left.getTarget()) && match(activity.getTarget(), right.getTarget()))
+            return 1;
+        if( match(activity.getTarget(), left.getTarget()) && !match(activity.getTarget(), right.getTarget()))
+            return -1;
+        if( !match(activity.getProvider(), left.getProvider()) && match(activity.getTarget(), right.getProvider()))
+            return 1;
+        if( match(activity.getProvider(), left.getProvider()) && !match(activity.getTarget(), right.getProvider()))
+            return -1;
+        return 0;
+    }
+
+    public int matchCount(ObjectCombination objectCombination) {
+        int matchCount = 0;
+        if( match(activity.getActor(), objectCombination.getActor()))
+            matchCount++;
+        if( match(activity.getObject(), objectCombination.getObject()))
+            matchCount++;
+        if( match(activity.getTarget(), objectCombination.getTarget()))
+            matchCount++;
+        if( match(activity.getProvider(), objectCombination.getProvider()))
+            matchCount++;
+        return matchCount;
+    }
+
+    public boolean match(ActivityObject activityObject, String pattern) {
+        if( activityObject != null &&
+            activityObject.getObjectType() != null &&
+            activityObject.getObjectType().equals(pattern)) return true;
+        else return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/main/java/org/apache/streams/verbs/VerbDefinitionResolver.java
----------------------------------------------------------------------
diff --git a/streams-verbs/src/main/java/org/apache/streams/verbs/VerbDefinitionResolver.java b/streams-verbs/src/main/java/org/apache/streams/verbs/VerbDefinitionResolver.java
new file mode 100644
index 0000000..4a9b079
--- /dev/null
+++ b/streams-verbs/src/main/java/org/apache/streams/verbs/VerbDefinitionResolver.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.streams.verbs;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.apache.streams.jackson.StreamsJacksonMapper;
+import org.apache.streams.pojo.json.Activity;
+import org.apache.streams.pojo.json.ActivityObject;
+import org.apache.streams.verbs.ObjectCombination;
+import org.apache.streams.verbs.VerbDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+
+public class VerbDefinitionResolver {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(VerbDefinitionResolver.class);
+
+    protected Set<VerbDefinition> verbDefinitionSet;
+
+    public VerbDefinitionResolver() {
+        // get with reflection
+    }
+
+    public VerbDefinitionResolver(Set<VerbDefinition> verbDefinitionSet) {
+        this();
+        this.verbDefinitionSet = verbDefinitionSet;
+    }
+
+    public List<VerbDefinition> matchingVerbDefinitions(Activity activity) {
+
+        Set<VerbDefinition> candidates = Sets.newConcurrentHashSet(verbDefinitionSet);
+
+        for( VerbDefinition verbDefinition : candidates ) {
+            if( activity.getVerb().equals(verbDefinition.getValue())) {
+                for( ObjectCombination criteria : verbDefinition.getObjects()) {
+                    if( filter(activity, criteria) == false ) {
+                        verbDefinition.getObjects().remove(criteria);
+                    }
+                }
+            } else {
+                candidates.remove(verbDefinition);
+            }
+            if( verbDefinition.getObjects().size() == 0)
+                candidates.remove(verbDefinition);
+
+        }
+
+        return Lists.newArrayList(candidates);
+
+    }
+
+    public List<ObjectCombination> matchingObjectCombinations(Activity activity) {
+
+        List<ObjectCombination> results = Lists.newArrayList();
+
+        for( VerbDefinition verbDefinition : verbDefinitionSet ) {
+            if( activity.getVerb().equals(verbDefinition.getValue())) {
+                for( ObjectCombination criteria : verbDefinition.getObjects()) {
+                    if( filter(activity, criteria) == true ) {
+                        results.add(criteria);
+                    }
+                }
+            }
+        }
+
+        results.sort(new ObjectCombinationSpecificOrdering(activity));
+
+        return results;
+    }
+
+    public static boolean filter(Activity activity, ObjectCombination criteria) {
+
+        return  filterType(activity.getActor(), criteria.getActorRequired(), criteria.getActor())
+                &&
+                filterType(activity.getObject(), criteria.getObjectRequired(), criteria.getObject())
+                &&
+                filterType(activity.getProvider(), criteria.getProviderRequired(), criteria.getProvider())
+                &&
+                filterType(activity.getTarget(), criteria.getTargetRequired(), criteria.getTarget())
+                ;
+
+    }
+
+    public static boolean filterType(ActivityObject activityObject, boolean required, String pattern) {
+        if (required == true && activityObject == null) return false;
+        if (required == false && activityObject == null) return true;
+        if (pattern.equals("*")) return true;
+        else if (activityObject.getObjectType() == null) return false;
+        else if (activityObject.getObjectType().equals(pattern))
+            return true;
+        else return false;
+    }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/main/java/org/apache/streams/verbs/VerbDefinitionTemplateUtil.java
----------------------------------------------------------------------
diff --git a/streams-verbs/src/main/java/org/apache/streams/verbs/VerbDefinitionTemplateUtil.java b/streams-verbs/src/main/java/org/apache/streams/verbs/VerbDefinitionTemplateUtil.java
new file mode 100644
index 0000000..ac5e1ed
--- /dev/null
+++ b/streams-verbs/src/main/java/org/apache/streams/verbs/VerbDefinitionTemplateUtil.java
@@ -0,0 +1,44 @@
+package org.apache.streams.verbs;
+
+import com.google.common.base.Strings;
+import org.apache.streams.pojo.json.Activity;
+import org.apache.streams.pojo.json.ActivityObject;
+import org.stringtemplate.v4.ST;
+
+/**
+ * Transforms VerbDefinition templates into readable strings
+ */
+public class VerbDefinitionTemplateUtil {
+
+    public static String asString(Activity activity, ObjectCombination objectCombination) {
+
+        return asString("*", activity, objectCombination);
+
+    }
+
+    public static String asString(String language, Activity activity, ObjectCombination objectCombination) {
+
+        String template = (String) objectCombination.getTemplates().getAdditionalProperties().get(language);
+        template = template.replace('{', '<');
+        template = template.replace('}', '>');
+        ST st = new ST(template);
+        st.add("actor", displayName(activity.getActor()));
+        st.add("provider", displayName(activity.getProvider()));
+        st.add("object", displayName(activity.getObject()));
+        st.add("target", displayName(activity.getTarget()));
+
+        return st.render();
+    }
+
+    public static String displayName(ActivityObject activityObject) {
+        if( activityObject == null )
+            return "";
+        if( !Strings.isNullOrEmpty(activityObject.getDisplayName()))
+            return activityObject.getDisplayName();
+        if( !Strings.isNullOrEmpty(activityObject.getObjectType()))
+            return activityObject.getObjectType();
+        if( !Strings.isNullOrEmpty(activityObject.toString()))
+            return activityObject.toString();
+        else return "";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/main/jsonschema/verb-definition.json
----------------------------------------------------------------------
diff --git a/streams-verbs/src/main/jsonschema/verb-definition.json b/streams-verbs/src/main/jsonschema/verb-definition.json
new file mode 100644
index 0000000..d651608
--- /dev/null
+++ b/streams-verbs/src/main/jsonschema/verb-definition.json
@@ -0,0 +1,94 @@
+{
+    "type" : "object",
+    "title" : "activity",
+    "javaType": "org.apache.streams.verbs.VerbDefinition",
+    "javaInterfaces": ["java.io.Serializable"],
+    "description" : "A verb definition declares what objectTypes should accompany a specific verb in an activity",
+    "additionalProperties": false,
+    "properties": {
+        "objectType" : {
+            "title" : "objectType",
+            "type" : "string",
+            "required" : true,
+            "default" : "verb",
+            "description" :"verb"
+        },
+        "id" :{
+            "type" : "string",
+            "description" : "The unique identifier for the verb object",
+            "required" : true
+        },
+        "value" : {
+            "title" : "value",
+            "type" : "string",
+            "required": true,
+            "description" :"The specific String that is to be used for the 'verb' property within an Activity object."
+        },
+        "displayName" : {
+            "title" : "displayName",
+            "type" : "string",
+            "description" :"A natural-language, human-readable and plain-text display name for the verb."
+        },
+        "synonyms" : {
+            "type" : "array",
+            "description" :"An array of zero or more other Strings known verbs for which this verb can be considered to be a synonym or alias.",
+            "note": "Tell JSON schema team to not put links inside http://json-schema.org/hyper-schema#properties",
+            "items": {
+                "type" : "string"
+            }
+        },
+        "hypernyms" : {
+            "type" : "array",
+            "description" :"An array of zero or more other Strings known verbs for which this verb can be considered to be a synonym or alias.",
+            "items": {
+                "type" : "string"
+            }
+        },
+        "objects" : {
+            "type" : "array",
+            "description" :"An array of Object Combinations.",
+            "items": {
+                "type" : "object",
+                "javaType" : "org.apache.streams.verbs.ObjectCombination",
+                "properties": {
+                    "actor": {
+                        "type" : "string",
+                        "default": "*"
+                    },
+                    "actorRequired": {
+                        "type" : "boolean",
+                        "default": "false"
+                    },
+                    "object": {
+                        "type" : "string",
+                        "default": "*"
+                    },
+                    "objectRequired": {
+                        "type" : "boolean",
+                        "default": "false"
+                    },
+                    "provider": {
+                        "type" : "string",
+                        "default": "*"
+                    },
+                    "providerRequired": {
+                        "type" : "boolean",
+                        "default": "false"
+                    },
+                    "target": {
+                        "type" : "string",
+                        "default": "*"
+                    },
+                    "targetRequired": {
+                        "type" : "boolean",
+                        "default": "false"
+                    },
+                    "templates" : {
+                        "type": "object",
+                        "additionalProperties": true
+                    }
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/main/resources/delete.json
----------------------------------------------------------------------
diff --git a/streams-verbs/src/main/resources/delete.json b/streams-verbs/src/main/resources/delete.json
new file mode 100644
index 0000000..d35af1f
--- /dev/null
+++ b/streams-verbs/src/main/resources/delete.json
@@ -0,0 +1,16 @@
+{
+    "objectType": "verb",
+    "id": "http://incubator.streams.apache.org/verbs/delete",
+    "value": "delete",
+    "objects": [
+        {
+            "actor": "page",
+            "object": "activity",
+            "target": "*",
+            "targetRequired": false,
+            "templates": {
+                "*": "{actor.displayName} deleted {object.displayName}"
+            }
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/main/resources/follow.json
----------------------------------------------------------------------
diff --git a/streams-verbs/src/main/resources/follow.json b/streams-verbs/src/main/resources/follow.json
new file mode 100644
index 0000000..e0387d3
--- /dev/null
+++ b/streams-verbs/src/main/resources/follow.json
@@ -0,0 +1,16 @@
+{
+    "objectType": "verb",
+    "id": "http://incubator.streams.apache.org/verbs/follow",
+    "value": "follow",
+    "objects": [
+        {
+            "actor": "page",
+            "object": "page",
+            "target": "*",
+            "targetRequired": false,
+            "templates": {
+                "*": "{actor.displayName} followed {object.displayName}"
+            }
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/main/resources/post.json
----------------------------------------------------------------------
diff --git a/streams-verbs/src/main/resources/post.json b/streams-verbs/src/main/resources/post.json
new file mode 100644
index 0000000..e37f674
--- /dev/null
+++ b/streams-verbs/src/main/resources/post.json
@@ -0,0 +1,16 @@
+{
+  "objectType": "verb",
+  "id": "http://incubator.streams.apache.org/verbs/post",
+  "value": "post",
+  "objects": [
+    {
+      "actor": "page",
+      "object": "note",
+      "target": "*",
+      "targetRequired": false,
+      "templates": {
+        "*": "{actor.displayName} posted {object.content}"
+      }
+    }
+  ]
+}

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/main/resources/share.json
----------------------------------------------------------------------
diff --git a/streams-verbs/src/main/resources/share.json b/streams-verbs/src/main/resources/share.json
new file mode 100644
index 0000000..9320f7e
--- /dev/null
+++ b/streams-verbs/src/main/resources/share.json
@@ -0,0 +1,16 @@
+{
+    "objectType": "verb",
+    "id": "http://incubator.streams.apache.org/verbs/share",
+    "value": "share",
+    "objects": [
+        {
+            "actor": "page",
+            "object": "activity",
+            "target": "*",
+            "targetRequired": false,
+            "templates": {
+                "*": "{actor.displayName} shared {object.content}"
+            }
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/test/java/org/apache/streams/verbs/ObjectCombinationGenericOrderingTest.java
----------------------------------------------------------------------
diff --git a/streams-verbs/src/test/java/org/apache/streams/verbs/ObjectCombinationGenericOrderingTest.java b/streams-verbs/src/test/java/org/apache/streams/verbs/ObjectCombinationGenericOrderingTest.java
new file mode 100644
index 0000000..bd67c96
--- /dev/null
+++ b/streams-verbs/src/test/java/org/apache/streams/verbs/ObjectCombinationGenericOrderingTest.java
@@ -0,0 +1,22 @@
+package org.apache.streams.verbs;
+
+import org.junit.Test;
+
+/**
+ * Orders ObjectCombinations from most specific to most general, without regard
+ * for degree of match to any specific Activity.
+ */
+public class ObjectCombinationGenericOrderingTest  {
+
+    @Test
+    public void compareWildcardCountTest() {
+        ObjectCombination combination1 = new ObjectCombination();
+        ObjectCombination combination2 = new ObjectCombination().withActor("actor");
+        assert (new ObjectCombinationGenericOrdering()).compare(combination1, combination2) > 0;
+        ObjectCombination combination3 = new ObjectCombination();
+        ObjectCombination combination4 = new ObjectCombination().withProvider("provider");
+        assert (new ObjectCombinationGenericOrdering()).compare(combination3, combination4) > 0;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/test/java/org/apache/streams/verbs/ObjectCombinationSpecificOrderingTest.java
----------------------------------------------------------------------
diff --git a/streams-verbs/src/test/java/org/apache/streams/verbs/ObjectCombinationSpecificOrderingTest.java b/streams-verbs/src/test/java/org/apache/streams/verbs/ObjectCombinationSpecificOrderingTest.java
new file mode 100644
index 0000000..fce4585
--- /dev/null
+++ b/streams-verbs/src/test/java/org/apache/streams/verbs/ObjectCombinationSpecificOrderingTest.java
@@ -0,0 +1,31 @@
+package org.apache.streams.verbs;
+
+import org.apache.streams.pojo.json.Activity;
+import org.apache.streams.pojo.json.Actor;
+import org.apache.streams.pojo.json.Provider;
+import org.junit.Test;
+
+/**
+ * Orders ObjectCombinations from most specific to most general, without regard
+ * for degree of match to any specific Activity.
+ */
+public class ObjectCombinationSpecificOrderingTest {
+
+    @Test
+    public void compareMatchCountTest() {
+        Actor actor = new Actor();
+        actor.setObjectType("actor");
+        Activity activity = new Activity().withActor(actor);
+        ObjectCombination combination1 = new ObjectCombination();
+        ObjectCombination combination2 = new ObjectCombination().withActor("actor");
+        assert (new ObjectCombinationSpecificOrdering(activity)).compare(combination1, combination2) > 0;
+        Provider provider = new Provider();
+        provider.setObjectType("application");
+        Activity activity2 = new Activity().withProvider(provider);
+        ObjectCombination combination3 = new ObjectCombination();
+        ObjectCombination combination4 = new ObjectCombination().withProvider("provider");
+        assert (new ObjectCombinationSpecificOrdering(activity2)).compare(combination3, combination4) > 0;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/test/java/org/apache/streams/verbs/VerbDefinitionResolverTest.java
----------------------------------------------------------------------
diff --git a/streams-verbs/src/test/java/org/apache/streams/verbs/VerbDefinitionResolverTest.java b/streams-verbs/src/test/java/org/apache/streams/verbs/VerbDefinitionResolverTest.java
new file mode 100644
index 0000000..1edcc31
--- /dev/null
+++ b/streams-verbs/src/test/java/org/apache/streams/verbs/VerbDefinitionResolverTest.java
@@ -0,0 +1,90 @@
+package org.apache.streams.verbs;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.Sets;
+import org.apache.streams.jackson.StreamsJacksonMapper;
+import org.apache.streams.pojo.json.Activity;
+import org.junit.Test;
+
+import java.util.List;
+
+/**
+ * Tests for {$link: org.apache.streams.verbs.VerbDefinitionResolver}
+ */
+public class VerbDefinitionResolverTest {
+
+    ObjectMapper mapper = new StreamsJacksonMapper();
+
+    /**
+     * Test of matchingVerbDefinitions
+     */
+    @Test
+    public void testMatchingVerbDefinitions() throws Exception {
+        VerbDefinition definition = mapper.readValue(VerbDefinitionResolverTest.class.getResourceAsStream("/post.json"), VerbDefinition.class);
+        VerbDefinitionResolver resolver = new VerbDefinitionResolver(Sets.newHashSet(definition));
+        Activity activity0 = mapper.readValue("{\"id\":\"1\",\"verb\":\"notpost\"}\n", Activity.class);
+        List<VerbDefinition> result0 = resolver.matchingVerbDefinitions(activity0);
+        assert result0.size() == 0;
+        Activity activity1 = mapper.readValue("{\"id\":\"1\",\"verb\":\"post\"}\n", Activity.class);
+        List<VerbDefinition> result1 = resolver.matchingVerbDefinitions(activity1);
+        assert result1.size() == 1;
+        assert definition.equals(result1.get(0));
+        Activity activity2 = mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"provider\":{\"id\":\"providerId\",\"objectType\":\"product\"}}\n", Activity.class);
+        List<VerbDefinition> result2 = resolver.matchingVerbDefinitions(activity2);
+        assert result2.size() == 1;
+        assert definition.equals(result2.get(0));
+        Activity activity3 = mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"provider\":{\"id\":\"providerId\",\"objectType\":\"application\"}}\n\n", Activity.class);
+        List<VerbDefinition> result3 = resolver.matchingVerbDefinitions(activity3);
+        assert result3.size() == 1;
+        assert definition.equals(result3.get(0));
+        Activity activity4 = mapper.readValue("{\"id\":\"id\",\"verb\":\"post\",\"object\":{\"id\":\"objectId\",\"objectType\":\"task\"}}\n", Activity.class);
+        List<VerbDefinition> result4 = resolver.matchingVerbDefinitions(activity4);
+        assert result4.size() == 1;
+        assert definition.equals(result4.get(0));
+        Activity activity5 = mapper.readValue("{\"id\":\"id\",\"verb\":\"post\",\"target\":{\"id\":\"targetId\",\"objectType\":\"group\"}}\n", Activity.class);
+        List<VerbDefinition> result5 = resolver.matchingVerbDefinitions(activity5);
+        assert result5.size() == 1;
+        assert definition.equals(result5.get(0));
+        Activity activity6 = mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"actor\":{\"id\":\"actorId\",\"objectType\":\"page\"}}\n", Activity.class);
+        List<VerbDefinition> result6 = resolver.matchingVerbDefinitions(activity6);
+        assert result6.size() == 1;
+        assert definition.equals(result6.get(0));
+    }
+
+    /**
+     * Test of matchingObjectCombinations
+     */
+    @Test
+    public void testMatchingObjectCombinations() throws Exception {
+        VerbDefinition provider = mapper.readValue(VerbDefinitionResolverTest.class.getResourceAsStream("/provider.json"), VerbDefinition.class);
+        VerbDefinition actor = mapper.readValue(VerbDefinitionResolverTest.class.getResourceAsStream("/actor.json"), VerbDefinition.class);
+        VerbDefinition object = mapper.readValue(VerbDefinitionResolverTest.class.getResourceAsStream("/object.json"), VerbDefinition.class);
+        VerbDefinition post = mapper.readValue(VerbDefinitionResolverTest.class.getResourceAsStream("/post.json"), VerbDefinition.class);
+        VerbDefinition follow = mapper.readValue(VerbDefinitionResolverTest.class.getResourceAsStream("/follow.json"), VerbDefinition.class);
+        VerbDefinitionResolver resolver = new VerbDefinitionResolver(Sets.newHashSet(provider, actor, object, post, follow));
+        Activity activity0 = mapper.readValue("{\"id\":\"1\",\"verb\":\"notpost\"}\n", Activity.class);
+        List<ObjectCombination> result0 = resolver.matchingObjectCombinations(activity0);
+        assert result0.size() == 0;
+        Activity activity1 = mapper.readValue("{\"id\":\"1\",\"verb\":\"post\"}\n", Activity.class);
+        List<ObjectCombination> result1 = resolver.matchingObjectCombinations(activity1);
+        assert result1.size() == 4;
+        Activity activity2 = mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"provider\":{\"id\":\"providerId\",\"objectType\":\"product\"}}\n", Activity.class);
+        List<ObjectCombination> result2 = resolver.matchingObjectCombinations(activity2);
+        assert result2.size() == 3;
+        Activity activity3 = mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"provider\":{\"id\":\"providerId\",\"objectType\":\"application\"}}\n", Activity.class);
+        List<ObjectCombination> result3 = resolver.matchingObjectCombinations(activity3);
+        assert result3.size() == 4;
+        assert provider.getObjects().get(0).equals(result3.get(0));
+        Activity activity4 = mapper.readValue("{\"id\":\"id\",\"verb\":\"post\",\"object\":{\"id\":\"objectId\",\"objectType\":\"task\"}}\n", Activity.class);
+        List<ObjectCombination> result4 = resolver.matchingObjectCombinations(activity4);
+        assert result4.size() == 4;
+        assert object.getObjects().get(0).equals(result4.get(0));
+        Activity activity5 = mapper.readValue("{\"id\":\"id\",\"verb\":\"post\",\"target\":{\"id\":\"targetId\",\"objectType\":\"group\"}}\n", Activity.class);
+        List<ObjectCombination> result5 = resolver.matchingObjectCombinations(activity5);
+        assert result5.size() == 4;
+        Activity activity6 = mapper.readValue("{\"id\":\"1\",\"verb\":\"post\",\"actor\":{\"id\":\"actorId\",\"objectType\":\"person\"}}\n", Activity.class);
+        List<ObjectCombination> result6 = resolver.matchingObjectCombinations(activity6);
+        assert result6.size() == 4;
+        assert actor.getObjects().get(0).equals(result6.get(0));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/test/java/org/apache/streams/verbs/VerbDefinitionTemplateTest.java
----------------------------------------------------------------------
diff --git a/streams-verbs/src/test/java/org/apache/streams/verbs/VerbDefinitionTemplateTest.java b/streams-verbs/src/test/java/org/apache/streams/verbs/VerbDefinitionTemplateTest.java
new file mode 100644
index 0000000..ba43c13
--- /dev/null
+++ b/streams-verbs/src/test/java/org/apache/streams/verbs/VerbDefinitionTemplateTest.java
@@ -0,0 +1,67 @@
+package org.apache.streams.verbs;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.streams.pojo.json.Activity;
+import org.apache.streams.pojo.json.ActivityObject;
+import org.apache.streams.pojo.json.Actor;
+import org.apache.streams.pojo.json.Provider;
+import org.junit.Test;
+
+import java.lang.annotation.Target;
+
+/**
+ * Tests for {$link: org.apache.streams.verbs.VerbDefinitionTemplateUtil}
+ */
+public class VerbDefinitionTemplateTest {
+
+    ObjectMapper mapper = new ObjectMapper();
+
+    /**
+     * Test application of template with no field
+     */
+    @Test
+    public void testNoField() throws Exception {
+        Activity activity = new Activity().withVerb("nofields");
+        VerbDefinition definition = mapper.readValue(VerbDefinitionResolverTest.class.getResourceAsStream("/nofields.json"), VerbDefinition.class);
+        assert VerbDefinitionTemplateUtil.asString(activity, definition.getObjects().get(0)).contains("something");
+    }
+
+    /**
+     * Test application of template with top-level fields
+     */
+    @Test
+    public void testTopField() throws Exception {
+        Actor actor = new Actor();
+        actor.setObjectType("page");
+        actor.setDisplayName("Paige");
+        Provider provider = new Provider();
+        provider.setObjectType("application");
+        provider.setDisplayName("Ahp");
+        ActivityObject object = new ActivityObject();
+        object.setObjectType("task");
+        object.setDisplayName("Tsk");
+        ActivityObject target = new ActivityObject();
+        target.setObjectType("person");
+        target.setDisplayName("Homie");
+        Activity activity = new Activity().withVerb("post");
+        activity.setActor(actor);
+        activity.setProvider(provider);
+        activity.setObject(object);
+        activity.setTarget(target);
+        VerbDefinition definition = mapper.readValue(VerbDefinitionTest.class.getResourceAsStream("/post.json"), VerbDefinition.class);
+        String message = VerbDefinitionTemplateUtil.asString(activity, definition.getObjects().get(0));
+        assert message.contains("Paige");
+        assert message.contains("Ahp");
+        assert message.contains("Tsk");
+        assert message.contains("Homie");
+    }
+
+    /**
+     * Test application of template with second-level fields
+     */
+    @Test
+    public void testSecondFields() {
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/test/java/org/apache/streams/verbs/VerbDefinitionTest.java
----------------------------------------------------------------------
diff --git a/streams-verbs/src/test/java/org/apache/streams/verbs/VerbDefinitionTest.java b/streams-verbs/src/test/java/org/apache/streams/verbs/VerbDefinitionTest.java
new file mode 100644
index 0000000..3f5d385
--- /dev/null
+++ b/streams-verbs/src/test/java/org/apache/streams/verbs/VerbDefinitionTest.java
@@ -0,0 +1,44 @@
+package org.apache.streams.verbs;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Test;
+
+public class VerbDefinitionTest {
+
+    ObjectMapper mapper = new ObjectMapper();
+
+    /**
+     * Test read verb definition from json
+     */
+    @Test
+    public void testReadVerbDefinitionJson() throws Exception {
+
+        VerbDefinition definition = mapper.readValue(VerbDefinitionTest.class.getResourceAsStream("/do.json"), VerbDefinition.class);
+
+        assert definition != null;
+        assert definition.getObjectType().equals("verb");
+        assert definition.getObjects().size() == 1;
+        assert definition.getObjects().get(0).getActor().equals("*");
+        assert definition.getObjects().get(0).getObject().equals("*");
+        assert definition.getObjects().get(0).getTarget().equals("*");
+        assert definition.getObjects().get(0).getProvider().equals("*");
+        assert definition.getObjects().get(0).getTemplates().getAdditionalProperties().size() == 1;
+    }
+
+    /**
+     * Test verb definition defaults are set
+     */
+    @Test
+    public void testObjectCombinationDefaults() throws Exception {
+
+        ObjectCombination combination = new ObjectCombination();
+
+        assert combination.getActor().equals("*");
+        assert combination.getObject().equals("*");
+        assert combination.getTarget().equals("*");
+        assert combination.getProvider().equals("*");
+        assert combination.getTargetRequired() == false;
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/test/resources/activities.txt
----------------------------------------------------------------------
diff --git a/streams-verbs/src/test/resources/activities.txt b/streams-verbs/src/test/resources/activities.txt
new file mode 100644
index 0000000..ecab0e5
--- /dev/null
+++ b/streams-verbs/src/test/resources/activities.txt
@@ -0,0 +1,4 @@
+{"id":"1","verb":"do","provider":{"id":"providerId","objectType":"product"}}
+{"id":"2","verb":"do","actor":{"id":"actorId","objectType":"person"}}
+{"id":"3","verb":"do","object":{"id":"objectId","objectType":"task"}}
+{"id":"4","verb":"do","target":{"id":"targetId","objectType":"group"}}

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/test/resources/actor.json
----------------------------------------------------------------------
diff --git a/streams-verbs/src/test/resources/actor.json b/streams-verbs/src/test/resources/actor.json
new file mode 100644
index 0000000..9db498a
--- /dev/null
+++ b/streams-verbs/src/test/resources/actor.json
@@ -0,0 +1,9 @@
+{
+    "id": "http://incubator.streams.apache.org/verbs/test/targetrequired",
+    "value": "post",
+    "objects": [
+        {
+            "actor": "person"
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/test/resources/do.json
----------------------------------------------------------------------
diff --git a/streams-verbs/src/test/resources/do.json b/streams-verbs/src/test/resources/do.json
new file mode 100644
index 0000000..058a912
--- /dev/null
+++ b/streams-verbs/src/test/resources/do.json
@@ -0,0 +1,14 @@
+{
+    "id": "http://incubator.streams.apache.org/verbs/test/do",
+    "value": "do",
+    "objects": [
+        {
+            "actor": "*",
+            "object": "*",
+            "target": "*",
+            "templates": {
+                "*": "{actor} do {object} to {target}"
+            }
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/test/resources/follow.json
----------------------------------------------------------------------
diff --git a/streams-verbs/src/test/resources/follow.json b/streams-verbs/src/test/resources/follow.json
new file mode 100644
index 0000000..06d14fe
--- /dev/null
+++ b/streams-verbs/src/test/resources/follow.json
@@ -0,0 +1,12 @@
+{
+    "id": "http://incubator.streams.apache.org/verbs/test/targetrequired",
+    "value": "follow",
+    "objects": [
+        {
+            "actorRequired": "true",
+            "actor": "page",
+            "object": "page",
+            "objectRequired": "true"
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/test/resources/nofields.json
----------------------------------------------------------------------
diff --git a/streams-verbs/src/test/resources/nofields.json b/streams-verbs/src/test/resources/nofields.json
new file mode 100644
index 0000000..e6e66ce
--- /dev/null
+++ b/streams-verbs/src/test/resources/nofields.json
@@ -0,0 +1,15 @@
+{
+    "id": "http://incubator.streams.apache.org/verbs/test/post",
+    "value": "nofields",
+    "objects": [
+        {
+            "actor": "*",
+            "object": "*",
+            "provider": "*",
+            "target": "*",
+            "templates": {
+                "*": "something did something to something"
+            }
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/test/resources/object.json
----------------------------------------------------------------------
diff --git a/streams-verbs/src/test/resources/object.json b/streams-verbs/src/test/resources/object.json
new file mode 100644
index 0000000..e4f8a3a
--- /dev/null
+++ b/streams-verbs/src/test/resources/object.json
@@ -0,0 +1,9 @@
+{
+    "id": "http://incubator.streams.apache.org/verbs/test/targetrequired",
+    "value": "post",
+    "objects": [
+        {
+            "object": "task"
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/test/resources/post.json
----------------------------------------------------------------------
diff --git a/streams-verbs/src/test/resources/post.json b/streams-verbs/src/test/resources/post.json
new file mode 100644
index 0000000..3be52be
--- /dev/null
+++ b/streams-verbs/src/test/resources/post.json
@@ -0,0 +1,15 @@
+{
+    "id": "http://incubator.streams.apache.org/verbs/test/post",
+    "value": "post",
+    "objects": [
+        {
+            "actor": "*",
+            "object": "*",
+            "provider": "*",
+            "target": "*",
+            "templates": {
+                "*": "[{provider}] {actor} post {object} to {target}"
+            }
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/0b2ba6cb/streams-verbs/src/test/resources/provider.json
----------------------------------------------------------------------
diff --git a/streams-verbs/src/test/resources/provider.json b/streams-verbs/src/test/resources/provider.json
new file mode 100644
index 0000000..928b219
--- /dev/null
+++ b/streams-verbs/src/test/resources/provider.json
@@ -0,0 +1,9 @@
+{
+    "id": "http://incubator.streams.apache.org/verbs/test/targetrequired",
+    "value": "post",
+    "objects": [
+        {
+            "provider": "application"
+        }
+    ]
+}
\ No newline at end of file


Mime
View raw message