blob: 91e3608863a18afec134e111a8cf34510986f685 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xerces.impl.xs;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Enumeration;
import java.util.Map;
import org.apache.xerces.impl.xs.assertion.XSAssertImpl;
import org.apache.xerces.impl.xs.traversers.XSDHandler;
import org.apache.xerces.util.NamespaceSupport;
import org.apache.xerces.xs.XSModel;
import org.apache.xerces.xs.XSTypeDefinition;
import org.eclipse.wst.xml.xpath2.processor.DefaultDynamicContext;
import org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator;
import org.eclipse.wst.xml.xpath2.processor.DynamicContext;
import org.eclipse.wst.xml.xpath2.processor.DynamicError;
import org.eclipse.wst.xml.xpath2.processor.Evaluator;
import org.eclipse.wst.xml.xpath2.processor.JFlexCupParser;
import org.eclipse.wst.xml.xpath2.processor.ResultSequence;
import org.eclipse.wst.xml.xpath2.processor.ResultSequenceFactory;
import org.eclipse.wst.xml.xpath2.processor.StaticChecker;
import org.eclipse.wst.xml.xpath2.processor.StaticError;
import org.eclipse.wst.xml.xpath2.processor.StaticNameResolver;
import org.eclipse.wst.xml.xpath2.processor.XPathParser;
import org.eclipse.wst.xml.xpath2.processor.XPathParserException;
import org.eclipse.wst.xml.xpath2.processor.ast.XPath;
import org.eclipse.wst.xml.xpath2.processor.function.FnFunctionLibrary;
import org.eclipse.wst.xml.xpath2.processor.function.XSCtrLibrary;
import org.eclipse.wst.xml.xpath2.processor.internal.Focus;
import org.eclipse.wst.xml.xpath2.processor.internal.types.AnyType;
import org.eclipse.wst.xml.xpath2.processor.internal.types.ElementType;
import org.eclipse.wst.xml.xpath2.processor.internal.types.QName;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSAnyURI;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSBoolean;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSByte;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSDate;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSDateTime;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSDayTimeDuration;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSDecimal;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSDouble;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSFloat;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSGDay;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSGMonth;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSGMonthDay;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSGYear;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSGYearMonth;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSInt;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSInteger;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSLong;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSNegativeInteger;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSNonNegativeInteger;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSNonPositiveInteger;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSPositiveInteger;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSShort;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSString;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSTime;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSUnsignedByte;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSUnsignedInt;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSUnsignedLong;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSUnsignedShort;
import org.eclipse.wst.xml.xpath2.processor.internal.types.XSYearMonthDuration;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* A base class providing common services for XPath 2 evaluation, with
* PsychoPath XPath 2.0 engine.
*
* @xerces.internal
*
* @author Mukul Gandhi, IBM
* @version $Id$
*/
public class AbstractPsychoPathImpl {
private DynamicContext fDynamicContext = null;
private Document domDoc = null;
/*
* Initialize the PsychoPath XPath 2 dynamic context.
*/
protected DynamicContext initDynamicContext(XSModel schema,
Document document,
Map psychoPathParams) {
fDynamicContext = new DefaultDynamicContext(schema, document);
// populate the PsychoPath XPath 2.0 static context, with namespace
// bindings derived from the XSD Schema document.
NamespaceSupport xpath2NamespaceContext = (NamespaceSupport)
psychoPathParams.get("XPATH2_NS_CONTEXT");
Enumeration currPrefixes = xpath2NamespaceContext.getAllPrefixes();
while (currPrefixes.hasMoreElements()) {
String prefix = (String)currPrefixes.nextElement();
String uri = xpath2NamespaceContext.getURI(prefix);
fDynamicContext.add_namespace(prefix, uri);
}
fDynamicContext.add_function_library(new FnFunctionLibrary());
fDynamicContext.add_function_library(new XSCtrLibrary());
domDoc = document;
return fDynamicContext;
} //initDynamicContext
/*
* Evaluate XPath expression with PsychoPath engine.
*/
protected boolean evaluatePsychoPathExpr(XPath xp,
String xPathDefaultNamespace,
Element contextNode)
throws StaticError, DynamicError {
StaticChecker sc = new StaticNameResolver(fDynamicContext);
sc.check(xp);
Evaluator eval = null;
if (contextNode != null) {
eval = new DefaultEvaluator(fDynamicContext, domDoc);
// change focus to the top most element
ResultSequence nodeEvalRS = ResultSequenceFactory.create_new();
nodeEvalRS.add(new ElementType(contextNode,
fDynamicContext.node_position(contextNode)));
if (xPathDefaultNamespace != null) {
fDynamicContext.add_namespace(null, xPathDefaultNamespace);
}
fDynamicContext.set_focus(new Focus(nodeEvalRS));
}
else {
eval = new DefaultEvaluator(fDynamicContext, null);
}
ResultSequence rs = eval.evaluate(xp);
boolean result = false;
if (rs == null) {
result = false;
} else {
if (rs.size() == 1) {
AnyType rsReturn = rs.get(0);
if (rsReturn instanceof XSBoolean) {
XSBoolean returnResultBool = (XSBoolean) rsReturn;
result = returnResultBool.value();
} else {
result = false;
}
} else {
result = false;
}
}
return result;
} //evaluatePsychoPathExpr
/*
* Compile the XPath string, and return the compiled XPath expression.
*/
protected XPath compileXPathStr(String xpathStr,
XSAssertImpl assertImpl,
XSDHandler fSchemaHandler) {
XPathParser xpp = new JFlexCupParser();
XPath xp = null;
try {
xp = xpp.parse("boolean(" + xpathStr + ")");
} catch (XPathParserException ex) {
// error compiling XPath expression
reportError("cvc-xpath.3.13.4.2", assertImpl, fSchemaHandler);
}
return xp;
}
/*
* Get psychopath xpath2 typed value, corresponding to the XSD language
* type.
*
* @param xsdTypeName a XSD built in type name, like "string", "date" etc.
* @param value a "string value", that need to be converted to, the
* psychopath xpath2 XSD typed value.
*/
protected Object getPsychoPathTypeForXSDType(String xsdTypeName,
String value) {
Object psychoPathType = null;
if ("anyURI".equals(xsdTypeName)) {
psychoPathType = new XSAnyURI(value);
}
else if ("boolean".equals(xsdTypeName)) {
psychoPathType = new XSBoolean(Boolean.valueOf(value).
booleanValue());
}
else if ("date".equals(xsdTypeName)) {
psychoPathType = XSDate.parse_date(value);
}
else if ("dateTime".equals(xsdTypeName)) {
psychoPathType = XSDateTime.parseDateTime(value);
}
// decimal and it's subtypes
else if ("decimal".equals(xsdTypeName)) {
psychoPathType = new XSDecimal(new BigDecimal(value));
}
else if ("integer".equals(xsdTypeName)) {
psychoPathType = new XSInteger(new BigInteger(value));
}
else if ("long".equals(xsdTypeName)) {
psychoPathType = new XSLong(new BigInteger(value));
}
else if ("int".equals(xsdTypeName)) {
psychoPathType = new XSInt(new BigInteger(value));
}
else if ("short".equals(xsdTypeName)) {
psychoPathType = new XSShort(new BigInteger(value));
}
else if ("byte".equals(xsdTypeName)) {
psychoPathType = new XSByte(new BigInteger(value));
}
else if ("nonNegativeInteger".equals(xsdTypeName)) {
psychoPathType = new XSNonNegativeInteger(new BigInteger(value));
}
else if ("positiveInteger".equals(xsdTypeName)) {
psychoPathType = new XSPositiveInteger(new BigInteger(value));
}
else if ("unsignedLong".equals(xsdTypeName)) {
psychoPathType = new XSUnsignedLong(new BigInteger(value));
}
else if ("unsignedInt".equals(xsdTypeName)) {
psychoPathType = new XSUnsignedInt(new BigInteger(value));
}
else if ("unsignedShort".equals(xsdTypeName)) {
psychoPathType = new XSUnsignedShort(new BigInteger(value));
}
else if ("unsignedByte".equals(xsdTypeName)) {
psychoPathType = new XSUnsignedByte(new BigInteger(value));
}
else if ("nonPositiveInteger".equals(xsdTypeName)) {
psychoPathType = new XSNonPositiveInteger(new BigInteger(value));
}
else if ("negativeInteger".equals(xsdTypeName)) {
psychoPathType = new XSNegativeInteger(new BigInteger(value));
}
// end of, decimal types
else if ("double".equals(xsdTypeName)) {
psychoPathType = new XSDouble(Double.parseDouble(value));
}
// duration and it's subtypes
/*
* doesn't compile with JRE 1.3 PsychoPath binary. Can be provided
* later.
else if ("duration".equals(xsdTypeName)) {
psychoPathType = XSDuration.parseDTDuration(value);
}
*/
else if ("dayTimeDuration".equals(xsdTypeName)) {
psychoPathType = XSDayTimeDuration.parseDTDuration(value);
}
else if ("yearMonthDuration".equals(xsdTypeName)) {
psychoPathType = XSYearMonthDuration.parseYMDuration(value);
}
// end of, duration types
else if ("float".equals(xsdTypeName)) {
psychoPathType = new XSFloat(Float.parseFloat(value));
}
else if ("gDay".equals(xsdTypeName)) {
psychoPathType = XSGDay.parse_gDay(value);
}
else if ("gMonth".equals(xsdTypeName)) {
psychoPathType = XSGMonth.parse_gMonth(value);
}
else if ("gMonthDay".equals(xsdTypeName)) {
psychoPathType = XSGMonthDay.parse_gMonthDay(value);
}
else if ("gYear".equals(xsdTypeName)) {
psychoPathType = XSGYear.parse_gYear(value);
}
else if ("gYearMonth".equals(xsdTypeName)) {
psychoPathType = XSGYearMonth.parse_gYearMonth(value);
}
else if ("NOTATION".equals(xsdTypeName)) {
psychoPathType = new XSString(value);
}
else if ("QName".equals(xsdTypeName)) {
psychoPathType = QName.parse_QName(value);
}
else if ("string".equals(xsdTypeName)) {
psychoPathType = new XSString(value);
}
else if ("time".equals(xsdTypeName)) {
psychoPathType = XSTime.parse_time(value);
}
else {
// create a XSString value, as fallback option
psychoPathType = new XSString(value);
}
return psychoPathType;
}
/*
* Method to report error messages
*/
private void reportError(String key, XSAssertImpl assertImpl,
XSDHandler fSchemaHandler) {
XSTypeDefinition typeDef = assertImpl.getTypeDefinition();
String typeString = "";
if (typeDef != null) {
typeString = (typeDef.getName() != null) ? typeDef.getName() :
"#anonymous";
}
else {
typeString = "#anonymous";
}
fSchemaHandler.reportSchemaError(key, new Object[] {
assertImpl.getTest().getXPath().toString(),
typeString }, null);
}
} //AbstractPsychoPathImpl