Bug in Synchronize Attributes feature?
In the Eclipse client there is the menu “Synchronize Attributes” that is used to update the attributes of existing work items in case the process template has changed and some new attributes have been added or old attributes are not available any more.
Looking at the invoked code it comes down to WorkItemCommon.updateWorkItemType(...) where the newType and oldType parameter are the same instance and this instance is the work item type of the current (meaning new) process template.
The method implementation is this:
public boolean updateWorkItemType(IWorkItem workItem, IWorkItemType newType, IWorkItemType oldType, IProgressMonitor monitor) throws TeamRepositoryException {Looking at the code it seems to me that attributes that are available in the work item but not any more in the work item type (of the new process template) are never removed. Removal of attributes only work if newType and oldType are different.
Assert.isTrue(workItem.isWorkingCopy());
((WorkItem) workItem).setWorkItemType(newType.getIdentifier());
boolean changed= false;
ItemHandleAwareHashSet<IAttributeHandle> customAttributes= new ItemHandleAwareHashSet<IAttributeHandle>(newType.getCustomAttributes());
for (IAttributeHandle customAttribute: customAttributes) {
IAttribute attribute= fAuditableCommon.resolveAuditable(customAttribute, IAttribute.FULL_PROFILE, monitor);
if (!workItem.hasAttribute(attribute)) {
workItem.addCustomAttribute(attribute);
workItem.setValue(attribute, attribute.getDefaultValue(fAuditableCommon, workItem, monitor));
changed= true;
} else if (AttributeTypes.isEnumerationAttributeType(attribute.getAttributeType())) {
if (workItem.getValue(attribute) == null) {
workItem.setValue(attribute, attribute.getDefaultValue(fAuditableCommon, workItem, monitor));
}
}
}
if (oldType != null) {
for (IAttributeHandle customAttribute: oldType.getCustomAttributes()) {
if (!customAttributes.contains(customAttribute)) {
if (workItem.hasCustomAttribute(customAttribute)) {
IAttribute attribute= fAuditableCommon.resolveAuditable(customAttribute, IAttribute.FULL_PROFILE, monitor);
workItem.removeCustomAttribute(attribute);
changed= true;
}
}
}
}
return changed;
}
This could be solved by replacing line
for (IAttributeHandle customAttribute: oldType.getCustomAttributes()) {by
for (IAttributeHandle customAttribute: workItem.getCustomAttributes()) {Am I missing something here?
Marko
2 answers
There is a defect on this:
Defect 431460: Javadoc for IWorkItemCommon updateWorkItemType is incomplete
This is working as designed. The way it works is:
1) If the old type is not provided, no attributes are removed.
2) If the old type is provided, attributes that are in the old type and not in the new type are removed.
3) Attributes in the new type are added.
4) Attributes that are not in the old type and not in the new type are not removed. These are inherited from base.
A tech note will appear here: http://g01zciwas018.ahe.pok.ibm.com/support/dcf/preview.wss?host=g01zcidbs003.ahe.pok.ibm.com&db=support/swg/rattech.nsf&unid=D130D8EB15505231852581630040E3F9&taxOC=SSC9M9F&MD=2017/07/20%2014:07:38&sid=
(currently it is a placeholder)
Comments
Note that although this is working as designed, I agree with Marko that the design has the inconsistency problem that he identifies above. But unfortunately, since the current behavior was introduced in release 2.0, it probably is not safe at this point to change that design, because customer processes are likely to have been created that depend on this design not changing.
Marco, I would submit an enhancement request. I am not sure if this is as planned or not. There might be reasons.
Comments
When I am changing the the type from let's say Task to Story then the not anymore used attributes in Task are removed. But when I am "updating" the Task work item the attributes are not removed.
So the implementation is inconsistent.
What adds to the confusion is that the javadoc says that only attributes are added. It does not mention at all that attributes are removed for my described scenario.
Your opinion?
This piece of code is invoked when I change the type of a work item in the Eclipse editor:
workItem.removeCustomAttribute(attribute);
What happens behind the scenes I don't know and is also not so important to me. The behaviour is simply inconsistent (if I would consider the javadoc as the only truth) because this method is called when the work item type is to be changed and if the work item types (that are given as parameter are different).
In the end I can live with the current behaviour of the implementation but then the javadoc should be adapted to explain the real behaviour:
- adds new attributes if the type is only updated
- If the type is to be changed removes all attributes that are not available in the new type.
I verified with a manual test that the attribute is removed (not just hidden).
Create a defect or enhancement request Marko.
I agree this is inconsistent, so I'd start with filing it as a defect.