/** * SPINdle (version 2.2.2) * Copyright (C) 2009-2012 NICTA Ltd. * * This file is part of SPINdle project. * * SPINdle is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SPINdle is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SPINdle. If not, see <http://www.gnu.org/licenses/>. * * @author H.-P. Lam (oleklam@gmail.com), National ICT Australia - Queensland Research Laboratory */ package spindle.io.outputter; import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.xml.bind.Marshaller; import spindle.core.dom.DomConst; import spindle.io.OutputterException; import spindle.io.xjc.XjcUtilities; import spindle.io.xjc.dom2.Conclusions; import spindle.io.xjc.dom2.CtConclusion; import spindle.io.xjc.dom2.CtInterval; import spindle.io.xjc.dom2.CtLiteral; import spindle.io.xjc.dom2.CtLiteralBooleanFunctionPair; import spindle.io.xjc.dom2.CtLiteralVariable; import spindle.io.xjc.dom2.CtLiteralVariablePair; import spindle.io.xjc.dom2.CtModeConflictRule; import spindle.io.xjc.dom2.CtModeConversionRule; import spindle.io.xjc.dom2.CtModeExclusionRule; import spindle.io.xjc.dom2.CtPredicates; import spindle.io.xjc.dom2.CtRule; import spindle.io.xjc.dom2.CtRuleBodyLiterals; import spindle.io.xjc.dom2.CtRuleHeadLiterals; import spindle.io.xjc.dom2.CtSuperiority; import spindle.io.xjc.dom2.ObjectFactory; import spindle.io.xjc.dom2.Rules; import spindle.io.xjc.dom2.Theory; /** * Defeasible theory and conclusions outputter in XML. * It is implemented based on the classes generated by <a href="https://jaxb.java.net/">JAXB</a> with the specified XML * schema. * It is going to be used to replace the old XML theory and conclusions outputter class ( * {@link spindle.io.outputter.XmlTheoryOutputter}). * * @author H.-P. Lam (oleklam@gmail.com), National ICT Australia - Queensland Research Laboratory * @version Last modified 2012.05.28 * @since version 2.2.2 * @see spindle.io.xjc.dom2 * @see spindle.io.outputter.XmlTheoryOutputter */ public class XmlTheoryOutputter2 extends AbstractTheoryOutputter { public static final String OUTPUTTER_TYPE = "xml"; private static final String LITERAL_PREDICATE_DEFAULT_VALUE = DomConst.Literal.DEFAULT_PREDICATE_VALUE; private static ObjectFactory objectFactory = null; private static XmlTheoryOutputter2 INSTANCE = null; private static Marshaller ruleMarshaller = null; private Marshaller theoryMarshaller = null; private Marshaller conclusionsMarshaller = null; public static String getTheoryAsXmlString(spindle.core.dom.Theory theory) throws OutputterException { ByteArrayOutputStream writer = new ByteArrayOutputStream(); XmlTheoryOutputter2 outputter = new XmlTheoryOutputter2(); outputter.save(writer, theory); return writer.toString(); } public static String getConclusionsAsXmlString(List<spindle.core.dom.Conclusion> conclusionsAsList) throws OutputterException { ByteArrayOutputStream writer = new ByteArrayOutputStream(); XmlTheoryOutputter2 outputter = new XmlTheoryOutputter2(); outputter.save(writer, conclusionsAsList); return writer.toString(); } public static String getRuleAsXmlString(spindle.core.dom.Rule rule) throws OutputterException { try { if (null == INSTANCE) INSTANCE = new XmlTheoryOutputter2(); if (null == ruleMarshaller) ruleMarshaller = XjcUtilities.getRuleMarshaller(); CtRule cRule = INSTANCE.generateRule(rule); Rules cRules = objectFactory.createRules(); cRules.setRule(cRule); ByteArrayOutputStream writer = new ByteArrayOutputStream(); ruleMarshaller.marshal(cRules, writer); String ruleStrDummy = writer.toString(); int sloc = ruleStrDummy.indexOf("<rule "); int eloc = ruleStrDummy.indexOf("</rules>"); String ruleStr = ruleStrDummy.substring(sloc, eloc); return ruleStr.replaceAll("\n ", "\n").trim(); } catch (Exception e) { throw new OutputterException(e); } } public XmlTheoryOutputter2() { super(OUTPUTTER_TYPE); if (null == objectFactory) objectFactory = XjcUtilities.getObjectFactory(); } @Override protected void saveToStream(OutputStream os, spindle.core.dom.Theory theory) throws OutputterException { try { if (null == theoryMarshaller) theoryMarshaller = XjcUtilities.getTheoryMarshaller(); Theory cTheory = objectFactory.createTheory(); if (!"".equals(theory.getDescription())) cTheory.setDescription(theory.getDescription()); List<Object> factsOrRules = generateFactOrRule(theory.getFactsAndAllRules()); if (null != factsOrRules) cTheory.getFactOrRule().addAll(factsOrRules); List<CtSuperiority> superiorities = generateSuperiority(theory.getAllSuperiority()); if (null != superiorities) cTheory.getSuperiority().addAll(superiorities); List<CtModeConversionRule> modeConversionRules = generateModeConversionRules(theory.getAllModeConversionRules()); if (null != modeConversionRules) cTheory.getConvert().addAll(modeConversionRules); List<CtModeConflictRule> modeConflictRules = generateModeConflictRules(theory.getAllModeConflictRules()); if (null != modeConflictRules) cTheory.getConflict().addAll(modeConflictRules); List<CtModeExclusionRule> modeExclusionRules = generateModeExclusionRules(theory.getAllModeExclusionRules()); if (null != modeExclusionRules) cTheory.getExclude().addAll(modeExclusionRules); List<CtLiteralVariablePair> literalVariables = generateLiteralVariables(theory.getLiteralVariables()); if (null != literalVariables) cTheory.getLiteralVariable().addAll(literalVariables); List<CtLiteralBooleanFunctionPair> literalBooleanFunctions = generateLiteralBooleanFunctions(theory .getLiteralBooleanFunctions()); if (null != literalBooleanFunctions) cTheory.getLiteralBooleanFunction().addAll(literalBooleanFunctions); theoryMarshaller.marshal(cTheory, os); } catch (Exception e) { throw new OutputterException(e); } } @Override protected void saveToStream(OutputStream os, List<spindle.core.dom.Conclusion> conclusionsAsList) throws OutputterException { try { if (null == conclusionsMarshaller) conclusionsMarshaller = XjcUtilities.getConclusionsMarshaller(); Conclusions cConclusions = objectFactory.createConclusions(); List<CtConclusion> conclusionsList = cConclusions.getConclusion(); for (spindle.core.dom.Conclusion conclusion : conclusionsAsList) { CtConclusion cConclusion = objectFactory.createCtConclusion(); cConclusion.setTag(conclusion.getConclusionType().getTextTag()); cConclusion.setLiteral(generateLiteral(conclusion.getLiteral())); conclusionsList.add(cConclusion); } conclusionsMarshaller.marshal(cConclusions, os); } catch (Exception e) { throw new OutputterException(e); } } private List<CtLiteralVariablePair> generateLiteralVariables( Map<spindle.core.dom.LiteralVariable, spindle.core.dom.LiteralVariable> literalVariables) { if (null == literalVariables || literalVariables.size() == 0) return null; List<CtLiteralVariablePair> cLiteralVariablePairs = new ArrayList<CtLiteralVariablePair>(); for (Entry<spindle.core.dom.LiteralVariable, spindle.core.dom.LiteralVariable> entry : literalVariables.entrySet()) { CtLiteralVariable name = generateLiteralVariable(entry.getKey()); CtLiteralVariable value = generateLiteralVariable(entry.getValue()); CtLiteralVariablePair cLiteralVariablePair = objectFactory.createCtLiteralVariablePair(); cLiteralVariablePair.setName(name); cLiteralVariablePair.setValue(value); cLiteralVariablePairs.add(cLiteralVariablePair); } return cLiteralVariablePairs.size() == 0 ? null : cLiteralVariablePairs; } private List<CtLiteralBooleanFunctionPair> generateLiteralBooleanFunctions( Map<spindle.core.dom.LiteralVariable, spindle.core.dom.LiteralVariable> literalBooleanFunctions) { if (null == literalBooleanFunctions || literalBooleanFunctions.size() == 0) return null; List<CtLiteralBooleanFunctionPair> cLiteralFunctionPairs = new ArrayList<CtLiteralBooleanFunctionPair>(); for (Entry<spindle.core.dom.LiteralVariable, spindle.core.dom.LiteralVariable> entry : literalBooleanFunctions.entrySet()) { CtLiteralVariable name = generateLiteralVariable(entry.getKey()); String value = entry.getValue().getName(); CtLiteralBooleanFunctionPair cLiteralFunctionPair = objectFactory.createCtLiteralBooleanFunctionPair(); cLiteralFunctionPair.setName(name); cLiteralFunctionPair.setValue(value); cLiteralFunctionPairs.add(cLiteralFunctionPair); } return cLiteralFunctionPairs.size() == 0 ? null : cLiteralFunctionPairs; } private CtLiteralVariable generateLiteralVariable(spindle.core.dom.LiteralVariable literalVariable) { CtLiteralVariable clv = objectFactory.createCtLiteralVariable(); clv.setAtom(literalVariable.getName()); CtPredicates cPredicates = generatePredicates(literalVariable.getPredicates()); if (null != cPredicates) clv.setPredicates(cPredicates); return clv; } private List<CtModeConversionRule> generateModeConversionRules(Map<String, Set<String>> conversionRules) { if (null == conversionRules || conversionRules.size() == 0) return null; List<CtModeConversionRule> modeRules = new ArrayList<CtModeConversionRule>(); for (Entry<String, Set<String>> entry : conversionRules.entrySet()) { CtModeConversionRule cConversionRule = objectFactory.createCtModeConversionRule(); cConversionRule.setFrom(entry.getKey()); cConversionRule.getTo().addAll(entry.getValue()); modeRules.add(cConversionRule); } return modeRules.size() == 0 ? null : modeRules; } private List<CtModeConflictRule> generateModeConflictRules(Map<String, Set<String>> conflictRules) { if (null == conflictRules || conflictRules.size() == 0) return null; List<CtModeConflictRule> modeRules = new ArrayList<CtModeConflictRule>(); for (Entry<String, Set<String>> entry : conflictRules.entrySet()) { CtModeConflictRule cConflictRule = objectFactory.createCtModeConflictRule(); cConflictRule.setMode(entry.getKey()); cConflictRule.getConflictWIth().addAll(entry.getValue()); modeRules.add(cConflictRule); } return modeRules.size() == 0 ? null : modeRules; } private List<CtModeExclusionRule> generateModeExclusionRules(Map<String, Set<String>> exclusionRules) { if (null == exclusionRules || exclusionRules.size() == 0) return null; List<CtModeExclusionRule> modeRules = new ArrayList<CtModeExclusionRule>(); for (Entry<String, Set<String>> entry : exclusionRules.entrySet()) { CtModeExclusionRule cExcludeRules = objectFactory.createCtModeExclusionRule(); cExcludeRules.setMode(entry.getKey()); cExcludeRules.getExcludeWith().addAll(entry.getValue()); modeRules.add(cExcludeRules); } return modeRules.size() == 0 ? null : modeRules; } private List<CtSuperiority> generateSuperiority(List<spindle.core.dom.Superiority> superiorities) { if (superiorities.size() == 0) return null; List<CtSuperiority> cSuperiorities = new ArrayList<CtSuperiority>(); for (spindle.core.dom.Superiority superiority : superiorities) { CtSuperiority cSuperiority = objectFactory.createCtSuperiority(); cSuperiority.setSuperior(superiority.getSuperior()); cSuperiority.setInferior(superiority.getInferior()); cSuperiorities.add(cSuperiority); } return cSuperiorities.size() == 0 ? null : cSuperiorities; } private List<Object> generateFactOrRule(Map<String, spindle.core.dom.Rule> factsOrRules) { List<Object> factOrRule = new ArrayList<Object>(); Object obj = null; for (spindle.core.dom.Rule rule : factsOrRules.values()) { switch (rule.getRuleType()) { case FACT: spindle.core.dom.Literal headLiteral = rule.getHeadLiterals().get(0); obj = generateLiteral(headLiteral); break; case STRICT: case DEFEASIBLE: case DEFEATER: obj = generateRule(rule); break; default: } if (null != obj) factOrRule.add(obj); } return factOrRule.size() == 0 ? null : factOrRule; } private CtRule generateRule(spindle.core.dom.Rule rule) { CtRule cRule = objectFactory.createCtRule(); switch (rule.getRuleType()) { case STRICT: cRule.setRuletype("STRICT"); break; case DEFEASIBLE: cRule.setRuletype("DEFEASIBLE"); break; case DEFEATER: cRule.setRuletype("DEFEATER"); break; default: } String ruleLabel = rule.getLabel(); if (!(null == ruleLabel || "".equals(ruleLabel))) { if (!ruleLabel.startsWith(spindle.core.dom.Theory.DEFAULT_RULE_LABEL_PREFIX)) cRule.setLabel(ruleLabel); } spindle.core.dom.Mode mode = rule.getMode(); if (null != mode && !"".equals(mode.getName())) cRule.setMode(mode.getName()); List<CtLiteral> cHeadLiterals = generateLiterals(rule.getHeadLiterals()); if (null != cHeadLiterals) { CtRuleHeadLiterals cHead = objectFactory.createCtRuleHeadLiterals(); cHead.getLiteral().addAll(cHeadLiterals); cRule.setHead(cHead); } List<CtLiteral> cBodyLiterals = generateLiterals(rule.getBodyLiterals()); if (null != cBodyLiterals) { CtRuleBodyLiterals cBody = objectFactory.createCtRuleBodyLiterals(); if (cBodyLiterals.size() == 1) { cBody.setLiteral(cBodyLiterals.get(0)); } else { CtRuleBodyLiterals.And bodyAnd = objectFactory.createCtRuleBodyLiteralsAnd(); bodyAnd.getLiteral().addAll(cBodyLiterals); cBody.setAnd(bodyAnd); } cRule.setBody(cBody); } return cRule; } private List<CtLiteral> generateLiterals(List<spindle.core.dom.Literal> literals) { if (null == literals || literals.size() == 0) return null; List<CtLiteral> cLiterals = new ArrayList<CtLiteral>(); for (spindle.core.dom.Literal literal : literals) { cLiterals.add(generateLiteral(literal)); } return cLiterals; } private CtLiteral generateLiteral(spindle.core.dom.Literal literal) { CtLiteral cLiteral = objectFactory.createCtLiteral(); if (literal.isNegation()) { CtLiteral.Not cNegLiteral = objectFactory.createCtLiteralNot(); cNegLiteral.setAtom(literal.getName()); cLiteral.getNot().add(cNegLiteral); } else { cLiteral.setAtom(literal.getName()); } spindle.core.dom.Mode mode = literal.getMode(); if (null != mode && !"".equals(mode.getName())) { if (mode.isNegation()) { CtLiteral.Not cNegMode = objectFactory.createCtLiteralNot(); cNegMode.setMode(mode.getName()); cLiteral.getNot().add(cNegMode); } else { cLiteral.setMode(mode.getName()); } } spindle.core.dom.Temporal temporal = literal.getTemporal(); if (null != temporal && temporal.hasTemporalInfo()) { CtInterval cInterval = objectFactory.createCtInterval(); if (Long.MIN_VALUE != temporal.getStartTime()) cInterval.setStart(temporal.getStartTime()); if (Long.MAX_VALUE != temporal.getEndTime()) cInterval.setEnd(temporal.getEndTime()); cLiteral.setInterval(cInterval); } CtPredicates cPredicates = generatePredicates(literal.getPredicates()); if (null != cPredicates) cLiteral.setPredicates(cPredicates); return cLiteral; } private CtPredicates generatePredicates(String[] predicates) { if (null != predicates && predicates.length > 0) { List<String> pList = new ArrayList<String>(); if (predicates.length == 1) { String p = predicates[0]; if (!LITERAL_PREDICATE_DEFAULT_VALUE.equals(p)) pList.add(p); } else { for (String p : predicates) { pList.add(LITERAL_PREDICATE_DEFAULT_VALUE.equals(p) ? "" : p); } } if (pList.size() > 0) { CtPredicates cPredicates = objectFactory.createCtPredicates(); cPredicates.getPredicate().addAll(pList); return cPredicates; } } return null; } }