Use Iterators to Apply Rules to More Than One Object

Use an iterator to apply a rule to more than one object in your configurator model.

  • Express a relationship between participants in a node.
  • Apply a rule to different options of an option feature when these options have the same attributes.
  • Apply a rule to different children of an option class when these children have the same attributes.
  • Use the node's attributes to specify participants in the rule. This helps to apply a consistent set of rules when you frequently modify the model's structure or the model's attributes.
  • Express a relationship between a combination of participants.

You can use a local variable in an iterator statement to iterate over one or more constraints.

You use these keywords.

  • FOR ALL IN
  • WHERE

Use More Than One Iterator

Consider an example that uses an ADD TO statement. If the value of the UDA2 attribute in feature x is equal to the UDA2 attribute in feature y, then Oracle Configurator uses the numeric value of x to set the values in y for all the options of x and y.

ADD &var1 TO &var2
FOR ALL &var1 IN {OptionsOf(x)}, &var2 IN {OptionsOf(y)}
WHERE &var1.userAttrs["UDA2"] = &var2.userAttrs["UDA2"]; 

For another example, see Make Sure Options Are Compatible.

Use the For All, In, and Where Keywords

You can use the FOR ALL, IN, and WHERE keywords in an iterator statement.

Keyword Description

FOR ALL

IN

Use these keywords to begin the two clauses of an iterator statement:

  • Use the IN keyword to specify the source to use for the iteration.
  • You can include only a literal collection or a collection of model nodes, such as OptionsOf, in the IN clause.
  • All instances of a model use the same iteration.
WHERE

Use this keyword to begin the clause of an iterator statement when you need to remove iterations that don't match with the WHERE:

  • Your conditional expression in the WHERE clause must be static.
  • If you use the COLLECT operation in a WHERE and in an IN clause, then your operands must be static.
  • Configurator evaluates each compatibility statement starting at the top of your code, and then moves down. It evaluates the first rule it encounters, and then the second rule, and so on. It doesn't prioritize or give precedence according to an expression's AND or OR operator.

Here's an example where the result provides three values, a, b, and c, for one option, d.

ADD &var TO d
FOR ALL &var IN {a, b, c};

Here's another example:

ADD &var.userAttrs["AG_name.NumAttr"]+ 10 TO d
FOR ALL &var IN {OptionsOf(a)}
WHERE &var.userAttrs["AG_name.UDA3"] < 5;

Note

  • If the UDA3 attribute in the a option class contains a value that's less than 5, then the result provides as many values to the numeric feature d as there are children in option class a.
  • The result contains only as many values as there are children in the criteria that you specify in the WHERE clause.
  • This example uses a set of curly brackets ({}) to enclose a collection. The collection is OptionsOf(a).

In both examples, Configurator expands a single statement into one or more constraints or contributions without explicitly repeating each one. You can also use the iterator variable in the left side of a statement that accumulates a value.

Use the COLLECT Operator

You can use the COLLECT operator in an iterator statement.

  • Use a function that aggregates a value, such as Min(...), Max(...), Sum(...), or AnyTrue(...), to accept a collection of values as an operand.
  • Use COLLECT to specify the range of values for the collection that Configurator sends to the aggregation function. In many cases, you can also use FOR ALL to achieve this purpose.
  • You can use COLLECT with a complex expression and a WHERE clause to filter out elements that the collection uses as the source for its range of values.
  • COLLECT is an operator that returns a collection, so you can use it inside a collection literal. Configurator flattens the collection literal, which allows it to concatenate each collection.
  • You can use only one iterator with COLLECT.
  • You can't use COLLECT to put dynamic variables in the IN clause or the WHERE clause because using dynamic variables in these clauses is a collection that's unknown, and it might cause a problem when you test your rule.

Here's an example that uses a COLLECT operator and a FOR ALL iterator with a single value. The value contains the maximum value of the collection for children of the a option feature.

ADD Max({COLLECT &var FOR ALL &var IN {OptionsOf(a)}}) TO d;

Here's another example that has the same result.

ADD Max &var TO d
FOR ALL &var IN {OptionsOf(a)} ;

If you need to limit the values that you aggregate, then you must use COLLECT. Consider an example:

CONSTRAIN &varA IMPLIES model.optionClass.item
FOR ALL &varA IN {Option11, Option32, OptionsOf(optionFeature1)}
WHERE &varA.userAttrs["UDA1"] = 5;

Each iteration of the FOR ALL clause and the WHERE clause results in an error for every element of the {Option11, Option32, OptionsOf(Feature1)} collection that doesn't contain the UDA1 attribute. You can use the COLLECT operator to prevent the error. For example:

CONSTRAIN &varA IMPLIES model.optionClass.item
FOR ALL &varA IN {Option11, Option32, {COLLECT &varB
    FOR ALL &varB IN OptionsOf(optionFeature2)
WHERE &varB.userAttrs["UDA1"] = 5}};

COLLECT Operator with DISTINCT

Here's an example that uses the COLLECT operator with the DISTINCT keyword to collect distinct values from an attribute.

AnyTrue({COLLECT &opt1
        FOR ALL &opt1 IN {'optionClass3'.Options()}
        WHERE &opt1.userAttrs["Physical.Shape"] = &shape}) 
EXCLUDES 
AnyTrue({COLLECT &opt2  
        FOR ALL &opt2 IN {'optionClass3'.Options()} 
        WHERE &opt2.userAttrs["Physical.Shape"] <> &shape}) 
FOR ALL &shape IN 
        {COLLECT DISTINCT &node.userAttrs["Physical.Shape"]
        FOR ALL &node IN 'optionClass3'.Options()}  

This example prevents your user from selecting options that have different values for the Shape attribute from the optionClass3 option class. optionClass3 has a value of zero for the Minimum Quantity attribute, and it has no limit for the Maximum Quantity attribute.