/* * Encog(tm) Core v3.4 - Java Version * http://www.heatonresearch.com/encog/ * https://github.com/encog/encog-java-core * Copyright 2008-2016 Heaton Research, Inc. * * 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. * * For more information on Heaton Research copyrights, licenses * and trademarks visit: * http://www.heatonresearch.com/copyright */ package org.encog.parse.tags.write; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import java.util.Stack; import org.encog.EncogError; import org.encog.neural.NeuralNetworkError; import org.encog.parse.ParseError; import org.encog.parse.tags.TagConst; /** * Class used to write out tags, such as XML or HTML. * * @author jheaton */ public class WriteTags { /** * The output stream to write to. */ private final OutputStream output; /** * Stack to keep track of beginning and ending tags. */ private final Stack<String> tagStack; /** * The attributes for the current tag. */ private final Map<String, String> attributes; /** * Construct an object to write tags. * * @param output * THe output stream. */ public WriteTags(final OutputStream output) { this.output = output; this.tagStack = new Stack<String>(); this.attributes = new HashMap<String, String>(); } /** * Add an attribute to be written with the next tag. * * @param name * The name of the attribute. * @param value * The value of the attribute. */ public void addAttribute(final String name, final String value) { this.attributes.put(name, value); } /** * Add CDATA to the output stream. XML allows a large block of unformatted * text to be added as a CDATA tag. * * @param text * The text to add. */ public void addCDATA(final String text) { final StringBuilder builder = new StringBuilder(); builder.append('<'); builder.append(TagConst.CDATA_BEGIN); builder.append(text); builder.append(TagConst.CDATA_END); builder.append('>'); try { this.output.write(builder.toString().getBytes()); } catch (final IOException e) { throw new ParseError(e); } } /** * Add a property as a double. A property is a value enclosed in two tags. * * @param name * The name of the enclosing tags. * @param d * The value to store. */ public void addProperty(final String name, final double d) { beginTag(name); addText("" + d); endTag(); } /** * Add a property as an integer. A property is a value enclosed in two tags. * * @param name * The name of the enclosing tags. * @param i * The value to store. */ public void addProperty(final String name, final int i) { addProperty(name, "" + i); } /** * Add a property as a string. A property is a value enclosed in two tags. * * @param name * The name of the enclosing tags. * @param str * The value to store. */ public void addProperty(final String name, final String str) { beginTag(name); addText(str); endTag(); } /** * Write an array as a property. * @param name The name of the property. * @param array The array to write. * @param len The length of the array to write. */ public void addProperty(final String name, final double[] array, int len) { if (array != null) { StringBuilder str = new StringBuilder(); for (int i = 0; i < len; i++) { if (i != 0) str.append(' '); str.append(array[i]); } addProperty(name, str.toString()); } } /** * Write an array as a property. * @param name The name of the property. * @param array The array to write. * @param len The length of the array to write. */ public void addProperty(final String name, final int[] array, int len) { if (array != null) { StringBuilder str = new StringBuilder(); for (int i = 0; i < len; i++) { if (i != 0) str.append(' '); str.append(array[i]); } addProperty(name, str.toString()); } } /** * Add text. * * @param text * The text to add. */ public void addText(final String text) { try { this.output.write(text.getBytes()); } catch (final IOException e) { throw new ParseError(e); } } /** * Called to begin the document. */ public void beginDocument() { } /** * Begin a tag with the specified name. * * @param name * The tag to begin. */ public void beginTag(final String name) { final StringBuilder builder = new StringBuilder(); builder.append("<"); builder.append(name); if (this.attributes.size() > 0) { for (final String key : this.attributes.keySet()) { final String value = this.attributes.get(key); builder.append(' '); builder.append(key); builder.append('='); builder.append("\""); builder.append(value); builder.append("\""); } } builder.append(">"); try { this.output.write(builder.toString().getBytes()); } catch (final IOException e) { throw new ParseError(e); } this.attributes.clear(); this.tagStack.push(name); } /** * Close this object. */ public void close() { try { this.output.close(); } catch (final IOException e) { throw new EncogError(e); } } /** * End the document. */ public void endDocument() { } /** * End the current tag. */ public void endTag() { if (this.tagStack.isEmpty()) { throw new NeuralNetworkError( "Can't create end tag, no beginning tag."); } final String tag = this.tagStack.pop(); final StringBuilder builder = new StringBuilder(); builder.append("</"); builder.append(tag); builder.append(">"); try { this.output.write(builder.toString().getBytes()); } catch (final IOException e) { throw new ParseError(e); } } /** * End a tag, require that we are ending the specified tag. * * @param name * The tag to be ending. */ public void endTag(final String name) { if (!this.tagStack.peek().equals(name)) { throw new ParseError( "End tag mismatch, should be ending: " + this.tagStack.peek() + ", but trying to end: " + name + "."); } else { endTag(); } } }