/* * This file or a portion of this file is licensed under the terms of * the Globus Toolkit Public License, found in file GTPL, or at * http://www.globus.org/toolkit/download/license.html. This notice must * appear in redistributions of this file, with or without modification. * * Redistributions of this Software, with or without modification, must * reproduce the GTPL in: (1) the Software, or (2) the Documentation or * some other similar material which is provided with the Software (if * any). * * Copyright 1999-2004 University of Chicago and The University of * Southern California. All rights reserved. */ package org.griphyn.vdl; import java.io.*; import java.text.*; import org.griphyn.vdl.util.Logging; /** * This abstract class defines a common base for all JAPI Chimera objects. * All VDL-related classes must conform to this interface, in order to * make various instances available as a reference to this class. * * @author Jens-S. Vöckler * @author Yong Zhao * @version $Revision$ */ public abstract class Chimera { /** * Escapes certain characters inappropriate for textual output. * * @param original is a string that needs to be quoted * @return a string that is "safe" to print. */ static public String escape( String original ) { if ( original == null ) return null; StringBuffer result = new StringBuffer( 2 * original.length() ); StringCharacterIterator i = new StringCharacterIterator(original); for ( char ch = i.first(); ch != i.DONE; ch = i.next() ) { if ( ch == '\r' ) { result.append("\\r"); } else if ( ch == '\n' ) { result.append("\\n"); } else if ( ch == '\t' ) { result.append("\\t"); } else { // Chimera bugzilla bug#21 // Do not escape apostrophe unless it is required to escape // it in the input. if ( ch == '\"' || ch == '\\' ) result.append('\\'); result.append(ch); } } return result.toString(); } /** * Escapes certain characters inappropriate for XML content output. * FIXME: Quotes within attribute values are still not handled correctly. * * @param original is a string that needs to be quoted * @param isAttribute denotes an attributes value, if set to true. * If false, it denotes regular XML content outside of attributes. * @return a string that is "safe" to print as XML. */ static public String quote( String original, boolean isAttribute ) { if ( original == null ) return null; StringBuffer result = new StringBuffer( 2 * original.length() ); StringCharacterIterator i = new StringCharacterIterator(original); for ( char ch = i.first(); ch != i.DONE; ch = i.next() ) { switch (ch) { case '<': result.append( "<" ); break; case '&': result.append( "&" ); break; case '>': result.append( ">" ); break; case '\'': result.append( "'" ); break; case '\"': result.append( """ ); break; default: result.append(ch); break; } } return result.toString(); } /** * Dumps content of the given element into a string. This function * traverses all sibling classes as necessary and converts the * data into textual output.<p> * * Sibling classes which represent small leaf objects, and can return * the necessary data more efficiently, are encouraged to overwrite * this method. * * @return a textual description of the element and its sub-classes. * Be advised that these strings might become large. */ public String toString() { StringWriter sw = new StringWriter(); try { this.toString( sw ); sw.flush(); } catch ( IOException ioe ) { Logging.instance().log( "default", 0, ioe.toString() ); } return sw.toString(); } /** * Dumps the content of the given element into a stream. This function * traverses all sibling classes as necessary and converts the * data into textual output. * * @param s is a stream opened and ready for writing. This can also be * a string stream for efficient output. The stream interface should * be able to handle large elements efficiently. * @exception IOException if something fishy happens to the stream. */ public abstract void toString( Writer s ) throws IOException; /** * XML write helper method writes a quoted attribute onto a stream. * The terminating quote will be appended automatically. Values will * be XML-escaped. No action will be taken, if the value is null. * * @param stream is the stream to append to * @param key is the attribute including initial space, attribute name, * equals sign, and opening quote. * @param value is a string value, which will be put within the quotes * and which will be escaped. If the value is null, no action will be * taken * @exception IOException for stream errors. */ public void writeAttribute( Writer stream, String key, String value ) throws IOException { if ( value != null ) { stream.write( key ); stream.write( quote(value,true) ); stream.write( '"' ); } } /** * Dumps the state of the current element as XML output. This function * traverses all sibling classes as necessary, and converts the data * into pretty-printed XML output.<p> * * Sibling classes which represent small leaf objects, and can return * the necessary data more efficiently, are encouraged to overwrite * this method. * * @param indent is a <code>String</code> of spaces used for pretty * printing. The initial amount of spaces should be an empty string. * The parameter is used internally for the recursive traversal. * If null, avoidable whitespaces in the output will be avoided. * @param namespace is the XML schema namespace prefix. If neither * empty nor null, each element will be prefixed with this prefix, * and the root element will map the XML namespace. * @return a String which contains the state of the current class * and its siblings using XML. Note that these strings might become large. */ public String toXML( String indent, String namespace ) { StringWriter sw = new StringWriter(); try { this.toXML( sw, indent, namespace ); sw.flush(); } catch ( IOException ioe ) { Logging.instance().log( "default", 0, ioe.toString() ); } return sw.toString(); } /** * Provides backward compatibility. * <pre> * toXML( stream, indent, (String) null ); * </pre> * * @param stream is a stream opened and ready for writing. This can also * be a string stream for efficient output. * @param indent is a <code>String</code> of spaces used for pretty * printing. The initial amount of spaces should be an empty string. * The parameter is used internally for the recursive traversal. * If a <code>null</code> value is specified, no indentation nor * linefeeds will be generated. * @exception IOException if something fishy happens to the stream. * @see #toXML( Writer, String, String ) */ public void toXML( Writer stream, String indent ) throws IOException { toXML( stream, indent, (String) null ); } /** * Dump the state of the current element as XML output. This function * traverses all sibling classes as necessary, and converts the data * into pretty-printed XML output. The stream interface should be able * to handle large output efficiently, if you used a buffered writer. * * @param stream is a stream opened and ready for writing. This can also * be a string stream for efficient output. * @param indent is a <code>String</code> of spaces used for pretty * printing. The initial amount of spaces should be an empty string. * The parameter is used internally for the recursive traversal. * If a <code>null</code> value is specified, no indentation nor * linefeeds will be generated. * @param namespace is the XML schema namespace prefix. If neither * empty nor null, each element will be prefixed with this prefix, * and the root element will map the XML namespace. * @exception IOException if something fishy happens to the stream. * @see java.io.BufferedWriter */ public abstract void toXML( Writer stream, String indent, String namespace ) throws IOException; }