Exposing the custom enumeration values in reports
Hi, I would like to create reports that display custom enumeration names. I noticed though that the live table in the workitem snapshot contains enumeration ids.
My approach then is to create a new snapshot that would have a table for custom enumerations mapping ids to names. I could then perform a join of this table and the live table in a BIRT report to properly display the names.
This is similar to what is already done in the work item snapshot that contains a priority table and a severity table.
I already know how to create a snapshot and a table based on guidance from https://jazz.net/wiki/bin/view/Main/DataWarehouseExtending but I'd like to get guidance on how to list the custom enumerations and translate the ids into names so I can insert rows in the table.
I got this source code excerpt as an example on how to translate the priority ids into names:
Identifier<IPriority> identifier = workItem.getPriority();
if (identifier == null) {
return unassigned;
}
IWorkItemServer service = getService(IWorkItemServer.class);
IEnumeration enumeration = service.resolveEnumeration
(service.findAttribute(projectArea,
IWorkItem.PRIORITY_PROPERTY,
new NullProgressMonitor()),
new NullProgressMonitor());
String value = enumeration.findEnumerationLiteral(identifier).getName();
Can I use the same resolveEumeration and findEnumerationLiteral methods to resolve the names of custom enumerations?
Also, this excerpt starts from a work item when in fact I'd like to list all the custom enumeration ids and their names in the snapshot table.
Thanks
My approach then is to create a new snapshot that would have a table for custom enumerations mapping ids to names. I could then perform a join of this table and the live table in a BIRT report to properly display the names.
This is similar to what is already done in the work item snapshot that contains a priority table and a severity table.
I already know how to create a snapshot and a table based on guidance from https://jazz.net/wiki/bin/view/Main/DataWarehouseExtending but I'd like to get guidance on how to list the custom enumerations and translate the ids into names so I can insert rows in the table.
I got this source code excerpt as an example on how to translate the priority ids into names:
Identifier<IPriority> identifier = workItem.getPriority();
if (identifier == null) {
return unassigned;
}
IWorkItemServer service = getService(IWorkItemServer.class);
IEnumeration enumeration = service.resolveEnumeration
(service.findAttribute(projectArea,
IWorkItem.PRIORITY_PROPERTY,
new NullProgressMonitor()),
new NullProgressMonitor());
String value = enumeration.findEnumerationLiteral(identifier).getName();
Can I use the same resolveEumeration and findEnumerationLiteral methods to resolve the names of custom enumerations?
Also, this excerpt starts from a work item when in fact I'd like to list all the custom enumeration ids and their names in the snapshot table.
Thanks
5 answers
Hi,
A couple of clarifying questions:
1. What version of RTC are you using?
2. Are you interested in live (current) data only or historical trend
data as well?
james
Jazz Reports Team Lead
lquintela wrote:
A couple of clarifying questions:
1. What version of RTC are you using?
2. Are you interested in live (current) data only or historical trend
data as well?
james
Jazz Reports Team Lead
lquintela wrote:
Hi, I would like to create reports that display custom enumeration
names. I noticed though that the live table in the workitem snapshot
contains enumeration ids.
My approach then is to create a new snapshot that would have a table
for custom enumerations mapping ids to names. I could then perform a
join of this table and the live table in a BIRT report to properly
display the names.
This is similar to what is already done in the work item snapshot that
contains a priority table and a severity table.
I already know how to create a snapshot and a table based on guidance
from https://jazz.net/wiki/bin/view/Main/DataWarehouseExtending but
I'd like to get guidance on how to list the custom enumerations and
translate the ids into names so I can insert rows in the table.
I got this source code excerpt as an example on how to translate the
priority ids into names:
Identifier<IPriority> identifier = workItem.getPriority();
if (identifier == null) {
return unassigned;
}
IWorkItemServer service = getService(IWorkItemServer.class);
IEnumeration enumeration = service.resolveEnumeration
(service.findAttribute(projectArea,
IWorkItem.PRIORITY_PROPERTY,
new NullProgressMonitor()),
new NullProgressMonitor());
String value =
enumeration.findEnumerationLiteral(identifier).getName();
Can I use the same resolveEumeration and findEnumerationLiteral
methods to resolve the names of custom enumerations?
Also, this excerpt starts from a work item when in fact I'd like to
list all the custom enumeration ids and their names in the snapshot
table.
Thanks
I'm using RTC 1.0.1 and I want to report against live data.
Here is the code I'm using to populate the table in the snapshot to map custom enumeration ids to names. The issue is that if more than one attribute is of the same enumeration type, the same enumeration will be inserted in the table more than once.
Is there a way to query the process configuration for the list of custom enumerations and iterate on that as opposed to iterating on the list of custom attributes for each work item type as I'm doing in the code below?
protected void updateSnapshot() throws TeamRepositoryException {
// TODO Auto-generated method stub
ITableDescriptor table = getTableDescriptor(ENUMERATIONS_FACT_TABLE);
long time = System.currentTimeMillis();
getCommonSnapshotService().createOneTimeRecord(time);
long nextFactId = getNextFactId(getTableDescriptor(ENUMERATIONS_FACT_TABLE));
System.out.println("Updating snapshot");
IAuditableServer auditableServer = getService (IAuditableServer.class);
IWorkItemServer workItemServer = getService(IWorkItemServer.class);
IItemType itemType= IProjectArea.ITEM_TYPE;
IDynamicQueryModel model= itemType.getQueryModel();
IItemQuery query= IItemQuery.FACTORY.newInstance((IItemQueryModel) model);
ItemQueryIterator<IProjectAreaHandle> iterator= new ItemQueryIterator<IProjectAreaHandle>(getService(IAuditableServer.class), query);
List<IProjectAreaHandle> projectAreas = iterator.toList(new NullProgressMonitor());
for (IProjectAreaHandle pa: projectAreas) {
System.out.println("**** Project Area: " + pa.getItemId().getUuidValue());
List<IWorkItemType> wiTypes = workItemServer.findWorkItemTypes(pa, null);
for (IWorkItemType type: wiTypes) {
System.out.println("****** Work Item Type: " + type.getDisplayName());
List<IAttribute> customAttributes = auditableServer.resolveAuditables(type.getCustomAttributes(), IAttribute.FULL_PROFILE, null);
for (IAttribute item: customAttributes) {
if ((AttributeTypes.getAttributeType(item.getAttributeType()) instanceof EnumerationAttributeType) &&
(item.isBuiltIn() == false)) {
System.out.println("******** Enumeration: " + item.getAttributeType());
IEnumeration enumeration = workItemServer.resolveEnumeration(item, null);
List<ILiteral> list = enumeration.getEnumerationLiterals();
for (ILiteral e: list) {
System.out.println("********** Value - " + e.getName() + " Id - " + e.getIdentifier2().getStringIdentifier());
IWritableDataRow record = createTableRecord(table);
record.setLong(FACT_ID_COLUMN, nextFactId);
record.setLong(TIME_ID_COLUMN, time);
record.setString(ENUMERATION_ID_COLUMN, e.getIdentifier2().getStringIdentifier());
record.setString(ENUMERATION_TYPE_COLUMN, item.getAttributeType());
record.setString(ENUMERATION_NAME_COLUMNN, e.getName());
storeTableRecord(table, record);
nextFactId++;
}
}
}
}
}
}
Here is the code I'm using to populate the table in the snapshot to map custom enumeration ids to names. The issue is that if more than one attribute is of the same enumeration type, the same enumeration will be inserted in the table more than once.
Is there a way to query the process configuration for the list of custom enumerations and iterate on that as opposed to iterating on the list of custom attributes for each work item type as I'm doing in the code below?
protected void updateSnapshot() throws TeamRepositoryException {
// TODO Auto-generated method stub
ITableDescriptor table = getTableDescriptor(ENUMERATIONS_FACT_TABLE);
long time = System.currentTimeMillis();
getCommonSnapshotService().createOneTimeRecord(time);
long nextFactId = getNextFactId(getTableDescriptor(ENUMERATIONS_FACT_TABLE));
System.out.println("Updating snapshot");
IAuditableServer auditableServer = getService (IAuditableServer.class);
IWorkItemServer workItemServer = getService(IWorkItemServer.class);
IItemType itemType= IProjectArea.ITEM_TYPE;
IDynamicQueryModel model= itemType.getQueryModel();
IItemQuery query= IItemQuery.FACTORY.newInstance((IItemQueryModel) model);
ItemQueryIterator<IProjectAreaHandle> iterator= new ItemQueryIterator<IProjectAreaHandle>(getService(IAuditableServer.class), query);
List<IProjectAreaHandle> projectAreas = iterator.toList(new NullProgressMonitor());
for (IProjectAreaHandle pa: projectAreas) {
System.out.println("**** Project Area: " + pa.getItemId().getUuidValue());
List<IWorkItemType> wiTypes = workItemServer.findWorkItemTypes(pa, null);
for (IWorkItemType type: wiTypes) {
System.out.println("****** Work Item Type: " + type.getDisplayName());
List<IAttribute> customAttributes = auditableServer.resolveAuditables(type.getCustomAttributes(), IAttribute.FULL_PROFILE, null);
for (IAttribute item: customAttributes) {
if ((AttributeTypes.getAttributeType(item.getAttributeType()) instanceof EnumerationAttributeType) &&
(item.isBuiltIn() == false)) {
System.out.println("******** Enumeration: " + item.getAttributeType());
IEnumeration enumeration = workItemServer.resolveEnumeration(item, null);
List<ILiteral> list = enumeration.getEnumerationLiterals();
for (ILiteral e: list) {
System.out.println("********** Value - " + e.getName() + " Id - " + e.getIdentifier2().getStringIdentifier());
IWritableDataRow record = createTableRecord(table);
record.setLong(FACT_ID_COLUMN, nextFactId);
record.setLong(TIME_ID_COLUMN, time);
record.setString(ENUMERATION_ID_COLUMN, e.getIdentifier2().getStringIdentifier());
record.setString(ENUMERATION_TYPE_COLUMN, item.getAttributeType());
record.setString(ENUMERATION_NAME_COLUMNN, e.getName());
storeTableRecord(table, record);
nextFactId++;
}
}
}
}
}
}
Hi Luis, I still don't see the value in storing the enumeration id to name mapping in the data warehouse? I think you should raise a Work Item against Reports and we will do the work for 2.0. To get you going here is what I would suggest:
In the BIRT report it self, define a scripted data set that gives you the mapping. You can hard code the mapping your self. In 1.0.1 we added support for report libraries, you can define those mapping tables in the some shared library that various report designs could use and share.
Whoever defines the enumerations in the process template could also define these report libraries that define the mapping. I already see many problems with your approach.
1) You are using FACT tables to store the mapping. You should use Dimension tables instead.
2) Dimension tables allow the records to be updated (when you call storeTableRecord using the same primary key it will result in an update of the record).
In the BIRT report it self, define a scripted data set that gives you the mapping. You can hard code the mapping your self. In 1.0.1 we added support for report libraries, you can define those mapping tables in the some shared library that various report designs could use and share.
Whoever defines the enumerations in the process template could also define these report libraries that define the mapping. I already see many problems with your approach.
1) You are using FACT tables to store the mapping. You should use Dimension tables instead.
2) Dimension tables allow the records to be updated (when you call storeTableRecord using the same primary key it will result in an update of the record).
Hi Rafik, isn't this model of creating mapping tables for enumerations used for priority and severity? This is why I'm using this approach. Also, with this approach, if the process changes you can update the snapshot and get the new mapping.
Do you have an example on how to create a dimension table? The example in the wiki is just for fact.
Thanks.
Do you have an example on how to create a dimension table? The example in the wiki is just for fact.
Thanks.
lquintela wrote:
There is no real difference in terms of how you define fact and
dimension tables. They're both just tables in the database. The
difference is their content and how they are used. You should define
dimensions so they are self-contained and don't have references to other
tables. (This is easy for enumerations). Then in your fact table you
define a reference to one or more of these dimension tables, and they
get joined when you query the data from the report.
So the example in the wiki should help. For a real example, look in our
code at CommonSnapshotService and CommonTableDescriptorFactory. In there
are a number of dimensions defined, such as the "contributor" dimension.
That should show you how we declare them (in the table descriptor
factory) and populate them (in the snapshot service).
Hope this helps.
james
Hi Rafik, isn't this model of creating mapping tables for enumerations
used for priority and severity? This is why I'm using this approach.
Also, with this approach, if the process changes you can update the
snapshot and get the new mapping.
Do you have an example on how to create a dimension table? The example
in the wiki is just for fact.
Thanks.
There is no real difference in terms of how you define fact and
dimension tables. They're both just tables in the database. The
difference is their content and how they are used. You should define
dimensions so they are self-contained and don't have references to other
tables. (This is easy for enumerations). Then in your fact table you
define a reference to one or more of these dimension tables, and they
get joined when you query the data from the report.
So the example in the wiki should help. For a real example, look in our
code at CommonSnapshotService and CommonTableDescriptorFactory. In there
are a number of dimensions defined, such as the "contributor" dimension.
That should show you how we declare them (in the table descriptor
factory) and populate them (in the snapshot service).
Hope this helps.
james