This is an automated email from the ASF dual-hosted git repository.

mattyb149 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new f339e4378d NIFI-11075 Add additional fields to C2 component definition 
model
f339e4378d is described below

commit f339e4378d59ccff7e65d0369464e00150f2e355
Author: Bryan Bende <[email protected]>
AuthorDate: Fri Jan 20 11:55:30 2023 -0500

    NIFI-11075 Add additional fields to C2 component definition model
    
    Signed-off-by: Matthew Burgess <[email protected]>
    
    This closes #6872
---
 ...ableComponentDefinition.java => Attribute.java} | 33 +++++---
 .../api/ConfigurableComponentDefinition.java       |  4 +
 .../api/ConfigurableExtensionDefinition.java       | 13 ++++
 .../c2/protocol/component/api/DynamicProperty.java | 67 ++++++++++++++++
 ...entDefinition.java => DynamicRelationship.java} | 32 +++++---
 .../protocol/component/api/ExtensionComponent.java | 30 ++++++++
 .../component/api/ProcessorDefinition.java         | 31 ++++++++
 ...ition.java => SystemResourceConsideration.java} | 32 +++++---
 .../impl/StandardRuntimeManifestBuilder.java       | 88 +++++++++++++++++++++-
 .../nifi/runtime/manifest/TestRuntimeManifest.java | 55 ++++++++++++++
 10 files changed, 349 insertions(+), 36 deletions(-)

diff --git 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableComponentDefinition.java
 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/Attribute.java
similarity index 58%
copy from 
c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableComponentDefinition.java
copy to 
c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/Attribute.java
index d8f3cc43f1..d6155fdea4 100644
--- 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableComponentDefinition.java
+++ 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/Attribute.java
@@ -14,23 +14,34 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.apache.nifi.c2.protocol.component.api;
 
-import java.util.LinkedHashMap;
-import java.util.Map;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 
-/**
- * A component that has property descriptors.
- */
-public interface ConfigurableComponentDefinition {
+@ApiModel
+public class Attribute {
+
+    private String name;
+    private String description;
+
+    @ApiModelProperty(value = "The name of the attribute")
+    public String getName() {
+        return name;
+    }
 
-    Map<String, PropertyDescriptor> getPropertyDescriptors();
+    public void setName(String name) {
+        this.name = name;
+    }
 
-    void setPropertyDescriptors(LinkedHashMap<String, PropertyDescriptor> 
propertyDescriptors);
+    @ApiModelProperty(value = "The description of the attribute")
+    public String getDescription() {
+        return description;
+    }
 
-    boolean getSupportsDynamicProperties();
+    public void setDescription(String description) {
+        this.description = description;
+    }
 
-    void setSupportsDynamicProperties(boolean supportsDynamicProperties);
 
 }
diff --git 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableComponentDefinition.java
 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableComponentDefinition.java
index d8f3cc43f1..b6d41a33b8 100644
--- 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableComponentDefinition.java
+++ 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableComponentDefinition.java
@@ -18,6 +18,7 @@
 package org.apache.nifi.c2.protocol.component.api;
 
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -33,4 +34,7 @@ public interface ConfigurableComponentDefinition {
 
     void setSupportsDynamicProperties(boolean supportsDynamicProperties);
 
+    List<DynamicProperty> getDynamicProperties();
+
+    void setDynamicProperties(List<DynamicProperty> dynamicProperties);
 }
diff --git 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableExtensionDefinition.java
 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableExtensionDefinition.java
index 3324519a39..3ef484a0b1 100644
--- 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableExtensionDefinition.java
+++ 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableExtensionDefinition.java
@@ -20,12 +20,15 @@ import io.swagger.annotations.ApiModelProperty;
 
 import java.util.Collections;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 
 public abstract class ConfigurableExtensionDefinition extends 
ExtensionComponent implements ConfigurableComponentDefinition {
 
     private Map<String, PropertyDescriptor> propertyDescriptors;
+
     private boolean supportsDynamicProperties;
+    private List<DynamicProperty> dynamicProperties;
 
     @Override
     @ApiModelProperty("Descriptions of configuration properties applicable to 
this component.")
@@ -49,4 +52,14 @@ public abstract class ConfigurableExtensionDefinition 
extends ExtensionComponent
         this.supportsDynamicProperties = supportsDynamicProperties;
     }
 
+    @Override
+    @ApiModelProperty("Describes the dynamic properties supported by this 
component")
+    public List<DynamicProperty> getDynamicProperties() {
+        return dynamicProperties;
+    }
+
+    @Override
+    public void setDynamicProperties(List<DynamicProperty> dynamicProperties) {
+        this.dynamicProperties = dynamicProperties;
+    }
 }
diff --git 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/DynamicProperty.java
 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/DynamicProperty.java
new file mode 100644
index 0000000000..25e247dbec
--- /dev/null
+++ 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/DynamicProperty.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.c2.protocol.component.api;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import org.apache.nifi.expression.ExpressionLanguageScope;
+
+@ApiModel
+public class DynamicProperty {
+
+    private String name;
+    private String value;
+    private String description;
+    private ExpressionLanguageScope expressionLanguageScope;
+
+    @ApiModelProperty(value = "The description of the dynamic property name")
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @ApiModelProperty(value = "The description of the dynamic property value")
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    @ApiModelProperty(value = "The description of the dynamic property")
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    @ApiModelProperty(value = "The scope of the expression language support")
+    public ExpressionLanguageScope getExpressionLanguageScope() {
+        return expressionLanguageScope;
+    }
+
+    public void setExpressionLanguageScope(ExpressionLanguageScope 
expressionLanguageScope) {
+        this.expressionLanguageScope = expressionLanguageScope;
+    }
+
+}
diff --git 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableComponentDefinition.java
 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/DynamicRelationship.java
similarity index 57%
copy from 
c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableComponentDefinition.java
copy to 
c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/DynamicRelationship.java
index d8f3cc43f1..0934490ee3 100644
--- 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableComponentDefinition.java
+++ 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/DynamicRelationship.java
@@ -14,23 +14,33 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.apache.nifi.c2.protocol.component.api;
 
-import java.util.LinkedHashMap;
-import java.util.Map;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 
-/**
- * A component that has property descriptors.
- */
-public interface ConfigurableComponentDefinition {
+@ApiModel
+public class DynamicRelationship {
+
+    private String name;
+    private String description;
 
-    Map<String, PropertyDescriptor> getPropertyDescriptors();
+    @ApiModelProperty(value = "The description of the dynamic relationship 
name")
+    public String getName() {
+        return name;
+    }
 
-    void setPropertyDescriptors(LinkedHashMap<String, PropertyDescriptor> 
propertyDescriptors);
+    public void setName(String name) {
+        this.name = name;
+    }
 
-    boolean getSupportsDynamicProperties();
+    @ApiModelProperty(value = "The description of the dynamic relationship")
+    public String getDescription() {
+        return description;
+    }
 
-    void setSupportsDynamicProperties(boolean supportsDynamicProperties);
+    public void setDescription(String description) {
+        this.description = description;
+    }
 
 }
diff --git 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ExtensionComponent.java
 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ExtensionComponent.java
index 8a4447d585..98fd48f9f7 100644
--- 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ExtensionComponent.java
+++ 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ExtensionComponent.java
@@ -37,15 +37,18 @@ public class ExtensionComponent extends DefinedType {
     private List<DefinedType> providedApiImplementations;
 
     private Set<String> tags;
+    private Set<String> seeAlso;
 
     private Boolean deprecated;
     private String deprecationReason;
+    private Set<String> deprecationAlternatives;
 
     private Boolean restricted;
     private String restrictedExplanation;
     private Set<Restriction> explicitRestrictions;
 
     private Stateful stateful;
+    private List<SystemResourceConsideration> systemResourceConsiderations;
 
     private boolean additionalDetails;
 
@@ -77,6 +80,15 @@ public class ExtensionComponent extends DefinedType {
         this.tags = tags;
     }
 
+    @ApiModelProperty("The names of other component types that may be related")
+    public Set<String> getSeeAlso() {
+        return seeAlso;
+    }
+
+    public void setSeeAlso(Set<String> seeAlso) {
+        this.seeAlso = seeAlso;
+    }
+
     @ApiModelProperty("Whether or not the component has been deprecated")
     public Boolean getDeprecated() {
         return deprecated;
@@ -95,6 +107,15 @@ public class ExtensionComponent extends DefinedType {
         this.deprecationReason = deprecationReason;
     }
 
+    @ApiModelProperty("If this component has been deprecated, this optional 
field provides alternatives to use")
+    public Set<String> getDeprecationAlternatives() {
+        return deprecationAlternatives;
+    }
+
+    public void setDeprecationAlternatives(Set<String> 
deprecationAlternatives) {
+        this.deprecationAlternatives = deprecationAlternatives;
+    }
+
     @ApiModelProperty("Whether or not the component has a general restriction")
     public Boolean isRestricted() {
         return restricted;
@@ -131,6 +152,15 @@ public class ExtensionComponent extends DefinedType {
         this.stateful = stateful;
     }
 
+    @ApiModelProperty("The system resource considerations for the given 
component")
+    public List<SystemResourceConsideration> getSystemResourceConsiderations() 
{
+        return systemResourceConsiderations;
+    }
+
+    public void 
setSystemResourceConsiderations(List<SystemResourceConsideration> 
systemResourceConsiderations) {
+        this.systemResourceConsiderations = systemResourceConsiderations;
+    }
+
     @ApiModelProperty("Indicates if the component has additional details 
documentation")
     public boolean isAdditionalDetails() {
         return additionalDetails;
diff --git 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ProcessorDefinition.java
 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ProcessorDefinition.java
index b28ae06bb1..ad11e7bb70 100644
--- 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ProcessorDefinition.java
+++ 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ProcessorDefinition.java
@@ -32,6 +32,7 @@ public class ProcessorDefinition extends 
ConfigurableExtensionDefinition {
     private InputRequirement.Requirement inputRequirement;
     private List<Relationship> supportedRelationships;
     private boolean supportsDynamicRelationships;
+    private DynamicRelationship dynamicRelationship;
 
     private boolean triggerSerially;
     private boolean triggerWhenEmpty;
@@ -50,6 +51,9 @@ public class ProcessorDefinition extends 
ConfigurableExtensionDefinition {
     private String defaultYieldDuration;
     private String defaultBulletinLevel;
 
+    private List<Attribute> readsAttributes;
+    private List<Attribute> writesAttributes;
+
     @ApiModelProperty("Any input requirements this processor has.")
     public InputRequirement.Requirement getInputRequirement() {
         return inputRequirement;
@@ -77,6 +81,15 @@ public class ProcessorDefinition extends 
ConfigurableExtensionDefinition {
         this.supportsDynamicRelationships = supportsDynamicRelationships;
     }
 
+    @ApiModelProperty("If the processor supports dynamic relationships, this 
describes the dynamic relationship")
+    public DynamicRelationship getDynamicRelationship() {
+        return dynamicRelationship;
+    }
+
+    public void setDynamicRelationship(DynamicRelationship 
dynamicRelationship) {
+        this.dynamicRelationship = dynamicRelationship;
+    }
+
     @ApiModelProperty("Whether or not this processor should be triggered 
serially (i.e. no concurrent execution).")
     public boolean getTriggerSerially() {
         return triggerSerially;
@@ -208,4 +221,22 @@ public class ProcessorDefinition extends 
ConfigurableExtensionDefinition {
     public void setDefaultBulletinLevel(String defaultBulletinLevel) {
         this.defaultBulletinLevel = defaultBulletinLevel;
     }
+
+    @ApiModelProperty("The FlowFile attributes this processor reads")
+    public List<Attribute> getReadsAttributes() {
+        return readsAttributes;
+    }
+
+    public void setReadsAttributes(List<Attribute> readsAttributes) {
+        this.readsAttributes = readsAttributes;
+    }
+
+    @ApiModelProperty("The FlowFile attributes this processor writes/updates")
+    public List<Attribute> getWritesAttributes() {
+        return writesAttributes;
+    }
+
+    public void setWritesAttributes(List<Attribute> writesAttributes) {
+        this.writesAttributes = writesAttributes;
+    }
 }
diff --git 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableComponentDefinition.java
 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/SystemResourceConsideration.java
similarity index 56%
copy from 
c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableComponentDefinition.java
copy to 
c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/SystemResourceConsideration.java
index d8f3cc43f1..3c008f1f72 100644
--- 
a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ConfigurableComponentDefinition.java
+++ 
b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/SystemResourceConsideration.java
@@ -14,23 +14,33 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.apache.nifi.c2.protocol.component.api;
 
-import java.util.LinkedHashMap;
-import java.util.Map;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 
-/**
- * A component that has property descriptors.
- */
-public interface ConfigurableComponentDefinition {
+@ApiModel
+public class SystemResourceConsideration {
+
+    private String resource;
+    private String description;
 
-    Map<String, PropertyDescriptor> getPropertyDescriptors();
+    @ApiModelProperty(value = "The resource to consider")
+    public String getResource() {
+        return resource;
+    }
 
-    void setPropertyDescriptors(LinkedHashMap<String, PropertyDescriptor> 
propertyDescriptors);
+    public void setResource(String resource) {
+        this.resource = resource;
+    }
 
-    boolean getSupportsDynamicProperties();
+    @ApiModelProperty(value = "The description of how the resource is 
affected")
+    public String getDescription() {
+        return description;
+    }
 
-    void setSupportsDynamicProperties(boolean supportsDynamicProperties);
+    public void setDescription(String description) {
+        this.description = description;
+    }
 
 }
diff --git 
a/nifi-manifest/nifi-runtime-manifest-core/src/main/java/org/apache/nifi/runtime/manifest/impl/StandardRuntimeManifestBuilder.java
 
b/nifi-manifest/nifi-runtime-manifest-core/src/main/java/org/apache/nifi/runtime/manifest/impl/StandardRuntimeManifestBuilder.java
index c5cf27d95c..9139206833 100644
--- 
a/nifi-manifest/nifi-runtime-manifest-core/src/main/java/org/apache/nifi/runtime/manifest/impl/StandardRuntimeManifestBuilder.java
+++ 
b/nifi-manifest/nifi-runtime-manifest-core/src/main/java/org/apache/nifi/runtime/manifest/impl/StandardRuntimeManifestBuilder.java
@@ -38,11 +38,14 @@ import org.apache.nifi.components.resource.ResourceType;
 import org.apache.nifi.components.state.Scope;
 import org.apache.nifi.expression.ExpressionLanguageScope;
 import org.apache.nifi.extension.manifest.AllowableValue;
+import org.apache.nifi.extension.manifest.Attribute;
 import org.apache.nifi.extension.manifest.DefaultSchedule;
 import org.apache.nifi.extension.manifest.DefaultSettings;
 import org.apache.nifi.extension.manifest.Dependency;
 import org.apache.nifi.extension.manifest.DependentValues;
 import org.apache.nifi.extension.manifest.DeprecationNotice;
+import org.apache.nifi.extension.manifest.DynamicProperty;
+import org.apache.nifi.extension.manifest.DynamicRelationship;
 import org.apache.nifi.extension.manifest.Extension;
 import org.apache.nifi.extension.manifest.ExtensionManifest;
 import org.apache.nifi.extension.manifest.Property;
@@ -50,6 +53,7 @@ import org.apache.nifi.extension.manifest.ProvidedServiceAPI;
 import org.apache.nifi.extension.manifest.ResourceDefinition;
 import org.apache.nifi.extension.manifest.Restricted;
 import org.apache.nifi.extension.manifest.Stateful;
+import org.apache.nifi.extension.manifest.SystemResourceConsideration;
 import org.apache.nifi.logging.LogLevel;
 import org.apache.nifi.runtime.manifest.ComponentManifestBuilder;
 import org.apache.nifi.runtime.manifest.ExtensionManifestContainer;
@@ -63,6 +67,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.stream.Collectors;
 
 /**
@@ -208,7 +213,6 @@ public class StandardRuntimeManifestBuilder implements 
RuntimeManifestBuilder {
         // processor specific fields
         
processorDefinition.setInputRequirement(getInputRequirement(extension.getInputRequirement()));
         
processorDefinition.setSupportedRelationships(getSupportedRelationships(extension.getRelationships()));
-        
processorDefinition.setSupportsDynamicRelationships(extension.getDynamicRelationship()
 != null);
         
processorDefinition.setTriggerWhenEmpty(extension.getTriggerWhenEmpty());
         processorDefinition.setTriggerSerially(extension.getTriggerSerially());
         
processorDefinition.setTriggerWhenAnyDestinationAvailable(extension.getTriggerWhenAnyDestinationAvailable());
@@ -217,6 +221,12 @@ public class StandardRuntimeManifestBuilder implements 
RuntimeManifestBuilder {
         processorDefinition.setPrimaryNodeOnly(extension.getPrimaryNodeOnly());
         processorDefinition.setSideEffectFree(extension.getSideEffectFree());
 
+        final DynamicRelationship dynamicRelationship = 
extension.getDynamicRelationship();
+        if (dynamicRelationship != null) {
+            processorDefinition.setSupportsDynamicRelationships(true);
+            
processorDefinition.setDynamicRelationship(getDynamicRelationship(dynamicRelationship));
+        }
+
         final DefaultSettings defaultSettings = extension.getDefaultSettings();
         processorDefinition.setDefaultPenaltyDuration(defaultSettings == null 
? DEFAULT_PENALIZATION_PERIOD : defaultSettings.getPenaltyDuration());
         processorDefinition.setDefaultYieldDuration(defaultSettings == null ? 
DEFAULT_YIELD_PERIOD : defaultSettings.getYieldDuration());
@@ -256,9 +266,41 @@ public class StandardRuntimeManifestBuilder implements 
RuntimeManifestBuilder {
         
processorDefinition.setDefaultConcurrentTasksBySchedulingStrategy(defaultConcurrentTasks);
         
processorDefinition.setDefaultSchedulingPeriodBySchedulingStrategy(defaultSchedulingPeriods);
 
+        final List<Attribute> readsAttributes = extension.getReadsAttributes();
+        if (isNotEmpty(readsAttributes)) {
+            processorDefinition.setReadsAttributes(
+                    readsAttributes.stream()
+                            .map(this::getAttribute)
+                            .collect(Collectors.toList())
+            );
+        }
+
+        final List<Attribute> writesAttributes = 
extension.getWritesAttributes();
+        if (isNotEmpty(writesAttributes)) {
+            processorDefinition.setWritesAttributes(
+                    writesAttributes.stream()
+                            .map(this::getAttribute)
+                            .collect(Collectors.toList())
+            );
+        }
+
         componentManifestBuilder.addProcessor(processorDefinition);
     }
 
+    private org.apache.nifi.c2.protocol.component.api.Attribute 
getAttribute(final Attribute attribute) {
+        final org.apache.nifi.c2.protocol.component.api.Attribute c2Attribute 
= new org.apache.nifi.c2.protocol.component.api.Attribute();
+        c2Attribute.setName(attribute.getName());
+        c2Attribute.setDescription(attribute.getDescription());
+        return c2Attribute;
+    }
+
+    private org.apache.nifi.c2.protocol.component.api.DynamicRelationship 
getDynamicRelationship(final DynamicRelationship dynamicRelationship) {
+        final org.apache.nifi.c2.protocol.component.api.DynamicRelationship 
c2DynamicRelationship = new 
org.apache.nifi.c2.protocol.component.api.DynamicRelationship();
+        c2DynamicRelationship.setName(dynamicRelationship.getName());
+        
c2DynamicRelationship.setDescription(dynamicRelationship.getDescription());
+        return c2DynamicRelationship;
+    }
+
     private InputRequirement.Requirement getInputRequirement(final 
org.apache.nifi.extension.manifest.InputRequirement inputRequirement) {
         if (inputRequirement == null) {
             return null;
@@ -351,7 +393,12 @@ public class StandardRuntimeManifestBuilder implements 
RuntimeManifestBuilder {
 
         final List<String> tags = extension.getTags();
         if (isNotEmpty(tags)) {
-            extensionComponent.setTags(new HashSet<>(tags));
+            extensionComponent.setTags(new TreeSet<>(tags));
+        }
+
+        final List<String> seeAlso = extension.getSeeAlso();
+        if (isNotEmpty(seeAlso)) {
+            extensionComponent.setSeeAlso(new TreeSet<>(seeAlso));
         }
 
         // the extension-manifest.xml will have <deprecationNotice/> for 
non-deprecated components which unmarshalls into
@@ -360,6 +407,10 @@ public class StandardRuntimeManifestBuilder implements 
RuntimeManifestBuilder {
         if (deprecationNotice != null && deprecationNotice.getReason() != 
null) {
             extensionComponent.setDeprecated(true);
             
extensionComponent.setDeprecationReason(deprecationNotice.getReason());
+            final List<String> alternatives = 
deprecationNotice.getAlternatives();
+            if (isNotEmpty(alternatives)) {
+                extensionComponent.setDeprecationAlternatives(new 
TreeSet<>(alternatives));
+            }
         }
 
         final List<ProvidedServiceAPI> providedServiceApis = 
extension.getProvidedServiceAPIs();
@@ -394,11 +445,27 @@ public class StandardRuntimeManifestBuilder implements 
RuntimeManifestBuilder {
             }
         }
 
+        final List<SystemResourceConsideration> systemResourceConsiderations = 
extension.getSystemResourceConsiderations();
+        if (isNotEmpty(systemResourceConsiderations)) {
+            extensionComponent.setSystemResourceConsiderations(
+                    systemResourceConsiderations.stream()
+                            .map(this::getSystemResourceConsideration)
+                            .collect(Collectors.toList())
+            );
+        }
+
         if (additionalDetails != null) {
             extensionComponent.setAdditionalDetails(true);
         }
     }
 
+    private 
org.apache.nifi.c2.protocol.component.api.SystemResourceConsideration 
getSystemResourceConsideration(final SystemResourceConsideration 
systemResourceConsideration) {
+        final 
org.apache.nifi.c2.protocol.component.api.SystemResourceConsideration 
c2consideration = new 
org.apache.nifi.c2.protocol.component.api.SystemResourceConsideration();
+        c2consideration.setResource(systemResourceConsideration.getResource());
+        
c2consideration.setDescription(systemResourceConsideration.getDescription());
+        return c2consideration;
+    }
+
     private Scope getScope(final org.apache.nifi.extension.manifest.Scope 
sourceScope) {
         switch (sourceScope) {
             case LOCAL:
@@ -434,11 +501,26 @@ public class StandardRuntimeManifestBuilder implements 
RuntimeManifestBuilder {
             
configurableComponentDefinition.setPropertyDescriptors(propertyDescriptors);
         }
 
-        if (isNotEmpty(extension.getDynamicProperties())) {
+        final List<DynamicProperty> dynamicProperties = 
extension.getDynamicProperties();
+        if (isNotEmpty(dynamicProperties)) {
             configurableComponentDefinition.setSupportsDynamicProperties(true);
+            configurableComponentDefinition.setDynamicProperties(
+                    dynamicProperties.stream()
+                            .map(this::getDynamicProperty)
+                            .collect(Collectors.toList())
+            );
         }
     }
 
+    private org.apache.nifi.c2.protocol.component.api.DynamicProperty 
getDynamicProperty(final DynamicProperty dynamicProperty) {
+        final org.apache.nifi.c2.protocol.component.api.DynamicProperty 
c2DynamicProperty = new 
org.apache.nifi.c2.protocol.component.api.DynamicProperty();
+        c2DynamicProperty.setName(dynamicProperty.getName());
+        c2DynamicProperty.setValue(dynamicProperty.getValue());
+        c2DynamicProperty.setDescription(dynamicProperty.getDescription());
+        
c2DynamicProperty.setExpressionLanguageScope(getELScope(dynamicProperty.getExpressionLanguageScope()));
+        return c2DynamicProperty;
+    }
+
     private void addPropertyDescriptor(final Map<String, PropertyDescriptor> 
propertyDescriptors, final Property property) {
         final PropertyDescriptor propertyDescriptor = 
createPropertyDescriptor(property);
         propertyDescriptors.put(propertyDescriptor.getName(), 
propertyDescriptor);
diff --git 
a/nifi-manifest/nifi-runtime-manifest-test/src/test/java/org/apache/nifi/runtime/manifest/TestRuntimeManifest.java
 
b/nifi-manifest/nifi-runtime-manifest-test/src/test/java/org/apache/nifi/runtime/manifest/TestRuntimeManifest.java
index 714128c3c5..633d776637 100644
--- 
a/nifi-manifest/nifi-runtime-manifest-test/src/test/java/org/apache/nifi/runtime/manifest/TestRuntimeManifest.java
+++ 
b/nifi-manifest/nifi-runtime-manifest-test/src/test/java/org/apache/nifi/runtime/manifest/TestRuntimeManifest.java
@@ -105,9 +105,22 @@ class TestRuntimeManifest {
         assertFalse(listHdfsDefinition.getSideEffectFree());
         
assertFalse(listHdfsDefinition.getTriggerWhenAnyDestinationAvailable());
         assertFalse(listHdfsDefinition.getSupportsDynamicProperties());
+        assertNull(listHdfsDefinition.getDynamicProperties());
         assertFalse(listHdfsDefinition.getSupportsDynamicRelationships());
+        assertNull(listHdfsDefinition.getDynamicRelationship());
         assertEquals(InputRequirement.Requirement.INPUT_FORBIDDEN, 
listHdfsDefinition.getInputRequirement());
         assertTrue(listHdfsDefinition.isAdditionalDetails());
+        assertNull(listHdfsDefinition.getReadsAttributes());
+        assertNotNull(listHdfsDefinition.getWritesAttributes());
+        assertFalse(listHdfsDefinition.getWritesAttributes().isEmpty());
+        
assertNotNull(listHdfsDefinition.getWritesAttributes().get(0).getName());
+        
assertNotNull(listHdfsDefinition.getWritesAttributes().get(0).getDescription());
+        assertNotNull(listHdfsDefinition.getSeeAlso());
+        assertFalse(listHdfsDefinition.getSeeAlso().isEmpty());
+        assertNull(listHdfsDefinition.getSystemResourceConsiderations());
+        assertNull(listHdfsDefinition.getDeprecated());
+        assertNull(listHdfsDefinition.getDeprecationReason());
+        assertNull(listHdfsDefinition.getDeprecationAlternatives());
 
         assertEquals("30 sec", listHdfsDefinition.getDefaultPenaltyDuration());
         assertEquals("1 sec", listHdfsDefinition.getDefaultYieldDuration());
@@ -230,6 +243,48 @@ class TestRuntimeManifest {
         assertEquals(2, joltTransformDefaultSchedulingPeriods.size());
         assertEquals(LIST_HDFS_DEFAULT_SCHEDULE_TIME, 
joltTransformDefaultSchedulingPeriods.get(SchedulingStrategy.TIMER_DRIVEN.name()));
         
assertEquals(SchedulingStrategy.CRON_DRIVEN.getDefaultSchedulingPeriod(), 
joltTransformDefaultSchedulingPeriods.get(SchedulingStrategy.CRON_DRIVEN.name()));
+
+        // Verify ExecuteSQL has readsAttributes
+        final ProcessorDefinition executeSqlDef = 
getProcessorDefinition(bundles, "nifi-standard-nar",
+                "org.apache.nifi.processors.standard.ExecuteSQL");
+        assertNotNull(executeSqlDef.getReadsAttributes());
+        assertFalse(executeSqlDef.getReadsAttributes().isEmpty());
+        assertNotNull(executeSqlDef.getReadsAttributes().get(0).getName());
+        
assertNotNull(executeSqlDef.getReadsAttributes().get(0).getDescription());
+
+        // Verify RouteOnAttribute dynamic relationships and dynamic properties
+        final ProcessorDefinition routeOnAttributeDef = 
getProcessorDefinition(bundles, "nifi-standard-nar",
+                "org.apache.nifi.processors.standard.RouteOnAttribute");
+
+        assertTrue(routeOnAttributeDef.getSupportsDynamicRelationships());
+        assertNotNull(routeOnAttributeDef.getDynamicRelationship());
+        assertNotNull(routeOnAttributeDef.getDynamicRelationship().getName());
+        
assertNotNull(routeOnAttributeDef.getDynamicRelationship().getDescription());
+
+        assertTrue(routeOnAttributeDef.getSupportsDynamicProperties());
+        assertNotNull(routeOnAttributeDef.getDynamicProperties());
+        assertFalse(routeOnAttributeDef.getDynamicProperties().isEmpty());
+        
assertNotNull(routeOnAttributeDef.getDynamicProperties().get(0).getName());
+        
assertNotNull(routeOnAttributeDef.getDynamicProperties().get(0).getDescription());
+        
assertNotNull(routeOnAttributeDef.getDynamicProperties().get(0).getValue());
+        
assertNotNull(routeOnAttributeDef.getDynamicProperties().get(0).getExpressionLanguageScope());
+
+        // Verify DeleteAzureBlobStorage is deprecated
+        final ProcessorDefinition deleteAzureBlobDef = 
getProcessorDefinition(bundles, "nifi-azure-nar",
+                
"org.apache.nifi.processors.azure.storage.DeleteAzureBlobStorage");
+        assertNotNull(deleteAzureBlobDef.getDeprecated());
+        assertTrue(deleteAzureBlobDef.getDeprecated().booleanValue());
+        assertNotNull(deleteAzureBlobDef.getDeprecationReason());
+        assertNotNull(deleteAzureBlobDef.getDeprecationAlternatives());
+        assertFalse(deleteAzureBlobDef.getDeprecationAlternatives().isEmpty());
+
+        // Verify SplitJson has @SystemResourceConsiderations
+        final ProcessorDefinition splitJsonDef = 
getProcessorDefinition(bundles, "nifi-standard-nar",
+                "org.apache.nifi.processors.standard.SplitJson");
+        assertNotNull(splitJsonDef.getSystemResourceConsiderations());
+        assertFalse(splitJsonDef.getSystemResourceConsiderations().isEmpty());
+        
assertNotNull(splitJsonDef.getSystemResourceConsiderations().get(0).getResource());
+        
assertNotNull(splitJsonDef.getSystemResourceConsiderations().get(0).getDescription());
     }
 
     private PropertyDescriptor getPropertyDescriptor(final ProcessorDefinition 
processorDefinition, final String propName) {


Reply via email to