<commit_before>/*
 *  eXist Open Source Native XML Database
 *  Copyright (C) 2001-04 <NAME>
 *  <EMAIL>
 *  http://exist.sourceforge.net
 *
 *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
 * 
 *  $Id$
 */
package org.exist.xquery.functions;

import org.exist.dom.NodeProxy;
import org.exist.dom.QName;
import org.exist.memtree.AttributeImpl;
import org.exist.xquery.*;
import org.exist.xquery.value.*;
import org.w3c.dom.*;
import org.w3c.dom.Attr;
import org.w3c.dom.Node;

/**
 * Implements the fn:deep-equal library function.
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 */
public class FunDeepEqual extends Function {

	public final static FunctionSignature signature =
		new FunctionSignature(
			new QName("deep-equal", Module.BUILTIN_FUNCTION_NS),
			new SequenceType[] {
					new SequenceType(Type.ITEM, Cardinality.ZERO_OR_MORE), 
					new SequenceType(Type.ITEM, Cardinality.ZERO_OR_MORE)
			},
			new SequenceType(Type.BOOLEAN, Cardinality.ONE));

	public FunDeepEqual(XQueryContext context) {
		super(context, signature);
	}

	public int getDependencies() {
		return Dependency.CONTEXT_SET | Dependency.CONTEXT_ITEM;
	}
	
	public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
		Sequence[] args = getArguments(contextSequence, contextItem);
		int length = args[0].getLength();
		if (length != args[1].getLength()) return BooleanValue.FALSE;
		for (int i=0; i<length; i++) {
			if (!deepEquals(args[0].itemAt(i), args[1].itemAt(i))) return BooleanValue.FALSE;
		}
		return BooleanValue.TRUE;
	}
	
	private boolean deepEquals(Item a, Item b) {
		try {
			if (Type.subTypeOf(a.getType(), Type.ATOMIC) || Type.subTypeOf(b.getType(), Type.ATOMIC)) {
				if (!Type.subTypeOf(a.getType(), Type.ATOMIC) || !Type.subTypeOf(b.getType(), Type.ATOMIC)) return false;
				return a.atomize().compareTo(context.getDefaultCollator(), b.atomize()) == 0;
			} else {
//				assert Type.subTypeOf(a.getType(), Type.NODE);
//				assert Type.subTypeOf(b.getType(), Type.NODE);
				if (a.getType() != b.getType()) return false;
				NodeValue nva = (NodeValue) a, nvb = (NodeValue) b;
				if (nva.equals(nvb)) return true;		// shortcut!
				Node na, nb;
				switch(a.getType()) {
					case Type.DOCUMENT:
						// NodeValue.getNode() doesn't seem to work for document nodes
						na = nva instanceof Node ? (Node) nva : ((NodeProxy) nva).getDocument();<commit_msg>This XQuery was crashing : deep-equal(42, 'hello')<commit_after>/*
 *  eXist Open Source Native XML Database
 *  Copyright (C) 2001-04 <NAME>
 *  <EMAIL>
 *  http://exist.sourceforge.net
 *
 *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
 * 
 *  $Id$
 */
package org.exist.xquery.functions;

import org.exist.dom.NodeProxy;
import org.exist.dom.QName;
import org.exist.memtree.AttributeImpl;
import org.exist.xquery.*;
import org.exist.xquery.value.*;
import org.w3c.dom.*;
import org.w3c.dom.Attr;
import org.w3c.dom.Node;

/**
 * Implements the fn:deep-equal library function.
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 */
public class FunDeepEqual extends Function {

	public final static FunctionSignature signature =
		new FunctionSignature(
			new QName("deep-equal", Module.BUILTIN_FUNCTION_NS),
			new SequenceType[] {
					new SequenceType(Type.ITEM, Cardinality.ZERO_OR_MORE), 
					new SequenceType(Type.ITEM, Cardinality.ZERO_OR_MORE)
			},
			new SequenceType(Type.BOOLEAN, Cardinality.ONE));

	public FunDeepEqual(XQueryContext context) {
		super(context, signature);
	}

	public int getDependencies() {
		return Dependency.CONTEXT_SET | Dependency.CONTEXT_ITEM;
	}
	
	public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
		Sequence[] args = getArguments(contextSequence, contextItem);
		int length = args[0].getLength();
		if (length != args[1].getLength()) return BooleanValue.FALSE;
		for (int i=0; i<length; i++) {
			if (!deepEquals(args[0].itemAt(i), args[1].itemAt(i))) return BooleanValue.FALSE;
		}
		return BooleanValue.TRUE;
	}
	
	private boolean deepEquals(Item a, Item b) {
		try {
			if (Type.subTypeOf(a.getType(), Type.ATOMIC) || Type.subTypeOf(b.getType(), Type.ATOMIC)) {
				if ( a.getType() != b.getType() ) return false;
				return a.atomize().compareTo(context.getDefaultCollator(), b.atomize()) == 0;
			} else {
//				assert Type.subTypeOf(a.getType(), Type.NODE);
//				assert Type.subTypeOf(b.getType(), Type.NODE);
				if (a.getType() != b.getType()) return false;
				NodeValue nva = (NodeValue) a, nvb = (NodeValue) b;
				if (nva.equals(nvb)) return true;		// shortcut!
				Node na, nb;
				switch(a.getType()) {
					case Type.DOCUMENT:
						// NodeValue.getNode() doesn't seem to work for document nodes
						na = nva instanceof Node ? (Node) nva : ((NodeProxy) nva).getDocument();
{'fraction_non_alphanumeric': 0.12383749388154675, 'fraction_numerical': 0.008157937673356175, 'mean_word_length': 3.959546925566343, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '6264486', 'n_tokens_mistral': 2121, 'n_tokens_neox': 1934, 'n_words': 586}