Process behavior lookup in Rational Team Concert 1.0
Summary
This article provides an overview of Process behavior lookup.
Note: After reading this article, you might want to read the follow-up article, Process Permissions Lookup.
Whenever a user performs a process-enabled operation, we must determine whether there are any preconditions that must be met and any follow-up actions that must be run. We call this an operation’s “behavior”. In Jazz, this behavior is computed based on the user’s assigned roles, the team area which governs the operation, and the point in time that the operation is being run. How exactly do these factors combine to determine the “correct” behavior?
The preconditions and follow-up actions that are executed by the process runtime come from a single “operation” element that is chosen from the process XML. We refer to such an element as an “operation configuration” or a “behavior configuration”. We treat each operation configuration as a self-contained unit; we never combine preconditions and follow-up actions from multiple configurations. Depending on the complexity of a team’s process, there can be many operation configurations to choose from. An operation’s behavior can be configured differently in every team area and project area. Within each team or project area, the behavior can be configured for each iteration type (such as “milestone end-game”), and for each iteration instance (such as Milestone 1, Milestone 2, etc.). Within each of those, the same operation can then be configured for every available role. We look up the correct configuration by traversing all of these elements and deciding when to stop. So how does that lookup work? How do we traverse these elements and how do we decide which operation configuration to use?
Here’s a basic summary of how the search works. Don’t worry if it doesn’t make too much sense yet; we will break this down and examine each aspect of the algorithm in more detail below. The lookup starts from the team area that governs the operation. For each of the roles that the user plays in the governing team area, we first look for a configuration in the governing team area and then work our way up the parent hierarchy to the project area. If an area configures behavior for different iterations, we choose the configuration that is most applicable to the current point in time. We use the behavior configuration that is found for the first of the user’s roles. Now let’s break down these steps to see what the implications are.
The lookup starts from the team area that governs the operation. Which team area governs the operation?
Each operation has its own way of determining which team area governs it based on the artifacts that the operation affects. We simply ask the operation which team area we should use, and it tells us. For example, when delivering change sets to a stream, the governing team area is the one which owns the target steam. And when saving a work item, the governing team area is the one that is associated with the work item’s category.
For example, consider the following two scenarios:
Scenario 1:
In this scenario, a developer is delivering a change set from Cool Developer’s Workspace to the Platform Core Stream. Because this stream is owned by the Platform Core Team, this team area governs the delivery process.
Scenario 2:
In this scenario, a developer is delivering a change set from Cool Developer’s Workspace to the Cool Tools Stream. Because this stream is owned by the Cool Tools Team, this team area governs the delivery process.For each of the roles that the user plays in that team area, we try to find a behavior configuration. How do we determine this set of roles and how do multiple roles interact?
When we have determined the governing team area, we try to find a behavior configuration for each of the roles that the logged-in user is assigned, in the order that they are assigned. For example, if a user is assigned the team lead and developer roles, we first try to find behavior configured for team leads. If we don’t find any behavior configured for team leads, then we try to find behavior for developers. Failing that, we try to find behavior for everyone (the “default” role). The first of these roles that is configured is the one whose behavior will take effect; we don’t combine behavior from multiple roles.
The complete set of roles that the user plays is composed of all roles assigned in the governing team area plus any roles assigned in parent team areas and the project area. When a user is assigned roles in a team or project area, those roles are assigned in a particular order. When we look for behavior, this ordering is taken to reflect the roles’ priority.
To compute all of a user’s roles, we have to combine roles from various team areas and the project area. How does this affect the ordering? First, any roles assigned in the governing team area are considered in order, then any roles in parent team areas, then any roles in the project area, and finally we consider the default role which applies to everyone in the repository. This means that any roles assigned in a team area take precedence over those assigned in a parent team area or project area. If the team wants a role from a parent team area to take priority over a role assigned at a lower level, the same role can be assigned to the same user again in the lower area. The priority of the role assignment in the lower area is the one that’s used.
For example, consider the following two scenarios:
Scenario 1:
In this scenario, new roles are assigned in the Cool SDK Project, Platform Team, and Platform Core Team. When behavior is sought for Platform Core Team, we consider the roles in the order: developer, buildmeister, team lead, project manager, project admin, default.
Scenario 2:
In this scenario, Platform Core Team reassigns some roles from the Cool SDK Project and Platform Team so that they are given priority. Note the difference in the resulting order. When behavior is sought for Platform Core Team, we consider the roles in the order: project manager, team lead, developer, buildmeister, project admin, default.
We first look for a configuration in the governing team area and then work our way up the parent hierarchy to the project area.
To find operation behavior for a role, we examine the configuration of the governing team area as well as the configuration of any parent team areas and the project area. First, we try to find behavior configured for the role in the governing team area. If the role isn’t configured in the governing team area, we then look in each successive parent team area and the project area until we find a configuration (that is, we take the “lowest” configuration that we find in the hierarchy). There is an exception to this rule, however, which is the “final” flag. If, for any team area or project area, the behavior that we find is configured as final, then we ignore any configurations which appear lower in child team areas. (More on the final flag to come.)
For example, consider the following two scenarios:
Scenario 1:
In this scenario, a developer is delivering a change set from Cool Developer’s Workspace to the Platform Core Stream. Because this stream is owned by the Platform Core Team, we examine the “Platform Core Team” team area, then the “Platform Team” team area, and finally the “Cool SDK Project” project area.
Scenario 2:
In this scenario, a developer is delivering a change set from Cool Developer’s Workspace to the Cool Tools Stream. Because this stream is owned by the Cool Tools Team, we examine the “Cool Tools Team” team area and then the “Cool SDK Project” project area.
If an area configures behavior for different iterations, we choose the configuration which is most applicable to the current point in time.
For each team area, we determine whether there is a behavior configuration for the role by examining the team customization. For project areas, we examine the “team configuration” section of the process specification. Within the team customization or process specification, behavior can be configured during particular iterations or it can be configured for all iterations. When looking for a behavior configuration, we consider customizations of the “current” iteration and its parent iterations.
We determine the current iteration from the development line that the governing team area belongs to. Every team area always belongs to exactly one development line and every development line has exactly one current iteration. Iterations can be defined hierarchically; in this case, any iteration at any point in the hierarchy may be flagged as current. The current iteration along with all parent iterations along the path up to the development line are considered. Each of these iterations may be of a particular type and each of these types may also be customized. How exactly do customization of iterations and iterations types interact?
We first look for the operation during the current iteration. If the operation isn’t configured for the current iteration, we then check if it is configured for the type of the current iteration. If the operation isn’t configured for the current iteration or its type, we then check if the operation is configured for the current iteration’s parent iteration, the type of the parent iteration, and so on up to the root of the team customization (or “team configuration” for the project area). By searching the path this way, we ensure that we use the behavior which is most appropriate for the current iteration.
Let’s look at a couple of scenarios to see what this means as a project moves through time. Consider an example where a project has defined the following iterations and a team area’s customization configures an operation at various points. (For this example, we ignore roles; but remember that this same lookup occurs for each of a user’s roles in order.)
Project Setup:
The Cool SDK Project defines two development lines: Main Development and 1.x Maintenance. The Main Development line defines a number of nested iterations and an iteration type called “stabilization”. Some of the iterations are declared as stabilization iterations. The “Platform Team” team area is defined in the Main Development line, so it can configure any of the iterations defined for this line. The customization configures the operation’s behavior for the “2.0 Development Phase” and “Milestone 2 Endgame” iterations (shown in brown and orange). It also configures the behavior for the “stabilization” iteration type (shown in purple).
Scenario 1: Milestone 1
In this example, we see how a behavior configuration is sought when the current iteration is “Milestone 1”. The search proceeds: does the Platform Team configure the behavior for Milestone 1? No. Does Milestone 1 have an iteration type? No. Does the Platform Team configure the behavior for the parent iteration, 2.0 Development Phase? Yes. So when the current iteration is Milestone 1, the behavior defined for the 2.0 Development Phase will be in effect.
Scenario 2: Milestone 1 Endgame
In this example, we see how a behavior configuration is sought when the current iteration is “Milestone 1 Endgame”. The search proceeds: does the Platform Team configure the behavior for Milestone 1 Endgame? No. Does Milestone 1 Endgame have an iteration type? Yes, “stabilization”. Does the Platform Team configure the behavior for the stabilization iteration type? Yes. So when the current iteration is Milestone 1 Endgame, the behavior defined for the “stabilization” iteration type will be in effect.
Scenario 3: Milestone 2 Endgame
In this example, we see how a behavior configuration is sought when the current iteration is “Milestone 2 Endgame”. The search proceeds: does the Platform Team configure the behavior for Milestone 2 Endgame? Yes. So when the current iteration is Milestone 2 Endgame, the behavior defined for the Milestone 2 Endgame iteration will be in effect. We see that the configuration of the iteration itself takes priority over configuration of the iteration’s type (“stabilization”).
Review Now that we understand how each piece of the search works, let’s put the pieces back together. In order to compute which preconditions and follow-up actions to run, we look for a configuration of the operation’s behavior following these steps:
- Decide which team area governs the operation.
- Compute which roles the user plays in that area by adding up all the role assignments from the governing area up to the project area.
- For each of these roles, in order:
- Start at the governing team area.
- For the governing team area and each parent team area up to and including the project area:
- Starting with the current iteration and working up any parent iterations:
- First, look for a configuration of the iteration itself.
- Second, look for a configuration of the iteration type.
- If a configuration is found in an area, remember this configuration.
- If a configuration is found in a parent area and it is declared as final, remember this configuration instead.
- Once we’ve looked all the way up the hierarchy, if we have a configuration, this is the one that is used,
- Starting with the current iteration and working up any parent iterations:
For our final example, we’ll walk through the lookup that occurs when a user delivers a change set to a stream.
First, we need to gather three pieces of information: the governing team area, the list of assigned roles, and the current iteration. To compute the governing team area, we ask the deliver operation which team area governs it. We use the “Platform Core Team” team area, since this area owns the stream we’re delivering to (“Platform Core Stream”). To compute the list of assigned roles, we start with the roles assigned in the Platform Core Team, then add the roles from the Platform Team, and finally the Cool SDK Project, ignoring any duplicate assignments. This gives us a role cast of project manager, team lead, developer, project admin, and default. To compute the current iteration, we query the project area. In this case, the current iteration is “Release Candidate 1”.
Taking the roles in order, we start with “project manager”. First we look in the Platform Core Team. We check if the project manager role’s behavior is configured for the “Release Candidate 1” iteration. Then we check Release Candidate 1’s iteration type (it doesn’t have one). Next, we check for a configuration for the parent iteration, “2.0 Stabilization Phase”, followed by the parent iteration’s type, “stabilization”. Finally, we check if the project manager role’s behavior is configured at the top level of the team customization. If we find a configuration, we remember it and stop examining the Platform Core Team.
Next we look for a configuration in the Platform Team. Again, we start with the current iteration. If we find a configuration for the Platform Team, we check if it is declared as “final”. If so, we remember this configuration; if not, we continue to remember any configuration from the Platform Core Team instead. After we’ve checked the Platform Team, we move on to the Cool SDK Project. The search for the project manager’s behavior in the Cool SDK Project is the same as the one we perform in each team area, except our search is limited to the team configuration section of the process specification. Again, if we find a configuration we check if it is final. If so, then this configuration is used; if not, we use whatever configuration we are remembering (if any) from the team area hierarchy.
If we search all the way to the project area and do not find a behavior configuration, we move on to the next role, “team lead”. Again, we start from the Platform Core Team and look for a configuration based on the current iteration and then we do the same for the Platform Team and Cool SDK Project. This continues for each role until the default role, which is always last.
Footnote on the “final” flag: The final flag doesn’t have any effect on the lookup that occurs within any given area (an area can’t declare that part of its own process should be ignored). This is important to note because it can be confusing if a team or project area contains a mix of final and non-final configurations. In these situations, we can’t tell whether or not any child team areas’ customizations will be ignored just by looking at the XML; it can actually vary based on the current iteration.
For example, say a team configures an operation as final during an iteration. If they provide no other configuration, then obviously this configuration will apply during this iteration and all child iterations and during this iteration any child team areas’ customizations will be ignored. However, what happens if the team then adds a non-final configuration for a child iteration? The process runtime interprets this as meaning “During the parent iterations and all child iterations except this one, the behavior’s configuration is final. But during this specific iteration, teams can customize the operation’s behavior.” So during the configured child iteration, all child team areas’ customizations suddenly come to life and any configuration of the behavior (not just those specified for the current iteration) override the parent config as normal.
© Copyright 2008 IBM