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

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

There is a newer version: 12.5
Show newest version
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2018-2023 Saxonica Limited
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package net.sf.saxon.value;

import net.sf.saxon.om.Genre;
import net.sf.saxon.str.StringView;
import net.sf.saxon.str.UnicodeString;
import net.sf.saxon.trans.Err;
import net.sf.saxon.transpile.CSharpReplaceBody;
import net.sf.saxon.type.ItemType;
import net.sf.saxon.type.JavaExternalObjectType;
import net.sf.saxon.type.TypeHierarchy;

import java.util.Objects;


/**
 * An XPath value that encapsulates a Java object. Such a value can only be constructed from
 * Java code either in a Java extension function, or in the calling application.
 * 

Until Saxon 9.4, ObjectValue was a subclass of AtomicValue, and external Java objects were * considered to be atomic. From 9.5, this has been changed so that an ObjectValue is another * kind of Item: a fourth kind, at the same level as nodes, atomic values, and function items.

*

In the same way as ObjectValue is a wrapper around a Java instance object, the type of the * value is a wrapper around the corresponding Java class. These types have subtype-supertype * relationships that correspond to the Java class hierarchy. The top type in this branch of * the class hierarchy, which wraps the Java class "Object", has item() as its superclass. * These types can be referred to in the SequenceType syntax using QNames of the form * jt:full.package.name.ClassName, where the conventional prefix jt maps to the namespace * URI http://saxon.sf.net/java-type.

*

An ObjectValue is no longer permitted to wrap a Java null. An empty sequence should be * used in this situation.

*

The effective boolean value of a wrapped Java object, like that of a node, is always true.

*

Atomizing a wrapped Java object, or applying the {@code fn:string()} function, returns * an {@code xs:string} whose value is the result of calling {@code toString()} on the wrapped * Java object.

*/ public class ObjectValue implements AnyExternalObject { /*@NotNull*/ private final T value; /** * Constructor * * @param object the object to be encapsulated */ public ObjectValue(/*@NotNull*/ T object) { value = Objects.requireNonNull(object, "External object cannot wrap a Java null"); } /** * Get the genre of this item * * @return the genre */ @Override public Genre getGenre() { return Genre.EXTERNAL; } /** * Get the value of the item as a string. For nodes, this is the string value of the * node as defined in the XPath 2.0 data model, except that all nodes are treated as being * untyped: it is not an error to get the string value of a node with a complex type. * For atomic values, the method returns the result of casting the atomic value to a string. * * @return the string value of the item * @throws UnsupportedOperationException if the item is a function item (an unchecked exception * is used here to avoid introducing exception handling to a large number of paths where it is not * needed) * @since 8.4 */ @Override public UnicodeString getUnicodeStringValue() { return StringView.of(value.toString()).tidy(); } /** * Atomize the item. * * @return the result of atomization. For an external object this is defined * to be the result of the toString() method, as an xs:string value. */ @Override public StringValue atomize() { return new StringValue(getUnicodeStringValue().tidy()); } /** * Determine the data type of the items in the expression, if possible * * @param th The TypeHierarchy. * @return for the default implementation: AnyItemType (not known) */ /*@NotNull*/ @Override @CSharpReplaceBody(code="return Saxon.Hej.type.AnyExternalObjectType.THE_INSTANCE;") public ItemType getItemType(/*@Nullable*/ TypeHierarchy th) { synchronized(th.getConfiguration()) { return JavaExternalObjectType.of(value.getClass()); } } /** * Display the type name for use in error messages * * @param value a Java object * @return the type name. This will be in the form "java-type:" followed by the full class name of the * wrapped Java object. */ /*@NotNull*/ public static String displayTypeName(Object value) { return "java-type:" + value.getClass().getName(); } /** * Get the effective boolean value of the value * * @return true (always) */ @Override public boolean effectiveBooleanValue() { return true; } /** * Get the encapsulated object * * @return the Java object that this external object wraps */ public T getObject() { return value; } /** * Get the encapsulated object. This version of the method does not use generics, * enabling it to work the same way in Java and C#. * * @return the Java object that this external object wraps */ @Override public Object getWrappedObject() { return value; } /** * Determine if two ObjectValues are equal * * @return true if the other object is also a wrapped Java object and if the two wrapped objects compare * equal using the Java equals() method. */ public boolean equals(/*@NotNull*/ Object other) { if (other instanceof ObjectValue) { Object o = ((ObjectValue) other).value; return value.equals(o); } else { return false; } } public int hashCode() { return value.hashCode(); } @Override public String toShortString() { String v = value.toString(); if (v.startsWith(value.getClass().getName())) { return v; } else { return "(" + value.getClass().getSimpleName() + ")" + Err.truncate30(StringView.tidy(value.toString())); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy