You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by kd...@apache.org on 2018/09/22 02:11:44 UTC
[45/51] [partial] nifi-registry git commit: NIFIREG-201 Refactoring
project structure to better isolate extensions
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedConnection.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedConnection.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedConnection.java
new file mode 100644
index 0000000..52b7d70
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedConnection.java
@@ -0,0 +1,177 @@
+/*
+ * 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 java.util.List;
+import java.util.Set;
+
+import io.swagger.annotations.ApiModelProperty;
+
+public class VersionedConnection extends VersionedComponent {
+ private ConnectableComponent source;
+ private ConnectableComponent destination;
+ private Integer labelIndex;
+ private Long zIndex;
+ private Set<String> selectedRelationships;
+
+ private Long backPressureObjectThreshold;
+ private String backPressureDataSizeThreshold;
+ private String flowFileExpiration;
+ private List<String> prioritizers;
+ private List<Position> bends;
+
+ private String loadBalanceStrategy;
+ private String partitioningAttribute;
+ private String loadBalanceCompression;
+
+
+ @ApiModelProperty("The source of the connection.")
+ public ConnectableComponent getSource() {
+ return source;
+ }
+
+ public void setSource(ConnectableComponent source) {
+ this.source = source;
+ }
+
+ @ApiModelProperty("The destination of the connection.")
+ public ConnectableComponent getDestination() {
+ return destination;
+ }
+
+ public void setDestination(ConnectableComponent destination) {
+ this.destination = destination;
+ }
+
+ @ApiModelProperty("The bend points on the connection.")
+ public List<Position> getBends() {
+ return bends;
+ }
+
+ public void setBends(List<Position> bends) {
+ this.bends = bends;
+ }
+
+ @ApiModelProperty("The index of the bend point where to place the connection label.")
+ public Integer getLabelIndex() {
+ return labelIndex;
+ }
+
+ public void setLabelIndex(Integer labelIndex) {
+ this.labelIndex = labelIndex;
+ }
+
+ @ApiModelProperty(
+ value = "The z index of the connection.",
+ name = "zIndex") // Jackson maps this method name to JSON key "zIndex", but Swagger does not by default
+ public Long getzIndex() {
+ return zIndex;
+ }
+
+ public void setzIndex(Long zIndex) {
+ this.zIndex = zIndex;
+ }
+
+ @ApiModelProperty("The selected relationship that comprise the connection.")
+ public Set<String> getSelectedRelationships() {
+ return selectedRelationships;
+ }
+
+ public void setSelectedRelationships(Set<String> relationships) {
+ this.selectedRelationships = relationships;
+ }
+
+
+ @ApiModelProperty("The object count threshold for determining when back pressure is applied. Updating this value is a passive change in the sense that it won't impact whether existing files "
+ + "over the limit are affected but it does help feeder processors to stop pushing too much into this work queue.")
+ public Long getBackPressureObjectThreshold() {
+ return backPressureObjectThreshold;
+ }
+
+ public void setBackPressureObjectThreshold(Long backPressureObjectThreshold) {
+ this.backPressureObjectThreshold = backPressureObjectThreshold;
+ }
+
+
+ @ApiModelProperty("The object data size threshold for determining when back pressure is applied. Updating this value is a passive change in the sense that it won't impact whether existing "
+ + "files over the limit are affected but it does help feeder processors to stop pushing too much into this work queue.")
+ public String getBackPressureDataSizeThreshold() {
+ return backPressureDataSizeThreshold;
+ }
+
+ public void setBackPressureDataSizeThreshold(String backPressureDataSizeThreshold) {
+ this.backPressureDataSizeThreshold = backPressureDataSizeThreshold;
+ }
+
+
+ @ApiModelProperty("The amount of time a flow file may be in the flow before it will be automatically aged out of the flow. Once a flow file reaches this age it will be terminated from "
+ + "the flow the next time a processor attempts to start work on it.")
+ public String getFlowFileExpiration() {
+ return flowFileExpiration;
+ }
+
+ public void setFlowFileExpiration(String flowFileExpiration) {
+ this.flowFileExpiration = flowFileExpiration;
+ }
+
+
+ @ApiModelProperty("The comparators used to prioritize the queue.")
+ public List<String> getPrioritizers() {
+ return prioritizers;
+ }
+
+ public void setPrioritizers(List<String> prioritizers) {
+ this.prioritizers = prioritizers;
+ }
+
+ @ApiModelProperty(value = "The Strategy to use for load balancing data across the cluster, or null, if no Load Balance Strategy has been specified.",
+ allowableValues = "DO_NOT_LOAD_BALANCE, PARTITION_BY_ATTRIBUTE, ROUND_ROBIN, SINGLE_NODE")
+ public String getLoadBalanceStrategy() {
+ return loadBalanceStrategy;
+ }
+
+ public void setLoadBalanceStrategy(String loadBalanceStrategy) {
+ this.loadBalanceStrategy = loadBalanceStrategy;
+ }
+
+ @ApiModelProperty("The attribute to use for partitioning data as it is load balanced across the cluster. If the Load Balance Strategy is configured to use PARTITION_BY_ATTRIBUTE, the value " +
+ "returned by this method is the name of the FlowFile Attribute that will be used to determine which node in the cluster should receive a given FlowFile. If the Load Balance Strategy is " +
+ "unset or is set to any other value, the Partitioning Attribute has no effect.")
+ public String getPartitioningAttribute() {
+ return partitioningAttribute;
+ }
+
+ public void setPartitioningAttribute(final String partitioningAttribute) {
+ this.partitioningAttribute = partitioningAttribute;
+ }
+
+ @ApiModelProperty(value = "Whether or not compression should be used when transferring FlowFiles between nodes",
+ allowableValues = "DO_NOT_COMPRESS, COMPRESS_ATTRIBUTES_ONLY, COMPRESS_ATTRIBUTES_AND_CONTENT")
+ public String getLoadBalanceCompression() {
+ return loadBalanceCompression;
+ }
+
+ public void setLoadBalanceCompression(final String compression) {
+ this.loadBalanceCompression = compression;
+ }
+
+ @Override
+ public ComponentType getComponentType() {
+ return ComponentType.CONNECTION;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedControllerService.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedControllerService.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedControllerService.java
new file mode 100644
index 0000000..7b14ac2
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedControllerService.java
@@ -0,0 +1,103 @@
+/*
+ * 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 java.util.List;
+import java.util.Map;
+
+import io.swagger.annotations.ApiModelProperty;
+
+public class VersionedControllerService extends VersionedComponent
+ implements VersionedConfigurableComponent, VersionedExtensionComponent {
+
+ private String type;
+ private Bundle bundle;
+ private List<ControllerServiceAPI> controllerServiceApis;
+
+ private Map<String, String> properties;
+ private Map<String, VersionedPropertyDescriptor> propertyDescriptors;
+ private String annotationData;
+
+
+ @Override
+ @ApiModelProperty(value = "The type of the controller service.")
+ public String getType() {
+ return type;
+ }
+
+ @Override
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ @Override
+ @ApiModelProperty(value = "The details of the artifact that bundled this processor type.")
+ public Bundle getBundle() {
+ return bundle;
+ }
+
+ @Override
+ public void setBundle(Bundle bundle) {
+ this.bundle = bundle;
+ }
+
+ @ApiModelProperty(value = "Lists the APIs this Controller Service implements.")
+ public List<ControllerServiceAPI> getControllerServiceApis() {
+ return controllerServiceApis;
+ }
+
+ public void setControllerServiceApis(List<ControllerServiceAPI> controllerServiceApis) {
+ this.controllerServiceApis = controllerServiceApis;
+ }
+
+ @Override
+ @ApiModelProperty(value = "The properties of the controller service.")
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+
+ @Override
+ public void setProperties(Map<String, String> properties) {
+ this.properties = properties;
+ }
+
+ @Override
+ @ApiModelProperty("The property descriptors for the processor.")
+ public Map<String, VersionedPropertyDescriptor> getPropertyDescriptors() {
+ return propertyDescriptors;
+ }
+
+ @Override
+ public void setPropertyDescriptors(Map<String, VersionedPropertyDescriptor> propertyDescriptors) {
+ this.propertyDescriptors = propertyDescriptors;
+ }
+
+ @ApiModelProperty(value = "The annotation for the controller service. This is how the custom UI relays configuration to the controller service.")
+ public String getAnnotationData() {
+ return annotationData;
+ }
+
+ public void setAnnotationData(String annotationData) {
+ this.annotationData = annotationData;
+ }
+
+ @Override
+ public ComponentType getComponentType() {
+ return ComponentType.CONTROLLER_SERVICE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedExtensionComponent.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedExtensionComponent.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedExtensionComponent.java
new file mode 100644
index 0000000..e1d514c
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedExtensionComponent.java
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+/**
+ * A component that is an extension and has a type and bundle.
+ */
+public interface VersionedExtensionComponent {
+
+ Bundle getBundle();
+
+ void setBundle(Bundle bundle);
+
+ String getType();
+
+ void setType(String type);
+
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlow.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlow.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlow.java
new file mode 100644
index 0000000..6ece46a
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlow.java
@@ -0,0 +1,56 @@
+/*
+ * 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 org.apache.nifi.registry.bucket.BucketItem;
+import org.apache.nifi.registry.bucket.BucketItemType;
+
+import javax.validation.constraints.Min;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * <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
+ */
+@XmlRootElement
+@ApiModel(value = "versionedFlow")
+public class VersionedFlow extends BucketItem {
+
+ @Min(0)
+ private long versionCount;
+
+ public VersionedFlow() {
+ super(BucketItemType.Flow);
+ }
+
+ @ApiModelProperty(value = "The number of versions of this flow.", readOnly = true)
+ public long getVersionCount() {
+ return versionCount;
+ }
+
+ public void setVersionCount(long versionCount) {
+ this.versionCount = versionCount;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowCoordinates.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowCoordinates.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowCoordinates.java
new file mode 100644
index 0000000..8e39c5b
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowCoordinates.java
@@ -0,0 +1,101 @@
+/*
+ * 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 java.util.Objects;
+
+import io.swagger.annotations.ApiModelProperty;
+
+public class VersionedFlowCoordinates {
+ private String registryUrl;
+ private String bucketId;
+ private String flowId;
+ private int version;
+ private Boolean latest;
+
+ @ApiModelProperty("The URL of the Flow Registry that contains the flow")
+ public String getRegistryUrl() {
+ return registryUrl;
+ }
+
+ public void setRegistryUrl(String registryUrl) {
+ this.registryUrl = registryUrl;
+ }
+
+ @ApiModelProperty("The UUID of the bucket that the flow resides in")
+ public String getBucketId() {
+ return bucketId;
+ }
+
+ public void setBucketId(String bucketId) {
+ this.bucketId = bucketId;
+ }
+
+ @ApiModelProperty("The UUID of the flow")
+ public String getFlowId() {
+ return flowId;
+ }
+
+ public void setFlowId(String flowId) {
+ this.flowId = flowId;
+ }
+
+ @ApiModelProperty("The version of the flow")
+ public int getVersion() {
+ return version;
+ }
+
+ public void setVersion(int version) {
+ this.version = version;
+ }
+
+ @ApiModelProperty("Whether or not these coordinates point to the latest version of the flow")
+ public Boolean getLatest() {
+ return latest;
+ }
+
+ public void setLatest(Boolean latest) {
+ this.latest = latest;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(registryUrl, bucketId, flowId, version);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof VersionedFlowCoordinates)) {
+ return false;
+ }
+
+ final VersionedFlowCoordinates other = (VersionedFlowCoordinates) obj;
+ return Objects.equals(registryUrl, other.registryUrl) && Objects.equals(bucketId, other.bucketId) && Objects.equals(flowId, other.flowId) && Objects.equals(version, other.version);
+ }
+
+ @Override
+ public String toString() {
+ return "VersionedFlowCoordinates[bucketId=" + bucketId + ", flowId=" + flowId + ", version=" + version + ", registryUrl=" + registryUrl + "]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshot.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshot.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshot.java
new file mode 100644
index 0000000..bc82397
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshot.java
@@ -0,0 +1,128 @@
+/*
+ * 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 org.apache.nifi.registry.bucket.Bucket;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import java.util.Objects;
+
+/**
+ * <p>
+ * Represents a snapshot of a versioned flow. A versioned flow may change many times
+ * over the course of its life. Each of these versions that is saved to the registry
+ * is saved as a snapshot, representing information such as the name of the flow, the
+ * version of the flow, the timestamp when it was saved, the contents of the flow, etc.
+ * </p>
+ */
+@ApiModel(value = "versionedFlowSnapshot")
+@XmlRootElement
+public class VersionedFlowSnapshot {
+
+ @Valid
+ @NotNull
+ private VersionedFlowSnapshotMetadata snapshotMetadata;
+
+ @Valid
+ @NotNull
+ private VersionedProcessGroup flowContents;
+
+ // read-only, only populated from retrieval of a snapshot
+ private VersionedFlow flow;
+
+ // read-only, only populated from retrieval of a snapshot
+ private Bucket bucket;
+
+
+ @ApiModelProperty(value = "The metadata for this snapshot", required = true)
+ public VersionedFlowSnapshotMetadata getSnapshotMetadata() {
+ return snapshotMetadata;
+ }
+
+ public void setSnapshotMetadata(VersionedFlowSnapshotMetadata snapshotMetadata) {
+ this.snapshotMetadata = snapshotMetadata;
+ }
+
+ @ApiModelProperty(value = "The contents of the versioned flow", required = true)
+ public VersionedProcessGroup getFlowContents() {
+ return flowContents;
+ }
+
+ public void setFlowContents(VersionedProcessGroup flowContents) {
+ this.flowContents = flowContents;
+ }
+
+ @ApiModelProperty(value = "The flow this snapshot is for", readOnly = true)
+ public VersionedFlow getFlow() {
+ return flow;
+ }
+
+ public void setFlow(VersionedFlow flow) {
+ this.flow = flow;
+ }
+
+ @ApiModelProperty(value = "The bucket where the flow is located", readOnly = true)
+ public Bucket getBucket() {
+ return bucket;
+ }
+
+ public void setBucket(Bucket bucket) {
+ this.bucket = bucket;
+ }
+
+ /**
+ * This is a convenience method that will return true when flow is populated and when the flow's versionCount
+ * is equal to the version of this snapshot.
+ *
+ * @return true if flow is populated and if this snapshot is the latest version for the flow at the time of retrieval
+ */
+ @XmlTransient
+ public boolean isLatest() {
+ return flow != null && snapshotMetadata != null && flow.getVersionCount() == getSnapshotMetadata().getVersion();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.snapshotMetadata);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ final VersionedFlowSnapshot other = (VersionedFlowSnapshot) obj;
+ return Objects.equals(this.snapshotMetadata, other.snapshotMetadata);
+ }
+
+ @Override
+ public String toString() {
+ final String flowName = (flow == null ? "null" : flow.getName());
+ return "VersionedFlowSnapshot[flowId=" + snapshotMetadata.getFlowIdentifier() + ", flowName=" + flowName
+ + ", version=" + snapshotMetadata.getVersion() + ", comments=" + snapshotMetadata.getComments() + "]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshotMetadata.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshotMetadata.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshotMetadata.java
new file mode 100644
index 0000000..2007279
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshotMetadata.java
@@ -0,0 +1,130 @@
+/*
+ * 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 org.apache.nifi.registry.link.LinkableEntity;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import java.util.Objects;
+
+/**
+ * The metadata information about a VersionedFlowSnapshot. This class implements Comparable in order
+ * to sort based on the snapshot version in ascending order.
+ */
+@ApiModel(value = "versionedFlowSnapshotMetadata")
+public class VersionedFlowSnapshotMetadata extends LinkableEntity implements Comparable<VersionedFlowSnapshotMetadata> {
+
+ @NotBlank
+ private String bucketIdentifier;
+
+ @NotBlank
+ private String flowIdentifier;
+
+ @Min(1)
+ private int version;
+
+ @Min(1)
+ private long timestamp;
+
+ @NotBlank
+ private String author;
+
+ private String comments;
+
+
+ @ApiModelProperty(value = "The identifier of the bucket this snapshot belongs to.", required = true)
+ public String getBucketIdentifier() {
+ return bucketIdentifier;
+ }
+
+ public void setBucketIdentifier(String bucketIdentifier) {
+ this.bucketIdentifier = bucketIdentifier;
+ }
+
+ @ApiModelProperty(value = "The identifier of the flow this snapshot belongs to.", required = true)
+ public String getFlowIdentifier() {
+ return flowIdentifier;
+ }
+
+ public void setFlowIdentifier(String flowIdentifier) {
+ this.flowIdentifier = flowIdentifier;
+ }
+
+ @ApiModelProperty(value = "The version of this snapshot of the flow.", required = true)
+ public int getVersion() {
+ return version;
+ }
+
+ public void setVersion(int version) {
+ this.version = version;
+ }
+
+ @ApiModelProperty(value = "The timestamp when the flow was saved, as milliseconds since epoch.", readOnly = true)
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ @ApiModelProperty(value = "The user that created this snapshot of the flow.", readOnly = true)
+ public String getAuthor() {
+ return author;
+ }
+
+ public void setAuthor(String author) {
+ this.author = author;
+ }
+
+ @ApiModelProperty("The comments provided by the user when creating the snapshot.")
+ public String getComments() {
+ return comments;
+ }
+
+ public void setComments(String comments) {
+ this.comments = comments;
+ }
+
+ @Override
+ public int compareTo(final VersionedFlowSnapshotMetadata o) {
+ return o == null ? -1 : Integer.compare(version, o.version);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.flowIdentifier, Integer.valueOf(this.version));
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ final VersionedFlowSnapshotMetadata other = (VersionedFlowSnapshotMetadata) obj;
+
+ return Objects.equals(this.flowIdentifier, other.flowIdentifier)
+ && Objects.equals(this.version, other.version);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFunnel.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFunnel.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFunnel.java
new file mode 100644
index 0000000..871dafc
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFunnel.java
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+public class VersionedFunnel extends VersionedComponent {
+ @Override
+ public ComponentType getComponentType() {
+ return ComponentType.FUNNEL;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedLabel.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedLabel.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedLabel.java
new file mode 100644
index 0000000..f2f7887
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedLabel.java
@@ -0,0 +1,73 @@
+/*
+ * 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 java.util.Map;
+
+import io.swagger.annotations.ApiModelProperty;
+
+public class VersionedLabel extends VersionedComponent {
+ private String label;
+
+ private Double width;
+ private Double height;
+
+ private Map<String, String> style;
+
+
+ @ApiModelProperty("The text that appears in the label.")
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(final String label) {
+ this.label = label;
+ }
+
+ @ApiModelProperty("The styles for this label (font-size : 12px, background-color : #eee, etc).")
+ public Map<String, String> getStyle() {
+ return style;
+ }
+
+ public void setStyle(final Map<String, String> style) {
+ this.style = style;
+ }
+
+ @ApiModelProperty("The height of the label in pixels when at a 1:1 scale.")
+ public Double getHeight() {
+ return height;
+ }
+
+ public void setHeight(Double height) {
+ this.height = height;
+ }
+
+ @ApiModelProperty("The width of the label in pixels when at a 1:1 scale.")
+ public Double getWidth() {
+ return width;
+ }
+
+ public void setWidth(Double width) {
+ this.width = width;
+ }
+
+ @Override
+ public ComponentType getComponentType() {
+ return ComponentType.LABEL;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedPort.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedPort.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedPort.java
new file mode 100644
index 0000000..f24e386
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedPort.java
@@ -0,0 +1,52 @@
+/*
+ * 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.ApiModelProperty;
+
+public class VersionedPort extends VersionedComponent {
+ private PortType type;
+ private Integer concurrentlySchedulableTaskCount;
+
+ @ApiModelProperty("The number of tasks that should be concurrently scheduled for the port.")
+ public Integer getConcurrentlySchedulableTaskCount() {
+ return concurrentlySchedulableTaskCount;
+ }
+
+ public void setConcurrentlySchedulableTaskCount(Integer concurrentlySchedulableTaskCount) {
+ this.concurrentlySchedulableTaskCount = concurrentlySchedulableTaskCount;
+ }
+
+ @ApiModelProperty("The type of port.")
+ public PortType getType() {
+ return type;
+ }
+
+ public void setType(PortType type) {
+ this.type = type;
+ }
+
+ @Override
+ public ComponentType getComponentType() {
+ if (type == PortType.OUTPUT_PORT) {
+ return ComponentType.OUTPUT_PORT;
+ }
+
+ return ComponentType.INPUT_PORT;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessGroup.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessGroup.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessGroup.java
new file mode 100644
index 0000000..2acd0a4
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessGroup.java
@@ -0,0 +1,148 @@
+/*
+ * 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 java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import io.swagger.annotations.ApiModelProperty;
+
+@XmlRootElement
+public class VersionedProcessGroup extends VersionedComponent {
+
+ private Set<VersionedProcessGroup> processGroups = new HashSet<>();
+ private Set<VersionedRemoteProcessGroup> remoteProcessGroups = new HashSet<>();
+ private Set<VersionedProcessor> processors = new HashSet<>();
+ private Set<VersionedPort> inputPorts = new HashSet<>();
+ private Set<VersionedPort> outputPorts = new HashSet<>();
+ private Set<VersionedConnection> connections = new HashSet<>();
+ private Set<VersionedLabel> labels = new HashSet<>();
+ private Set<VersionedFunnel> funnels = new HashSet<>();
+ private Set<VersionedControllerService> controllerServices = new HashSet<>();
+ private VersionedFlowCoordinates versionedFlowCoordinates = null;
+
+ private Map<String, String> variables = new HashMap<>();
+
+ @ApiModelProperty("The child Process Groups")
+ public Set<VersionedProcessGroup> getProcessGroups() {
+ return processGroups;
+ }
+
+ public void setProcessGroups(Set<VersionedProcessGroup> processGroups) {
+ this.processGroups = new HashSet<>(processGroups);
+ }
+
+ @ApiModelProperty("The Remote Process Groups")
+ public Set<VersionedRemoteProcessGroup> getRemoteProcessGroups() {
+ return remoteProcessGroups;
+ }
+
+ public void setRemoteProcessGroups(Set<VersionedRemoteProcessGroup> remoteProcessGroups) {
+ this.remoteProcessGroups = new HashSet<>(remoteProcessGroups);
+ }
+
+ @ApiModelProperty("The Processors")
+ public Set<VersionedProcessor> getProcessors() {
+ return processors;
+ }
+
+ public void setProcessors(Set<VersionedProcessor> processors) {
+ this.processors = new HashSet<>(processors);
+ }
+
+ @ApiModelProperty("The Input Ports")
+ public Set<VersionedPort> getInputPorts() {
+ return inputPorts;
+ }
+
+ public void setInputPorts(Set<VersionedPort> inputPorts) {
+ this.inputPorts = new HashSet<>(inputPorts);
+ }
+
+ @ApiModelProperty("The Output Ports")
+ public Set<VersionedPort> getOutputPorts() {
+ return outputPorts;
+ }
+
+ public void setOutputPorts(Set<VersionedPort> outputPorts) {
+ this.outputPorts = new HashSet<>(outputPorts);
+ }
+
+ @ApiModelProperty("The Connections")
+ public Set<VersionedConnection> getConnections() {
+ return connections;
+ }
+
+ public void setConnections(Set<VersionedConnection> connections) {
+ this.connections = new HashSet<>(connections);
+ }
+
+ @ApiModelProperty("The Labels")
+ public Set<VersionedLabel> getLabels() {
+ return labels;
+ }
+
+ public void setLabels(Set<VersionedLabel> labels) {
+ this.labels = new HashSet<>(labels);
+ }
+
+ @ApiModelProperty("The Funnels")
+ public Set<VersionedFunnel> getFunnels() {
+ return funnels;
+ }
+
+ public void setFunnels(Set<VersionedFunnel> funnels) {
+ this.funnels = new HashSet<>(funnels);
+ }
+
+ @ApiModelProperty("The Controller Services")
+ public Set<VersionedControllerService> getControllerServices() {
+ return controllerServices;
+ }
+
+ public void setControllerServices(Set<VersionedControllerService> controllerServices) {
+ this.controllerServices = new HashSet<>(controllerServices);
+ }
+
+ @Override
+ public ComponentType getComponentType() {
+ return ComponentType.PROCESS_GROUP;
+ }
+
+ public void setVariables(Map<String, String> variables) {
+ this.variables = variables;
+ }
+
+ @ApiModelProperty("The Variables in the Variable Registry for this Process Group (not including any ancestor or descendant Process Groups)")
+ public Map<String, String> getVariables() {
+ return variables;
+ }
+
+ public void setVersionedFlowCoordinates(VersionedFlowCoordinates flowCoordinates) {
+ this.versionedFlowCoordinates = flowCoordinates;
+ }
+
+ @ApiModelProperty("The coordinates where the remote flow is stored, or null if the Process Group is not directly under Version Control")
+ public VersionedFlowCoordinates getVersionedFlowCoordinates() {
+ return versionedFlowCoordinates;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessor.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessor.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessor.java
new file mode 100644
index 0000000..aef6dcc
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedProcessor.java
@@ -0,0 +1,197 @@
+/*
+ * 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 java.util.Map;
+import java.util.Set;
+
+import io.swagger.annotations.ApiModelProperty;
+
+public class VersionedProcessor extends VersionedComponent
+ implements VersionedConfigurableComponent, VersionedExtensionComponent {
+
+ private Bundle bundle;
+ private Map<String, String> style;
+
+ private String type;
+ private Map<String, String> properties;
+ private Map<String, VersionedPropertyDescriptor> propertyDescriptors;
+ private String annotationData;
+
+ private String schedulingPeriod;
+ private String schedulingStrategy;
+ private String executionNode;
+ private String penaltyDuration;
+ private String yieldDuration;
+ private String bulletinLevel;
+ private Long runDurationMillis;
+ private Integer concurrentlySchedulableTaskCount;
+ private Set<String> autoTerminatedRelationships;
+
+
+ @ApiModelProperty("The frequency with which to schedule the processor. The format of the value will depend on th value of schedulingStrategy.")
+ public String getSchedulingPeriod() {
+ return schedulingPeriod;
+ }
+
+ public void setSchedulingPeriod(String setSchedulingPeriod) {
+ this.schedulingPeriod = setSchedulingPeriod;
+ }
+
+ @ApiModelProperty("Indcates whether the prcessor should be scheduled to run in event or timer driven mode.")
+ public String getSchedulingStrategy() {
+ return schedulingStrategy;
+ }
+
+ public void setSchedulingStrategy(String schedulingStrategy) {
+ this.schedulingStrategy = schedulingStrategy;
+ }
+
+ @Override
+ @ApiModelProperty("The type of Processor")
+ public String getType() {
+ return type;
+ }
+
+ @Override
+ public void setType(final String type) {
+ this.type = type;
+ }
+
+ @ApiModelProperty("Indicates the node where the process will execute.")
+ public String getExecutionNode() {
+ return executionNode;
+ }
+
+ public void setExecutionNode(String executionNode) {
+ this.executionNode = executionNode;
+ }
+
+ @ApiModelProperty("The amout of time that is used when the process penalizes a flowfile.")
+ public String getPenaltyDuration() {
+ return penaltyDuration;
+ }
+
+ public void setPenaltyDuration(String penaltyDuration) {
+ this.penaltyDuration = penaltyDuration;
+ }
+
+ @ApiModelProperty("The amount of time that must elapse before this processor is scheduled again after yielding.")
+ public String getYieldDuration() {
+ return yieldDuration;
+ }
+
+ public void setYieldDuration(String yieldDuration) {
+ this.yieldDuration = yieldDuration;
+ }
+
+ @ApiModelProperty("The level at which the processor will report bulletins.")
+ public String getBulletinLevel() {
+ return bulletinLevel;
+ }
+
+ public void setBulletinLevel(String bulletinLevel) {
+ this.bulletinLevel = bulletinLevel;
+ }
+
+ @ApiModelProperty("The number of tasks that should be concurrently schedule for the processor. If the processor doesn't allow parallol processing then any positive input will be ignored.")
+ public Integer getConcurrentlySchedulableTaskCount() {
+ return concurrentlySchedulableTaskCount;
+ }
+
+ public void setConcurrentlySchedulableTaskCount(Integer concurrentlySchedulableTaskCount) {
+ this.concurrentlySchedulableTaskCount = concurrentlySchedulableTaskCount;
+ }
+
+ @Override
+ @ApiModelProperty("The properties for the processor. Properties whose value is not set will only contain the property name.")
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+
+ @Override
+ public void setProperties(Map<String, String> properties) {
+ this.properties = properties;
+ }
+
+ @Override
+ @ApiModelProperty("The property descriptors for the processor.")
+ public Map<String, VersionedPropertyDescriptor> getPropertyDescriptors() {
+ return propertyDescriptors;
+ }
+
+ @Override
+ public void setPropertyDescriptors(Map<String, VersionedPropertyDescriptor> propertyDescriptors) {
+ this.propertyDescriptors = propertyDescriptors;
+ }
+
+ @ApiModelProperty("The annotation data for the processor used to relay configuration between a custom UI and the procesosr.")
+ public String getAnnotationData() {
+ return annotationData;
+ }
+
+ public void setAnnotationData(String annotationData) {
+ this.annotationData = annotationData;
+ }
+
+
+ @ApiModelProperty("The names of all relationships that cause a flow file to be terminated if the relationship is not connected elsewhere. This property differs "
+ + "from the 'isAutoTerminate' property of the RelationshipDTO in that the RelationshipDTO is meant to depict the current configuration, whereas this "
+ + "property can be set in a DTO when updating a Processor in order to change which Relationships should be auto-terminated.")
+ public Set<String> getAutoTerminatedRelationships() {
+ return autoTerminatedRelationships;
+ }
+
+ public void setAutoTerminatedRelationships(final Set<String> autoTerminatedRelationships) {
+ this.autoTerminatedRelationships = autoTerminatedRelationships;
+ }
+
+ @ApiModelProperty("The run duration for the processor in milliseconds.")
+ public Long getRunDurationMillis() {
+ return runDurationMillis;
+ }
+
+ public void setRunDurationMillis(Long runDurationMillis) {
+ this.runDurationMillis = runDurationMillis;
+ }
+
+ @Override
+ @ApiModelProperty("Information about the bundle from which the component came")
+ public Bundle getBundle() {
+ return bundle;
+ }
+
+ @Override
+ public void setBundle(Bundle bundle) {
+ this.bundle = bundle;
+ }
+
+ @ApiModelProperty("Stylistic data for rendering in a UI")
+ public Map<String, String> getStyle() {
+ return style;
+ }
+
+ public void setStyle(Map<String, String> style) {
+ this.style = style;
+ }
+
+ @Override
+ public ComponentType getComponentType() {
+ return ComponentType.PROCESSOR;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedPropertyDescriptor.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedPropertyDescriptor.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedPropertyDescriptor.java
new file mode 100644
index 0000000..2fa9463
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedPropertyDescriptor.java
@@ -0,0 +1,63 @@
+/*
+ * 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.ApiModelProperty;
+
+public class VersionedPropertyDescriptor {
+ private String name;
+ private String displayName;
+ private boolean identifiesControllerService;
+ private boolean sensitive;
+
+ @ApiModelProperty("The name of the property")
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @ApiModelProperty("The display name of the property")
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
+
+ @ApiModelProperty("Whether or not the property provides the identifier of a Controller Service")
+ public boolean getIdentifiesControllerService() {
+ return identifiesControllerService;
+ }
+
+ public void setIdentifiesControllerService(boolean identifiesControllerService) {
+ this.identifiesControllerService = identifiesControllerService;
+ }
+
+ @ApiModelProperty("Whether or not the property is considered sensitive")
+ public boolean isSensitive() {
+ return sensitive;
+ }
+
+ public void setSensitive(boolean sensitive) {
+ this.sensitive = sensitive;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteGroupPort.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteGroupPort.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteGroupPort.java
new file mode 100644
index 0000000..ca85ce4
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteGroupPort.java
@@ -0,0 +1,109 @@
+/*
+ * 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 java.util.Objects;
+
+import io.swagger.annotations.ApiModelProperty;
+
+public class VersionedRemoteGroupPort extends VersionedComponent {
+ private String remoteGroupId;
+ private Integer concurrentlySchedulableTaskCount;
+ private Boolean useCompression;
+ private BatchSize batchSize;
+ private ComponentType componentType;
+ private String targetId;
+
+ @ApiModelProperty("The number of task that may transmit flowfiles to the target port concurrently.")
+ public Integer getConcurrentlySchedulableTaskCount() {
+ return concurrentlySchedulableTaskCount;
+ }
+
+ public void setConcurrentlySchedulableTaskCount(Integer concurrentlySchedulableTaskCount) {
+ this.concurrentlySchedulableTaskCount = concurrentlySchedulableTaskCount;
+ }
+
+ @ApiModelProperty("The id of the remote process group that the port resides in.")
+ public String getRemoteGroupId() {
+ return remoteGroupId;
+ }
+
+ public void setRemoteGroupId(String groupId) {
+ this.remoteGroupId = groupId;
+ }
+
+
+ @ApiModelProperty("Whether the flowfiles are compressed when sent to the target port.")
+ public Boolean isUseCompression() {
+ return useCompression;
+ }
+
+ public void setUseCompression(Boolean useCompression) {
+ this.useCompression = useCompression;
+ }
+
+ @ApiModelProperty("The batch settings for data transmission.")
+ public BatchSize getBatchSize() {
+ return batchSize;
+ }
+
+ public void setBatchSize(BatchSize batchSize) {
+ this.batchSize = batchSize;
+ }
+
+ @ApiModelProperty("The ID of the port on the target NiFi instance")
+ public String getTargetId() {
+ return targetId;
+ }
+
+ public void setTargetId(final String targetId) {
+ this.targetId = targetId;
+ }
+
+ @Override
+ public int hashCode() {
+ return 923847 + String.valueOf(getName()).hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof VersionedRemoteGroupPort)) {
+ return false;
+ }
+
+ final VersionedRemoteGroupPort other = (VersionedRemoteGroupPort) obj;
+ return Objects.equals(getName(), other.getName());
+ }
+
+ @Override
+ public ComponentType getComponentType() {
+ return componentType;
+ }
+
+ @Override
+ public void setComponentType(final ComponentType componentType) {
+ if (componentType != ComponentType.REMOTE_INPUT_PORT && componentType != ComponentType.REMOTE_OUTPUT_PORT) {
+ throw new IllegalArgumentException();
+ }
+
+ this.componentType = componentType;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteProcessGroup.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteProcessGroup.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteProcessGroup.java
new file mode 100644
index 0000000..834afac
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedRemoteProcessGroup.java
@@ -0,0 +1,161 @@
+/*
+ * 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.ApiModelProperty;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Set;
+
+public class VersionedRemoteProcessGroup extends VersionedComponent {
+ private String targetUri;
+ private String targetUris;
+
+ private String communicationsTimeout;
+ private String yieldDuration;
+ private String transportProtocol;
+ private String localNetworkInterface;
+ private String proxyHost;
+ private Integer proxyPort;
+ private String proxyUser;
+
+ private Set<VersionedRemoteGroupPort> inputPorts;
+ private Set<VersionedRemoteGroupPort> outputPorts;
+
+
+ @Deprecated
+ @ApiModelProperty(
+ value = "[DEPRECATED] The target URI of the remote process group." +
+ " If target uri is not set, but uris are set, then returns the first uri in the uris." +
+ " If neither target uri nor uris are set, then returns null.",
+ notes = "This field is deprecated and will be removed in version 1.x of NiFi Registry." +
+ " Please migrate to using targetUris only.")
+ public String getTargetUri() {
+
+ if (!StringUtils.isEmpty(targetUri)) {
+ return targetUri;
+ }
+ return !StringUtils.isEmpty(targetUris) ? targetUris.split(",", 2)[0] : null;
+
+ }
+
+ public void setTargetUri(final String targetUri) {
+ this.targetUri = targetUri;
+ }
+
+ @ApiModelProperty(
+ value = "The target URIs of the remote process group." +
+ " If target uris is not set but target uri is set, then returns the single target uri." +
+ " If neither target uris nor target uri is set, then returns null.")
+ public String getTargetUris() {
+
+ if (!StringUtils.isEmpty(targetUris)) {
+ return targetUris;
+ }
+ return !StringUtils.isEmpty(targetUri) ? targetUri : null;
+
+ }
+
+ public void setTargetUris(String targetUris) {
+ this.targetUris = targetUris;
+ }
+
+ @ApiModelProperty("The time period used for the timeout when communicating with the target.")
+ public String getCommunicationsTimeout() {
+ return communicationsTimeout;
+ }
+
+ public void setCommunicationsTimeout(String communicationsTimeout) {
+ this.communicationsTimeout = communicationsTimeout;
+ }
+
+ @ApiModelProperty("When yielding, this amount of time must elapse before the remote process group is scheduled again.")
+ public String getYieldDuration() {
+ return yieldDuration;
+ }
+
+ public void setYieldDuration(String yieldDuration) {
+ this.yieldDuration = yieldDuration;
+ }
+
+ @ApiModelProperty(value = "The Transport Protocol that is used for Site-to-Site communications", allowableValues = "RAW, HTTP")
+ public String getTransportProtocol() {
+ return transportProtocol;
+ }
+
+ public void setTransportProtocol(String transportProtocol) {
+ this.transportProtocol = transportProtocol;
+ }
+
+ @ApiModelProperty("A Set of Input Ports that can be connected to, in order to send data to the remote NiFi instance")
+ public Set<VersionedRemoteGroupPort> getInputPorts() {
+ return inputPorts;
+ }
+
+ public void setInputPorts(Set<VersionedRemoteGroupPort> inputPorts) {
+ this.inputPorts = inputPorts;
+ }
+
+ @ApiModelProperty("A Set of Output Ports that can be connected to, in order to pull data from the remote NiFi instance")
+ public Set<VersionedRemoteGroupPort> getOutputPorts() {
+ return outputPorts;
+ }
+
+ public void setOutputPorts(Set<VersionedRemoteGroupPort> outputPorts) {
+ this.outputPorts = outputPorts;
+ }
+
+
+ @ApiModelProperty("The local network interface to send/receive data. If not specified, any local address is used. If clustered, all nodes must have an interface with this identifier.")
+ public String getLocalNetworkInterface() {
+ return localNetworkInterface;
+ }
+
+ public void setLocalNetworkInterface(String localNetworkInterface) {
+ this.localNetworkInterface = localNetworkInterface;
+ }
+
+ public String getProxyHost() {
+ return proxyHost;
+ }
+
+ public void setProxyHost(String proxyHost) {
+ this.proxyHost = proxyHost;
+ }
+
+ public Integer getProxyPort() {
+ return proxyPort;
+ }
+
+ public void setProxyPort(Integer proxyPort) {
+ this.proxyPort = proxyPort;
+ }
+
+ public String getProxyUser() {
+ return proxyUser;
+ }
+
+ public void setProxyUser(String proxyUser) {
+ this.proxyUser = proxyUser;
+ }
+
+ @Override
+ public ComponentType getComponentType() {
+ return ComponentType.REMOTE_PROCESS_GROUP;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkAdapter.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkAdapter.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkAdapter.java
new file mode 100644
index 0000000..c3dae90
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkAdapter.java
@@ -0,0 +1,67 @@
+/*
+ * 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.link;
+
+import javax.ws.rs.core.Link;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import javax.xml.namespace.QName;
+import java.util.Map;
+
+/**
+ * This class is a modified version of Jersey's Link.JaxbAdapter that adds protection against nulls.
+ */
+public class LinkAdapter extends XmlAdapter<Link.JaxbLink, Link> {
+
+ /**
+ * Convert a {@link Link.JaxbLink} into a {@link Link}.
+ *
+ * @param v instance of type {@link Link.JaxbLink}.
+ * @return mapped instance of type {@link Link.JaxbLink}
+ */
+ @Override
+ public Link unmarshal(Link.JaxbLink v) {
+ if (v == null) {
+ return null;
+ }
+
+ Link.Builder lb = Link.fromUri(v.getUri());
+ for (Map.Entry<QName, Object> e : v.getParams().entrySet()) {
+ lb.param(e.getKey().getLocalPart(), e.getValue().toString());
+ }
+ return lb.build();
+ }
+
+ /**
+ * Convert a {@link Link} into a {@link Link.JaxbLink}.
+ *
+ * @param v instance of type {@link Link}.
+ * @return mapped instance of type {@link Link.JaxbLink}.
+ */
+ @Override
+ public Link.JaxbLink marshal(Link v) {
+ if (v == null) {
+ return null;
+ }
+
+ Link.JaxbLink jl = new Link.JaxbLink(v.getUri());
+ for (Map.Entry<String, String> e : v.getParams().entrySet()) {
+ final String name = e.getKey();
+ jl.getParams().put(new QName("", name), e.getValue());
+ }
+ return jl;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkableEntity.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkableEntity.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkableEntity.java
new file mode 100644
index 0000000..896e9d3
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkableEntity.java
@@ -0,0 +1,45 @@
+/*
+ * 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.link;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import javax.ws.rs.core.Link;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+/**
+ * Base classes for domain objects that want to provide a hypermedia link.
+ */
+@ApiModel("linkableEntity")
+public abstract class LinkableEntity {
+
+ private Link link;
+
+ @XmlElement
+ @XmlJavaTypeAdapter(LinkAdapter.class)
+ @ApiModelProperty(value = "An WebLink to this entity.", readOnly = true)
+ public Link getLink() {
+ return link;
+ }
+
+ public void setLink(Link link) {
+ this.link = link;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/params/SortOrder.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/params/SortOrder.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/params/SortOrder.java
new file mode 100644
index 0000000..8e571de
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/params/SortOrder.java
@@ -0,0 +1,47 @@
+/*
+ * 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.params;
+
+public enum SortOrder {
+
+ ASC("asc"),
+
+ DESC("desc");
+
+ private final String name;
+
+ SortOrder(final String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public static SortOrder fromString(String order) {
+ if (ASC.getName().equals(order)) {
+ return ASC;
+ }
+
+ if (DESC.getName().equals(order)) {
+ return DESC;
+ }
+
+ throw new IllegalArgumentException("Unknown Sort Order: " + order);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/params/SortParameter.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/params/SortParameter.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/params/SortParameter.java
new file mode 100644
index 0000000..d4a1add
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/params/SortParameter.java
@@ -0,0 +1,85 @@
+/*
+ * 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.params;
+
+/**
+ * Sort parameter made up of a field and a sort order.
+ */
+public class SortParameter {
+
+ public static final String API_PARAM_DESCRIPTION =
+ "Apply client-defined sorting to the resulting list of resource objects. " +
+ "The value of this parameter should be in the format \"field:order\". " +
+ "Valid values for 'field' can be discovered via GET :resourceURI/fields. " +
+ "Valid values for 'order' are 'ASC' (ascending order), 'DESC' (descending order).";
+
+ private final String fieldName;
+
+ private final SortOrder order;
+
+ public SortParameter(final String fieldName, final SortOrder order) {
+ this.fieldName = fieldName;
+ this.order = order;
+
+ if (this.fieldName == null) {
+ throw new IllegalStateException("Field Name cannot be null");
+ }
+
+ if (this.fieldName.trim().isEmpty()) {
+ throw new IllegalStateException("Field Name cannot be blank");
+ }
+
+ if (this.order == null) {
+ throw new IllegalStateException("Order cannot be null");
+ }
+ }
+
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ public SortOrder getOrder() {
+ return order;
+ }
+
+ /**
+ * Parses a sorting expression of the form field:order.
+ *
+ * @param sortExpression the expression
+ * @return the Sort instance
+ */
+ public static SortParameter fromString(final String sortExpression) {
+ if (sortExpression == null) {
+ throw new IllegalArgumentException("Sort cannot be null");
+ }
+
+ final String[] sortParts = sortExpression.split("[:]");
+ if (sortParts.length != 2) {
+ throw new IllegalArgumentException("Sort must be in the form field:order");
+ }
+
+ final String fieldName = sortParts[0];
+ final SortOrder order = SortOrder.fromString(sortParts[1]);
+
+ return new SortParameter(fieldName, order);
+ }
+
+ @Override
+ public String toString() {
+ return fieldName + ":" + order.getName();
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-data-model/src/test/java/org/apache/nifi/registry/flow/TestVersionedRemoteProcessGroup.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-data-model/src/test/java/org/apache/nifi/registry/flow/TestVersionedRemoteProcessGroup.java b/nifi-registry-core/nifi-registry-data-model/src/test/java/org/apache/nifi/registry/flow/TestVersionedRemoteProcessGroup.java
new file mode 100644
index 0000000..bbe6724
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/test/java/org/apache/nifi/registry/flow/TestVersionedRemoteProcessGroup.java
@@ -0,0 +1,102 @@
+/*
+ * 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 org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestVersionedRemoteProcessGroup {
+
+ @Test
+ public void testGetTargetUriAndGetTargetUris() {
+
+ VersionedRemoteProcessGroup vRPG = new VersionedRemoteProcessGroup();
+
+
+ /* targetUri is null, targetUris varies */
+
+ vRPG.setTargetUri(null);
+ vRPG.setTargetUris(null);
+ assertEquals(null, vRPG.getTargetUri());
+ assertEquals(null, vRPG.getTargetUris());
+
+ vRPG.setTargetUri(null);
+ vRPG.setTargetUris("");
+ assertEquals(null, vRPG.getTargetUri());
+ assertEquals(null, vRPG.getTargetUris());
+
+ vRPG.setTargetUri(null);
+ vRPG.setTargetUris("uri-2");
+ //assertEquals("uri-2", vRPG.getTargetUri());
+ assertEquals("uri-2", vRPG.getTargetUris());
+
+ vRPG.setTargetUri(null);
+ vRPG.setTargetUris("uri-2,uri-3");
+ assertEquals("uri-2", vRPG.getTargetUri());
+ assertEquals("uri-2,uri-3", vRPG.getTargetUris());
+
+
+ /* targetUri is empty, targetUris varies */
+
+ vRPG.setTargetUri("");
+ vRPG.setTargetUris(null);
+ assertEquals(null, vRPG.getTargetUri());
+ assertEquals(null, vRPG.getTargetUris());
+
+ vRPG.setTargetUri("");
+ vRPG.setTargetUris("");
+ assertEquals(null, vRPG.getTargetUri());
+ assertEquals(null, vRPG.getTargetUris());
+
+ vRPG.setTargetUri("");
+ vRPG.setTargetUris("uri-2");
+ assertEquals("uri-2", vRPG.getTargetUri());
+ assertEquals("uri-2", vRPG.getTargetUris());
+
+ vRPG.setTargetUri("");
+ vRPG.setTargetUris("uri-2,uri-3");
+ assertEquals("uri-2", vRPG.getTargetUri());
+ assertEquals("uri-2,uri-3", vRPG.getTargetUris());
+
+
+ /* targetUri is set, targetUris varies */
+
+ vRPG.setTargetUri("uri-1");
+ vRPG.setTargetUris(null);
+ assertEquals("uri-1", vRPG.getTargetUri());
+ assertEquals("uri-1", vRPG.getTargetUris());
+
+ vRPG.setTargetUri("uri-1");
+ vRPG.setTargetUris("");
+ assertEquals("uri-1", vRPG.getTargetUri());
+ assertEquals("uri-1", vRPG.getTargetUris());
+
+ vRPG.setTargetUri("uri-1");
+ vRPG.setTargetUris("uri-2");
+ assertEquals("uri-1", vRPG.getTargetUri());
+ assertEquals("uri-2", vRPG.getTargetUris());
+
+ vRPG.setTargetUri("uri-1");
+ vRPG.setTargetUris("uri-2,uri-3");
+ assertEquals("uri-1", vRPG.getTargetUri());
+ assertEquals("uri-2,uri-3", vRPG.getTargetUris());
+
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-docker/dockerhub/.dockerignore
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-docker/dockerhub/.dockerignore b/nifi-registry-core/nifi-registry-docker/dockerhub/.dockerignore
new file mode 100644
index 0000000..30a2650
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-docker/dockerhub/.dockerignore
@@ -0,0 +1,19 @@
+# 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.
+
+# Place files you want to exclude from the docker build here similar to .gitignore https://docs.docker.com/engine/reference/builder/#dockerignore-file
+DockerBuild.sh
+DockerRun.sh
+DockerImage.txt
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-docker/dockerhub/DockerBuild.sh
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-docker/dockerhub/DockerBuild.sh b/nifi-registry-core/nifi-registry-docker/dockerhub/DockerBuild.sh
new file mode 100755
index 0000000..c7e01e3
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-docker/dockerhub/DockerBuild.sh
@@ -0,0 +1,36 @@
+# 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.
+
+#!/bin/bash
+
+DOCKER_UID=1000
+if [ -n "$1" ]; then
+ DOCKER_UID="$1"
+fi
+
+DOCKER_GID=1000
+if [ -n "$2" ]; then
+ DOCKER_GID="$2"
+fi
+
+MIRROR=https://archive.apache.org/dist
+if [ -n "$3" ]; then
+ MIRROR="$3"
+fi
+
+DOCKER_IMAGE="$(egrep -v '(^#|^\s*$|^\s*\t*#)' DockerImage.txt)"
+NIFI_REGISTRY_IMAGE_VERSION="$(echo $DOCKER_IMAGE | cut -d : -f 2)"
+echo "Building NiFi-Registry Image: '$DOCKER_IMAGE' Version: NIFI_REGISTRY_IMAGE_VERSION Mirror: $MIRROR"
+docker build --build-arg UID="$DOCKER_UID" --build-arg GID="$DOCKER_GID" --build-arg NIFI_REGISTRY_VERSION="$NIFI_REGISTRY_IMAGE_VERSION" --build-arg MIRROR="$MIRROR" -t $DOCKER_IMAGE .
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-docker/dockerhub/DockerImage.txt
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-docker/dockerhub/DockerImage.txt b/nifi-registry-core/nifi-registry-docker/dockerhub/DockerImage.txt
new file mode 100644
index 0000000..07d6e8d
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-docker/dockerhub/DockerImage.txt
@@ -0,0 +1,16 @@
+# 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.
+
+apache/nifi-registry:0.3.0
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-docker/dockerhub/Dockerfile
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-docker/dockerhub/Dockerfile b/nifi-registry-core/nifi-registry-docker/dockerhub/Dockerfile
new file mode 100644
index 0000000..5d78ca0
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-docker/dockerhub/Dockerfile
@@ -0,0 +1,56 @@
+# 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.
+#
+
+FROM openjdk:8-jdk-slim
+LABEL maintainer="Apache NiFi <de...@nifi.apache.org>"
+LABEL site="https://nifi.apache.org"
+
+ARG UID=1000
+ARG GID=1000
+ARG NIFI_REGISTRY_VERSION=0.3.0
+ARG MIRROR=https://archive.apache.org/dist
+
+ENV NIFI_REGISTRY_BASE_DIR /opt/nifi-registry
+ENV NIFI_REGISTRY_HOME=${NIFI_REGISTRY_BASE_DIR}/nifi-registry-${NIFI_REGISTRY_VERSION} \
+ NIFI_REGISTRY_BINARY_URL=nifi/nifi-registry/nifi-registry-${NIFI_REGISTRY_VERSION}/nifi-registry-${NIFI_REGISTRY_VERSION}-bin.tar.gz
+
+ADD sh/ ${NIFI_REGISTRY_BASE_DIR}/scripts/
+
+# Setup NiFi-Registry user
+RUN groupadd -g ${GID} nifi || groupmod -n nifi `getent group ${GID} | cut -d: -f1` \
+ && useradd --shell /bin/bash -u ${UID} -g ${GID} -m nifi \
+ && chown -R nifi:nifi ${NIFI_REGISTRY_BASE_DIR} \
+ && apt-get update -y \
+ && apt-get install -y curl jq xmlstarlet
+
+USER nifi
+
+# Download, validate, and expand Apache NiFi-Registry binary.
+RUN curl -fSL ${MIRROR}/${NIFI_REGISTRY_BINARY_URL} -o ${NIFI_REGISTRY_BASE_DIR}/nifi-registry-${NIFI_REGISTRY_VERSION}-bin.tar.gz \
+ && echo "$(curl ${MIRROR}/${NIFI_REGISTRY_BINARY_URL}.sha256) *${NIFI_REGISTRY_BASE_DIR}/nifi-registry-${NIFI_REGISTRY_VERSION}-bin.tar.gz" | sha256sum -c - \
+ && tar -xvzf ${NIFI_REGISTRY_BASE_DIR}/nifi-registry-${NIFI_REGISTRY_VERSION}-bin.tar.gz -C ${NIFI_REGISTRY_BASE_DIR} \
+ && rm ${NIFI_REGISTRY_BASE_DIR}/nifi-registry-${NIFI_REGISTRY_VERSION}-bin.tar.gz \
+ && chown -R nifi:nifi ${NIFI_REGISTRY_HOME}
+
+# Web HTTP(s) ports
+EXPOSE 18080 18443
+
+WORKDIR ${NIFI_REGISTRY_HOME}
+
+# Apply configuration and start NiFi Registry
+CMD ${NIFI_REGISTRY_BASE_DIR}/scripts/start.sh