<commit_before>/*
 * eXist Open Source Native XML Database
 * Copyright (C) 2001-2007 The eXist Project
 * http://exist-db.org
 *
 * This program 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
 * of the License, or (at your option) any later version.
 *  
 * This program 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 program; if not, write to the Free Software Foundation
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *  
 *  $Id$
 */
package org.exist.dom;

import org.exist.storage.ElementValue;
import org.exist.util.XMLChar;
import org.exist.xquery.Constants;
import org.exist.xquery.XPathException;
import org.exist.xquery.XQueryContext;

/**
 * Represents a QName, consisting of a local name, a namespace URI and a prefix.
 * 
 * @author Wolfgang <<EMAIL>>
 */
public class QName implements Comparable {

	/*
    public final static QName DOCUMENT_QNAME = new QName("#document", "", null);
	public final static QName TEXT_QNAME = new QName("#text", "", null);
	public final static QName COMMENT_QNAME = new QName("#comment", "", null);
	public final static QName DOCTYPE_QNAME = new QName("#doctype", "", null);
	*/ 
	public final static QName EMPTY_QNAME = new QName("", "", null);
    public final static QName DOCUMENT_QNAME = EMPTY_QNAME;
	public final static QName TEXT_QNAME = EMPTY_QNAME;
	public final static QName COMMENT_QNAME = EMPTY_QNAME;
	public final static QName DOCTYPE_QNAME = EMPTY_QNAME; 
	
	private String localName_ = null;
	private String namespaceURI_ = null;
	private String prefix_ = null;
	//TODO ; use ElementValue.INKNOWN and type explicitely ?
    private byte nameType_ = ElementValue.ELEMENT;

	/**
	 * Construct a QName. The prefix might be null for the default namespace or if no prefix 
	 * has been defined for the QName. The namespace URI should be set to the empty 
	 * string, if no namespace URI is defined.
	 * 
	 * @param localName
	 * @param namespaceURI
	 * @param prefix
	 */
	public QName(String localName, String namespaceURI, String prefix) {
		localName_ = localName;
		if(namespaceURI == null)
		    namespaceURI_ = "";
		else
		    namespaceURI_ = namespaceURI;
		prefix_ = prefix;
	}

	public QName(String localName, String namespaceURI) {
		this(localName, namespaceURI, null);
	}

	public QName(QName other) {
	    this(other.localName_, other.namespaceURI_, other.prefix_);
	    nameType_ = other.nameType_;
	}
	
	public QName(String name) {
		this(extractLocalName(name), null, extractPrefix(name));
	}
	
	public String getLocalName() {
		return localName_;
	}

	public void setLocalName(String name) {
		localName_ = name;
	}

	public String getNamespaceURI() {
		return namespaceURI_;
	}

	public void setNamespaceURI(String namespaceURI) {
		namespaceURI_ = namespaceURI;
	}

	/**
	 * Returns true if the QName defines a namespace URI.
	 * 
	 */
	public boolean needsNamespaceDecl() {
		return namespaceURI_ != null && namespaceURI_.length() > 0;
	}

	public String getPrefix() {
		return prefix_;
	}

	public void setPrefix(String prefix) {
		prefix_ = prefix;
	}

	public void setNameType(byte type) {
		nameType_ = type;
	}

	public byte getNameType() {
		return nameType_;
	}

	public String getStringValue() {
		if (prefix_ != null && prefix_.length() > 0)
			return prefix_ + ':' + localName_;
		else 
			return localName_;
	}

	/**
	 * (deprecated) : use for debugging purpose only,
	 * use getStringValue() for production
	 */
	public String toString() {
		//TODO : remove this copy of getStringValue()
		return getStringValue();
		//TODO : replace by something like this
		/*
		if (prefix_ != null && prefix_.length() > 0)
			return prefix_ + ':' + localName_;
		if (needsNamespaceDecl()) {
			if (prefix_ != null && prefix_.length() > 0)
				return "{" + namespaceURI_ + "}" + prefix_ + ':' + localName_;
			return "{" + namespaceURI_ + "}" + localName_;
		} else 
			return localName_;
		*/
	}

	/**
	 * Compares two QNames by comparing namespace URI
	 * and local names. The prefixes are not relevant.
	 * 
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	public int compareTo(Object o) {
		QName other = (QName) o;
		if(nameType_ != other.nameType_) {
			return nameType_ < other.nameType_ ? Constants.INFERIOR : Constants.SUPERIOR;
		}
		int c;
		if (namespaceURI_ == null)
			c = other.namespaceURI_ == null ? Constants.EQUAL : Constants.INFERIOR;
		else if (other.namespaceURI_ == null)
			c = Constants.SUPERIOR;
		else
			c = namespaceURI_.compareTo(other.namespaceURI_);
		return c == Constants.EQUAL ? localName_.compareTo(other.localName_) : c;
	}
	
	/** 
	 * Checks two QNames for equality. Two QNames are equal
	 * if their namespace URIs, local names and prefixes are equal.
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	public boolean equals(Object obj) {
		int cmp = compareTo(obj);
		if(cmp != 0)
			return false;
		QName other = (QName) obj;
		if(prefix_ == null)
			return other.prefix_ == null ? true : false;
		else if(other.prefix_ == null)
			return false;
		else
			return prefix_.equals(other.prefix_);
	}
	
	public boolean equalsSimple(QName other) {
        int c;
        if (namespaceURI_ == null)
            c = other.namespaceURI_ == null ? Constants.EQUAL : Constants.INFERIOR;
        else if (other.namespaceURI_ == null)
            c = Constants.SUPERIOR;
        else
            c = namespaceURI_.compareTo(other.namespaceURI_);
        if (c == Constants.EQUAL)
            return localName_.equals(other.localName_);
        return false;
    }
    
	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	public int hashCode() {
		int h = nameType_ + 31 + localName_.hashCode();
		h += 31*h + (namespaceURI_ == null ? 1 : namespaceURI_.hashCode());
		h += 31*h + (prefix_ == null ? 1 : prefix_.hashCode());
		return h;
	}

    public javax.xml.namespace.QName toJavaQName() {
        return new javax.xml.namespace.QName(namespaceURI_ == null ? "" : namespaceURI_, localName_,
                prefix_ == null ? "" : prefix_);
    }
    
    /**
	 * Extract the prefix from a QName string.
	 *  
	 * @param qname
	 * @return the prefix, if found
	 * @exception IllegalArgumentException if the qname starts with a leading :
	 */
	public static String extractPrefix(String qname) 
    throws IllegalArgumentException {
		int p = qname.indexOf(':');
		if (p == Constants.STRING_NOT_FOUND)
			return null;
		if (p == 0)
			throw new IllegalArgumentException("Illegal QName: starts with a :");
        // fixme! Should we not use isQName() here? /ljo
        if (Character.isDigit(qname.substring(0,1).charAt(0))) {
            throw new IllegalArgumentException("Illegal QName: starts with a digit");
        }
		return qname.substring(0, p);
	}

	/**
	 * Extract the local name from a QName string.
	 * 
	 * @param qname
	 * @exception IllegalArgumentException if the qname starts with a leading : or ends with a :
	 */
	public static String extractLocalName(String qname) 
        throws IllegalArgumentException {
		int p = qname.indexOf(':');
		if (p == Constants.STRING_NOT_FOUND)
			return qname;
		if (p == 0)
			throw new IllegalArgumentException("Illegal QName: starts with a :");
		if (p == qname.length())
			throw new IllegalArgumentException("Illegal QName: ends with a :");
        if (!isQName(qname)) {
			throw new IllegalArgumentException("Illegal QName: not a valid local name.");
        }

		return qname.substring(p + 1);
	}

	/**
	 * Parses the given string into a QName. The method uses context to look up
	 * a namespace URI for an existing prefix.
	 * 
	 * @param context
	 * @param qname
	 * @param defaultNS the default namespace to use if no namespace prefix is present.
     * @return QName
	 * @exception IllegalArgumentException if no namespace URI is mapped to the prefix
	 */
	public static QName parse(XQueryContext context, String qname, String defaultNS)
		throws XPathException {
		String prefix = extractPrefix(qname);
		String namespaceURI;
		if (prefix != null) {
			namespaceURI = context.getURIForPrefix(prefix);
			if (namespaceURI == null)
				throw new XPathException("XPST0081: No namespace defined for prefix " + prefix);
		} else
			namespaceURI = defaultNS;
		if (namespaceURI == null)
			namespaceURI = "";
		return new QName(extractLocalName(qname), namespaceURI, prefix);
	}
	
	/**
	 * Parses the given string into a QName. The method uses context to look up
	 * a namespace URI for an existing prefix.
	 * 
	 * This method uses the default element namespace for qnames without prefix.
	 * 
	 * @param context
	 * @param qname
	 * @exception IllegalArgumentException if no namespace URI is mapped to the prefix
	 */
	public static QName parse(XQueryContext context, String qname)
		throws XPathException {
		return parse(context, qname, context.getURIForPrefix(""));
	}
	
	public final static boolean isQName(String name) {
		int colon = name.indexOf(':');
		if (colon == Constants.STRING_NOT_FOUND)
			return XMLChar.isValidNCName(name);
		if (colon == 0 || colon == name.length() - 1)
			return false;
		if (!XMLChar.isValidNCName(name.substring(0, colon)))
			return false;
		if (!XMLChar.isValidNCName(name.substring(colon + 1)))
			return false;
		return true;
	}
}
<commit_msg>[ignore] tidy up eXist (generics)<commit_after>/*
 * eXist Open Source Native XML Database
 * Copyright (C) 2001-2007 The eXist Project
 * http://exist-db.org
 *
 * This program 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
 * of the License, or (at your option) any later version.
 *  
 * This program 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 program; if not, write to the Free Software Foundation
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *  
 *  $Id$
 */
package org.exist.dom;

import org.exist.storage.ElementValue;
import org.exist.util.XMLChar;
import org.exist.xquery.Constants;
import org.exist.xquery.XPathException;
import org.exist.xquery.XQueryContext;

/**
 * Represents a QName, consisting of a local name, a namespace URI and a prefix.
 * 
 * @author Wolfgang <<EMAIL>>
 */
public class QName implements Comparable<QName> {

	/*
    public final static QName DOCUMENT_QNAME = new QName("#document", "", null);
	public final static QName TEXT_QNAME = new QName("#text", "", null);
	public final static QName COMMENT_QNAME = new QName("#comment", "", null);
	public final static QName DOCTYPE_QNAME = new QName("#doctype", "", null);
	*/ 
	public final static QName EMPTY_QNAME = new QName("", "", null);
    public final static QName DOCUMENT_QNAME = EMPTY_QNAME;
	public final static QName TEXT_QNAME = EMPTY_QNAME;
	public final static QName COMMENT_QNAME = EMPTY_QNAME;
	public final static QName DOCTYPE_QNAME = EMPTY_QNAME; 
	
	private String localName_ = null;
	private String namespaceURI_ = null;
	private String prefix_ = null;
	//TODO ; use ElementValue.INKNOWN and type explicitely ?
    private byte nameType_ = ElementValue.ELEMENT;

	/**
	 * Construct a QName. The prefix might be null for the default namespace or if no prefix 
	 * has been defined for the QName. The namespace URI should be set to the empty 
	 * string, if no namespace URI is defined.
	 * 
	 * @param localName
	 * @param namespaceURI
	 * @param prefix
	 */
	public QName(String localName, String namespaceURI, String prefix) {
		localName_ = localName;
		if(namespaceURI == null)
		    namespaceURI_ = "";
		else
		    namespaceURI_ = namespaceURI;
		prefix_ = prefix;
	}

	public QName(String localName, String namespaceURI) {
		this(localName, namespaceURI, null);
	}

	public QName(QName other) {
	    this(other.localName_, other.namespaceURI_, other.prefix_);
	    nameType_ = other.nameType_;
	}
	
	public QName(String name) {
		this(extractLocalName(name), null, extractPrefix(name));
	}
	
	public String getLocalName() {
		return localName_;
	}

	public void setLocalName(String name) {
		localName_ = name;
	}

	public String getNamespaceURI() {
		return namespaceURI_;
	}

	public void setNamespaceURI(String namespaceURI) {
		namespaceURI_ = namespaceURI;
	}

	/**
	 * Returns true if the QName defines a namespace URI.
	 * 
	 */
	public boolean needsNamespaceDecl() {
		return namespaceURI_ != null && namespaceURI_.length() > 0;
	}

	public String getPrefix() {
		return prefix_;
	}

	public void setPrefix(String prefix) {
		prefix_ = prefix;
	}

	public void setNameType(byte type) {
		nameType_ = type;
	}

	public byte getNameType() {
		return nameType_;
	}

	public String getStringValue() {
		if (prefix_ != null && prefix_.length() > 0)
			return prefix_ + ':' + localName_;
		else 
			return localName_;
	}

	/**
	 * (deprecated) : use for debugging purpose only,
	 * use getStringValue() for production
	 */
	public String toString() {
		//TODO : remove this copy of getStringValue()
		return getStringValue();
		//TODO : replace by something like this
		/*
		if (prefix_ != null && prefix_.length() > 0)
			return prefix_ + ':' + localName_;
		if (needsNamespaceDecl()) {
			if (prefix_ != null && prefix_.length() > 0)
				return "{" + namespaceURI_ + "}" + prefix_ + ':' + localName_;
			return "{" + namespaceURI_ + "}" + localName_;
		} else 
			return localName_;
		*/
	}

	/**
	 * Compares two QNames by comparing namespace URI
	 * and local names. The prefixes are not relevant.
	 * 
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	public int compareTo(QName other) {
		if(nameType_ != other.nameType_) {
			return nameType_ < other.nameType_ ? Constants.INFERIOR : Constants.SUPERIOR;
		}
		int c;
		if (namespaceURI_ == null)
			c = other.namespaceURI_ == null ? Constants.EQUAL : Constants.INFERIOR;
		else if (other.namespaceURI_ == null)
			c = Constants.SUPERIOR;
		else
			c = namespaceURI_.compareTo(other.namespaceURI_);
		return c == Constants.EQUAL ? localName_.compareTo(other.localName_) : c;
	}
	
	/** 
	 * Checks two QNames for equality. Two QNames are equal
	 * if their namespace URIs, local names and prefixes are equal.
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	public boolean equals(Object obj) {
		QName other = (QName) obj;

		int cmp = compareTo(other);
		if(cmp != 0)
			return false;
		
		if(prefix_ == null)
			return other.prefix_ == null ? true : false;
		else if(other.prefix_ == null)
			return false;
		else
			return prefix_.equals(other.prefix_);
	}
	
	public boolean equalsSimple(QName other) {
        int c;
        if (namespaceURI_ == null)
            c = other.namespaceURI_ == null ? Constants.EQUAL : Constants.INFERIOR;
        else if (other.namespaceURI_ == null)
            c = Constants.SUPERIOR;
        else
            c = namespaceURI_.compareTo(other.namespaceURI_);
        if (c == Constants.EQUAL)
            return localName_.equals(other.localName_);
        return false;
    }
    
	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	public int hashCode() {
		int h = nameType_ + 31 + localName_.hashCode();
		h += 31*h + (namespaceURI_ == null ? 1 : namespaceURI_.hashCode());
		h += 31*h + (prefix_ == null ? 1 : prefix_.hashCode());
		return h;
	}

    public javax.xml.namespace.QName toJavaQName() {
        return new javax.xml.namespace.QName(namespaceURI_ == null ? "" : namespaceURI_, localName_,
                prefix_ == null ? "" : prefix_);
    }
    
    /**
	 * Extract the prefix from a QName string.
	 *  
	 * @param qname
	 * @return the prefix, if found
	 * @exception IllegalArgumentException if the qname starts with a leading :
	 */
	public static String extractPrefix(String qname) 
    throws IllegalArgumentException {
		int p = qname.indexOf(':');
		if (p == Constants.STRING_NOT_FOUND)
			return null;
		if (p == 0)
			throw new IllegalArgumentException("Illegal QName: starts with a :");
        // fixme! Should we not use isQName() here? /ljo
        if (Character.isDigit(qname.substring(0,1).charAt(0))) {
            throw new IllegalArgumentException("Illegal QName: starts with a digit");
        }
		return qname.substring(0, p);
	}

	/**
	 * Extract the local name from a QName string.
	 * 
	 * @param qname
	 * @exception IllegalArgumentException if the qname starts with a leading : or ends with a :
	 */
	public static String extractLocalName(String qname) 
        throws IllegalArgumentException {
		int p = qname.indexOf(':');
		if (p == Constants.STRING_NOT_FOUND)
			return qname;
		if (p == 0)
			throw new IllegalArgumentException("Illegal QName: starts with a :");
		if (p == qname.length())
			throw new IllegalArgumentException("Illegal QName: ends with a :");
        if (!isQName(qname)) {
			throw new IllegalArgumentException("Illegal QName: not a valid local name.");
        }

		return qname.substring(p + 1);
	}

	/**
	 * Parses the given string into a QName. The method uses context to look up
	 * a namespace URI for an existing prefix.
	 * 
	 * @param context
	 * @param qname
	 * @param defaultNS the default namespace to use if no namespace prefix is present.
     * @return QName
	 * @exception IllegalArgumentException if no namespace URI is mapped to the prefix
	 */
	public static QName parse(XQueryContext context, String qname, String defaultNS)
		throws XPathException {
		String prefix = extractPrefix(qname);
		String namespaceURI;
		if (prefix != null) {
			namespaceURI = context.getURIForPrefix(prefix);
			if (namespaceURI == null)
				throw new XPathException("XPST0081: No namespace defined for prefix " + prefix);
		} else
			namespaceURI = defaultNS;
		if (namespaceURI == null)
			namespaceURI = "";
		return new QName(extractLocalName(qname), namespaceURI, prefix);
	}
	
	/**
	 * Parses the given string into a QName. The method uses context to look up
	 * a namespace URI for an existing prefix.
	 * 
	 * This method uses the default element namespace for qnames without prefix.
	 * 
	 * @param context
	 * @param qname
	 * @exception IllegalArgumentException if no namespace URI is mapped to the prefix
	 */
	public static QName parse(XQueryContext context, String qname)
		throws XPathException {
		return parse(context, qname, context.getURIForPrefix(""));
	}
	
	public final static boolean isQName(String name) {
		int colon = name.indexOf(':');
		if (colon == Constants.STRING_NOT_FOUND)
			return XMLChar.isValidNCName(name);
		if (colon == 0 || colon == name.length() - 1)
			return false;
		if (!XMLChar.isValidNCName(name.substring(0, colon)))
			return false;
		if (!XMLChar.isValidNCName(name.substring(colon + 1)))
			return false;
		return true;
	}
}

{'fraction_non_alphanumeric': 0.10453720508166969, 'fraction_numerical': 0.004977962146746176, 'mean_word_length': 3.4335632183908045, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5033273', 'n_tokens_mistral': 6285, 'n_tokens_neox': 5698, 'n_words': 1932}