Author: sletellier Date: 2011-12-15 11:31:40 +0100 (Thu, 15 Dec 2011) New Revision: 520 Url: http://nuiton.org/repositories/revision/sandbox/520 Log: - Parse mexico xml files (inputDesign and experimentDesign) - Add test parsing mexico xml files - Refactor creating specific writer and parser - Rename Element to XmlNode Added: masc/masc-api/src/main/java/fr/inra/masc/io/DateFormatFactory.java masc/masc-api/src/main/java/fr/inra/masc/io/MascXmlConstant.java masc/masc-api/src/main/java/fr/inra/masc/io/MexicoXmlConstant.java masc/masc-api/src/main/java/fr/inra/masc/io/parser/ masc/masc-api/src/main/java/fr/inra/masc/io/parser/ExperienceDesignParser.java masc/masc-api/src/main/java/fr/inra/masc/io/parser/InputDesignParser.java masc/masc-api/src/main/java/fr/inra/masc/io/parser/MascModelParser.java masc/masc-api/src/main/java/fr/inra/masc/io/parser/MexicoXmlParser.java masc/masc-api/src/main/java/fr/inra/masc/io/parser/XmlParser.java masc/masc-api/src/main/java/fr/inra/masc/io/writer/ masc/masc-api/src/main/java/fr/inra/masc/io/writer/DexiXmlWriter.java masc/masc-api/src/main/java/fr/inra/masc/io/writer/ExperienceDesignXmlWriter.java masc/masc-api/src/main/java/fr/inra/masc/io/writer/InputDesignXmlWriter.java masc/masc-api/src/main/java/fr/inra/masc/io/writer/MexicoXmlWriter.java masc/masc-api/src/main/java/fr/inra/masc/io/writer/XmlNode.java masc/masc-api/src/main/java/fr/inra/masc/io/writer/XmlWriter.java masc/masc-api/src/test/java/fr/inra/masc/services/MexicoLoadModelServiceTest.java Removed: masc/masc-api/src/main/java/fr/inra/masc/io/Element.java masc/masc-api/src/main/java/fr/inra/masc/model/MascXmlConstant.java Modified: masc/masc-api/src/main/java/fr/inra/masc/services/LoadModelService.java masc/masc-api/src/main/java/fr/inra/masc/services/MexicoLoadModelService.java 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/MexicoSaveModelServiceTest.java Added: masc/masc-api/src/main/java/fr/inra/masc/io/DateFormatFactory.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/DateFormatFactory.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/DateFormatFactory.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,21 @@ +package fr.inra.masc.io; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class DateFormatFactory { + + public static final String MEXICO_DATE_PATTERN = "yyyy-MM-dd"; + protected static DateFormat mexicoDateFormat; + + public static DateFormat getMexicoDateFormat() { + // singleton + if (mexicoDateFormat == null) { + mexicoDateFormat = new SimpleDateFormat(MEXICO_DATE_PATTERN); + } + return mexicoDateFormat; + } +} Deleted: masc/masc-api/src/main/java/fr/inra/masc/io/Element.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/Element.java 2011-12-14 15:37:31 UTC (rev 519) +++ masc/masc-api/src/main/java/fr/inra/masc/io/Element.java 2011-12-15 10:31:40 UTC (rev 520) @@ -1,115 +0,0 @@ -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); - } -} Copied: masc/masc-api/src/main/java/fr/inra/masc/io/MascXmlConstant.java (from rev 516, masc/masc-api/src/main/java/fr/inra/masc/model/MascXmlConstant.java) =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/MascXmlConstant.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/MascXmlConstant.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,36 @@ +package fr.inra.masc.io; + +import fr.inra.masc.model.ComputableCriteria; +import fr.inra.masc.model.Criteria; +import fr.inra.masc.model.Function; +import fr.inra.masc.model.MascModel; +import fr.inra.masc.model.ScaleValue; + +/** + * Regroup all masc xml constants tags + * + * @author sletellier <letellier@codelutin.com> + * @since 0.1 + */ +public class MascXmlConstant { + + public static final String DEXI = "DEXi"; + public static final String LINE = "line"; + public static final String ATTRIBUTE = "attribute"; + public static final String MODEL_NAME = MascModel.PROPERTY_NAME; + public static final String MODEL_DESCRIPTION = MascModel.PROPERTY_DESCRIPTION; + public static final String OPTION = MascModel.PROPERTY_OPTION; + public static final String SETTINGS = MascModel.PROPERTY_SETTINGS; + public static final String CRITERIA_NAME = Criteria.PROPERTY_NAME; + public static final String CRITERIA_DESCRIPTION = Criteria.PROPERTY_DESCRIPTION; + public static final String SCALE = Criteria.PROPERTY_SCALE; + public static final String SCALE_VALUE = ScaleValue.class.getSimpleName(); + public static final String SCALE_VALUE_NAME = ScaleValue.PROPERTY_NAME; + public static final String SCALE_VALUE_DESCRIPTION = ScaleValue.PROPERTY_DESCRIPTION; + public static final String SCALE_VALUE_GROUP = ScaleValue.PROPERTY_GROUP; + public static final String FUNCTION = ComputableCriteria.PROPERTY_FUNCTION; + public static final String FUNCTION_LOW = Function.PROPERTY_LOW; + public static final String FUNCTION_ENTERED = Function.PROPERTY_ENTERED; + public static final String FUNCTION_WEIGHTS = Function.PROPERTY_WEIGHTS; + public static final String FUNCTION_CONSIST = Function.PROPERTY_CONSIST; +} Added: masc/masc-api/src/main/java/fr/inra/masc/io/MexicoXmlConstant.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/MexicoXmlConstant.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/MexicoXmlConstant.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,46 @@ +package fr.inra.masc.io; + +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; + +/** + * Regroup all mexico xml constants tags + * + * @author sletellier <letellier@codelutin.com> + * @since 0.1 + */ +public class MexicoXmlConstant { + + public static final String EXPERIMENT_DESIGN = ExperienceDesign.class.getSimpleName().toLowerCase(); + public static final String EXPERIMENT_DESIGN_DATE = ExperienceDesign.PROPERTY_DATE; + public static final String EXPERIMENT_DESIGN_ID = ExperienceDesign.PROPERTY_ID; + public static final String EXPERIMENT_DESIGN_AUTHOR = ExperienceDesign.PROPERTY_AUTHOR; + public static final String EXPERIMENT_DESIGN_LICENCE = ExperienceDesign.PROPERTY_LICENCE; + public static final String EXPERIMENT_DESIGN_DESCRIPTION = ExperienceDesign.PROPERTY_DESCRIPTION; + public static final String FACTORS = ExperienceDesign.PROPERTY_FACTORS; + public static final String FACTOR = Factor.class.getSimpleName().toLowerCase(); + public static final String FACTOR_ID = Factor.PROPERTY_ID; + public static final String FACTOR_NAME = Factor.PROPERTY_NAME; + public static final String FACTOR_UNIT = Factor.PROPERTY_UNIT; + public static final String FACTOR_DESCRIPTION = Factor.PROPERTY_DESCRIPTION; + public static final String DOMAIN = Factor.PROPERTY_DOMAIN; + public static final String DOMAIN_NAME = Domain.PROPERTY_NAME; + public static final String DOMAIN_DISTRIBUTION_PARAMETER = Domain.PROPERTY_DISTRIBUTION_PARAMETER; + public static final String DOMAIN_LEVEL = Domain.PROPERTY_LEVEL; + public static final String DOMAIN_VALUE_TYPE = Domain.PROPERTY_VALUE_TYPE; + public static final String DOMAIN_NOMINAL_VALUE = Domain.PROPERTY_NOMINAL_VALUE; + public static final String FEATURE = Feature.class.getSimpleName().toLowerCase(); + public static final String FEATURE_NAME = Feature.PROPERTY_NAME; + public static final String FEATURE_VALUE = Feature.PROPERTY_VALUE; + public static final String FEATURE_VALUE_TYPE = Feature.PROPERTY_VALUE_TYPE; + public static final String INPUT_DESIGN = InputDesign.class.getSimpleName().toLowerCase(); + public static final String INPUT_DESIGN_DATE = InputDesign.PROPERTY_DATE; + public static final String SCENARIO = Scenario.class.getSimpleName().toLowerCase(); + public static final String SCENARIO_NAME = Scenario.PROPERTY_NAME; + public static final String SCENARIO_ORDER_NUMBER = Scenario.PROPERTY_ORDER_NUMBER; + public static final String SCENARIO_FACTOR_VALUES = Scenario.PROPERTY_FACTOR_VALUES; +} Added: masc/masc-api/src/main/java/fr/inra/masc/io/parser/ExperienceDesignParser.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/parser/ExperienceDesignParser.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/parser/ExperienceDesignParser.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,215 @@ +package fr.inra.masc.io.parser; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import fr.ifremer.mexico.model.Domain; +import fr.ifremer.mexico.model.DomainImpl; +import fr.ifremer.mexico.model.ExperienceDesign; +import fr.ifremer.mexico.model.ExperienceDesignImpl; +import fr.ifremer.mexico.model.Factor; +import fr.ifremer.mexico.model.FactorImpl; +import fr.ifremer.mexico.model.Feature; +import fr.ifremer.mexico.model.FeatureImpl; +import fr.ifremer.mexico.model.ValueType; +import fr.inra.masc.MascTechnicalException; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.text.ParseException; +import java.util.List; +import java.util.Map; + +import static fr.inra.masc.io.MexicoXmlConstant.DOMAIN; +import static fr.inra.masc.io.MexicoXmlConstant.DOMAIN_DISTRIBUTION_PARAMETER; +import static fr.inra.masc.io.MexicoXmlConstant.DOMAIN_LEVEL; +import static fr.inra.masc.io.MexicoXmlConstant.DOMAIN_NAME; +import static fr.inra.masc.io.MexicoXmlConstant.DOMAIN_NOMINAL_VALUE; +import static fr.inra.masc.io.MexicoXmlConstant.DOMAIN_VALUE_TYPE; +import static fr.inra.masc.io.MexicoXmlConstant.EXPERIMENT_DESIGN; +import static fr.inra.masc.io.MexicoXmlConstant.EXPERIMENT_DESIGN_AUTHOR; +import static fr.inra.masc.io.MexicoXmlConstant.EXPERIMENT_DESIGN_DATE; +import static fr.inra.masc.io.MexicoXmlConstant.EXPERIMENT_DESIGN_DESCRIPTION; +import static fr.inra.masc.io.MexicoXmlConstant.EXPERIMENT_DESIGN_ID; +import static fr.inra.masc.io.MexicoXmlConstant.EXPERIMENT_DESIGN_LICENCE; +import static fr.inra.masc.io.MexicoXmlConstant.FACTORS; +import static fr.inra.masc.io.MexicoXmlConstant.FACTOR_DESCRIPTION; +import static fr.inra.masc.io.MexicoXmlConstant.FEATURE; +import static fr.inra.masc.io.MexicoXmlConstant.FEATURE_NAME; +import static fr.inra.masc.io.MexicoXmlConstant.FEATURE_VALUE; +import static fr.inra.masc.io.MexicoXmlConstant.FEATURE_VALUE_TYPE; + +/** +* @author sletellier <letellier@codelutin.com> +*/ +public class ExperienceDesignParser extends MexicoXmlParser<ExperienceDesign> { + + protected Map<String, Factor> factors; + + public ExperienceDesignParser(File file) throws FileNotFoundException { + super(file); + this.factors = Maps.newHashMap(); + } + + @Override + protected ExperienceDesign parseModel(XmlPullParser parser) throws IOException, XmlPullParserException, ParseException { + ExperienceDesign model = new ExperienceDesignImpl(); + + parseExperienceDesignMeta(parser, model); + parseFactors(parser, model); + + return model; + } + + protected void parseExperienceDesignMeta(XmlPullParser parser, ExperienceDesign model) throws IOException, XmlPullParserException, ParseException { + + // file must start with experiment design tag + if (parser.nextTag() == XmlPullParser.START_TAG && + !parserEqual(parser, EXPERIMENT_DESIGN)) { + throw new MascTechnicalException("Experiment design file must start with " + EXPERIMENT_DESIGN + " tag"); + } + + // parse experiment design id + String id = parser.getAttributeValue(null, EXPERIMENT_DESIGN_ID); + model.setId(id); + + // parse date + String dateAsString = parser.getAttributeValue(null, EXPERIMENT_DESIGN_DATE); + model.setDate(parseDate(dateAsString)); + + // parse author + String author = parser.getAttributeValue(null, EXPERIMENT_DESIGN_AUTHOR); + model.setAuthor(author); + + // parse license + String license = parser.getAttributeValue(null, EXPERIMENT_DESIGN_LICENCE); + model.setLicence(license); + + // parse description + if (parser.nextTag() == XmlPullParser.START_TAG && + parserEqual(parser, EXPERIMENT_DESIGN_DESCRIPTION)) { + + model.setDescription(parser.nextText()); + + // read next tag + parser.nextTag(); + } + } + protected void parseFactors(XmlPullParser parser, ExperienceDesign model) throws IOException, XmlPullParserException { + + // factors + int eventType = parser.getEventType(); + if (eventType == XmlPullParser.START_TAG && + parserEqual(parser, FACTORS)) { + + List<Factor> factors = Lists.newArrayList(); + while (!(parser.nextTag() == XmlPullParser.END_TAG && + parserEqual(parser, FACTORS))) { + + // factor + factors.add(parseFactor(parser)); + } + model.setFactors(factors); + } + + // read experience design next tag + parser.nextTag(); + } + + protected Factor parseFactor(XmlPullParser parser) throws IOException, XmlPullParserException { + + Factor factor = new FactorImpl(); + + // parse description + int eventType = parser.nextTag(); + if (eventType == XmlPullParser.START_TAG && + parserEqual(parser, FACTOR_DESCRIPTION)) { + factor.setDescription(parser.nextText()); + + // read function close tag + eventType = parser.nextTag(); + } + + // domain + if (eventType == XmlPullParser.START_TAG && + parserEqual(parser, DOMAIN)) { + factor.setDomain(parseDomain(parser)); + } + + // features + if (parser.getEventType() == XmlPullParser.START_TAG && + parserEqual(parser, FEATURE)) { + + List<Feature> features = Lists.newArrayList(); + + while (parserEqual(parser, FEATURE)) { + + // feature + features.add(parseFeature(parser)); + + // read feature close tag + parser.nextTag(); + + // read next tag + parser.nextTag(); + } + factor.setFeatures(features); + } + + // keep factors + factors.put(factor.getId(), factor); + + return factor; + } + protected Domain parseDomain(XmlPullParser parser) throws XmlPullParserException { + Domain domain = new DomainImpl(); + + // name + String name = parser.getAttributeValue(null, DOMAIN_NAME); + domain.setName(name); + + // distributionParameter + String distributionParameter = parser.getAttributeValue(null, DOMAIN_DISTRIBUTION_PARAMETER); + domain.setDistributionParameter(distributionParameter); + + // level + String level = parser.getAttributeValue(null, DOMAIN_LEVEL); + domain.setLevel(Integer.parseInt(level)); + + // valueType + String valueType = parser.getAttributeValue(null, DOMAIN_VALUE_TYPE); + domain.setValueType(ValueType.valueOf(valueType)); + + // nominaleValue + // TODO sletellier 20111215 : take care of type + String nominaleValue = parser.getAttributeValue(null, DOMAIN_NOMINAL_VALUE); + domain.setNominalValue(nominaleValue); + + return domain; + } + + protected Feature parseFeature(XmlPullParser parser) { + Feature feature = new FeatureImpl(); + + // name + String name = parser.getAttributeValue(null, FEATURE_NAME); + feature.setName(name); + + // value + // TODO sletellier 20111215 : take care of type + String value = parser.getAttributeValue(null, FEATURE_VALUE); + feature.setValue(value); + + // value type + String valueType = parser.getAttributeValue(null, FEATURE_VALUE_TYPE); + feature.setValueType(ValueType.valueOf(valueType)); + + return feature; + } + + public Map<String, Factor> getFactors() { + return factors; + } +} Added: masc/masc-api/src/main/java/fr/inra/masc/io/parser/InputDesignParser.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/parser/InputDesignParser.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/parser/InputDesignParser.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,126 @@ +package fr.inra.masc.io.parser; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import fr.ifremer.mexico.model.ExperienceDesign; +import fr.ifremer.mexico.model.Factor; +import fr.ifremer.mexico.model.InputDesign; +import fr.ifremer.mexico.model.InputDesignImpl; +import fr.ifremer.mexico.model.Scenario; +import fr.ifremer.mexico.model.ScenarioImpl; +import fr.inra.masc.MascTechnicalException; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.text.ParseException; +import java.util.List; +import java.util.Map; + +import static fr.inra.masc.io.MexicoXmlConstant.FACTOR; +import static fr.inra.masc.io.MexicoXmlConstant.INPUT_DESIGN; +import static fr.inra.masc.io.MexicoXmlConstant.INPUT_DESIGN_DATE; +import static fr.inra.masc.io.MexicoXmlConstant.SCENARIO; +import static fr.inra.masc.io.MexicoXmlConstant.SCENARIO_FACTOR_VALUES; +import static fr.inra.masc.io.MexicoXmlConstant.SCENARIO_NAME; +import static fr.inra.masc.io.MexicoXmlConstant.SCENARIO_ORDER_NUMBER; + +/** +* @author sletellier <letellier@codelutin.com> +*/ +public class InputDesignParser extends MexicoXmlParser<InputDesign> { + + protected ExperienceDesignParser experienceDesignParser; + + public InputDesignParser(File file) throws FileNotFoundException { + super(file); + experienceDesignParser = new ExperienceDesignParser(file); + } + + @Override + protected InputDesign parseModel(XmlPullParser parser) throws IOException, XmlPullParserException, ParseException { + InputDesign model = new InputDesignImpl(); + + parseInputDesignMeta(parser, model); + + // parse experiment design + ExperienceDesign experienceDesign = experienceDesignParser.parseModel(parser); + model.setExperienceDesign(experienceDesign); + + parseScenarios(parser, model); + + return model; + } + + protected void parseInputDesignMeta(XmlPullParser parser, InputDesign model) throws IOException, XmlPullParserException, ParseException { + + // file must start with input design tag + if (parser.next() == XmlPullParser.START_TAG && + !parserEqual(parser, INPUT_DESIGN)) { + throw new MascTechnicalException("Input design file must start with " + INPUT_DESIGN + " tag"); + } + + // parse date + String dateAsString = parser.getAttributeValue(null, INPUT_DESIGN_DATE); + model.setDate(parseDate(dateAsString)); + } + + protected void parseScenarios(XmlPullParser parser, InputDesign model) throws IOException, XmlPullParserException { + + // scenarios + if (parser.nextTag() == XmlPullParser.START_TAG && + parserEqual(parser, SCENARIO)) { + + List<Scenario> scenarios = Lists.newArrayList(); + while (!(parser.getEventType() == XmlPullParser.END_TAG && + parserEqual(parser, INPUT_DESIGN))) { + + // factor + scenarios.add(parseScenario(parser)); + } + model.setScenarios(scenarios); + } + } + + protected Scenario parseScenario(XmlPullParser parser) throws IOException, XmlPullParserException { + Scenario scenario = new ScenarioImpl(); + + // name + String name = parser.getAttributeValue(null, SCENARIO_NAME); + scenario.setName(name); + + // orderValue + String orderValue = parser.getAttributeValue(null, SCENARIO_ORDER_NUMBER); + scenario.setOrderNumber(Integer.parseInt(orderValue)); + + // factor values + if (parser.nextTag() == XmlPullParser.START_TAG && + parserEqual(parser, SCENARIO_FACTOR_VALUES)) { + + Map<Factor, Object> factorValues = Maps.newHashMap(); + while (!(parser.getEventType() == XmlPullParser.END_TAG && + parserEqual(parser, SCENARIO))) { + + // get factor + String factorId = parser.getAttributeValue(null, FACTOR); + Factor factor = experienceDesignParser.getFactors().get(factorId); + + // factor value + String value = parser.nextText(); + + factorValues.put(factor, value); + + // read next tag + parser.nextTag(); + } + scenario.setFactorValues(factorValues); + } + + // read next tag + parser.nextTag(); + + return scenario; + } +} Added: masc/masc-api/src/main/java/fr/inra/masc/io/parser/MascModelParser.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/parser/MascModelParser.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/parser/MascModelParser.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,372 @@ +package fr.inra.masc.io.parser; + +import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; +import fr.inra.masc.MascTechnicalException; +import fr.inra.masc.model.ComputableCriteria; +import fr.inra.masc.model.ComputableCriteriaImpl; +import fr.inra.masc.model.Criteria; +import fr.inra.masc.model.Function; +import fr.inra.masc.model.FunctionImpl; +import fr.inra.masc.model.MascModel; +import fr.inra.masc.model.MascModelImpl; +import fr.inra.masc.model.Option; +import fr.inra.masc.model.OptionImpl; +import fr.inra.masc.model.OptionValue; +import fr.inra.masc.model.OptionValueImpl; +import fr.inra.masc.model.ScaleGroup; +import fr.inra.masc.model.ScaleValue; +import fr.inra.masc.model.ScaleValueImpl; +import fr.inra.masc.model.ThresholdCriteria; +import fr.inra.masc.model.ThresholdCriteriaImpl; +import fr.inra.masc.model.ValuedCriteriaImpl; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import static fr.inra.masc.io.MascXmlConstant.ATTRIBUTE; +import static fr.inra.masc.io.MascXmlConstant.CRITERIA_DESCRIPTION; +import static fr.inra.masc.io.MascXmlConstant.CRITERIA_NAME; +import static fr.inra.masc.io.MascXmlConstant.DEXI; +import static fr.inra.masc.io.MascXmlConstant.FUNCTION; +import static fr.inra.masc.io.MascXmlConstant.FUNCTION_CONSIST; +import static fr.inra.masc.io.MascXmlConstant.FUNCTION_ENTERED; +import static fr.inra.masc.io.MascXmlConstant.FUNCTION_LOW; +import static fr.inra.masc.io.MascXmlConstant.FUNCTION_WEIGHTS; +import static fr.inra.masc.io.MascXmlConstant.LINE; +import static fr.inra.masc.io.MascXmlConstant.MODEL_DESCRIPTION; +import static fr.inra.masc.io.MascXmlConstant.MODEL_NAME; +import static fr.inra.masc.io.MascXmlConstant.OPTION; +import static fr.inra.masc.io.MascXmlConstant.SCALE; +import static fr.inra.masc.io.MascXmlConstant.SCALE_VALUE_DESCRIPTION; +import static fr.inra.masc.io.MascXmlConstant.SCALE_VALUE_GROUP; +import static fr.inra.masc.io.MascXmlConstant.SCALE_VALUE_NAME; +import static fr.inra.masc.io.MascXmlConstant.SETTINGS; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class MascModelParser extends XmlParser<MascModel> { + + protected Multimap<String,Integer> thresholds; + + public MascModelParser(File file, Multimap<String,Integer> thresholds) throws FileNotFoundException { + super(file); + this.thresholds = thresholds; + } + + @Override + protected MascModel parseModel(XmlPullParser parser) throws IOException, XmlPullParserException, ParseException { + MascModel model = new MascModelImpl(); + + parseMeta(parser, model); + parseAttributes(parser, model); + + return model; + } + + protected void parseMeta(XmlPullParser parser, MascModel model) throws IOException, XmlPullParserException { + + // file must start with DEXi tag + if (parser.next() == XmlPullParser.START_TAG && + !parserEqual(parser, DEXI)) { + throw new MascTechnicalException("Masc file must start with " + DEXI + " tag"); + } + + // start parsing model attributes + // parse name + int eventType = parser.nextTag(); + if (eventType == XmlPullParser.START_TAG && + parserEqual(parser, MODEL_NAME)) { + model.setName(parser.nextText()); + + // read next tag + eventType = parser.nextTag(); + } + + // parse description + if (eventType == XmlPullParser.START_TAG && + parserEqual(parser, MODEL_DESCRIPTION)) { + + List<String> descriptions = Lists.newArrayList(); + while (!(parser.nextTag() == XmlPullParser.END_TAG && + parserEqual(parser, MODEL_DESCRIPTION))) { + + if (parserEqual(parser, LINE)) { + descriptions.add(parser.nextText()); + } + } + + model.setDescription(descriptions); + + // read next tag + eventType = parser.nextTag(); + } + + // parse options + List<Option> options = Lists.newLinkedList(); + while (eventType == XmlPullParser.START_TAG && + parserEqual(parser, OPTION)) { + + Option option = new OptionImpl(); + option.setName(parser.nextText()); + options.add(option); + + // read end option tag + eventType = parser.nextTag(); + } + model.setOption(options); + + // parse settings + if (eventType == XmlPullParser.START_TAG && + parserEqual(parser, SETTINGS)) { + + Map<String, String> settings = new LinkedHashMap<String, String>(); + while (!(parser.nextTag() == XmlPullParser.END_TAG && + parserEqual(parser, SETTINGS))) { + settings.put(parser.getName(), parser.nextText()); + } + model.setSettings(settings); + + // read next tag + parser.nextTag(); + } + } + + protected void parseAttributes(XmlPullParser parser, MascModel model) throws IOException, XmlPullParserException { + List<Criteria> criterias = Lists.newArrayList(); + while (parser.getEventType() == XmlPullParser.START_TAG && + parserEqual(parser, ATTRIBUTE)) { + + Criteria criteria = parseAttribute(parser, model); + criterias.add(criteria); + + // Read closeTag + parser.nextTag(); + } + model.setCriteria(criterias); + } + + protected Criteria parseAttribute(XmlPullParser parser, MascModel model) throws IOException, XmlPullParserException { + + // parse name + int eventType = parser.nextTag(); + if (eventType == XmlPullParser.START_TAG && + !parserEqual(parser, CRITERIA_NAME)) { + + throw new MascTechnicalException("All criteria must have a name"); + } + String name = parser.nextText(); + + // read next tag + eventType = parser.nextTag(); + + // parse description + String description = null; + if (eventType == XmlPullParser.START_TAG && + parserEqual(parser, CRITERIA_DESCRIPTION)) { + + description = parser.nextText(); + + // read next tag + eventType = parser.nextTag(); + } + + // parse scales + if (eventType == XmlPullParser.START_TAG && + !parserEqual(parser, SCALE)) { + + throw new MascTechnicalException("All criteria must have a scalesValue"); + } + List<ScaleValue> scaleValues = parseScale(parser); + + // parse function + Function function = null; + if (parser.getEventType() == XmlPullParser.START_TAG && + parserEqual(parser, FUNCTION)) { + + function = parseFunction(parser); + } + + // parse option value + int optionValueCnt = 0; + List<OptionValue> optionValues = Lists.newLinkedList(); + while (eventType == XmlPullParser.START_TAG && + parserEqual(parser, OPTION)) { + + OptionValue optionValue = new OptionValueImpl(); + optionValue.setValue(Integer.parseInt(parser.nextText())); + Option option = model.getOption(optionValueCnt++); + + // initialize option value list + if (option.getOptionValue() == null) { + LinkedList<OptionValue> optionValuesList = Lists.newLinkedList(); + option.setOptionValue(optionValuesList); + } + option.addOptionValue(optionValue); + optionValues.add(optionValue); + + // read next tag + eventType = parser.nextTag(); + } + + // parse attributes + List<Criteria> criterias = new ArrayList<Criteria>(); + if (parser.getEventType() == XmlPullParser.START_TAG && + parserEqual(parser, ATTRIBUTE)) { + + while (!(parser.getEventType() == XmlPullParser.END_TAG && + parserEqual(parser, ATTRIBUTE))) { + + criterias.add(parseAttribute(parser, model)); + parser.nextTag(); + } + } + + Criteria current; + if (function != null) { + + // non editable criteria + ComputableCriteria computableCriteria = new ComputableCriteriaImpl(); + computableCriteria.setFunction(function); + current = computableCriteria; + } else { + + // editable criteria + // check on properties if its a threshold criteria + if (thresholds.containsKey(name)) { + ThresholdCriteria thresholdCriteria = new ThresholdCriteriaImpl(); + Collection<Integer> values = thresholds.get(name); + thresholdCriteria.setValues(values); + current = thresholdCriteria; + } else { + // else is a valued one + current = new ValuedCriteriaImpl(); + } + } + + // fill options values + for (OptionValue optionValue : optionValues) { + optionValue.setCriteria(current); + } + + // fill criteria + current.setName(name); + current.setDescription(description); + current.setScale(scaleValues); + current.setChildren(criterias); + + return current; + } + + protected List<ScaleValue> parseScale(XmlPullParser parser) throws IOException, XmlPullParserException { + + List<ScaleValue> scaleValues = new ArrayList<ScaleValue>(); + while (!(parser.nextTag() == XmlPullParser.END_TAG && + parserEqual(parser, SCALE))) { + + // parse name + int eventType = parser.nextTag(); + if (eventType == XmlPullParser.START_TAG && + !parserEqual(parser, SCALE_VALUE_NAME)) { + + throw new MascTechnicalException("All scale value must have a name"); + } + ScaleValue scaleValue = new ScaleValueImpl(); + scaleValue.setName(parser.nextText()); + eventType = parser.nextTag(); + + // parse description + if (eventType == XmlPullParser.START_TAG && + parserEqual(parser, SCALE_VALUE_DESCRIPTION)) { + + scaleValue.setDescription(parser.nextText()); + + // read next tag + eventType = parser.nextTag(); + } + + // parse group + if (eventType == XmlPullParser.START_TAG && + parserEqual(parser, SCALE_VALUE_GROUP)) { + + String groupValue = parser.nextText(); + scaleValue.setGroup(ScaleGroup.valueOf(groupValue)); + + // read next tag + parser.nextTag(); + } + scaleValues.add(scaleValue); + } + // read scale close tag + parser.nextTag(); + + return scaleValues; + } + + protected Function parseFunction(XmlPullParser parser) throws IOException, XmlPullParserException { + Function function = new FunctionImpl(); + + // parse low + int eventType = parser.nextTag(); + if (eventType == XmlPullParser.START_TAG && + parserEqual(parser, FUNCTION_LOW)) { + + function.setLow(parser.nextText()); + + // read next tag + eventType = parser.nextTag(); + } + + // parse entered + if (eventType == XmlPullParser.START_TAG && + parserEqual(parser, FUNCTION_ENTERED)) { + + function.setEntered(parser.nextText()); + + // read next tag + eventType = parser.nextTag(); + } + + // parse weights + if (eventType == XmlPullParser.START_TAG && + parserEqual(parser, FUNCTION_WEIGHTS)) { + + function.setWeights(parser.nextText()); + + // read next tag + eventType = parser.nextTag(); + } + + // parse consist + if (eventType == XmlPullParser.START_TAG && + parserEqual(parser, FUNCTION_CONSIST)) { + + function.setConsist(Boolean.parseBoolean(parser.nextText())); + + // read next tag + parser.nextTag(); + } + + // read function close tag + parser.nextTag(); + + return function; + } + + @Override + public boolean parserEqual(XmlPullParser parser, String name) { + String tagName = parser.getName(); + return tagName.equalsIgnoreCase(name); + } +} Added: masc/masc-api/src/main/java/fr/inra/masc/io/parser/MexicoXmlParser.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/parser/MexicoXmlParser.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/parser/MexicoXmlParser.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,22 @@ +package fr.inra.masc.io.parser; + +import fr.inra.masc.io.DateFormatFactory; + +import java.io.File; +import java.io.FileNotFoundException; +import java.text.ParseException; +import java.util.Date; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public abstract class MexicoXmlParser<M> extends XmlParser<M> { + + public MexicoXmlParser(File file) throws FileNotFoundException { + super(file); + } + + public Date parseDate(String toParse) throws ParseException { + return DateFormatFactory.getMexicoDateFormat().parse(toParse); + } +} Added: masc/masc-api/src/main/java/fr/inra/masc/io/parser/XmlParser.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/parser/XmlParser.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/parser/XmlParser.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,42 @@ +package fr.inra.masc.io.parser; + +import fr.inra.masc.io.DateFormatFactory; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParserFactory; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.text.ParseException; + +/** + * Abstract parser to get model from xml file using XPP3 + * + * @author sletellier <letellier@codelutin.com> + * @since 0.1 + */ +public abstract class XmlParser<M> extends FileReader { + + public XmlParser(File file) throws FileNotFoundException { + super(file); + } + + public M getModel() throws XmlPullParserException, IOException, ParseException { + + XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); + XmlPullParser parser = factory.newPullParser(); + parser.setInput(this); + + // parse model + return parseModel(parser); + } + + protected abstract M parseModel(XmlPullParser parser) throws IOException, XmlPullParserException, ParseException; + + public boolean parserEqual(XmlPullParser parser, String name) { + String tagName = parser.getName(); + return tagName.equals(name); + } +} Added: masc/masc-api/src/main/java/fr/inra/masc/io/writer/DexiXmlWriter.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/writer/DexiXmlWriter.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/writer/DexiXmlWriter.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,174 @@ +package fr.inra.masc.io.writer; + +import com.google.common.collect.LinkedListMultimap; +import com.google.common.collect.Multimap; +import fr.inra.masc.model.ComputableCriteria; +import fr.inra.masc.model.Criteria; +import fr.inra.masc.model.Function; +import fr.inra.masc.model.MascModel; +import fr.inra.masc.model.Option; +import fr.inra.masc.model.OptionValue; +import fr.inra.masc.model.ScaleValue; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Map; + +import static fr.inra.masc.io.MascXmlConstant.ATTRIBUTE; +import static fr.inra.masc.io.MascXmlConstant.CRITERIA_DESCRIPTION; +import static fr.inra.masc.io.MascXmlConstant.CRITERIA_NAME; +import static fr.inra.masc.io.MascXmlConstant.DEXI; +import static fr.inra.masc.io.MascXmlConstant.FUNCTION; +import static fr.inra.masc.io.MascXmlConstant.FUNCTION_CONSIST; +import static fr.inra.masc.io.MascXmlConstant.FUNCTION_ENTERED; +import static fr.inra.masc.io.MascXmlConstant.FUNCTION_LOW; +import static fr.inra.masc.io.MascXmlConstant.FUNCTION_WEIGHTS; +import static fr.inra.masc.io.MascXmlConstant.LINE; +import static fr.inra.masc.io.MascXmlConstant.MODEL_DESCRIPTION; +import static fr.inra.masc.io.MascXmlConstant.MODEL_NAME; +import static fr.inra.masc.io.MascXmlConstant.OPTION; +import static fr.inra.masc.io.MascXmlConstant.SCALE; +import static fr.inra.masc.io.MascXmlConstant.SCALE_VALUE; +import static fr.inra.masc.io.MascXmlConstant.SCALE_VALUE_DESCRIPTION; +import static fr.inra.masc.io.MascXmlConstant.SCALE_VALUE_GROUP; +import static fr.inra.masc.io.MascXmlConstant.SCALE_VALUE_NAME; +import static fr.inra.masc.io.MascXmlConstant.SETTINGS; + +/** + * Writer to create DEXi file with {@link MascModel} model + * + * @author sletellier <letellier@codelutin.com> + * @since 0.1 + */ +public class DexiXmlWriter extends XmlWriter<MascModel> { + + protected Multimap<Criteria, OptionValue> criteriaOptionValues; + + public DexiXmlWriter(File file, MascModel model) throws IOException { + super(file, model); + this.criteriaOptionValues = LinkedListMultimap.create(); + } + + @Override + public XmlNode getRootElement() { + XmlNode rootXmlNode = new XmlNode(DEXI); + composeMeta(rootXmlNode); + composeAttributes(rootXmlNode); + + return rootXmlNode; + } + + protected void composeMeta(XmlNode rootXmlNode) { + + // model name + add(rootXmlNode, MODEL_NAME, model.getName()); + + // model description + XmlNode descriptionXmlNode = createElement(rootXmlNode, MODEL_DESCRIPTION); + for (String line : model.getDescription()) { + add(descriptionXmlNode, LINE, line); + } + + // options + for (Option option : model.getOption()) { + add(rootXmlNode, OPTION, option.getName()); + + // load all option values + for (OptionValue optionValue : option.getOptionValue()) { + + // fill map + Criteria criteria = optionValue.getCriteria(); + criteriaOptionValues.put(criteria, optionValue); + } + } + + // settings + Map<String,String> settings = model.getSettings(); + if (MapUtils.isNotEmpty(settings)) { + XmlNode settingXmlNode = createElement(rootXmlNode, SETTINGS); + for (String settingName : settings.keySet()) { + String settingsValue = settings.get(settingName); + add(settingXmlNode, settingName, settingsValue); + } + } + } + + protected void composeAttributes(XmlNode rootXmlNode) { + Collection<Criteria> criterias = model.getCriteria(); + if (CollectionUtils.isNotEmpty(criterias)) { + for (Criteria criteria : criterias) { + composeAttribute(criteria, rootXmlNode); + } + } + } + + protected void composeAttribute(Criteria criteria, XmlNode rootXmlNode) { + XmlNode attributeXmlNode = createElement(rootXmlNode, ATTRIBUTE); + + // attribute name + add(attributeXmlNode, CRITERIA_NAME, criteria.getName()); + + // attribute description + add(attributeXmlNode, CRITERIA_DESCRIPTION, criteria.getDescription()); + + // scale + XmlNode scaleXmlNode = createElement(attributeXmlNode, SCALE); + + // scale values + for (ScaleValue scaleValue : criteria.getScale()) { + XmlNode scaleValueXmlNode = createElement(scaleXmlNode, SCALE_VALUE); + add(scaleValueXmlNode, SCALE_VALUE_NAME, scaleValue.getName()); + add(scaleValueXmlNode, SCALE_VALUE_DESCRIPTION, scaleValue.getDescription()); + add(scaleValueXmlNode, SCALE_VALUE_GROUP, scaleValue.getGroup()); + } + + // function + if (criteria instanceof ComputableCriteria) { + ComputableCriteria computableCriteria = (ComputableCriteria) criteria; + XmlNode functionXmlNode = createElement(attributeXmlNode, FUNCTION); + Function function = computableCriteria.getFunction(); + add(functionXmlNode, FUNCTION_LOW, function.getLow()); + add(functionXmlNode, FUNCTION_ENTERED, function.getEntered()); + add(functionXmlNode, FUNCTION_WEIGHTS, function.getWeights()); + add(functionXmlNode, FUNCTION_CONSIST, function.getConsist()); + } + + // options + Collection<OptionValue> optionValues = criteriaOptionValues.get(criteria); + for (OptionValue optionValue : optionValues) { + add(attributeXmlNode, OPTION, optionValue.getValue()); + } + + // children + for (Criteria child : criteria.getChildren()) { + composeAttribute(child, attributeXmlNode); + } + } + + protected void add(XmlNode parentXmlNode, String tagName, Object value) { + if (value != null) { + String toString = value.toString(); + + // boolean are capitalized in masc xml file + if (value instanceof Boolean) { + toString = StringUtils.capitalize(toString); + } + createElement(parentXmlNode, tagName, toString); + } + } + + // Override to upper case tagNames + public XmlNode createElement(XmlNode parentXmlNode, String tagName) { + return createElement(parentXmlNode, tagName, null); + } + + public XmlNode createElement(XmlNode parentXmlNode, String tagName, String text) { + XmlNode xmlNode = XmlNode.createElement(tagName.toUpperCase(), text); + parentXmlNode.add(xmlNode); + return xmlNode; + } +} Added: masc/masc-api/src/main/java/fr/inra/masc/io/writer/ExperienceDesignXmlWriter.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/writer/ExperienceDesignXmlWriter.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/writer/ExperienceDesignXmlWriter.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,113 @@ +package fr.inra.masc.io.writer; + +import fr.ifremer.mexico.model.Domain; +import fr.ifremer.mexico.model.ExperienceDesign; +import fr.ifremer.mexico.model.Factor; +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Date; + +import static fr.inra.masc.io.MexicoXmlConstant.DOMAIN; +import static fr.inra.masc.io.MexicoXmlConstant.DOMAIN_DISTRIBUTION_PARAMETER; +import static fr.inra.masc.io.MexicoXmlConstant.DOMAIN_LEVEL; +import static fr.inra.masc.io.MexicoXmlConstant.DOMAIN_NAME; +import static fr.inra.masc.io.MexicoXmlConstant.DOMAIN_NOMINAL_VALUE; +import static fr.inra.masc.io.MexicoXmlConstant.DOMAIN_VALUE_TYPE; +import static fr.inra.masc.io.MexicoXmlConstant.EXPERIMENT_DESIGN; +import static fr.inra.masc.io.MexicoXmlConstant.EXPERIMENT_DESIGN_AUTHOR; +import static fr.inra.masc.io.MexicoXmlConstant.EXPERIMENT_DESIGN_DATE; +import static fr.inra.masc.io.MexicoXmlConstant.EXPERIMENT_DESIGN_DESCRIPTION; +import static fr.inra.masc.io.MexicoXmlConstant.EXPERIMENT_DESIGN_ID; +import static fr.inra.masc.io.MexicoXmlConstant.EXPERIMENT_DESIGN_LICENCE; +import static fr.inra.masc.io.MexicoXmlConstant.FACTOR; +import static fr.inra.masc.io.MexicoXmlConstant.FACTORS; +import static fr.inra.masc.io.MexicoXmlConstant.FACTOR_DESCRIPTION; +import static fr.inra.masc.io.MexicoXmlConstant.FACTOR_ID; +import static fr.inra.masc.io.MexicoXmlConstant.FACTOR_NAME; +import static fr.inra.masc.io.MexicoXmlConstant.FACTOR_UNIT; + +/** + * Writer to create experiment design file with {@link ExperienceDesign} model + * + * @author sletellier <letellier@codelutin.com> + * @since 0.1 + */ +public class ExperienceDesignXmlWriter extends MexicoXmlWriter<ExperienceDesign> { + + public ExperienceDesignXmlWriter(File file, ExperienceDesign model) throws IOException { + super(file, model); + } + + @Override + public XmlNode getRootElement() { + + XmlNode rootXmlNode = new XmlNode(EXPERIMENT_DESIGN); + composeExperienceDesignMeta(rootXmlNode); + composeFactors(rootXmlNode); + + // TODO sletellier 2011/12/14 : implement workflow + // composeWorkFlow(rootXmlNode); + + return rootXmlNode; + } + + protected void composeExperienceDesignMeta(XmlNode rootXmlNode) { + + // date + Date date = model.getDate(); + addParameter(rootXmlNode, EXPERIMENT_DESIGN_DATE, formatDate(date)); + + addParameter(rootXmlNode, EXPERIMENT_DESIGN_ID, model.getId()); + addParameter(rootXmlNode, EXPERIMENT_DESIGN_AUTHOR, model.getAuthor()); + addParameter(rootXmlNode, EXPERIMENT_DESIGN_LICENCE, model.getLicence()); + + // description + String description = model.getDescription(); + if (StringUtils.isNotEmpty(description)) { + XmlNode.createElement(rootXmlNode, EXPERIMENT_DESIGN_DESCRIPTION, description); + } + } + + protected void composeFactors(XmlNode rootXmlNode) { + Collection<Factor> factors = model.getFactors(); + + // do nothing if no factors in model + if (factors.isEmpty()) { + return; + } + + // creating factors node + XmlNode factorsXmlNode = XmlNode.createElement(rootXmlNode, FACTORS); + for (Factor factor : factors) { + + // factor + XmlNode factorXmlNode = XmlNode.createElement(factorsXmlNode, FACTOR); + addParameter(factorXmlNode, FACTOR_ID, factor.getId()); + addParameter(factorXmlNode, FACTOR_NAME, factor.getName()); + addParameter(factorXmlNode, FACTOR_UNIT, factor.getUnit()); + + // description + String description = model.getDescription(); + if (StringUtils.isNotEmpty(description)) { + XmlNode.createElement(factorXmlNode, FACTOR_DESCRIPTION, factor.getDescription()); + } + + // domain + Domain domain = factor.getDomain(); + if (domain != null) { + XmlNode domainXmlNode = XmlNode.createElement(factorXmlNode, DOMAIN); + addParameter(domainXmlNode, DOMAIN_NAME, domain.getName()); + addParameter(domainXmlNode, DOMAIN_DISTRIBUTION_PARAMETER, domain.getDistributionParameter()); + addParameter(domainXmlNode, DOMAIN_LEVEL, String.valueOf(domain.getLevel())); + addParameter(domainXmlNode, DOMAIN_VALUE_TYPE, domain.getValueType()); + addParameter(domainXmlNode, DOMAIN_NOMINAL_VALUE, domain.getNominalValue()); + } + + // features + addAllFeature(factorXmlNode, factor.getFeatures()); + } + } +} Added: masc/masc-api/src/main/java/fr/inra/masc/io/writer/InputDesignXmlWriter.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/writer/InputDesignXmlWriter.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/writer/InputDesignXmlWriter.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,71 @@ +package fr.inra.masc.io.writer; + +import fr.ifremer.mexico.model.Factor; +import fr.ifremer.mexico.model.InputDesign; +import fr.ifremer.mexico.model.Scenario; + +import java.io.File; +import java.io.IOException; +import java.util.Date; +import java.util.Map; + +import static fr.inra.masc.io.MexicoXmlConstant.FACTOR; +import static fr.inra.masc.io.MexicoXmlConstant.INPUT_DESIGN; +import static fr.inra.masc.io.MexicoXmlConstant.INPUT_DESIGN_DATE; +import static fr.inra.masc.io.MexicoXmlConstant.SCENARIO; +import static fr.inra.masc.io.MexicoXmlConstant.SCENARIO_FACTOR_VALUES; +import static fr.inra.masc.io.MexicoXmlConstant.SCENARIO_NAME; +import static fr.inra.masc.io.MexicoXmlConstant.SCENARIO_ORDER_NUMBER; + +/** + * Writer to create input design file with {@link fr.ifremer.mexico.model.InputDesign} model + * + * @author sletellier <letellier@codelutin.com> + * @since 0.1 + */ +public class InputDesignXmlWriter extends MexicoXmlWriter<InputDesign> { + + public InputDesignXmlWriter(File file, InputDesign model) throws IOException { + super(file, model); + } + + @Override + public XmlNode getRootElement() { + XmlNode rootXmlNode = new XmlNode(INPUT_DESIGN); + composeInputDesignMeta(rootXmlNode); + composeScenarios(rootXmlNode); + + return rootXmlNode; + } + + protected void composeInputDesignMeta(XmlNode rootXmlNode) { + + // date + Date date = model.getDate(); + addParameter(rootXmlNode, INPUT_DESIGN_DATE, formatDate(date)); + + // experiement design + rootXmlNode.add(getRootElement()); + } + + protected void composeScenarios(XmlNode rootXmlNode) { + + // scenarios + for (Scenario scenario : model.getScenarios()) { + XmlNode scenariosXmlNode = XmlNode.createElement(rootXmlNode, SCENARIO); + addParameter(scenariosXmlNode, SCENARIO_NAME, scenario.getName()); + addParameter(scenariosXmlNode, SCENARIO_ORDER_NUMBER, scenario.getOrderNumber()); + + // factor values + Map<Factor,Object> factorValues = scenario.getFactorValues(); + for (Map.Entry<Factor,Object> entry : factorValues.entrySet()) { + Object value = entry.getValue(); + XmlNode factorValueXmlNode = XmlNode.createElement(scenariosXmlNode, SCENARIO_FACTOR_VALUES, String.valueOf(value)); + factorValueXmlNode.addAttribute(FACTOR, entry.getKey().getId()); + } + + // features + addAllFeature(scenariosXmlNode, scenario.getFeatures()); + } + } +} Added: masc/masc-api/src/main/java/fr/inra/masc/io/writer/MexicoXmlWriter.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/writer/MexicoXmlWriter.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/writer/MexicoXmlWriter.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,48 @@ +package fr.inra.masc.io.writer; + +import fr.ifremer.mexico.model.Feature; +import fr.inra.masc.io.DateFormatFactory; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Date; + +import static fr.inra.masc.io.MexicoXmlConstant.FEATURE; +import static fr.inra.masc.io.MexicoXmlConstant.FEATURE_NAME; +import static fr.inra.masc.io.MexicoXmlConstant.FEATURE_VALUE; +import static fr.inra.masc.io.MexicoXmlConstant.FEATURE_VALUE_TYPE; + +/** + * Abstract writer create mexico files with specific model + * + * @author sletellier <letellier@codelutin.com> + * @since 0.1 + */ +public abstract class MexicoXmlWriter<M> extends XmlWriter<M> { + + protected MexicoXmlWriter(File file, M model) throws IOException { + super(file, model); + } + + public void addParameter(XmlNode xmlNode, String parameterName, Object value) { + if (value != null) { + xmlNode.addAttribute(parameterName, value.toString()); + } + } + + protected void addAllFeature(XmlNode factorXmlNode, Collection<Feature> features) { + if (features != null) { + for (Feature feature : features) { + XmlNode featureXmlNode = XmlNode.createElement(factorXmlNode, FEATURE); + addParameter(featureXmlNode, FEATURE_NAME, feature.getName()); + addParameter(featureXmlNode, FEATURE_VALUE, feature.getValue()); + addParameter(featureXmlNode, FEATURE_VALUE_TYPE, feature.getValueType()); + } + } + } + + public String formatDate(Date toFormat) { + return DateFormatFactory.getMexicoDateFormat().format(toFormat); + } +} Copied: masc/masc-api/src/main/java/fr/inra/masc/io/writer/XmlNode.java (from rev 519, masc/masc-api/src/main/java/fr/inra/masc/io/Element.java) =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/writer/XmlNode.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/writer/XmlNode.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,115 @@ +package fr.inra.masc.io.writer; + +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 XmlNode { + + 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<XmlNode> children; + protected Map<String, String> attributes; + protected String tagName; + protected String text; + + public XmlNode(String tagName) { + this(tagName, null); + } + + public XmlNode(String tagName, String text) { + this.tagName = tagName; + this.text = text; + this.children = Lists.newLinkedList(); + this.attributes = Maps.newHashMap(); + } + + public void add(XmlNode e) { + this.children.add(e); + } + + public void addAttribute(String name, String value) { + this.attributes.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 (XmlNode 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, getAttributesAsString())); + } + + protected String getIndentPrefix(int start, int lenght) { + String result = ""; + for (int i=0;i<start + lenght;i++) { + result += " "; + } + return result; + } + + protected String getAttributesAsString() { + StringBuilder builder = new StringBuilder(); + Set<Map.Entry<String,String>> entries = attributes.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 XmlNode createElement(XmlNode parentXmlNode, String tagName) { + return createElement(parentXmlNode, tagName, null); + } + + public static XmlNode createElement(XmlNode parentXmlNode, String tagName, String text) { + XmlNode xmlNode = createElement(tagName, text); + parentXmlNode.add(xmlNode); + return xmlNode; + } + + public static XmlNode createElement(String tagName, String text) { + return new XmlNode(tagName, text); + } +} Added: masc/masc-api/src/main/java/fr/inra/masc/io/writer/XmlWriter.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/io/writer/XmlWriter.java (rev 0) +++ masc/masc-api/src/main/java/fr/inra/masc/io/writer/XmlWriter.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,32 @@ +package fr.inra.masc.io.writer; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +/** + * Abstract writer to create xml files using {@link XmlNode} + * + * @author sletellier <letellier@codelutin.com> + * @since 0.1 + */ +public abstract class XmlWriter<M> extends FileWriter { + + public static final int INDENT = 2; + + protected M model; + + public XmlWriter(File file, M model) throws IOException { + super(file); + this.model = model; + } + + public void write() throws IOException { + + String toWrite = getRootElement().toXml(INDENT); + super.write(toWrite); + } + + public abstract XmlNode getRootElement(); + +} Deleted: masc/masc-api/src/main/java/fr/inra/masc/model/MascXmlConstant.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/model/MascXmlConstant.java 2011-12-14 15:37:31 UTC (rev 519) +++ masc/masc-api/src/main/java/fr/inra/masc/model/MascXmlConstant.java 2011-12-15 10:31:40 UTC (rev 520) @@ -1,30 +0,0 @@ -package fr.inra.masc.model; - -/** - * Regroup all masc xml constants tags - * - * @author sletellier <letellier@codelutin.com> - * @since 0.1 - */ -public class MascXmlConstant { - - public static final String DEXI = "DEXi"; - public static final String LINE = "line"; - public static final String ATTRIBUTE = "attribute"; - public static final String MODEL_NAME = MascModel.PROPERTY_NAME; - public static final String MODEL_DESCRIPTION = MascModel.PROPERTY_DESCRIPTION; - public static final String OPTION = MascModel.PROPERTY_OPTION; - public static final String SETTINGS = MascModel.PROPERTY_SETTINGS; - public static final String CRITERIA_NAME = Criteria.PROPERTY_NAME; - public static final String CRITERIA_DESCRIPTION = Criteria.PROPERTY_DESCRIPTION; - public static final String SCALE = Criteria.PROPERTY_SCALE; - public static final String SCALE_VALUE = ScaleValue.class.getSimpleName(); - public static final String SCALE_VALUE_NAME = ScaleValue.PROPERTY_NAME; - public static final String SCALE_VALUE_DESCRIPTION = ScaleValue.PROPERTY_DESCRIPTION; - public static final String SCALE_VALUE_GROUP = ScaleValue.PROPERTY_GROUP; - public static final String FUNCTION = ComputableCriteria.PROPERTY_FUNCTION; - public static final String FUNCTION_LOW = Function.PROPERTY_LOW; - public static final String FUNCTION_ENTERED = Function.PROPERTY_ENTERED; - public static final String FUNCTION_WEIGHTS = Function.PROPERTY_WEIGHTS; - public static final String FUNCTION_CONSIST = Function.PROPERTY_CONSIST; -} Modified: masc/masc-api/src/main/java/fr/inra/masc/services/LoadModelService.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/services/LoadModelService.java 2011-12-14 15:37:31 UTC (rev 519) +++ masc/masc-api/src/main/java/fr/inra/masc/services/LoadModelService.java 2011-12-15 10:31:40 UTC (rev 520) @@ -1,60 +1,16 @@ package fr.inra.masc.services; -import com.google.common.collect.Lists; -import com.google.common.collect.Multimap; -import fr.inra.masc.model.ComputableCriteria; -import fr.inra.masc.model.ComputableCriteriaImpl; -import fr.inra.masc.model.Criteria; -import fr.inra.masc.model.Function; -import fr.inra.masc.model.FunctionImpl; +import fr.inra.masc.io.parser.MascModelParser; import fr.inra.masc.model.MascModel; -import fr.inra.masc.model.MascModelImpl; -import fr.inra.masc.model.Option; -import fr.inra.masc.model.OptionImpl; -import fr.inra.masc.model.OptionValue; -import fr.inra.masc.model.OptionValueImpl; -import fr.inra.masc.model.ScaleGroup; -import fr.inra.masc.model.ScaleValue; -import fr.inra.masc.model.ScaleValueImpl; -import fr.inra.masc.model.ThresholdCriteria; -import fr.inra.masc.model.ThresholdCriteriaImpl; -import fr.inra.masc.model.ValuedCriteriaImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlPullParserFactory; import java.io.File; import java.io.FileNotFoundException; -import java.io.FileReader; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.text.ParseException; -import static fr.inra.masc.model.MascXmlConstant.ATTRIBUTE; -import static fr.inra.masc.model.MascXmlConstant.CRITERIA_DESCRIPTION; -import static fr.inra.masc.model.MascXmlConstant.CRITERIA_NAME; -import static fr.inra.masc.model.MascXmlConstant.DEXI; -import static fr.inra.masc.model.MascXmlConstant.FUNCTION; -import static fr.inra.masc.model.MascXmlConstant.FUNCTION_CONSIST; -import static fr.inra.masc.model.MascXmlConstant.FUNCTION_ENTERED; -import static fr.inra.masc.model.MascXmlConstant.FUNCTION_LOW; -import static fr.inra.masc.model.MascXmlConstant.FUNCTION_WEIGHTS; -import static fr.inra.masc.model.MascXmlConstant.LINE; -import static fr.inra.masc.model.MascXmlConstant.MODEL_DESCRIPTION; -import static fr.inra.masc.model.MascXmlConstant.MODEL_NAME; -import static fr.inra.masc.model.MascXmlConstant.OPTION; -import static fr.inra.masc.model.MascXmlConstant.SCALE; -import static fr.inra.masc.model.MascXmlConstant.SCALE_VALUE_DESCRIPTION; -import static fr.inra.masc.model.MascXmlConstant.SCALE_VALUE_GROUP; -import static fr.inra.masc.model.MascXmlConstant.SCALE_VALUE_NAME; -import static fr.inra.masc.model.MascXmlConstant.SETTINGS; - /** * Service use to parse mascXmlFile and build MascModel corresponding * @@ -75,12 +31,14 @@ MascModel mascModel = null; try { - XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); - XmlPullParser parser = factory.newPullParser(); - parser.setInput(new FileReader(mascFile)); + MascModelParser mascModelParser = new MascModelParser(mascFile, getConfig().getThresholds()); - // parse model parameters - mascModel = parseMascModel(parser); + try { + // parse model + mascModel = mascModelParser.getModel(); + } finally { + mascModelParser.close(); + } } catch (XmlPullParserException eee) { throwMascTechnicalException("Failed to parse masc file '" + mascFile.getName() + "'", eee); @@ -88,314 +46,11 @@ throwMascTechnicalException("Masc file '" + mascFile.getName() + "' not found", eee); } catch (IOException eee) { throwMascTechnicalException("Error reading masc file '" + mascFile.getName() + "'", eee); + } catch (ParseException eee) { + throwMascTechnicalException("Failed to parse masc file '" + mascFile.getName() + "'", eee); } return mascModel; } - protected MascModel parseMascModel(XmlPullParser parser) throws IOException, XmlPullParserException { - - MascModel model = new MascModelImpl(); - - parseMeta(model, parser); - parseAttributes(model, parser); - - return model; - } - - protected void parseMeta(MascModel model, XmlPullParser parser) throws IOException, XmlPullParserException { - - // file must start with DEXi balise - if (parser.next() == XmlPullParser.START_TAG && - !parserEqual(parser, DEXI)) { - throwMascTechnicalException("Masc file must start with " + DEXI + " tag"); - } - - // start parsing model parameters - // parse name - int eventType = parser.nextTag(); - if (eventType == XmlPullParser.START_TAG && - parserEqual(parser, MODEL_NAME)) { - model.setName(parser.nextText()); - - // read next tag - eventType = parser.nextTag(); - } - - // parse description - if (eventType == XmlPullParser.START_TAG && - parserEqual(parser, MODEL_DESCRIPTION)) { - - List<String> descriptions = Lists.newArrayList(); - while (!(parser.nextTag() == XmlPullParser.END_TAG && - parserEqual(parser, MODEL_DESCRIPTION))) { - - if (parserEqual(parser, LINE)) { - descriptions.add(parser.nextText()); - } - } - - model.setDescription(descriptions); - - // read next tag - eventType = parser.nextTag(); - } - - // parse options - List<Option> options = Lists.newLinkedList(); - while (eventType == XmlPullParser.START_TAG && - parserEqual(parser, OPTION)) { - - Option option = new OptionImpl(); - option.setName(parser.nextText()); - options.add(option); - - // read end option tag - eventType = parser.nextTag(); - } - model.setOption(options); - - // parse settings - if (eventType == XmlPullParser.START_TAG && - parserEqual(parser, SETTINGS)) { - - Map<String, String> settings = new LinkedHashMap<String, String>(); - while (!(parser.nextTag() == XmlPullParser.END_TAG && - parserEqual(parser, SETTINGS))) { - settings.put(parser.getName(), parser.nextText()); - } - model.setSettings(settings); - - // read next tag - parser.nextTag(); - } - } - - protected void parseAttributes(MascModel model, XmlPullParser parser) throws IOException, XmlPullParserException { - List<Criteria> criterias = Lists.newArrayList(); - while (parser.getEventType() == XmlPullParser.START_TAG && - parserEqual(parser, ATTRIBUTE)) { - - Criteria criteria = parseAttribute(model, parser); - criterias.add(criteria); - - // Read closeTag - parser.nextTag(); - } - model.setCriteria(criterias); - } - - protected Criteria parseAttribute(MascModel model, XmlPullParser parser) throws IOException, XmlPullParserException { - - // parse name - int eventType = parser.nextTag(); - if (eventType == XmlPullParser.START_TAG && - !parserEqual(parser, CRITERIA_NAME)) { - - log.info(parser.getName()); - throwMascTechnicalException("All criteria must have a name"); - } - String name = parser.nextText(); - - // read next tag - eventType = parser.nextTag(); - - // parse description - String description = null; - if (eventType == XmlPullParser.START_TAG && - parserEqual(parser, CRITERIA_DESCRIPTION)) { - - description = parser.nextText(); - - // read next tag - eventType = parser.nextTag(); - } - - // parse scales - if (eventType == XmlPullParser.START_TAG && - !parserEqual(parser, SCALE)) { - - throwMascTechnicalException("All criteria must have a scalesValue"); - } - List<ScaleValue> scaleValues = parseScale(parser); - - // parse function - Function function = null; - if (parser.getEventType() == XmlPullParser.START_TAG && - parserEqual(parser, FUNCTION)) { - - function = parseFunction(parser); - } - - // parse option value - int optionValueCnt = 0; - List<OptionValue> optionValues = Lists.newLinkedList(); - while (eventType == XmlPullParser.START_TAG && - parserEqual(parser, OPTION)) { - - OptionValue optionValue = new OptionValueImpl(); - optionValue.setValue(Integer.parseInt(parser.nextText())); - Option option = model.getOption(optionValueCnt++); - - // initialize option value list - if (option.getOptionValue() == null) { - LinkedList<OptionValue> optionValuesList = Lists.newLinkedList(); - option.setOptionValue(optionValuesList); - } - option.addOptionValue(optionValue); - optionValues.add(optionValue); - - // read next tag - eventType = parser.nextTag(); - } - - // parse attributes - List<Criteria> criterias = new ArrayList<Criteria>(); - if (parser.getEventType() == XmlPullParser.START_TAG && - parserEqual(parser, ATTRIBUTE)) { - - while (!(parser.getEventType() == XmlPullParser.END_TAG && - parserEqual(parser, ATTRIBUTE))) { - - criterias.add(parseAttribute(model, parser)); - parser.nextTag(); - } - } - - Criteria current; - if (function != null) { - - // non editable criteria - ComputableCriteria computableCriteria = new ComputableCriteriaImpl(); - computableCriteria.setFunction(function); - current = computableCriteria; - } else { - - // editable criteria - // check on properties if its a threshold criteria - Multimap<String,Integer> thresholds = getConfig().getThresholds(); - if (thresholds.containsKey(name)) { - ThresholdCriteria thresholdCriteria = new ThresholdCriteriaImpl(); - Collection<Integer> values = thresholds.get(name); - thresholdCriteria.setValues(values); - current = thresholdCriteria; - } else { - // else is a valued one - current = new ValuedCriteriaImpl(); - } - } - - // fill options values - for (OptionValue optionValue : optionValues) { - optionValue.setCriteria(current); - } - - // fill criteria - current.setName(name); - current.setDescription(description); - current.setScale(scaleValues); - current.setChildren(criterias); - - return current; - } - - protected List<ScaleValue> parseScale(XmlPullParser parser) throws IOException, XmlPullParserException { - - List<ScaleValue> scaleValues = new ArrayList<ScaleValue>(); - while (!(parser.nextTag() == XmlPullParser.END_TAG && - parserEqual(parser, SCALE))) { - - // parse name - int eventType = parser.nextTag(); - if (eventType == XmlPullParser.START_TAG && - !parserEqual(parser, SCALE_VALUE_NAME)) { - - throwMascTechnicalException("All scale value must have a name"); - } - ScaleValue scaleValue = new ScaleValueImpl(); - scaleValue.setName(parser.nextText()); - eventType = parser.nextTag(); - - // parse description - if (eventType == XmlPullParser.START_TAG && - parserEqual(parser, SCALE_VALUE_DESCRIPTION)) { - - scaleValue.setDescription(parser.nextText()); - - // read next tag - eventType = parser.nextTag(); - } - - // parse group - if (eventType == XmlPullParser.START_TAG && - parserEqual(parser, SCALE_VALUE_GROUP)) { - - String groupValue = parser.nextText(); - scaleValue.setGroup(ScaleGroup.valueOf(groupValue)); - - // read next tag - parser.nextTag(); - } - scaleValues.add(scaleValue); - } - // read scale close tag - parser.nextTag(); - - return scaleValues; - } - - protected Function parseFunction(XmlPullParser parser) throws IOException, XmlPullParserException { - Function function = new FunctionImpl(); - - // parse low - int eventType = parser.nextTag(); - if (eventType == XmlPullParser.START_TAG && - parserEqual(parser, FUNCTION_LOW)) { - - function.setLow(parser.nextText()); - - // read next tag - eventType = parser.nextTag(); - } - - // parse entered - if (eventType == XmlPullParser.START_TAG && - parserEqual(parser, FUNCTION_ENTERED)) { - - function.setEntered(parser.nextText()); - - // read next tag - eventType = parser.nextTag(); - } - - // parse weights - if (eventType == XmlPullParser.START_TAG && - parserEqual(parser, FUNCTION_WEIGHTS)) { - - function.setWeights(parser.nextText()); - - // read next tag - eventType = parser.nextTag(); - } - - // parse consist - if (eventType == XmlPullParser.START_TAG && - parserEqual(parser, FUNCTION_CONSIST)) { - - function.setConsist(Boolean.parseBoolean(parser.nextText())); - - // read next tag - parser.nextTag(); - } - - // read function close tag - parser.nextTag(); - - return function; - } - - protected boolean parserEqual(XmlPullParser parser, String name) { - String tagName = parser.getName(); - return tagName.equalsIgnoreCase(name); - } } Modified: masc/masc-api/src/main/java/fr/inra/masc/services/MexicoLoadModelService.java =================================================================== --- masc/masc-api/src/main/java/fr/inra/masc/services/MexicoLoadModelService.java 2011-12-14 15:37:31 UTC (rev 519) +++ masc/masc-api/src/main/java/fr/inra/masc/services/MexicoLoadModelService.java 2011-12-15 10:31:40 UTC (rev 520) @@ -1,10 +1,17 @@ package fr.inra.masc.services; import fr.ifremer.mexico.model.ExperienceDesign; +import fr.ifremer.mexico.model.InputDesign; +import fr.inra.masc.io.parser.ExperienceDesignParser; +import fr.inra.masc.io.parser.InputDesignParser; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.xmlpull.v1.XmlPullParserException; import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.text.ParseException; /** * @author sletellier <letellier@codelutin.com> @@ -19,15 +26,54 @@ return log; } - public File loadExperienceDesign(ExperienceDesign mexicoModel, File toSave) { + public ExperienceDesign loadExperienceDesignModel(File experienceDesignFile) { - // TODO sletellier : load mexico experience design xml file - return toSave; + ExperienceDesign experienceDesignModel = null; + try { + ExperienceDesignParser experienceDesignParser = new ExperienceDesignParser(experienceDesignFile); + try { + // parse experienceDesign + experienceDesignModel = experienceDesignParser.getModel(); + } finally { + experienceDesignParser.close(); + } + + } catch (XmlPullParserException eee) { + throwMascTechnicalException("Failed to parse ExperienceDesign file '" + experienceDesignFile.getName() + "'", eee); + } catch (FileNotFoundException eee) { + throwMascTechnicalException("ExperienceDesign file '" + experienceDesignFile.getName() + "' not found", eee); + } catch (IOException eee) { + throwMascTechnicalException("Error reading ExperienceDesign file '" + experienceDesignFile.getName() + "'", eee); + } catch (ParseException eee) { + throwMascTechnicalException("Failed to parse ExperienceDesign file '" + experienceDesignFile.getName() + "'", eee); + } + + return experienceDesignModel; } - public File loadInputDesignDesign(ExperienceDesign mexicoModel, File toSave) { + public InputDesign loadInputDesignDesignModel(File inputDesignFile) { - // TODO sletellier : write mexico input design xml file - return toSave; + InputDesign inputDesignModel = null; + try { + // parse inputDesign + InputDesignParser inputDesignParser = new InputDesignParser(inputDesignFile); + try { + inputDesignModel = inputDesignParser.getModel(); + } finally { + inputDesignParser.close(); + } + + } catch (XmlPullParserException eee) { + throwMascTechnicalException("Failed to parse InputDesign file '" + inputDesignFile.getName() + "'", eee); + } catch (FileNotFoundException eee) { + throwMascTechnicalException("InputDesign file '" + inputDesignFile.getName() + "' not found", eee); + } catch (IOException eee) { + throwMascTechnicalException("Error reading InputDesign file '" + inputDesignFile.getName() + "'", eee); + } catch (ParseException eee) { + throwMascTechnicalException("Failed to parse InputDesign file '" + inputDesignFile.getName() + "'", eee); + } + + return inputDesignModel; } + } 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 15:37:31 UTC (rev 519) +++ masc/masc-api/src/main/java/fr/inra/masc/services/MexicoSaveModelService.java 2011-12-15 10:31:40 UTC (rev 520) @@ -1,23 +1,14 @@ 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 fr.inra.masc.io.writer.ExperienceDesignXmlWriter; +import fr.inra.masc.io.writer.InputDesignXmlWriter; 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 @@ -37,204 +28,30 @@ public void saveExperienceDesign(ExperienceDesign experienceDesign, File 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); - } + ExperienceDesignXmlWriter writer = new ExperienceDesignXmlWriter(toSave, experienceDesign); + try { + writer.write(); + } finally { + writer.close(); } + } catch (IOException eee) { + throwMascTechnicalException("Failed to write experiment design xml file", eee); } } public void saveInputDesign(InputDesign inputDesign, File 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); - } + InputDesignXmlWriter writer = new InputDesignXmlWriter(toSave, inputDesign); + try { + writer.write(); + } finally { + writer.close(); } + } catch (IOException eee) { + throwMascTechnicalException("Failed to write input 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 15:37:31 UTC (rev 519) +++ masc/masc-api/src/main/java/fr/inra/masc/services/SaveModelService.java 2011-12-15 10:31:40 UTC (rev 520) @@ -1,47 +1,13 @@ package fr.inra.masc.services; -import com.google.common.collect.LinkedListMultimap; -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; +import fr.inra.masc.io.writer.DexiXmlWriter; import fr.inra.masc.model.MascModel; -import fr.inra.masc.model.Option; -import fr.inra.masc.model.OptionValue; -import fr.inra.masc.model.ScaleValue; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections.MapUtils; -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.util.Collection; -import java.util.Map; -import static fr.inra.masc.model.MascXmlConstant.ATTRIBUTE; -import static fr.inra.masc.model.MascXmlConstant.CRITERIA_DESCRIPTION; -import static fr.inra.masc.model.MascXmlConstant.CRITERIA_NAME; -import static fr.inra.masc.model.MascXmlConstant.DEXI; -import static fr.inra.masc.model.MascXmlConstant.FUNCTION; -import static fr.inra.masc.model.MascXmlConstant.FUNCTION_CONSIST; -import static fr.inra.masc.model.MascXmlConstant.FUNCTION_ENTERED; -import static fr.inra.masc.model.MascXmlConstant.FUNCTION_LOW; -import static fr.inra.masc.model.MascXmlConstant.FUNCTION_WEIGHTS; -import static fr.inra.masc.model.MascXmlConstant.LINE; -import static fr.inra.masc.model.MascXmlConstant.MODEL_DESCRIPTION; -import static fr.inra.masc.model.MascXmlConstant.MODEL_NAME; -import static fr.inra.masc.model.MascXmlConstant.OPTION; -import static fr.inra.masc.model.MascXmlConstant.SCALE; -import static fr.inra.masc.model.MascXmlConstant.SCALE_VALUE; -import static fr.inra.masc.model.MascXmlConstant.SCALE_VALUE_DESCRIPTION; -import static fr.inra.masc.model.MascXmlConstant.SCALE_VALUE_GROUP; -import static fr.inra.masc.model.MascXmlConstant.SCALE_VALUE_NAME; -import static fr.inra.masc.model.MascXmlConstant.SETTINGS; - /** * Service to save masc model to DEXi xml file * @@ -60,153 +26,16 @@ public void saveModel(MascModel model, File saveFile) { - DexiXmlWriter dexiXmlWriter = new DexiXmlWriter(model); - String xml = dexiXmlWriter.composeXml(2); - - FileWriter writer = null; try { - writer = new FileWriter(saveFile); - writer.write(xml); + DexiXmlWriter writer = new DexiXmlWriter(saveFile, model); + try { + writer.write(); + } finally { + writer.close(); + } } catch (IOException eee) { throwMascTechnicalException("Failed to write DEXi xml file", eee); - } finally { - if (writer != null) { - try { - writer.close(); - } catch (IOException eee) { - throwMascTechnicalException("Failed to close DEXi xml file", eee); - } - } } } - protected class DexiXmlWriter { - - protected MascModel model; - protected Multimap<Criteria, OptionValue> criteriaOptionValues; - - public DexiXmlWriter(MascModel model) { - this.model = model; - this.criteriaOptionValues = LinkedListMultimap.create(); - } - - public String composeXml(int indent) { - Element rootElement = new Element(DEXI); - composeMeta(rootElement); - composeAttributes(rootElement); - - return rootElement.toXml(indent); - } - - - protected void composeMeta(Element rootElement) { - - // model name - add(rootElement, MODEL_NAME, model.getName()); - - // model description - Element descriptionElement = createElement(rootElement, MODEL_DESCRIPTION); - for (String line : model.getDescription()) { - add(descriptionElement, LINE, line); - } - - // options - for (Option option : model.getOption()) { - add(rootElement, OPTION, option.getName()); - - // load all option values - for (OptionValue optionValue : option.getOptionValue()) { - - // fill map - Criteria criteria = optionValue.getCriteria(); - criteriaOptionValues.put(criteria, optionValue); - } - } - - // settings - Map<String,String> settings = model.getSettings(); - if (MapUtils.isNotEmpty(settings)) { - Element settingElement = createElement(rootElement, SETTINGS); - for (String settingName : settings.keySet()) { - String settingsValue = settings.get(settingName); - add(settingElement, settingName, settingsValue); - } - } - } - - protected void composeAttributes(Element rootElement) { - Collection<Criteria> criterias = model.getCriteria(); - if (CollectionUtils.isNotEmpty(criterias)) { - for (Criteria criteria : criterias) { - composeAttribute(criteria, rootElement); - } - } - } - - protected void composeAttribute(Criteria criteria, Element rootElement) { - Element attributeElement = createElement(rootElement, ATTRIBUTE); - - // attribute name - add(attributeElement, CRITERIA_NAME, criteria.getName()); - - // attribute description - add(attributeElement, CRITERIA_DESCRIPTION, criteria.getDescription()); - - // scale - Element scaleElement = createElement(attributeElement, SCALE); - - // scale values - for (ScaleValue scaleValue : criteria.getScale()) { - Element scaleValueElement = createElement(scaleElement, SCALE_VALUE); - add(scaleValueElement, SCALE_VALUE_NAME, scaleValue.getName()); - add(scaleValueElement, SCALE_VALUE_DESCRIPTION, scaleValue.getDescription()); - add(scaleValueElement, SCALE_VALUE_GROUP, scaleValue.getGroup()); - } - - // function - if (criteria instanceof ComputableCriteria) { - ComputableCriteria computableCriteria = (ComputableCriteria) criteria; - Element functionElement = createElement(attributeElement, FUNCTION); - Function function = computableCriteria.getFunction(); - add(functionElement, FUNCTION_LOW, function.getLow()); - add(functionElement, FUNCTION_ENTERED, function.getEntered()); - add(functionElement, FUNCTION_WEIGHTS, function.getWeights()); - add(functionElement, FUNCTION_CONSIST, function.getConsist()); - } - - // options - Collection<OptionValue> optionValues = criteriaOptionValues.get(criteria); - for (OptionValue optionValue : optionValues) { - add(attributeElement, OPTION, optionValue.getValue()); - } - - // children - for (Criteria child : criteria.getChildren()) { - composeAttribute(child, attributeElement); - } - } - - protected void add(Element parentElement, String tagName, Object value) { - if (value != null) { - String toString = value.toString(); - - // boolean are capitalized in masc xml file - if (value instanceof Boolean) { - toString = StringUtils.capitalize(toString); - } - createElement(parentElement, tagName, toString); - } - } - - // Override to upper case tagNames - public Element createElement(Element parentElement, String tagName) { - return createElement(parentElement, tagName, null); - } - - public Element createElement(Element parentElement, String tagName, String text) { - Element element = Element.createElement(tagName.toUpperCase(), text); - parentElement.add(element); - return element; - } - } } Added: masc/masc-api/src/test/java/fr/inra/masc/services/MexicoLoadModelServiceTest.java =================================================================== --- masc/masc-api/src/test/java/fr/inra/masc/services/MexicoLoadModelServiceTest.java (rev 0) +++ masc/masc-api/src/test/java/fr/inra/masc/services/MexicoLoadModelServiceTest.java 2011-12-15 10:31:40 UTC (rev 520) @@ -0,0 +1,51 @@ +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 MexicoLoadModelServiceTest extends AbstractServiceTest { + + @Test + public void testLoadExperienceDesignModel() 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); + + ExperienceDesign loadedExperienceDesign = getService(MexicoLoadModelService.class).loadExperienceDesignModel(savedFile); + assertExperimentDesignEqual(experienceDesign, loadedExperienceDesign); + } + + @Test + public void testLoadInputDesignDesignModel() 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); + + InputDesign loadedInputDesign = getService(MexicoLoadModelService.class).loadInputDesignDesignModel(savedFile); + + assertExperimentDesignEqual(inputDesign.getExperienceDesign(), loadedInputDesign.getExperienceDesign()); + assertEquals(inputDesign.getScenarios().size(), loadedInputDesign.getScenarios().size()); + } + + protected void assertExperimentDesignEqual(ExperienceDesign expectedExperienceDesign, ExperienceDesign experienceDesign) { + assertEquals(expectedExperienceDesign.getId(), experienceDesign.getId()); + assertEquals(expectedExperienceDesign.getFactors().size(), experienceDesign.getFactors().size()); + } +} Modified: masc/masc-api/src/test/java/fr/inra/masc/services/MexicoSaveModelServiceTest.java =================================================================== --- masc/masc-api/src/test/java/fr/inra/masc/services/MexicoSaveModelServiceTest.java 2011-12-14 15:37:31 UTC (rev 519) +++ masc/masc-api/src/test/java/fr/inra/masc/services/MexicoSaveModelServiceTest.java 2011-12-15 10:31:40 UTC (rev 520) @@ -20,7 +20,7 @@ MascModel mascModel = getService(LoadModelService.class).loadModel(dexiTestFile); ExperienceDesign experienceDesign = mexicoModelConvertorService.convertMascModelToMexicoExperienceDesignModel(mascModel); - File savedFile = new File(testWorkDir, "ExperienceDesignTestFileResult.xml"); + File savedFile = new File(testWorkDir, "experienceDesignTestFileResult.xml"); getService(MexicoSaveModelService.class).saveExperienceDesign(experienceDesign, savedFile); }