@@ -50,6 +50,8 @@ public record ApplicableTo
5050 [ YamlMember ( Alias = "product" ) ]
5151 public AppliesCollection ? Product { get ; set ; }
5252
53+ public ProductApplicability ? ProductApplicability { get ; set ; }
54+
5355 internal YamlDiagnosticsCollection ? Diagnostics { get ; set ; }
5456
5557 public static ApplicableTo All { get ; } = new ( )
@@ -113,12 +115,69 @@ public record ServerlessProjectApplicability
113115 } ;
114116}
115117
118+ [ YamlSerializable ]
119+ public record ProductApplicability
120+ {
121+ [ YamlMember ( Alias = "ecctl" ) ]
122+ public AppliesCollection ? Ecctl { get ; set ; }
123+
124+ [ YamlMember ( Alias = "curator" ) ]
125+ public AppliesCollection ? Curator { get ; set ; }
126+
127+ [ YamlMember ( Alias = "apm_agent_dotnet" ) ]
128+ public AppliesCollection ? ApmAgentDotnet { get ; set ; }
129+
130+ [ YamlMember ( Alias = "apm_agent_go" ) ]
131+ public AppliesCollection ? ApmAgentGo { get ; set ; }
132+
133+ [ YamlMember ( Alias = "apm_agent_java" ) ]
134+ public AppliesCollection ? ApmAgentJava { get ; set ; }
135+
136+ [ YamlMember ( Alias = "apm_agent_node" ) ]
137+ public AppliesCollection ? ApmAgentNode { get ; set ; }
138+
139+ [ YamlMember ( Alias = "apm_agent_python" ) ]
140+ public AppliesCollection ? ApmAgentPython { get ; set ; }
141+
142+ [ YamlMember ( Alias = "apm_agent_ruby" ) ]
143+ public AppliesCollection ? ApmAgentRuby { get ; set ; }
144+
145+ [ YamlMember ( Alias = "apm_agent_rum" ) ]
146+ public AppliesCollection ? ApmAgentRum { get ; set ; }
147+
148+ [ YamlMember ( Alias = "edot_ios" ) ]
149+ public AppliesCollection ? EdotIos { get ; set ; }
150+
151+ [ YamlMember ( Alias = "edot_android" ) ]
152+ public AppliesCollection ? EdotAndroid { get ; set ; }
153+
154+ [ YamlMember ( Alias = "edot_dotnet" ) ]
155+ public AppliesCollection ? EdotDotnet { get ; set ; }
156+
157+ [ YamlMember ( Alias = "edot_java" ) ]
158+ public AppliesCollection ? EdotJava { get ; set ; }
159+
160+ [ YamlMember ( Alias = "edot_node" ) ]
161+ public AppliesCollection ? EdotNode { get ; set ; }
162+
163+ [ YamlMember ( Alias = "edot_php" ) ]
164+ public AppliesCollection ? EdotPhp { get ; set ; }
165+
166+ [ YamlMember ( Alias = "edot_python" ) ]
167+ public AppliesCollection ? EdotPython { get ; set ; }
168+ }
169+
116170public class ApplicableToConverter : IYamlTypeConverter
117171{
118172 private static readonly string [ ] KnownKeys =
119- [ "stack" , "deployment" , "serverless" , "product" , "ece" ,
120- "eck" , "ess" , "self" , "elasticsearch" , "observability" , "security"
121- ] ;
173+ [
174+ "stack" , "deployment" , "serverless" , "product" ,
175+ "ece" , "eck" , "ess" , "self" ,
176+ "elasticsearch" , "observability" , "security" ,
177+ "ecctl" , "curator" ,
178+ "apm_agent_dotnet" , "apm_agent_go" , "apm_agent_java" , "apm_agent_node" , "apm_agent_python" , "apm_agent_ruby" , "apm_agent_rum" ,
179+ "edot_ios" , "edot_android" , "edot_dotnet" , "edot_java" , "edot_node" , "edot_php" , "edot_python"
180+ ] ;
122181
123182 public bool Accepts ( Type type ) => type == typeof ( ApplicableTo ) ;
124183
@@ -154,9 +213,7 @@ public class ApplicableToConverter : IYamlTypeConverter
154213 if ( TryGetApplicabilityOverTime ( dictionary , "stack" , diagnostics , out var stackAvailability ) )
155214 applicableTo . Stack = stackAvailability ;
156215
157- if ( TryGetApplicabilityOverTime ( dictionary , "product" , diagnostics , out var productAvailability ) )
158- applicableTo . Product = productAvailability ;
159-
216+ AssignProduct ( dictionary , applicableTo , diagnostics ) ;
160217 AssignServerless ( dictionary , applicableTo , diagnostics ) ;
161218 AssignDeploymentType ( dictionary , applicableTo , diagnostics ) ;
162219
@@ -166,6 +223,9 @@ public class ApplicableToConverter : IYamlTypeConverter
166223 if ( TryGetProjectApplicability ( dictionary , diagnostics , out var serverless ) )
167224 applicableTo . Serverless = serverless ;
168225
226+ if ( TryGetProductApplicability ( dictionary , diagnostics , out var product ) )
227+ applicableTo . ProductApplicability = product ;
228+
169229 if ( diagnostics . Count > 0 )
170230 applicableTo . Diagnostics = new YamlDiagnosticsCollection ( diagnostics ) ;
171231 return applicableTo ;
@@ -196,6 +256,48 @@ private static void AssignDeploymentType(Dictionary<object, object?> dictionary,
196256 }
197257 }
198258
259+ private static void AssignProduct ( Dictionary < object , object ? > dictionary , ApplicableTo applicableTo , List < ( Severity , string ) > diagnostics )
260+ {
261+ if ( ! dictionary . TryGetValue ( "product" , out var productValue ) )
262+ return ;
263+
264+ // This handles string, null, and empty string cases.
265+ if ( productValue is not Dictionary < object , object ? > productDictionary )
266+ {
267+ if ( TryGetApplicabilityOverTime ( dictionary , "product" , diagnostics , out var productAvailability ) )
268+ applicableTo . Product = productAvailability ;
269+ return ;
270+ }
271+
272+ // Handle dictionary case
273+ if ( TryGetProductApplicability ( productDictionary , diagnostics , out var applicability ) )
274+ applicableTo . ProductApplicability = applicability ;
275+ }
276+
277+ private static void AssignServerless ( Dictionary < object , object ? > dictionary , ApplicableTo applicableTo , List < ( Severity , string ) > diagnostics )
278+ {
279+ if ( ! dictionary . TryGetValue ( "serverless" , out var serverless ) )
280+ return ;
281+
282+ if ( serverless is null || ( serverless is string s && string . IsNullOrWhiteSpace ( s ) ) )
283+ applicableTo . Serverless = ServerlessProjectApplicability . All ;
284+ else if ( serverless is string serverlessString )
285+ {
286+ var av = AppliesCollection . TryParse ( serverlessString , diagnostics , out var a ) ? a : null ;
287+ applicableTo . Serverless = new ServerlessProjectApplicability
288+ {
289+ Elasticsearch = av ,
290+ Observability = av ,
291+ Security = av
292+ } ;
293+ }
294+ else if ( serverless is Dictionary < object , object ? > serverlessDictionary )
295+ {
296+ if ( TryGetProjectApplicability ( serverlessDictionary , diagnostics , out var applicability ) )
297+ applicableTo . Serverless = applicability ;
298+ }
299+ }
300+
199301 private static bool TryGetDeployment ( Dictionary < object , object ? > dictionary , List < ( Severity , string ) > diagnostics ,
200302 [ NotNullWhen ( true ) ] out DeploymentApplicability ? applicability )
201303 {
@@ -207,6 +309,7 @@ private static bool TryGetDeployment(Dictionary<object, object?> dictionary, Lis
207309 d . Ece = ece ;
208310 assigned = true ;
209311 }
312+
210313 if ( TryGetApplicabilityOverTime ( dictionary , "eck" , diagnostics , out var eck ) )
211314 {
212315 d . Eck = eck ;
@@ -234,30 +337,6 @@ private static bool TryGetDeployment(Dictionary<object, object?> dictionary, Lis
234337 return false ;
235338 }
236339
237- private static void AssignServerless ( Dictionary < object , object ? > dictionary , ApplicableTo applicableTo , List < ( Severity , string ) > diagnostics )
238- {
239- if ( ! dictionary . TryGetValue ( "serverless" , out var serverless ) )
240- return ;
241-
242- if ( serverless is null || ( serverless is string s && string . IsNullOrWhiteSpace ( s ) ) )
243- applicableTo . Serverless = ServerlessProjectApplicability . All ;
244- else if ( serverless is string serverlessString )
245- {
246- var av = AppliesCollection . TryParse ( serverlessString , diagnostics , out var a ) ? a : null ;
247- applicableTo . Serverless = new ServerlessProjectApplicability
248- {
249- Elasticsearch = av ,
250- Observability = av ,
251- Security = av
252- } ;
253- }
254- else if ( serverless is Dictionary < object , object ? > serverlessDictionary )
255- {
256- if ( TryGetProjectApplicability ( serverlessDictionary , diagnostics , out var applicability ) )
257- applicableTo . Serverless = applicability ;
258- }
259- }
260-
261340 private static bool TryGetProjectApplicability ( Dictionary < object , object ? > dictionary ,
262341 List < ( Severity , string ) > diagnostics ,
263342 [ NotNullWhen ( true ) ] out ServerlessProjectApplicability ? applicability )
@@ -270,6 +349,7 @@ private static bool TryGetProjectApplicability(Dictionary<object, object?> dicti
270349 serverlessAvailability . Elasticsearch = elasticsearch ;
271350 assigned = true ;
272351 }
352+
273353 if ( TryGetApplicabilityOverTime ( dictionary , "observability" , diagnostics , out var observability ) )
274354 {
275355 serverlessAvailability . Observability = observability ;
@@ -288,6 +368,115 @@ private static bool TryGetProjectApplicability(Dictionary<object, object?> dicti
288368 return true ;
289369 }
290370
371+ private static bool TryGetProductApplicability ( Dictionary < object , object ? > dictionary ,
372+ List < ( Severity , string ) > diagnostics ,
373+ [ NotNullWhen ( true ) ] out ProductApplicability ? applicability )
374+ {
375+ applicability = null ;
376+ var productAvailability = new ProductApplicability ( ) ;
377+ var assigned = false ;
378+ if ( TryGetApplicabilityOverTime ( dictionary , "ecctl" , diagnostics , out var ecctl ) )
379+ {
380+ productAvailability . Ecctl = ecctl ;
381+ assigned = true ;
382+ }
383+
384+ if ( TryGetApplicabilityOverTime ( dictionary , "curator" , diagnostics , out var curator ) )
385+ {
386+ productAvailability . Curator = curator ;
387+ assigned = true ;
388+ }
389+
390+ if ( TryGetApplicabilityOverTime ( dictionary , "apm_agent_dotnet" , diagnostics , out var apmAgentDotnet ) )
391+ {
392+ productAvailability . ApmAgentDotnet = apmAgentDotnet ;
393+ assigned = true ;
394+ }
395+
396+ if ( TryGetApplicabilityOverTime ( dictionary , "apm_agent_go" , diagnostics , out var apmAgentGo ) )
397+ {
398+ productAvailability . ApmAgentGo = apmAgentGo ;
399+ assigned = true ;
400+ }
401+
402+ if ( TryGetApplicabilityOverTime ( dictionary , "apm_agent_java" , diagnostics , out var apmAgentJava ) )
403+ {
404+ productAvailability . ApmAgentJava = apmAgentJava ;
405+ assigned = true ;
406+ }
407+
408+ if ( TryGetApplicabilityOverTime ( dictionary , "apm_agent_node" , diagnostics , out var apmAgentNode ) )
409+ {
410+ productAvailability . ApmAgentNode = apmAgentNode ;
411+ assigned = true ;
412+ }
413+
414+ if ( TryGetApplicabilityOverTime ( dictionary , "apm_agent_python" , diagnostics , out var apmAgentPython ) )
415+ {
416+ productAvailability . ApmAgentPython = apmAgentPython ;
417+ assigned = true ;
418+ }
419+
420+ if ( TryGetApplicabilityOverTime ( dictionary , "apm_agent_ruby" , diagnostics , out var apmAgentRuby ) )
421+ {
422+ productAvailability . ApmAgentRuby = apmAgentRuby ;
423+ assigned = true ;
424+ }
425+
426+ if ( TryGetApplicabilityOverTime ( dictionary , "apm_agent_rum" , diagnostics , out var apmAgentRum ) )
427+ {
428+ productAvailability . ApmAgentRum = apmAgentRum ;
429+ assigned = true ;
430+ }
431+
432+ if ( TryGetApplicabilityOverTime ( dictionary , "edot_ios" , diagnostics , out var edotIos ) )
433+ {
434+ productAvailability . EdotIos = edotIos ;
435+ assigned = true ;
436+ }
437+
438+ if ( TryGetApplicabilityOverTime ( dictionary , "edot_android" , diagnostics , out var edotAndroid ) )
439+ {
440+ productAvailability . EdotAndroid = edotAndroid ;
441+ assigned = true ;
442+ }
443+
444+ if ( TryGetApplicabilityOverTime ( dictionary , "edot_dotnet" , diagnostics , out var edotDotnet ) )
445+ {
446+ productAvailability . EdotDotnet = edotDotnet ;
447+ assigned = true ;
448+ }
449+
450+ if ( TryGetApplicabilityOverTime ( dictionary , "edot_java" , diagnostics , out var edotJava ) )
451+ {
452+ productAvailability . EdotJava = edotJava ;
453+ assigned = true ;
454+ }
455+
456+ if ( TryGetApplicabilityOverTime ( dictionary , "edot_node" , diagnostics , out var edotNode ) )
457+ {
458+ productAvailability . EdotNode = edotNode ;
459+ assigned = true ;
460+ }
461+
462+ if ( TryGetApplicabilityOverTime ( dictionary , "edot_php" , diagnostics , out var edotPhp ) )
463+ {
464+ productAvailability . EdotPhp = edotPhp ;
465+ assigned = true ;
466+ }
467+
468+ if ( TryGetApplicabilityOverTime ( dictionary , "edot_python" , diagnostics , out var edotPython ) )
469+ {
470+ productAvailability . EdotPython = edotPython ;
471+ assigned = true ;
472+ }
473+
474+ if ( ! assigned )
475+ return false ;
476+ applicability = productAvailability ;
477+ return true ;
478+ }
479+
291480 private static bool TryGetApplicabilityOverTime ( Dictionary < object , object ? > dictionary , string key , List < ( Severity , string ) > diagnostics ,
292481 out AppliesCollection ? availability )
293482 {
0 commit comments