레이블이 process인 게시물을 표시합니다. 모든 게시물 표시
레이블이 process인 게시물을 표시합니다. 모든 게시물 표시

2011년 12월 27일 화요일

Team Process REST API (Draft)

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


This guide is accurate for Foundation 3.Next (RTC 3.Next). Older revisions: Foundation 3.0.1 (RTC3.0.1), Foundation 3.0 (RTC3.0), Foundation 1.0 (RTC 2.0).


WARNING: THIS IS WORK IN PROGRESS FOR Foundation 1.0.0.1 AND HIGHER.
THIS IS PROVISIONAL API AND MAY CHANGE IN THE NEXT RELEASE.

DRAFT - Process REST API


-

2011년 12월 18일 일요일

Team Process - 프로세스 기본 흐름


 The process framework is split between the client and repository. The basic flow of control is:
  1. User starts process-enabled operation
  2. Client runs client-side advisors (potentially failing the operation)
  3. Client requests that server run the operation
  4. Server runs server-side advisors (potentially failing the operation)
  5. Operation completes on server
  6. Operation completes on client
  7. Client renders successful operation in Team Advisor view 

Team Process - 오퍼레이션 행위 결정

출처 : http://jazz.net/library/article/292
Process behavior lookup in Rational Team Concert 2.0


사용자가 프로세스 활용 오퍼레이션을 수행할 때는 만족해야 할 전제조건, 실행할 후속조치를 결정하는 데, 이를 일컬어 오퍼레이션 "동작"이라고 합니다. 동작은 사용자에게 지정된 역할, 오퍼레이션이 수행되는 프로세스 영역, 수행되는 시점에 따라 계산됩니다. 정확한 동작을 위해선 이런 여러 요소들을 정확히 조합해야 합니다. 

프로세스 런타임에 의해 수행될 전제 조건과 후속 조치는 프로세스 XML에서 선택된 단일 "오퍼레이션" 요소로 부터 비롯됩니다. 이런 요소를 일컬어 "오퍼레이션 구성" 또는 "동작 구성" 이라 합니다.  각각의 오퍼레이션 구성은 하나의 유닛 단위로 제한하며, 여러 구성을 조합해서 전제 조건과 후속 조치를 만들지 않습니다. 팀 프로세스가 복잡해 지면, 여러 오퍼레이션 구성을 있게 됩니다. 오퍼레인션 동작은 프로젝트 영역과 각 팀 영역별로 다르게 구성할 수 있습니다. 프로젝트 영역이나 각 팀 영역 내에서도, 각 반복 유형별로 그리고 각 반복 인스턴스별로 동작을 구성할 수 있습니다. 그리고 이들 내에서, 같은 오퍼레이션는 각각의 역할별로 구성할 수 있습니다. 이런 요소들을 살펴보고 정확한 구성을 찾을 수 있습니다.

어떻게 검색하는 지 간단히 요약하면 다음과 같습니다. 아래에서는 각각을 분해해서 알고리즘을 상세히 알려드리겠습니다. 검색은 해당 오퍼레이션을 지배하는 프로세스 영역으로 부터 출발합니다. 사용자에게 지정된 각각의 역할에 대해, 오퍼레이션에 대한 구성을 지배하는 프로세스 영역에서 먼저 찾고 차례로 거슬러서 프로젝트 영역까지 검색합니다. 하나의 영역에서 여러 반복에 대해 구성을 한 경우에는, 현재 시점에 가정 적합한 구성을 선택합니다. 사용자의 역할들 중 가장 먼저 찾은 동작 구성를 사용합니다.

Team Process - 오퍼레이션 권한 결정

출처 : http://jazz.net/library/article/291
Process permissions lookup in RTC 2.0

사용자가 프로세스 활용 오퍼레이션을 수행할 때는, 사용자가 시도하는 조치를 수행하도록 허용되는 지를 알아야 합니다. 프로세스에 친숙한 째즈 사용자는 사용자에게 지정된 역할, 오퍼레이션을 지배하는 프로세스 영역, 오퍼레이션이 수행되는 시점에 따라 허가 여부를 계산하고 있음을 알고 있습니다. 하지만 이런 요소들이 정확이 어떻게 조합되어 사용자에 대한 허가 여부를 결정하는 것일 까요?


먼저, 허가에 대한 간단한 소개를 합니다 : 
모든 역할은 역할에 부여된 허가만을 갖습니다. 한 곳에서 특정 역할에 부여된 해당 오퍼레이션을 수행할 수 있는 허가라 하더라도, 다른 곳에서는 해당 오퍼레이션에 대한 허가를 부여하지 않을 수 있습니다(XML로 표현하면, 해당 오퍼레이션 블록에 하위 "action" 요소를 제거함).  따라서 프로세스 런타임이 허가 여부를 체크할 때는, 기본적으로 XML 요소를 검색하여 사용자에게 허가된 목록을 알아내고, 사용자가 수행할려고 하는 조치 목록을 비교함으로 알 수 있습니다.


프로세스 허가 검색과정은 오퍼레이션 행위 판정에 기술된 내용과 거의 똑같습니다. 일단 오퍼레이션 동작 검색 방법을 이해하게 되면, 허가 검색 과정도 거의 이해할 수 있습니다. 허가 검색과 동작 검색 간의 핵심적인 차이점은, 동작은 XML로 부터 하나의 "오퍼레이션 동작 구성"를 선택한다면, 허가는 잠재적으로 복수의 "오퍼레이션 허가 구성"을 각각의 사용자 역할에 대해 선택한다는 점입니다. 결과적으로 사용자는 각 역할에 부여된 허가를 (모두) 보유하게 됩니다.


다음 예제 시나리오를 살펴보죠 : 
여러분의 팀은 role 1 만이 action A를 수행할 수 있고, role 2 만이 action B를 수행할 수 있도록 구성했습니다. 만약 어떤 사용자에게 role 1과 role 2를 지정했고, action A와 action B를 수행할려고 한다면, 모두 수행할 수 있습니다. 그 까닭은 프로세스 런타임은 먼저 role 1에 대한 구성 정보(action A 수행을 허가함)을 얻고, 다음에는 role 2에 대한 구성 정보(action B 수행을 허가함)를 얻고, 두가지 action에 대해 판단을 한 다음, 해당 오퍼레이션이 수행되도록 허락을 합니다.

Team Process - 확장 개발 가이드

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

This guide is accurate for Foundation 3.0.1, Foundation 3.0, and Foundation 1.0 (RTC 2.0).



Overview

A project area represents a development project. A project area contains a multi-rooted hierarchy of team areas. (We sometimes refer to both project areas and team areas asprocess areas.)
A project area is associated with a team process. Part of the team process is a specification of the executable process. Teams specify their process by configuring operations, events, and data.
A project area may have a set of timelines. Each timeline may be broken down into a set of iterations. An iteration is an interval in the lifetime of the project. An iteration can be decomposed into sub iterations. One timeline can be marked as the project timeline. This is the overall timeline for the project and all its teams. Additional timelines can be defined and root team areas can be assigned to them. When a root team area is assigned to a specific timeline, that team and all child team areas will be governed by the specified timeline instead of the project timeline. (Conceptually, this timeline + team area association can be thought of as a kind of "sub-project" on its own schedule.)
The project area can also define a set of iteration types which can be assigned to iterations. A project's permissions and behavior can be customized for any given timeline, iteration, or iteration type.
The process template chosen when creating a project area declares the initial set of timelines, iterations, and iteration types, along with a default executable process. The process template may also define a set of initial setup actions which are run when a newly created project area is initialized.
An example executable process specification looks like this:

    
        
            
                
                    
                    
                
            
        
        
            
                  
            
        
    
    
        
            
                
                    
                    
                
            
        
        
            
                
                    
                        
                        
                    
                
            
        
    


Each team area can override the permissions and behavior defined in the process specification by specifying a new configuration in its team customization. The actual executable process governing a team area is determined at runtime by the executable process of its project area patched by all overriding configurations. The search path for overriding configurations starts at the team area and goes up the team area hierarchy to the root. From the root it goes to the project area. Configurations can only be overridden if they are not marked as final in any node closer to the end of the search path.
(A detailed explanation of the runtime's search path can be found in the Process Behavior Lookup article.)
The specification of an overriding configuration in the team customization looks similar to the process specification with the difference that it only talks about the iterations and roles whose configurations it wants to override.

    
        
    
    
        
            
            
        
        
            
                
                
            
        
    

Components and Process

Components usually interact with the Team Process component in two ways:
  • a component allows the team process to impact its behavior
  • a component extends the set of choices that are available when configuring behavior
Components that allow the team process to impact their behavior can do so along three different lines corresponding to the three different kinds of configuration points:
  • Operations when a component wants to allow teams to configure permissions or when the components wants to allow preparation steps such as precondition checking or automated followup actions. These additional contributions to the operation are called advisors and participants. Advisors are run in advance and determine whether or not an operation should be executed. Participants are run after an operation is executed and generally cause additional modifications to the repository related to the operation. (Note: In the user interface, advisors are called "preconditions" and participants are called "follow-up actions".)
  • Configuration data when the component wants to allow the team process to provide XML data. The format of the configuration data is defined by the component. The component can access the data at any point in time and can do whatever it wants with it.
  • Events when a component issues change events for which it wants to allow the process to define server side event handlers.
Components that want to extend the set of available behaviors may add new participants, advisors and event handlers.

Open up for Process Interaction

In order to open up for process interaction the following plug-ins are required:
  • On the server
    • com.ibm.team.process.common
    • com.ibm.team.process.service
  • On the client
    • com.ibm.team.process.common
    • com.ibm.team.process.client

Operations

A component can open up for process participation in operations on the server and on the client. Process can "advise and execute" operations or it can merely "advise" them. Simply advising an operation is intended to answer the question for the user "What would happen if I did this now?"

Process Execution of Operations

When process is asked to advise and execute an operation, it will first run all advisors which are configured for the operation. Conceptually, advisors decide whether or not an operation should proceed. Advisors report any problems in the form of errors. If no advisors report any errors, the process runtime will invoke the operation. After the operation completes, participants are invoked. If a participant fails for some reason, either throwing an uncaught exception or reporting an error, no further participants are executed. This is the same for both the client and server process.
There is an important difference between the client and server process, though. The server process runs the entire request to advise and execute an operation in a single transaction. All advisors, the operation, and all participants are run in this transaction and if any errors are detected or any exceptions thrown, the entire transaction is rolled back. But if a participant fails on the client, the operation and any participants which have already run will have already done their work. For this reason, we say that client-side participants (and advisors) may not cause modifications to the repository.

Process Advising of Operations

When process is asked to only advise an operation, it will first run all advisors which are configured for the operation. The advisors will produce their errors and then process will call the advise(...) method on the operation. AdvisableOperation#advise(...) is a method which subclasses may optionally implement if the operation has some code that it wants to perform to participate in the advising.
For example, a client-side operation may support performing server-side checks. The client-side operation would implement advise(...) to call a service method. The service implementation would then ask the server-side process to advise an operation and it would return the result to the client. The client's implementation of advise(...) would then return this result. A concrete example of this scenario can be seen in the implementation of IExampleClientService#save(IExampleItem, boolean)

Defining Operations on the Server

  • The component defines an operation configuration point:
   
      
   
  • Please see ProcessExtensionSchemas to learn about how to define a schema.
  • The component wraps its operation implementation into an AdvisableOperation and passes it to the server-side team process for a certain team or project area. Usually, the operation affects an item that is associated with an area. However, the component decides which area to use.
  • A process enabled server operation should include the operation report generated for the advisable operation into its response to the caller. This can be done by either extending the component specific server response to piggyback the operation report or by defining the service method to return a response of one of the operation response types provided by the process component.
The implementation of a server-side operation might look something like this:
   public class MySaveOperation extends AdvisableOperation {
      private MyItem itemToSave;
      private MyItem saved;
      private IRepositoryItemService itemService;
      public MySaveOperation(MyItem itemToSave, IProcessArea processArea, IRepositoryItemService itemService) {
         super("com.ibm.example.service.mySaveOperation", itemToSave, processArea);
         this.itemToSave = itemToSave;
         this.itemService = itemService;
      }
      public IOperationReport run(IBehaviorConfiguration configuration, IProgressMonitor monitor) throws TeamRepositoryException {
         saved = (MyItem) service.saveItem(item, monitor);
         return null; // No nested report to return.
      }
      public MyItem getSavedItem() {
         return saved;
      }
   }
The component's service implementation would then invoke this operation:
   public IItemsResponse saveItem(MyItem itemToSave) throws TeamRepositoryException {
      IProcessArea processArea = findProcessArea(itemToSave); // custom component logic
      IRepositoryItemService itemService = getService(IRepositoryItemService.class);
      IProcessServerService processService = getService(IProcessServerService.class);
      IServerProcess serverProcess = processService.getServerProcess(processArea);

      MySaveOperation operation = new MySaveOperation(itemToSave, processArea, itemService);
      IOperationReport report = serverProcess.adviseAndExecute(operation);

      IItemsResponse response = ProcessCommon.createItemsResponse();  
      response.setOperationReport(report);
      MyItem saved = operation.getSavedItem();
      response.setClientItems(new IExampleItem[] { saved };

      return response;
   }
Grouping Operations on the Server (Process Runnables)
This section is not something most components are expected to utilize.
A ProcessRunnable is most commonly defined on the client to support implementing a server-side only operation. However, they can also be a useful tool for the purpose of grouping multiple server-side operations so that they will be run in a single transaction and grouped together when they are presented to the user.
A service method can run any number of process-enabled operations inside the context of a process runnable and it need only return the single report generated for the runnable in order to transfer all of the nested reports to the client as well. This works because the process framework automatically appends reports together when they are called in the same thread.
For example, the Process component defines a process runnable on the server when saving multiple team areas. Each team area is potentially saved according to a different process so they must be saved in separate operations. But by using a process runnable, all of these operations are grouped together at runtime (in a single transaction) and in the client UI (Team Advisor view).
The implementation of a server-side process runnable might look something like this:
   public class MyItemsSaveRunnable extends ProcessRunnable {
      private MyItem[] itemsToSave;
      private MyItem[] saved;
      private MyService service;

      public MyItemsSaveRunnable(MyItem[] itemsToSave, MyService service) {
         this.itemsToSave = itemsToSave;
         this.service = service;
      }
      public IOperationReport run(IProgressMonitor monitor) {
         saved = new MyItem[itemsToSave.length];
         for (int i = 0; i < itemsToSave.length; i++) {
            // Invoke component logic which saves an item using an operation
            saved[i] = service.internalSaveItem(item);
         }
         return null; // server-side runnables don't return anything
      }
      public MyItem[] getSavedItems() {
         return saved;
      }
   }
The component service would then execute this runnable:
   public IItemsResponse saveItems(final MyItem[] items) throws TeamRepositoryException {
      IProcessServerService processService = getService(IProcessServerService.class);
      MyItemsSaveRunnable runnable = new MyItemsSaveRunnable(items, this);
      IOperationReport report = processService.execute(runnable, "Save My Items");
      MyItem[] saved = runnable.getSavedItems();

      IItemsResponse response = ProcessCommon.createItemsResponse();
      response.setOperationReport(report);
      reponse.setClientItems(saved);
      return response;
   }

Defining Operations on the Client

  • The component defines an operation configuration point:
   
      
   
  • Please see ProcessExtensionSchemas to learn about how to define a schema.
  • The component wraps its operation into an AdvisableOperation and passes it to the client-side team process for a certain team or project area. Usually, the operation affects an item that is associated with an area. However, the component decides which area to use.
  • When the operation involves the call of a process-enabled server-side service method, your implementation of the advisable operation's run method should return the server side generated operation report.
  • The server-side team process will throw a TeamOperationCanceledException in the event that the operation is canceled by process. This exception is currently a subclass ofTeamRepositoryException which carries an IOperationReport. If an AdvisableOperation calls a service method in run() and catches TeamRepositoryException (this is generally not recommended), the implementation should rethrow the exception if it is a TeamOperationCanceledException.
The implementation of a client-side operation might look something like this:
   public class MySaveOperation extends AdvisableOperation {
      private MyItem itemToSave;
      private MyItem saved;
      private MyService service;
      public MySaveOperation(MyItem itemToSave, IProcessArea processArea, MyService service) {
         super("com.ibm.example.client.mySaveOperation", itemToSave, processArea);
         this.itemToSave = itemToSave;
         this.service = service;
      }
      public IOperationReport run(IBehaviorConfigurationconfiguration, IProgressMonitor monitor) throws TeamRepositoryException {
         IItemsResponse serviceResponse = service.saveItem(itemToSave, monitor); // invoke the service method
         saved = (MyItem) response.getFirstClientItem;
         return response.getOperationReport(); // Return the nested server-side report.
      }
      public MyItem getSavedItem() {
         return saved;
      }
   }
The component's client library would then invoke this operation:
   public MyItem saveItem(MyItem itemToSave, IProgressMonitor monitor) throws TeamRepositoryException {
      IProcessArea processArea = findProcessArea(itemToSave); // custom component logic
      MyService myService = (MyService) clientLibraryContext.getServiceInterface(IProcessService.class);
      IProcessClientService processService = repository.getClientLibrary(IProcessClientService.class);
      IClientProcess clientProcess = processService.getClientProcess(processArea, monitor);

      MySaveOperation operation = MySaveOperation(itemToSave, processArea, myService);
      clientProcess.adviseAndExecute(operation);
      return operation.getSavedItem();
   }
Server-side Only Operations (Process Runnables)
If a component wishes to define a process-enabled operation on the server which in not invoked by a corresponding process-enabled operation on the client, a ProcessRunnable can be defined on the client which returns the server-side report to the process framework. By using a process runnable which returns the server-side report, a server-side only operation can be displayed to the end user by the process framework.
Process runnables are simply instantiated at runtime and passed to the process framework. They are not declared via an extension point, so they don't show up in the process specification. Process runnables do not allow for advisors, participants, or permission checking; they are just executed by the framework.
The implementation of a client-side process runnable might look something like:
   public class MyItemSaveRunnable extends ProcessRunnable {
      private MyItem itemToSave;
      private MyItem saved;
      private MyService service;

      public MyItemSaveRunnable(MyItem itemToSave, MyService service) {
         this.itemToSave = itemToSave;
         this.service = service;
      }
      public IOperationReport run(IProgressMonitor monitor) throws TeamRepositoryException {
         IItemsResponse response = service.saveItem(item, monitor);
         saved = (MyItem) response.getFirstClientItem();
         // Return the operation report from the server to the process framework.
         return response.getOperationReport();
      }
      public MyItem getSavedItem() {
         return savedItem;
      }
   }
The component's client library would then execute this process runnable:
   public MyItem saveItem(MyItem item, IProgressMonitor monitor) throws TeamRepositoryException {
      MyService service = clientLibraryContext.getServiceInterface(MyService.class);
      IProcessClientService processClient = (IProcessClientService) clientLibraryContext.getTeamRepository().getClientLibrary(IProcessClientService.class);

      MyItemSaveRunnable runnable = new MyItemSaveRunnable(item, service);
      processClient.execute(runnable, monitor);
      return runnable.getSavedItem();
   }

Operation Actions (Process Permissions)

Operations can declare a set of actions which they may perform. A team can then configure their process to selectively grant permission to perform those actions. At runtime, an operation can report which actions it will perform and process can allow/disallow the operation based on the applicable permissions.
An operation's available actions are declared in the client or server extension. For example:
   
      
         
            
            
         
      
   
The team would then configure the permitted actions:
   [...]
   
      
         
             
               
             
         
      
   
   [...]
Here, the process uses the special keyword "any" to specify that all "Modify" actions are allowed.
An operation can report any path in its declared actions at runtime. In this example, the "Save Example Item" operation could return the following values as actions:
  "Modify"
  "Modify/Description"
  "Modify/Name"
When process is asked to execute an operation, it asks it for the actions it will perform. These actions are then compared against the permissions which apply to the current logged in user. As long as the permitted action paths match the actions to be performed, process will execute the operation. Otherwise, the operation will be blocked and reported in the Team Advisor view.
Secondary Actions (Multi-Area Operations)
We say that an advisable operation is run relative to a process area and it can return a set of actions for the purpose of checking permissions. However, sometimes an operation needs to check permissions relative to more than just one process area and this is supported by allowing to specify "secondary" areas and actions.
This is important, for example, for an operation which moves an item from the context of one team area to another. In order to enforce a notion of ownership which is enforced by process permissions, such an operation would specify the source area as a secondary process area and return an appropriate action for this area, such as "remove".
Secondary areas are consulted only for permissions. Advisors and participants configured for secondary areas are not invoked.
An operation which moved an item from one team area to another and enforced permissions relative to both areas might look something like:
   public class MyItemMoveOperation extends AdvisableOperation {
      IProcessArea sourceArea;
      
      public MyItemMoveOperation(MyItem itemToMove, IProcessArea targetArea, IProcessArea sourceArea) {
         // Use targetArea as the operation's primary area
         super("com.example.moveItem", itemToMove, targetArea);
         this.sourceArea = sourceArea;
      }
      public IOperationReport run(...) {
          [...]
      }
      public String[] getActions() {
         // Return actions for the operation's process area (targetArea)
         return new String[] { "add" };
      }
      public IProcessArea[] getSecondaryAreas() {
         return new IProcessArea[] { sourceArea };
      }
      public String[] getActions(IProcessArea secondaryArea) {
         if (secondaryArea.sameItemId(sourceArea)) {
            return new String[] { "remove" };
         }
         return super.getActions(secondaryArea);
      }
   }

Process Data Validation (Configuration Source)

For operations which run on the client and server, the process framework provides a mechanism to validate that clients are running up-to-date process.
When a client-side operation is run, we pass in the IBehaviorConfiguration which configures the operation. This object carries an "operation configuration info" object which contains information about exactly which process configuration was used (see IBehaviorConfiguration#getOperationConfigurationInfo()). The client-side operation can pass this IOperationConfigurationInfo over the wire in its service method.
On the server, we have API which takes one of these configuration info objects and validates that the configuration which was run on the client in sync with the current repository contents (IServerProcess#validateSource(IOperationConfigurationInfo)). If validation fails, an exception is thrown.
Back on the client, process catches this exception from the client-side operation, updates the client's process data, and re-runs the operation (if the operation supports this). Tying into this mechanism provides a seamless experience for the end user.

Configuration Data

A component can open up for configuration data on the server and on the client. Configuration data, independent of where it has been declared, can always be accessed on both the client and the server without limitation. Configuration data can only be defined in the project area and is global in nature. Configuration data should be used sparingly, only in situations where the data in question is really part of a project's process. In particular, components are warned against using configuration data for settings which should really be user preferences or which should be persisted as part of their component model and configured in their own editors.

Configuration Data on the Server

  • The component defines a configuration data configuration-point (the element name "staticConfigurationData" is a holdover which will be changed to "configurationData" eventually):
   
      
   
  • Please see ProcessExtensionSchemas to learn about how to define a schema.
  • The component retrieves the configuration data from the server-side team process for the project area.
   IProcessArea processArea = findProcessArea(parameter);
   IProcessServerService service = (IProcessServerService) getService(IProcessServerService.class);
   IServerProcess serverProcess = service.getServerProcess(processArea);
   IProcessConfigurationData data = serverProcess.getProjectConfigurationData("com.ibm.team.process.example.elementPreferences");
   if (data != null) {
      IProcessConfigurationElement[] elements = data.getElements();
      for (int i = 0; i < elements.length; i++) {
         IProcessConfigurationElement element = elements[i];
         ...
      }
   }

Configuration Data on the Client

  • The component defines a static configuration data configuration-point:
   
      
   
  • Please see ProcessExtensionSchemas to learn about how to define a schema.
  • The component retrieves the configuration data from the client-side team process for the project area.
   IProcessArea processArea = findProcessArea(parameter);
   IProcessClientService processService = (IProcessClientService) repository.getClientLibrary(IProcessClientService.class);
   IClientProcess clientProcess = processService.getClientProcess(processArea, new SubProgressMontior(monitor, 1));
   IProcessConfiguration data = clientProcess.getProjectConfigurationData("com.ibm.team.process.example.itemTypes", new SubProgressMontior(monitor, 1));
   if (data != null) {
      IProcessConfigurationElement[] elements = data.getElements();
      for (int i = 0; i < elements.length; i++) {
         IProcessConfigurationElement element = elements[i];
         ...
      }
   }

Events

In order for a component's server part to allow process reaction to its change events, the component must define an event configuration point. The event's identifier corresponds to the value of IChangeEvent#getCategory()
The process server-side component installs a scheduling task on the server which queries for new change events at a regular interval and dispatches them to the event handlers which have been configured by the team.

Associate Items with a Process Area

All of the scenarios above have forced the component to retrieve a client or server-side process relative to a process area. Usually, the process area is determined based on the items affected by a particular operation and those items' association to a team area.
A component defines the way in which its items are associated with a process area. The typical way to do this is by adding a field to the item which references a process area.

Extending the Choices of Process

In order to extend the choices of process the following plug-ins are required:
  • On the client
    • com.ibm.team.process.common
    • com.ibm.team.process.client
    • com.ibm.team.process.ide.ui
  • On the server
    • com.ibm.team.process.commmon
    • com.ibm.team.process.service

Adding New Operation Advisors

Operation advisors are run before an operation is invoked to decide whether or not the operation should be executed. Advisors check conditions and report problems via the collector they are given at runtime. If an advisor reports a serious problem with an operation, the operation will not be executed (though subsequent advisors will still be checked).
Advisors may not make modifications to data which is persisted in the repository. If an advisor were to modify the data in the repository, its changes could invalidate the checks made by previous advisors which would potentially cause a team's desired preconditions to not be correctly enforced. Clients wishing to participate in operations by modifying data should implement a participant instead.
Client-side advisors support the notion of being optionally overrulable. If a team specifies that users can overrule an advisor, users have the freedom to ignore a particular advisor if they wish it. The support for overruling advisors is handled completely by the process framework. Advisor implementors do not need to do anything to support it. Note that at this time, onlyclient-side advisors support overruling.
Operation advisors can be provided for the client and the server side via the com.ibm.team.process.client.operationAdvisors and com.ibm.team.process.service.operationAdvisors extension points, respectively.
In order to provide a new advisor available in process definitions and process settings a component must:
  • Implement a new advisor by implementing com.ibm.team.process.common.advice.runtime.IOperationAdvisor.
  • Provide an extension to the operation advisor extension point to declare the new advisor
  • Optionally, a component may provide a schema which describes custom syntax for configuring the advisor. See ProcessExtensionSchemas for details.

  
    
      This advisor requires that everything is great before something can be modified.
    
  

If a server-side advisor does not make reference to any services, providing an implementation of this interface via an extension declaration like the example above is sufficient. However, there are two additional requirements for server-side implementors who wish to access services:
  • The implementation of this interface must also extend com.ibm.team.repository.service.AbstractService.
  • The extension declaration of such an advisor must include an extensionService element which declares all of the services which the advisor requires.
The following example shows a definition of a server-side advisor which requires the repository item service and the process server service:

  
    
      This advisor requires that everything is great before something can be modified.
    
    
      
        
        
      
    
  

Adding New Operation Participants

Operation participants run after an operation is invoked and may make modifications to the repository. In an operation fails (for example, because it is blocked by an advisor or if an exception occurs), its participants will not be invoked. On the server, participants are run in the same transaction as the operation in which they are participating.
If an participant throws an exception or reports a serious problem, subsequent participants will not be run. On the server, this will cause the entire operation transaction to be rolled back.
Operation participants can be provided for the client and the server side via the com.ibm.team.process.client.operationParticipants and com.ibm.team.process.service.operationParticipants extension points, respectively.
In order to provide a new participant which teams can configure for an operation a component must:
  • Implement a new participant by implementing com.ibm.team.process.common.advice.runtime.IOperationParticipant.
  • Provide an extension to the operation participant extension point to declare the new participant
  • Optionally, a component may provide a schema which describes custom syntax for configuring the participant. See ProcessExtensionSchemas for details.

  
    
      This participant creates a receipt whenever something is modified.
    
  

If a server-side participant does not make reference to any services, providing an implementation of this interface via an extension declaration like the example above is sufficient. However, there are two additional requirements for server-side implementors who wish to access services:
  • The implementation of this interface must also extend com.ibm.team.repository.service.AbstractService.
  • The extension declaration of such a participant must include an extensionService element which declares all of the services which the participant requires.
The following example shows a definition of a server-side participant which requires the repository item service and the process server service:

  
    
      This participant creates a receipt whenever something is modified.
    
    
      
        
        
      
    
  

Adding New Event Handlers

Event handlers can only be provided for the server side. In order to provide a new event handler which teams can configure for an event a component must:
  • Implement a new event handler by implementing the interface com.ibm.team.process.service.IChangeEventHandler.
  • Declare an extension to the event handler extension point to provide the new event handler.
  • Optionally, a component may provide a schema which describes custom syntax for configuring the handle. See ProcessExtensionSchemas for details.
   
      
   

Hooking in to Content Assist in the Process Editors

In addition to defining schema to describe the format of component specific data associated with a process related configuration point, component authors can register to provide completion proposals for attribute values when content assist is requested in the process editors.
For example, if your schema defines a new element "foo" with an attribute "type" and you want to provide the user with a list of valid values for the "type" attribute when content assist is requested, this mechanism will allow you to do that.
In order contribute your proposals, in one of your component's client-side plugins, you need to provide an extension to the com.ibm.team.process.ide.ui.attributeValueProposalProvidersextension point. Via this extension, you will indicate which source types (specifications and/or customization) you support and the attributes for which you intend to provide values. In addition, you must specify a class which implements com.ibm.team.process.ide.ui.IAttributeValueProposalProvider. This is the class which will be called to obtain the completion proposals. Please see the extension point description for additional details.
The following is an example extension which provides attribute value proposals for an attribute named "fooType" which appears on elements named "foo" in the "http://com.ibm.team.process.ide.ui.tests" namespace. Proposals are provide for both specification and customization source types:
    
       
          
          
          
          
          
             
                
                
             
          
       
    
The following is the code for the TestAttributeValueProvider class referenced by the extension.
public class TestAttributeValueProvider implements IAttributeValueProposalProvider {

   public TestAttributeValueProvider() {
   }

   public IProcessCompletionProposal[] computeProposals(IProcessArea processArea, IProcessProposalContext context, IProgressMonitor monitor) {
      
      ArrayList proposals = new ArrayList();
      
      switch (context.getSourceType()) {
         case IProcessProposalContext.SPECIFICATION_SOURCE_TYPE:
            if (processArea instanceof IProjectArea) {
               IProjectArea projectArea = (IProjectArea) processArea;
               List teamAreas = projectArea.getTeamAreas();
               
               ITeamRepository repo = (ITeamRepository) projectArea.getOrigin();
               IItemManager itemManager = repo.itemManager();
               try {
                  List items = itemManager.fetchCompleteItems(teamAreas, IItemManager.DEFAULT, monitor);
                  for (Iterator iterator = items.iterator(); iterator.hasNext();) {
                     ITeamArea teamArea = (ITeamArea) iterator.next();
                     if (teamArea != null) {
                        proposals.add(ProcessCompletionProposalFactory.createProposal(context, teamArea.getName()));
                     }
                     
                  }
               } catch (TeamRepositoryException e) {
                  // just ignore for this test / example provider...
               }
            } else {
               proposals.add(ProcessCompletionProposalFactory.createProposal(context, "A1"));
               proposals.add(ProcessCompletionProposalFactory.createProposal(context, "B1"));
               proposals.add(ProcessCompletionProposalFactory.createProposal(context, "C1"));
            }
            break;
         case IProcessProposalContext.CUSTOMIZATION_SOURCE_TYPE:
            proposals.add(ProcessCompletionProposalFactory.createProposal(context, "A2"));
            proposals.add(ProcessCompletionProposalFactory.createProposal(context, "B2"));
            proposals.add(ProcessCompletionProposalFactory.createProposal(context, "C2"));
            break;
      }
      
      return (IProcessCompletionProposal[]) proposals.toArray(new IProcessCompletionProposal[proposals.size()]);
   }
}
This particular provider provides a static list of proposals "A2", "B2", "C2" when invoked for the customization source type (e.g. when content assist is used in the Team Area editors 'customization' tab). When it is called for a specification source type and the process area provided is a project area (e.g. when content assist is used in the Project Area editor 'specification' tab) the proposals are the names of the team areas for the project area. When the provided process area is not a project area (i.e. content assist was invoked in the specification tab of a template editor), the proposals provided are "A1", "B1", "C1".
While this provider only provides for a single attribute, through the use of the namespace, element, and attribute configuration elements, a single provider can indicate its ability to provide for multiple attributes spanning multiple elements and/or namespaces.

Gotchas

The following are specific situations that we have discovered can be confusing for people who haven't yet totally absorbed the Team Process mindset.
  • Operations may involve other operations and the two may involve different processes. For example:
    • SCM stream HEAD is associated with team area Foo
    • Workitem category UI is associated with team area Bar
    • Deliver code to HEAD
      • For the deliver operation, the advisors and participants configured in team area Foo will be run
      • One of the deliver participants modifies a workitem whose category is UI
        • For the workitem save operation, the advisors and participants configured in team area Bar will be run