防止重复

决条件:您必须熟悉教程中使用的语法 并且已经创建了一个扩展.

学习:配置唯一性规则

水平:初学者

域:XML,  ConstrainDictionary

最低版本:2.6.0

通过定制化iTop,可以在类和唯一性规则上指定规则,以防止重复输入。
在此教程中,我们将看到:

  • 从用户角度看唯一性规则的行为
  • 如何定义新的唯一性规则
  • 开箱即用的iTop中在Person类上定义的唯一性规则
  • 删除现有的唯一性规则

行为

  • 规则将指定必须在其上检查唯一性的对象的范围。例如,您不希望两个人拥有相同的员工编号,除非该编号为空。那么范围将是每个employee_number不为空的人。
  • 在控制台或门户上进行单个创建或修改的过程中,规则可以
    • 阻止对象的创建

https://www.itophub.io/wiki/media?w=600&tok=4d07d2&media=2_7_0%3Arelease%3Auniqueness-error.png

  • 或在创建更新后仅显示警告消息。

https://www.itophub.io/wiki/media?w=400&tok=267cc7&media=2_7_0%3Arelease%3Auniqueness-warning.png

  • 唯一性规则适用于该类的一个或多个字段(包括ExternalFields)
  • 不支持属性类型的唯一性,例如 File, Image, Dashboard, Stopwatch,… (不完整的列表)。

如果您想为组织和员工编号上的人员使用唯一性规则,但是该规则仅适用于您的公司,则将规则的范围定义为“组织XXX的唯一人员”。

默认规则

在标准数据模型中,我们添加了以下规则:

  • Class Brand, id=name, field name,字段名称必须是唯一的。
  • Class Model, id=name_brand, fields: name + brand_id 必须是唯一的。
  • Class Person, id=employee_number fields: org_id + employee_number 仅在定义了employee_id的情况下必须是唯一的。
  • Class Person, id=name, fields: org_id + first_name + name应该是唯一的(仅警告)。

定义自己的规则

对于定义唯一性规则,我们只需要编写XML。

子类中的唯一名称

在此用例中,仅当它们都属于同一子类时,我们才希望防止它们与另一个FunctionalCI具有相同的名称。例如,NetworkDevice和服务器可以具有相同的名称,但是两个服务器不能具有相同的名称。

itop-design / classes / class@FunctionalCI / properties
 
        <uniqueness_rules>
          <rule id="functionalci_name" _delta="define">
            <!-- field or combination of "FunctionalCI" fields which must be unique -->
            <attributes>
              <attribute id="name"/>
              <attribute id="finalclass"/>
            </attributes>
          <!-- ... -->
itop-design / dictionaries / dictionary@EN US / entries
 
<entry id="Class:FunctionalCI/UniquenessRule:functionalci_name">
  <![CDATA[there is already a '$this->finalclass$' with the same name]]>
</entry>

注意在错误消息中使用占位符'$ this-> finalclass $'

这也可以作为每个子类上的单独唯一性规则来完成,但这需要更多工作。

仅供参考:finalclass是一个神奇的属性,仅存在于抽象类或具有除cmdbAbstractObject或DBObject之外的父的类上。

子类的唯一名称

在此用例中,我们要防止两个FunctionalCI具有相同的名称。除非FunctionalCI实际上是SoftwareInstance,MiddlewareInstance,DatabaseSchema或ApplicationSolution,在这种情况下,我们不在乎。

假设我们的iTop中只有两个FunctionalCI:

  • 一个名为“test.combodo.com”的NetworkDevice
  • 和一个名为“ iTop”的ApplicationSolution

我们可以做和不能做的:

  • 此规则将阻止创建名为“test.combodo.com”的服务器,因为已经存在具有相同名称的NetworkDevice
  • 这将防止将服务器重命名为“test.combodo.com”,因为已经存在具有相同名称的NetworkDevice
  • 将允许创建名为“ iTop”的服务器,因为名为“ iTop”的现有ApplicationSolution是最终类的一部分,这些类已被过滤掉
itop-design
 
  <classes>
    <class id="FunctionalCI" _delta="must_exist">
      <properties>
        <uniqueness_rules>
          <!-- For the "id" it must be a single word without special character but underscore -->
          <rule id="functionalci_name" _delta="define">
            <!-- field or combination of "FunctionalCI" fields which must be unique -->
            <attributes>
              <attribute id="name"/>
            </attributes>
            <!-- Define an OQL WHERE clause with condition on FunctionalCI fields -->
            <!-- It will be combined this way "SELECT FunctionalCI WHERE " + <filter> -->
            <filter><![CDATA[
               finalclass NOT IN ('DBServer','Middleware',
              'OtherSoftware','WebServer','PCSoftware','MiddlewareInstance',
              'DatabaseSchema','ApplicationSolution')]]>
            </filter>
            <!-- This flag allow you to keep the rule in the XML but desactivate it -->
            <disabled>false</disabled>
            <!-- If true or ommitted, a duplicate is blocking the creation/update -->
            <!-- otherwise it displays a warning message after creation/update -->
            <is_blocking>true</is_blocking>
          </rule>
        </uniqueness_rules>
      </properties>
    </class>
  </classes>
  <dictionaries>
    <dictionary id="EN US" _delta="must_exist">
      <entries>
        <entry id="Class:FunctionalCI/UniquenessRule:functionalci_name" _delta="define">
          <![CDATA[There are already a Functional CI with that name, please use another name.]]>
        </entry>
        <entry id="Class:FunctionalCI/UniquenessRule:functionalci_name+" _delta="define">
          <![CDATA[FunctionalCI name should be unique]]>
        </entry>
      </entries>
    </dictionary>
  </dictionaries>

注意字典条目““Class:” + class-name + “/UniquenessRule:” + rule_id的语法

  • 该条目用于与唯一性规则相关的错误消息。
  • 相同的代码结尾带有+,对应于唯一性规则的描述,尚未在任何地方显示,但可能有一天会在Datamodel查看器中显示。

现行人事规则

让我们看一下iTop中默认提供的有关Person的现有唯一性规则。有2条规则:

员工编号

  • 这是一个阻止规则,如果使用错误,它将阻止creation/update
  • 这样可以防止属于同一组织的两个人拥有相同的员工编号,
  • 允许使用空员工编号,即使在同一组织中存在空员工编号的其他人也不会生成错误。
  • 两个人只有属于两个不同的组织,才能具有相同的非空员工编号。
  • 此规则只是警告,它不会阻止creation/update,它只会显示一条消息。
  • 如果在同一组织中存在同音异义词,则生成

它们的定义方式如下:

itop-design / classes / class@Person / properties
 
   <uniqueness_rules>
      <rule id="employee_number">
         <attributes>
            <attribute id="org_id"/>
            <attribute id="employee_number"/>
         </attributes>
         <!-- Empty employee_number is allowed and will not be treated as a duplicate -->
         <filter><![CDATA[employee_number != '']]></filter>
         <disabled>false</disabled>
         <is_blocking>true</is_blocking>
       </rule>
       <rule id="name">
          <attributes>
             <attribute id="org_id"/>
             <attribute id="name"/>
             <attribute id="first_name"/>
          </attributes>
          <filter/>
          <disabled>false</disabled>
          <is_blocking>false</is_blocking>
       </rule>
     </rules>
   </uniqueness_rules>

删除规则

在此示例中,我们将删除默认的iTop数据模型中的现有唯一性规则。为了删除唯一性规则,您需要了解两件事:

  • 在哪个班级被宣布,这里是“人”
  • 和它的rule_id在这里''employee_number

删除规则需要在扩展中嵌入一部分XML,就像添加规则一样。这里重要的一点是上层节点中的_delta =“ delete”,必须将其所有子节点删除

itop-design / classes
 
    <class id="Person" _delta="must_exist">
      <properties>
        <uniqueness_rules>
          <rule id="employee_number" _delta="delete"/>
        </uniqueness_rules>
        </properties>
      </class>

部分禁用规则

在此用例中,我们假设此规则是在FunctionalCI上定义的:

classes / class@FunctionalCI / properties
 
        <uniqueness_rules>
          <rule id="functionalci_name" _delta="define">
            <!-- field or combination of "FunctionalCI" fields which must be unique -->
            <attributes>
              <attribute id="name"/>
              <attribute id="finalclass"/>
            </attributes>
          <!-- ... -->

我们想将其变更用于DatacenterDevice(FunctionalCI的子类),为此我们希望在DatacenterDevice的所有子类中使用名称为唯一性的其他行为。

为此,我们禁用父类规则“ functionalci_name”,并定义一个新规则,此处为“ datacenterdevice_name”。

classes / class@DatacenterDevice / properties
 
        <uniqueness_rules>
          <!-- here we use the same rule_id as the rule we want to stop -->
          <!-- We are on a child class, so the node is new, which explain the _delta="define" -->
          <rule id="functionalci_name" _delta="define">
            <!-- 'disabled' is the only tag supported when overwriting an existing rule_id -->
            <!-- It disables the 'functionalci_name' rule that for DatacenterDevices -->
            <disabled>true</disabled>
          </rule>
          <!-- then we can add another rule or not... -->                    
          <rule id="datacenterdevice_name" _delta="define">
            <attributes>
              <attribute id="name"/>
            </attributes>
          <!-- ... -->

规则ID在分层类的每个分支中必须唯一!
仅允许在分支内重用一个禁用父规则

原贴链接:https://www.itophub.io/wiki/page?id=2_7_0%3Acustomization%3Auniqueness-rules


Prevent duplicates

Prerequisite: You must be familiar with the Syntax used in Tutorials and have already created an extension.

learning:
Configure uniqueness rules
level:
Beginner
domains:
XMLConstrainDictionary
min version:
2.6.0

By customizing iTop, you can specify on a class, uniqueness rules, to prevent duplicate entries.
In this Tutorial we will see:

  • How uniqueness rules behave from a user perspective

  • How to define new uniqueness rules

  • Uniqueness rules defined on Person class in iTop out of the box

  • Removing an existing uniqueness rule

Behavior

  • A rule would specify the scope of objects on which the uniqueness must be checked. For example, you don't want to have two persons with the same employee number, unless that number is empty. The scope would then be every Person with employee_number not empty.

  • During a single creation or modification made on the console or the portal, a rule can either

    •  

    block the creation/update of the object

https://www.itophub.io/wiki/media?w=600&tok=4d07d2&media=2_7_0%3Arelease%3Auniqueness-error.png

  • or just display a warning message after the creation/update.

https://www.itophub.io/wiki/media?w=400&tok=267cc7&media=2_7_0%3Arelease%3Auniqueness-warning.png

  • A uniqueness rule applies on one or multiple fields of the class (including ExternalFields)

  • Uniqueness on attribute types such as File, Image, Dashboard, Stopwatch,… are not supported (incomplete list).

If you want a Uniqueness Rule for a Person on Organization and Employee number, but this rule only applies to your company, then you define the scope of the rule to be “Only Persons of organization XXX”

Default rules

In Standard Data Model, we have added those rules:

  • Class Brand, id=name, field name must be unique.

  • Class Model, id=name_brand, fields: name + brand_id must be unique.

  • Class Person, id=employee_number fields: org_id + employee_number must be unique only if employee_id is defined.

  • Class Person, id=name, fields: org_id + first_name + name should be unique (warning only).

Defining your own rule

For defining Uniqueness rules we only need to write XML.

Unique name within sub-classes

In this usecase we want to prevent any FunctionalCI to have the same name as another FunctionalCI only if they both belong to the same sub-class. For example a NetworkDevice and a Server can have the same name, but two Servers must not have the same name.

itop-design / classes / class@FunctionalCI / properties
 
        <uniqueness_rules>
          <rule id="functionalci_name" _delta="define">
            <!-- field or combination of "FunctionalCI" fields which must be unique -->
            <attributes>
              <attribute id="name"/>
              <attribute id="finalclass"/>
            </attributes>
          <!-- ... -->
itop-design / dictionaries / dictionary@EN US / entries
 
<entry id="Class:FunctionalCI/UniquenessRule:functionalci_name">
  <![CDATA[there is already a '$this->finalclass$' with the same name]]>
</entry>

Note the use of the placeholder '$this->finalclass$' within the error message

This could also have been done as separate uniqueness rule on each an every sub-class, but that's more work.

FYI: finalclass is a magic attribute which only exist on classes which are abstract or have a parent other than cmdbAbstractObject or DBObject.

Unique name across sub-classes

In this use case we want to prevent two FunctionalCIs to have the same name. Except if the FunctionalCI is in fact a SoftwareInstance, a MiddlewareInstance, a DatabaseSchema or an ApplicationSolution, in which case, we don't care.

Let's assume we have just two FunctionalCI in our iTop:

  • a NetworkDevice named “test.combodo.com”

  • and a ApplicationSolution named “iTop”

What we can and cannot do:

  • This rule will prevent creation of a Server named “test.combodo.com” as a NetworkDevice exists already with that same name

  • It will prevent the rename of a Server into “test.combodo.com” as a NetworkDevice exists already with that same name

  • It will allow creation of a Server named “iTop” as the existing ApplicationSolution named “iTop” is part of the final classes which are filtered out

itop-design
 
  <classes>
    <class id="FunctionalCI" _delta="must_exist">
      <properties>
        <uniqueness_rules>
          <!-- For the "id" it must be a single word without special character but underscore -->
          <rule id="functionalci_name" _delta="define">
            <!-- field or combination of "FunctionalCI" fields which must be unique -->
            <attributes>
              <attribute id="name"/>
            </attributes>
            <!-- Define an OQL WHERE clause with condition on FunctionalCI fields -->
            <!-- It will be combined this way "SELECT FunctionalCI WHERE " + <filter> -->
            <filter><![CDATA[
               finalclass NOT IN ('DBServer','Middleware',
              'OtherSoftware','WebServer','PCSoftware','MiddlewareInstance',
              'DatabaseSchema','ApplicationSolution')]]>
            </filter>
            <!-- This flag allow you to keep the rule in the XML but desactivate it -->
            <disabled>false</disabled>
            <!-- If true or ommitted, a duplicate is blocking the creation/update -->
            <!-- otherwise it displays a warning message after creation/update -->
            <is_blocking>true</is_blocking>
          </rule>
        </uniqueness_rules>
      </properties>
    </class>
  </classes>
  <dictionaries>
    <dictionary id="EN US" _delta="must_exist">
      <entries>
        <entry id="Class:FunctionalCI/UniquenessRule:functionalci_name" _delta="define">
          <![CDATA[There are already a Functional CI with that name, please use another name.]]>
        </entry>
        <entry id="Class:FunctionalCI/UniquenessRule:functionalci_name+" _delta="define">
          <![CDATA[FunctionalCI name should be unique]]>
        </entry>
      </entries>
    </dictionary>
  </dictionaries>

Note the syntax of a dictionary entry “Class:” + class-name + “/UniquenessRule:” + rule_id

  • This entry is used for the error message related to the Uniqueness rule.

  • The same code with a + at the end, correspond to a description of the Uniqueness rule, not yet displayed anywhere, but probably one day, it will be displayed in the Datamodel viewer.

Existing Rules on Person

Let's look at the existing uniqueness rules on Person, provided by default in iTop. There are 2 rules:

employee_number

  • It's a blocking rule, it will prevent creation/update in case of error

  • It will prevent two persons belonging to the same organization to have the same employee number,

  • An empty employee number is allowed and will not generate an error, even if other persons exist with an empty employee number in the same organization.

  • Two persons can have the same non-empty employee number only if they belongs to two different organizations.

name

  • This rule is just a warning, it does not prevent creation/update, it just display a message.

  • It is generated if there is an homonym within the same organization

Here is how they have been defined:

itop-design / classes / class@Person / properties
 
   <uniqueness_rules>
      <rule id="employee_number">
         <attributes>
            <attribute id="org_id"/>
            <attribute id="employee_number"/>
         </attributes>
         <!-- Empty employee_number is allowed and will not be treated as a duplicate -->
         <filter><![CDATA[employee_number != '']]></filter>
         <disabled>false</disabled>
         <is_blocking>true</is_blocking>
       </rule>
       <rule id="name">
          <attributes>
             <attribute id="org_id"/>
             <attribute id="name"/>
             <attribute id="first_name"/>
          </attributes>
          <filter/>
          <disabled>false</disabled>
          <is_blocking>false</is_blocking>
       </rule>
     </rules>
   </uniqueness_rules>

Removing a Rule

In this example we will remove an existing uniqueness rule, which is in the default iTop datamodel. In order to remove a uniqueness rule, you need to know two things:

  • on which class it has been declared, here “Person”

  • and its rule_id here ''employee_number

Removing a rule requires a piece of XML embedded in an extension, just like adding a rule. The important piece here is _delta=“delete” within the upper node which must be removed with all its sub-nodes

itop-design / classes
 
    <class id="Person" _delta="must_exist">
      <properties>
        <uniqueness_rules>
          <rule id="employee_number" _delta="delete"/>
        </uniqueness_rules>
        </properties>
      </class>

Partially disabling a rule

In this usecase we suppose that this rule was defined on FunctionalCI:

classes / class@FunctionalCI / properties
 
        <uniqueness_rules>
          <rule id="functionalci_name" _delta="define">
            <!-- field or combination of "FunctionalCI" fields which must be unique -->
            <attributes>
              <attribute id="name"/>
              <attribute id="finalclass"/>
            </attributes>
          <!-- ... -->

and we want to change it for DatacenterDevice (which is a child class of FunctionalCI), for which we want a different behavior with a uniqueness of name across all sub-classes of DatacenterDevice.

For this we disable the parent class rule “functionalci_name” and define a new rule, here “datacenterdevice_name”.

classes / class@DatacenterDevice / properties
 
        <uniqueness_rules>
          <!-- here we use the same rule_id as the rule we want to stop -->
          <!-- We are on a child class, so the node is new, which explain the _delta="define" -->
          <rule id="functionalci_name" _delta="define">
            <!-- 'disabled' is the only tag supported when overwriting an existing rule_id -->
            <!-- It disables the 'functionalci_name' rule that for DatacenterDevices -->
            <disabled>true</disabled>
          </rule>
          <!-- then we can add another rule or not... -->                    
          <rule id="datacenterdevice_name" _delta="define">
            <attributes>
              <attribute id="name"/>
            </attributes>
          <!-- ... -->

A rule id must be unique within each branch of the class hierarchy!
Reusing one within a branch is only allowed to disable the parent rule

标签:
由 superadmin 在 2020/08/27, 17:16 创建
    

需要帮助?

如果您需要有关XWiki的帮助,可以联系:

深圳市艾拓先锋企业管理咨询有限公司