All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.saxon.value.AnyURIValue Maven / Gradle / Ivy

package net.sf.saxon.value;
import net.sf.saxon.expr.XPathContext;
import net.sf.saxon.functions.EscapeURI;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.*;
import net.sf.saxon.om.StandardNames;
import net.sf.saxon.sort.LRUCache;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;



/**
* An XPath value of type xs:anyURI.
 *
 * 

This is implemented as a subtype of StringValue even though xs:anyURI is not a subtype of * xs:string in the XPath type hierarchy. This enables type promotion from URI to String to happen * automatically in most cases where it is appropriate.

* *

This implementation of xs:anyURI allows any string to be contained in the value space. It is possible * to validate that the string is a "valid URI" in the sense of XML Schema Part 2 (which refers to the XLink * specification and to RFC 2396); however, this validation is optional, and is not carried out by default. * In particular, there is no constraint that namespace URIs, collation URIs, and the like should be valid * URIs. However, casting from strings to xs:anyURI does invoke validation.

*/ public final class AnyURIValue extends StringValue { public static final AnyURIValue EMPTY_URI = new AnyURIValue(""); /** * To prevent repeated validation of commonly used URIs (especially namespaces) * we keep a small cache. This is especially useful in the case of URIs that are * valid only after escaping, as otherwise an exception occurs during the validation process */ private static LRUCache cache = new LRUCache(20); /** * Constructor * @param value the String value. Null is taken as equivalent to "". This constructor * does not check that the value is a valid anyURI instance. */ public AnyURIValue(CharSequence value) { this.value = (value==null ? "" : Whitespace.collapseWhitespace(value).toString()); typeLabel = BuiltInAtomicType.ANY_URI; } /** * Constructor for a user-defined subtype of anyURI * @param value the String value. Null is taken as equivalent to "". * @param type a user-defined subtype of anyURI. It is the caller's responsibility * to ensure that this is actually a subtype of anyURI, and that the value conforms * to the definition of this type. */ public AnyURIValue(CharSequence value, AtomicType type) { this.value = (value==null ? "" : Whitespace.collapseWhitespace(value).toString()); typeLabel = type; } /** * Create a copy of this atomic value, with a different type label * * @param typeLabel the type label of the new copy. The caller is responsible for checking that * the value actually conforms to this type. */ public AtomicValue copyAsSubType(AtomicType typeLabel) { AnyURIValue v = new AnyURIValue(value); v.length = length; v.typeLabel = typeLabel; return v; } /** * Check whether a string consititutes a valid URI * @param value the string to be tested * @return true if the string is a valid URI */ public static boolean isValidURI(CharSequence value) { if (cache.get(value) != null) { return true; } String sv = Whitespace.trim(value); // Allow zero-length strings (RFC2396 is ambivalent on this point) if (sv.length() == 0) { return true; } // Allow a string if the java.net.URI class accepts it try { new URI(sv); cache.put(value, value); return true; } catch (URISyntaxException e) { // keep trying // Note: it's expensive to throw exceptions on a success path, so we keep a cache. } // Allow a string if it can be escaped into a form that java.net.URI accepts sv = EscapeURI.iriToUri(sv).toString(); try { new URI(sv); cache.put(value, value); return true; } catch (URISyntaxException e) { return false; } } public BuiltInAtomicType getPrimitiveType() { return BuiltInAtomicType.ANY_URI; } /** * Convert to target data type * @param requiredType integer code representing the item type required * @param context the XPath dynamic evaluation context * @return the result of the conversion, or an ErrorValue */ public ConversionResult convertPrimitive(BuiltInAtomicType requiredType, boolean validate, XPathContext context) { int req = requiredType.getPrimitiveType(); switch(req) { case StandardNames.XS_ANY_ATOMIC_TYPE: case StandardNames.XS_ANY_URI: return this; case StandardNames.XS_UNTYPED_ATOMIC: return new UntypedAtomicValue(value); case StandardNames.XS_STRING: return new StringValue(value); case StandardNames.XS_NORMALIZED_STRING: case StandardNames.XS_TOKEN: case StandardNames.XS_LANGUAGE: case StandardNames.XS_NAME: case StandardNames.XS_NCNAME: case StandardNames.XS_ID: case StandardNames.XS_IDREF: case StandardNames.XS_ENTITY: case StandardNames.XS_NMTOKEN: return makeRestrictedString(value, requiredType, (validate ? context.getConfiguration().getNameChecker() : null)); default: ValidationFailure err = new ValidationFailure("Cannot convert anyURI to " + requiredType.getDisplayName()); err.setErrorCode("XPTY0004"); return err; } } /** * Convert to Java object (for passing to external functions) * @param target the Java class to which conversion is required * @return the result of the conversion * @throws XPathException if conversion to this target type is not possible */ public Object convertToJava(Class target, XPathContext context) throws XPathException { if (target==Object.class) { return value; } else if (target.isAssignableFrom(StringValue.class)) { return this; } else if (target==URI.class) { try { return new URI(value.toString()); } catch (URISyntaxException err) { throw new XPathException("The anyURI value '" + value + "' is not an acceptable Java URI"); } } else if (target==URL.class) { try { return new URL(value.toString()); } catch (MalformedURLException err) { throw new XPathException("The anyURI value '" + value + "' is not an acceptable Java URL"); } } else if (target==String.class) { return value; } else if (target==CharSequence.class) { return value; } else { Object o = super.convertToJava(target, context); if (o == null) { throw new XPathException("Conversion of anyURI to " + target.getName() + " is not supported"); } return o; } } } // // The contents of this file are subject to the Mozilla Public License Version 1.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.mozilla.org/MPL/ // // Software distributed under the License is distributed on an "AS IS" basis, // WITHOUT WARRANTY OF ANY KIND, either express or implied. // See the License for the specific language governing rights and limitations under the License. // // The Original Code is: all this file. // // The Initial Developer of the Original Code is Michael H. Kay // // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved. // // Contributor(s): none. //




© 2015 - 2025 Weber Informatics LLC | Privacy Policy