nifi-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Otto Fowler <ottobackwa...@gmail.com>
Subject Re: Static processor design
Date Fri, 08 Jan 2021 17:44:01 GMT
*ListenDynamicPropertyChange

> On Jan 8, 2021, at 12:42, Otto Fowler <ottobackwards@gmail.com> wrote:
> 
> So you would be implementing ListDynamicPropertyChange kind of.
> 
> 
>> On Jan 8, 2021, at 12:41, Otto Fowler <ottobackwards@gmail.com <mailto:ottobackwards@gmail.com>>
wrote:
>> 
>> What are the attributes of the processor?
>> Do you have : 
>> 
>> @InputRequirement(InputRequirement.Requirement.INPUT_FORBIDDEN)
>> or anything?
>> 
>> You should take a look at the Listen** processors.
>> They do not have any inputs etc, and run processing queued input from a background
thread.
>> You can have on modified queue a change and then have trigger process the queue of
changes.
>> 
>> 
>> 
>>> On Jan 8, 2021, at 11:04, Russell Bateman <russ@windofkeltia.com <mailto:russ@windofkeltia.com>>
wrote:
>>> 
>>> I only put the code I want to execute in onTrigger(), I suspected it would not
fire there. I know that this isn't what processors do. Configuration is a messy problem to
solve when your downstreamers want it made easy. This is supposed to be a solution that allows
them to remain in the NiFi UI and not have to run off doing harder things to configure. I
could put what I'm doing in /HumanReadables/ into a real, running processor, but then, I would
kind of have to add them to several processors and I wanted to avoid the confusion that created.
>>> 
>>> Here's the code. Thanks.
>>> 
>>> import com.windofkeltia.constants.HumanReadableMappings;
>>> 
>>> ...
>>> 
>>> @TriggerWhenEmpty
>>> @SideEffectFree
>>> @CapabilityDescription( "Dynamic properties can be created to specify (or add
to) static configuration"
>>>                       + " of key-value substitution pairs. See additional details."
)
>>> public class HumanReadables extends AbstractProcessor
>>> {
>>>   @Override
>>>   public void onTrigger( final ProcessContext context, final ProcessSession session
) throws ProcessException
>>>   {
>>>     getLogger().info( "inside onTrigger()..." );
>>> 
>>>     for( Map.Entry< PropertyDescriptor, String > entry : context.getProperties().entrySet()
)
>>>     {
>>>       PropertyDescriptor property = entry.getKey();
>>> 
>>>       // do work here--maybe pre-wipe all key-value pairs if we're just going
to recreate them?
>>>       final String PROPERTY_NAME  = property.getName();
>>>       final String PROPERTY_VALUE = entry.getValue();
>>> 
>>>       logger.trace( "Processing configurable mappings titled \"" + PROPERTY_NAME
+ "\"" );
>>> 
>>>       try
>>>       {
>>>         harvestDynamicPropertyMappings( PROPERTY_VALUE );
>>>       }
>>>       catch( Exception e )
>>>       {
>>> getLogger().debug( e.getMessage() );
>>>       }
>>>     }
>>>   }
>>> 
>>>   protected static void harvestDynamicPropertyMappings( final String PROPERTY_VALUE
)
>>>   {
>>>     final String[] LINES      = PROPERTY_VALUE.split( "\n" );
>>>     int            lineNumber = 0;
>>> 
>>>     if( LINES.length < 1 )
>>>       return;
>>> 
>>>     final String WHICH_LIST = LINES[ 0 ];
>>> 
>>>     for( final String VALUE_LINE : LINES )
>>>     {
>>>       char delimiter = VALUE_LINE.charAt( 0 );
>>>       int  position = VALUE_LINE.indexOf( delimiter, 1 );
>>>       String key, value;
>>> 
>>>       key   = ( position < 0 ) ? VALUE_LINE.substring( 1 ) : VALUE_LINE.substring(
1, position ).trim();
>>>       value = ( position > 0 ) ? VALUE_LINE.substring( position + 1 ).trim()
: "";
>>> 
>>>       HumanReadableMappings.add( key, value );
>>>     }
>>>   }
>>> 
>>>   @Override
>>>   protected PropertyDescriptor getSupportedDynamicPropertyDescriptor( final String
propertyDescriptorName )
>>>   {
>>>     return new PropertyDescriptor.Builder()
>>>                                  .required( false )
>>>                                  .name( propertyDescriptorName )
>>>                                  .addValidator( StandardValidators.NON_EMPTY_VALIDATOR
)
>>>                                  // or .addValidator( Validator.VALID ) if you
do not wish it validated!
>>>                                  .dynamic( true )
>>>                                  .build();
>>>   }
>>> 
>>>   private volatile Set< String > dynamicPropertyNames = new HashSet<>();
>>> 
>>>   @Override
>>>   public void onPropertyModified( final PropertyDescriptor descriptor, final
String oldValue, final String newValue )
>>>   {
>>>     getLogger().info( oldValue + " -> " + newValue );
>>> 
>>>     final Set< String > newDynamicPropertyNames = new HashSet<>(
dynamicPropertyNames );
>>> 
>>>     if( isNull( newValue ) )
>>>       newDynamicPropertyNames.remove( descriptor.getName() );
>>>     else if( isNull( oldValue ) && descriptor.isDynamic() )
>>>       newDynamicPropertyNames.add( descriptor.getName() );
>>> 
>>>     dynamicPropertyNames = Collections.unmodifiableSet( newDynamicPropertyNames
);
>>> 
>>>     final Set< String > allDynamicProperties = dynamicPropertyNames;
>>>   }
>>> 
>>>   @OnScheduled public void processProperties( final ProcessContext context )
>>>   {
>>>     for( Map.Entry< PropertyDescriptor, String > entry : context.getProperties().entrySet()
)
>>>     {
>>>       PropertyDescriptor descriptor = entry.getKey();
>>> 
>>>       if( descriptor.isDynamic() )
>>>         getLogger().debug( "Dynamic property named:\n    " + descriptor.getName()
>>>                             + ", value: " + entry.getValue().replaceAll( "\n",
" + " ) );
>>>     }
>>>   }
>>> 
>>>   protected static final String DEFAULT_MAPPING_VALUE = ""
>>>     + "|http://loinc.org <http://loinc.org/> |LOINC\n"
>>>     + "|http://snomed.info/sct <http://snomed.info/sct> |SNOMED\n"
>>>     + "|http://www.ama-assn.org/go/cpt <http://www.ama-assn.org/go/cpt>
             |CPT\n"
>>>     + "|http://aapc.org <http://aapc.org/>                            
|CPT\n"
>>>     + "|http://www.nlm.nih.gov/research/umls/rxnorm <http://www.nlm.nih.gov/research/umls/rxnorm>
|RxNorm\n"
>>>     + "|http://hl7.org/fhir/sid/ndc <http://hl7.org/fhir/sid/ndc>     
           |NDC\n"
>>>     + "|http://hl7.org/fhir/sid/icd-9-cm <http://hl7.org/fhir/sid/icd-9-cm>
|ICD-9\n"
>>>     + "|http://hl7.org/fhir/sid/icd-10 <http://hl7.org/fhir/sid/icd-10>
|ICD-10\n";
>>> 
>>>   public static final PropertyDescriptor DEFAULT_MAPPINGS = new PropertyDescriptor.Builder()
>>>       .name( "default mappings" )
>>>       .displayName( "Default mappings" )
>>>       .required( false )
>>>       .expressionLanguageSupported( ExpressionLanguageScope.NONE )
>>>       .defaultValue( DEFAULT_MAPPING_VALUE )
>>>       .addValidator( Validator.VALID )
>>>       .description( "These default mappings are already set up, but can be changed.
To erase completely,"
>>>                   + " merely clear the value of this property and ignore it in
favor of creating and"
>>>                   + " maintaining one or more of your own dynamic properties.")
>>>       .build();
>>> 
>>>   private List< PropertyDescriptor > properties;
>>> 
>>>   @Override
>>>   public void init( final ProcessorInitializationContext context )
>>>   {
>>>     List< PropertyDescriptor > properties = new ArrayList<>();
>>>     properties.add( DEFAULT_MAPPINGS );
>>>     this.properties = Collections.unmodifiableList( properties );
>>>   }
>>> 
>>>   @Override public List< PropertyDescriptor > getSupportedPropertyDescriptors()
{ return properties; }
>>> }
>>> 
>> 
> 


Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message