/** * Copyright (c) 2011 Michael Kutschke. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Michael Kutschke - initial API and implementation. */ package org.eclipse.recommenders.jayes.io.xmlbif; import static org.eclipse.recommenders.jayes.io.xmlbif.Constants.*; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.lang3.StringEscapeUtils; import org.eclipse.recommenders.internal.jayes.io.util.XPathUtil; import org.eclipse.recommenders.jayes.BayesNet; import org.eclipse.recommenders.jayes.BayesNode; import org.eclipse.recommenders.jayes.io.IBayesNetReader; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.xpath.XPathEvaluator; import org.xml.sax.SAXException; import com.google.common.primitives.Doubles; /** * a Reader thats reads the XMLBIF v0.3 format (<a href="http://www.cs.cmu.edu/~fgcozman/Research/InterchangeFormat/" * >specification</a>) */ public class XMLBIFReader implements IBayesNetReader { private final InputStream in; public XMLBIFReader(InputStream in) { this.in = in; } public BayesNet read() throws IOException { Document doc; try { doc = obtainDocument(in); } catch (ParserConfigurationException e) { throw new IOException(e); } catch (SAXException e) { throw new IOException(e); } return readFromDocument(doc); } private Document obtainDocument(InputStream biffile) throws ParserConfigurationException, SAXException, IOException { DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); docBuilderFactory.setValidating(true); DocumentBuilder docBldr = docBuilderFactory.newDocumentBuilder(); Document doc = docBldr.parse(biffile); doc.normalize(); return doc; } public BayesNet readFromString(String xmlBif) throws ParserConfigurationException, SAXException, IOException { DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); docBuilderFactory.setValidating(true); DocumentBuilder docBldr = docBuilderFactory.newDocumentBuilder(); Document doc = docBldr.parse(new ByteArrayInputStream(xmlBif.getBytes())); return readFromDocument(doc); } private BayesNet readFromDocument(Document doc) { BayesNet net = new BayesNet(); net.setName(doc.getElementsByTagName(NAME).item(0).getTextContent()); initializeNodes(doc, net); XPathEvaluator xpath = getXPathEvaluator(doc); NodeList nodelist = doc.getElementsByTagName(DEFINITION); for (int i = 0; i < nodelist.getLength(); i++) { Node node = nodelist.item(i); String name = XPathUtil.evalXPath(xpath, FOR, node).next().getTextContent(); BayesNode bNode = net.getNode(name); setParents(bNode, net, node, xpath); parseProbabilities(xpath, node, bNode); } return net; } private void initializeNodes(Document doc, BayesNet net) { XPathEvaluator xpath = getXPathEvaluator(doc); NodeList nodelist = doc.getElementsByTagName(VARIABLE); for (int i = 0; i < nodelist.getLength(); i++) { Node node = nodelist.item(i); Node name = XPathUtil.evalXPath(xpath, NAME, node).next(); BayesNode bNode = net.createNode(name.getTextContent()); for (Iterator<Node> it = XPathUtil.evalXPath(xpath, OUTCOME, node); it.hasNext();) { bNode.addOutcome(StringEscapeUtils.unescapeXml(it.next().getTextContent())); } } } private XPathEvaluator getXPathEvaluator(Document doc) { return (XPathEvaluator) doc.getFeature("+XPath", null); } private void setParents(BayesNode bNode, BayesNet net, Node node, XPathEvaluator xpath) { List<BayesNode> parents = new ArrayList<BayesNode>(); for (Iterator<Node> it = XPathUtil.evalXPath(xpath, GIVEN, node); it.hasNext();) { parents.add(net.getNode(it.next().getTextContent())); } bNode.setParents(parents); } private void parseProbabilities(XPathEvaluator xpath, Node node, BayesNode bNode) { String table = XPathUtil.evalXPath(xpath, TABLE, node).next().getTextContent(); List<Double> probabilities = new ArrayList<Double>(); StringTokenizer tok = new StringTokenizer(table); while (tok.hasMoreTokens()) { probabilities.add(Double.valueOf(tok.nextToken())); } bNode.setProbabilities(Doubles.toArray(probabilities)); } @Override public void close() throws IOException { in.close(); } }