blob: b7b882b7a23693fb58d6073397f0c5ccbbcafb88 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2009 Andrea Bittau, University College London, 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:
* Andrea Bittau - initial API and implementation from the PsychoPath XPath 2.0
*******************************************************************************/
package org.eclipse.wst.xml.xpath2.processor.internal.function;
import org.eclipse.wst.xml.xpath2.processor.DynamicError;
import org.eclipse.wst.xml.xpath2.processor.ResultSequence;
import org.eclipse.wst.xml.xpath2.processor.ResultSequenceFactory;
import org.eclipse.wst.xml.xpath2.processor.internal.*;
import org.eclipse.wst.xml.xpath2.processor.internal.types.*;
import java.util.*;
import org.w3c.dom.*;
/**
* The function assesses whether two sequences are deep-equal to each other. To
* be deep-equal, they must contain items that are pairwise deep-equal; and for
* two items to be deep-equal, they must either by atomic values that compare
* equal, or nodes of the same kind, with the same name, whose children are
* deep-equal. This is defined in more detail below. The $collation argument
* identifies a collation which is used at all levels of recursion when strings
* are compared (but not when names are compared), according to the rules in
* 7.3.1 Collations in the specification.
*/
public class FnDeepEqual extends Function {
/**
* Constructor for FnDeepEqual.
*/
public FnDeepEqual() {
super(new QName("deep-equal"), 2);
}
/**
* Evaluate arguments.
*
* @param args
* argument expressions.
* @throws DynamicError
* Dynamic error.
* @return Result of evaluation.
*/
@Override
public ResultSequence evaluate(Collection args) throws DynamicError {
return deep_equal(args);
}
/**
* Deep-Equal expression operation.
*
* @param args
* Result from the expressions evaluation.
* @throws DynamicError
* Dynamic error.
* @return Result of fn:deep-equal operation.
*/
public static ResultSequence deep_equal(Collection args)
throws DynamicError {
assert args.size() == 2;
// get args
Iterator citer = args.iterator();
ResultSequence arg1 = (ResultSequence) citer.next();
ResultSequence arg2 = (ResultSequence) citer.next();
boolean result = deep_equal(arg1, arg2);
return ResultSequenceFactory.create_new(new XSBoolean(result));
}
/**
* Deep-Equal boolean operation.
*
* @param one
* input1 xpath expression/variable.
* @param two
* input2 xpath expression/variable.
* @return Result of fn:deep-equal operation.
*/
public static boolean deep_equal(ResultSequence one, ResultSequence two) {
if (one.empty() && two.empty())
return true;
if (one.size() != two.size())
return false;
Iterator onei = one.iterator();
Iterator twoi = two.iterator();
while (onei.hasNext()) {
AnyType a = (AnyType) onei.next();
AnyType b = (AnyType) twoi.next();
if (!deep_equal(a, b))
return false;
}
return true;
}
/**
* Deep-Equal boolean operation for inputs of any type.
*
* @param one
* input1 xpath expression/variable.
* @param two
* input2 xpath expression/variable.
* @return Result of fn:deep-equal operation.
*/
public static boolean deep_equal(AnyType one, AnyType two) {
if ((one instanceof AnyAtomicType) && (two instanceof AnyAtomicType))
return deep_equal((AnyAtomicType) one, (AnyAtomicType) two);
else if (((one instanceof AnyAtomicType) && (two instanceof NodeType))
|| ((one instanceof NodeType) && (two instanceof AnyAtomicType)))
return false;
else if ((one instanceof NodeType) && (two instanceof NodeType))
return deep_equal((NodeType) one, (NodeType) two);
else {
assert false;
return false;
}
}
/**
* Deep-Equal boolean operation for inputs of any atomic type.
*
* @param one
* input1 xpath expression/variable.
* @param two
* input2 xpath expression/variable.
* @return Result of fn:deep-equal operation.
*/
public static boolean deep_equal(AnyAtomicType one, AnyAtomicType two) {
if (!(one instanceof CmpEq))
return false;
if (!(two instanceof CmpEq))
return false;
CmpEq a = (CmpEq) one;
try {
if (a.eq(two))
return true;
return false;
} catch (DynamicError err) {
return false; // XXX ???
}
}
/**
* Deep-Equal boolean operation for inputs of node type.
*
* @param one
* input1 xpath expression/variable.
* @param two
* input2 xpath expression/variable.
* @return Result of fn:deep-equal operation.
*/
public static boolean deep_equal(NodeType one, NodeType two) {
Node a = one.node_value();
Node b = two.node_value();
if (a.getNodeType() != b.getNodeType())
return false;
// XXX implement
assert false;
return false;
}
}