package hudson.plugins.global_build_stats.xstream;
import hudson.plugins.global_build_stats.GlobalBuildStatsPlugin;
import hudson.plugins.global_build_stats.model.BuildStatConfiguration;
import hudson.plugins.global_build_stats.model.JobBuildResult;
import hudson.plugins.global_build_stats.xstream.migration.GlobalBuildStatsDataMigrator;
import hudson.plugins.global_build_stats.xstream.migration.GlobalBuildStatsPOJO;
import hudson.plugins.global_build_stats.xstream.migration.GlobalBuildStatsXStreamReader;
import hudson.plugins.global_build_stats.xstream.migration.v0.V0XStreamReader;
import hudson.plugins.global_build_stats.xstream.migration.v1.V0ToV1Migrator;
import hudson.plugins.global_build_stats.xstream.migration.v1.V1GlobalBuildStatsPOJO;
import hudson.plugins.global_build_stats.xstream.migration.v1.V1XStreamReader;
import java.util.logging.Logger;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
/**
* XStream converter for GlobalBuildStatsPlugin XStream data
* @author fcamblor
*/
public class GlobalBuildStatsXStreamConverter implements Converter {
private static final Logger LOGGER = Logger.getLogger(GlobalBuildStatsXStreamConverter.class.getName());
public static final String BUILD_STAT_CONFIG_CLASS_ALIAS = "bsc";
public static final String JOB_BUILD_RESULT_CLASS_ALIAS = "jbr";
/**
* List of XStream readers for previous XStream representations of
* GlobalBuildStatsPlugin
*/
private static final GlobalBuildStatsXStreamReader[] READERS = new GlobalBuildStatsXStreamReader[]{
new V0XStreamReader(),
new V1XStreamReader()
};
/**
* Migrators for old versions of GlobalBuildStatsPlugin data representations
*/
private static final GlobalBuildStatsDataMigrator[] MIGRATORS = new GlobalBuildStatsDataMigrator[]{
new V0ToV1Migrator()
};
/**
* Converter is only applicable on GlobalBuildStatsPlugin data
*/
public boolean canConvert(Class type) {
return GlobalBuildStatsPlugin.class.isAssignableFrom(type);
}
public void marshal(Object source, HierarchicalStreamWriter writer,
MarshallingContext context) {
GlobalBuildStatsPlugin plugin = (GlobalBuildStatsPlugin)source;
// Since "v1", providing version number in globalbuildstats heading tag
writer.addAttribute("version", String.valueOf(getCurrentGlobalBuildStatsVersionNumber()));
// Serializing job build results
writer.startNode("jobBuildResults");
if(plugin.getJobBuildResults() != null){
for(JobBuildResult r: plugin.getJobBuildResults()){
writer.startNode(BUILD_STAT_CONFIG_CLASS_ALIAS);
context.convertAnother(r);
writer.endNode();
}
}
writer.endNode();
// Serializing build stat configurations
writer.startNode("buildStatConfigs");
if(plugin.getBuildStatConfigs() != null){
for(BuildStatConfiguration c: plugin.getBuildStatConfigs()){
writer.startNode(JOB_BUILD_RESULT_CLASS_ALIAS);
context.convertAnother(c);
writer.endNode();
}
}
writer.endNode();
}
/**
* @return current version number of global build stats plugin
* data representation in XStream
*/
private static int getCurrentGlobalBuildStatsVersionNumber(){
return MIGRATORS.length;
}
/**
* Will transform global build stats XStream data representation into
* current GlobalBuildStatsPlugin instance
*/
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
GlobalBuildStatsPlugin plugin;
if(context.currentObject() == null || !(context.currentObject() instanceof GlobalBuildStatsPlugin)){
// Retrieving already instantiated GlobalBuildStats plugin into current context ..
plugin = new GlobalBuildStatsPlugin();
} else {
// This should never happen to get here
plugin = (GlobalBuildStatsPlugin)context.currentObject();
}
// Retrieving data representation version number
String version = reader.getAttribute("version");
// Before version 1 (version 0), there wasn't any version in the globalbuildstats
// configuration file
int versionNumber = 0;
if(version != null){
versionNumber = Integer.parseInt(version);
}
if(versionNumber != getCurrentGlobalBuildStatsVersionNumber()){
// There will be a data migration ..
LOGGER.info("Your version of persisted GlobalBuildStatsPlugin data is not up-to-date (v"+versionNumber+" < v"+getCurrentGlobalBuildStatsVersionNumber()+") : data will be migrated !");
}
// Calling version's reader to read data representation
GlobalBuildStatsPOJO pojo = READERS[versionNumber].readGlobalBuildStatsPOJO(reader, context);
// Migrating old data into up-to-date data
for(int i=versionNumber; i<getCurrentGlobalBuildStatsVersionNumber(); i++){
pojo = MIGRATORS[i].migrate(pojo);
}
// Populating latest POJO information into GlobalBuildStatsPlugin
populateGlobalBuildStatsPlugin(plugin, pojo);
return plugin;
}
protected void populateGlobalBuildStatsPlugin(GlobalBuildStatsPlugin plugin, GlobalBuildStatsPOJO pojo){
// Latest POJO is v1
V1GlobalBuildStatsPOJO versionedPojo = (V1GlobalBuildStatsPOJO)pojo;
plugin.getBuildStatConfigs().clear();
plugin.getBuildStatConfigs().addAll(versionedPojo.buildStatConfigs);
plugin.getJobBuildResults().clear();
plugin.getJobBuildResults().addAll(versionedPojo.jobBuildResults);
}
}