package org.jboss.mq.xml;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import org.xml.sax.Attributes;
public class XElement {
private XElement parent = null;
private String name = null;
private Hashtable metadata = new Hashtable();
private Vector contents = new Vector();
private final static String nl = System.getProperty( "line.separator" );
public XElement( String objectName ) {
if ( objectName == null ) {
throw new NullPointerException();
}
name = objectName;
contents.addElement( new StringBuffer() );
}
public XElement( String objectName, Attributes atts ) {
if ( objectName == null ) {
throw new NullPointerException();
}
if ( atts == null ) {
throw new NullPointerException();
}
name = objectName;
contents.addElement( new StringBuffer() );
for ( int i = 0; i < atts.getLength(); i++ ) {
metadata.put( atts.getQName( i ), atts.getValue( i ) );
}
}
public void setAttribute( String key, String value ) {
metadata.put( key, value );
}
public void setName( String newName ) {
name = newName;
}
public void setValue( String value )
throws XElementException {
if ( !isField() ) {
throw new XElementException( "" + getName() + " is not an attribute object" );
}
contents.setElementAt( new StringBuffer( value ), 0 );
}
public void setField( String key, String value )
throws XElementException {
getElement( key ).setValue( value );
}
public String getAttribute( String key ) {
String t = ( String )metadata.get( key );
if ( t == null ) {
return "";
}
return t;
}
public java.lang.String getName() {
return name;
}
public XElement getParent() {
return parent;
}
public String getText() {
return contents.elementAt( 0 ).toString().trim();
}
public String getValue()
throws XElementException {
if ( !isField() ) {
throw new XElementException( "" + getName() + " is not an attribute object" );
}
return contents.elementAt( 0 ).toString();
}
public XElement getElement( String relativeName )
throws XElementException {
if ( relativeName == null ) {
throw new NullPointerException();
}
String names[] = {null, relativeName};
String split[] = splitFront( relativeName, "/" );
if ( split != null ) {
if ( split[0].length() == 0 ) {
if ( parent == null ) {
split[0] = null;
}
else {
return parent.getElement( relativeName );
}
}
if ( split[1].length() == 0 ) {
if ( split[0].equals( null ) ) {
return this;
}
throw new XElementException( "Invalid name (trailing '/') : " + relativeName );
}
names = split;
}
if ( names[0] == null ) {
for ( int i = 1; i < contents.size(); i++ ) {
XElement o = ( XElement )contents.elementAt( i );
if ( names[1].equals( o.getName() ) ) {
return o;
}
}
} else {
if ( names[0].equals( "." ) ) {
return getElement( names[1] );
} else if ( names[0].equals( ".." ) ) {
if ( parent != null ) {
return parent.getElement( names[1] );
} else {
throw new XElementException( "Invalid name (" + getName() + " has no parent) : " + relativeName );
}
} else {
for ( int i = 1; i < contents.size(); i++ ) {
XElement o = ( XElement )contents.elementAt( i );
if ( names[0].equals( o.getName() ) ) {
return o.getElement( names[1] );
}
}
}
}
throw new XElementException( "Invalid name (" + getName() + " does not contain the name) : " + relativeName );
}
public String getField( String objectName )
throws XElementException {
return getElement( objectName ).getValue();
}
public boolean isField() {
return contents.size() == 1;
}
public java.util.Enumeration getElementsNamed( String relativeName ) {
Vector t = new Vector();
addElementsToVector( t, relativeName );
return t.elements();
}
public void add( String data ) {
( ( StringBuffer )contents.elementAt( 0 ) ).append( data );
}
public String toString() {
return toString( 0, true );
}
public void addElement( XElement subObject ) {
contents.addElement( subObject );
subObject.parent = this;
}
public void addField( String key, String value ) {
XElement subObject = new XElement( key );
subObject.add( value );
addElement( subObject );
}
public boolean containsElement( String objectName ) {
try {
getElement( objectName );
return true;
} catch ( XElementException e ) {
return false;
}
}
public boolean containsField( String objectName ) {
try {
XElement obj = getElement( objectName );
return obj.isField();
} catch ( XElementException e ) {
return false;
}
}
public String toString( int nestingLevel, boolean indent ) {
try {
StringBuffer indentation = new StringBuffer();
StringBuffer rc = new StringBuffer();
if ( indent ) {
for ( int i = 0; i < nestingLevel; i++ ) {
indentation.append( '\t' );
}
}
rc.append( indentation.toString() );
rc.append( "<" );
rc.append( getName() );
Enumeration enumeration = metadata.keys();
while ( enumeration.hasMoreElements() ) {
String key = ( String )enumeration.nextElement();
String value = ( String )metadata.get( key );
rc.append( ' ' );
rc.append( key );
rc.append( "=\"" );
rc.append( metaValueEncode( value ) );
rc.append( '"' );
}
if ( isField() ) {
if ( getValue().length() == 0 ) {
rc.append( "/>" );
rc.append( nl );
} else {
rc.append( '>' );
rc.append( valueEncode( getValue() ) );
rc.append( "</" );
rc.append( getName() );
rc.append( '>' );
rc.append( nl );
}
} else {
rc.append( '>' );
rc.append( nl );
String text = getText();
if ( text.length() > 0 ) {
rc.append( indentation.toString() + "\t" );
rc.append( getText() );
rc.append( nl );
}
for ( int i = 1; i < contents.size(); i++ ) {
Object o = contents.elementAt( i );
rc.append( ( ( XElement )o ).toString( nestingLevel + 1, indent ) );
}
rc.append( indentation.toString() );
rc.append( "</" );
rc.append( getName() );
rc.append( '>' );
rc.append( nl );
}
return rc.toString();
} catch ( XElementException e ) {
e.printStackTrace();
System.exit( 1 );
return "";
}
}
public String toXML( boolean indent ) {
return
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + nl +
toString( 0, indent );
}
public void removeFromParent()
throws XElementException {
if ( parent == null ) {
throw new XElementException( "" + getName() + " does not have a parent" );
}
parent.contents.remove( this );
parent = null;
}
public Enumeration elements() {
return getElementsNamed( "*" );
}
private void addElementsToVector( Vector t, String relativeName ) {
String names[] = {null, relativeName};
String split[] = splitFront( relativeName, "/" );
if ( split != null ) {
if ( split[0].length() == 0 ) {
if ( parent == null ) {
split[0] = null;
} else {
parent.addElementsToVector( t, relativeName );
return;
}
}
if ( split[1].length() == 0 ) {
return;
}
names = split;
}
if ( names[0] == null ) {
if ( names[1].equals( "*" ) ) {
for ( int i = 1; i < contents.size(); i++ ) {
t.addElement( contents.elementAt( i ) );
}
} else {
for ( int i = 1; i < contents.size(); i++ ) {
XElement o = ( XElement )contents.elementAt( i );
if ( names[1].equals( o.getName() ) ) {
t.addElement( o );
}
}
}
} else {
if ( names[0].equals( "." ) ) {
addElementsToVector( t, names[1] );
return;
} else if ( names[0].equals( ".." ) ) {
if ( parent != null ) {
parent.addElementsToVector( t, names[1] );
}
return;
} else {
for ( int i = 1; i < contents.size(); i++ ) {
XElement o = ( XElement )contents.elementAt( i );
if ( names[0].equals( o.getName() ) ) {
o.addElementsToVector( t, names[1] );
}
}
}
}
}
public static XElement createFrom( java.io.InputStream is )
throws XElementException, java.io.IOException {
class MyRecordConsumer implements XElementConsumer {
XElement root = null;
public void documentEndEvent() {
}
public void documentStartEvent() {
}
public void recordReadEvent( XElement o ) {
root = o;
}
}
MyRecordConsumer consumer = new MyRecordConsumer();
XElementProducer producer = new XElementProducer( consumer );
try {
producer.parse( is );
if ( consumer.root == null ) {
throw new XElementException( "No root element" );
}
return consumer.root;
} catch ( java.io.IOException e ) {
throw e;
} catch ( Exception e ) {
throw new XElementException( "Parse Error: " + e );
}
}
public static XElement createFrom( java.net.URL url )
throws XElementException, java.io.IOException {
class MyRecordConsumer implements XElementConsumer {
XElement root = null;
public void documentEndEvent() {
}
public void documentStartEvent() {
}
public void recordReadEvent( XElement o ) {
root = o;
}
}
MyRecordConsumer consumer = new MyRecordConsumer();
XElementProducer producer = new XElementProducer( consumer );
try {
producer.parse( url );
if ( consumer.root == null ) {
throw new XElementException( "No root element" );
}
return consumer.root;
} catch ( java.io.IOException e ) {
throw e;
} catch ( Exception e ) {
throw new XElementException( "Parse Error: " + e );
}
}
private static String findAndReplace( String value, String searchStr, String replaceStr ) {
StringBuffer buffer = new StringBuffer( value.length() );
while ( value.length() > 0 ) {
int pos = value.indexOf( searchStr );
if ( pos != -1 ) {
buffer.append( value.substring( 0, pos ) );
buffer.append( replaceStr );
if ( pos + searchStr.length() < value.length() ) {
value = value.substring( pos + searchStr.length() );
} else {
value = "";
}
} else {
buffer.append( value );
value = "";
}
}
return buffer.toString();
}
private static String metaValueEncode( String value ) {
value = findAndReplace( value, "&", "&" );
value = findAndReplace( value, "\"", """ );
value = findAndReplace( value, "'", "'" );
return utf8Encode( value );
}
private static String utf8Encode( String value ) {
try {
char buff[] = new char[value.length()];
value.getChars( 0, buff.length, buff, 0 );
sun.io.CharToByteUTF8 conv = new sun.io.CharToByteUTF8();
byte b[] = conv.convertAll( buff );
return new String( b );
} catch ( sun.io.MalformedInputException e ) {
return null;
}
}
private static String valueEncode( String value ) {
value = findAndReplace( value, "&", "&" );
value = findAndReplace( value, "<", "<" );
value = findAndReplace( value, ">", ">" );
return utf8Encode( value );
}
private static String[] splitFront( String string, String splitMarker ) {
if ( string == null || splitMarker == null ) {
throw new NullPointerException();
}
String front;
String back;
int pos = string.indexOf( splitMarker );
if ( pos == -1 ) {
return null;
}
int l = splitMarker.length();
front = string.substring( 0, pos );
if ( pos + l >= string.length() ) {
back = "";
} else {
back = string.substring( pos + l );
}
String rc[] = {front, back};
return rc;
}
public String getOptionalField( String field) throws XElementException {
if ( !containsField(field) )
return null;
return getField(field);
}
public void setOptionalField( String field, String value) throws XElementException {
if ( value == null ) {
if( containsField(field) )
getElement(field).removeFromParent();
return;
}
if( containsField(field) )
setField(field, value);
else
addField(field, value);
}
}