org.eclipse.recommenders.jayes.io.XMLBIFReader.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.recommenders.jayes.io.XMLBIFReader.java

Source

/**
 * 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;

import static org.eclipse.recommenders.jayes.io.util.XMLBIFConstants.*;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
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.jayes.BayesNet;
import org.eclipse.recommenders.jayes.BayesNode;
import org.eclipse.recommenders.jayes.io.util.XPathUtil;
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 {

    /**
     * when set to true, methods that were not available in version 1.0.0 will be skipped
     */
    private boolean legacyMode = false;

    public BayesNet read(String filename) throws ParserConfigurationException, SAXException, IOException {
        return read(new File(filename));
    }

    public BayesNet read(File biffile) throws ParserConfigurationException, SAXException, IOException {
        Document doc = obtainDocument(new BufferedInputStream(new FileInputStream(biffile)));

        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();

        if (!legacyMode) {
            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;
    }

    @SuppressWarnings("deprecation")
    //the Jayes 1.0.0 API is used here intentionally
    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 = new BayesNode(name.getTextContent());

            for (Iterator<Node> it = XPathUtil.evalXPath(xpath, OUTCOME, node); it.hasNext();) {
                bNode.addOutcome(StringEscapeUtils.unescapeXml(it.next().getTextContent()));
            }

            net.addNode(bNode);

        }
    }

    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));
    }

    public BayesNet read(InputStream systemResourceAsStream)
            throws ParserConfigurationException, SAXException, IOException {
        Document doc = obtainDocument(systemResourceAsStream);
        return readFromDocument(doc);
    }

    public boolean isLegacyMode() {
        return legacyMode;
    }

    /**
     * 
     * @param legacyMode
     *            when set to true, the object will only use Jayes 1.0.0 API
     */
    public void setLegacyMode(boolean legacyMode) {
        this.legacyMode = legacyMode;
    }

}