/******************************************************************************* * Copyright (c) 2012 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.xdsl; import static org.eclipse.recommenders.jayes.io.xdsl.Constants.*; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import org.eclipse.recommenders.internal.jayes.io.util.XMLUtil; import org.eclipse.recommenders.jayes.BayesNet; import org.eclipse.recommenders.jayes.BayesNode; import org.eclipse.recommenders.jayes.io.IBayesNetWriter; public class XDSLWriter implements IBayesNetWriter { private static final String XML_HEADER = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"; private static final String COMMENT = "<!--\n\t Bayesian Network in XDSL format \n-->\n"; private final Writer out; public XDSLWriter(OutputStream out) { this.out = new OutputStreamWriter(out); } @Override public void write(BayesNet net) throws IOException { StringBuilder bldr = new StringBuilder(); bldr.append(XML_HEADER); bldr.append(COMMENT); int offset = bldr.length(); getVariableDefs(bldr, net); getGenieExtensions(bldr, net); XMLUtil.surround(offset, bldr, "smile", "version", "1.0", ID, XMLUtil.escape(net.getName()), "numsamples", "1000"); out.write(bldr.toString()); out.flush(); } private void getGenieExtensions(StringBuilder bldr, BayesNet net) { int offset = bldr.length(); for (BayesNode node : net.getNodes()) { int nodeOffset = bldr.length(); bldr.append(XMLUtil.escape(node.getName())); XMLUtil.surround(nodeOffset, bldr, "name"); bldr.append('\n'); int posOffset = bldr.length(); bldr.append("0 0 100 100"); XMLUtil.surround(posOffset, bldr, "position"); bldr.append('\n'); XMLUtil.emptyTag(bldr, "font", "color", "000000", "name", "Arial", "size", "8"); bldr.append('\n'); XMLUtil.emptyTag(bldr, "interior", "color", "e5f6f7"); bldr.append('\n'); XMLUtil.emptyTag(bldr, "outline", "color", "000000"); bldr.append('\n'); XMLUtil.surround(nodeOffset, bldr, "node", "id", XMLUtil.escape(node.getName())); } XMLUtil.surround(offset, bldr, "genie", "version", "1.0", "name", XMLUtil.escape(net.getName())); XMLUtil.surround(offset, bldr, "extensions"); } private void getVariableDefs(StringBuilder bldr, BayesNet net) { int offset = bldr.length(); for (BayesNode node : net.getNodes()) { int nodeOffset = bldr.length(); encodeStates(bldr, node); encodeParents(bldr, node); bldr.append('\n'); encodeProbabilities(bldr, node); XMLUtil.surround(nodeOffset, bldr, CPT, ID, XMLUtil.escape(node.getName())); bldr.append('\n'); } XMLUtil.surround(offset, bldr, "nodes"); } private void encodeStates(StringBuilder bldr, BayesNode node) { for (String outcome : node.getOutcomes()) { XMLUtil.emptyTag(bldr, STATE, ID, XMLUtil.escape(outcome)); bldr.append('\n'); } } private void encodeParents(StringBuilder bldr, BayesNode node) { int offset = bldr.length(); for (BayesNode p : node.getParents()) { // XDSL can't handle names containing whitespaces! bldr.append(XMLUtil.escape(p.getName())); bldr.append(' '); } if (!node.getParents().isEmpty()) { bldr.deleteCharAt(bldr.length() - 1); // delete last whitespace } XMLUtil.surround(offset, bldr, PARENTS); } private void encodeProbabilities(StringBuilder bldr, BayesNode node) { if (node.getProbabilities().length == 0) { throw new IllegalArgumentException("Bayesian Network is broken: " + node.getName() + " has an empty conditional probability table"); } int offset = bldr.length(); for (double d : node.getProbabilities()) { bldr.append(d); bldr.append(' '); } bldr.deleteCharAt(bldr.length() - 1); // delete last whitespace XMLUtil.surround(offset, bldr, PROBABILITIES); } @Override public void close() throws IOException { out.close(); } }