package org.bodington.xml;

public class XMLUtils
	{
	public static char[] illegalPCDataChars = 
		{ '<', '>', '&',  };
		
	public static String[] pcDataEscapes = 
		{ "&lt;", "&gt;", "&amp;",  };
		
	public static char[] illegalAttributeChars = 
		{ '<', '>', '&', '\'', '"' };

	public static String[] attributeEscapes = 
		{ "&lt;", "&gt;", "&amp;", "&apos;", "&quot;" };
		

	private static boolean needsEscaping( String str, char[] illegalChars )
		{
		for ( int j=0; j< illegalChars.length; j++ )
			if ( str.indexOf( illegalChars[j] ) >=0 )
				return true;
				
		return false;
		}

	private static String escapeString( String str, char[] illegalChars, String[] escapes )
		{
		if ( !needsEscaping( str, illegalChars ) )
			return str;
		
		StringBuffer output = new StringBuffer( ((str.length() * 10) / 16)+1 );
		int i, j;
		
		for ( i = 0; i<str.length(); i++ )
			{
			for ( j=0; j< illegalChars.length; j++ )
				{
				if ( illegalChars[j] == str.charAt( i ) )
					break;
				}
				
			if ( j<illegalChars.length )
				output.append( escapes[j] );
			else
				output.append( str.charAt( i ) );
			}
			
		return output.toString();
		}
		

	public static String toPCData( String str )
		{
		return escapeString( str, illegalPCDataChars, pcDataEscapes );
		}
		
	public static String toAttribute( String str )
		{
		return escapeString( str, illegalAttributeChars, attributeEscapes );
		}

    /**
     * Ordered list of {@link org.xml.sax.XMLReader} implementations. This list
     * is used by the method {@link #getXMLReader()}. The order is as follows:
     * <ol>
     * <li>{@link org.apache.xerces.parsers.SAXParser}
     * <li>{@link com.sun.org.apache.xerces.internal.parsers.SAXParser}
     * <li>{@link org.apache.crimson.parser.XMLReaderImpl}
     * </ol>
     * @see #getXMLReader()
     */
    static final String[] XML_READERS = {"org.apache.xerces.parsers.SAXParser",
        "com.sun.org.apache.xerces.internal.parsers.SAXParser",
        "org.apache.crimson.parser.XMLReaderImpl"};
    
    /**
     * Get the class name of an {@link org.xml.sax.XMLReader} implementation.
     * This method will try to find a suitable implementation that is available
     * to the runtime.
     * @return the class name of an available {@link org.xml.sax.XMLReader}
     * implementation.
     * @see #XML_READERS
     */
    public static final String getXMLReader()
    	{   
        /*
         * NOTE: currently known values (24/11/04):
         * 
         * [A] org.apache.xerces.parsers.SAXParser
         * [B] com.sun.org.apache.xerces.internal.parsers.SAXParser
         * [C] org.apache.crimson.parser.XMLReaderImpl
         * 
         *          Sun     Blackdown       IBM
         * 1.4.2     C          C            A      
         * 1.5.0     B          ?            ?
         * 
         * If [A] is not present in the JDK, it may will be in the application
         * server, e.g. Tomcat. Plus, it is the parser that users will most
         * wish to override with over time, even the one in JDK 1.5.        
         */
        for (int i = 0; i < XML_READERS.length; i++)
            {   
            try
                {
                return Class.forName( XML_READERS[i] ).getName();
                }
            catch ( ClassNotFoundException e )
                {
                continue;
                }
            }
        return null; // if no match found:
    	}
	}
