2011년 12월 5일 월요일

작업항목 스크립트기반 사용자정의

https://jazz.net/wiki/bin/view/Main/AttributeCustomization


dojo.provide("org.example.workitems.providers.SeverityTagValueSet");

dojo.require("com.ibm.team.workitem.api.common.WorkItemAttributes");
dojo.require("dojo.string");

(function() {
var WorkItemAttributes= com.ibm.team.workitem.api.common.WorkItemAttributes;

dojo.declare("org.example.workitems.providers.SeverityTagValueSet", null, {

    getValueSet: function(attributeId, workItem, configuration) {
    
        var tags= workItem.getValue(WorkItemAttributes.TAGS);
        var severityOptions= [];
        
        if (tags.indexOf("important") === -1) {
            severityOptions.push("severity.literal.l1"); // Unclassified
            severityOptions.push("severity.literal.l2"); // Minor
            severityOptions.push("severity.literal.l3"); // Normal
        }
        
        severityOptions.push("severity.literal.l4"); // Major
        severityOptions.push("severity.literal.l5"); // Critical
        severityOptions.push("severity.literal.l6"); // Blocker

        return severityOptions;
    }
});
})();


Attribute customization is a way to add additional behavior for an attribute of a work item. For example you might want to validate the value of an attribute or even calculate its value based on other attributes. This article discusses in detail all available types of attribute customization. The examples on this page have been developed and tested with RTC version 3.0.1.


This Wiki page is not a tutorial and is meant to serve as a reference. Please see Customizing attributes in RTC 3.0 for a step-by-step introduction on attribute customization where the general concepts are explained and a few examples are provided. Here you can find more details about each possible customization together with further examples. This Wiki also contains information about using scripts to achieve more advanced behavior.

Customizing attributes

Whenever you want to customize the behavior of an attribute you need to perform three steps in the Process Configuration:
  1. Create a new instance of an attribute customization Each customization instance has a name that you can choose. The instance will belong to a specific customizationCategory and will implement a specific customization Type within that category. Types and categories are discussed below.
  2. Configure the new customization instance Each customization instance can be configured. You can configure most built-in customizations using the Eclipse UI, just after they are created. Script-based customizations can be configured in the Process Configuration Source. Some customizations do not need to be configured.
  3. Apply a customization instance to a work item attribute After a customization is created you can apply it to any work item attribute that has a supported type. Simply edit the attribute in the Process Configuration UI and specify what customizations it should use. The Customization Categories section provides information about the compatibility of attribute types and customization categories.

Each customization has three important characteristics:
  • Category The category is used as a high-level classification of customizations. There are five possible categories: Default values, Calculated Values, Value sets, Validators and Conditions.
  • Type A type is a specific customization implementation. Within each category there are different types of customizations.
  • Applicability An attribute customization can only be applied to specific attribute types.
All of these characteristics are discussed in detail in the Customization Categories section.
RTC provides a number of built-in customizations which can be easily configured from the Eclipse UI. To allow for more flexibility you can also implement new customizations written in Javascript and Java.

Using scripts for attribute customization

This section contains general information about using scripts for attribute customization. The next section discusses specific customization categories, including details for non-script and script-based implementations. You can find more examples of Javascript customizations in the Attribute Customization Examples Wiki.

Configuring a script-based customization by attaching a Javascript implementation

To use scripts deployed as process attachments you need to enable this functionality:
  1. Go to administrative page of your RTC server https://your.server.name:9443/ccm/admin.
  2. Open the Server tab.
  3. From the left side-bar open Configuration > Advanced Properties
  4. In the Work Item Component find the Enable Process Attachment Scripts property and set its value to true.
Alternatively you can add the following line to teamserver.properties:
# Allow to use scripts deployed as process attachments
com.ibm.team.workitem.process.scripts.enabled=true
The configuration interface for a Script-based customization is the same for all customization categories:
You must provide the local path to the Javascript file that implements the custom behavior.

API for Javascript

The API that is used with Script-based attribute customization is very simple. Scripts are implemented as Dojo classes which contain at a minimum a single function with three arguments:
  • The name of the function and the return type depend on the specific customization:
    CustomiztionFunction nameReturn type
    Default valuegetDefaultValueany type that is compatible with the type of the target attribute
    Calculated valuegetValueany type that is compatible with the type of the target attribute
    Value setgetValueSetarray
    Validatorvalidatecom.ibm.team.workitem.api.common.Status
    Conditionmatchesboolean
  • The three input arguments are always the same (except for Conditions which do not have an attributeId argument):
    • attributeId A string that represents the id of the attribute for which this customization has been set
    • workItem An instance of a work item for which this script is being executed. This supports the following operations:
      • getValue(String attributeId) returns the value of the attribute with the specified id.
      • getLabel(String attributeId) (since 3.5, to get the label of an enumeration literal)
      • isAttributeSet(String attributeId) returns a boolean value that indicates whether the specified attribute is set for the current work item.
    • configuration the configuration of this customization. It supports the following operations:
      • getChild(String name) returns the sub-element of configuration with the specified name. This sub-element has the same interface as configuration.
      • getChildren(String name) returns an array of all sub-elements of the configuration with the specified name. Each sub-element has the same interface as configuration.
      • getString(String name) returns the value of the configuration attribute with the specified name.
      • getStringDefault(String name, String default) returns the value of the configuration attribute with the specified name. If the specified attribute does not exist this function will return the value specified by default.
      • since 3.next M1 getWorkflowAction() returns a string that is the id of a workflow action currently selected by the user. This action will be executed when the item is saved. If the user has not selected any action this method will return nullNote: This method works only when used inside a Condition script, the return value will always benull when this is used in other customization script types.
  • Only values of the following attribute types can be safely read by and returned from scripts:
    • Short String
    • Medium String
    • Large String
    • Integer
    • Long
    • Boolean
    • Timestamp as an ISO-8601 standard string. Use dojo.date.stamp to convert a Javascript Date object to and from an ISO-8601 string. When converting a Date object to a string set the milliseconds and the zulu options to true.
      • To convert the value of a timestamp attribute with the id attributeId to a Date object use:
        var date= dojo.date.stamp.fromISOString(workItem.getValue(attributeId));
      • To convert a Date object to an ISO-8601 string use:
        var string= dojo.date.stamp.toISOString(date, {milliseconds:true, zulu:true});
    • Limited support for Enumeration. See the Working with Enumerations section for more information about using Enumerations in scripts.
    • Limited support for Items
Currently there is no dedicated API to work with Items or Enumerations and scripts can only use the id of such attributes. If you need additional information, such as the name that corresponds to an Enumeration literal id, you can pass it to scripts using configuration parameters. See the Configuring additional script parameters section for more information.

API Example

Here is an example of how to use the input arguments to access the current work item and the configuration:
dojo.provide("org.example.workitems.providers.APIExample");

dojo.require("com.ibm.team.workitem.api.common.WorkItemAttributes");

(function() {
var WorkItemAttributes= com.ibm.team.workitem.api.common.WorkItemAttributes;

dojo.declare("org.example.workitems.providers.APIExample", null, {
    getValue: function(attributeId, workItem, configuration) {
    
        var result= "Attribute ID: " + attributeId;
        result+= " item type: " + workItem.getValue(WorkItemAttributes.TYPE);
        
        var greeting= configuration.getChild("greeting");
        result+= " greeting: " + greeting.getString("first") + greeting.getString("second");
        
        var numbers= configuration.getChild("numbers");
        result+= " numbers: " + numbers.getStringDefault("a", "N/A") + numbers.getStringDefault("b", "N/A");
        
        return result;
    }
});
})();

Configuring additional script parameters

The example script above shows how you can gain access to the configuration parameters of the customization. In this case these are the greeting and the numbers. Any script-based customization that requires additional parameters in order to work correctly needs to be configured. Currently only the script file of such customizations can be configured via the UI. You must specify other parameters manually in the Process configuration source. You can configure each customization globally or locally:
  • The Global configuration is set at the location where the customization provider is defined.
    <configuration-data final="false" id="com.ibm.team.workitem.configuration.providers" xmlns="http://com.ibm.team.workitem/providers">
        <defaultValueProviders>
            ...
        </defaultValueProviders>
        <valueSetProviders>
            ...
        </valueSetProviders>
        <conditions>
            ...
        </conditions>
        <validators>
            ...
        </validators>
       <valueProviders>
            ...
        </valueProviders>
    </configuration-data>
    The global configuration includes at a minimum the name of the script file to run. Optionally it includes other parameters that the script requires. See below for an example.
  • The Local configuration is set at the attribute definition that includes the customization:
    <attributeDefinition id="customizedattribute" name="CustomizedAttribute" type="smallString">
        <defaultValueProvider>
            ...
        </defaultValueProvider>
        <valueSetProvider>
            ...
        </valueSetProvider>
        <validator>
            ...
        </validator>
       <valueProvider>
            ...
        </valueProvider>
    </attributeDefinition>
    The local configuration includes at a minimum the id of the customization used. Optionally you can include additional elements to parametrize the customization for the current attribute. If an element appears both in the Global and in the Local configuration, the one from the Local configuration will be used.
This is the global configuration of the customization for the script example above:
<valueProvider id="apiexample" name="APIExample" providerId="com.ibm.team.workitem.shared.common.internal.valueProviders.ScriptAttributeValueProvider">
    <script class="org.example.workitems.providers.APIExample" path="/workitem/scripts/common/APIExample.js"/>
    <greeting first="Hello" second="World"/>
    <numbers a="42"/>
</valueProvider>
The top-level element (valueProvider in this case) and the script element are created by the UI when a new script-based customization is created. If needed you can add any number of additional configuration elements. The example above includes an extra greeting element with two values first and second and one additional element - numbers with the attribute a. Using the API shown above, you can access the values of the attributes defined here from within the script file that implements this customization.
If you try out the above example and associate this Calculated value customziation with a string attribute, the value of that attribute will be similar to:
Attribute ID: someattribute item type: defect greeting: HelloWorld numbers: 42N/A
Furthermore you might additionally specify a different greeting locally in the attribute specification:
<attributeDefinition id="someattribute" name="someAttribute" type="smallString">
   <valueProvider id="apiexample" >
       <greeting first="Bye" second="Bye"/>
    </valueProvider>
</attributeDefinition>
If set, this new greeting will be preferred to the one configured in the global customization definition. In this case the value of the attribute will be similar to:
Attribute ID: someattribute item type: defect greeting: ByeBye numbers: 42N/A

Accessing built-in attributes of the work item

The examples above use the com.ibm.team.workitem.api.common.WorkItemAttributes class which contains the the string constants that are used to access built-in attributes of work items. Here are all possible values:
  • WorkItemAttributes.SEVERITY
  • WorkItemAttributes.PRIORITY
  • WorkItemAttributes.FOUND_IN
  • WorkItemAttributes.ID
  • WorkItemAttributes.TYPE
  • WorkItemAttributes.PROJECT_AREA
  • WorkItemAttributes.SUMMARY
  • WorkItemAttributes.STATE
  • WorkItemAttributes.CREATOR
  • WorkItemAttributes.OWNER
  • WorkItemAttributes.DESCRIPTION
  • WorkItemAttributes.CREATION_DATE
  • WorkItemAttributes.RESOLUTION
  • WorkItemAttributes.DUE_DATE
  • WorkItemAttributes.ESTIMATE
  • WorkItemAttributes.CORRECTED_ESTIMATE
  • WorkItemAttributes.TIME_SPENT
  • WorkItemAttributes.FILED_AGAINST
  • WorkItemAttributes.PLANNED_FOR
  • WorkItemAttributes.RESOLVER
  • WorkItemAttributes.RESOLUTION_DATE
  • WorkItemAttributes.TAGS
  • WorkItemAttributes.MODIFIED
  • WorkItemAttributes.MODIFIED_BY

Accessing an item's Status attribute

Using workItem.getValue(WorkItemAttributes.STATE) you can gain access to an item's workflow state. The value that you receive depends on the state id that is specified in the process configuration. The following rules apply:
  • If the state id is of the form s### where ### is an integer value, getValue() will return a string representation of the integer value. For example by default the Verified state has the ids4. Therefore when using getValue() the result will be the string "4".
  • If the state id is of a different form it will be directly returned by getValue().
This distinction is necessary to support legacy applications.

Working with Enumerations

An enumeration is a special attribute type that allows an attribute to have one of a fixed predefined set of values called literals. When you define an enumeration you specify a name for each literal. Internally each literal is assigned a literal id. You can also manually configure this id in the process specification. When working with enumerations inside an attribute customization script you should use the literal ids to refer to literals and not their names. To see what the id for a literal is, open the process configuration source XML and look for the enumeration definition. Here is, for example, the configuration of the Severity enumeration:
<enumeration attributeTypeId="severity" name="Severity">

    <literal icon="processattachment:/enumeration/unassigned2.gif" id="severity.literal.l1" name="Unclassified"/>
    <literal icon="processattachment:/enumeration/minor.gif" id="severity.literal.l2" name="Minor"/>
    <literal default="true" icon="processattachment:/enumeration/normal.gif" id="severity.literal.l3" name="Normal"/>
    <literal icon="processattachment:/enumeration/major.gif" id="severity.literal.l4" name="Major"/>
    <literal icon="processattachment:/enumeration/critical.gif" id="severity.literal.l5" name="Critical"/>
    <literal icon="processattachment:/enumeration/blocker.gif" id="severity.literal.l6" name="Blocker"/>
</enumeration>
By default each literal id will be of the form
EnumerationName.literal.l#
where # is a number that uniquely identifies the literal.
You might want to manually specify the literal ids for enumerations which are used in scripts to make them easier to understand. However you should only change the literal ids immediately after you create an Enumeration. After an Enumeration has been used, any changes to the literal ids will not be reflected in existing work items and their stored attributes will contain invalid data.

Customization Categories

Default values

A default value customization can be used to provide an initial value for an attribute when creating a new work item. Below is a list of all Default Value customizations that you can configure using the Eclipse client:
Customization typeApplicable to attributes of type
Single-Line TextSmall String, Medium String
Multi-Line TextLarge String
Single-Line HTMLMedium HTML
Multi-Line HTMLLarge HTML
WikiWiki
IterationInterval
CategoryCategory
UserContributor
User ListContributor List, Subscriptions
NumberInteger, Long
Role Based Enumeration DefaultEnumeration
Operating SystemEnumeration
Script Based DefaultAny attribute type
You can configure all of these types (except Operating System and Script Based Default) using the Eclipse UI, by simply providing a fixed value to use. Here is a screen shot of the configuration UI for a default value of type Multi-line Text:

Operating System default value

You can use this customization whenever an enumeration attribute should be initialized with a literal corresponding to the operating system that the Eclipse client is using.
WARNING: A default value configured with this customization will only work if an item is created using the Eclipse client.
For this customization to work correctly you need to configure it in the project XML.
First, create an Operating System enumeration:
<enumeration attributeTypeId="operatingsystem" name="Operating System">

    <literal default="true" id="operatingsystem.literal.windows" name="Windows"/>

    <literal id="operatingsystem.literal.linux" name="Linux"/>

    <literal id="operatingsystem.literal.macosx" name="Mac OS X"/>

</enumeration>
For more information about enumerations see the Working with Enumerations section
Next, create the Operating system customization and configure it for the specific Enumeration. A mapping is needed from operating system identification strings to literals of the enumeration. Here is an example:
<defaultValueProvider id="OSDefault" name="OS" providerId="com.ibm.team.workitem.common.internal.attributeValueProviders.OSLiteralProvider">

<mapping>

    <value content="windows">
        <literal id="operatingsystem.literal.windows" />
    </value>
    <value content="linux">
        <literall id="operatingsystem.literal.linux" />
    </value>
    <value content="macosx">
        <literall id="operatingsystem.literal.macosx" />
    </value>
</mapping>

</defaultValueProvider>
The operating system identification string ( the content attribute in the example above ) depends on the operating system on which the Eclipse client is running. This string is the value returned by the org.eclipse.core.runtime.Platform.getOS() method. The literal id in the mapping above must correspond to a literal id of the Operating system enumeration. If such a correspondence is found, the value of that literal will be used as a default. Otherwise the default value for the enumeration will be used (Windows in the example above).

Script-based default values

Note: You can find general information about script-based attribute customization in the Using scripts for attribute customization section.
If you want to use a custom script in order to provide a default value, simply add a new Script Based Default customization and type the file name of the JavaScript file implementing the script. To write your script use the skeleton below:
dojo.provide("com.example.common.MyClass");

(function() {
dojo.declare("com.example.common.MyClass", null, {

    getDefaultValue: function(attribute, workItem, configuration) {
      
        var value = ... //Some code that computes a return value
        return value;
    
    }
   
});
})();
Here is an example that simply returns the name of the current week day:
dojo.provide("com.example.common.CurrentDay");

(function() {
dojo.declare("com.example.common.CurrentDay", null, {

    getDefaultValue: function(attributeId, workItem, configuration) {

        var day = ( new Date() ).getDay();
        var dayName = "Unknown day";

        if (day == 0) dayName =  "Sunday";
        else if (day == 1) dayName =  "Monday";
        else if (day == 2) dayName =  "Tuesday";
        else if (day == 3) dayName =  "Wednesday";
        else if (day == 4) dayName =  "Thursday";
        else if (day == 5) dayName =  "Friday";
        else if (day == 6) dayName =  "Saturday";
        
        return dayName;
    }
});
})();

Calculated values

You can use this customization if the value of an attribute must be calculated instead of entered by the user. Optionally the calculated value can depend on the value of other attributes of the same work item. An attribute configured with a calculated value customization should use a read-only presentation. Here are all Calculated Value customizations that you can configure using the Eclipse client:
Customization typeApplicable to attributes of type
Exposure ProviderThese customizations are designed for special case usage in project areas based on the Formal Project Template and depend on specific attributes defined there. These customizations are preconfigured in that template and can not be used outside of it.
Probability Cost Provider
Script Based Calculated ValueAny attribute type

Script-based calculated values

Note: You can find general information about script-based attribute customization in the Using scripts for attribute customization section.
If you configure a Script-based calculated value, the script will be executed in two cases:
  • When a work item is saved, the script is executed to recalculate the value.
  • When an attribute which the current attribute depends on is changed, the value of the current attribute is recalculated. Depending on the presentations of the two attributes this may not work in all cases.
Here is a skeleton for a script that implements a calculated value customization:
dojo.provide("org.example.workitems.providers.CalculatedValueSkeleton");

(function() {
dojo.declare("org.example.workitems.providers.CalculatedValueSkeleton", null, {

    getValue: function(attributeId, workItem, configuration) {
        return 42;
    }
});
})();
And here is an example script that returns an "on-time" status of a work item. Items which are more critical have tighter deadlines and thus will be labelled as late or very late after shorter periods following their creation.
dojo.provide("org.example.workitems.providers.LatenessIndicator");

dojo.require("com.ibm.team.workitem.api.common.WorkItemAttributes");
dojo.require("dojo.date");
dojo.require("dojo.date.stamp");

(function() {
var WorkItemAttributes= com.ibm.team.workitem.api.common.WorkItemAttributes;

dojo.declare("org.example.workitems.providers.LatenessIndicator", null, {

    getValue: function(attributeId, workItem, configuration) {

        // Get the creation date and the current date and compute the difference in days.
        var creationDate= dojo.date.stamp.fromISOString(workItem.getValue(WorkItemAttributes.CREATION_DATE));
        var currentDate= new Date();
        var dayDiff= dojo.date.difference(currentDate, creationDate, "day");

        // Return a string that indicates whether the completion of this work item is on time
        // or not based on its severity and how much time has passed since it was created.
        var severity= workItem.getValue(WorkItemAttributes.SEVERITY);
        if ((severity === "severity.literal.l6")) { // Blocking severity
            if (dayDiff < 7) return "on time";
            else if (dayDiff < 30) return "late";
            else return "very late";
        } else if ((severity === "severity.literal.l5")) { // Critical severity
            if (dayDiff < 14) return "on time";
            else if (dayDiff < 45) return "late";
            else return "very late";
        } else if ((severity === "severity.literal.l4")) { // Major severity
            if (dayDiff < 30) return "on time";
            else if (dayDiff < 90) return "late";
            else return "very late";
        } else {
            if (dayDiff < 90) return "on time";
            else if (dayDiff < 180) return "late";
            else return "very late";
        }
    }
});
})();
Note: The example above uses the Severity Enumeration. You can find more information about using Enumerations in scripts in the Working with Enumerations section. To make this script reusable in different situations you can pass the enumeration ids as configuration parameters as explained in the Configuring Scripts with additional parameters section.
If the value of an attribute is calculated based on the value of other attributes it is important that you specify these dependencies in the attribute configuration:

Value sets

You can use a value set customization to determine a set of values that can be assigned to an attribute. Here are all Value set customizations that can be configured using the Eclipse client:
Customization typeApplicable to attributes of type
Dependent EnumerationsEnumeration
Role Based User ListContributor
Script Based Value SetAny attribute type

Dependent Enumerations (3.0.1)

You can use this customization if the set of possible values for an attribute depends on another attribute. Both attributes must be of type Enumeration. You use the configuration UI to specify the source and dependent enumerations. There you indicate what dependent values are available for each value of the source enumeration.
When applying this customization to an attribute it is important to indicate a dependency on the attribute that defines the source enumeration:

Dependent Enumerations (3.5)

In RTC 3.5 the support for dependent enumerations was greatly improved to be more powerful. To make it easier to configure large enumerations, Default Values have been introduced so that you can specify the default value set that an enumeration should have in case the value of an attribute is not specifically configured. Another addition is support for non-enumeration Attribute Dependencies. With RTC 3.5 any work item attribute can serve as value set provider for an enumeration. And finally with the help of Dynamic Hierarchies, a work item attribute that has a hierarchical structure (like Categories, Iterations and Team Areas) can be configured to provide values for an enumeration if the value is selected or any of the child values.
In the following parts of this document you will find instructions how to configure each of the new features. The instructions also outline the process specification XML to assist with attributes that are not providing a configuration UI.
Default Values (UI)
Simply select the default entry on top in the list of entries and configure the values.
Default Values (XML)
Configuring default values for an enumeration is simple. Just leave out the content attribute of the value XML element and the provided literals will be used as value set in case the attribute matches a value that is not configured otherwise.
Attribute Dependencies (UI)
Simply select any desired attribute from the list in "Source Attributes". Currently a configuration UI is provided for all enumerations, "Filed Against", "Found In", "Planned For", "Status", "Resolution", "Team Area" and "Type".
Attribute Dependencies (XML)
You can now configure any work item attribute to be the provider of values to an enumeration. Simply put the attribute type identifier as value into the sourceEnumeration attribute of themapping XML element to specify the attribute you want to use as source. For example, you can use interval for the "Planned For" attribute, category for the "Filed Against" attribute orsmallString for any string based attribute like "Status". Second, inside the content attribute of the value XML element, place the item identifier. For item based attributes like "Planned For", use the UUID of the iteration. For string based attributes like "Status", use the actual value (e.g. identifier of the Status as defined by the workflow).
If you want to configure an enumeration that depends on the Team Area a work item is filed against, use com.ibm.team.workitem.teamArea as value for the mapping XML element. And for thecontent attribute of the value XML element, simply use the item UUID of the team area.
Do not forget to configure the attribute dependency in the "Types and Artifacts" editor. An enumeration attribute has to list all its dependencies in order to update its value properly.
Dynamic Hierarchies (UI)
Dynamic hierarchies can be configured for the attributes "Planned For", "Filed Against" and "Team Area". Simply open the context menu on any node with children and choose to include children for the value set.
Dynamic Hierarchies (XML)
Some work item attributes support hierarchies. Categories, Iterations and Teams can have a hierarchy and often you might want to configure a value set for an enumeration for a specific attribute value and all child values that are configured. Think about an iteration that is divided into several child iterations for your release. You might want to configure a value set that is returned whenever either the parent iteration or any of its children is selected in the work item editor.
To configure a specific attribute value to match including all child values, add the attribute includeChildren with a value of true to the value XML element that provides the value set. For thecontent attribute of the value XML element, use the UUID of parent item you want to match on.

Role Based User List

You can use this customization with an attribute of type Contributor in order to limit the choice of users. Only users which have the specified roles within the team can be assigned to the attribute:

Script Based Value Set

Note: You can find general information about script-based attribute customization in the Using scripts for attribute customization section.
You may provide custom value sets using scripts. Values which are permitted for an attribute must be explicitly included in the returned value set.
Here is a skeleton for implementing Value set providers using a script:
dojo.provide("org.example.workitems.providers.ValueSetSkeleton");

(function() {
dojo.declare("org.example.workitems.providers.ValueSetSkeleton", null, {

    getValueSet: function(attributeId, workItem, configuration) {
        var result= [];
        result.push("a");
        result.push("b");
        return result;
    }
});
})();
Here is an example that defines which Severity levels are available based on the tags of a work item. If the work item is tagged as important, only the Major, Critical and Blocker severities can be specified for this item. If it is not tagged as important all severity levels are enabled:
dojo.provide("org.example.workitems.providers.SeverityTagValueSet");

dojo.require("com.ibm.team.workitem.api.common.WorkItemAttributes");
dojo.require("dojo.string");

(function() {
var WorkItemAttributes= com.ibm.team.workitem.api.common.WorkItemAttributes;

dojo.declare("org.example.workitems.providers.SeverityTagValueSet", null, {

    getValueSet: function(attributeId, workItem, configuration) {
    
        var tags= workItem.getValue(WorkItemAttributes.TAGS);
        var severityOptions= [];
        
        if (tags.indexOf("important") === -1) {
            severityOptions.push("severity.literal.l1"); // Unclassified
            severityOptions.push("severity.literal.l2"); // Minor
            severityOptions.push("severity.literal.l3"); // Normal
        }
        
        severityOptions.push("severity.literal.l4"); // Major
        severityOptions.push("severity.literal.l5"); // Critical
        severityOptions.push("severity.literal.l6"); // Blocker

        return severityOptions;
    }
});
})();
Note: The example above uses the Severity Enumeration. You can find more information about using Enumerations in the Working with Enumerations section.
When configuring an attribute with the above customization the Severity attribute should include a dependency on the Tags attribute.

Validators

A validator can be applied to a work item attribute in order to assure that the value of the attribute fulfils certain conditions. Attributes which have attached validators are checked in three different situations:
  • In the WebUI when the user is editing the attribute. If the value is invalid an icon will be displayed. This icon can be configured to represent an Error, a Warning or Information Only.
  • In the Eclipse client when the user is editing the attribute. Like above an icon is displayed.
  • When the work item containing the attribute is saved. This is only true if the behavior of the save operation has been manually configured in Team Configuration, Operation Behavior to require attribute validation. Otherwise attributes are not checked when saved. Furthermore attributes which are not required and are left empty will never be validated.
In all three cases you can configure the validator with a message that is displayed when a value is invalid.
Note: When using a validator for an attribute, you should carefully choose the presentation of the attribute. Some presentations do not show validation results, and users can be confused by the lack of error notifications when an attribute value is invalid. Presentations behave differently in the Eclipse client and the WebUI. The discussion of validators below includes information about suitable editor presentations. No matter what presentation you choose to use, all attribute values will be validated when they are saved on the server if Attribute validation is configured as a precondition for saving in Team Configuration, Operation Behavior.
Here is a summary of all Validator customizations that can be configured using the Eclipse client:
Customization typeApplicable to attributes of type
Number RangeInteger, Long
Regular ExpressionSmall String, Medium String, Large String, Medium HTML, Large HTML
Script Based ValidationAny attribute type

Number Range

You can use this validator in order to restrict the values an attribute may have to a single range, defined by a minimum and a maximum value. You can configure the allowed range using the Eclipse client. In addition you can also configure a message to be displayed when validation fails and a corresponding icon:
Depending on the type of the validated attribute, you can use different editor presentations. The table below defines the validation behavior for all possible cases.
NumberRange validator on Integer and Long attribute types
Presentation kindInteger/LongString
Works in Web UINO
Works in EclipseNO (can't edit)
Works on Save

Regular Expression

You can use this validator to require that a string matches a certain regular expression. You can fully configure this validator using the Eclipse client:
Depending on the type of the validated attribute, you can use different editor presentations. The tables below define the validation behavior for all possible cases.
RegEx validator on a Medium/Large HTML attribute type
Presentation kindDescriptionHTMLSmallHTMLStringText
Works in Web UI✓ (in preview mode)✓ (in preview mode)NO
Works in EclipseNONO✓ (on focus change)NO (can't edit)
Works on Save
RegEx validator on a Small/Medium/Large String attribute type
Presentation kindCheckbox Multi-select ListDescriptionMulti-select listStringText
Works in Web UI✓ (in preview mode)NO
Works in EclipseNO
Works on Save

Script Based Validation

Note: You can find general information about script-based attribute customization in the Using scripts for attribute customization section.
You can also provide a custom validator using a script. Here is a skeleton for validators:
dojo.provide("com.example.Condition");

dojo.require("com.ibm.team.workitem.api.common.Severity");
dojo.require("com.ibm.team.workitem.api.common.Status");

(function() {
    
    var Severity = com.ibm.team.workitem.api.common.Severity;
    var Status = com.ibm.team.workitem.api.common.Status;
    
    dojo.declare("com.example.Condition", null, {

    validate: function(attributeId, workItem, configuration) {
        
        return new Status(Severity["ERROR"], "Validation failed");
    }
});
})();
A validation script must declare the function validate which returns a Status object. A status indicates the severity of the validation error and an error message. If the validation passed successfully the OK status should be used:
return Status.OK_STATUS;
Possible severity levels are:
Severity["OK"]
Severity["INFO"]
Severity["WARNING"]
Severity["ERROR"]
Here is an example of a validator that makes sure the date specified by one attribute comes after the date specified by another:
dojo.provide("org.example.DateValidator");

dojo.require("com.ibm.team.workitem.api.common.Severity");
dojo.require("com.ibm.team.workitem.api.common.Status");
dojo.require("dojo.date"); // We need the date class from Dojo to compare two dates
dojo.require("dojo.date.stamp"); // We need the stamp class to work with ISO date strings

(function() {
var Severity = com.ibm.team.workitem.api.common.Severity;
var Status = com.ibm.team.workitem.api.common.Status;

var DateValidator = dojo.declare("org.example.DateValidator", null, {

    validate: function(attributeId, workItem, configuration) {
    
        // Get the configuration parameters about the severity and error message of this validator
        var severity= configuration.getChild("parameters").getStringDefault("severity", Severity.ERROR.name);
        var message= configuration.getChild("parameters").getStringDefault("message", "");
        
        // Get the begin date attribute from the configuration and make a Date object from it
        var beginDateId = configuration.getChild("parameters").getStringDefault("beginDateAttributeId", "");
        var beginDate = dojo.date.stamp.fromISOString(workItem.getValue(beginDateId));
        
        // Get the current attribute's value and make a Date object from it
        var endDate= dojo.date.stamp.fromISOString(workItem.getValue(attributeId));
        
        // Compare the two dates and make sure endDate is not earlier than beginDate
        if (dojo.date.compare(endDate, beginDate) >= 0) {
            return Status.OK_STATUS;
        } else {
            return new Status(Severity[severity], message);
        }
    }
});
})();
You need to configure this script in the Process Configuration Source:
<validator id="dateval" name="Date Validator" providerId="com.ibm.team.workitem.shared.common.internal.valueProviders.ScriptAttributeValueProvider">

    <script class="org.example.DateValidator" path="/workitem/scripts/common/DateValidator.js"/>
    <parameters beginDateAttributeId="startdate" message="The completion date can not be earlier than the start date" severity="ERROR"/>
</validator>
Note: This validator depends on the value of another attribute ("startdate" in this case). It is important that you explicitly set this dependency in the attribute properties for the attribute that uses this validator.

Conditions

Conditions are a special type of customization that is used to dynamically determine required attributes. Conditions are evaluated for an entire work item and if a condition is met any attributes associated with it will be required.
Currently only script-based conditions are supported.
Note: You can find general information about script-based attribute customization in the Using scripts for attribute customization section.
Currently, you can only use conditions to dynamically determine required attributes, but we plan to expand their applicability. The rest of this section will demonstrate how to configure a condition to dynamically determine required attributes. The configuration of this customization consists of two steps:
  • In the Attribute Customization section of the process configuration, create a new Condition .
  • In the Operation Behavior section of the process configuration, create a pre-condition of type Dynamic Required Attributes. Associate the condition you created with one or more attributes.
Whenever the user saves a work item, all conditions will be evaluated. If a condition is met any associated attributes will be required.
Here is a skeleton of a script that implements a condition:
dojo.provide("org.example.workitems.providers.ConditionTest");

(function() {
dojo.declare("org.example.workitems.providers.ConditionTest", null, {

    matches: function(workItem, configuration) {
        return true;
    }
});
})();
Notice that a condition only has two arguments. There is no attributeId argument since a condition is not associated with any particular attribute.
Here is an example of a condition that is true whenever the state of an item is Resolved or Verified:
dojo.provide("org.example.workitems.providers.FinishedCondition");

dojo.require("com.ibm.team.workitem.api.common.WorkItemAttributes");

(function() {
var WorkItemAttributes= com.ibm.team.workitem.api.common.WorkItemAttributes;

dojo.declare("org.example.workitems.providers.FinishedCondition", null, {

    matches: function(workItem, configuration) {
        var state= workItem.getValue(WorkItemAttributes.STATE);
        console.log(typeof(state))
        return (state === "3" || state === "4"); // Resolved or Verified state
    }
});
})();
You can configure this condition to be checked when saving the work item in order to require that an attribute is set for items which have been completed. The screen shot below contains a Dynamic Required Attributes pre-condition that requires the Estimate attribute whenever the Finished condition is met:

Debugging scripts

Here are a few hints about debugging scripts used for attribute customization.

WebUI

By default all scripts sent to the browser are preprocessed for efficiency. This includes combining files, reducing white space and shortening identifier names. The preprocessed Javascript is not suitable for debugging and you can disable it by including the special argument
debug=true
in the URL for a web-page. For example:
https://Your.Site.Name:9443/ccm/web/projects/MyProject?debug=true#action=com.ibm.team.workitem.newWorkItem&type=defect&ts=13058802500900
https://Your.Site.Name:9443/ccm/web/projects/MyProject?debug=true#action=com.ibm.team.workitem.viewWorkItem&id=132
Doing this will disable all preprocessing of the Javascript files and will enable tools like Firebug to easily debug scripts inside a web browser. A limitation of this approach is that only validators and calculated values are executed in the browser, the other type of customizations only run on the server.

RTC Server / Eclipse Client

While it is not yet possible to set break points inside of scripts running on the server, it is possible to output messages to the server log. Use the following in your Javascript file:
console.log("My message");
The result in the log will be similar to:
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2011-05-20 10:56:15.980
!MESSAGE LOG: My message
You will find the log entries in these files:
  • Server: JazzTeamServer/server/tomcat/work/Catalina/localhost/ccm/eclipse/workspace/.metadata/.log
  • Eclipse client: client/eclipse/workspace/.metadata/.log

Providing new customizations implemented in Java

Note: This is an advanced topic meant for experts users only. If you need to implement your own customization behavior, consider using a script-based approach first.
It is possible to also implement new customizations in Java. The advantages of this approach are that the available Java API has more functionality and that there is better tool support. However there are some major disadvantages. A plug-in that implements a customization needs provisioning for the client and for the server and can not be deployed dynamically. Furthermore customizations implemented using Java do not work in the WebUI.
Consider the following points regarding Java based customizations of different categories:
  • Dynamic customizations such as validators and calculated values will only work on the server side and in the Eclipse client. Users of the WebUI will not get immediate feedback if a validation fails or if a calculated value needs to be recomputed. Users of the WebUI will need to first save the current work item and may have to refresh the web page in order for the new values to be visible.
  • Default values, value sets and conditions should work fine, as they are executed only on the server side.
Providing a Java based customization consists of the following steps:
  1. Create a new plug-in that extends the com.ibm.team.workitem.common.attributeValueProviders extension point by implementing the desired customization.
  2. Create a feature that contains the plug-in and an update site for this feature.
  3. Provision the RTC server and Eclipse clients by using the update site containing the new feature.
  4. Configure attributes to use the new customization. This step is identical with the case of built-in customization.
A step-by-step tutorial about creating a plug-in for RTC and provisioning the server is available here. The following section contains specific details for creating plug-ins that provide attribute customization. Examples of Java based customizations can be found here: Attribute Customization Examples.

Creating a plug-in that contributes an attribute customization

  1. Create a new Plug-in project:
    • An activator is not necessary.
    • The project does not use any predefined template.
  2. Edit the plug-in configuration:
    • On the Dependencies tab add the following dependencies:
      • Required plug-ins
        • com.ibm.team.workitem.common
        • com.ibm.team.repository.common
        • org.eclipse.core.runtime
    • On the Extensions tab:
      • Add a new extension of type com.ibm.team.workitem.common.attributeValueProviders.
      • Right click on the new extension and select New:

        The menu allows you to choose what category your new customization should be created for. Choose one and configure its mandatory attributes:
        • id The id of this customization.
        • name The name of this customization. This is the Type which is displayed when the user chooses a customization within a category.
        • class The class that will implement this customization.
      • Right click on the new customization and select New > attributeType. This allows you to set what attribute types can the new customization be applied to. Possible type ids include:
        • integer
        • long
        • smallString
        • mediumString
        • string
        • mediumHtml
        • html
        • wiki
        • interval
        • contributor
        • category
        • contributorList
        • subscriptions
        • enumeration
        • * (any type)
      • In the end the configuration should look similar to this:
      • Click on the class link to create the new class that will implement this customization. This will create a skeleton that includes all necessary imports and interface references.
  3. Implement the custom functionality that you require in the class that you configured in the plug-in manifest. Here is an example:
    package org.example.attributecustomization;
    
    import org.eclipse.core.runtime.IProgressMonitor;
    
    import com.ibm.team.repository.common.TeamRepositoryException;
    import com.ibm.team.workitem.common.IWorkItemCommon;
    import com.ibm.team.workitem.common.internal.attributeValueProviders.IConfiguration;
    import com.ibm.team.workitem.common.internal.attributeValueProviders.IValueProvider;
    import com.ibm.team.workitem.common.model.IAttribute;
    import com.ibm.team.workitem.common.model.IWorkItem;
    
    public class MyValueProvider implements IValueProvider {
    
        @Override
        public String getValue(IAttribute attribute, IWorkItem workItem,
                IWorkItemCommon workItemCommon, IConfiguration configuration,
                IProgressMonitor monitor) throws TeamRepositoryException {
    
            // This example simply returns the name of the attribute as a calculated value
            return attribute.getIdentifier();
        }
    
    }

Provisioning the RTC server

After the plug-in is created the RTC servers needs to be provisioned:
  1. Create a Feature that includes the new plug-in.
  2. Create a Site that includes the Feature.
  3. Build the Site. This will create two folders Plugins and Features and a site.xml file.
  4. You need to copy the two folders and the file into a new folder in the server. The new folder's name should be something like attribute-customization-site and should be placed in the sites folder of your RTC configuration:
    • For CLM builds this is usually \server\conf\ccm\sites
    • For RTC-only builds this usually \server\conf\jazz\sites In the end the folder structure should look like this:
    • server\conf\ccm\sites
    • server\conf\ccm\sites\attribute-customization-site
    • server\conf\ccm\sites\attribute-customization-site\site.xml
    • server\conf\ccm\sites\attribute-customization-site\plugins
    • server\conf\ccm\sites\attribute-customization-site\plugins\plugin.jar
    • server\conf\ccm\sites\attribute-customization-site\features
    • server\conf\ccm\sites\attribute-customization-site\features\feature.jar
  5. Finally, in order to enable the new update site you need to create a new provision profile file server\conf\ccm\provision_profiles\attribute-customization-site.ini. Substitute ccm with jazzfor RTC-only installs. The content of the file should be:
    url=file:ccm/sites/attribute-customization-site
    featureid=CustomValueProviderFeature
    

    Where the url should point to the relative location of the site folder you created and the featureid should match the ID of the feature you created.
  6. Restart the server. To make sure that it has been provisioned properly go to https://Your.Server.Name:9443/ccm/admin?showinternal=true#action=com.ibm.team.repository.admin.provisionStatus. Your new feature and plug-in should appear in the log.

Provisioning the Eclipse Client

In order for the new customization to be configurable via the Eclipse client you need to install it first:
  1. Open the Plug-ins installation manager from the menu Help > Install new software...
  2. Click Add... and then Local.... Open the directory containing the install site you created and click OK.
  3. From the list select the new feature and finish the installation.
These steps must be performed for each Eclipse client that will use the new customization features.


댓글 없음:

댓글 쓰기