11// src/processors/flow/Choice.js
2- // TODO implement
32
43import logger from '../../utils/Logger.js'
54import ns from '../../utils/ns.js'
@@ -9,77 +8,140 @@ import Processor from '../../model/Processor.js'
98 * @class Choice
109 * @extends Processor
1110 * @classdesc
12- * **a Transmissions Processor**
11+ * **a Transmissions Processor for Conditional Logic **
1312 *
14- * Processes messages by applying conditional logic and property transformations.
13+ * Evaluates a condition and sets message properties based on the result, enabling
14+ * conditional branching within transmission pipelines.
1515 *
1616 * ### Processor Signature
1717 *
1818 * #### __*Settings*__
19- * * **`ns.trn.me`** - Identifier for the processor instance
20- * * **`ns.trn.common`** - Common value to be added to the message
21- * * **`ns.trn.something1`** - First value to be processed
22- * * **`ns.trn.something2`** - Second value to be processed
23- * * **`ns.trn.added`** - Optional string to append to something1
24- * * **`ns.trn.notavalue`** - Fallback value if not provided in config
19+ * * **`ns.trn.testProperty`** - Property name to test (e.g., "userType", "status")
20+ * * **`ns.trn.testOperator`** - Comparison operator: "equals", "contains", "greater", "less", "exists"
21+ * * **`ns.trn.testValue`** - Value to compare against (for equals, contains, greater, less)
22+ * * **`ns.trn.trueProperty`** - Property to set if condition is true
23+ * * **`ns.trn.trueValue`** - Value to set for true condition
24+ * * **`ns.trn.falseProperty`** - Property to set if condition is false
25+ * * **`ns.trn.falseValue`** - Value to set for false condition
2526 *
2627 * #### __*Input*__
27- * * **`message`** - The message object to be processed
28+ * * **`message`** - The message object containing properties to test
2829 *
2930 * #### __*Output*__
30- * * **`message`** - The modified message object with added/updated fields
31+ * * **`message`** - Message with additional properties set based on the choice made
3132 *
3233 * #### __*Behavior*__
33- * * Forwards message immediately if `message.done` is true
34- * * Retrieves and processes configuration properties
35- * * Appends optional values to message fields
36- * * Handles fallback values for missing properties
34+ * * Skips processing if `message.done` is true
35+ * * Evaluates the specified condition using testProperty, testOperator, and testValue
36+ * * Sets trueProperty=trueValue if condition is true
37+ * * Sets falseProperty=falseValue if condition is false
38+ * * Supports operators: equals, contains, greater, less, exists
39+ * * Enables downstream processors to react to the choice via message properties
3740 *
3841 * #### __*Side Effects*__
39- * * Modifies the input message object
40- * * Logs processing information
42+ * * Adds choice result properties to the message object
43+ * * Logs the condition evaluation and choice made
4144 *
42- * #### __*Tests*__
43- * * TODO: Add test coverage
45+ * #### __*Example Configuration*__
46+ * ```turtle
47+ * :userRouter a :Choice ;
48+ * :settings :userChoiceConfig .
49+ *
50+ * :userChoiceConfig a :ConfigSet ;
51+ * :testProperty "userType" ;
52+ * :testOperator "equals" ;
53+ * :testValue "premium" ;
54+ * :trueProperty "processingPath" ;
55+ * :trueValue "premium-flow" ;
56+ * :falseProperty "processingPath" ;
57+ * :falseValue "standard-flow" .
58+ * ```
4459 */
4560class Choice extends Processor {
4661 constructor ( config ) {
4762 super ( config )
4863 }
4964
5065 /**
51- * Processes the message by applying property transformations and conditional logic .
66+ * Evaluates a condition and sets message properties based on the result .
5267 * @param {Object } message - The message object to process
5368 * @returns {Promise } Resolves when processing is complete
5469 */
5570 async process ( message ) {
56- logger . debug ( `\n\nChoice .process` )
71+ logger . debug ( `Choice .process starting ` )
5772
58- // TODO figure this out better
59- // may be needed if preceded by a spawning processor, eg. fs/DirWalker
73+ // Skip processing if message is marked as done
6074 if ( message . done ) {
75+ logger . debug ( `Choice: Message marked as done, skipping` )
6176 return this . emit ( 'message' , message )
62- // or simply return
6377 }
6478
65- // message is processed here :
79+ // Get configuration properties
80+ const testProperty = this . getProperty ( ns . trn . testProperty )
81+ const testOperator = this . getProperty ( ns . trn . testOperator , 'equals' )
82+ const testValue = this . getProperty ( ns . trn . testValue )
83+ const trueProperty = this . getProperty ( ns . trn . trueProperty )
84+ const trueValue = this . getProperty ( ns . trn . trueValue )
85+ const falseProperty = this . getProperty ( ns . trn . falseProperty )
86+ const falseValue = this . getProperty ( ns . trn . falseValue )
6687
67- // property values pulled from message | config settings | fallback
68- const me = await this . getProperty ( ns . trn . me )
69- logger . log ( `\nI am ${ me } ` )
88+ if ( ! testProperty ) {
89+ logger . warn ( `Choice: No testProperty specified, skipping condition evaluation` )
90+ return this . emit ( 'message' , message )
91+ }
7092
71- message . common = await this . getProperty ( ns . trn . common )
72- message . something1 = await this . getProperty ( ns . trn . something1 )
93+ // Get the value to test from the message
94+ const messageValue = message [ testProperty ]
7395
74- message . something2 = await this . getProperty ( ns . trn . something2 )
96+ // Evaluate the condition
97+ const conditionResult = this . evaluateCondition ( messageValue , testOperator , testValue )
7598
76- var added = await this . getProperty ( ns . trn . added , '' )
77- message . something1 = message . something1 + added
99+ logger . debug ( `Choice: ${ testProperty } ="${ messageValue } " ${ testOperator } "${ testValue } " = ${ conditionResult } ` )
78100
79- message . notavalue = await this . getProperty ( ns . trn . notavalue , 'fallback value' )
101+ // Apply the choice result
102+ if ( conditionResult ) {
103+ if ( trueProperty && trueValue !== undefined ) {
104+ message [ trueProperty ] = trueValue
105+ logger . debug ( `Choice: TRUE - Set ${ trueProperty } ="${ trueValue } "` )
106+ }
107+ } else {
108+ if ( falseProperty && falseValue !== undefined ) {
109+ message [ falseProperty ] = falseValue
110+ logger . debug ( `Choice: FALSE - Set ${ falseProperty } ="${ falseValue } "` )
111+ }
112+ }
80113
81- // message forwarded
82114 return this . emit ( 'message' , message )
83115 }
116+
117+ /**
118+ * Evaluates a condition using the specified operator
119+ * @param {any } messageValue - Value from the message to test
120+ * @param {string } operator - Comparison operator
121+ * @param {any } testValue - Value to compare against
122+ * @returns {boolean } Result of the condition evaluation
123+ */
124+ evaluateCondition ( messageValue , operator , testValue ) {
125+ switch ( operator . toLowerCase ( ) ) {
126+ case 'equals' :
127+ return messageValue == testValue
128+
129+ case 'contains' :
130+ return String ( messageValue || '' ) . includes ( String ( testValue || '' ) )
131+
132+ case 'greater' :
133+ return Number ( messageValue ) > Number ( testValue )
134+
135+ case 'less' :
136+ return Number ( messageValue ) < Number ( testValue )
137+
138+ case 'exists' :
139+ return messageValue !== undefined && messageValue !== null && messageValue !== ''
140+
141+ default :
142+ logger . warn ( `Choice: Unknown operator "${ operator } ", defaulting to equals` )
143+ return messageValue == testValue
144+ }
145+ }
84146}
85147export default Choice
0 commit comments