blob: 8e7e1b02e5bf659a09dbbcba5ed668c82c0f75bb [file] [log] [blame]
/* Copyright 2004 The Apache Software Foundation
*
* Licensed 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.xmlbeans.impl.values;
import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.common.*;
import org.apache.xmlbeans.impl.schema.SchemaTypeImpl;
import org.apache.xmlbeans.impl.schema.SchemaTypeVisitorImpl;
import org.apache.xmlbeans.impl.validator.Validator;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import java.io.*;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.function.Function;
import java.util.function.IntFunction;
public abstract class XmlObjectBase implements TypeStoreUser, Serializable, XmlObject, SimpleValue {
public static final short MAJOR_VERSION_NUMBER = (short) 1; // for serialization
public static final short MINOR_VERSION_NUMBER = (short) 1; // for serialization
public static final short KIND_SETTERHELPER_SINGLETON = 1;
public static final short KIND_SETTERHELPER_ARRAYITEM = 2;
public final Object monitor() {
if (has_store()) {
return get_store().get_locale();
}
return this;
}
private static XmlObjectBase underlying(XmlObject obj) {
if (obj == null) {
return null;
}
if (obj instanceof XmlObjectBase) {
return (XmlObjectBase) obj;
}
while (obj instanceof DelegateXmlObject) {
obj = ((DelegateXmlObject) obj).underlyingXmlObject();
}
if (obj instanceof XmlObjectBase) {
return (XmlObjectBase) obj;
}
throw new IllegalStateException("Non-native implementations of XmlObject should extend FilterXmlObject or implement DelegateXmlObject");
}
public final XmlObject copy() {
if (preCheck()) {
return _copy();
} else {
synchronized (monitor()) {
return _copy();
}
}
}
public final XmlObject copy(XmlOptions options) {
if (preCheck()) {
return _copy(options);
} else {
synchronized (monitor()) {
return _copy(options);
}
}
}
private boolean preCheck() {
// if ( isImmutable() )
// return true;
if (has_store()) {
return get_store().get_locale().noSync();
}
return false;
}
/**
* Same as copy() but unsynchronized.
* Warning: Using this method in mutithreaded environment can cause invalid states.
*/
public final XmlObject _copy() {
return _copy(null);
}
/**
* Same as copy() but unsynchronized.
* If Locale.COPY_USE_NEW_LOCALE is set in the options, a new locale will be created for the copy.
* Warning: Using this method in mutithreaded environment can cause invalid states.
*/
public final XmlObject _copy(XmlOptions xmlOptions) {
// immutable objects don't get copied. They're immutable
if (isImmutable()) {
return this;
}
check_orphaned();
SchemaTypeLoader stl = get_store().get_schematypeloader();
return (XmlObject) get_store().copy(stl, schemaType(), xmlOptions);
}
public XmlDocumentProperties documentProperties() {
XmlCursor cur = newCursorForce();
try {
return cur.documentProperties();
} finally {
cur.dispose();
}
}
public XMLStreamReader newXMLStreamReader() {
return newXMLStreamReader(null);
}
public XMLStreamReader newXMLStreamReader(XmlOptions options) {
XmlCursor cur = newCursorForce();
try {
return cur.newXMLStreamReader(makeInnerOptions(options));
} finally {
cur.dispose();
}
}
public InputStream newInputStream() {
return newInputStream(null);
}
public InputStream newInputStream(XmlOptions options) {
XmlCursor cur = newCursorForce();
try {
return cur.newInputStream(makeInnerOptions(options));
} finally {
cur.dispose();
}
}
public Reader newReader() {
return newReader(null);
}
public Reader newReader(XmlOptions options) {
XmlCursor cur = newCursorForce();
try {
return cur.newReader(makeInnerOptions(options));
} finally {
cur.dispose();
}
}
public Node getDomNode() {
XmlCursor cur = newCursorForce();
try {
return cur.getDomNode();
} finally {
cur.dispose();
}
}
public Node newDomNode() {
return newDomNode(null);
}
public Node newDomNode(XmlOptions options) {
XmlCursor cur = newCursorForce();
try {
return cur.newDomNode(makeInnerOptions(options));
} finally {
cur.dispose();
}
}
public void save(ContentHandler ch, LexicalHandler lh, XmlOptions options) throws SAXException {
XmlCursor cur = newCursorForce();
try {
cur.save(ch, lh, makeInnerOptions(options));
} finally {
cur.dispose();
}
}
public void save(File file, XmlOptions options) throws IOException {
XmlCursor cur = newCursorForce();
try {
cur.save(file, makeInnerOptions(options));
} finally {
cur.dispose();
}
}
public void save(OutputStream os, XmlOptions options) throws IOException {
XmlCursor cur = newCursorForce();
try {
cur.save(os, makeInnerOptions(options));
} finally {
cur.dispose();
}
}
public void save(Writer w, XmlOptions options) throws IOException {
XmlCursor cur = newCursorForce();
try {
cur.save(w, makeInnerOptions(options));
} finally {
cur.dispose();
}
}
public void save(ContentHandler ch, LexicalHandler lh) throws SAXException {
save(ch, lh, null);
}
public void save(File file) throws IOException {
save(file, null);
}
public void save(OutputStream os) throws IOException {
save(os, null);
}
public void save(Writer w) throws IOException {
save(w, null);
}
public void dump() {
XmlCursor cur = newCursorForce();
try {
cur.dump();
} finally {
cur.dispose();
}
}
public XmlCursor newCursorForce() {
synchronized (monitor()) {
return ensureStore().newCursor();
}
}
private XmlObject ensureStore() {
if ((_flags & FLAG_STORE) != 0) {
return this;
}
check_dated();
String value =
(_flags & FLAG_NIL) != 0
? ""
: compute_text(has_store() ? get_store() : null);
XmlOptions options = new XmlOptions().setDocumentType(schemaType());
XmlObject x = XmlObject.Factory.newInstance(options);
XmlCursor c = x.newCursor();
c.toNextToken();
c.insertChars(value);
return x;
}
private static XmlOptions makeInnerOptions(XmlOptions options) {
XmlOptions innerOptions = new XmlOptions(options);
innerOptions.setSaveInner();
return innerOptions;
}
public XmlCursor newCursor() {
if ((_flags & FLAG_STORE) == 0) {
throw new IllegalStateException("XML Value Objects cannot create cursors");
}
check_orphaned();
// Note that new_cursor does not really need sync ....
XmlLocale l = getXmlLocale();
if (l.noSync()) {
l.enter();
try {
return get_store().new_cursor();
} finally {
l.exit();
}
} else {
synchronized (l) {
l.enter();
try {
return get_store().new_cursor();
} finally {
l.exit();
}
}
}
}
public abstract SchemaType schemaType();
public SchemaType instanceType() {
synchronized (monitor()) {
return isNil() ? null : schemaType();
}
}
private SchemaField schemaField() {
SchemaType st = schemaType();
SchemaField field;
// First check if this field has an anonymous type
field = st.getContainerField();
if (field == null) {
field = get_store().get_schema_field();
}
return field;
}
/**
* Use _voorVc when you want to throw a ValueOutOfRangeException when
* validating a simple type.
*/
private static final class ValueOutOfRangeValidationContext implements ValidationContext {
public void invalid(String message) {
throw new XmlValueOutOfRangeException(message);
}
public void invalid(String code, Object[] args) {
throw new XmlValueOutOfRangeException(code, args);
}
}
/**
* Used to supply validation context for the validate_value methods
*/
private static final class ImmutableValueValidationContext implements ValidationContext {
private final XmlObject _loc;
private final Collection<XmlError> _coll;
ImmutableValueValidationContext(Collection<XmlError> coll, XmlObject loc) {
_coll = coll;
_loc = loc;
}
public void invalid(String message) {
_coll.add(XmlError.forObject(message, _loc));
}
public void invalid(String code, Object[] args) {
_coll.add(XmlError.forObject(code, args, _loc));
}
}
public static final ValidationContext _voorVc = new ValueOutOfRangeValidationContext();
public boolean validate() {
return validate(null);
}
public boolean validate(XmlOptions options) {
if ((_flags & FLAG_STORE) == 0) {
if ((_flags & FLAG_IMMUTABLE) != 0) {
return validate_immutable(options);
}
throw new IllegalStateException(
"XML objects with no underlying store cannot be validated");
}
synchronized (monitor()) {
if ((_flags & FLAG_ORPHANED) != 0) {
throw new XmlValueDisconnectedException();
}
SchemaField field = schemaField();
SchemaType type = schemaType();
TypeStore typeStore = get_store();
Validator validator =
new Validator(
type, field, typeStore.get_schematypeloader(), options, null);
typeStore.validate(validator);
return validator.isValid();
}
}
private boolean validate_immutable(XmlOptions options) {
Collection<XmlError> errorListener = options == null ? null : options.getErrorListener();
XmlErrorWatcher watcher = new XmlErrorWatcher(errorListener);
if (!(schemaType().isSimpleType() || options != null &&
options.isValidateTextOnly())) {
// cannot have any required attributes or elements
SchemaProperty[] properties = schemaType().getProperties();
for (SchemaProperty property : properties) {
if (property.getMinOccurs().signum() > 0) {
// KHK: error code?
if (property.isAttribute()) {
watcher.add(XmlError.forObject(XmlErrorCodes.ELEM_COMPLEX_TYPE_LOCALLY_VALID$MISSING_REQUIRED_ATTRIBUTE, new Object[]{QNameHelper.pretty(property.getName()),}, this));
} else {
watcher.add(XmlError.forObject(XmlErrorCodes.ELEM_COMPLEX_TYPE_LOCALLY_VALID$MISSING_ELEMENT, new Object[]{property.getMinOccurs(), QNameHelper.pretty(property.getName()),}, this));
}
}
}
if (schemaType().getContentType() != SchemaType.SIMPLE_CONTENT) {
return !watcher.hasError(); // don't validate non-simple-content
}
}
String text = (String) _textsource;
if (text == null) {
text = "";
}
validate_simpleval(text, new ImmutableValueValidationContext(watcher, this));
return !watcher.hasError();
}
protected void validate_simpleval(String lexical, ValidationContext ctx) {
}
private static XmlObject[] _typedArray(XmlObject[] input) {
if (input.length == 0) {
return input;
}
SchemaType commonType = input[0].schemaType();
if (commonType.equals(XmlObject.type) || commonType.isNoType()) {
return input;
}
for (int i = 1; i < input.length; i++) {
if (input[i].schemaType().isNoType()) {
return input;
}
commonType = commonType.getCommonBaseType(input[i].schemaType());
if (commonType.equals(XmlObject.type)) {
return input;
}
}
Class<?> desiredClass = commonType.getJavaClass();
while (desiredClass == null) {
commonType = commonType.getBaseType();
if (XmlObject.type.equals(commonType)) {
return input;
}
desiredClass = commonType.getJavaClass();
}
XmlObject[] result = (XmlObject[]) Array.newInstance(desiredClass, input.length);
System.arraycopy(input, 0, result, 0, input.length);
return result;
}
public XmlObject[] selectPath(String path) {
return selectPath(path, null);
}
public XmlObject[] selectPath(String path, XmlOptions options) {
XmlObject[] selections;
// all user-level code; doesn't need to be synchronized
XmlCursor c = newCursor();
if (c == null) {
throw new XmlValueDisconnectedException();
}
try {
c.selectPath(path, options);
if (!c.hasNextSelection()) {
selections = EMPTY_RESULT;
} else {
selections = new XmlObject[c.getSelectionCount()];
for (int i = 0; c.toNextSelection(); i++) {
if ((selections[i] = c.getObject()) == null) {
if (!c.toParent() || (selections[i] = c.getObject()) == null) {
throw
new XmlRuntimeException(
"Path must select only elements " +
"and attributes");
}
}
}
}
} finally {
c.dispose();
}
return _typedArray(selections);
}
public XmlObject[] execQuery(String path) {
return execQuery(path, null);
}
public XmlObject[] execQuery(String queryExpr, XmlOptions options) {
synchronized (monitor()) {
TypeStore typeStore = get_store();
if (typeStore == null) {
throw
new XmlRuntimeException(
"Cannot do XQuery on XML Value Objects");
}
return _typedArray(typeStore.exec_query(queryExpr, options));
}
}
public XmlObject changeType(SchemaType type) {
if (type == null) {
throw new IllegalArgumentException("Invalid type (null)");
}
if ((_flags & FLAG_STORE) == 0) {
throw
new IllegalStateException(
"XML Value Objects cannot have thier type changed");
}
synchronized (monitor()) {
check_orphaned();
return (XmlObject) get_store().change_type(type);
}
}
public XmlObject substitute(QName name, SchemaType type) {
if (name == null) {
throw new IllegalArgumentException("Invalid name (null)");
}
if (type == null) {
throw new IllegalArgumentException("Invalid type (null)");
}
if ((_flags & FLAG_STORE) == 0) {
throw
new IllegalStateException(
"XML Value Objects cannot be used with substitution");
}
synchronized (monitor()) {
check_orphaned();
return (XmlObject) get_store().substitute(name, type);
}
}
private int _flags;
private Object _textsource;
protected XmlObjectBase() {
_flags = FLAG_NILLABLE | FLAG_NIL;
}
public void init_flags(SchemaProperty prop) {
if (prop == null) {
return;
}
if (prop.hasDefault() == SchemaProperty.VARIABLE ||
prop.hasFixed() == SchemaProperty.VARIABLE ||
prop.hasNillable() == SchemaProperty.VARIABLE) {
return;
}
_flags &= ~FLAGS_ELEMENT;
_flags |=
(prop.hasDefault() == SchemaProperty.NEVER ? 0 : TypeStore.HASDEFAULT) |
(prop.hasFixed() == SchemaProperty.NEVER ? 0 : TypeStore.FIXED) |
(prop.hasNillable() == SchemaProperty.NEVER ? 0 : TypeStore.NILLABLE) |
(FLAG_NOT_VARIABLE);
}
private static final int FLAG_NILLABLE = TypeStore.NILLABLE;
private static final int FLAG_HASDEFAULT = TypeStore.HASDEFAULT;
private static final int FLAG_FIXED = TypeStore.FIXED;
private static final int FLAG_ATTRIBUTE = 8;
private static final int FLAG_STORE = 16;
private static final int FLAG_VALUE_DATED = 32;
private static final int FLAG_NIL = 64;
private static final int FLAG_NIL_DATED = 128;
private static final int FLAG_ISDEFAULT = 256;
private static final int FLAG_ELEMENT_DATED = 512;
private static final int FLAG_SETTINGDEFAULT = 1024;
private static final int FLAG_ORPHANED = 2048;
private static final int FLAG_IMMUTABLE = 4096;
private static final int FLAG_COMPLEXTYPE = 8192;
private static final int FLAG_COMPLEXCONTENT = 16384;
private static final int FLAG_NOT_VARIABLE = 32768;
private static final int FLAG_VALIDATE_ON_SET = 65536;
/**
* The three dated flags are always stacked:
* FLAG_ELEMENT_DATED implies FLAG_NIL_DATED is set
* FLAG_NIL_DATED implies FLAG_TEXT_DATED is set.
* checkers work on the flags from top to bottom.
*/
private static final int FLAGS_DATED =
FLAG_VALUE_DATED | FLAG_NIL_DATED | FLAG_ELEMENT_DATED;
/**
* The three element status flags have one interrlationshiop:
* FLAG_FIXED implies FLAG_HASDEFAULT is set.
* These flags are used when setting nils, defaults, strings.
* Since an initial get implies setting from text, they're
* also used during getting.
*/
private static final int FLAGS_ELEMENT =
FLAG_NILLABLE | FLAG_FIXED | FLAG_HASDEFAULT;
/**
* Called by restriction subclasses within their constructors to enable
* complex type support.
*/
protected void initComplexType(boolean complexType, boolean complexContent) {
_flags |= (complexType ? FLAG_COMPLEXTYPE : 0) |
(complexContent ? FLAG_COMPLEXCONTENT : 0);
}
protected boolean _isComplexType() {
return (_flags & FLAG_COMPLEXTYPE) != 0;
}
protected boolean _isComplexContent() {
return (_flags & FLAG_COMPLEXCONTENT) != 0;
}
public void setValidateOnSet() {
_flags |= FLAG_VALIDATE_ON_SET;
}
protected boolean _validateOnSet() {
return (_flags & FLAG_VALIDATE_ON_SET) != 0;
}
/**
* True if the value is nilled.
*/
public final boolean isNil() {
synchronized (monitor()) {
check_dated();
return ((_flags & FLAG_NIL) != 0);
}
}
/**
* True if the value is fixed.
*/
public final boolean isFixed() {
check_element_dated();
return ((_flags & FLAG_FIXED) != 0);
}
/**
* True if the value is allowed to be nil.
*/
public final boolean isNillable() {
check_element_dated();
return ((_flags & FLAG_NILLABLE) != 0);
}
/**
* True if the value is currently defaulted.
*/
public final boolean isDefaultable() {
check_element_dated();
return ((_flags & FLAG_HASDEFAULT) != 0);
}
/**
* True if the value is currently defaulted.
*/
public final boolean isDefault() {
check_dated();
return ((_flags & FLAG_ISDEFAULT) != 0);
}
/**
* Nils the value.
*/
public final void setNil() {
synchronized (monitor()) {
set_prepare();
// if we're not nillable, throw exception on setNil(true)
if ((_flags & FLAG_NILLABLE) == 0 &&
(_flags & FLAG_VALIDATE_ON_SET) != 0) {
throw new XmlValueNotNillableException();
}
// the implementation should zero the value to reflect nil
set_nil();
// set the nil flag
_flags |= FLAG_NIL;
// ordinary commit except no clearing of nil flag
if ((_flags & FLAG_STORE) != 0) {
get_store().invalidate_text();
_flags &= ~FLAGS_DATED;
get_store().invalidate_nil();
} else {
_textsource = null;
}
}
}
/**
* Used for situations where these flags must be passed on to
* chained values. (See XmlAnySimpleType (allSimpleValue), union
* implementations).
*/
protected int elementFlags() {
check_element_dated();
return (_flags & FLAGS_ELEMENT);
}
/**
* Used to make a free-standing xml simple value instance immutable.
* This is a one-way street, and it is illegal to attempt to make a
* value that is embedded in an xml document immutable.
* <p>
* Once a value is marked as immutable, it is illegal to call setters
* of any kind.
*/
public void setImmutable() {
if ((_flags & (FLAG_IMMUTABLE | FLAG_STORE)) != 0) {
throw new IllegalStateException();
}
_flags |= FLAG_IMMUTABLE;
}
/**
* Is this instance an immutable value?
*/
public boolean isImmutable() {
return (_flags & FLAG_IMMUTABLE) != 0;
}
// TEXTUSER implementation
/**
* Called to initialize the TypeStore associated with this XmlObject
* implementation. If not called, this is a free-floating value holder.
* <p>
* When a value is first attached, it is put in a completely invalidated
* state.
*/
public final void attach_store(TypeStore store) {
_textsource = store;
if ((_flags & FLAG_IMMUTABLE) != 0) {
throw new IllegalStateException();
}
_flags |= FLAG_STORE | FLAG_VALUE_DATED | FLAG_NIL_DATED | FLAG_ELEMENT_DATED;
if (store.is_attribute()) {
_flags |= FLAG_ATTRIBUTE;
}
if (store.validate_on_set()) {
_flags |= FLAG_VALIDATE_ON_SET;
}
}
/**
* Called by a TypeStore to indicate that the text has been
* invalidated and should be fetched next time the value is
* needed.
*/
public final void invalidate_value() {
assert ((_flags & FLAG_STORE) != 0);
_flags |= FLAG_VALUE_DATED;
}
public final boolean uses_invalidate_value() {
SchemaType type = schemaType();
return type.isSimpleType() || type.getContentType() == SchemaType.SIMPLE_CONTENT;
}
/**
* Called by a TypeStore to indicate that the xsi:nil attribute
* on the containing element (and possibly the text) has been
* invalidated and both should be consulted next time the value
* is needed.
*/
public final void invalidate_nilvalue() {
assert ((_flags & FLAG_STORE) != 0);
_flags |= FLAG_VALUE_DATED | FLAG_NIL_DATED;
}
/**
* Called by a TypeStore to indicate that the element's default
* value, nillability, fixedness, etc, may have changed by
* virtue of the element order changing (and xsi:nil and the
* text may have changed too); so the store should be consulted
* next time any setter or getter is called.
*/
public final void invalidate_element_order() {
assert ((_flags & FLAG_STORE) != 0);
_flags |= FLAG_VALUE_DATED | FLAG_NIL_DATED | FLAG_ELEMENT_DATED;
}
/**
* Used by the ComplexTypeImpl subclass to get direct access
* to the store.
*/
public final TypeStore get_store() {
assert ((_flags & FLAG_STORE) != 0);
return (TypeStore) _textsource;
}
public final XmlLocale getXmlLocale() {
return get_store().get_locale();
}
protected final boolean has_store() {
return (_flags & FLAG_STORE) != 0;
}
/**
* Called by a TypeStore to pull out the most reasonable
* text value from us. This is done after we have invalidated
* the store (typically when our value has been set).
*/
public final String build_text(NamespaceManager nsm) {
assert ((_flags & FLAG_STORE) != 0);
assert ((_flags & FLAG_VALUE_DATED) == 0);
if ((_flags & (FLAG_NIL | FLAG_ISDEFAULT)) != 0) {
return "";
}
return compute_text(
nsm == null ? has_store() ? get_store() : null : nsm);
}
/**
* A store will call back on build_nil after we've called invalidate_nil
* and it needs to know what the nil value is.
*/
public boolean build_nil() {
assert ((_flags & FLAG_STORE) != 0);
assert ((_flags & FLAG_VALUE_DATED) == 0);
return (_flags & FLAG_NIL) != 0;
}
/**
* A store will call back on validate_now to force us to look at
* the text if we're in an invalid state. We're allowed to throw
* an exception if the text isn't valid for our type.
*/
public void validate_now() {
check_dated();
}
/**
* A store calls back here in order to force a disconnect.
* After this is done, the object should be considered invalid.
* Any attempt to access or set a value should result in an
* exception.
* <p>
* Note that this is how we handle deletions and xsi:type changes.
*/
public void disconnect_store() {
assert ((_flags & FLAG_STORE) != 0);
_flags |= FLAGS_DATED | FLAG_ORPHANED;
// do NOT null out _textsource, because we need it non-null for synchronization
}
/**
* A typestore user can create a new TypeStoreUser instance for
* a given element child name as long as you also pass the
* qname contained by the xsi:type attribute, if any.
* <p>
* Note that we will ignore the xsiType if it turns out to be invalid.
* <p>
* Returns null if there is no strongly typed information for that
* given element (which implies, recusively, no strongly typed information
* downwards).
*/
public TypeStoreUser create_element_user(QName eltName, QName xsiType) {
return
(TypeStoreUser)
((SchemaTypeImpl) schemaType()).createElementType(
eltName, xsiType, get_store().get_schematypeloader());
/*
SchemaTypeImpl stype = (SchemaTypeImpl)schemaType().getElementType(eltName, xsiType, get_store().get_schematypeloader());
if (stype == null)
return null;
return (TypeStoreUser)stype.createUnattachedNode();
*/
}
/**
* A typestore user can create a new TypeStoreUser instance for
* a given attribute child, based on the attribute name.
* <p>
* Returns null if there is no strongly typed information for that
* given attributes.
*/
public TypeStoreUser create_attribute_user(QName attrName) {
return (TypeStoreUser) ((SchemaTypeImpl) schemaType()).createAttributeType(attrName, get_store().get_schematypeloader());
}
public SchemaType get_schema_type() {
return schemaType();
}
public SchemaType get_element_type(QName eltName, QName xsiType) {
return schemaType().getElementType(
eltName, xsiType, get_store().get_schematypeloader());
}
public SchemaType get_attribute_type(QName attrName) {
return schemaType().getAttributeType(
attrName, get_store().get_schematypeloader());
}
/**
* Returns the default element text, if it's consistent. If it's
* not consistent, returns null, and requires a visitor walk.
* <p>
* Also returns null if there is no default at all (although
* that can also be discovered via get_elementflags without
* doing a walk).
*/
public String get_default_element_text(QName eltName) {
assert (_isComplexContent());
if (!_isComplexContent()) {
throw new IllegalStateException();
}
SchemaProperty prop = schemaType().getElementProperty(eltName);
if (prop == null) {
return "";
}
return prop.getDefaultText();
}
/**
* Returns the default attribute text for the attribute with
* the given name, or null if no default.
*/
public String get_default_attribute_text(QName attrName) {
assert (_isComplexType());
if (!_isComplexType()) {
throw new IllegalStateException();
}
SchemaProperty prop = schemaType().getAttributeProperty(attrName);
if (prop == null) {
return "";
}
return prop.getDefaultText();
}
/**
* Returns the elementflags, if they're consistent. If they're
* not, returns -1, and requires a vistor walk.
*/
public int get_elementflags(QName eltName) {
if (!_isComplexContent()) {
return 0;
}
SchemaProperty prop = schemaType().getElementProperty(eltName);
if (prop == null) {
return 0;
}
if (prop.hasDefault() == SchemaProperty.VARIABLE ||
prop.hasFixed() == SchemaProperty.VARIABLE ||
prop.hasNillable() == SchemaProperty.VARIABLE) {
return -1;
}
return
(prop.hasDefault() == SchemaProperty.NEVER ? 0 : TypeStore.HASDEFAULT) |
(prop.hasFixed() == SchemaProperty.NEVER ? 0 : TypeStore.FIXED) |
(prop.hasNillable() == SchemaProperty.NEVER ? 0 : TypeStore.NILLABLE);
}
/**
* Returns the flags for the given attribute.
*/
public int get_attributeflags(QName attrName) {
if (!_isComplexType()) {
return 0;
}
SchemaProperty prop = schemaType().getAttributeProperty(attrName);
if (prop == null) {
return 0;
}
return
(prop.hasDefault() == SchemaProperty.NEVER ? 0 : TypeStore.HASDEFAULT) |
(prop.hasFixed() == SchemaProperty.NEVER ? 0 : TypeStore.FIXED);
// BUGBUG: todo: hook up required?
}
/**
* Returns false if child elements are insensitive to order;
* if it returns true, you're required to call invalidate_element_order
* on children to the right of any child order rearrangement.
*/
public boolean is_child_element_order_sensitive() {
if (!_isComplexType()) {
return false;
}
return schemaType().isOrderSensitive();
}
/**
* Inserting a new element is always unambiguous except in one
* situation: when adding an element after the last one with
* that name (or the first one if there are none).
* <p>
* In that case, add the element at the first possible slot
* BEFORE any element whose qname is contained in the QNameSet
* given. (If the QNameSet is empty, that means add the new
* element at the very end.)
* <p>
* If the returned QNameSet is null, treat it as if the QNameSet
* contained all QNames, i.e., add the new element at the very
* first position possible (adjacent to the last element of the
* same name, or at the very first slot if it is the first elt
* with that name).
*/
public final QNameSet get_element_ending_delimiters(QName eltname) {
SchemaProperty prop = schemaType().getElementProperty(eltname);
if (prop == null) {
return null;
}
return prop.getJavaSetterDelimiter();
}
/**
* A typestore user can return a visitor that is used to compute
* default text and elementflags for an arbitrary element.
*/
public TypeStoreVisitor new_visitor() {
if (!_isComplexContent()) {
return null;
}
return new SchemaTypeVisitorImpl(schemaType().getContentModel());
}
public SchemaField get_attribute_field(QName attrName) {
SchemaAttributeModel model = schemaType().getAttributeModel();
if (model == null) {
return null;
}
return model.getAttribute(attrName);
}
/**
* Setting a string preserves any noncanonical literal
* representation. This is done by storing the actual
* string in the underlying store after checking it
* against the primitive type for validity.
*/
protected void set_String(String v) {
if ((_flags & FLAG_IMMUTABLE) != 0) {
throw new IllegalStateException();
}
boolean wasNilled = ((_flags & FLAG_NIL) != 0);
// update the underlying value from the string
String wscanon = apply_wscanon(v);
update_from_wscanon_text(wscanon);
// Now store the literal text immediately in the underlying
if ((_flags & FLAG_STORE) != 0) {
_flags &= ~FLAG_VALUE_DATED;
if ((_flags & FLAG_SETTINGDEFAULT) == 0) {
get_store().store_text(v);
}
if (wasNilled) {
get_store().invalidate_nil();
}
} else {
_textsource = v;
}
}
/**
* Update the value based on complex content.
*/
protected void update_from_complex_content() {
throw new XmlValueNotSupportedException("Complex content");
}
/**
* Utility to update the value based on a string that
* was passed either from the text store or from the user.
* This function handles the cases where there is a default
* that must be applied, and where the value must match
* a fixed value.
*/
private void update_from_wscanon_text(String v) {
// Whitespace is default if this type treats this space as defaultable
if ((_flags & FLAG_HASDEFAULT) != 0 && (_flags & FLAG_SETTINGDEFAULT) == 0) {
// This isn't quite correct since the .equals("") test should be
// done on the actual text, not the wscanon text
if ((_flags & FLAG_ATTRIBUTE) == 0 && v.equals("")) {
String def = get_store().compute_default_text();
if (def == null) {
throw new XmlValueOutOfRangeException();
}
// protect against recursion with this flag
_flags |= FLAG_SETTINGDEFAULT;
try {
this.setStringValue(def);
} finally {
_flags &= ~FLAG_SETTINGDEFAULT;
}
_flags &= ~FLAG_NIL;
_flags |= FLAG_ISDEFAULT;
return;
}
}
// If we haven't returned yet, the default doesn't apply.
// Ask underlying impl to parse ordinary non-default text
set_text(v);
_flags &= ~(FLAG_NIL | FLAG_ISDEFAULT);
}
/**
* Types should return false if they don't treat the given
* whitespace as a default value.
*/
protected boolean is_defaultable_ws(String v) {
return true;
}
/**
* Returns the whitespace rule that will be applied before
* building a string to pass to get_text().
* <p>
* Overridden by subclasses that don't need their text
* for set_text canonicalized; perhaps they already implement
* scanners that can deal with whitespace, and they know
* they have no regex pattern restrictions.
*/
protected int get_wscanon_rule() {
return SchemaType.WS_COLLAPSE;
}
/**
* Called to canonicalize whitespace before calling set_text.
* <p>
* Tries to avoid allocation when the string is already canonical, but
* otherwise this is not particularly efficient. Hopefully the common
* case is that we pass our wscanon rule to the store via fetch_text
* and it's canonicalized before we even see it as a string.
*/
private String apply_wscanon(String v) {
return XmlWhitespace.collapse(v, get_wscanon_rule());
}
/**
* Called before every set and get, to ensure that we have
* a correct picture of whether we're nillable, fixed, or
* if we have a default that can be applied.
*/
private void check_element_dated() {
if ((_flags & FLAG_ELEMENT_DATED) != 0 &&
(_flags & FLAG_NOT_VARIABLE) == 0) {
if ((_flags & FLAG_ORPHANED) != 0) {
throw new XmlValueDisconnectedException();
}
int eltflags = get_store().compute_flags();
// int eltflags = 0;
_flags &= ~(FLAGS_ELEMENT | FLAG_ELEMENT_DATED);
_flags |= eltflags;
}
if ((_flags & FLAG_NOT_VARIABLE) != 0) {
_flags &= ~(FLAG_ELEMENT_DATED);
}
}
/**
* Describes the orphaned status of this object.
*/
protected final boolean is_orphaned() {
return (_flags & FLAG_ORPHANED) != 0;
}
/**
* Called before every getter and setter on the strongly
* typed classes to ensure that the object has not been
* orphaned.
*/
protected final void check_orphaned() {
if (is_orphaned()) {
throw new XmlValueDisconnectedException();
}
}
/**
* Called prior to every get operation, to ensure
* that the value being read is valid. If the value
* has been invalidated, it is re-read from the underlying
* text store, and this may cause an out of range exception.
* <p>
* This method deals with nils, nillability, defaults, etc.
*/
public final void check_dated() {
if ((_flags & FLAGS_DATED) != 0) {
if ((_flags & FLAG_ORPHANED) != 0) {
throw new XmlValueDisconnectedException();
}
assert ((_flags & FLAG_STORE) != 0);
check_element_dated();
if ((_flags & FLAG_ELEMENT_DATED) != 0) {
int eltflags = get_store().compute_flags();
_flags &= ~(FLAGS_ELEMENT | FLAG_ELEMENT_DATED);
_flags |= eltflags;
}
boolean nilled = false;
if ((_flags & FLAG_NIL_DATED) != 0) {
if (get_store().find_nil()) {
if ((_flags & FLAG_NILLABLE) == 0 &&
(_flags & FLAG_VALIDATE_ON_SET) != 0) {
throw new XmlValueOutOfRangeException(); // nil not allowed
}
// let the implementation know that we're nil now
set_nil();
_flags |= FLAG_NIL;
nilled = true;
} else {
_flags &= ~FLAG_NIL;
}
_flags &= ~FLAG_NIL_DATED;
}
if (!nilled) {
String text;
if ((_flags & FLAG_COMPLEXCONTENT) != 0 || (text = get_wscanon_text()) == null) {
update_from_complex_content();
} else {
NamespaceContext.push(new NamespaceContext(get_store()));
try {
update_from_wscanon_text(text);
} finally {
NamespaceContext.pop();
}
}
}
_flags &= ~FLAG_VALUE_DATED;
}
}
/**
* Called before every set operation (except for the
* special case of setting a string) to:
* (1) get the nillable, fixed, etc flags
* (2) throw an exception if it's fixed (not for strings)
*/
private void set_prepare() {
check_element_dated();
if ((_flags & FLAG_IMMUTABLE) != 0) {
throw new IllegalStateException();
}
}
/**
* Called after every set operation to invalidate
* the attached raw text. Also, if we were dated,
* we make a note that we're now current, since the
* latest set beats the previous invalidate. Also,
* if we were nil, we're no longer.
*/
private void set_commit() {
boolean wasNilled = ((_flags & FLAG_NIL) != 0);
_flags &= ~(FLAG_NIL | FLAG_ISDEFAULT);
if ((_flags & FLAG_STORE) != 0) {
_flags &= ~(FLAGS_DATED);
get_store().invalidate_text();
if (wasNilled) {
get_store().invalidate_nil();
}
} else {
_textsource = null;
}
}
/**
* Grabs the undelying litral representation, applying the
* implementation's wscanon rule.
* Null if not simple content.
*/
public final String get_wscanon_text() {
if ((_flags & FLAG_STORE) == 0) {
return apply_wscanon((String) _textsource);
} else {
return get_store().fetch_text(get_wscanon_rule());
}
}
/**
* This should set the value of the type from text,
* or throw an XmlValueOutOfRangeException if it can't.
*/
abstract protected void set_text(String text);
/**
* This should clear the value, and set it to whatever
* is supposed to be returned when the value is nilled.
*/
abstract protected void set_nil();
/**
* This should return the canonical string value of the primitive.
* Only called when non-nil.
*/
abstract protected String compute_text(NamespaceManager nsm);
// SIMPLE VALUE ACCESSORS BELOW -------------------------------------------
// numerics: fractional
public float getFloatValue() {
BigDecimal bd = getBigDecimalValue();
return bd == null ? 0.0f : bd.floatValue();
}
public double getDoubleValue() {
BigDecimal bd = getBigDecimalValue();
return bd == null ? 0.0 : bd.doubleValue();
}
public BigDecimal getBigDecimalValue() {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
new Object[]{getPrimitiveTypeName(), "numeric"});
}
// numerics: integral
public BigInteger getBigIntegerValue() {
BigDecimal bd = getBigDecimalValue();
return bd == null ? null : bd.toBigInteger();
}
public byte getByteValue() {
long l = getIntValue();
if (l > Byte.MAX_VALUE) {
throw new XmlValueOutOfRangeException();
}
if (l < Byte.MIN_VALUE) {
throw new XmlValueOutOfRangeException();
}
return (byte) l;
}
public short getShortValue() {
long l = getIntValue();
if (l > Short.MAX_VALUE) {
throw new XmlValueOutOfRangeException();
}
if (l < Short.MIN_VALUE) {
throw new XmlValueOutOfRangeException();
}
return (short) l;
}
public int getIntValue() {
long l = getLongValue();
if (l > Integer.MAX_VALUE) {
throw new XmlValueOutOfRangeException();
}
if (l < Integer.MIN_VALUE) {
throw new XmlValueOutOfRangeException();
}
return (int) l;
}
private static final BigInteger _max = BigInteger.valueOf(Long.MAX_VALUE);
private static final BigInteger _min = BigInteger.valueOf(Long.MIN_VALUE);
public long getLongValue() {
BigInteger b = getBigIntegerValue();
if (b == null) {
return 0L;
}
if (b.compareTo(_max) >= 0) {
throw new XmlValueOutOfRangeException();
}
if (b.compareTo(_min) <= 0) {
throw new XmlValueOutOfRangeException();
}
return b.longValue();
}
private static final XmlOptions _toStringOptions =
buildInnerPrettyOptions();
static XmlOptions buildInnerPrettyOptions() {
XmlOptions options = new XmlOptions();
options.setSaveInner();
options.setSavePrettyPrint();
options.setSaveAggressiveNamespaces();
options.setUseDefaultNamespace();
return options;
}
/*
private static final void dumpStack ( String msg )
{
try
{
java.io.FileOutputStream fos = new java.io.FileOutputStream( "C:\\ee.txt", true );
java.io.PrintStream ps = new java.io.PrintStream( fos );
ps.println( "======================================" );
ps.println( msg );
new Exception().printStackTrace( ps );
ps.close();
fos.close();
}
catch ( Exception e )
{
}
}
*/
public final String toString() {
synchronized (monitor()) {
return ensureStore().xmlText(_toStringOptions);
}
}
public String xmlText() {
return xmlText(null);
}
public String xmlText(XmlOptions options) {
XmlCursor cur = newCursorForce();
try {
return cur.xmlText(makeInnerOptions(options));
} finally {
cur.dispose();
}
}
// enums
public StringEnumAbstractBase getEnumValue() {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
new Object[]{getPrimitiveTypeName(), "enum"});
}
// various
public String getStringValue() {
if (isImmutable()) {
if ((_flags & FLAG_NIL) != 0) {
return null;
}
return compute_text(null);
}
// Since complex-content types don't have a "natural" string value, we
// emit the deeply concatenated, tag-removed content of the tag.
synchronized (monitor()) {
if (_isComplexContent()) {
return get_store().fetch_text(TypeStore.WS_PRESERVE);
}
check_dated();
if ((_flags & FLAG_NIL) != 0) {
return null;
}
return compute_text(has_store() ? get_store() : null);
}
}
public byte[] getByteArrayValue() {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
new Object[]{getPrimitiveTypeName(), "byte[]"});
}
public boolean getBooleanValue() {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
new Object[]{getPrimitiveTypeName(), "boolean"});
}
public GDate getGDateValue() {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
new Object[]{getPrimitiveTypeName(), "Date"});
}
public Date getDateValue() {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
new Object[]{getPrimitiveTypeName(), "Date"});
}
public Calendar getCalendarValue() {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
new Object[]{getPrimitiveTypeName(), "Calendar"});
}
public GDuration getGDurationValue() {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
new Object[]{getPrimitiveTypeName(), "Duration"});
}
public QName getQNameValue() {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
new Object[]{getPrimitiveTypeName(), "QName"});
}
public List getListValue() {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
new Object[]{getPrimitiveTypeName(), "List"});
}
public List xgetListValue() {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
new Object[]{getPrimitiveTypeName(), "List"});
}
public Object getObjectValue() {
return java_value(this);
}
// set this value
public final void setBooleanValue(boolean v) {
synchronized (monitor()) {
set_prepare();
set_boolean(v);
set_commit();
}
}
public final void setByteValue(byte v) {
synchronized (monitor()) {
set_prepare();
set_byte(v);
set_commit();
}
}
public final void setShortValue(short v) {
synchronized (monitor()) {
set_prepare();
set_short(v);
set_commit();
}
}
public final void setIntValue(int v) {
synchronized (monitor()) {
set_prepare();
set_int(v);
set_commit();
}
}
public final void setLongValue(long v) {
synchronized (monitor()) {
set_prepare();
set_long(v);
set_commit();
}
}
public final void setFloatValue(float v) {
synchronized (monitor()) {
set_prepare();
set_float(v);
set_commit();
}
}
public final void setDoubleValue(double v) {
synchronized (monitor()) {
set_prepare();
set_double(v);
set_commit();
}
}
public final void setByteArrayValue(byte[] obj) {
if (obj == null) {
setNil();
} else {
synchronized (monitor()) {
set_prepare();
set_ByteArray(obj);
set_commit();
}
}
}
public final void setEnumValue(StringEnumAbstractBase obj) {
if (obj == null) {
setNil();
} else {
synchronized (monitor()) {
set_prepare();
set_enum(obj);
set_commit();
}
}
}
public final void setBigIntegerValue(BigInteger obj) {
if (obj == null) {
setNil();
} else {
synchronized (monitor()) {
set_prepare();
set_BigInteger(obj);
set_commit();
}
}
}
public final void setBigDecimalValue(BigDecimal obj) {
if (obj == null) {
setNil();
} else {
synchronized (monitor()) {
set_prepare();
set_BigDecimal(obj);
set_commit();
}
}
}
public final void setCalendarValue(Calendar obj) {
if (obj == null) {
setNil();
} else {
synchronized (monitor()) {
set_prepare();
set_Calendar(obj);
set_commit();
}
}
}
public final void setDateValue(Date obj) {
if (obj == null) {
setNil();
} else {
synchronized (monitor()) {
set_prepare();
set_Date(obj);
set_commit();
}
}
}
public final void setGDateValue(GDate obj) {
if (obj == null) {
setNil();
} else {
synchronized (monitor()) {
set_prepare();
set_GDate(obj);
set_commit();
}
}
}
public final void setGDateValue(GDateSpecification obj) {
if (obj == null) {
setNil();
} else {
synchronized (monitor()) {
set_prepare();
set_GDate(obj);
set_commit();
}
}
}
public final void setGDurationValue(GDuration obj) {
if (obj == null) {
setNil();
} else {
synchronized (monitor()) {
set_prepare();
set_GDuration(obj);
set_commit();
}
}
}
public final void setGDurationValue(GDurationSpecification obj) {
if (obj == null) {
setNil();
} else {
synchronized (monitor()) {
set_prepare();
set_GDuration(obj);
set_commit();
}
}
}
public final void setQNameValue(QName obj) {
if (obj == null) {
setNil();
} else {
synchronized (monitor()) {
set_prepare();
set_QName(obj);
set_commit();
}
}
}
public final void setListValue(List<?> obj) {
if (obj == null) {
setNil();
} else {
synchronized (monitor()) {
set_prepare();
set_list(obj);
set_commit();
}
}
}
public final void setStringValue(String obj) {
if (obj == null) {
setNil();
} else {
synchronized (monitor()) {
set_prepare();
set_String(obj); /* strings are special, so set_String does its own commit.*/
}
}
}
public void setObjectValue(Object o) {
if (o == null) {
setNil();
return;
}
if (o instanceof XmlObject) {
set((XmlObject) o);
} else if (o instanceof String) {
setStringValue((String) o);
} else if (o instanceof StringEnumAbstractBase) {
setEnumValue((StringEnumAbstractBase) o);
} else if (o instanceof BigInteger) {
setBigIntegerValue((BigInteger) o);
} else if (o instanceof BigDecimal) {
setBigDecimalValue((BigDecimal) o);
} else if (o instanceof Byte) {
setByteValue((Byte) o);
} else if (o instanceof Short) {
setShortValue((Short) o);
} else if (o instanceof Integer) {
setIntValue((Integer) o);
} else if (o instanceof Long) {
setLongValue((Long) o);
} else if (o instanceof Boolean) {
setBooleanValue((Boolean) o);
} else if (o instanceof Float) {
setFloatValue((Float) o);
} else if (o instanceof Double) {
setDoubleValue((Double) o);
} else if (o instanceof Calendar) {
setCalendarValue(((Calendar) o));
} else if (o instanceof Date) {
setDateValue((Date) o);
} else if (o instanceof GDateSpecification) {
setGDateValue((GDateSpecification) o);
} else if (o instanceof GDurationSpecification) {
setGDurationValue((GDurationSpecification) o);
} else if (o instanceof QName) {
setQNameValue((QName) o);
} else if (o instanceof List) {
setListValue((List<?>) o);
} else if (o instanceof byte[]) {
setByteArrayValue((byte[]) o);
} else {
throw
new XmlValueNotSupportedException(
"Can't set union object of class : " +
o.getClass().getName());
}
}
public final void set_newValue(XmlObject obj) {
if (obj == null || obj.isNil()) {
setNil();
return;
}
primitive:
if (obj instanceof XmlAnySimpleType) {
XmlAnySimpleType v = (XmlAnySimpleType) obj;
SchemaType instanceType = ((SimpleValue) v).instanceType();
assert (instanceType != null) : "Nil case should have been handled already";
// handle lists
if (instanceType.getSimpleVariety() == SchemaType.LIST) {
synchronized (monitor()) {
set_prepare();
set_list(((SimpleValue) v).xgetListValue());
set_commit();
return;
}
}
// handle atomic types
synchronized (monitor()) {
assert (instanceType.getSimpleVariety() == SchemaType.ATOMIC);
switch (instanceType.getPrimitiveType().getBuiltinTypeCode()) {
default:
assert (false) : "encountered nonprimitive type.";
// case SchemaType.BTC_ANY_SIMPLE: This is handled below...
// but we eventually want to handle it with a treecopy, so
// eventually we should break here.
break primitive;
case SchemaType.BTC_BOOLEAN: {
boolean bool = ((SimpleValue) v).getBooleanValue();
set_prepare();
set_boolean(bool);
break;
}
case SchemaType.BTC_BASE_64_BINARY: {
byte[] byteArr = ((SimpleValue) v).getByteArrayValue();
set_prepare();
set_b64(byteArr);
break;
}
case SchemaType.BTC_HEX_BINARY: {
byte[] byteArr = ((SimpleValue) v).getByteArrayValue();
set_prepare();
set_hex(byteArr);
break;
}
case SchemaType.BTC_QNAME: {
QName name = ((SimpleValue) v).getQNameValue();
set_prepare();
set_QName(name);
break;
}
case SchemaType.BTC_FLOAT: {
float f = ((SimpleValue) v).getFloatValue();
set_prepare();
set_float(f);
break;
}
case SchemaType.BTC_DOUBLE: {
double d = ((SimpleValue) v).getDoubleValue();
set_prepare();
set_double(d);
break;
}
case SchemaType.BTC_DECIMAL: {
switch (instanceType.getDecimalSize()) {
case SchemaType.SIZE_BYTE: {
byte b = ((SimpleValue) v).getByteValue();
set_prepare();
set_byte(b);
break;
}
case SchemaType.SIZE_SHORT: {
short s = ((SimpleValue) v).getShortValue();
set_prepare();
set_short(s);
break;
}
case SchemaType.SIZE_INT: {
int i = ((SimpleValue) v).getIntValue();
set_prepare();
set_int(i);
break;
}
case SchemaType.SIZE_LONG: {
long l = ((SimpleValue) v).getLongValue();
set_prepare();
set_long(l);
break;
}
case SchemaType.SIZE_BIG_INTEGER: {
BigInteger bi = ((SimpleValue) v).getBigIntegerValue();
set_prepare();
set_BigInteger(bi);
break;
}
default: {
assert (false) : "invalid numeric bit count";
// fallthrough
}
case SchemaType.SIZE_BIG_DECIMAL: {
BigDecimal bd = ((SimpleValue) v).getBigDecimalValue();
set_prepare();
set_BigDecimal(bd);
break;
}
}
break;
}
case SchemaType.BTC_ANY_URI: {
String uri = v.getStringValue();
set_prepare();
set_text(uri);
break;
}
case SchemaType.BTC_NOTATION: {
String s = v.getStringValue();
set_prepare();
set_notation(s);
break;
}
case SchemaType.BTC_DURATION: {
GDuration gd = ((SimpleValue) v).getGDurationValue();
set_prepare();
set_GDuration(gd);
break;
}
case SchemaType.BTC_DATE_TIME:
case SchemaType.BTC_TIME:
case SchemaType.BTC_DATE:
case SchemaType.BTC_G_YEAR_MONTH:
case SchemaType.BTC_G_YEAR:
case SchemaType.BTC_G_MONTH_DAY:
case SchemaType.BTC_G_DAY:
case SchemaType.BTC_G_MONTH: {
GDate gd = ((SimpleValue) v).getGDateValue();
set_prepare();
set_GDate(gd);
break;
}
case SchemaType.BTC_STRING: {
String s = v.getStringValue();
set_prepare();
set_String(s);
break;
}
case SchemaType.BTC_ANY_SIMPLE: {
boolean pushed = false;
if (!v.isImmutable()) {
pushed = true;
NamespaceContext.push(new NamespaceContext(v));
}
try {
set_prepare();
set_xmlanysimple(v);
} finally {
if (pushed) {
NamespaceContext.pop();
}
}
break;
}
}
set_commit();
return; // primitive node tree copy handled.
}
}
throw new IllegalStateException("Complex type unexpected");
}
private TypeStoreUser setterHelper(XmlObjectBase src) {
check_orphaned();
src.check_orphaned();
return
get_store().copy_contents_from(src.get_store()).
get_store().change_type(src.schemaType());
}
public final XmlObject set(XmlObject src) {
if (isImmutable()) {
throw new IllegalStateException("Cannot set the value of an immutable XmlObject");
}
XmlObjectBase obj = underlying(src);
TypeStoreUser newObj = this;
if (obj == null) {
setNil();
return this;
}
if (obj.isImmutable()) {
setStringValue(obj.getStringValue());
} else {
boolean noSyncThis = preCheck();
boolean noSyncObj = obj.preCheck();
if (monitor() == obj.monitor()) // both are in the same locale
{
if (noSyncThis) // the locale is not sync
{
newObj = setterHelper(obj);
} else // the locale is sync
{
synchronized (monitor()) {
newObj = setterHelper(obj);
}
}
} else // on different locale's
{
if (noSyncThis) {
if (noSyncObj) // both unsync
{
newObj = setterHelper(obj);
} else // only obj is sync
{
synchronized (obj.monitor()) {
newObj = setterHelper(obj);
}
}
} else {
if (noSyncObj) // only this is sync
{
synchronized (monitor()) {
newObj = setterHelper(obj);
}
} else // both are sync can't avoid the global lock
{
boolean acquired = false;
try {
// about to grab two locks: don't deadlock ourselves
GlobalLock.acquire();
acquired = true;
synchronized (monitor()) {
synchronized (obj.monitor()) {
GlobalLock.release();
acquired = false;
newObj = setterHelper(obj);
}
}
} catch (InterruptedException e) {
throw new XmlRuntimeException(e);
} finally {
if (acquired) {
GlobalLock.release();
}
}
}
}
}
}
return (XmlObject) newObj;
}
public final XmlObject generatedSetterHelperImpl(XmlObject src, QName propName, int index,
short kindSetterHelper) {
XmlObjectBase srcObj = underlying(src);
if (srcObj == null) {
synchronized (monitor()) {
XmlObjectBase target = getTargetForSetter(propName, index, kindSetterHelper);
target.setNil();
return target;
}
}
if (srcObj.isImmutable()) {
synchronized (monitor()) {
XmlObjectBase target = getTargetForSetter(propName, index, kindSetterHelper);
target.setStringValue(srcObj.getStringValue());
return target;
}
}
boolean noSyncThis = preCheck();
boolean noSyncObj = srcObj.preCheck();
if (monitor() == srcObj.monitor()) {
// both are in the same locale
if (noSyncThis) {
// the locale is not sync
return (XmlObject) objSetterHelper(srcObj, propName, index, kindSetterHelper);
} else {
// the locale is sync
synchronized (monitor()) {
return (XmlObject) objSetterHelper(srcObj, propName, index, kindSetterHelper);
}
}
}
if (noSyncThis) {
// on different locale's
if (noSyncObj) {
// both unsync
return (XmlObject) objSetterHelper(srcObj, propName, index, kindSetterHelper);
} else {
// only obj is sync
synchronized (srcObj.monitor()) {
return (XmlObject) objSetterHelper(srcObj, propName, index, kindSetterHelper);
}
}
} else {
if (noSyncObj) {
// only this is sync
synchronized (monitor()) {
return (XmlObject) objSetterHelper(srcObj, propName, index, kindSetterHelper);
}
} else {
// both are sync can't avoid the global lock
boolean acquired = false;
try {
// about to grab two locks: don't deadlock ourselves
GlobalLock.acquire();
acquired = true;
synchronized (monitor()) {
synchronized (srcObj.monitor()) {
GlobalLock.release();
acquired = false;
return (XmlObject) objSetterHelper(srcObj, propName, index, kindSetterHelper);
}
}
} catch (InterruptedException e) {
throw new XmlRuntimeException(e);
} finally {
if (acquired) {
GlobalLock.release();
}
}
}
}
}
private TypeStoreUser objSetterHelper(XmlObjectBase srcObj, QName propName, int index, short kindSetterHelper) {
XmlObjectBase target = getTargetForSetter(propName, index, kindSetterHelper);
target.check_orphaned();
srcObj.check_orphaned();
return target.get_store().copy_contents_from(srcObj.get_store()).
get_store().change_type(srcObj.schemaType());
}
private XmlObjectBase getTargetForSetter(QName propName, int index, short kindSetterHelper) {
switch (kindSetterHelper) {
case KIND_SETTERHELPER_SINGLETON: {
check_orphaned();
XmlObjectBase target;
target = (XmlObjectBase) get_store().find_element_user(propName, index);
if (target == null) {
target = (XmlObjectBase) get_store().add_element_user(propName);
}
if (target.isImmutable()) {
throw new IllegalStateException("Cannot set the value of an immutable XmlObject");
}
return target;
}
case KIND_SETTERHELPER_ARRAYITEM: {
check_orphaned();
XmlObjectBase target;
target = (XmlObjectBase) get_store().find_element_user(propName, index);
if (target == null) {
throw new IndexOutOfBoundsException();
}
if (target.isImmutable()) {
throw new IllegalStateException("Cannot set the value of an immutable XmlObject");
}
return target;
}
default:
throw new IllegalArgumentException("Unknown kindSetterHelper: " + kindSetterHelper);
}
}
/**
* Same as set() but unsynchronized.
* Warning: Using this method in mutithreaded environment can cause invalid states.
*/
public final XmlObject _set(XmlObject src) {
if (isImmutable()) {
throw new IllegalStateException("Cannot set the value of an immutable XmlObject");
}
XmlObjectBase obj = underlying(src);
TypeStoreUser newObj = this;
if (obj == null) {
setNil();
return this;
}
if (obj.isImmutable()) {
setStringValue(obj.getStringValue());
} else {
check_orphaned();
obj.check_orphaned();
newObj = get_store().copy_contents_from(obj.get_store()).
get_store().change_type(obj.schemaType());
}
return (XmlObject) newObj;
}
protected void set_list(List<?> list) {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
new Object[]{"List", getPrimitiveTypeName()});
}
protected void set_boolean(boolean v) {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
new Object[]{"boolean", getPrimitiveTypeName()});
}
protected void set_byte(byte v) {
set_int(v);
}
protected void set_short(short v) {
set_int(v);
}
protected void set_int(int v) {
set_long(v);
}
protected void set_long(long v) {
set_BigInteger(BigInteger.valueOf(v));
}
protected void set_char(char v) {
set_String(Character.toString(v));
}
protected void set_float(float v) {
set_BigDecimal(new BigDecimal(v));
}
protected void set_double(double v) {
set_BigDecimal(new BigDecimal(v));
}
protected void set_enum(StringEnumAbstractBase e) {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
new Object[]{"enum", getPrimitiveTypeName()});
}
protected void set_ByteArray(byte[] b) {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
new Object[]{"byte[]", getPrimitiveTypeName()});
}
protected void set_b64(byte[] b) {
set_ByteArray(b);
}
protected void set_hex(byte[] b) {
set_ByteArray(b);
}
protected void set_BigInteger(BigInteger v) {
set_BigDecimal(new BigDecimal(v));
}
protected void set_BigDecimal(BigDecimal v) {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
new Object[]{"numeric", getPrimitiveTypeName()});
}
protected void set_Date(Date v) {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
new Object[]{"Date", getPrimitiveTypeName()});
}
protected void set_Calendar(Calendar v) {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
new Object[]{"Calendar", getPrimitiveTypeName()});
}
protected void set_GDate(GDateSpecification v) {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
new Object[]{"Date", getPrimitiveTypeName()});
}
protected void set_GDuration(GDurationSpecification v) {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
new Object[]{"Duration", getPrimitiveTypeName()});
}
protected void set_ComplexXml(XmlObject v) {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
new Object[]{"complex content", getPrimitiveTypeName()});
}
protected void set_QName(QName v) {
throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
new Object[]{"QName", getPrimitiveTypeName()});
}
protected void set_notation(String v) {
throw new XmlValueNotSupportedException();
}
protected void set_xmlanysimple(XmlAnySimpleType v) {
set_String(v.getStringValue());
}
private String getPrimitiveTypeName() {
SchemaType type = schemaType();
if (type.isNoType()) {
return "unknown";
}
SchemaType t = type.getPrimitiveType();
if (t == null) {
return "complex";
} else {
return t.getName().getLocalPart();
}
}
private boolean comparable_value_spaces(SchemaType t1, SchemaType t2) {
assert (t1.getSimpleVariety() != SchemaType.UNION && t2.getSimpleVariety() != SchemaType.UNION);
if (!t1.isSimpleType() && !t2.isSimpleType()) {
return (t1.getContentType() == t2.getContentType());
}
if (!t1.isSimpleType() || !t2.isSimpleType()) {
return false;
}
if (t1.getSimpleVariety() == SchemaType.LIST && t2.getSimpleVariety() == SchemaType.LIST) {
return true;
}
if (t1.getSimpleVariety() == SchemaType.LIST || t2.getSimpleVariety() == SchemaType.LIST) {
return false;
}
return (t1.getPrimitiveType().equals(t2.getPrimitiveType()));
}
private boolean valueEqualsImpl(XmlObject xmlobj) {
check_dated();
SchemaType typethis = instanceType();
SchemaType typeother = ((SimpleValue) xmlobj).instanceType();
if (typethis == null && typeother == null) // detects nil
{
return true;
}
if (typethis == null || typeother == null) {
return false;
}
if (!comparable_value_spaces(typethis, typeother)) {
return false;
}
if (xmlobj.schemaType().getSimpleVariety() == SchemaType.UNION) {
return (underlying(xmlobj)).equal_to(this);
}
return equal_to(xmlobj);
}
public final boolean valueEquals(XmlObject xmlobj) {
boolean acquired = false;
try {
if (isImmutable()) {
if (xmlobj.isImmutable()) {
return valueEqualsImpl(xmlobj);
} else {
synchronized (xmlobj.monitor()) {
return valueEqualsImpl(xmlobj);
}
}
} else {
if (xmlobj.isImmutable() || monitor() == xmlobj.monitor()) {
synchronized (monitor()) {
return valueEqualsImpl(xmlobj);
}
} else {
GlobalLock.acquire();
acquired = true;
synchronized (monitor()) {
synchronized (xmlobj.monitor()) {
GlobalLock.release();
acquired = false;
return valueEqualsImpl(xmlobj);
}
}
}
}
} catch (InterruptedException e) {
throw new XmlRuntimeException(e);
} finally {
if (acquired) {
GlobalLock.release();
}
}
}
/**
* Implements Comparable. This compareTo is inconsistent with
* equals unless isImmutable() is true.
*/
public final int compareTo(Object obj) {
int result = compareValue((XmlObject) obj); // can throw ClassCast
if (result == 2) {
throw new ClassCastException();
}
return result;
}
/**
* Allowed to return 2 for incomparable.
*/
private int compareValueImpl(XmlObject xmlobj) {
SchemaType type1, type2;
try {
type1 = instanceType();
type2 = ((SimpleValue) xmlobj).instanceType();
} catch (XmlValueOutOfRangeException e) {
return 2;
}
if (type1 == null && type2 == null) {
return 0;
}
if (type1 == null || type2 == null) {
return 2;
}
if (!type1.isSimpleType() || type1.isURType()) {
return 2;
}
if (!type2.isSimpleType() || type2.isURType()) {
return 2;
}
type1 = type1.getPrimitiveType();
type2 = type2.getPrimitiveType();
// Different value spaces: different
if (type1.getBuiltinTypeCode() != type2.getBuiltinTypeCode()) {
return 2;
}
// now we'll depend on our impl class to do the work
return compare_to(xmlobj);
}
public final int compareValue(XmlObject xmlobj) {
if (xmlobj == null) {
return 2;
}
boolean acquired = false;
try {
if (isImmutable()) {
if (xmlobj.isImmutable()) {
return compareValueImpl(xmlobj);
} else {
synchronized (xmlobj.monitor()) {
return compareValueImpl(xmlobj);
}
}
} else {
if (xmlobj.isImmutable() || monitor() == xmlobj.monitor()) {
synchronized (monitor()) {
return compareValueImpl(xmlobj);
}
} else {
GlobalLock.acquire();
acquired = true;
synchronized (monitor()) {
synchronized (xmlobj.monitor()) {
GlobalLock.release();
acquired = false;
return compareValueImpl(xmlobj);
}
}
}
}
} catch (InterruptedException e) {
throw new XmlRuntimeException(e);
} finally {
if (acquired) {
GlobalLock.release();
}
}
}
/**
* This implementation of compare_to is allowed to do two
* unusual things:
* (1) it can assume that the xmlobj passed has a primitive
* type underlying the instance type that matches the
* current instance, and that neither is nil.
* (2) it is allowed to return 2 for "incomparable";
* it should not throw an exception.
*/
protected int compare_to(XmlObject xmlobj) {
if (equal_to(xmlobj)) {
return 0;
}
return 2;
}
protected abstract boolean equal_to(XmlObject xmlobj);
protected abstract int value_hash_code();
public int valueHashCode() {
synchronized (monitor()) {
return value_hash_code();
}
}
public boolean isInstanceOf(SchemaType type) {
SchemaType myType;
if (type.getSimpleVariety() != SchemaType.UNION) {
for (myType = instanceType(); myType != null; myType = myType.getBaseType()) {
if (type == myType) {
return true;
}
}
} else {
Set<SchemaType> ctypes = new HashSet<>(Arrays.asList(type.getUnionConstituentTypes()));
for (myType = instanceType(); myType != null; myType = myType.getBaseType()) {
if (ctypes.contains(myType)) {
return true;
}
}
}
return false;
}
public final boolean equals(Object obj) {
if (!isImmutable()) {
return super.equals(obj);
}
if (!(obj instanceof XmlObject)) {
return false;
}
XmlObject xmlobj = (XmlObject) obj;
if (!xmlobj.isImmutable()) {
return false;
}
return valueEquals(xmlobj);
}
public final int hashCode() {
if (!isImmutable()) {
return super.hashCode();
}
synchronized (monitor()) {
if (isNil()) {
return 0;
}
return value_hash_code();
}
}
private static final XmlObject[] EMPTY_RESULT = new XmlObject[0];
/**
* Selects the contents of the children elements with the given name.
*/
public XmlObject[] selectChildren(QName elementName) {
XmlCursor xc = this.newCursor();
try {
if (!xc.isContainer()) {
return EMPTY_RESULT;
}
List<XmlObject> result = new ArrayList<>();
if (xc.toChild(elementName)) {
// look for elements
do {
result.add(xc.getObject());
}
while (xc.toNextSibling(elementName));
}
if (result.size() == 0) {
return EMPTY_RESULT;
} else {
return result.toArray(EMPTY_RESULT);
}
} finally {
xc.dispose();
}
}
/**
* Selects the contents of the children elements with the given name.
*/
public XmlObject[] selectChildren(String elementUri, String elementLocalName) {
return selectChildren(new QName(elementUri, elementLocalName));
}
/**
* Selects the contents of the children elements that are contained in the elementNameSet.
*/
public XmlObject[] selectChildren(QNameSet elementNameSet) {
if (elementNameSet == null) {
throw new IllegalArgumentException();
}
XmlCursor xc = this.newCursor();
try {
if (!xc.isContainer()) {
return EMPTY_RESULT;
}
List<XmlObject> result = new ArrayList<>();
if (xc.toFirstChild()) {
// look for elements
do {
assert xc.isContainer();
if (elementNameSet.contains(xc.getName())) {
result.add(xc.getObject());
}
}
while (xc.toNextSibling());
}
if (result.size() == 0) {
return EMPTY_RESULT;
} else {
return result.toArray(EMPTY_RESULT);
}
} finally {
xc.dispose();
}
}
/**
* Selects the content of the attribute with the given name.
*/
public XmlObject selectAttribute(QName attributeName) {
XmlCursor xc = this.newCursor();
try {
if (!xc.isContainer()) {
return null;
}
if (xc.toFirstAttribute()) {
//look for attributes
do {
if (xc.getName().equals(attributeName)) {
return xc.getObject();
}
}
while (xc.toNextAttribute());
}
return null;
} finally {
xc.dispose();
}
}
/**
* Selects the content of the attribute with the given name.
*/
public XmlObject selectAttribute(String attributeUri, String attributeLocalName) {
return selectAttribute(new QName(attributeUri, attributeLocalName));
}
/**
* Selects the contents of the attributes that are contained in the elementNameSet.
*/
public XmlObject[] selectAttributes(QNameSet attributeNameSet) {
if (attributeNameSet == null) {
throw new IllegalArgumentException();
}
XmlCursor xc = this.newCursor();
try {
if (!xc.isContainer()) {
return EMPTY_RESULT;
}
List<XmlObject> result = new ArrayList<>();
if (xc.toFirstAttribute()) {
//look for attributes
do {
if (attributeNameSet.contains(xc.getName())) {
result.add(xc.getObject());
}
}
while (xc.toNextAttribute());
}
if (result.size() == 0) {
return EMPTY_RESULT;
} else {
return result.toArray(EMPTY_RESULT);
}
} finally {
xc.dispose();
}
}
/**
* This method can writeReplace either an unwrapped XmlObjectBase
* or an XBean proxy. A "true" argument means unwrapped.
* <p>
* The serialization strategy for XmlObjects is this:
* <p>
* (1) Only the root XmlObject for a document actually gets
* fully serialized; it is serialized as a SerializedRootObject,
* which simply saves itself as XML text.
* <p>
* (2) Interior XmlObjects get serialized as a reference to the
* root XmlObject for their document, plus an integer which
* indicates the position of the XmlObject within the owner
* document. This pair is stored as a SerializedInteriorObject.
* <p>
* Both objects can be maked as wrapped or unwrapped. If wrapped,
* then the proxy is returned when deserializing; if unwrapped, then
* the proxy is stripped when deserializing.
*/
public Object writeReplace() {
synchronized (monitor()) {
if (isRootXmlObject()) {
return new SerializedRootObject(this);
}
return new SerializedInteriorObject(this, getRootXmlObject());
}
}
/**
* True if the object is at the root of the document.
*/
private boolean isRootXmlObject() {
XmlCursor cur = newCursor();
if (cur == null) {
return false;
}
boolean result = !cur.toParent();
cur.dispose();
return result;
}
/**
* Gets the root XmlObject for this document.
*/
private XmlObject getRootXmlObject() {
XmlCursor cur = newCursor();
if (cur == null) {
return this;
}
cur.toStartDoc();
XmlObject result = cur.getObject();
cur.dispose();
return result;
}
/**
* Serializable rewrite object that knows how to resolve
* to an XmlObjectBase or a proxy for the root object of
* a document.
*/
private static class SerializedRootObject implements Serializable {
private static final long serialVersionUID = 1;
transient Class<?> _xbeanClass;
transient XmlObject _impl;
private SerializedRootObject(XmlObject impl) {
_xbeanClass = impl.schemaType().getJavaClass();
_impl = impl;
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeObject(_xbeanClass);
// the first short is written out for backwards compatibility
// it will always be zero for objects written with
// this code, but it used to be the first 2 bytes of the
// writeUTF() method
out.writeShort((short) 0);
out.writeShort(MAJOR_VERSION_NUMBER);
out.writeShort(MINOR_VERSION_NUMBER);
// CR122401 - need to use writeObject instead of writeUTF
// for xmlText as writeUTF has a length limitation of
// 65535 bytes
String xmlText = _impl.xmlText();
out.writeObject(xmlText);
out.writeBoolean(false);
}
private void readObject(ObjectInputStream in) throws IOException {
try {
// read class object first - this is
// first just for historical reasons - really
// it would be better to have the version numbers
// first
_xbeanClass = (Class<?>) in.readObject();
int utfBytes = in.readUnsignedShort();
// determine version numbers
// if utfBytes is non-zero then we default to 0.0
// otherwise expect major and minor version numbers
// to be next entries in stream
int majorVersionNum = 0;
int minorVersionNum = 0;
if (utfBytes == 0) {
majorVersionNum = in.readUnsignedShort();
minorVersionNum = in.readUnsignedShort();
}
String xmlText;
switch (majorVersionNum) {
case 0: // original, unnumbered version
// minorVersionNum is always zero
xmlText = readObjectV0(in, utfBytes);
in.readBoolean(); // ignored
break;
case 1:
switch (minorVersionNum) {
case 1:
xmlText = (String) in.readObject();
in.readBoolean(); // ignored
break;
default:
throw new IOException("Deserialization error: " +
"version number " + majorVersionNum + "." +
minorVersionNum + " not supported.");
}
break;
default:
throw new IOException("Deserialization error: " +
"version number " + majorVersionNum + "." +
minorVersionNum + " not supported.");
}
XmlOptions opts = new XmlOptions().setDocumentType(XmlBeans.typeForClass(_xbeanClass));
_impl = XmlBeans.getContextTypeLoader().parse(xmlText, null, opts);
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
// this method is for reading the UTF-8 String that used to be
// written out for a serialized XmlObject according to the
// original format before this fix, i.e. it expects it
// to have been written using the following algorithm:
//
// writeObject(Class object)
// writeUTF(xmlText of object as String)
// writeBoolean()
//
// this method is passed the original input stream positioned as though
// it had just read the class object plus the next 2 bytes. Those 2
// bytes are interpreted as an unsigned short saying how many more
// bytes there are representing the bytes of the UTF-8-formatted String;
// this value is passed in as the argument utfBytes
private String readObjectV0(ObjectInputStream in, int utfBytes)
throws IOException {
// allow an extra 2 bytes up front for the unsigned short
byte[] bArray = new byte[utfBytes + 2];
// for format of these first 2 bytes see
// Java API docs - DataOutputStream.writeShort()
bArray[0] = (byte) (0xff & (utfBytes >> 8));
bArray[1] = (byte) (0xff & utfBytes);
// read the next numBytes bytes from the input stream
// into the byte array starting at offset 2; this may
// take multiple calls to read()
int totalBytesRead = 0;
int numRead;
while (totalBytesRead < utfBytes) {
numRead =
in.read(bArray, 2 + totalBytesRead, utfBytes - totalBytesRead);
if (numRead == -1) // reached end of stream
{
break;
}
totalBytesRead += numRead;
}
if (totalBytesRead != utfBytes) {
throw new IOException("Error reading backwards compatible " +
"XmlObject: number of bytes read (" + totalBytesRead +
") != number expected (" + utfBytes + ")");
}
// now set up a DataInputStream to read those
// bytes as a UTF-8 String i.e. as though we'd never
// read the first 2 bytes from the original stream
DataInputStream dis = null;
String str;
try {
dis = new DataInputStream(new ByteArrayInputStream(bArray));
str = dis.readUTF();
} finally {
if (dis != null) {
dis.close();
}
}
return str;
}
private Object readResolve() throws ObjectStreamException {
return _impl;
}
}
/**
* Serializable rewrite object that knows how to resolve
* to an XmlObjectBase or a proxy for an interior position
* within a document.
*/
private static class SerializedInteriorObject implements Serializable {
private static final long serialVersionUID = 1;
transient XmlObject _impl;
transient XmlObject _root;
private SerializedInteriorObject(XmlObject impl, XmlObject root) {
_impl = impl;
_root = root;
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeObject(_root);
out.writeBoolean(false);
out.writeInt(distanceToRoot());
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
_root = (XmlObject) in.readObject();
in.readBoolean();
_impl = objectAtDistance(in.readInt());
}
private Object readResolve() throws ObjectStreamException {
return _impl;
}
private int distanceToRoot() {
XmlCursor cur = _impl.newCursor();
int count = 0;
while (!cur.toPrevToken().isNone()) {
if (!cur.currentTokenType().isNamespace()) {
count += 1;
// System.out.println("Count: " + count + " " + cur.currentTokenType().toString() + " " + QName.pretty(cur.getName()));
}
}
cur.dispose();
return count;
}
private XmlObject objectAtDistance(int count) {
XmlCursor cur = _root.newCursor();
while (count > 0) {
cur.toNextToken();
if (!cur.currentTokenType().isNamespace()) {
count -= 1;
// System.out.println("Count: " + count + " " + cur.currentTokenType().toString() + " " + QName.pretty(cur.getName()));
}
}
XmlObject result = cur.getObject();
cur.dispose();
return result;
}
}
protected static Object java_value(XmlObject obj) {
if (obj.isNil()) {
return null;
}
if (!(obj instanceof XmlAnySimpleType)) {
return obj;
}
SchemaType instanceType = ((SimpleValue) obj).instanceType();
assert (instanceType != null) : "Nil case should have been handled above";
// handle lists
if (instanceType.getSimpleVariety() == SchemaType.LIST) {
return ((SimpleValue) obj).getListValue();
}
SimpleValue base = (SimpleValue) obj;
switch (instanceType.getPrimitiveType().getBuiltinTypeCode()) {
case SchemaType.BTC_BOOLEAN:
return base.getBooleanValue() ? Boolean.TRUE : Boolean.FALSE;
case SchemaType.BTC_BASE_64_BINARY:
case SchemaType.BTC_HEX_BINARY:
return base.getByteArrayValue();
case SchemaType.BTC_QNAME:
return base.getQNameValue();
case SchemaType.BTC_FLOAT:
return base.getFloatValue();
case SchemaType.BTC_DOUBLE:
return base.getDoubleValue();
case SchemaType.BTC_DECIMAL: {
switch (instanceType.getDecimalSize()) {
case SchemaType.SIZE_BYTE:
return base.getByteValue();
case SchemaType.SIZE_SHORT:
return base.getShortValue();
case SchemaType.SIZE_INT:
return base.getIntValue();
case SchemaType.SIZE_LONG:
return base.getLongValue();
case SchemaType.SIZE_BIG_INTEGER:
return base.getBigIntegerValue();
default:
assert (false) : "invalid numeric bit count";
// fallthrough
case SchemaType.SIZE_BIG_DECIMAL:
return base.getBigDecimalValue();
}
}
case SchemaType.BTC_ANY_URI:
return base.getStringValue();
case SchemaType.BTC_DURATION:
return base.getGDurationValue();
case SchemaType.BTC_DATE_TIME:
case SchemaType.BTC_TIME:
case SchemaType.BTC_DATE:
case SchemaType.BTC_G_YEAR_MONTH:
case SchemaType.BTC_G_YEAR:
case SchemaType.BTC_G_MONTH_DAY:
case SchemaType.BTC_G_DAY:
case SchemaType.BTC_G_MONTH:
return base.getCalendarValue();
default:
assert (false) : "encountered nonprimitive type.";
// fallthrough
// NB: for string enums we just do java.lang.String
// when in the context of unions. It's easier on users.
case SchemaType.BTC_NOTATION:
case SchemaType.BTC_STRING:
case SchemaType.BTC_ANY_SIMPLE:
// return base.getStringValue();
return base.getStringValue();
}
}
/**
* Called by code generated code to get the default attribute value
* for a given attribute name, or null if none.
*/
protected XmlAnySimpleType get_default_attribute_value(QName name) {
SchemaType sType = schemaType();
SchemaAttributeModel aModel = sType.getAttributeModel();
if (aModel == null) {
return null;
}
SchemaLocalAttribute sAttr = aModel.getAttribute(name);
if (sAttr == null) {
return null;
}
return sAttr.getDefaultValue();
}
private List<XmlObjectBase> getBaseArray(QName elementName) {
check_orphaned();
List<XmlObjectBase> targetList = new java.util.ArrayList<>();
get_store().find_all_element_users(elementName, targetList);
return targetList;
}
private List<XmlObjectBase> getBaseArray(QNameSet elementSet) {
check_orphaned();
List<XmlObjectBase> targetList = new java.util.ArrayList<>();
get_store().find_all_element_users(elementSet, targetList);
return targetList;
}
protected <T> T[] getObjectArray(QName elementName, Function<SimpleValue, T> fun, IntFunction<T[]> arrayCon) {
synchronized (monitor()) {
return getBaseArray(elementName).stream().map(fun).toArray(arrayCon);
}
}
protected <T> T[] getEnumArray(QName elementName, IntFunction<T[]> arrayCon) {
synchronized (monitor()) {
return getBaseArray(elementName).stream().map(SimpleValue::getEnumValue).toArray(arrayCon);
}
}
protected boolean[] getBooleanArray(QName elementName) {
synchronized (monitor()) {
List<XmlObjectBase> targetList = getBaseArray(elementName);
boolean[] result = new boolean[targetList.size()];
for (int i = 0; i < result.length; i++) {
result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getBooleanValue();
}
return result;
}
}
protected float[] getFloatArray(QName elementName) {
synchronized (monitor()) {
List<XmlObjectBase> targetList = getBaseArray(elementName);
float[] result = new float[targetList.size()];
for (int i = 0; i < result.length; i++) {
result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getFloatValue();
}
return result;
}
}
protected double[] getDoubleArray(QName elementName) {
synchronized (monitor()) {
List<XmlObjectBase> targetList = getBaseArray(elementName);
return targetList.stream()
.map(org.apache.xmlbeans.SimpleValue.class::cast)
.mapToDouble(org.apache.xmlbeans.SimpleValue::getDoubleValue)
.toArray();
}
}
protected byte[] getByteArray(QName elementName) {
synchronized (monitor()) {
List<XmlObjectBase> targetList = getBaseArray(elementName);
byte[] result = new byte[targetList.size()];
for (int i = 0; i < result.length; i++) {
result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getByteValue();
}
return result;
}
}
protected short[] getShortArray(QName elementName) {
synchronized (monitor()) {
List<XmlObjectBase> targetList = getBaseArray(elementName);
short[] result = new short[targetList.size()];
for (int i = 0; i < result.length; i++) {
result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getShortValue();
}
return result;
}
}
protected int[] getIntArray(QName elementName) {
synchronized (monitor()) {
List<XmlObjectBase> targetList = getBaseArray(elementName);
return targetList.stream()
.map(org.apache.xmlbeans.SimpleValue.class::cast)
.mapToInt(org.apache.xmlbeans.SimpleValue::getIntValue)
.toArray();
}
}
protected long[] getLongArray(QName elementName) {
synchronized (monitor()) {
List<XmlObjectBase> targetList = getBaseArray(elementName);
return targetList.stream()
.map(org.apache.xmlbeans.SimpleValue.class::cast)
.mapToLong(org.apache.xmlbeans.SimpleValue::getLongValue)
.toArray();
}
}
protected <T extends XmlObject> T[] getXmlObjectArray(QName elementName, T[] arrayCon) {
synchronized (monitor()) {
return getBaseArray(elementName).toArray(arrayCon);
}
}
protected <T> T[] getObjectArray(QNameSet elementSet, Function<SimpleValue, T> fun, IntFunction<T[]> arrayCon) {
synchronized (monitor()) {
return getBaseArray(elementSet).stream().map(fun).toArray(arrayCon);
}
}
protected <T> T[] getEnumArray(QNameSet elementSet, IntFunction<T[]> arrayCon) {
synchronized (monitor()) {
return getBaseArray(elementSet).stream().map(SimpleValue::getEnumValue).toArray(arrayCon);
}
}
protected boolean[] getBooleanArray(QNameSet elementSet) {
synchronized (monitor()) {
List<XmlObjectBase> targetList = getBaseArray(elementSet);
boolean[] result = new boolean[targetList.size()];
for (int i = 0; i < result.length; i++) {
result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getBooleanValue();
}
return result;
}
}
protected float[] getFloatArray(QNameSet elementSet) {
synchronized (monitor()) {
List<XmlObjectBase> targetList = getBaseArray(elementSet);
float[] result = new float[targetList.size()];
for (int i = 0; i < result.length; i++) {
result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getFloatValue();
}
return result;
}
}
protected double[] getDoubleArray(QNameSet elementSet) {
synchronized (monitor()) {
List<XmlObjectBase> targetList = getBaseArray(elementSet);
return targetList.stream()
.map(org.apache.xmlbeans.SimpleValue.class::cast)
.mapToDouble(org.apache.xmlbeans.SimpleValue::getDoubleValue)
.toArray();
}
}
protected byte[] getByteArray(QNameSet elementSet) {
synchronized (monitor()) {
List<XmlObjectBase> targetList = getBaseArray(elementSet);
byte[] result = new byte[targetList.size()];
for (int i = 0; i < result.length; i++) {
result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getByteValue();
}
return result;
}
}
protected short[] getShortArray(QNameSet elementSet) {
synchronized (monitor()) {
List<XmlObjectBase> targetList = getBaseArray(elementSet);
short[] result = new short[targetList.size()];
for (int i = 0; i < result.length; i++) {
result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getShortValue();
}
return result;
}
}
protected int[] getIntArray(QNameSet elementSet) {
synchronized (monitor()) {
List<XmlObjectBase> targetList = getBaseArray(elementSet);
return targetList.stream()
.map(org.apache.xmlbeans.SimpleValue.class::cast)
.mapToInt(org.apache.xmlbeans.SimpleValue::getIntValue)
.toArray();
}
}
protected long[] getLongArray(QNameSet elementSet) {
synchronized (monitor()) {
List<XmlObjectBase> targetList = getBaseArray(elementSet);
return targetList.stream()
.map(org.apache.xmlbeans.SimpleValue.class::cast)
.mapToLong(org.apache.xmlbeans.SimpleValue::getLongValue)
.toArray();
}
}
protected <T extends XmlObject> T[] getXmlObjectArray(QNameSet elementSet, T[] arrayCon) {
synchronized (monitor()) {
return getBaseArray(elementSet).toArray(arrayCon);
}
}
protected <T extends XmlObject> T[] xgetArray(QName elementName, IntFunction<T[]> arrayCon) {
synchronized (monitor()) {
check_orphaned();
java.util.List<T> targetList = new java.util.ArrayList<>();
get_store().find_all_element_users(elementName, targetList);
return targetList.stream().toArray(arrayCon);
}
}
protected <T extends XmlObject> T[] xgetArray(QNameSet elementSet, IntFunction<T[]> arrayCon) {
synchronized (monitor()) {
check_orphaned();
java.util.List<T> targetList = new java.util.ArrayList<>();
get_store().find_all_element_users(elementSet, targetList);
return targetList.stream().toArray(arrayCon);
}
}
}