16
16
from enum import Enum
17
17
import re
18
18
19
- from py4j .protocol import Py4JJavaError
19
+ from py4j .protocol import Py4JError
20
20
21
21
from nifiapi .componentstate import StateManager
22
22
from nifiapi .__jvm__ import JvmHolder
@@ -254,6 +254,8 @@ def to_java_descriptor(self, gateway, cs_type_lookup):
254
254
return builder .build ()
255
255
256
256
257
+
258
+
257
259
def __get_allowable_values (self , gateway ):
258
260
if self .allowableValues is None :
259
261
return None
@@ -296,6 +298,106 @@ def __add_resource_definition(self, gateway, resource_definition, builder):
296
298
builder .identifiesExternalResource (cardinality , types [0 ], types [1 :])
297
299
298
300
301
+ def _collect_descriptor_metadata (java_context ):
302
+ descriptor_list = []
303
+ descriptor_lookup = {}
304
+ value_lookup = {}
305
+
306
+ try :
307
+ java_properties = java_context .getProperties ()
308
+ except AttributeError :
309
+ java_properties = None
310
+
311
+ if java_properties is not None :
312
+ for entry in java_properties .entrySet ():
313
+ descriptor = entry .getKey ()
314
+ name = descriptor .getName ()
315
+ if name not in descriptor_lookup :
316
+ descriptor_list .append (descriptor )
317
+ descriptor_lookup [name ] = descriptor
318
+
319
+ configured_value = entry .getValue ()
320
+ value_lookup [name ] = configured_value if configured_value is not None else descriptor .getDefaultValue ()
321
+
322
+ try :
323
+ supported_descriptor_supplier = getattr (java_context , 'getSupportedPropertyDescriptors' )
324
+ except AttributeError :
325
+ supported_descriptor_supplier = None
326
+
327
+ supported_descriptors = None
328
+ if callable (supported_descriptor_supplier ):
329
+ try :
330
+ supported_descriptors = supported_descriptor_supplier ()
331
+ except Py4JError :
332
+ supported_descriptors = None
333
+
334
+ if supported_descriptors is not None :
335
+ for descriptor in supported_descriptors :
336
+ name = descriptor .getName ()
337
+ if name not in descriptor_lookup :
338
+ descriptor_list .append (descriptor )
339
+ descriptor_lookup [name ] = descriptor
340
+ if name not in value_lookup :
341
+ value_lookup [name ] = descriptor .getDefaultValue ()
342
+
343
+ return descriptor_list , descriptor_lookup , value_lookup
344
+
345
+
346
+ def _dependent_values_iter (dependency ):
347
+ dependent_values = dependency .getDependentValues ()
348
+ if dependent_values is None :
349
+ return None
350
+ return [value for value in dependent_values ]
351
+
352
+
353
+ def _dependencies_satisfied (descriptor , descriptor_lookup , value_lookup , cache , visiting ):
354
+ name = descriptor .getName ()
355
+ if name in cache :
356
+ return cache [name ]
357
+
358
+ if name in visiting :
359
+ # Circular dependency detected; treat as unsatisfied to avoid infinite recursion
360
+ cache [name ] = False
361
+ return False
362
+
363
+ dependencies = descriptor .getDependencies ()
364
+ if dependencies is None or dependencies .isEmpty ():
365
+ cache [name ] = True
366
+ return True
367
+
368
+ visiting .add (name )
369
+
370
+ for dependency in dependencies :
371
+ dependency_name = dependency .getPropertyName ()
372
+ dependency_descriptor = descriptor_lookup .get (dependency_name )
373
+ if dependency_descriptor is None :
374
+ cache [name ] = False
375
+ visiting .remove (name )
376
+ return False
377
+
378
+ if not _dependencies_satisfied (dependency_descriptor , descriptor_lookup , value_lookup , cache , visiting ):
379
+ cache [name ] = False
380
+ visiting .remove (name )
381
+ return False
382
+
383
+ dependency_value = value_lookup .get (dependency_name )
384
+ dependent_values = _dependent_values_iter (dependency )
385
+ if dependent_values is None :
386
+ if dependency_value is None :
387
+ cache [name ] = False
388
+ visiting .remove (name )
389
+ return False
390
+ else :
391
+ if dependency_value not in dependent_values :
392
+ cache [name ] = False
393
+ visiting .remove (name )
394
+ return False
395
+
396
+ visiting .remove (name )
397
+ cache [name ] = True
398
+ return True
399
+
400
+
299
401
class PropertyContext :
300
402
__trivial_attribute_reference__ = re .compile (r"\$\{([^${}\[\],:;/*\' \t\r\n\\d][^${}\[\],:;/*\' \t\r\n]*)}" )
301
403
__escaped_attribute_reference__ = re .compile (r"\$\{'([^${}\[\],:;/*\' \t\r\n\\d][^${}\[\],:;/*\'\t\r\n]*)'}" )
@@ -331,25 +433,25 @@ class ProcessContext(PropertyContext):
331
433
332
434
def __init__ (self , java_context ):
333
435
self .java_context = java_context
436
+ descriptors , descriptor_lookup , value_lookup = _collect_descriptor_metadata (java_context )
437
+ dependency_cache = {}
334
438
335
- try :
336
- descriptors = java_context .getProperties ().keySet ()
337
- except AttributeError :
338
- descriptors = getattr (java_context , 'getSupportedPropertyDescriptors' )()
339
- self .name = java_context .getName ()
439
+ get_name = getattr (java_context , 'getName' , None )
440
+ self .name = get_name () if callable (get_name ) else None
340
441
self .property_values = {}
341
442
self .descriptor_value_map = {}
342
443
343
444
for descriptor in descriptors :
344
- string_value = None
345
- property_value = None
346
- try :
347
- property_value = java_context .getProperty (descriptor .getName ())
348
- string_value = property_value .getValue ()
349
- except (AssertionError , Py4JJavaError ):
350
- # Dependencies for this property are not satisfied; skip adding it
445
+ if not _dependencies_satisfied (descriptor , descriptor_lookup , value_lookup , dependency_cache , set ()):
351
446
continue
352
447
448
+ property_value = java_context .getProperty (descriptor .getName ())
449
+ string_value = property_value .getValue ()
450
+ if string_value is None :
451
+ string_value = value_lookup .get (descriptor .getName ())
452
+ else :
453
+ value_lookup [descriptor .getName ()] = string_value
454
+
353
455
property_value = self .create_python_property_value (descriptor .isExpressionLanguageSupported (), property_value , string_value )
354
456
self .property_values [descriptor .getName ()] = property_value
355
457
@@ -370,24 +472,22 @@ class ValidationContext(PropertyContext):
370
472
371
473
def __init__ (self , java_context ):
372
474
self .java_context = java_context
373
-
374
- try :
375
- descriptors = java_context .getProperties ().keySet ()
376
- except AttributeError :
377
- descriptors = getattr (java_context , 'getSupportedPropertyDescriptors' )()
475
+ descriptors , descriptor_lookup , value_lookup = _collect_descriptor_metadata (java_context )
476
+ dependency_cache = {}
378
477
self .property_values = {}
379
478
self .descriptor_value_map = {}
380
479
381
480
for descriptor in descriptors :
382
- string_value = None
383
- property_value = None
384
- try :
385
- property_value = java_context .getProperty (descriptor )
386
- string_value = property_value .getValue ()
387
- except (AssertionError , Py4JJavaError ):
388
- # Dependencies for this property are not satisfied; skip adding it
481
+ if not _dependencies_satisfied (descriptor , descriptor_lookup , value_lookup , dependency_cache , set ()):
389
482
continue
390
483
484
+ property_value = java_context .getProperty (descriptor )
485
+ string_value = property_value .getValue ()
486
+ if string_value is None :
487
+ string_value = value_lookup .get (descriptor .getName ())
488
+ else :
489
+ value_lookup [descriptor .getName ()] = string_value
490
+
391
491
property_value = self .create_python_property_value (descriptor .isExpressionLanguageSupported (), property_value , string_value )
392
492
self .property_values [descriptor .getName ()] = property_value
393
493
0 commit comments