/*******************************************************************************
 * Copyright (c) 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.bpel.ui.util;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

/**
 * Utility class for calculating default namespaces based on namespace templates from the preference store. 
 */
public class NamespaceUtils
{
    protected static char NS_SEPARATOR = '/'; 
    protected static char PACKAGE_SEPARATOR = '.'; 
    protected static String HEX_PREFIX = "%"; //$NON-NLS-1$
    protected static String CHARSET_UTF8 = "UTF-8"; //$NON-NLS-1$
    
    // unsafe characters
    public static final String SPACE = " "; //$NON-NLS-1$
    public static final String DOUBLE_QUOTE = "\""; //$NON-NLS-1$
    public static final String LESS_THAN = "<"; //$NON-NLS-1$
    public static final String GREATER_THAN = ">"; //$NON-NLS-1$
    public static final String POUND = "#"; //$NON-NLS-1$
    public static final String PERCENT = "%"; //$NON-NLS-1$
    public static final String LEFT_CURLY = "{"; //$NON-NLS-1$
    public static final String RIGHT_CURLY = "}"; //$NON-NLS-1$
    public static final String PIPE = "|"; //$NON-NLS-1$
    public static final String BACKSLASH = "\\"; //$NON-NLS-1$
    public static final String CARET = "^"; //$NON-NLS-1$
    public static final String TILDE = "~"; //$NON-NLS-1$
    public static final String LEFT_SQUARE = "["; //$NON-NLS-1$
    public static final String RIGHT_SQUARE = "]"; //$NON-NLS-1$
    public static final String GRAVE = "`"; //$NON-NLS-1$
    
    // escaped characters
    public static final String ESCAPED_SPACE = "%20"; //$NON-NLS-1$
    public static final String ESCAPED_DOUBLE_QUOTE = "%22"; //$NON-NLS-1$
    public static final String ESCAPED_LESS_THAN = "%3C"; //$NON-NLS-1$
    public static final String ESCAPED_GREATER_THAN = "%3E"; //$NON-NLS-1$
    public static final String ESCAPED_POUND = "%23"; //$NON-NLS-1$
    public static final String ESCAPED_PERCENT = "%25"; //$NON-NLS-1$
    public static final String ESCAPED_LEFT_CURLY = "%7B"; //$NON-NLS-1$
    public static final String ESCAPED_RIGHT_CURLY = "%7D"; //$NON-NLS-1$
    public static final String ESCAPED_PIPE = "%7C"; //$NON-NLS-1$
    public static final String ESCAPED_BACKSLASH = "%5C"; //$NON-NLS-1$
    public static final String ESCAPED_CARET = "%5E"; //$NON-NLS-1$
    public static final String ESCAPED_TILDE = "%7E"; //$NON-NLS-1$
    public static final String ESCAPED_LEFT_SQUARE = "%5B"; //$NON-NLS-1$
    public static final String ESCAPED_RIGHT_SQUARE = "%5D"; //$NON-NLS-1$
    public static final String ESCAPED_GRAVE = "%60"; //$NON-NLS-1$
    
    protected static HashMap fCharToEscaped = new HashMap(15);
    static
    {
        fCharToEscaped.put(SPACE, ESCAPED_SPACE);
        fCharToEscaped.put(DOUBLE_QUOTE, ESCAPED_DOUBLE_QUOTE);
        fCharToEscaped.put(LESS_THAN, ESCAPED_LESS_THAN);
        fCharToEscaped.put(GREATER_THAN, ESCAPED_GREATER_THAN);
        fCharToEscaped.put(POUND, ESCAPED_POUND);
        fCharToEscaped.put(PERCENT, ESCAPED_PERCENT);
        fCharToEscaped.put(LEFT_CURLY, ESCAPED_LEFT_CURLY);
        fCharToEscaped.put(RIGHT_CURLY, ESCAPED_RIGHT_CURLY);
        fCharToEscaped.put(PIPE, ESCAPED_PIPE);
        fCharToEscaped.put(BACKSLASH, ESCAPED_BACKSLASH);
        fCharToEscaped.put(CARET, ESCAPED_CARET);
        fCharToEscaped.put(TILDE, ESCAPED_TILDE);
        fCharToEscaped.put(LEFT_SQUARE, ESCAPED_LEFT_SQUARE);
        fCharToEscaped.put(RIGHT_SQUARE, ESCAPED_RIGHT_SQUARE);
        fCharToEscaped.put(GRAVE, ESCAPED_GRAVE);
    }
        
    /**
     * Converts a UTF-8 escaped string back into a unicode string.  This method undoes the
     * operation performed in convertNamespaceToUri.
     * 
     * @param uri
     * @return - a unicode representation of the given UTF-8 escaped string.
     * @see convertNamespaceToUri
     */
    public static String convertUriToNamespace(String uri)
    {
        if (uri==null || uri.length()<1)
            return null;
        
        String namespace = uri;
        
        int prevIndex = 0; // index of the previously found %, plus 1
        int contiguousIndex = 0; // index of next contiguous hex number
        Byte hexByte = null;
        ArrayList contiguousBytes = null;
        String hexChunk = null;
        
        for (int i=uri.indexOf(HEX_PREFIX); i>=0; i=uri.indexOf(HEX_PREFIX, prevIndex))
        {
            // get hex byte
            hexByte = getHexByte(uri, i);
            contiguousBytes = new ArrayList();
            contiguousIndex = i;
            hexChunk = "";
            
            prevIndex = contiguousIndex+1; // +1 for %
            
            // get contiguous bytes
            while (hexByte!=null)
            {
                contiguousBytes.add(hexByte);
                
                hexChunk += uri.substring(contiguousIndex, contiguousIndex+3);
                prevIndex = contiguousIndex+1; // +1 for %
                                
                hexByte = getHexByte(uri, contiguousIndex+3); // 2 for current hex num, 1 for %
                
                contiguousIndex += 3;
            }
            prevIndex = prevIndex>=uri.length()?uri.length()-1:prevIndex;
            
            if (contiguousBytes.size()<=0)
                continue;
            
            // convert hex string to bytes
            byte[] cbytes = new byte[contiguousBytes.size()];
            for (int j=0; j<cbytes.length; j++)
                cbytes[j] = ((Byte)contiguousBytes.get(j)).byteValue();
            
            try
            {
                // convert bytes to unicode
                String unicode = new String(cbytes, CHARSET_UTF8);
                
                // now find the hex string in the namespace and replace it with the proper unicode
                int beginIndex = namespace.indexOf(hexChunk);
                int endIndex = beginIndex+hexChunk.length();
                int lastIndex = namespace.length();
                endIndex = endIndex>lastIndex?lastIndex:endIndex;
                
                namespace = namespace.substring(0, beginIndex) + unicode + namespace.substring(endIndex);
            }
            catch(UnsupportedEncodingException e)
            {
                // this should never happen -- log anyway
            	// JM: Commented out:
                //ModelUtilPlugin.logWarning(e, e.getMessage());
            }
        }   
        
        return namespace;
    }
    
    /**
     * Returns the Byte value of the hex string at position index in string uri.
     * 
     * @param uri
     * @param index
     * @return null if characters at position index aren't of the form %HH
     */
    protected static Byte getHexByte(String uri, int index)
    {
        if (uri==null || uri.length()<1)
            return null;
        
        if (index>=uri.length())
            return null;
        
        // first character must be %
        if (!HEX_PREFIX.equals(String.valueOf(uri.charAt(index))))
            return null;
        
        // hex string is two digits
        int lastIndex = uri.length();
        int endIndex = index+3;
        
        // ensure endIndex doesn't extend the length of the string
        if (endIndex>lastIndex)
            endIndex = lastIndex;
        
        String hexString = uri.substring(index+1, endIndex);
        byte hexByte = 0;
        
        try
        {
            hexByte = Integer.valueOf(hexString, 16).byteValue();
        }
        catch (NumberFormatException e)
        {
            // not a hex number, return
            return null;
        }
        
        return Byte.valueOf( hexByte );
    }

    /**
     * Convert a string intended to be a target namespace, i.e. any string typed with xsd:anyURI.  According to the
     * XSD spec, any string typed with xsd:anyURI cannot contain any characters outside the US-ASCII character set.
     * These characters must be escaped in the UTF-8 hex notation, %HH.  This method also escapes "unwise" characters
     * by calling escapeUnsafeCharacters first.
     * 
     * Note that models saving to an XMLResource don't need this method since the XMLResource saves/loads using a
     * Xerces parser which automatically does this.  Models using the SSE parser for saving/loading need this as the
     * SSE parser doesn't do this automatically.
     * 
     * @param namespace
     * @return - UTF-8 character escaped string of any characters outside the US-ASCII character set.
     * @see convertUriToNamespace
     * @see escapeUnsafeCharacters
     */
    public static String convertNamespaceToUri(String namespace)
    {
        return convertNamespaceToUri(namespace, true);
    }
    
    /**
     * Convert a string intended to be a target namespace, i.e. any string typed with xsd:anyURI.  According to the
     * XSD spec, any string typed with xsd:anyURI cannot contain any characters outside the US-ASCII character set.
     * These characters must be escaped in the UTF-8 hex notation, %HH.  This method also escapes "unwise" characters
     * (except for '%' if escapePercent is set to false) by calling escapeUnsafeCharacters first.  Setting escapePercent
     * to false means you can call this method on previously converted strings without the '%' from '%HH' being converted
     * again.
     * 
     * Note that models saving to an XMLResource don't need this method since the XMLResource saves/loads using a
     * Xerces parser which automatically does this.  Models using the SSE parser for saving/loading need this as the
     * SSE parser doesn't do this automatically.
     * 
     * @param namespace
     * @param escapePercent - escapes '%' to it's hex value if true, ignores it otherwise.
     * @return - UTF-8 character escaped string of any characters outside the US-ASCII character set.
     * @see convertUriToNamespace
     * @see escapeUnsafeCharacters
     */
    public static String convertNamespaceToUri(String namespace, boolean escapePercent)
    {
        if (namespace==null || namespace.length()<1)
            return null;
        
        StringBuffer buffer = new StringBuffer();
        
        // first escape "unsafe" characters 
        namespace = escapeUnsafeCharacters(namespace, escapePercent);
        
        char[] nsChars = namespace.toCharArray();
        byte[] utf8 = null;
        
        try
        {
	        for (int i=0; i<nsChars.length; i++)
	        {
	            // Convert all characters outside the US-ASCII range (>127) to
	            // UTF-8 bytes as dictated by the anyURI definition in the
	            // XSD spec.
	            if (nsChars[i]>127)
	            {
	                utf8 = String.valueOf(nsChars[i]).getBytes(CHARSET_UTF8);
	                for (int j=0; j<utf8.length; j++)
	                {
	                    buffer.append(HEX_PREFIX);
	                    
	                    // 2-digit hex value
	                    buffer.append(Integer.toString(( utf8[j] & 0xff ), 16).toUpperCase());
	                }
	            }
	            else
	            {
	                buffer.append(nsChars[i]);
	            }
	        }
        }
        catch (UnsupportedEncodingException e)
        {
            // this should never happen -- log anyway
        	// JM commented out:
            //ModelUtilPlugin.logWarning(e, e.getMessage());
        }
        
        return buffer.toString();
    }
    
    /**
     * Escapes the "delim" and "unwise" characters as specified by rfc2396.  Also escapes the tilde (~) as this
     * also seems to cause problems with the XSD validator.  The characters are escaped using the UTF-8 hex 
     * notation, %HH.
     * 
     * To do undo this operation, call convertUriToNamespace
     * 
     * @param anyURI
     * @return
     * @see this is equivalent to escapeUnsafeCharacters(anyURI, true)
     */
    public static String escapeUnsafeCharacters(String anyURI)
    {
        return escapeUnsafeCharacters(anyURI, true);
    }

    /**
     * Escapes the "delim" and "unwise" characters as specified by rfc2396.  Also escapes the tilde (~) as this
     * also seems to cause problems with the XSD validator.  The characters are escaped using the UTF-8 hex 
     * notation, %HH.
     * 
     * To do undo this operation, call convertUriToNamespace
     * 
     * @param anyURI
     * @param escapePercent - escapes '%' to it's hex value if true, ignores it otherwise.
     * @return
     */
    public static String escapeUnsafeCharacters(String anyURI, boolean escapePercent)
    {
        if (anyURI==null)
            return null;

        // must escape % first since our escapes have % in them.
        if (escapePercent)
            anyURI = anyURI.replaceAll("\\"+PERCENT, (String)fCharToEscaped.get(PERCENT)); //$NON-NLS-1$
        
        String key = null;
        
        // escape all other characters except %
        for (Iterator i = fCharToEscaped.keySet().iterator(); i.hasNext();)
        {
            key = (String)i.next();
            if (key.equals(PERCENT))
                continue;
            
            anyURI = anyURI.replaceAll("\\"+key, (String)fCharToEscaped.get(key)); //$NON-NLS-1$
        }

        return anyURI;
    }

    /**
     * Returns the "delim" and "unwise" characters as specified by rfc2396 if found.  Also returns the tilde (~) as this
     * also seems to cause problems with the XSD validator.  Returns null if no unsafe characters found. 
     *
     * @param anyURI
     * @param spaceUnsafe - if true, treats a space as an "unwise" character.
     * @return null if no unsafe characters found,
     * 		   the unsafe character string otherwise
     */
    public static String containsUnsafeCharacter(String anyURI, boolean spaceUnsafe)
    {
        if (anyURI==null)
            return null;
        
        String key = null;
        
        for (Iterator i = fCharToEscaped.keySet().iterator(); i.hasNext();)
        {
            key = (String)i.next();
            
            if (!spaceUnsafe && SPACE.equals(key))
                continue;
            
            if (anyURI.indexOf(key)>=0)
                return key;
        }
        
        // no unsafe characters
        return null;
    }
}
