/* * $Id$ * This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc * * Copyright (c) 2000-2012 Stephane GALLAND. * Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports, * Universite de Technologie de Belfort-Montbeliard. * Copyright (c) 2013-2016 The original authors, and other authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.arakhne.afc.math.tree.io; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Iterator; import org.arakhne.afc.inputoutput.filefilter.GXLFileFilter; import org.arakhne.afc.math.tree.Tree; import org.arakhne.afc.math.tree.TreeNode; /** * This is a writer of .gxl file from a tree. * * <p>The .gxl file format is an XML dialect for the .dot file format. * It is defined on <a href="http://www.gupro.de/GXL/">Graph eXchange Language page</a>. * * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ * @since 13.0 */ public class DotGxlWriter { /** Common extension used for <code>.dot</code> files. * * @deprecated see {@link GXLFileFilter#EXTENSION}. */ @Deprecated public static final String EXTENSION = GXLFileFilter.EXTENSION; private final Writer writer; private int graphIndex; /** * Create a new gxl writer that output inside the given output stream. * * @param outputStream is the stream to write in. */ public DotGxlWriter(OutputStream outputStream) { this(new OutputStreamWriter(outputStream)); } /** * Create a new gxl writer that output inside the given output stream. * * @param outputStream is the stream to write in. */ public DotGxlWriter(Writer outputStream) { assert outputStream != null; this.writer = outputStream; this.graphIndex = 1; } /** * Write the given tree inside the .gxl output stream. * * @param tree is the tree to write * @throws IOException in case of error */ public void write(Tree<?, ?> tree) throws IOException { this.writer.append("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"); //$NON-NLS-1$ this.writer.append("<gxl>\n"); //$NON-NLS-1$ if (tree != null) { this.writer.append("\t<graph id=\""); //$NON-NLS-1$ this.writer.append(Integer.toHexString(System.identityHashCode(new Integer(tree.hashCode())))); this.writer.append("-"); //$NON-NLS-1$ this.writer.append(Integer.toString(this.graphIndex++)); this.writer.append("\" edgeids=\"true\" edgemode=\"directed\">\n"); //$NON-NLS-1$ // Write the node attributes Iterator<? extends TreeNode<?, ?>> iterator = tree.broadFirstIterator(); TreeNode<?, ?> node; int dataCount; while (iterator.hasNext()) { node = iterator.next(); dataCount = node.getUserDataCount(); final String name = "NODE" + Integer.toHexString(node.hashCode()); //$NON-NLS-1$ final String label = Integer.toString(dataCount); this.writer.append("\t\t<node id=\""); //$NON-NLS-1$ this.writer.append(name); this.writer.append("\">\n"); //$NON-NLS-1$ this.writer.append("\t\t\t<attr name=\"label\">\n"); //$NON-NLS-1$ this.writer.append("\t\t\t\t<string>"); //$NON-NLS-1$ this.writer.append(label); this.writer.append("</string>\n"); //$NON-NLS-1$ this.writer.append("\t\t\t</attr>\n"); //$NON-NLS-1$ this.writer.append("\t\t</node>\n"); //$NON-NLS-1$ } // Write the node attributes iterator = tree.broadFirstIterator(); TreeNode<?, ?> child; String childName; while (iterator.hasNext()) { node = iterator.next(); final String name = "NODE" + Integer.toHexString(node.hashCode()); //$NON-NLS-1$ if (!node.isLeaf()) { final int childCount = node.getChildCount(); for (int i = 0; i < childCount; ++i) { child = node.getChildAt(i); if (child != null) { childName = "NODE" + Integer.toHexString(child.hashCode()); //$NON-NLS-1$ this.writer.append("\t\t<edge id=\""); //$NON-NLS-1$ this.writer.append(name); this.writer.append("--"); //$NON-NLS-1$ this.writer.append(childName); this.writer.append("\" isdirected=\"true\" from=\""); //$NON-NLS-1$ this.writer.append(name); this.writer.append("\" to=\""); //$NON-NLS-1$ this.writer.append(childName); this.writer.append("\">\n"); //$NON-NLS-1$ this.writer.append("\t\t\t<attr name=\"label\">\n"); //$NON-NLS-1$ this.writer.append("\t\t\t\t<string>"); //$NON-NLS-1$ this.writer.append(Integer.toString(i)); this.writer.append("</string>\n"); //$NON-NLS-1$ this.writer.append("\t\t\t</attr>\n"); //$NON-NLS-1$ this.writer.append("\t\t</edge>\n"); //$NON-NLS-1$ } } } } this.writer.append("\t</graph>\n"); //$NON-NLS-1$ } this.writer.append("</gxl>\n"); //$NON-NLS-1$ } /** Close the output stream. * * @throws IOException in case of error. */ public void close() throws IOException { this.writer.close(); } }