/* Soot - a J*va Optimization Framework
* Copyright (C) 2002 David Eng
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the Sable Research Group and others 1997-1999.
* See the 'credits' file distributed with Soot for the complete list of
* contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
*/
package soot.xml;
/** XML helper */
public class XMLNode extends XMLRoot
{
// constants
public static final int TAG_STRING_BUFFER = 4096;
// node pointers
public XMLNode next = null; // -> to next node
public XMLNode prev = null; // -> to previous node
public XMLNode parent = null; // -> to parent node
public XMLNode child = null; // -> to child node
public XMLRoot root = null; // -> to root node
public XMLNode( String in_name, String in_value, String[] in_attributes, String[] in_values )
{
name = in_name;
value = in_value;
attributes = in_attributes;
values = in_values;
}
public XMLNode( XMLNode node )
{
if( node != null )
{
name = node.name;
value = node.value;
attributes = node.attributes;
values = node.values;
if( node.child != null )
this.child = ( XMLNode )node.child.clone();
if( node.next != null )
this.next = ( XMLNode )node.next.clone();
}
}
public Object clone()
{
return new XMLNode( this );
}
public String toPostString()
{
return toPostString( "" );
}
public String toPostString( String indent )
{
if( next != null )
return this.toString( indent ) + next.toPostString( indent);
else
return this.toString( indent );
}
// returns the number of children
public int getNumberOfChildren()
{
int count = 0;
if( child != null )
{
XMLNode current = child;
while( current != null )
{
current = current.next;
count++;
}
}
return count;
}
// adds an attribute to an element
public XMLNode addAttribute( String attribute, String value )
{
// check if this attribute already exists
String[] tempAttributes = this.attributes;
String[] tempValues = this.values;
this.attributes = new String[ tempAttributes.length + 1 ];
this.values = new String[ tempValues.length + 1 ];
for( int i = 0; i < tempAttributes.length; i++ )
{
this.attributes[ i ] = tempAttributes[ i ];
if( tempValues.length > i )
{
this.values[ i ] = tempValues[ i ];
}
}
this.attributes[ tempAttributes.length ] = attribute.trim();
this.values[ tempValues.length ] = value.trim();
return this;
}
// XML Printing and formatting
//
public String toString()
{
return toString( "" );
}
public String toString( String indent )
{
// <tag
StringBuffer beginTag = new StringBuffer( TAG_STRING_BUFFER );
StringBuffer endTag = new StringBuffer( TAG_STRING_BUFFER );
String xmlName = eliminateSpaces( name );
beginTag.append( "<" + xmlName );
if( attributes != null )
{
for( int i = 0; i < attributes.length; i++ )
{
if( attributes[ i ].length() > 0 )
{
// <tag attr="
String attributeName = eliminateSpaces( attributes[ i ].toString().trim() );
// TODO: attribute name should be one word! squish it?
beginTag.append( " " + attributeName + "=\"" );
// <tag attr="val"
// if there is no value associated with this attribute,
// consider it a <hr NOSHADE> style attribute;
// use the default: <hr NOSHADE="NOSHADE">
if( values != null )
{
if( i < values.length )
{
beginTag.append( values[ i ].toString().trim() + "\"" );
}
else
{
beginTag.append( attributeName.trim() + "\"" );
}
}
}
}
}
// <tag attr="val"...> or <tag attr="val".../>
// if there is no value in this element AND this element has no children, it can be a single tag <.../>
if( value.length() < 1 && child == null )
{
beginTag.append( " />\n" );
endTag.setLength( 0 );
}
else
{
beginTag.append( ">" );
endTag.append( "</" + xmlName + ">\n" );
}
//return ( prev.toString() + beginTag.toString() + value.toString() + child.toString() + endTag.toString() + next.toString() );
String returnStr = indent + beginTag.toString();
if( value.length() > 0 )
returnStr += value.toString();
if( child != null )
returnStr += "\n" + child.toPostString( indent + " " );
if( child != null )
returnStr += indent;
if( endTag.length() > 0 )
returnStr += endTag.toString();
return( returnStr );
}
// CONSTRUCTION ROUTINES
//
//
// insert element before the node here
public XMLNode insertElement( String name )
{
return insertElement( name, "", "", "" );
}
public XMLNode insertElement( String name, String value )
{
return insertElement( name, value, "", "" );
}
public XMLNode insertElement( String name, String value, String[] attributes )
{
return insertElement( name, value, attributes, null );
}
public XMLNode insertElement( String name, String[] attributes, String[] values )
{
return insertElement( name, "", attributes, values );
}
public XMLNode insertElement( String name, String value, String attribute, String attributeValue )
{
return insertElement( name, value, new String[] { attribute}, new String[] { attributeValue} );
}
public XMLNode insertElement( String name, String value, String[] attributes, String[] values )
{
XMLNode newnode = new XMLNode( name, value, attributes, values );
// check if this node is the first of a chain
if( this.parent != null )
{
if( this.parent.child.equals( this ) )
{
this.parent.child = newnode;
}
}
// if it has no parent it might be a root's child
else
{
if( this.prev == null )
{
this.root.child = newnode;
}
}
newnode.child = null;
newnode.parent = this.parent;
newnode.prev = this.prev;
if( newnode.prev != null )
newnode.prev.next = newnode;
this.prev = newnode;
newnode.next = this;
return newnode;
}
// add element to end of tree
public XMLNode addElement( String name )
{
return addElement( name, "", "", "" );
}
public XMLNode addElement( String name, String value )
{
return addElement( name, value, "", "" );
}
public XMLNode addElement( String name, String value, String[] attributes )
{
return addElement( name, value, attributes, null );
}
public XMLNode addElement( String name, String[] attributes, String[] values )
{
return addElement( name, "", attributes, values );
}
public XMLNode addElement( String name, String value, String attribute, String attributeValue )
{
return addElement( name, value, new String[] { attribute}, new String[] { attributeValue} );
}
public XMLNode addElement( String name, String value, String[] attributes, String[] values )
{
XMLNode newnode = new XMLNode( name, value, attributes, values);
return addElement( newnode );
}
public XMLNode addElement( XMLNode node )
{
XMLNode current = this;
while( current.next != null )
{
current = current.next;
}
current.next = node;
node.prev = current;
return node;
}
// add one level of children
public XMLNode addChildren( XMLNode children )
{
XMLNode current = children;
while( current != null )
{
current.parent = this;
current = current.next;
}
if( this.child == null )
{
this.child = children;
}
else
{
current = this.child;
while( current.next != null )
{
current = current.next;
}
current.next = children;
}
return this;
}
// add element to end of tree
public XMLNode addChild( String name )
{
return addChild( name, "", "", "" );
}
public XMLNode addChild( String name, String value )
{
return addChild( name, value, "", "" );
}
public XMLNode addChild( String name, String value, String[] attributes )
{
return addChild( name, value, attributes, null );
}
public XMLNode addChild( String name, String[] attributes, String[] values )
{
return addChild( name, "", attributes, values );
}
public XMLNode addChild( String name, String value, String attribute, String attributeValue )
{
return addChild( name, value, new String[] { attribute}, new String[] { attributeValue} );
}
public XMLNode addChild( String name, String value, String[] attributes, String[] values )
{
XMLNode newnode = new XMLNode( name, value, attributes, values );
return addChild( newnode );
}
public XMLNode addChild( XMLNode node )
{
if( this.child == null )
{
this.child = node;
node.parent = this;
}
else
{
XMLNode current = this.child;
while( current.next != null )
{
current = current.next;
}
current.next = node;
node.prev = current;
node.parent = this;
}
return node;
}
private String eliminateSpaces( String str )
{
return str.trim().replace( ' ', '_' );
}
}