/*
 * (c) Copyright IBM Corp 2002, 2005 
 */

package edu.uga.cs.lsdis.meteors.wadls.util.xml;

import javax.wadls.Application;
import javax.wadls.WADLSException;
import javax.xml.XMLConstants;
import javax.xml.namespace.*;

import org.w3c.dom.*;

public class QNameUtils
{
  public static boolean matches(QName qname, Node node)
  {
    return (node != null && qname.equals(newQName(node)));
  }

  public static QName newQName(Node node)
  {
    if (node != null)
    {
     // System.out.println("node:namespace uri is " + node.getNamespaceURI());
      QName q = new QName(node.getNamespaceURI(), node.getLocalName());
      //System.out.println("Qname generated is "+q);
      return q;
      
    }
    else
    {
      return new QName(null, null);
    }
  }
  
  public static QName getQName(String prefixedValue,
						        Element contextEl)
  								throws WADLSException{
	int    index        = prefixedValue.indexOf(':');
	String prefix       = (index != -1)
								? prefixedValue.substring(0, index)
								: null;
	String localPart    = prefixedValue.substring(index + 1);
	String namespaceURI = DOMUtils.getNamespaceURIFromPrefix(contextEl, prefix);

	if (namespaceURI != null)
		return new QName(namespaceURI, localPart);
	else{
		String faultCode = (prefix == null)
		  ? WADLSException.NO_PREFIX_SPECIFIED
		  : WADLSException.UNBOUND_PREFIX;
	
		WADLSException wsdlExc = new WADLSException(faultCode,
	                         "Unable to determine " +
	                         "namespace of '" +
	                         prefixedValue + "'.");
	
		wsdlExc.setLocation(XPathUtils.getXPathExprFromNode(contextEl));
	
		throw wsdlExc;
	}
  }  
  
	/**
	 * Parse a string, return a QName. 
	 * The String can be only in the form of "{namespace}localpart"
	 * @param qNameAsString
	 * @return A QName by parsing the given string.
	 */
	public static QName generateQName(String qNameAsString){
		return generateQName(qNameAsString, null);
	}
	
	/**
	 * Parse a string, return a QName. 
	 * The String may be in the form of "prefix:localpart" or "{namespace}localpart"
	 * @param qNameAsString
	 * @param wsdlDef Wsdl definition for the purpose of getting URI from prefix, and vice versa.
	 * @return A QName by paring the given string.
	 */
	public static QName generateQName(String qNameAsString, Application wadlApp){
		String nsURI = null;
		String prefix = null;
		String localPart = null;
	
		if (qNameAsString == null) {
			throw new IllegalArgumentException("cannot create QName from \"null\" or \"\" String");
		}

		if (qNameAsString.charAt(0) == '{') {	//namespace + localpart
			int endOfNamespaceURI = qNameAsString.indexOf('}');
	        if (endOfNamespaceURI == -1) {
	            throw new IllegalArgumentException(
	                "cannot create QName from \""
	                    + qNameAsString
	                    + "\", missing closing \"}\"");
	        }
	        else{
	        	nsURI = qNameAsString.substring(1, endOfNamespaceURI);
	        	//get prefix from wsdls definition
	        	if (wadlApp != null)
	        		prefix = wadlApp.getPrefix(nsURI);
	        	localPart = qNameAsString.substring(endOfNamespaceURI + 1);
	        	return new QName(nsURI, localPart, nsURI);
	        }

		}
		else{
		    int endOfPrefix = qNameAsString.indexOf(':');	//try prefix
		    
			if (endOfPrefix == -1){		//localpart only, use tagetNamespace from wsdls definition
				if (wadlApp != null)
		    		nsURI = wadlApp.getTargetNamespace();
		    	else
		    		nsURI = XMLConstants.NULL_NS_URI;
				return new QName(nsURI, qNameAsString);
			}
			else if (wadlApp != null){		//prefix + localpart
			    prefix = qNameAsString.substring(1, endOfPrefix);
				nsURI = wadlApp.getNamespace(prefix);
				localPart = qNameAsString.substring(endOfPrefix + 1);
				return new QName(nsURI, localPart, nsURI);
			}
			else
	            throw new IllegalArgumentException(
		                "cannot create QName from \""
		                    + qNameAsString
		                    + "\", no URI and no wsdl definition is given");
		}
	}
}