How do I find out who has created and/or modified an Iteration in the project Configuration ?
Is there a way to find out who has created an Iteration and when? Also who has modified it?
I did not find any UI nor in the API.
Only place I know is the Event Feed, but this shows me only the last few days. Is this feed somewhere stored? <
What about the DWA? Is this information available there?
I did not find any UI nor in the API.
Only place I know is the Event Feed, but this shows me only the last few days. Is this feed somewhere stored? <
What about the DWA? Is this information available there?
Accepted answer
If you're willing to use our Java API, the information is out there.
Key things to understand about the data we store and the history of that data:
1. There are three types of "items" involved here: project areas (IProjectArea), timelines (IDevelopmentLine), and iterations (IIteration).
2. All these items inherit from IAuditable, which inherits from IItem.
3. Every time an IAuditable is saved, it generates a new "state".
4. When you fetch an IAuditable from the repository, you get the current state.
5. IAuditable#getPredecessorState() will give you access to next oldest state. And that predecessor will have a pointer to the next predecessor once you fetch it.
In addition to walking the predecessor states one at a time, the IItemManager interface (ITeamRepository.itemManager()) allows you to fetch the handles of all the states of an item at once, using IItemManager.fetchAllStateHandles(...). You can then fetch the full content of all those states using IItemManager.fetchCompleteStates(...). Something to be aware of is that the states come back in random order, so once you fetch them you'd want to sort them by modified time.
Hope that helps.
Key things to understand about the data we store and the history of that data:
1. There are three types of "items" involved here: project areas (IProjectArea), timelines (IDevelopmentLine), and iterations (IIteration).
2. All these items inherit from IAuditable, which inherits from IItem.
3. Every time an IAuditable is saved, it generates a new "state".
4. When you fetch an IAuditable from the repository, you get the current state.
5. IAuditable#getPredecessorState() will give you access to next oldest state. And that predecessor will have a pointer to the next predecessor once you fetch it.
In addition to walking the predecessor states one at a time, the IItemManager interface (ITeamRepository.itemManager()) allows you to fetch the handles of all the states of an item at once, using IItemManager.fetchAllStateHandles(...). You can then fetch the full content of all those states using IItemManager.fetchCompleteStates(...). Something to be aware of is that the states come back in random order, so once you fetch them you'd want to sort them by modified time.
Hope that helps.
Comments
Thanks Jared, it works perfect. Now I have a commanline showing me all the changes people did in the project configuration! Big brother :-)
Is that commandline code something you can share @schneidg? It sounds very useful.
I'm not allowed to share the whole tool yet, but the code snippet. I'm in discussion with our legal department, if I could create an open source project for my Jazz Tools. I tzhink some of them could be interesting for others, and some helping hands would be great. I post the code-snippet in an answer below.
I just saw during my tests of V.4.0.3 M3, there is a new history tab in ADMIN showing such information.
Thanks to IBM.
Plan Item 93159 if you're interested in seeing more details.
One other answer
/**
* Get the history of all project time lines and their iterations.
*
* @param project : The project to get the time lines of.
* @return True if successfull
*/
@SuppressWarnings("unchecked")
public boolean getTimeLineHistory(IProjectArea project) {
boolean result = false;
IProgressMonitor monitor = null;
try {
// get all time lines
IDevelopmentLineHandle[] timeLines = project.getDevelopmentLines();
for (IDevelopmentLineHandle timeLine : timeLines) {
try {
// get the history of the time line
List<IDevelopmentLine> history = this.teamRepository.itemManager().fetchAllStateHandles(timeLine, monitor);
history = this.teamRepository.itemManager().fetchCompleteStates(history, monitor); // the time lines in the list are random
for (IDevelopmentLine preLine : history) {
ArrayList<String> preState = new ArrayList<String>();
// predecessor state of the time line
// ID
preState.add(preLine.getId());
// name
preState.add(preLine.getName());
// modified date
preState.add(DateFormater.format(preLine.modified())); // use any DateFormat.format() to get the String of the date
// modified by contributor
IContributor modifier = (IContributor) this.teamRepository.itemManager().fetchCompleteItem(preLine.getModifiedBy(), 0, monitor);
preState.add(modifier.getUserId());
// start date
if (preLine.getStartDate() != null) {
preState.add(DateFormat.format(preLine.getStartDate())); // use any DateFormat.format() to get the String of the date
} else {
preState.add("");
}
// end date
if (preLine.getEndDate() != null) {
preState.add(DateFormat.format(preLine.getEndDate())); // use any DateFormat.format() to get the String of the date
} else {
preState.add("");
}
// child iterations
String iterations = "";
for (IIterationHandle iteration : preLine.getIterations()) {
IIteration iter = (IIteration) this.teamRepository.itemManager().fetchCompleteItem(iteration, 0, monitor);
iterations = iterations + iter.getName() + ",";
}
preState.add(iterations);
// is archived?
String archived = preLine.isArchived() == true ? "archived" : "";
preState.add(archived);
//
// Do anything with the values in the ArrayList 'preState'
//
}
// get the state history of the iterations
IIterationHandle[] iterations = (IIterationHandle[])
((IDevelopmentLine)
this.teamRepository.itemManager().fetchCompleteItem(timeLine, 0, monitor))
.getIterations();
for (IIterationHandle iteration : iterations) {
getIterationHistory(iteration, monitor);
}
} catch (TeamRepositoryException e) {
e.getMessage();
} catch (Exception e) {
e.getMessage();
}
}
result = true;
} catch (Exception e) {
e.getMessage();
}
return result;
}
/**
* Get the history states of the iteration.
*
* @param iteration : The iteration to get the history states of.
* @param monitor : The IProgressMonitor to work with.
*/
@SuppressWarnings("unchecked")
private void getIterationHistory(IIterationHandle iteration, IProgressMonitor monitor) {
try {
// get the history of the iteration
List<IIteration> history = this.teamRepository.itemManager().fetchAllStateHandles(iteration, monitor);
history = this.teamRepository.itemManager().fetchCompleteStates(history, monitor); // the iterations in the list are random
for (IIteration preIteration : history) {
ArrayList<String> preState = new ArrayList<String>();
// predecessor state of the iteration
// ID
preState.add(preIteration.getId());
// name
preState.add(preIteration.getName());
// modified date
preState.add(DateFormater.format(preIteration.modified())); // use any DateFormat.format() to get the String of the date
// modified by contributor
IContributor modifier = (IContributor) this.teamRepository.itemManager().fetchCompleteItem(preIteration.getModifiedBy(), 0, monitor);
preState.add(modifier.getUserId());
// start
if (preIteration.getStartDate() != null) {
preState.add(DateFormater.format(preIteration.getStartDate())); // use any DateFormat.format() to get the String of the date
} else {
preState.add("");
}
// end
if (preIteration.getEndDate() != null) {
preState.add(DateFormater.format(preIteration.getEndDate())); // use any DateFormat.format() to get the String of the date
} else {
preState.add("");
}
// child iteration
String children = "";
for (IIterationHandle child : preIteration.getChildren()) {
IIteration iter = (IIteration) this.teamRepository.itemManager().fetchCompleteItem(child, 0, monitor);
children = children + iter.getName() + ",";
}
preState.add(children);
// is archived?
String archived = preIteration.isArchived() == true ? "archived" : "";
preState.add(archived);
//
// Do anything with the values in the ArrayList 'preState'
//
}
// get the state history of the child iterations
IIterationHandle[] children = (IIterationHandle[])
((IIteration)
this.teamRepository.itemManager().fetchCompleteItem(iteration, 0, monitor))
.getChildren();
for (IIterationHandle child : children) {
getIterationHistory(child, monitor);
}
} catch (TeamRepositoryException e) {
e.getMessage();
}
}
* Get the history of all project time lines and their iterations.
*
* @param project : The project to get the time lines of.
* @return True if successfull
*/
@SuppressWarnings("unchecked")
public boolean getTimeLineHistory(IProjectArea project) {
boolean result = false;
IProgressMonitor monitor = null;
try {
// get all time lines
IDevelopmentLineHandle[] timeLines = project.getDevelopmentLines();
for (IDevelopmentLineHandle timeLine : timeLines) {
try {
// get the history of the time line
List<IDevelopmentLine> history = this.teamRepository.itemManager().fetchAllStateHandles(timeLine, monitor);
history = this.teamRepository.itemManager().fetchCompleteStates(history, monitor); // the time lines in the list are random
for (IDevelopmentLine preLine : history) {
ArrayList<String> preState = new ArrayList<String>();
// predecessor state of the time line
// ID
preState.add(preLine.getId());
// name
preState.add(preLine.getName());
// modified date
preState.add(DateFormater.format(preLine.modified())); // use any DateFormat.format() to get the String of the date
// modified by contributor
IContributor modifier = (IContributor) this.teamRepository.itemManager().fetchCompleteItem(preLine.getModifiedBy(), 0, monitor);
preState.add(modifier.getUserId());
// start date
if (preLine.getStartDate() != null) {
preState.add(DateFormat.format(preLine.getStartDate())); // use any DateFormat.format() to get the String of the date
} else {
preState.add("");
}
// end date
if (preLine.getEndDate() != null) {
preState.add(DateFormat.format(preLine.getEndDate())); // use any DateFormat.format() to get the String of the date
} else {
preState.add("");
}
// child iterations
String iterations = "";
for (IIterationHandle iteration : preLine.getIterations()) {
IIteration iter = (IIteration) this.teamRepository.itemManager().fetchCompleteItem(iteration, 0, monitor);
iterations = iterations + iter.getName() + ",";
}
preState.add(iterations);
// is archived?
String archived = preLine.isArchived() == true ? "archived" : "";
preState.add(archived);
//
// Do anything with the values in the ArrayList 'preState'
//
}
// get the state history of the iterations
IIterationHandle[] iterations = (IIterationHandle[])
((IDevelopmentLine)
this.teamRepository.itemManager().fetchCompleteItem(timeLine, 0, monitor))
.getIterations();
for (IIterationHandle iteration : iterations) {
getIterationHistory(iteration, monitor);
}
} catch (TeamRepositoryException e) {
e.getMessage();
} catch (Exception e) {
e.getMessage();
}
}
result = true;
} catch (Exception e) {
e.getMessage();
}
return result;
}
/**
* Get the history states of the iteration.
*
* @param iteration : The iteration to get the history states of.
* @param monitor : The IProgressMonitor to work with.
*/
@SuppressWarnings("unchecked")
private void getIterationHistory(IIterationHandle iteration, IProgressMonitor monitor) {
try {
// get the history of the iteration
List<IIteration> history = this.teamRepository.itemManager().fetchAllStateHandles(iteration, monitor);
history = this.teamRepository.itemManager().fetchCompleteStates(history, monitor); // the iterations in the list are random
for (IIteration preIteration : history) {
ArrayList<String> preState = new ArrayList<String>();
// predecessor state of the iteration
// ID
preState.add(preIteration.getId());
// name
preState.add(preIteration.getName());
// modified date
preState.add(DateFormater.format(preIteration.modified())); // use any DateFormat.format() to get the String of the date
// modified by contributor
IContributor modifier = (IContributor) this.teamRepository.itemManager().fetchCompleteItem(preIteration.getModifiedBy(), 0, monitor);
preState.add(modifier.getUserId());
// start
if (preIteration.getStartDate() != null) {
preState.add(DateFormater.format(preIteration.getStartDate())); // use any DateFormat.format() to get the String of the date
} else {
preState.add("");
}
// end
if (preIteration.getEndDate() != null) {
preState.add(DateFormater.format(preIteration.getEndDate())); // use any DateFormat.format() to get the String of the date
} else {
preState.add("");
}
// child iteration
String children = "";
for (IIterationHandle child : preIteration.getChildren()) {
IIteration iter = (IIteration) this.teamRepository.itemManager().fetchCompleteItem(child, 0, monitor);
children = children + iter.getName() + ",";
}
preState.add(children);
// is archived?
String archived = preIteration.isArchived() == true ? "archived" : "";
preState.add(archived);
//
// Do anything with the values in the ArrayList 'preState'
//
}
// get the state history of the child iterations
IIterationHandle[] children = (IIterationHandle[])
((IIteration)
this.teamRepository.itemManager().fetchCompleteItem(iteration, 0, monitor))
.getChildren();
for (IIterationHandle child : children) {
getIterationHistory(child, monitor);
}
} catch (TeamRepositoryException e) {
e.getMessage();
}
}
Comments
Jared Burns
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER Jul 10 '12, 7:41 p.m.You mentioned API. Are you comfortable using our Java API? If so, I can explain how to get the data that way...
1 vote
Guido Schneider
Jul 11 '12, 2:46 a.m.Yes. We have developed a Jazz Commandline Interface (JCI) with a lot of administrative tasks like export/import of project configurations etc. I like to implement a "-lshistory" command, where I see the hoistory e.g. of the timeline configurations. Something like I would save all the feeds in a textfile for history.