<a id="comparing-objects"></a>
<a id="id1"></a>
# Comparing Objects

A Document Template or an [Import Script](../../organizations/import_scripts.html.md#organization-import-scripts) can compare two objects in the same way as the Compare dialog, and use the result to report what is different. There are two functions:

- **`compare_to_standard(object)`:** Compares an object with the Library Standard it was matched to, as the Compare dialog opened from a Standards Compliance page does. Standard Rules, Allowed Changes and explanations apply.

  It returns nothing when the object has no Library Standard, when its Standards Compliance is being calculated again, or when the Standard is in a Project you cannot view. Test the result before using it.
- **`compare(first, second)`:** Compares two objects of the same kind directly, and reports every difference. Custom Objects must be of the same Custom Object Type.

`compare` can compare Drafts, Forms, Folders, Edit Checks, Derivations, Custom Functions, Data Dictionaries, Unit Dictionaries, Matrices, Test Cases, Standard Rules and Custom Objects. `compare_to_standard` can compare Forms, Folders, Edit Checks, Derivations, Custom Functions, Data Dictionaries, Unit Dictionaries, Test Cases and Custom Objects, the objects that are matched to a Library Standard. For a Draft, a Matrix or a Standard Rule it returns nothing.

Both compare only objects in Projects that the person generating the document, or running the script, can view.

This template lists, for each Form in a Draft, what is different from its Library Standard:

```jinja
{% macro changed_rows(rows, indent) %}
{% for row in rows if row.state not in ('same', 'not_compared') %}
{{ indent }}{{ row.name }}: {{ row.source_value }} / {{ row.target_value }} ({{ row.description }})
{% if row.rule %}
{{ indent }}  Rule {{ row.rule.rule_id }}: {{ row.rule.text }}
{% endif %}
{% if row.explanation %}
{{ indent }}  {{ row.explanation.description }} by {{ row.explanation.who }}: {{ row.explanation.text }}
{% endif %}
{% endfor %}
{% endmacro %}
{% for form in draft.als_forms_set.order_by('Ordinal') %}
{% set result = compare_to_standard(form) %}
{% if not result %}
{{ form.OID }}: no Library Standard
{% elif not result.has_changes %}
{{ form.OID }}: matches its Library Standard
{% else %}
{{ form.OID }}: {{ result.summary.differences.total }} differences, {{ result.summary.added.total }} added, {{ result.summary.removed.total }} removed, {{ result.summary.rules_failed.total }} rules failed, {{ result.summary.rules_passed }} rules passed
{{ changed_rows(result.attributes, '  ') -}}
{% for collection in result.children %}
{% for child in collection.objects if child.state not in ('same', 'not_compared') %}
{% if child.change == 'matched' %}
  {{ collection.name }} {{ child.name }}: {{ child.description }}
{{ changed_rows(child.attributes, '    ') -}}
{% else %}
  {{ collection.name }} {{ child.name }}: {{ child.change }}
{% endif %}
{% endfor %}
{% endfor %}
{% endif %}
{% endfor %}
```

The result does not include the highlighted text the Compare dialog shows for each difference. Each attribute's two values are there to compare instead.

<a id="the-result"></a>
## The result

The result describes the object that was compared, and each object it contains in the same way.

| Name | Description |
| --- | --- |
| kind | `standard` from `compare_to_standard`, `direct` from `compare`. |
| type | The kind of object compared, such as `Form`, or the name of the Custom Object Type. |
| has_changes | False when the Compare dialog would say "There are no changes". A Standard Rule that is met, or a change the Library Standard allows, counts as a change, as it does in the Compare dialog. Use the `summary` counts to tell those apart from differences. |
| explanations_enabled | True when the Compare dialog would show explanations for this compare. |
| name | The object's name, as the Compare dialog shows it. |
| state, description, reason | The object's own state (see [States](#states) below), the label the Compare dialog shows for it, and why. The state covers the object's own attributes. Use `has_changes` to find out whether there is a change anywhere in it. |
| source, target | The `name` and `id` of the object on each side. For `compare_to_standard` the source is the Library Standard. |
| explanation | The explanation for the object, if it has one (see [Explanations](#explanations) below). |
| attributes | A list with one entry for each attribute and Custom Property (see [Attributes](#attributes) below). |
| children | A list with one entry for each kind of object it contains, such as `Fields`. Each has a `name` and a list of `objects`. Each object has the same entries as this table, apart from `kind`, `type`, `has_changes`, `explanations_enabled` and `summary`, and also has `change`: `matched` when it is on both sides, `added` when it is only on the target side, and `removed` when it is only on the source side. The attributes of an added or removed object are listed with an empty value on the side it is not on. |
| summary | The counts the Compare dialog shows (see [Summary](#summary) below). |

<a id="attributes"></a>
### Attributes

| Name | Description |
| --- | --- |
| name | The attribute's name, as the Compare dialog shows it. |
| source_value, target_value | The value on each side, as text. |
| state, description, reason | The attribute's state, the label the Compare dialog shows for it, and why. |
| custom_property | True for a Custom Property. |
| active | False for a Custom Property that is no longer active. |
| rule | The Standard Rule that applies to the attribute, if there is one: its `rule_id`, `description`, `text`, and `passed`, which is True unless the attribute failed the rule. A rule that is met with the same value as the Library Standard leaves the attribute's state as `same` and is not counted in `rules_passed`, as in the Compare dialog. |
| explanation | The explanation for the difference, if it has one (see [Explanations](#explanations) below). |

<a id="states"></a>
### States

| State | Meaning |
| --- | --- |
| same | The two sides are the same. |
| changed | The two sides are different. |
| added | Only on the target side. |
| removed | Only on the source side. |
| allowed_change, allowed_add, allowed_delete | Different, but the Library Standard allows the change. |
| rule_passed | A Standard Rule applies, and the target side meets it. |
| rule_failed | A Standard Rule applies, and the target side does not meet it. |
| not_compared | Not compared, because the object it belongs to is on one side only. |

<a id="explanations"></a>
### Explanations

| Name | Description |
| --- | --- |
| state, description | `not_explained`, `approval_requested`, `conditionally_approved`, `approved`, `denied` or `not_applicable`, and the label the Compare dialog shows for it. |
| text | The explanation. |
| who, when | The username of the person who gave it, and when. |
| obsolete | True when the explanation no longer applies. |
| history | Every explanation given for the difference, oldest first, each with `state`, `description`, `text`, `who` and `when`. |

<a id="summary"></a>
### Summary

| Name | Description |
| --- | --- |
| differences, added, removed, rules_failed | The number of each kind of deviation, by the state of its explanation: `not_explained`, `approval_requested`, `approved`, `conditionally_approved`, `denied`, and the `total`. |
| allowed_changes, allowed_added, allowed_removed, rules_passed | The number of changes the Library Standard allows, and of Standard Rules met. |
| added_types, removed_types, allowed_added_types, allowed_removed_types | The number of objects added or removed, by kind of object. |
| order_differs | True when objects on both sides are in a different order. |
