You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by bb...@apache.org on 2017/08/09 18:17:27 UTC

[1/2] nifi-registry git commit: NIFIREG-8 - Initial NiFi Registry Web API endpoints

Repository: nifi-registry
Updated Branches:
  refs/heads/master a201fa5b2 -> a520c7575


http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-web-api/src/main/resources/templates/operation.hbs
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/resources/templates/operation.hbs b/nifi-registry-web-api/src/main/resources/templates/operation.hbs
new file mode 100644
index 0000000..5fb25e7
--- /dev/null
+++ b/nifi-registry-web-api/src/main/resources/templates/operation.hbs
@@ -0,0 +1,104 @@
+{{!--
+    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 with
+    the License.  You may obtain a copy of the License at
+        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.
+--}}
+<div class="operation hidden">
+    {{#if description}}
+    <div class="description">
+        {{description}}
+    </div>
+    {{/if}}
+    <div class="title">Request</div>
+    <div class="mediatypes details">
+        {{#if consumes}}
+        <div class="mediatype"><div class="title">consumes:</div><div class="mono">{{join consumes ", "}}</div><div class="clear"></div></div>
+        {{/if}}
+    </div>
+    {{#if parameters}}
+    <table>
+        <thead>
+            <tr>
+                <th>Name</th>
+                <th>Location</th>
+                <th>Type</th>
+                <th>Description</th>
+            </tr>
+        </thead>
+        <tbody>
+    {{/if}}
+    {{#each parameters}}
+        <tr>
+            <td>{{#ifeq in "body"}}{{else}}{{name}}{{/ifeq}}</td>
+            <td>{{in}}</td>
+            {{#ifeq in "body"}}
+                <td>
+                {{#ifeq schema.type "array"}}Array[<a class="type-link" href="javascript:void(0);">{{basename schema.items.$ref}}</a>]{{/ifeq}}
+                {{#schema.$ref}}<a class="type-link" href="javascript:void(0);">{{basename schema.$ref}}</a> {{/schema.$ref}}
+                </td>
+            {{else}}
+                {{#ifeq type "array"}}
+                        <td>Array[{{items.type}}] ({{collectionFormat}})</td>
+                {{else}}
+                    {{#ifeq type "ref"}}
+                        <td>string</td>
+                    {{else}}
+                        <td>{{type}} {{#format}}({{format}}){{/format}}</td>
+                    {{/ifeq}}
+                {{/ifeq}}
+            {{/ifeq}}
+            <td>{{description}}</td>
+        </tr>
+    {{/each}}
+    {{#if parameters}}
+        </tbody>
+    </table>
+    {{/if}}
+    <div class="title">Response</div>
+    <div class="mediatypes details">
+        {{#if produces}}
+        <div class="mediatype"><div class="title">produces:</div><div class="mono">{{join produces ", "}}</div><div class="clear"></div></div>
+        {{/if}}
+    </div>
+    <table>
+        <thead>
+            <tr>
+                <th>Status Code</th>
+                <th>Type</th>
+                <th>Description</th>
+            </tr>
+        </thead>
+        <tbody>
+            {{#each responses}}
+            <tr>
+                <td>{{@key}}</td>
+                <td>
+                    {{#if schema}}
+                        {{#schema.$ref}}<a class="type-link" href="javascript:void(0);">{{basename schema.$ref}}</a>{{/schema.$ref}}
+                    {{else}}
+                        string
+                    {{/if}}
+                </td>
+                <td>{{description}}</td>
+            </tr>
+            {{/each}}
+        </tbody>
+    </table>
+    <div class="title">Authorization</div>
+    <div class="authorization details">
+        {{#security}}
+            {{#each this}}
+            <div>{{@key}}</div>
+            {{/each}}
+        {{/security}}
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-web-api/src/main/resources/templates/type.hbs
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/resources/templates/type.hbs b/nifi-registry-web-api/src/main/resources/templates/type.hbs
new file mode 100644
index 0000000..f6f117b
--- /dev/null
+++ b/nifi-registry-web-api/src/main/resources/templates/type.hbs
@@ -0,0 +1,57 @@
+{{!--
+    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 with
+    the License.  You may obtain a copy of the License at
+        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.
+--}}
+<div id="{{@key}}" class="type hidden">
+    <h3>{{@key}}</h3>
+    <div class="type-container">
+        <table>
+            <tr>
+                <th>Name</th>
+                <th>Type</th>
+                <th>Required</th>
+                <th>Description</th>
+            </tr>
+            {{#each properties}}
+                <tr>
+                    <td>{{@key}}</td>
+                    <td>
+                        {{#ifeq type "array"}}
+                            {{#items.$ref}}
+                                {{type}}[<a class="type-link" href="javascript:void(0);">{{basename items.$ref}}</a>]
+                            {{/items.$ref}}
+                            {{^items.$ref}}
+                                {{type}}[{{items.type}}]
+                            {{/items.$ref}}
+                        {{else}}
+                            {{#$ref}}
+                                <a class="type-link" href="javascript:void(0);">{{basename $ref}}</a>
+                            {{/$ref}}
+                            {{^$ref}}
+                                {{type}}{{#format}} ({{format}}){{/format}}
+                            {{/$ref}}
+                        {{/ifeq}}
+                    </td>
+                    <td>{{#required}}required{{/required}}{{^required}}optional{{/required}}</td>
+                    <td>{{#description}}{{{description}}}{{/description}}
+                        {{#if enum}} Allowable values: {{join enum ", "}}{{/if}}
+                        {{#if readOnly}} This property is read only.{{/if}}</td>
+                </tr>
+            {{/each}}
+        </table>
+        <h4>Example JSON</h4>
+        <code class="example"><span class="open-object">&#123;{{> example}}&#125;</span></code>
+    </div>
+    <div class="close">Close</div>
+    <div class="clear"></div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 83aee92..4185344 100644
--- a/pom.xml
+++ b/pom.xml
@@ -98,7 +98,7 @@
         <inceptionYear>2017</inceptionYear>
     	<org.slf4j.version>1.7.12</org.slf4j.version>
         <jetty.version>9.2.11.v20150529</jetty.version>
-        <jersey.version>2.19</jersey.version>
+        <jersey.version>2.25.1</jersey.version>
     </properties>
 
     <repositories>


[2/2] nifi-registry git commit: NIFIREG-8 - Initial NiFi Registry Web API endpoints

Posted by bb...@apache.org.
NIFIREG-8 - Initial NiFi Registry Web API endpoints

This closes #4.

Signed-off-by: Bryan Bende <bb...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/nifi-registry/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi-registry/commit/a520c757
Tree: http://git-wip-us.apache.org/repos/asf/nifi-registry/tree/a520c757
Diff: http://git-wip-us.apache.org/repos/asf/nifi-registry/diff/a520c757

Branch: refs/heads/master
Commit: a520c7575493989dc55f14705bbb68e62ae099e0
Parents: a201fa5
Author: Kevin Doran <kd...@gmail.com>
Authored: Mon Aug 7 10:29:11 2017 -0400
Committer: Bryan Bende <bb...@apache.org>
Committed: Wed Aug 9 14:16:55 2017 -0400

----------------------------------------------------------------------
 nifi-registry-flow-data-model/pom.xml           |   4 +-
 .../apache/nifi/registry/flow/BatchSize.java    |   2 +-
 .../org/apache/nifi/registry/flow/Bucket.java   |  96 +++
 .../apache/nifi/registry/flow/BucketObject.java |  35 +
 .../org/apache/nifi/registry/flow/Bundle.java   |   2 +-
 .../registry/flow/ConnectableComponent.java     |   2 +-
 .../registry/flow/ControllerServiceAPI.java     |   2 +-
 .../org/apache/nifi/registry/flow/Position.java |   4 +-
 .../nifi/registry/flow/VersionedComponent.java  |   2 +-
 .../nifi/registry/flow/VersionedConnection.java |   2 +-
 .../flow/VersionedControllerService.java        |   2 +-
 .../nifi/registry/flow/VersionedFlow.java       | 136 ++++
 .../registry/flow/VersionedFlowSnapshot.java    |   6 +-
 .../nifi/registry/flow/VersionedLabel.java      |   2 +-
 .../nifi/registry/flow/VersionedPort.java       |   2 +-
 .../registry/flow/VersionedProcessGroup.java    |   2 +-
 .../nifi/registry/flow/VersionedProcessor.java  |   2 +-
 .../registry/flow/VersionedRemoteGroupPort.java |   2 +-
 .../flow/VersionedRemoteProcessGroup.java       |   2 +-
 nifi-registry-web-api/pom.xml                   |  68 ++
 .../registry/web/api/BucketFlowResource.java    |  69 ++
 .../nifi/registry/web/api/BucketResource.java   | 137 ++++
 .../nifi/registry/web/api/FlowResource.java     | 202 ++++++
 .../src/main/resources/images/bgNifiLogo.png    | Bin 0 -> 3894 bytes
 .../src/main/resources/images/nifi16.ico        | Bin 0 -> 1150 bytes
 .../src/main/resources/templates/endpoint.hbs   |  61 ++
 .../src/main/resources/templates/example.hbs    |  18 +
 .../src/main/resources/templates/index.html.hbs | 687 +++++++++++++++++++
 .../src/main/resources/templates/operation.hbs  | 104 +++
 .../src/main/resources/templates/type.hbs       |  57 ++
 pom.xml                                         |   2 +-
 31 files changed, 1692 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/pom.xml b/nifi-registry-flow-data-model/pom.xml
index 0bb0c5a..2485791 100644
--- a/nifi-registry-flow-data-model/pom.xml
+++ b/nifi-registry-flow-data-model/pom.xml
@@ -23,9 +23,9 @@
     
     <dependencies>
         <dependency>
-            <groupId>com.wordnik</groupId>
+            <groupId>io.swagger</groupId>
             <artifactId>swagger-annotations</artifactId>
-            <version>1.5.3-M1</version>
+            <version>1.5.16</version>
         </dependency>
     </dependencies>
 </project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/BatchSize.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/BatchSize.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/BatchSize.java
index 7a0fb84..b0687b9 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/BatchSize.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/BatchSize.java
@@ -17,7 +17,7 @@
 
 package org.apache.nifi.registry.flow;
 
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModelProperty;
 
 public class BatchSize {
     private Integer count;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/Bucket.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/Bucket.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/Bucket.java
new file mode 100644
index 0000000..5cc483f
--- /dev/null
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/Bucket.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 with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     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.nifi.registry.flow;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+@ApiModel(value = "bucket")
+public class Bucket {
+
+    private String identifier;
+    private String name;
+    private long createdTimestamp;
+    private String description;
+    private Map<String, BucketObject> bucketObjectMap = new HashMap<>();
+
+    @ApiModelProperty("The id of the bucket. This is set by the server at creation time.")
+    public String getIdentifier() {
+        return identifier;
+    }
+
+    public void setIdentifier(String identifier) {
+        this.identifier = identifier;
+    }
+
+    @ApiModelProperty("The name of the bucket.")
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @ApiModelProperty("The timestamp of when the bucket was first created. This is set by the server at creation time.")
+    public long getCreatedTimestamp() {
+        return createdTimestamp;
+    }
+
+    public void setCreatedTimestamp(long createdTimestamp) {
+        this.createdTimestamp = createdTimestamp;
+    }
+
+    @ApiModelProperty("A description of the bucket.")
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    /**
+     * Add a new object version to this bucket.
+     *
+     * Note that this method has a potential side effect.
+     * If a BucketObject ID is not set, a random UUID string will be set.
+     *
+     * @param object  The object to add to this bucket.
+     */
+    public void addObject(BucketObject object) {
+        if(object.getIdentifier() == null) {
+            object.setIdentifier(UUID.randomUUID().toString());
+        }
+
+        this.bucketObjectMap.put(object.getIdentifier(), object);
+    }
+
+    protected Map<String, BucketObject> getBucketObjectMap() {
+        return bucketObjectMap;
+    }
+
+    protected void setBucketObjectMap(Map<String, BucketObject> bucketObjectMap) {
+        this.bucketObjectMap = bucketObjectMap;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/BucketObject.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/BucketObject.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/BucketObject.java
new file mode 100644
index 0000000..2e2bdf4
--- /dev/null
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/BucketObject.java
@@ -0,0 +1,35 @@
+/*
+ * 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 with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     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.nifi.registry.flow;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("bucketObject")
+public abstract class BucketObject {
+
+    private String identifier;
+
+    @ApiModelProperty("An ID to uniquely identify this object.")
+    public String getIdentifier() {
+        return identifier;
+    }
+
+    public void setIdentifier(String id) {
+        this.identifier = id;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/Bundle.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/Bundle.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/Bundle.java
index ae251f9..1050ac9 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/Bundle.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/Bundle.java
@@ -19,7 +19,7 @@ package org.apache.nifi.registry.flow;
 
 import java.util.Objects;
 
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModelProperty;
 
 public class Bundle {
     private String group;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/ConnectableComponent.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/ConnectableComponent.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/ConnectableComponent.java
index 38bc367..abd34bf 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/ConnectableComponent.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/ConnectableComponent.java
@@ -17,7 +17,7 @@
 
 package org.apache.nifi.registry.flow;
 
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModelProperty;
 
 public class ConnectableComponent {
     private String id;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/ControllerServiceAPI.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/ControllerServiceAPI.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/ControllerServiceAPI.java
index 2e7c960..b46e87a 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/ControllerServiceAPI.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/ControllerServiceAPI.java
@@ -19,7 +19,7 @@ package org.apache.nifi.registry.flow;
 
 import java.util.Objects;
 
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModelProperty;
 
 public class ControllerServiceAPI {
     private String type;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/Position.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/Position.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/Position.java
index 20c2008..0cbb12c 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/Position.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/Position.java
@@ -17,8 +17,8 @@
 
 package org.apache.nifi.registry.flow;
 
-import com.wordnik.swagger.annotations.ApiModel;
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 
 @ApiModel("The position of a component on the graph")
 public class Position {

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedComponent.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedComponent.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedComponent.java
index 365e3ea..bef9557 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedComponent.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedComponent.java
@@ -17,7 +17,7 @@
 
 package org.apache.nifi.registry.flow;
 
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModelProperty;
 
 
 public abstract class VersionedComponent {

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedConnection.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedConnection.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedConnection.java
index 1ca46c5..59740e9 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedConnection.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedConnection.java
@@ -20,7 +20,7 @@ package org.apache.nifi.registry.flow;
 import java.util.List;
 import java.util.Set;
 
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModelProperty;
 
 public class VersionedConnection extends VersionedComponent {
     private ConnectableComponent source;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedControllerService.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedControllerService.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedControllerService.java
index 64d36c3..2275e73 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedControllerService.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedControllerService.java
@@ -21,7 +21,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModelProperty;
 
 public class VersionedControllerService extends VersionedComponent {
 

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlow.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlow.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlow.java
new file mode 100644
index 0000000..dc3bc09
--- /dev/null
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlow.java
@@ -0,0 +1,136 @@
+/*
+ * 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 with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     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.nifi.registry.flow;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * <p>
+ * Represents a versioned flow. A versioned flow is a named flow that is expected to change
+ * over time. This flow is saved to the registry with information such as its name, a description,
+ * and each version of the flow.
+ * </p>
+ *
+ * @see VersionedFlowSnapshot
+ */
+@ApiModel(value = "versionedFlow")
+public class VersionedFlow extends BucketObject {
+
+    private String name;
+    private long createdTimestamp;
+    private long modifiedTimestamp;
+    private String description;
+    private int currentMaxVersion = 0;
+    private ArrayList<VersionedFlowSnapshot> snapshots = new ArrayList<>();
+    private Map<Integer, VersionedFlowSnapshot> snapshotsByVersion = new HashMap<>(); // TODO, could use a third-party collection type that supports primitive keys.
+    private Map<String, VersionedFlowSnapshot> snapshotsById = new HashMap<>();
+
+    @ApiModelProperty("The name of the flow.")
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @ApiModelProperty("The timestamp of when the flow was first created.")
+    public long getCreatedTimestamp() {
+        return createdTimestamp;
+    }
+
+    public void setCreatedTimestamp(long timestamp) {
+        this.createdTimestamp = timestamp;
+    }
+
+    @ApiModelProperty("The timestamp of when the flow was last modified, e.g., when a new version was saved.")
+    public long getModifiedTimestamp() {
+        return modifiedTimestamp;
+    }
+
+    public void setModifiedTimestamp(long modifiedTimestamp) {
+        this.modifiedTimestamp = modifiedTimestamp;
+    }
+
+    @ApiModelProperty("A description of the flow.")
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public List<VersionedFlowSnapshot> getSnapshots() {
+        return snapshots;
+    }
+
+    public VersionedFlowSnapshot getSnapshot(String id) {
+        return snapshotsById.get(id);
+    }
+
+    public VersionedFlowSnapshot getSnapshot(int version) {
+        return snapshotsByVersion.get(Integer.valueOf(version));
+    }
+
+    /**
+     * Add a new snapshot version to this VersionedFlow.
+     *
+     * Note that this method has potential side effects.
+     * If a snapshot version number is not a positive integer,
+     * a new version number will be set as the current max version number + 1.
+     * If a snapshot ID is not set, a random UUID string will be set.
+     *
+     * @param snapshot  The snapshot to add to this versionedFlow
+     */
+    public void addVersionedFlowSnapshot(VersionedFlowSnapshot snapshot) {
+        if (snapshot == null) {
+            return;
+        }
+
+        int snapshotVersion = snapshot.getVersion();
+        if (snapshotVersion < 1) {
+            snapshotVersion = ++currentMaxVersion;
+            snapshot.setVersion(snapshotVersion);
+        } else if (snapshotsById.containsKey(Integer.valueOf(snapshotVersion))) {
+            throw new IllegalStateException("Unable to add snapshot to VersionedFlow with duplicate version number '" + snapshotVersion + "'.");
+        } else {
+            currentMaxVersion = (snapshotVersion > currentMaxVersion) ? snapshotVersion : currentMaxVersion;
+        }
+
+        String snapshotId = snapshot.getIdentifier();
+        if (snapshot.getIdentifier() == null) {
+            snapshotId = UUID.randomUUID().toString();
+            snapshot.setIdentifier(snapshotId);
+        }
+        if (snapshotsById.containsKey(snapshotId)) {
+            throw new IllegalStateException("Unable to add snapshot to VersionedFlow with duplicate ID '" + snapshotId + "'.");
+        }
+
+        snapshots.add(snapshot);
+        snapshotsByVersion.put(Integer.valueOf(snapshotVersion), snapshot);
+        snapshotsById.put(snapshotId, snapshot);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshot.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshot.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshot.java
index 2d7d440..875a26d 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshot.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshot.java
@@ -17,7 +17,8 @@
 
 package org.apache.nifi.registry.flow;
 
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 
 /**
  * <p>
@@ -27,6 +28,7 @@ import com.wordnik.swagger.annotations.ApiModelProperty;
  * version of the flow, the timestamp when it was saved, the contents of the flow, etc.
  * </p>
  */
+@ApiModel(value = "versionedFlowSnapshot")
 public class VersionedFlowSnapshot {
     private String identifier;
     private int version;
@@ -44,7 +46,7 @@ public class VersionedFlowSnapshot {
         this.identifier = identifier;
     }
 
-    @ApiModelProperty("The version of for this snapshot of the flow")
+    @ApiModelProperty("The version of this snapshot of the flow")
     public int getVersion() {
         return version;
     }

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedLabel.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedLabel.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedLabel.java
index ac0caa8..e7af4de 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedLabel.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedLabel.java
@@ -19,7 +19,7 @@ package org.apache.nifi.registry.flow;
 
 import java.util.Map;
 
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModelProperty;
 
 public class VersionedLabel extends VersionedComponent {
     private String label;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedPort.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedPort.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedPort.java
index 4163c04..f24e386 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedPort.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedPort.java
@@ -17,7 +17,7 @@
 
 package org.apache.nifi.registry.flow;
 
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModelProperty;
 
 public class VersionedPort extends VersionedComponent {
     private PortType type;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessGroup.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessGroup.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessGroup.java
index b51c914..9458cda 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessGroup.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessGroup.java
@@ -20,7 +20,7 @@ package org.apache.nifi.registry.flow;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModelProperty;
 
 
 public class VersionedProcessGroup extends VersionedComponent {

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessor.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessor.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessor.java
index 49405f2..4678726 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessor.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessor.java
@@ -20,7 +20,7 @@ package org.apache.nifi.registry.flow;
 import java.util.Map;
 import java.util.Set;
 
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModelProperty;
 
 public class VersionedProcessor extends VersionedComponent {
 

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteGroupPort.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteGroupPort.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteGroupPort.java
index a80e5e0..73b037e 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteGroupPort.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteGroupPort.java
@@ -19,7 +19,7 @@ package org.apache.nifi.registry.flow;
 
 import java.util.Objects;
 
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModelProperty;
 
 public class VersionedRemoteGroupPort extends VersionedComponent {
     private String groupId;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteProcessGroup.java
----------------------------------------------------------------------
diff --git a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteProcessGroup.java b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteProcessGroup.java
index 896c392..8417cfc 100644
--- a/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteProcessGroup.java
+++ b/nifi-registry-flow-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteProcessGroup.java
@@ -19,7 +19,7 @@ package org.apache.nifi.registry.flow;
 
 import java.util.Set;
 
-import com.wordnik.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiModelProperty;
 
 public class VersionedRemoteProcessGroup extends VersionedComponent {
     private String targetUri;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-web-api/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/pom.xml b/nifi-registry-web-api/pom.xml
index a7e58ae..b8925f5 100644
--- a/nifi-registry-web-api/pom.xml
+++ b/nifi-registry-web-api/pom.xml
@@ -24,6 +24,64 @@
     <artifactId>nifi-registry-web-api</artifactId>
     <version>0.0.1-SNAPSHOT</version>
     <packaging>war</packaging>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>com.github.kongchen</groupId>
+                <artifactId>swagger-maven-plugin</artifactId>
+                <version>3.1.5</version>
+                <executions>
+                    <execution>
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>generate</goal>
+                        </goals>
+                        <configuration>
+                            <apiSources>
+                                <apiSource>
+                                    <locations>
+                                        <location>org.apache.nifi.registry.web.api</location>
+                                    </locations>
+                                    <schemes>
+                                        <scheme>http</scheme>
+                                        <scheme>https</scheme>
+                                    </schemes>
+                                    <basePath>/nifi-registry-api</basePath>
+                                    <info>
+                                        <title>NiFi Registry REST API</title>
+                                        <version>${project.version}</version>
+                                        <description>
+                                            The Rest Api provides an interface to a registry with operations for saving, versioning, reading NiFi flows
+                                            and components.
+                                        </description>
+                                        <contact>
+                                            <name>Apache NiFi Registry</name>
+                                            <email>dev@nifi.apache.org</email>
+                                            <url>https://nifi.apache.org</url>
+                                        </contact>
+                                        <license>
+                                            <url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
+                                            <name>Apache 2.0 License</name>
+                                        </license>
+                                    </info>
+                                    <templatePath>classpath:/templates/index.html.hbs</templatePath>
+                                    <outputPath>${project.build.directory}/${project.artifactId}-${project.version}/docs/rest-api/index.html</outputPath>
+                                    <swaggerDirectory>${project.build.directory}/swagger-ui</swaggerDirectory>
+                                </apiSource>
+                            </apiSources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
     <dependencies>
         <dependency>
             <groupId>org.apache.nifi.registry</groupId>
@@ -57,5 +115,15 @@
             <groupId>org.glassfish.jersey.media</groupId>
             <artifactId>jersey-media-json-jackson</artifactId>
         </dependency>
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-annotations</artifactId>
+            <version>1.5.16</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi.registry</groupId>
+            <artifactId>nifi-registry-flow-data-model</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
     </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java
new file mode 100644
index 0000000..fc838fd
--- /dev/null
+++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java
@@ -0,0 +1,69 @@
+/*
+ * 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 with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     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.nifi.registry.web.api;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.nifi.registry.flow.VersionedFlow;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Path("/buckets/{bucketId}/flows")
+@Api(
+        value = "bucket >> flows",
+        description = "Create flows scoped to an existing bucket in the registry."
+)
+public class BucketFlowResource {
+
+    private static final Logger logger = LoggerFactory.getLogger(BucketFlowResource.class);
+
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Create a named flow and store it in the specified bucket. " +
+                    "The flow id is created by the server and a location URI for the created flow resource is returned.",
+            response = VersionedFlow.class
+    )
+    public Response createFlow(@PathParam("bucketId") String bucketId) {
+        // TODO implement createFlow
+        logger.error("This API functionality has not yet been implemented.");
+        return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+    }
+
+    /* TODO, add redirection URIs so that GET, PUT, DELETE operations for a given flow id (once created)
+     * are accessible as a subresource from /buckets as well */
+//    @GET
+//    @PathParam("/{bucketId}/flows/{flowSubpath}")
+//    @ApiOperation("Redirects to /flows/{flowSubpath}")
+//    public Response getFlowAlias(
+//            @PathParam("bucketId") String bucketId,
+//            @PathParam("flowSubpath") String flowSubpath) {
+//        logger.info("Redirecting flow operation on bucket resource handler to flow resource handler.");
+//        UriBuilder addressBuilder = uriInfo.getBaseUriBuilder();
+//        addressBuilder.path("flows/" + flowSubpath);
+//        return Response.seeOther(addressBuilder.build()).build();
+//    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketResource.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketResource.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketResource.java
new file mode 100644
index 0000000..fff1f2c
--- /dev/null
+++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketResource.java
@@ -0,0 +1,137 @@
+/*
+ * 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 with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     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.nifi.registry.web.api;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.apache.nifi.registry.flow.Bucket;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+@Path("/buckets")
+@Api(
+        value = "/buckets",
+        description = "Create named buckets in the registry to store NiFI objects such flows and extensions. " +
+                "Search for and retrieve existing buckets."
+)
+public class BucketResource {
+
+    private static final Logger logger = LoggerFactory.getLogger(BucketResource.class);
+
+    @Context
+    UriInfo uriInfo;
+
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Create a named bucket capable of storing NiFi bucket objects such as flows and extension bundles.",
+            response = Bucket.class
+    )
+    public Response createBucket(Bucket bucket) {
+        // TODO implement createBucket
+        logger.error("This API functionality has not yet been implemented.");
+        return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+    }
+
+    @GET
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Get metadata for all buckets in the registry for which the client is authorized. TODO: Will add some search parameters as well.",
+            response = Bucket.class,
+            responseContainer = "List"
+    )
+    public Response getBuckets() {
+        // TODO implement getBuckets
+        logger.error("This API functionality has not yet been implemented.");
+        return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+    }
+
+    @GET
+    @Path("{bucketId}")
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Get metadata for an existing bucket in the registry.",
+            response = Bucket.class
+    )
+    @ApiResponses(
+            value = {
+                    @ApiResponse(code = 404, message = "The specified resource could not be found."),
+            }
+    )
+    public Response getBucket(@PathParam("bucketId") String bucketId) {
+        // TODO implement getBucket
+        logger.error("This API functionality has not yet been implemented.");
+        return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+    }
+
+    @PUT
+    @Path("{bucketId}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Update the metadata for an existing bucket in the registry. Objects stored in the bucket will not be modified.",
+            response = Bucket.class
+    )
+    @ApiResponses(
+            value = {
+                    @ApiResponse(code = 404, message = "The specified resource could not be found."),
+            }
+    )
+    public Response updateBucket(@PathParam("bucketId") String bucketId) {
+        // TODO implement updateBucket
+        logger.error("This API functionality has not yet been implemented.");
+        return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+    }
+
+    @DELETE
+    @Path("{bucketId}")
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Delete an existing bucket in the registry, along with all the objects it is storing.",
+            response = Bucket.class
+    )
+    @ApiResponses(
+            value = {
+                    @ApiResponse(code = 404, message = "The specified resource could not be found."),
+            }
+    )
+    public Response deleteBucket(@PathParam("bucketId") String bucketId) {
+        // TODO implement deleteBucket
+        logger.error("This API functionality has not yet been implemented.");
+        return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/FlowResource.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/FlowResource.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/FlowResource.java
new file mode 100644
index 0000000..5ad934d
--- /dev/null
+++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/FlowResource.java
@@ -0,0 +1,202 @@
+/*
+ * 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 with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     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.nifi.registry.web.api;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.apache.nifi.registry.flow.VersionedFlow;
+import org.apache.nifi.registry.flow.VersionedFlowSnapshot;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Path("/flows")
+@Api(
+        value = "/flows",
+        description = "Create named flows that can be versioned. Search for and retrieve existing flows."
+)
+public class FlowResource {
+
+    private static final Logger logger = LoggerFactory.getLogger(FlowResource.class);
+
+    @GET
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Get metadata for all flows in all buckets that the registry has stored for which the client is authorized. TODO: Will add some search parameters as well.",
+            response = VersionedFlow.class,
+            responseContainer = "List"
+    )
+    public Response getFlows() {
+        // TODO implement getFlows
+        logger.error("This API functionality has not yet been implemented.");
+        return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+    }
+
+    @GET
+    @Path("/{flowId}")
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Get metadata for an existing flow the registry has stored.",
+            response = VersionedFlow.class
+    )
+    @ApiResponses(
+            value = {
+                    @ApiResponse(code = 404, message = "The specified resource could not be found."),
+            }
+    )
+    public Response getFlow(
+            @PathParam("flowId") String flowId) {
+        // TODO implement getFlow
+        logger.error("This API functionality has not yet been implemented.");
+        return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+    }
+
+    @PUT
+    @Path("/{flowId}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Update an existing flow the registry has stored.",
+            response = VersionedFlow.class
+    )
+    @ApiResponses(
+            value = {
+                    @ApiResponse(code = 404, message = "The specified resource could not be found."),
+            }
+    )
+    public Response updateFlow(
+            @PathParam("flowId") String flowId) {
+        // TODO implement updateFlow
+        logger.error("This API functionality has not yet been implemented.");
+        return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+    }
+
+    @DELETE
+    @Path("/{flowId}")
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Delete an existing flow the registry has stored.",
+            response = VersionedFlow.class
+    )
+    @ApiResponses(
+            value = {
+                    @ApiResponse(code = 404, message = "The specified resource could not be found."),
+            }
+    )
+    public Response deleteFlow(
+            @PathParam("flowId") String flowId) {
+        // TODO implement deleteFlow
+        logger.error("This API functionality has not yet been implemented.");
+        return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+    }
+
+    @POST
+    @Path("/{flowId}/versions")
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Create the next version of a given flow ID. " +
+            "The version number is created by the server and a location URI for the created version resource is returned.",
+            response = VersionedFlowSnapshot.class
+    )
+    public Response createFlowVersion(
+            @PathParam("flowId") String flowId) {
+        // TODO implement createFlowVersion
+        logger.error("This API functionality has not yet been implemented.");
+        return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+    }
+
+    @GET
+    @Path("/{flowId}/versions")
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Get summary of all versions of a flow for a given flow ID.",
+            response = VersionedFlowSnapshot.class, /* TODO, add a JSON serialization view for VersionedFlowSnapshot
+                                                       for this endpoint that  hides the flowContents property when
+                                                       this object is returned as part of a collection. */
+            responseContainer = "List"
+    )
+    @ApiResponses(
+            value = {
+                    @ApiResponse(code = 404, message = "The specified resource could not be found."),
+            }
+    )
+    public Response getFlowVersions(
+            @PathParam("flowId") String flowId) {
+        // TODO implement getFlowVersions
+        logger.error("This API functionality has not yet been implemented.");
+        return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+    }
+
+    @GET
+    @Path("/{flowId}/versions/latest")
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Get the latest version of a flow for a given flow ID",
+            response = VersionedFlowSnapshot.class
+    )
+    @ApiResponses(
+            value = {
+                    @ApiResponse(code = 404, message = "The specified resource could not be found."),
+            }
+    )
+    public Response getLatestFlowVersion(
+            @PathParam("flowId") String flowId) {
+        // TODO implement getLatestFlowVersion
+        logger.error("This API functionality has not yet been implemented.");
+        return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+    }
+
+    @GET
+    @Path("/{flowId}/versions/{versionNumber: \\d+}")
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Get a given version of a flow for a given flow ID",
+            response = VersionedFlowSnapshot.class
+    )
+    @ApiResponses(
+            value = {
+                    @ApiResponse(code = 404, message = "The specified resource could not be found."),
+            }
+    )
+    public Response getFlowVersion(
+            @PathParam("flowId") String flowId,
+            @PathParam("versionNumber") Integer versionNumber) {
+        // TODO implement getFlowVersion
+        logger.error("This API functionality has not yet been implemented.");
+        return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-web-api/src/main/resources/images/bgNifiLogo.png
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/resources/images/bgNifiLogo.png b/nifi-registry-web-api/src/main/resources/images/bgNifiLogo.png
new file mode 100644
index 0000000..2558d43
Binary files /dev/null and b/nifi-registry-web-api/src/main/resources/images/bgNifiLogo.png differ

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-web-api/src/main/resources/images/nifi16.ico
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/resources/images/nifi16.ico b/nifi-registry-web-api/src/main/resources/images/nifi16.ico
new file mode 100644
index 0000000..2ac3670
Binary files /dev/null and b/nifi-registry-web-api/src/main/resources/images/nifi16.ico differ

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-web-api/src/main/resources/templates/endpoint.hbs
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/resources/templates/endpoint.hbs b/nifi-registry-web-api/src/main/resources/templates/endpoint.hbs
new file mode 100644
index 0000000..6296862
--- /dev/null
+++ b/nifi-registry-web-api/src/main/resources/templates/endpoint.hbs
@@ -0,0 +1,61 @@
+{{!--
+    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 with
+    the License.  You may obtain a copy of the License at
+        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.
+--}}
+<div class="endpoints">
+    <span class="path hidden">{{@key}}</span>
+    {{#post}}
+        <div class="endpoint post">
+            <div class="operation-handle">
+                <div class="method">POST</div>
+                <div class="path mono"></div>
+                <div class="summary">{{summary}}</div>
+                <div class="clear"></div>
+            </div>
+            {{> operation}}
+        </div>
+    {{/post}}
+    {{#get}}
+        <div class="endpoint get">
+            <div class="operation-handle">
+                <div class="method">GET</div>
+                <div class="path mono"></div>
+                <div class="summary">{{summary}}</div>
+                <div class="clear"></div>
+            </div>
+            {{> operation}}
+        </div>
+    {{/get}}
+    {{#put}}
+        <div class="endpoint put">
+            <div class="operation-handle">
+                <div class="method">PUT</div>
+                <div class="path mono"></div>
+                <div class="summary">{{summary}}</div>
+                <div class="clear"></div>
+            </div>
+            {{> operation}}
+        </div>
+    {{/put}}
+    {{#delete}}
+        <div class="endpoint delete">
+            <div class="operation-handle">
+                <div class="method">DELETE</div>
+                <div class="path mono"></div>
+                <div class="summary">{{summary}}</div>
+                <div class="clear"></div>
+            </div>
+            {{> operation}}
+        </div>
+    {{/delete}}
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-web-api/src/main/resources/templates/example.hbs
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/resources/templates/example.hbs b/nifi-registry-web-api/src/main/resources/templates/example.hbs
new file mode 100644
index 0000000..26a4283
--- /dev/null
+++ b/nifi-registry-web-api/src/main/resources/templates/example.hbs
@@ -0,0 +1,18 @@
+{{!--
+    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 with
+    the License.  You may obtain a copy of the License at
+        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.
+--}}{{!-- formatting here matters... in whitespace: pre. this is not comprehensive but sufficent for our examples --}}
+{{#each properties}}    {{#ifeq type "string"}}"{{@key}}": "value"{{/ifeq}}{{#ifeq type "boolean"}}"{{@key}}": true{{/ifeq}}{{#ifeq type "integer"}}"{{@key}}": 0{{/ifeq}}{{#ifeq type "number"}}"{{@key}}": 0.0{{/ifeq}}{{#if $ref}}"{{@key}}": <span class="nested collapsed"><span class="nested-id hidden">{{basename $ref}}</span><span class="nested-example"><span class="open-object">&#123;&#8230;&#125;</span></span></span>{{/if}}{{#ifeq type "array"}}"{{@key}}": [{{#if items.$ref}}<span class="nested collapsed"><span class="nested-id hidden">{{basename items.$ref}}</span><span class="nested-example"><span class="open-object">&#123;&#8230;&#125;</span></span></span>{{else}}"value"{{/if}}]{{/ifeq}}{{#ifeq type "object"}}"{{@key}}": <span class="open-object">&#123;
+        "name": {{#if additionalProperties.$ref}}<span class="nested collapsed"><span class="nested-id hidden">{{basename additionalProperties.$ref}}</span><span class="nested-example"><span class="open-object">&#123;&#8230;&#125;</span></span></span>{{else}}{{#ifeq additionalProperties.type "integer"}}0{{else}}"value"{{/ifeq}}{{/if}}
+    &#125;</span>{{/ifeq}}<span class="comma">,</span>
+{{/each}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/a520c757/nifi-registry-web-api/src/main/resources/templates/index.html.hbs
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/resources/templates/index.html.hbs b/nifi-registry-web-api/src/main/resources/templates/index.html.hbs
new file mode 100644
index 0000000..595d470
--- /dev/null
+++ b/nifi-registry-web-api/src/main/resources/templates/index.html.hbs
@@ -0,0 +1,687 @@
+<!DOCTYPE html>
+<!--
+    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 with
+    the License.  You may obtain a copy of the License at
+        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.
+-->
+<html>
+    <head>
+        <title>{{info.title}}-{{info.version}}</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <link rel="shortcut icon" href="images/nifi16.ico"/>
+        <script type="text/javascript" src="../../nifi/assets/jquery/dist/jquery.min.js"></script>
+        <script type="text/javascript">
+            if (typeof window.jQuery === 'undefined') {
+                document.write(unescape('%3Cscript src="https://code.jquery.com/jquery-3.1.1.min.js" type="text/javascript" %3E%3C/script%3E'));
+            }
+        </script>
+        <style>
+            @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic|Noto+Serif:400,400italic,700,700italic|Droid+Sans+Mono:400";
+
+            html {
+                overflow-y: scroll;
+            }
+            
+            html, html a {
+                -webkit-font-smoothing: antialiased;
+                text-shadow: 1px 1px 1px rgba(0,0,0,0.004);
+            }
+
+            body {
+                width: 62.5em;
+                margin: 0 auto;
+                display: block;
+                font-family: "Open Sans", "DejaVu Sans", sans-serif;
+            }
+            
+            div.header {
+                margin-top: 10px;
+            }
+            
+            img.logo {
+                float: left;
+                margin-right: 10px;
+            }
+            
+            div.header > div.title {
+                font-size: 30px;
+                height: 50px;
+                line-height: 50px;
+            }
+            
+            .sub-title {
+                font-style: italic;
+                color: #aaa;
+            }
+            
+            div.overview {
+                margin-top: 10px;
+                margin-bottom: 15px;
+            }
+            
+            div.endpoint {
+                margin-bottom: 10px;
+            }
+
+            /* get */
+            
+            div.endpoint.get {
+                border: 1px solid #174961;
+            }
+            
+            div.get div.operation-handle {
+                background-color: rgba(23, 73, 97, .15);
+            }
+            
+            div.get div.method {
+                background-color: #174961;
+            }
+            
+            div.get div.operation {
+                border-top: 1px solid #174961;
+            }
+            
+            /* post */
+            
+            div.endpoint.post {
+                border: 1px solid #7298AC;
+            }
+            
+            div.post div.operation-handle {
+                background-color: rgba(114, 152, 172, .15);
+            }
+            
+            div.post div.method {
+                background-color: #7298AC;
+            }
+            
+            div.post div.operation {
+                border-top: 1px solid #7298AC;
+            }
+            
+            /* put */
+            
+            div.endpoint.put {
+                border: 1px solid #063046;
+            }
+            
+            div.put div.operation-handle {
+                background-color: rgba(6, 48, 70, .15);
+            }
+            
+            div.put div.method {
+                background-color: #063046;
+            }
+            
+            div.put div.operation {
+                border-top: 1px solid #063046;
+            }
+            
+            /* delete */
+            
+            div.endpoint.delete {
+                border: 1px solid #47758E;
+            }
+            
+            div.delete div.operation-handle {
+                background-color: rgba(71, 117, 142, .15);
+            }
+            
+            div.delete div.method {
+                background-color: #47758E;
+            }
+            
+            div.delete div.operation {
+                border-top: 1px solid #47758E;
+            }
+            
+            /* operations */
+            
+            div.operation-handle {
+                cursor: pointer;
+                padding-right: 5px;
+                height: 22px;
+            }
+            
+            div.method {
+                float: left;
+                width: 75px;
+                color: #fff;
+                text-align: center;
+                background-color: #7098ad;
+                margin-right: 10px;
+                font-weight: bold;
+            }
+
+            div.endpoint div.path {
+                float: left;
+                line-height: 22px;
+            }
+
+            div.summary {
+                float: right;
+                font-size: 12px;
+                line-height: 22px;
+            }
+
+            div.operation {
+                padding: 5px;
+                font-size: 12px;
+            }
+
+            div.operation > div.title {
+                font-weight: bold;
+                color: #000;
+            }
+            
+            div.operation > table {
+                margin-left: 5px;
+                margin-right: 5px;
+            }
+            
+            div.operation div.details {
+                margin-left: 5px;
+                margin-bottom: 5px;
+                color: #333;
+            }
+            
+            div.operation div.description {
+                margin-bottom: 10px;
+            }
+
+            div.mediatype {
+                line-height: 16px;
+            }
+
+            div.mediatype > div.title {
+                float: left;
+                width: 70px;
+            }
+            
+            div.mediatype div.title {
+                float: left;
+            }
+            
+            div.type {
+                position: fixed;
+                width: 800px;
+                height: 500px;
+                left: 50%;
+                top: 50%;
+                margin-left: -400px;
+                margin-top: -250px;
+                border: 3px solid #365C6A;
+                box-shadow: 4px 4px 6px rgba(0, 0, 0, 0.9);
+                padding: 10px;
+                background-color: #eee;
+                font-size: 12px;
+            }
+            
+            div.type-container {
+                overflow-y: auto;
+                height: 415px;
+                border-bottom: 1px solid #ccc;
+            }
+            
+            div.close {
+                border: 1px solid #aaa;
+                background-color: #ddd;
+                float: right;
+                margin-top: 10px;
+                font-weight: bold;
+                height: 25px;
+                line-height: 25px;
+                padding: 0 10px;
+                cursor: pointer;
+            }
+            
+            div.close:hover {
+                background-color: #d1d1d1;
+            }
+            
+            div.section-header > div.title {
+                font-size: 24px;
+                float: left;
+            }
+            
+            div.section-description {
+                float: right;
+                margin-top: 10px;
+            }
+            
+            div.section-endpoints {
+                margin-top: 10px;
+            }
+            
+            /* tables */
+
+            table {
+                background-color: #fefefe;
+                border: 1px solid #ccc;
+                border-left: 6px solid #ccc;
+                color: #555;
+                display: block;
+                margin-bottom: 12px;
+                padding: 5px 8px;
+            }
+            
+            table th {
+                font-weight: bold;
+                vertical-align:top;
+                text-align:left;
+                padding: 4px 15px;
+                border-width: 0;
+                white-space: nowrap;
+            }
+            
+            table td {
+                vertical-align:top;
+                text-align:left;
+                padding: 2px 15px;
+                border-width: 0;
+                white-space: nowrap;
+            }
+            
+            table td:last-child {
+                width: 99%;
+                white-space: normal;
+            }
+            
+            code.example {
+                background-color: #fefefe;
+                border: 1px solid #ccc;
+                border-left: 6px solid #ccc;
+                color: #555;
+                margin-bottom: 10px;
+                padding: 5px 8px;
+                white-space: pre;
+                display: block;
+                tab-size: 4;
+                -moz-tab-size: 4;
+                -o-tab-size: 4;
+                line-height: 20px
+            }
+            
+            span.nested.collapsed {
+                cursor: pointer;
+                border: 1px solid #7298AC;
+                background-color: rgba(114, 152, 172, .15);
+                padding: 1px;
+            }
+            
+            /* general */
+            
+            .mono {
+                font-family: monospace;
+            }
+            
+            div.clear {
+                clear: both;
+            }
+
+            .hidden {
+                display: none;
+            }
+            
+            a, .link {
+                cursor: pointer;
+                color: #1e373f;
+                font-weight: normal;
+            }
+            
+            a:hover, .link:hover {
+                color: #264c58;
+                text-decoration: underline;
+            }
+        </style>
+        <script type="text/javascript">
+            $(document).ready(function () {
+                // hide any open type dialogs
+                $('html').on('click', function() {
+                    $('div.type').hide();
+                }).on('keydown', function(e) {
+                    if (e.which === 27) {
+                        $('div.type').hide();
+                    }
+                });
+                
+                // populate all paths - this is necessary because the @key
+                // doesn't seem to reset after iterating through a nested 
+                // array or object
+                $('span.path').each(function() {
+                    var path = $(this);
+                    var endpoint = path.parent();
+                    endpoint.find('div.path').text(path.text());
+                });
+                
+                // toggles the visibility of a given operation
+                $('div.operation-handle').on('click', function () {
+                    $(this).next('div.operation').slideToggle();
+                });
+                
+                // add support for clicking to view the definition of a type
+                $('a.type-link').on('click', function(e) {
+                    // hide any previously shown dialogs
+                    $('div.type').hide();
+
+                    // show the type selected
+                    var link = $(this);
+                    var typeId = link.text();
+                    $('#' + typeId).show();
+                    e.stopPropagation();
+                });
+                
+                // prevent hiding when clicking on the type dialog
+                $('div.type').on('click', function(e) {
+                    e.stopPropagation();
+                });
+                
+                // due to lack of support for @last when iterating objects in 
+                // handlebars we need to remove the last comma from each example
+                $('code.example').find('span.comma:last').remove();
+                
+                // populate nested examples
+                $('code.example').on('click', 'span.nested', function(e) {
+                    var nested = $(this).removeClass('collapsed');
+                    var nestedId = nested.find('span.nested-id');
+                    var nestedExample = nested.find('span.nested-example');
+                    
+                    // get the id of the nested example
+                    var typeId = nestedId.text();
+                    var example = $('#' + typeId + ' code.example').html();
+                    var depth = nestedId.parents('span.open-object').length;
+                    
+                    // tab over as appropriate
+                    example = example.replace(/(\r\n|\r|\n)/g, function(match) {
+                        var tab = '\t';
+                        for (var i = 0; i < depth - 1; i++) {
+                            tab += '\t';
+                        }
+                        return match + tab;
+                    });
+                    
+                    // copy over the example
+                    nestedExample.html(example);
+                    e.stopPropagation();
+                });
+                
+                // handle close button
+                $('div.close').on('click', function() {
+                    $(this).closest('div.type').hide();
+                });
+                
+                // function for organizing the endpoints
+                var organizeEndpoints = function(term, container) {
+                    $('div.unorganized > div.endpoints').each(function() {
+                        var endpoints = $(this);
+                        var path = endpoints.find('div.path').text();
+                        
+                        if (term === null || path.indexOf(term) === 0) {
+                            endpoints.detach().appendTo(container);
+                        }
+                    });
+                };
+                
+                // organize the endpoints
+                organizeEndpoints('/process-groups', $('#process-group-endpoints'));
+                organizeEndpoints('/controller-services', $('#controller-service-endpoints'));
+                organizeEndpoints('/reporting-tasks', $('#reporting-task-endpoints'));
+                organizeEndpoints('/counters', $('#counter-endpoints'));
+                organizeEndpoints('/controller', $('#controller-endpoints'));
+                organizeEndpoints('/connections', $('#connection-endpoints'));
+                organizeEndpoints('/flowfile-queue', $('#flowfile-queue-endpoints'));
+                organizeEndpoints('/processors', $('#processor-endpoints'));
+                organizeEndpoints('/funnels', $('#funnel-endpoints'));
+                organizeEndpoints('/remote-process-groups', $('#remote-process-group-endpoints'));
+                organizeEndpoints('/input-ports', $('#input-port-endpoints'));
+                organizeEndpoints('/output-ports', $('#output-port-endpoints'));
+                organizeEndpoints('/labels', $('#label-endpoints'));
+                organizeEndpoints('/access', $('#access-endpoints'));
+                organizeEndpoints('/flow', $('#flow-endpoints'));
+                organizeEndpoints('/provenance-events', $('#provenance-event-endpoints'));
+                organizeEndpoints('/provenance', $('#provenance-endpoints'));
+                organizeEndpoints('/tenants', $('#tenant-endpoints'));
+                organizeEndpoints('/data-transfer', $('#data-transfer-endpoints'));
+                organizeEndpoints('/policies', $('#policy-endpoints'));
+                organizeEndpoints('/resources', $('#resource-endpoints'));
+                organizeEndpoints('/site-to-site', $('#site-to-site-endpoints'));
+                organizeEndpoints('/snippets', $('#snippet-endpoints'));
+                organizeEndpoints('/system', $('#system-diagnostic-endpoints'));
+                organizeEndpoints('/templates', $('#template-endpoints'));
+                organizeEndpoints(null, $('#controller-endpoints'));
+
+                // handle expanding/collapsing the sections
+                $('div.section-header > div.title').on('click', function() {
+                    $(this).parent('div.section-header').next('div.section-endpoints').slideToggle();
+                });
+            });
+        </script>
+    </head>
+    <body>
+        <div class="header">
+            <img class="logo" src="images/bgNifiLogo.png" alt="NiFi Logo"/>
+            <div class="title">{{basePath}}</div>
+            <div class="sub-title">{{info.title}} {{info.version}}</div>
+            <div class="clear"></div>
+        </div>
+        <div class="clear"></div>
+        <div class="overview">{{info.description}}</div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Access</div>
+                <div class="sub-title section-description">User authentication and token endpoints</div>
+                <div class="clear"></div>
+            </div>
+            <div id="access-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Controller</div>
+                <div class="sub-title section-description">Get controller configuration, Manage the cluster, Create reporting tasks</div>
+                <div class="clear"></div>
+            </div>
+            <div id="controller-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Controller Services</div>
+                <div class="sub-title section-description">Manage controller services, Update controller service references</div>
+                <div class="clear"></div>
+            </div>
+            <div id="controller-service-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Reporting Tasks</div>
+                <div class="sub-title section-description">Manage reporting tasks</div>
+                <div class="clear"></div>
+            </div>
+            <div id="reporting-task-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Counters</div>
+                <div class="sub-title section-description">Get counters, Reset counters</div>
+                <div class="clear"></div>
+            </div>
+            <div id="counter-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Flow</div>
+                <div class="sub-title section-description">Get the data flow, Obtain component status, Query history</div>
+                <div class="clear"></div>
+            </div>
+            <div id="flow-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Process Groups</div>
+                <div class="sub-title section-description">Create components, Instantiate a template, Upload a template</div>
+                <div class="clear"></div>
+            </div>
+            <div id="process-group-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Processors</div>
+                <div class="sub-title section-description">Create a processor, Set properties, Schedule</div>
+                <div class="clear"></div>
+            </div>
+            <div id="processor-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Connections</div>
+                <div class="sub-title section-description">Create a connection, Set queue priority, Update connection destination</div>
+                <div class="clear"></div>
+            </div>
+            <div id="connection-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">FlowFile Queues</div>
+                <div class="sub-title section-description">View queue contents, Download flowfile content, Empty queue</div>
+                <div class="clear"></div>
+            </div>
+            <div id="flowfile-queue-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Input Ports</div>
+                <div class="sub-title section-description">Create an input port, Set remote port access control</div>
+                <div class="clear"></div>
+            </div>
+            <div id="input-port-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Output Ports</div>
+                <div class="sub-title section-description">Create an output port, Set remote port access control</div>
+                <div class="clear"></div>
+            </div>
+            <div id="output-port-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Remote Process Groups</div>
+                <div class="sub-title section-description">Create a remote group, Enable transmission</div>
+                <div class="clear"></div>
+            </div>
+            <div id="remote-process-group-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Labels</div>
+                <div class="sub-title section-description">Create a label, Set label style</div>
+                <div class="clear"></div>
+            </div>
+            <div id="label-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Funnels</div>
+                <div class="sub-title section-description">Manage funnels</div>
+                <div class="clear"></div>
+            </div>
+            <div id="funnel-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Provenance</div>
+                <div class="sub-title section-description">Query provenance, Search event lineage</div>
+                <div class="clear"></div>
+            </div>
+            <div id="provenance-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Provenance Events</div>
+                <div class="sub-title section-description">Download content, Replay</div>
+                <div class="clear"></div>
+            </div>
+            <div id="provenance-event-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Tenants</div>
+                <div class="sub-title section-description">Add users and group, Group users</div>
+                <div class="clear"></div>
+            </div>
+            <div id="tenant-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Policies</div>
+                <div class="sub-title section-description">Get policies, Create policies</div>
+                <div class="clear"></div>
+            </div>
+            <div id="policy-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Resources</div>
+                <div class="sub-title section-description">Get resources</div>
+                <div class="clear"></div>
+            </div>
+            <div id="resource-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Site to Site</div>
+                <div class="sub-title section-description">Get available ports, Get peers</div>
+                <div class="clear"></div>
+            </div>
+            <div id="site-to-site-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Data Transfer</div>
+                <div class="sub-title section-description">Send data, Receive data</div>
+                <div class="clear"></div>
+            </div>
+            <div id="data-transfer-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Snippets</div>
+                <div class="sub-title section-description">Create a snippet, Move a snippet, Delete a snippet</div>
+                <div class="clear"></div>
+            </div>
+            <div id="snippet-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">Templates</div>
+                <div class="sub-title section-description">Download a template, Delete a template</div>
+                <div class="clear"></div>
+            </div>
+            <div id="template-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="section">
+            <div class="section-header">
+                <div class="title link">System Diagnostics</div>
+                <div class="sub-title section-description">Get system diagnostics</div>
+                <div class="clear"></div>
+            </div>
+            <div id="system-diagnostic-endpoints" class="section-endpoints hidden"></div>
+        </div>
+        <div class="unorganized hidden">
+            {{#each paths}}
+                {{> endpoint}}
+            {{/each}}
+        </div>
+        {{#each definitions}}
+            {{> type}}
+        {{/each}}
+    </body>
+</html>
\ No newline at end of file