Java tutorial
/******************************************************************************* * Copyright (c) 2006-2010 Vienna University of Technology, * Department of Software Technology and Interactive Systems * * All rights reserved. This program and the accompanying * materials are made available under the terms of the * Apache License, Version 2.0 which accompanies * this distribution, and is available at * http://www.apache.org/licenses/LICENSE-2.0 *******************************************************************************/ package eu.planets_project.pp.plato.xml; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.List; import java.util.Map; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.Namespace; import org.dom4j.QName; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import sun.misc.BASE64Encoder; import eu.planets_project.pp.plato.model.Alternative; import eu.planets_project.pp.plato.model.ChangeLog; import eu.planets_project.pp.plato.model.DetailedExperimentInfo; import eu.planets_project.pp.plato.model.DigitalObject; import eu.planets_project.pp.plato.model.ExecutablePlanDefinition; import eu.planets_project.pp.plato.model.Experiment; import eu.planets_project.pp.plato.model.Parameter; import eu.planets_project.pp.plato.model.Plan; import eu.planets_project.pp.plato.model.PlanDefinition; import eu.planets_project.pp.plato.model.Policy; import eu.planets_project.pp.plato.model.PolicyNode; import eu.planets_project.pp.plato.model.SampleObject; import eu.planets_project.pp.plato.model.TargetValueObject; import eu.planets_project.pp.plato.model.Trigger; import eu.planets_project.pp.plato.model.measurement.MeasurableProperty; import eu.planets_project.pp.plato.model.measurement.Measurement; import eu.planets_project.pp.plato.model.measurement.MeasurementInfo; import eu.planets_project.pp.plato.model.measurement.Metric; import eu.planets_project.pp.plato.model.scales.FreeStringScale; import eu.planets_project.pp.plato.model.scales.RestrictedScale; import eu.planets_project.pp.plato.model.scales.Scale; import eu.planets_project.pp.plato.model.scales.ScaleType; import eu.planets_project.pp.plato.model.transform.NumericTransformer; import eu.planets_project.pp.plato.model.transform.OrdinalTransformer; import eu.planets_project.pp.plato.model.tree.Leaf; import eu.planets_project.pp.plato.model.tree.TemplateTree; import eu.planets_project.pp.plato.model.tree.TreeNode; import eu.planets_project.pp.plato.model.values.Value; import eu.planets_project.pp.plato.util.FloatFormatter; import eu.planets_project.pp.plato.util.PlatoLogger; /** * Static methods providing means to export projects to XML using dom4j. * * @author Michael Kraxner */ public class ProjectExporter { private TimestampFormatter formatter = new TimestampFormatter(); private FloatFormatter floatFormatter = new FloatFormatter(); public static OutputFormat prettyFormat = new OutputFormat(" ", true, "UTF-8"); //OutputFormat.createPrettyPrint(); public static OutputFormat compactFormat = new OutputFormat(null, false, "UTF-8"); //OutputFormat.createPrettyPrint(); public static Namespace excutablePlanNS; public static Namespace xsi; public static Namespace platoNS; static { excutablePlanNS = new Namespace("wdt", "http://www.planets-project.eu/wdt"); xsi = new Namespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); platoNS = new Namespace("", "http://www.planets-project.eu/plato"); } public ProjectExporter() { } /** * Returns the xml-representation of the given project as a String. * NOTE: It writes all data - including encoded binary data - directly to the DOM tree * this may result in performance problems for large amounts of data. */ public String exportToString(Plan p) { return exportToXml(p).asXML(); } /** * Takes the given project and turns it into a dom4j-xml-representation. * NOTE: It writes all data - including encoded binary data - directly to the DOM tree * this may result in performance problems for large amounts of data. * @return dom4j-document representing the given project */ public Document exportToXml(Plan p) { Document doc = createProjectDoc(); addProject(p, doc, null, null); return doc; } public Document createProjectDoc() { Document doc = DocumentHelper.createDocument(); Element root = doc.addElement("plans"); root.add(xsi); root.add(platoNS); root.addAttribute(xsi.getPrefix() + ":schemaLocation", "http://www.planets-project.eu/plato plato-3.0.xsd"); root.add(excutablePlanNS); root.add(new Namespace("fits", "http://hul.harvard.edu/ois/xml/ns/fits/fits_output")); // set version of corresponding schema root.addAttribute("version", "3.0.0"); return doc; } public Document createTemplateDoc() { Document doc = DocumentHelper.createDocument(); Element root = doc.addElement("templates"); root.add(xsi); return doc; } /** * This method creates a template xml from the objective tree contained in Plan p. The template xml is of the form * * <templates> * <template name="Public Fragments"> * <node name="Template 1" weight="0.0" single="false" lock="false"> * <node name="Interactive multimedia presentations" weight="0.0" single="false" lock="false"> * ... * </template> * </templates> * * For creating the tree we use {@link ProjectExporter#addSubTree(TreeNode, Element)} and remove afterwards * the evaluation part which we don't want to have in the template. * * @param p preservation plan * @param templateLibrary name of the template library (e.g. 'Public Templates') * @param name name of the template * @param description description of the template * @return xml as string */ public String getObjectiveTreeAsTemplate(Plan p, String templateLibrary, String name, String description) { Document templateDoc = createTemplateDoc(); Element template = templateDoc.getRootElement().addElement("template"); template.addAttribute("name", templateLibrary); // Objectivetree (including weights, evaluation values and transformers) if (p.getTree().getRoot() != null) { addSubTree(p.getTree().getRoot(), template); } // get the root node of the tree Element treeRootNode = (Element) template.selectSingleNode("//templates/template/node"); // change the name of the template if (name == null) { name = ""; } treeRootNode.addAttribute("name", name); if (description == null) { description = ""; } // set the description of the template Element descriptionElement = treeRootNode.addElement("description"); descriptionElement.setText(description); // remove the evaluation from the template List<Element> nodes = templateDoc.selectNodes("//leaf/evaluation"); for (Element n : nodes) { n.getParent().remove(n); } return templateDoc.asXML(); } /** * Takes the given projects and turns them into a dom4j-xml-representation. * NOTE: It writes all data - including encoded binary data - directly to the DOM tree * this may result in performance problems for large amounts of data. * @return dom4j-document representing the given project public static Document exportToXml(List<Plan> projects) { Document doc = createProjectDoc(); for (Plan project : projects) { ProjectExporter.addProject(project, doc, null, null); } return doc; } */ /** * Writes the xml-representation of the given projects to the given target file. * NOTE: It writes all data - including encoded binary data - directly to the DOM tree * this may result in performance problems for large amounts of data. */ public void exportToFile(Plan p, File target) throws IOException { XMLWriter writer = new XMLWriter(new FileWriter(target), ProjectExporter.prettyFormat); writer.write(exportToXml(p)); writer.close(); } /** * Writes the xml-representation of the given project into a temporary file and * returns the java-representation of this file. * NOTE: It writes all data - including encoded binary data - directly to the DOM tree * this may result in performance problems for large amounts of data. * */ public File exportToFile(Plan p) throws IOException { File temp = File.createTempFile("plato-plan-export-", ".xml"); exportToFile(p, temp); return temp; } /* public static File exportTemplatesToFile(List<TemplateTree> trees) throws IOException { File temp = File.createTempFile("plato-templates-export-", ".xml"); XMLWriter writer = new XMLWriter(new FileWriter(temp), ProjectExporter.prettyFormat); //writer.setMaximumAllowedCharacter(127); writer.write(ProjectExporter.exportTemplates(trees)); writer.close(); return temp; }*/ public Document exportTemplates(List<TemplateTree> trees) { Document doc = DocumentHelper.createDocument(); Element root = doc.addElement("templates"); for (TemplateTree template : trees) { addTemplateTree(template, root); } return doc; } /** * Adds the XML representation of the complete template tree to the parent node <code>root</code>. * * @param tree * @param root */ private void addTemplateTree(TemplateTree tree, Element root) { Element template = root.addElement("template"); template.addAttribute("name", tree.getName()); template.addAttribute("owner", tree.getOwner()); for (TreeNode child : tree.getRoot().getChildren()) { addSubTree(child, template); } } private void addSubPolicyTree(PolicyNode data, Element xmlRoot) { if (data == null) { return; } if (data.isPolicy()) { Element policy = xmlRoot.addElement("policy"); Policy p = (Policy) data; policy.addAttribute("name", p.getName()); policy.addAttribute("value", p.getValue()); } else { Element policyNode = xmlRoot.addElement("policyNode"); policyNode.addAttribute("name", data.getName()); for (PolicyNode pn : data.getChildren()) { addSubPolicyTree(pn, policyNode); } } } /** * Adds the XML-representation of the treenode <code>data</code> to the parent node <code>xmlRoot</code>. * (also called recursivly for its children) * * @param data * @param xmlRoot */ private void addSubTree(TreeNode data, Element xmlRoot) { if (data.isLeaf()) { Element leaf = xmlRoot.addElement("leaf"); addNodeAttributes(data, leaf); Leaf l = (Leaf) data; leaf.addElement("aggregationMode").addAttribute("value", l.getAggregationMode().name()); String typename = null; /* * Scale: * A special element is created, depending on the type of the scale */ Scale s = l.getScale(); if (s != null) { typename = deriveElementname(s.getClass()); addScale(s, leaf); // Transformer if (l.getTransformer() != null) { Element transformer = leaf.addElement(deriveElementname(l.getTransformer().getClass())); if (l.getTransformer() instanceof OrdinalTransformer) { Map<String, TargetValueObject> mapping = ((OrdinalTransformer) l.getTransformer()) .getMapping(); Element mappings = transformer.addElement("mappings"); for (String ordinal : mapping.keySet()) { mappings.addElement("mapping").addAttribute("ordinal", ordinal).addAttribute("target", floatFormatter.formatFloatPrecisly(mapping.get(ordinal).getValue())); } } if (l.getTransformer() instanceof NumericTransformer) { NumericTransformer nt = (NumericTransformer) l.getTransformer(); transformer.addElement("mode").addAttribute("value", nt.getMode().name()); Element thresholds = transformer.addElement("thresholds"); thresholds.addElement("threshold1") .setText(floatFormatter.formatFloatPrecisly(nt.getThreshold1())); thresholds.addElement("threshold2") .setText(floatFormatter.formatFloatPrecisly(nt.getThreshold2())); thresholds.addElement("threshold3") .setText(floatFormatter.formatFloatPrecisly(nt.getThreshold3())); thresholds.addElement("threshold4") .setText(floatFormatter.formatFloatPrecisly(nt.getThreshold4())); thresholds.addElement("threshold5") .setText(floatFormatter.formatFloatPrecisly(nt.getThreshold5())); } addChangeLog(l.getTransformer().getChangeLog(), transformer); } if (l.getMeasurementInfo() != null) { addMeasurementInfo(l.getMeasurementInfo(), leaf); } Element eval = leaf.addElement("evaluation"); typename = typename.substring(0, typename.lastIndexOf("Scale")); /* * keep in mind: there are only values of the considered alternatives in the map */ for (String a : l.getValueMap().keySet()) { Element alt = eval.addElement("alternative"); alt.addAttribute("key", a); addStringElement(alt, "comment", l.getValueMap().get(a).getComment()); for (Value v : l.getValueMap().get(a).getList()) { /* * A special element is created, depending on the type of the scale */ Element valElement = alt.addElement(typename + "Result"); addStringElement(valElement, "value", v.toString()); addStringElement(valElement, "comment", v.getComment()); addChangeLog(v.getChangeLog(), valElement); } } } } else { // not a leaf Element node = xmlRoot.addElement("node"); addNodeAttributes(data, node); for (TreeNode child : data.getChildren()) { addSubTree(child, node); } } } /** * creates a new element with all information of the given measurementInfo, * and adds it to the parent node. * This includes the property and the chosen metric, but NOT the list of possible metrics. * * @param info * @param parent */ private void addMeasurementInfo(MeasurementInfo info, Element parent) { Element infoEl = parent.addElement("measurementInfo"); MeasurableProperty prop = (MeasurableProperty) info.getProperty(); if (prop != null) { Element propertyEl = infoEl.addElement("property"); addStringElement(propertyEl, "category", prop.getCategory().toString()); addStringElement(propertyEl, "propertyId", prop.getPropertyId()); addStringElement(propertyEl, "name", prop.getName()); addStringElement(propertyEl, "description", prop.getDescription()); addScale(prop.getScale(), propertyEl); // note: we only keep the selected property and metric addChangeLog(prop.getChangeLog(), propertyEl); } addMetric(info.getMetric(), infoEl); addChangeLog(info.getChangeLog(), infoEl); } /** * creates a new element with all information of the given metric, * and adds it to the parent node. * * @param m * @param parent */ private void addMetric(Metric m, Element parent) { if (m != null) { Element metricEl = parent.addElement("metric"); addStringElement(metricEl, "metricId", m.getMetricId()); addStringElement(metricEl, "name", m.getName()); addStringElement(metricEl, "description", m.getDescription()); addScale(m.getScale(), metricEl); addChangeLog(m.getChangeLog(), metricEl); } } /** * Adds the given node's properties to the xmlNode. */ private void addNodeAttributes(TreeNode data, Element xmlNode) { xmlNode.addAttribute("name", data.getName()).addAttribute("weight", floatFormatter.formatFloatPrecisly(data.getWeight())); if (data instanceof Leaf) { xmlNode.addAttribute("single", Boolean.toString(data.isSingle())); } xmlNode.addAttribute("lock", Boolean.toString(data.isLock())); addStringElement(xmlNode, "description", data.getDescription()); addChangeLog(data.getChangeLog(), xmlNode); } private void addChangeLog(ChangeLog log, Element xmlNode) { if (log != null) { xmlNode.addElement("changelog").addAttribute("created", formatter.formatTimestamp(log.getCreated())) .addAttribute("createdBy", log.getCreatedBy()) .addAttribute("changed", formatter.formatTimestamp(log.getChanged())) .addAttribute("changedBy", log.getChangedBy()); } } private Element addUpload(DigitalObject upload, Element parentNode, String elementName, BASE64Encoder encoder, List<Integer> uploadIDs) { Element xmlNode = null; if ((upload != null) && (!"".equals(upload.getFullname())) && upload.isDataExistent()) { xmlNode = parentNode.addElement(elementName); xmlNode.addAttribute("fullname", upload.getFullname()).addAttribute("contentType", upload.getContentType()); Element data = xmlNode.addElement("data"); data.addAttribute("hasData", "true"); data.addAttribute("encoding", "base64"); if (uploadIDs != null) { // write only DigitalObject.id, it will be replaced later data.setText("" + upload.getId()); // remember ID of upload uploadIDs.add(upload.getId()); } else { // directly write encoded data data.setText(encoder.encode(upload.getData().getData())); } if (upload.getXcdlDescription() != null) { addUpload(upload.getXcdlDescription(), xmlNode, "xcdlDescription", encoder, uploadIDs); } addJhoveString(upload, encoder, xmlNode); addFitsInfo(upload, encoder, xmlNode); addChangeLog(upload.getChangeLog(), xmlNode); } return xmlNode; } private void addJhoveString(DigitalObject digitalObject, BASE64Encoder encoder, Element xmlNode) { String jhoveXML = digitalObject.getJhoveXMLString(); if ((jhoveXML != null) && (!"".equals(jhoveXML))) { Element jhove = xmlNode.addElement("jhoveXML"); jhove.addAttribute("encoding", "base64"); try { jhove.setText(encoder.encode(jhoveXML.getBytes("UTF-8"))); } catch (UnsupportedEncodingException e) { jhove.setText(""); PlatoLogger.getLogger(this.getClass()).error(e.getMessage(), e); } } } private void addFitsInfo(DigitalObject digitalObject, BASE64Encoder encoder, Element xmlNode) { String fitsInfo = digitalObject.getFitsXMLString(); if ((fitsInfo != null) && (!"".equals(fitsInfo))) { Element fitsElement = xmlNode.addElement("fitsXML"); fitsElement.addAttribute("encoding", "base64"); try { fitsElement.setText(encoder.encode(fitsInfo.getBytes("UTF-8"))); } catch (UnsupportedEncodingException e) { fitsElement.setText(""); PlatoLogger.getLogger(this.getClass()).error(e.getMessage(), e); } } } private String deriveElementname(Class c) { String name = c.getName(); name = name.substring(name.lastIndexOf(".") + 1); name = name.substring(0, 1).toLowerCase() + name.substring(1); return name; } /** * Adds the XML-representation of the given project to the parent <code>projectNode</code> * * @param p * @param projectNode */ public void addProject(Plan p, Document projectsDoc, List<Integer> uploadIDs, List<Integer> recordIDs) { Element projectNode = projectsDoc.getRootElement().addElement(new QName("plan", platoNS)); // Base64 encoder for binary data BASE64Encoder encoder = new BASE64Encoder(); addChangeLog(p.getChangeLog(), projectNode); // Plan state projectNode.addElement("state").addAttribute("value", Integer.toString(p.getState().getValue())); Element properties = projectNode.addElement("properties"); addUpload(p.getPlanProperties().getReportUpload(), properties, "report", encoder, uploadIDs); // Plan properties properties.addAttribute("author", p.getPlanProperties().getAuthor()) .addAttribute("organization", p.getPlanProperties().getOrganization()) .addAttribute("name", p.getPlanProperties().getName()) .addAttribute("privateProject", Boolean.toString(p.getPlanProperties().isPrivateProject())) .addAttribute("reportPublic", Boolean.toString(p.getPlanProperties().isReportPublic())); addStringElement(properties, "description", p.getPlanProperties().getDescription()); addStringElement(properties, "owner", p.getPlanProperties().getOwner()); addChangeLog(p.getPlanProperties().getChangeLog(), properties); // Plan Basis Element basis = projectNode.addElement("basis"); basis.addAttribute("identificationCode", p.getProjectBasis().getIdentificationCode()); addStringElement(basis, "documentTypes", p.getProjectBasis().getDocumentTypes()); addStringElement(basis, "applyingPolicies", p.getProjectBasis().getApplyingPolicies()); addStringElement(basis, "designatedCommunity", p.getProjectBasis().getDesignatedCommunity()); addStringElement(basis, "mandate", p.getProjectBasis().getMandate()); addStringElement(basis, "organisationalProcedures", p.getProjectBasis().getOrganisationalProcedures()); addStringElement(basis, "planningPurpose", p.getProjectBasis().getPlanningPurpose()); addStringElement(basis, "planRelations", p.getProjectBasis().getPlanRelations()); addStringElement(basis, "preservationRights", p.getProjectBasis().getPreservationRights()); addStringElement(basis, "referenceToAgreements", p.getProjectBasis().getReferenceToAgreements()); Element triggers = basis.addElement("triggers"); if (p.getProjectBasis().getTriggers() != null) { addTrigger(triggers, p.getProjectBasis().getTriggers().getNewCollection()); addTrigger(triggers, p.getProjectBasis().getTriggers().getPeriodicReview()); addTrigger(triggers, p.getProjectBasis().getTriggers().getChangedEnvironment()); addTrigger(triggers, p.getProjectBasis().getTriggers().getChangedObjective()); addTrigger(triggers, p.getProjectBasis().getTriggers().getChangedCollectionProfile()); } Element policyTree = basis.addElement("policyTree"); addSubPolicyTree(p.getProjectBasis().getPolicyTree().getRoot(), policyTree); addChangeLog(p.getProjectBasis().getChangeLog(), basis); // Sample Records Element samplerecords = projectNode.addElement("sampleRecords"); addStringElement(samplerecords, "samplesDescription", p.getSampleRecordsDefinition().getSamplesDescription()); Element collectionProfile = samplerecords.addElement("collectionProfile"); if (p.getSampleRecordsDefinition().getCollectionProfile() != null) { addStringElement(collectionProfile, "collectionID", p.getSampleRecordsDefinition().getCollectionProfile().getCollectionID()); addStringElement(collectionProfile, "description", p.getSampleRecordsDefinition().getCollectionProfile().getDescription()); addStringElement(collectionProfile, "expectedGrowthRate", p.getSampleRecordsDefinition().getCollectionProfile().getExpectedGrowthRate()); addStringElement(collectionProfile, "numberOfObjects", p.getSampleRecordsDefinition().getCollectionProfile().getNumberOfObjects()); addStringElement(collectionProfile, "typeOfObjects", p.getSampleRecordsDefinition().getCollectionProfile().getTypeOfObjects()); addStringElement(collectionProfile, "retentionPeriod", p.getSampleRecordsDefinition().getCollectionProfile().getRetentionPeriod()); for (SampleObject rec : p.getSampleRecordsDefinition().getRecords()) { Element sampleRecord = samplerecords.addElement("record") .addAttribute("shortName", rec.getShortName()).addAttribute("fullname", rec.getFullname()) .addAttribute("contentType", rec.getContentType()); Element data = sampleRecord.addElement("data"); if (rec.isDataExistent()) { data.addAttribute("hasData", "true"); data.addAttribute("encoding", "base64"); if (recordIDs != null) { data.setText("" + rec.getId()); recordIDs.add(rec.getId()); } else { data.setText(encoder.encode(rec.getData().getData())); } addUpload(rec.getXcdlDescription(), sampleRecord, "xcdlDescription", encoder, uploadIDs); addJhoveString(rec, encoder, sampleRecord); addFitsInfo(rec, encoder, sampleRecord); } else { data.addAttribute("hasData", "false"); } Element formatInfo = sampleRecord.addElement("formatInfo") .addAttribute("puid", rec.getFormatInfo().getPuid()) .addAttribute("name", rec.getFormatInfo().getName()) .addAttribute("version", rec.getFormatInfo().getVersion()) .addAttribute("mimeType", rec.getFormatInfo().getMimeType()) .addAttribute("defaultExtension", rec.getFormatInfo().getDefaultExtension()); addChangeLog(rec.getFormatInfo().getChangeLog(), formatInfo); addChangeLog(rec.getChangeLog(), sampleRecord); addStringElement(sampleRecord, "description", rec.getDescription()); addStringElement(sampleRecord, "originalTechnicalEnvironment", rec.getOriginalTechnicalEnvironment()); } addChangeLog(p.getSampleRecordsDefinition().getChangeLog(), samplerecords); // Requirementsdefinition Element rdef = projectNode.addElement("requirementsDefinition"); addStringElement(rdef, "description", p.getRequirementsDefinition().getDescription()); Element uploads = rdef.addElement("uploads"); for (DigitalObject upload : p.getRequirementsDefinition().getUploads()) { addUpload(upload, uploads, "upload", encoder, uploadIDs); } addChangeLog(p.getRequirementsDefinition().getChangeLog(), rdef); // Alternatives Element alternatives = projectNode.addElement("alternatives"); addStringElement(alternatives, "description", p.getAlternativesDefinition().getDescription()); for (Alternative a : p.getAlternativesDefinition().getAlternatives()) { /* * Export all alternatives (also discarded ones) * Indices of the result-set reference only the considered alternatives! */ Element alt = alternatives.addElement("alternative") .addAttribute("discarded", Boolean.toString(a.isDiscarded())) .addAttribute("name", a.getName()); addStringElement(alt, "description", a.getDescription()); if (a.getAction() != null) { Element action = alt.addElement("action"); action.addAttribute("shortname", a.getAction().getShortname()) .addAttribute("url", a.getAction().getUrl()) .addAttribute("actionIdentifier", a.getAction().getActionIdentifier()) .addAttribute("info", a.getAction().getInfo()) .addAttribute("targetFormat", a.getAction().getTargetFormat()) .addAttribute("executable", String.valueOf(a.getAction().isExecutable())); addStringElement(action, "descriptor", a.getAction().getDescriptor()); addStringElement(action, "parameterInfo", a.getAction().getParameterInfo()); Element params = action.addElement("params"); if (a.getAction().getParams() != null) { for (Parameter param : a.getAction().getParams()) { params.addElement("param").addAttribute("name", param.getName()).addAttribute("value", param.getValue()); } } addChangeLog(a.getAction().getChangeLog(), action); } Element resourceDescr = alt.addElement("resourceDescription"); addStringElement(resourceDescr, "necessaryResources", a.getResourceDescription().getNecessaryResources()); addStringElement(resourceDescr, "configSettings", a.getResourceDescription().getConfigSettings()); addStringElement(resourceDescr, "reasonForConsidering", a.getResourceDescription().getReasonForConsidering()); addChangeLog(a.getResourceDescription().getChangeLog(), resourceDescr); Element experiment = alt.addElement("experiment"); Experiment exp = a.getExperiment(); addStringElement(experiment, "description", exp.getDescription()); //addStringElement(experiment, "runDescription", exp.getRunDescription()); addStringElement(experiment, "settings", exp.getSettings()); uploads = experiment.addElement("results"); for (SampleObject record : exp.getResults().keySet()) { DigitalObject up = exp.getResults().get(record); if (up != null) { // only existing uploads are exported Element upload = addUpload(up, uploads, "result", encoder, uploadIDs); if (upload != null) { upload.addAttribute("key", record.getShortName()); } } } // // */experiment/xcdlDescriptions/xcdlDescription // Element xcdls = experiment.addElement("xcdlDescriptions"); // for (SampleObject record : exp.getResults().keySet()) { // DigitalObject result = exp.getResults().get(record); // if (result != null) { // XcdlDescription x = result.getXcdlDescription(); // if (x != null) { // // only existing xcdls are exported // Element upload = addUpload(x, xcdls, "xcdlDescription", encoder, uploadIDs); // if (upload != null) { // upload.addAttribute("key", record.getShortName()); // } // } // } // } // export detailed experiment info's Element detailedInfos = experiment.addElement("detailedInfos"); for (SampleObject record : exp.getDetailedInfo().keySet()) { DetailedExperimentInfo dinfo = exp.getDetailedInfo().get(record); Element detailedInfo = detailedInfos.addElement("detailedInfo") .addAttribute("key", record.getShortName()) .addAttribute("successful", "" + dinfo.getSuccessful()); addStringElement(detailedInfo, "programOutput", dinfo.getProgramOutput()); addStringElement(detailedInfo, "cpr", dinfo.getCpr()); Element measurements = detailedInfo.addElement("measurements"); for (Measurement m : dinfo.getMeasurements().values()) { Element measurement = measurements.addElement("measurement"); // measurement.value: String typename = deriveElementname(m.getValue().getClass()); Element valueElem = measurement.addElement(typename); //.addAttribute("value", m.getValue().toString()); addStringElement(valueElem, "value", m.getValue().toString()); addChangeLog(m.getValue().getChangeLog(), valueElem); // measurement.property: Element property = measurement.addElement("property").addAttribute("name", m.getProperty().getName()); addScale(m.getProperty().getScale(), property); } } addChangeLog(a.getExperiment().getChangeLog(), experiment); addChangeLog(a.getChangeLog(), alt); } addChangeLog(p.getAlternativesDefinition().getChangeLog(), alternatives); // go-nogo - is created in the go-nogo step and need not exist if (p.getDecision() != null) { Element decision = projectNode.addElement("decision"); addStringElement(decision, "reason", p.getDecision().getReason()); addStringElement(decision, "actionNeeded", p.getDecision().getActionNeeded()); decision.addElement("goDecision").addAttribute("value", p.getDecision().getDecision().name()); addChangeLog(p.getDecision().getChangeLog(), decision); } // Evaluation Element evaluation = projectNode.addElement("evaluation"); addStringElement(evaluation, "comment", p.getEvaluation().getComment()); addChangeLog(p.getEvaluation().getChangeLog(), evaluation); // importance weighting Element importanceWeighting = projectNode.addElement("importanceWeighting"); addStringElement(importanceWeighting, "comment", p.getImportanceWeighting().getComment()); addChangeLog(p.getImportanceWeighting().getChangeLog(), importanceWeighting); // Recommendation Element recommendation = projectNode.addElement("recommendation"); if (p.getRecommendation().getAlternative() != null) { recommendation.addAttribute("alternativeName", p.getRecommendation().getAlternative().getName()); } addStringElement(recommendation, "reasoning", p.getRecommendation().getReasoning()); addStringElement(recommendation, "effects", p.getRecommendation().getEffects()); addChangeLog(p.getRecommendation().getChangeLog(), recommendation); // transformation Element trafo = projectNode.addElement("transformation"); addStringElement(trafo, "comment", p.getTransformation().getComment()); addChangeLog(p.getTransformation().getChangeLog(), trafo); // Objectivetree (including weights, evaluation values and transformers) Element tree = projectNode.addElement("tree"); tree.addAttribute("weightsInitialized", "" + p.getTree().isWeightsInitialized()); if (p.getTree().getRoot() != null) addSubTree(p.getTree().getRoot(), tree); } Element executablePlan = projectNode.addElement("executablePlan"); try { if (p.getExecutablePlanDefinition().getExecutablePlan() != null) { Document execPlan = DocumentHelper.parseText(p.getExecutablePlanDefinition().getExecutablePlan()); Element execPlanRoot = execPlan.getRootElement(); if (execPlanRoot.hasContent()) { Element planWorkflow = executablePlan.addElement("planWorkflow"); planWorkflow.add(execPlanRoot); } } if (p.getExecutablePlanDefinition().getEprintsExecutablePlan() != null) { Document execPlan = DocumentHelper .parseText(p.getExecutablePlanDefinition().getEprintsExecutablePlan()); Element execPlanRoot = execPlan.getRootElement(); if (execPlanRoot.hasContent()) { //Element planWorkflow = executablePlan.addElement("eprintsPlan"); executablePlan.add(execPlanRoot); } } } catch (DocumentException e) { // if the stored exec. plan is invalid for some reason, we leave the plan out. // TODO: HK this should no happen as we write the xml ourselves, but still, // we need a mechanism here to prevent the export if the xml is invalid. PlatoLogger.getLogger(this.getClass()).error(e.getMessage(), e); } // TODO HK how does this here relate to the upper try-catch block and the exception?? // Smells like a hack! ExecutablePlanDefinition plan = p.getExecutablePlanDefinition(); addStringElement(executablePlan, "objectPath", plan.getObjectPath()); addStringElement(executablePlan, "toolParameters", plan.getToolParameters()); addStringElement(executablePlan, "triggersConditions", plan.getTriggersConditions()); addStringElement(executablePlan, "validateQA", plan.getValidateQA()); addChangeLog(plan.getChangeLog(), executablePlan); Element planDef = projectNode.addElement("planDefinition"); PlanDefinition pdef = p.getPlanDefinition(); planDef.addAttribute("currency", pdef.getCurrency()); addStringElement(planDef, "costsIG", pdef.getCostsIG()); addStringElement(planDef, "costsPA", pdef.getCostsPA()); addStringElement(planDef, "costsPE", pdef.getCostsPE()); addStringElement(planDef, "costsQA", pdef.getCostsQA()); addStringElement(planDef, "costsREI", pdef.getCostsREI()); addStringElement(planDef, "costsRemarks", pdef.getCostsRemarks()); addStringElement(planDef, "costsRM", pdef.getCostsRM()); addStringElement(planDef, "costsTCO", pdef.getCostsTCO()); addStringElement(planDef, "responsibleExecution", pdef.getResponsibleExecution()); addStringElement(planDef, "responsibleMonitoring", pdef.getResponsibleMonitoring()); triggers = planDef.addElement("triggers"); if (pdef.getTriggers() != null) { addTrigger(triggers, pdef.getTriggers().getNewCollection()); addTrigger(triggers, pdef.getTriggers().getPeriodicReview()); addTrigger(triggers, pdef.getTriggers().getChangedEnvironment()); addTrigger(triggers, pdef.getTriggers().getChangedObjective()); addTrigger(triggers, pdef.getTriggers().getChangedCollectionProfile()); } addChangeLog(pdef.getChangeLog(), planDef); } private void addTrigger(Element triggers, Trigger t) { if (t == null) { return; } Element trigger = triggers.addElement("trigger"); trigger.addAttribute("type", t.getType().name()); trigger.addAttribute("active", Boolean.toString(t.isActive())); trigger.addAttribute("description", t.getDescription()); } /** * Long strings are stored as XML-elements, not as attributes. * It is not possible to add an element with value <code>null</code>, * therefore this has to be handled here: * A new element is only added if there is a value at all. * * @param parent * @param name * @param value */ private Element addStringElement(Element parent, String name, String value) { Element e = null; // &&(!"".equals(value) if (value != null) { e = parent.addElement(name); if (!"".equals(value)) { e.addText(value); } } return e; } public String exportTreeToFreemind(Plan plan) { return exportTreeToFreemind(plan.getTree().getRoot()); } public String exportTreeToFreemind(TreeNode treeRoot) { Document doc = DocumentHelper.createDocument(); Element root = doc.addElement("map"); Namespace xsi = new Namespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); root.add(xsi); root.addAttribute("version", "0.8.1"); root.addComment( "To view this file, download free mind mapping software FreeMind from http://freemind.sourceforge.net"); addSubTreeFreemind(root, treeRoot); String xml = doc.asXML(); //PlatoLogger.getLogger(ProjectExporter.class).debug(arg0) return xml; } private void addSubTreeFreemind(Element xmlElement, TreeNode node) { Element element = xmlElement.addElement("node"); addFreemindAttributes(node, element); if (node.isLeaf()) { //add scale Leaf leaf = (Leaf) node; Scale scale = leaf.getScale(); if (scale != null) { Element scaleElement = element.addElement("node"); String restriction = "?"; //restrictions: restrictedscale, ordinals -freestring if (scale instanceof FreeStringScale) { restriction = "free text"; } else if ((scale.getType() == ScaleType.ordinal || scale.getType() == ScaleType.restricted) && !"".equals(((RestrictedScale) scale).getRestriction())) { restriction = ((RestrictedScale) scale).getRestriction(); } else { restriction = scale.getUnit(); } scaleElement.addAttribute("TEXT", restriction); } } else { // add children for (TreeNode child : node.getChildren()) { addSubTreeFreemind(element, child); } } } private void addFreemindAttributes(TreeNode node, Element element) { element.addAttribute("TEXT", node.getName()); //TODO export weights? units? single? >> future. String mInfoUri = null; if (node.isLeaf()) { mInfoUri = ((Leaf) node).getMeasurementInfo().getUri(); } // add DESCRIPTION if existent if (((mInfoUri != null) && (!"".equals(mInfoUri))) || (node.getDescription() != null && !"".equals(node.getDescription()))) { Element hook = element.addElement("hook"); hook.addAttribute("NAME", "accessories/plugins/NodeNote.properties"); Element description = hook.addElement("text"); String descr = ""; // and measurement info if ((mInfoUri != null) && (!"".equals(mInfoUri))) { descr = "measuredProperty=" + mInfoUri + "\n"; } if (node.getDescription() != null) { descr = descr + node.getDescription(); } description.setText(descr); } } private void addScale(Scale s, Element parent) { if (s != null) { String typename = deriveElementname(s.getClass()); Element scale = parent.addElement(typename); // && (!"".equals(s.getUnit() if (s.getUnit() != null) { scale.addAttribute("unit", s.getUnit()); } //scale.addAttribute("displayName", s.getDisplayName()); if (s instanceof RestrictedScale) { scale.addAttribute("restriction", ((RestrictedScale) s).getRestriction()); } addChangeLog(s.getChangeLog(), scale); } } }