r519 - in masc/masc-api/src: main/java/fr/inra/masc main/java/fr/inra/masc/io main/java/fr/inra/masc/services test/java/fr/inra/masc/services
Author: sletellier Date: 2011-12-14 16:37:31 +0100 (Wed, 14 Dec 2011) New Revision: 519 Url: http://nuiton.org/repositories/revision/sandbox/519 Log: - Improve Element to write xml - Write mexico xml files - Write tests Added: masc/masc-api/src/main/java/fr/inra/masc/io/ masc/masc-api/src/main/java/fr/inra/masc/io/Element.java masc/masc-api/src/test/java/fr/inra/masc/services/MexicoSaveModelServiceTest.java Modified: masc/masc-api/src/main/java/fr/inra/masc/services/MexicoSaveModelService.java masc/masc-api/src/main/java/fr/inra/masc/services/SaveModelService.java masc/masc-api/src/test/java/fr/inra/masc/services/SaveModelServiceTest.java Added: masc/masc-api/src/main/java/fr/inra/masc/io/Element.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/Element.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/Element.java 2011-12-14 15:37:31 UTC (rev 519) @@ -0,0 +1,115 @@ +package fr.inra.masc.io; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.LinkedList; +import java.util.Map; +import java.util.Set; + +/** + * Represent an XML node + * + * @author sletellier <letellier@codelutin.com> + * @since 0.1 + */ +public class Element { + + public static final String XML_META = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; + public static final String CLOSED_TAG = "%s<%s%s/>\n"; + public static final String START_TAG = "%s<%s%s>"; + public static final String END_TAG = "%s</%s>\n"; + + protected LinkedList<Element> children; + protected Map<String, String> parameters; + protected String tagName; + protected String text; + + public Element(String tagName) { + this(tagName, null); + } + + public Element(String tagName, String text) { + this.tagName = tagName; + this.text = text; + this.children = Lists.newLinkedList(); + this.parameters = Maps.newHashMap(); + } + + public void add(Element e) { + this.children.add(e); + } + + public void addParameter(String name, String value) { + this.parameters.put(name, value); + } + + public String toXml(int indent) { + StringBuilder stringBuilder = new StringBuilder(XML_META).append("\n"); + buildXml(-indent, indent, stringBuilder); + return stringBuilder.toString(); + } + + protected void buildXml(int start, int indent, StringBuilder stringBuilder) { + + // closed tag if content is empty + if (children.isEmpty() && StringUtils.isEmpty(text)) { + addToBuilder(stringBuilder, CLOSED_TAG, getIndentPrefix(start, indent), tagName); + return; + } + + // start tag + addToBuilder(stringBuilder, START_TAG, getIndentPrefix(start, indent), tagName); + if (StringUtils.isNotEmpty(text)) { + + // end inline tag + addToBuilder(stringBuilder, END_TAG, StringEscapeUtils.escapeXml(text), tagName); + } else { + stringBuilder.append("\n"); + for (Element child : children) { + child.buildXml(start + indent, indent, stringBuilder); + } + // end tag + addToBuilder(stringBuilder, END_TAG, getIndentPrefix(start, indent), tagName); + } + } + + protected void addToBuilder(StringBuilder stringBuilder, String template, String prefix, String tagName) { + stringBuilder.append(String.format(template, prefix, tagName, getParametersAsString())); + } + + protected String getIndentPrefix(int start, int lenght) { + String result = ""; + for (int i=0;i<start + lenght;i++) { + result += " "; + } + return result; + } + + protected String getParametersAsString() { + StringBuilder builder = new StringBuilder(); + Set<Map.Entry<String,String>> entries = parameters.entrySet(); + for (Map.Entry<String,String> entry : entries) { + + // add to builder param like : name="value" + builder.append(" ").append(entry.getKey()).append("=\"").append(entry.getValue()).append("\""); + } + return builder.toString(); + } + + public static Element createElement(Element parentElement, String tagName) { + return createElement(parentElement, tagName, null); + } + + public static Element createElement(Element parentElement, String tagName, String text) { + Element element = createElement(tagName, text); + parentElement.add(element); + return element; + } + + public static Element createElement(String tagName, String text) { + return new Element(tagName, text); + } +} Modified: masc/masc-api/src/main/java/fr/inra/masc/services/MexicoSaveModelService.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/services/MexicoSaveModelService.java 2011-12-14 10:05:14 UTC (rev 518) +++ masc/masc-api/src/main/java/fr/inra/masc/services/MexicoSaveModelService.java 2011-12-14 15:37:31 UTC (rev 519) @@ -1,13 +1,29 @@ package fr.inra.masc.services; +import fr.ifremer.mexico.model.Domain; import fr.ifremer.mexico.model.ExperienceDesign; +import fr.ifremer.mexico.model.Factor; +import fr.ifremer.mexico.model.Feature; +import fr.ifremer.mexico.model.InputDesign; +import fr.ifremer.mexico.model.Scenario; +import fr.inra.masc.io.Element; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.Map; /** + * Service to save mexico model to mexico xml file + * * @author sletellier <letellier@codelutin.com> + * @since 0.1 */ public class MexicoSaveModelService extends MascService { @@ -19,15 +35,206 @@ return log; } - public File saveExperienceDesign(ExperienceDesign mexicoModel, File toSave) { + public void saveExperienceDesign(ExperienceDesign experienceDesign, File toSave) { - // TODO sletellier : write mexico experience design xml file - return toSave; + ExperienceDesignXmlWriter experienceDesignXmlWriter = new ExperienceDesignXmlWriter(experienceDesign); + String xml = experienceDesignXmlWriter.composeXml(2); + + log.info(xml); + + FileWriter writer = null; + try { + writer = new FileWriter(toSave); + writer.write(xml); + } catch (IOException eee) { + throwMascTechnicalException("Failed to write exp design xml file", eee); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException eee) { + throwMascTechnicalException("Failed to close exp design xml file", eee); + } + } + } } - public File saveInputDesignDesign(ExperienceDesign mexicoModel, File toSave) { + public void saveInputDesign(InputDesign inputDesign, File toSave) { - // TODO sletellier : write mexico input design xml file - return toSave; + InputDesignXmlWriter inputDesignXmlWriter = new InputDesignXmlWriter(inputDesign); + String xml = inputDesignXmlWriter.composeXml(2); + + log.info(xml); + + FileWriter writer = null; + try { + writer = new FileWriter(toSave); + writer.write(xml); + } catch (IOException eee) { + throwMascTechnicalException("Failed to write exp design xml file", eee); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException eee) { + throwMascTechnicalException("Failed to close exp design xml file", eee); + } + } + } } + + public class ExperienceDesignXmlWriter { + + protected ExperienceDesign model; + + public ExperienceDesignXmlWriter(ExperienceDesign model) { + this.model = model; + } + + public String composeXml(int indent) { + + return getRootElement().toXml(indent); + } + + public Element getRootElement() { + + Element rootElement = new Element(ExperienceDesign.class.getSimpleName()); + composeExperienceDesignMeta(rootElement); + composeFactors(rootElement); + + // TODO sletellier 2011/12/14 : implement workflow + // composeWorkFlow(rootElement); + + return rootElement; + } + + protected void composeExperienceDesignMeta(Element rootElement) { + + // date + Date date = model.getDate(); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String formatedDate = dateFormat.format(date); + addParameter(rootElement, ExperienceDesign.PROPERTY_DATE, formatedDate); + + addParameter(rootElement, ExperienceDesign.PROPERTY_ID, model.getId()); + addParameter(rootElement, ExperienceDesign.PROPERTY_AUTHOR, model.getAuthor()); + addParameter(rootElement, ExperienceDesign.PROPERTY_LICENCE, model.getLicence()); + + // description + String description = model.getDescription(); + if (StringUtils.isNotEmpty(description)) { + Element.createElement(rootElement, ExperienceDesign.PROPERTY_DESCRIPTION, description); + } + } + + protected void composeFactors(Element rootElement) { + Collection<Factor> factors = model.getFactors(); + + // do nothing if no factors in model + if (factors.isEmpty()) { + return; + } + + // creating factors node + Element factorsElement = Element.createElement(rootElement, ExperienceDesign.PROPERTY_FACTORS); + for (Factor factor : factors) { + + // factor + Element factorElement = Element.createElement(factorsElement, Factor.class.getSimpleName()); + addParameter(factorElement, Factor.PROPERTY_ID, factor.getId()); + addParameter(factorElement,Factor.PROPERTY_NAME, factor.getName()); + addParameter(factorElement, Factor.PROPERTY_UNIT, factor.getUnit()); + + // description + String description = model.getDescription(); + if (StringUtils.isNotEmpty(description)) { + Element.createElement(factorElement, Factor.PROPERTY_DESCRIPTION, factor.getDescription()); + } + + // domain + Domain domain = factor.getDomain(); + if (domain != null) { + Element domainElement = Element.createElement(factorElement, Factor.PROPERTY_DOMAIN); + addParameter(domainElement, Domain.PROPERTY_NAME, domain.getName()); + addParameter(domainElement, Domain.PROPERTY_DISTRIBUTION_PARAMETER, domain.getDistributionParameter()); + addParameter(domainElement, Domain.PROPERTY_LEVEL, String.valueOf(domain.getLevel())); + addParameter(domainElement, Domain.PROPERTY_VALUE_TYPE, domain.getValueType()); + addParameter(domainElement, Domain.PROPERTY_NOMINAL_VALUE, domain.getNominalValue()); + } + + // features + addAllFeature(factorElement, factor.getFeatures()); + } + } + + protected void addAllFeature(Element factorElement, Collection<Feature> features) { + if (features != null) { + for (Feature feature : features) { + Element featureElement = Element.createElement(factorElement, Factor.PROPERTY_FEATURES); + addParameter(featureElement, Feature.PROPERTY_NAME, feature.getName()); + addParameter(featureElement, Feature.PROPERTY_VALUE, feature.getValue()); + addParameter(featureElement, Feature.PROPERTY_VALUE_TYPE, feature.getValueType()); + } + } + } + + protected void addParameter(Element element, String parameterName, Object value) { + if (value != null) { + element.addParameter(parameterName, value.toString()); + } + } + } + + public class InputDesignXmlWriter extends ExperienceDesignXmlWriter{ + + protected InputDesign model; + + public InputDesignXmlWriter(InputDesign model) { + super(model.getExperienceDesign()); + this.model = model; + } + + @Override + public String composeXml(int indent) { + + Element rootElement = new Element(InputDesign.class.getSimpleName()); + composeInputDesignMeta(rootElement); + composeScenarios(rootElement); + + return rootElement.toXml(indent); + } + + protected void composeInputDesignMeta(Element rootElement) { + + // date + Date date = model.getDate(); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String formatedDate = dateFormat.format(date); + addParameter(rootElement, InputDesign.PROPERTY_DATE, formatedDate); + + // experiement design + rootElement.add(getRootElement()); + } + + protected void composeScenarios(Element rootElement) { + + // scenarios + for (Scenario scenario : model.getScenarios()) { + Element scenariosElement = Element.createElement(rootElement, InputDesign.PROPERTY_SCENARIOS); + addParameter(scenariosElement, Scenario.PROPERTY_NAME, scenario.getName()); + addParameter(scenariosElement, Scenario.PROPERTY_ORDER_NUMBER, scenario.getOrderNumber()); + + // factor values + Map<Factor,Object> factorValues = scenario.getFactorValues(); + for (Map.Entry<Factor,Object> entry : factorValues.entrySet()) { + Object value = entry.getValue(); + Element factorValueElement = Element.createElement(scenariosElement, Scenario.PROPERTY_FACTOR_VALUES, String.valueOf(value)); + factorValueElement.addParameter(Factor.class.getSimpleName(), entry.getKey().getId()); + } + + // features + addAllFeature(scenariosElement, scenario.getFeatures()); + } + } + } } Modified: masc/masc-api/src/main/java/fr/inra/masc/services/SaveModelService.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/services/SaveModelService.java 2011-12-14 10:05:14 UTC (rev 518) +++ masc/masc-api/src/main/java/fr/inra/masc/services/SaveModelService.java 2011-12-14 15:37:31 UTC (rev 519) @@ -1,8 +1,8 @@ package fr.inra.masc.services; import com.google.common.collect.LinkedListMultimap; -import com.google.common.collect.Lists; import com.google.common.collect.Multimap; +import fr.inra.masc.io.Element; import fr.inra.masc.model.ComputableCriteria; import fr.inra.masc.model.Criteria; import fr.inra.masc.model.Function; @@ -12,7 +12,6 @@ import fr.inra.masc.model.ScaleValue; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; -import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -21,7 +20,6 @@ import java.io.FileWriter; import java.io.IOException; import java.util.Collection; -import java.util.LinkedList; import java.util.Map; import static fr.inra.masc.model.MascXmlConstant.ATTRIBUTE; @@ -45,7 +43,7 @@ import static fr.inra.masc.model.MascXmlConstant.SETTINGS; /** - * Service to save masc model + * Service to save masc model to DEXi xml file * * @author sletellier <letellier@codelutin.com> * @since 0.1 @@ -63,20 +61,20 @@ public void saveModel(MascModel model, File saveFile) { DexiXmlWriter dexiXmlWriter = new DexiXmlWriter(model); - Element xml = dexiXmlWriter.composeXml(); + String xml = dexiXmlWriter.composeXml(2); FileWriter writer = null; try { writer = new FileWriter(saveFile); - writer.write(xml.toXml(2)); + writer.write(xml); } catch (IOException eee) { - throwMascTechnicalException("Failed to write document", eee); + throwMascTechnicalException("Failed to write DEXi xml file", eee); } finally { if (writer != null) { try { writer.close(); } catch (IOException eee) { - throwMascTechnicalException("Failed to close document", eee); + throwMascTechnicalException("Failed to close DEXi xml file", eee); } } } @@ -92,12 +90,12 @@ this.criteriaOptionValues = LinkedListMultimap.create(); } - public Element composeXml() { + public String composeXml(int indent) { Element rootElement = new Element(DEXI); composeMeta(rootElement); composeAttributes(rootElement); - return rootElement; + return rootElement.toXml(indent); } @@ -200,81 +198,15 @@ } } - protected Element createElement(Element parentElement, String tagName) { + // Override to upper case tagNames + public Element createElement(Element parentElement, String tagName) { return createElement(parentElement, tagName, null); } - - protected Element createElement(Element parentElement, String tagName, String text) { - Element element = createElement(tagName.toUpperCase(), text); + + public Element createElement(Element parentElement, String tagName, String text) { + Element element = Element.createElement(tagName.toUpperCase(), text); parentElement.add(element); return element; } - - protected Element createElement(String tagName, String text) { - return new Element(tagName, text); - } - } - - protected class Element { - - public static final String XML_META = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; - - protected LinkedList<Element> children; - protected String tagName; - protected String text; - - public Element(String tagName) { - this(tagName, null); - } - - public Element(String tagName, String text) { - this.tagName = tagName; - this.text = text; - this.children = Lists.newLinkedList(); - } - - public void add(Element e) { - this.children.add(e); - } - - public String toXml(int indent) { - StringBuilder stringBuilder = new StringBuilder(XML_META).append("\n"); - buildXml(-indent, indent, stringBuilder); - return stringBuilder.toString(); - } - - protected void buildXml(int start, int indent, StringBuilder stringBuilder) { - - // closed tag if content is empty - if (children.isEmpty() && StringUtils.isEmpty(text)) { - stringBuilder.append(getIndentPrefix(start, indent)).append("<").append(tagName).append("/>").append("\n"); - return; - } - - // start tag - stringBuilder.append(getIndentPrefix(start, indent)).append("<").append(tagName).append(">"); - if (StringUtils.isNotEmpty(text)) { - stringBuilder.append(StringEscapeUtils.escapeXml(text)); - - // end inline tag - stringBuilder.append("</").append(tagName).append(">").append("\n"); - } else { - stringBuilder.append("\n"); - for (Element child : children) { - child.buildXml(start + indent, indent, stringBuilder); - } - // end tag - stringBuilder.append(getIndentPrefix(start, indent)).append("</").append(tagName).append(">").append("\n"); - } - } - - protected String getIndentPrefix(int start, int lenght) { - String result = ""; - for (int i=0;i<start + lenght;i++) { - result += " "; - } - return result; - } - } } Added: masc/masc-api/src/test/java/fr/inra/masc/services/MexicoSaveModelServiceTest.java =================================================================== --- masc/masc-api/src/test/java/fr/inra/masc/services/MexicoSaveModelServiceTest.java (rev 0) +++ masc/masc-api/src/test/java/fr/inra/masc/services/MexicoSaveModelServiceTest.java 2011-12-14 15:37:31 UTC (rev 519) @@ -0,0 +1,38 @@ +package fr.inra.masc.services; + +import fr.ifremer.mexico.model.ExperienceDesign; +import fr.ifremer.mexico.model.InputDesign; +import fr.inra.masc.model.MascModel; +import org.junit.Test; + +import java.io.File; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 0.1 + */ +public class MexicoSaveModelServiceTest extends AbstractServiceTest { + + @Test + public void testSaveExperienceDesign() throws Exception { + MexicoModelConvertorService mexicoModelConvertorService = getService(MexicoModelConvertorService.class); + File dexiTestFile = getDexiTestFile(); + MascModel mascModel = getService(LoadModelService.class).loadModel(dexiTestFile); + ExperienceDesign experienceDesign = mexicoModelConvertorService.convertMascModelToMexicoExperienceDesignModel(mascModel); + + File savedFile = new File(testWorkDir, "ExperienceDesignTestFileResult.xml"); + getService(MexicoSaveModelService.class).saveExperienceDesign(experienceDesign, savedFile); + } + + @Test + public void testSaveInputDesign() throws Exception { + File dexiTestFile = getDexiTestFile(); + MascModel mascModel = getService(LoadModelService.class).loadModel(dexiTestFile); + MexicoModelConvertorService mexicoModelConvertorService = getService(MexicoModelConvertorService.class); + ExperienceDesign experienceDesign = mexicoModelConvertorService.convertMascModelToMexicoExperienceDesignModel(mascModel); + InputDesign inputDesign = mexicoModelConvertorService.convertMascModelToMexicoInputDesignModel(mascModel, experienceDesign); + + File savedFile = new File(testWorkDir, "inputDesignTestFileResult.xml"); + getService(MexicoSaveModelService.class).saveInputDesign(inputDesign, savedFile); + } +} Modified: masc/masc-api/src/test/java/fr/inra/masc/services/SaveModelServiceTest.java =================================================================== --- masc/masc-api/src/test/java/fr/inra/masc/services/SaveModelServiceTest.java 2011-12-14 10:05:14 UTC (rev 518) +++ masc/masc-api/src/test/java/fr/inra/masc/services/SaveModelServiceTest.java 2011-12-14 15:37:31 UTC (rev 519) @@ -3,7 +3,6 @@ import fr.inra.masc.model.MascModel; import org.apache.commons.io.FileUtils; import org.custommonkey.xmlunit.Diff; -import org.junit.Ignore; import org.junit.Test; import org.xml.sax.SAXException; @@ -16,7 +15,6 @@ public class SaveModelServiceTest extends AbstractServiceTest { @Test - @Ignore // TODO sletellier 20111209 : fix line separator public void testSaveModelWithDexiTestModelFile() throws Exception { File dexiTestFile = getDexiModelTestFile(); @@ -46,6 +44,9 @@ String input = FileUtils.readFileToString(in); String output = FileUtils.readFileToString(out); + // Hack to don't take care of end of line char + input = input.replaceAll("\r\n", "\n"); + assertEquals(input.trim(), output.trim()); Diff myDiff = new Diff(input, output);
participants (1)
-
sletellier@users.nuiton.org