Contents > 9 Extending the Metrics and Rule Engine > 9.1 Metric Procedures > 9.1.2 Implementation of the Metric Procedure

### 9.1.2 Implementation of the Metric Procedure

The following listing shows the complete implementation of the new metric procedure outlined in the previous section. Because we heavily utilize the API of the metrics engine, which already provides much of the functionality, the implementation of the procedure is quite compact, and essentially contains a nested loop to generate the element pairs.
```   packacke com.acme;
import java.util.Collection;
import java.util.Comparator;
import com.sdmetrics.math.ExpressionNode;
import com.sdmetrics.metrics.*;
import com.sdmetrics.model.ModelElement;

01 public class MetricProcedurePairwise extends MetricProcedure {

@Override
02 public Object calculate(ModelElement element, Metric metric)
throws SDMetricsException {
03    ProcedureAttributes attributes = metric.getAttributes();

04    Variables vars = new Variables(element);
05    Collection<ModelElement> set =
getRelationOrSet(element, attributes, vars);
06    if (set == null)
07       return Integer.valueOf(0);

08    ExpressionNode pairCondition = attributes.getExpression("paircondition");
09    boolean allTuples = attributes.getBooleanValue("tuples", false);
10    boolean withSelf = attributes.getBooleanValue("withself", allTuples);

11    FilterAttributeProcessor fap = getFilterAttributeProcessor(attributes);
12    SummationHelper sum = new SummationHelper(getMetricsEngine(), attributes);
13    Comparator<ModelElement> comparator = ModelElement.getComparator();

14    for (ModelElement first : fap.validIteration(set, vars)) {
15       vars.setVariable("_first", first);
16       for (ModelElement second : fap.validIteration(set, vars)) {
17          int comp = comparator.compare(first, second);
18          if (comp == 0 && !withSelf)
19             continue;
20          if (comp > 0 && !allTuples)
21             continue;

22          vars.setVariable("_second", second);
23          if (pairCondition == null
|| evalBooleanExpression(element, pairCondition, vars)) {
}
}
}
25    return sum.getTotal();
}
}

```
Let's go through the salient points of this implementation line by line:
• 01: All metric procedure classes must have public visibility, a default or no-argument constructor, and extend the abstract class com.sdmetrics.metrics.MetricProcedure.
• 02: The base class defines the abstract method calculate which we must override. Input parameters are the model element and the metric to be calculated.
• 03: Class ProcedureAttributes provides access to the attribute values in the metric definition.
• 04: Class Variables contains the values of variables to be used in metric expressions. In the constructor, we specify the principal model element for which the metric is calculated.
• 05: Method getRelationOrSet is a helper method provided by the base class to evaluate the "relation" or "relset" attributes (whichever was specified) as we know them from metric and set projections.
• 08: Class ExpressionNode represents metric, set, or condition expressions (see Section 8.5 "Expression Terms"). Here, we obtain the condition expression of the "paircondition" that we defined.
• 09-10: Here we obtain the values of attributes "tuples" and "withself", providing default values when the attributes are not set.
• 11: Class FilterAttributeProcessor is a helper class to process the standard filter attributes ("target", "targetcondition", "element", "eltype", "condition", and "scope"). The method getFilterAttributeProcessor() yields an instance of this class to apply the filter attributes for the metric at hand.
• 12: Class SummationHelper is a helper class that processes the "sum" and "stat" attributes.
• 14: We use the filter attribute processor from line 11 to iterate over all elements specified via the "relation" or "relset" attribute from line 5. The filter attribute processor automatically discards elements which should be ignored as per the element filter settings (see Section 4.2.2 "Specifying Filters") for us, applies the filter attributes "target", "element" etc., and returns an iteration over the resulting elements.
• 15: We define a variable "_first" with the first element of the pair/tuple as value.
• 16-21: In a nested loop, we iterate again over all elements. Depending on the values of attributes "tuples" and "withself", we skip unwanted pairs/tuples.
• 22: At this point we have identified a relevant pair or tuple, and we define a variable "_second" with the second element of the pair/tuple as value.
• 23: We evaluate the "paircondition" (if set), making sure to pass the values of the "_first" and "_second" variables into the evaluation. Method evalBooleanExpression evaluates condition expressions for model elements and returns a simple boolean value with the result.
• 24: When the "paircondition" yields true (or was not set), we use the summation helper from line 12 to either increase the result value by one or process the "sum" and "stat" attributes if they were specified. Again, we pass the "_first" and "_second" variables to the summation helper so that the values are available for the evaluation of the "sum" attribute.
• 25: We return the total as value of the metric.