Interface IonValue
-
- All Superinterfaces:
java.lang.Cloneable
- All Known Subinterfaces:
_Private_IonContainer
,_Private_IonDatagram
,_Private_IonSymbol
,_Private_IonValue
,IonBlob
,IonBool
,IonClob
,IonContainer
,IonDatagram
,IonDecimal
,IonFloat
,IonInt
,IonList
,IonLob
,IonNull
,IonNumber
,IonSequence
,IonSexp
,IonString
,IonStruct
,IonSymbol
,IonText
,IonTimestamp
public interface IonValue extends java.lang.Cloneable
Base type for all Ion data nodes.WARNING: This interface should not be implemented or extended by code outside of this library.
The
IonValue
hierarchy presents a "tree view" of Ion data; every node in the tree is an instance of this class. Since the Ion type system is highly orthogonal, most operations use this base type, and applications will need to examine individual instances and "downcast" the value to one of the "real" types (e.g.,IonString
) in order to access the Ion content.Besides the real types, there are other generic interfaces that can be useful:
-
IonText
generalizesIonString
andIonSymbol
-
IonContainer
generalizesIonList
,IonSexp
, andIonStruct
-
IonSequence
generalizesIonList
andIonSexp
-
IonLob
generalizesIonBlob
andIonClob
To determine the real type of a generic
IonValue
, there are three main mechanisms:-
Use
instanceof
to look for a desired interface:if (v instanceof IonString) { useString((IonString) v); } else if (v instanceof IonStruct) { useStruct((IonStruct) v); } // ...
-
Call
getType()
and thenswitch
over the resultingIonType
:switch (v.getType()) { case IonType.STRING: useString((IonString) v); break; case IonType.STRUCT: useStruct((IonStruct) v); break; // ... }
-
Implement
ValueVisitor
and callaccept(ValueVisitor)
:public class MyVisitor extends AbstractValueVisitor { public void visit(IonString value) { useString(v); } public void visit(IonStruct value) { useStruct(v); } // ... }
Single-Parent Restriction
IonValue
trees are strictly hierarchical: every node has at most one parent, as exposed throughgetContainer()
(and, implicitly,getFieldName()
). You cannot add anIonValue
instance into twoIonContainer
s; any attempt to do so will result in aContainedValueException
. You can of course add the same instance to multiple "normal"Collections
, since that's stepping outside of the DOM.The implication of this design is that you need to be careful when performing DOM transformations. You must remove a node from its parent before adding it to another one;
removeFromContainer()
is handy. Alternatively you canclone()
a value, but be aware that cloning is a deep-copy operation (for the very same single-parent reason).Thread Safety
MutableIonValues
are not safe for use by multiple threads! Your application must perform its own synchronization if you need to accessIonValues
from multiple threads. This is true even for read-only use cases, since implementations may perform lazy materialization or other state changes internally.Alternatively, you can invoke
makeReadOnly()
from a single thread, after which point the value (and all recursively contained values) will be immutable and hence thread-safe.It is important to note that
makeReadOnly()
is not guaranteed to implicitly provide a synchronization point between threads. This means it is the responsibility of the application to make sure operations on a thread other than the one that invokedmakeReadOnly()
causally happen after that invocation observing the rules of the Java Memory Model (JSR-133).Here is an example of ensuring the correct ordering for multiple threads accessing an
IonValue
using aCountDownLatch
to explicitly create a the temporal relationship:// ... // Shared Between Threads // ... IonValue value = ...; CountDownLatch latch = new CountDownLatch(1); // ... // Thread 1 // ... value.makeReadOnly(); latch.countDown(); // ... // Thread 2 // ... // before this point operations on 'value' are not defined latch.await(); // we can now operate (in a read-only way) on 'value' value.isNullValue();
In the above, two threads have a reference to
value
.latch
in this example provides a way to synchronize whenmakeReadOnly()
happens in the first thread relative toisNullValue()
being invoked on the second thread.
-
-
Field Summary
Fields Modifier and Type Field Description static IonValue[]
EMPTY_ARRAY
A zero-length immutableIonValue
array.
-
Method Summary
All Methods Instance Methods Abstract Methods Deprecated Methods Modifier and Type Method Description void
accept(ValueVisitor visitor)
Entry point for visitor pattern.void
addTypeAnnotation(java.lang.String annotation)
Adds a user type annotation to the annotations attached to this value.void
clearTypeAnnotations()
Removes all the user type annotations attached to this value.IonValue
clone()
Creates a copy of this value and all of its children.boolean
equals(java.lang.Object other)
Compares two Ion values for structural equality, which means that they represent the exact same semantics, including annotations, numeric precision, and so on.IonContainer
getContainer()
Gets the container of this value, ornull
if this is not part of one.int
getFieldId()
Deprecated.UsegetFieldNameSymbol()
instead.java.lang.String
getFieldName()
Gets the field name attached to this value, ornull
if this is not part of anIonStruct
.SymbolToken
getFieldNameSymbol()
Gets the field name attached to this value as an interned symbol (text + ID).SymbolTable
getSymbolTable()
Gets the symbol table used to encode this value.IonSystem
getSystem()
Gets the system that constructed this value.IonType
getType()
Gets an enumeration value identifying the core Ion data type of this object.java.lang.String[]
getTypeAnnotations()
Gets this value's user type annotations as text.SymbolToken[]
getTypeAnnotationSymbols()
Gets this value's user type annotations as interned symbols (text + ID).int
hashCode()
Returns a hash code consistent withequals(Object)
.boolean
hasTypeAnnotation(java.lang.String annotation)
Determines whether or not the value is annotated with a particular user type annotation.boolean
isNullValue()
Determines whether this in an Ion null value, e.g.,null
ornull.string
.boolean
isReadOnly()
Determines whether this value is read-only.void
makeReadOnly()
Marks this instance and its children to be immutable.boolean
removeFromContainer()
Removes this value from its container, if any.void
removeTypeAnnotation(java.lang.String annotation)
Removes a user type annotation from the list of annotations attached to this value.void
setTypeAnnotations(java.lang.String... annotations)
Replaces all type annotations with the given text.void
setTypeAnnotationSymbols(SymbolToken... annotations)
Replaces all type annotations with the given symbol tokens.IonValue
topLevelValue()
Finds the top level value above this value.java.lang.String
toPrettyString()
Returns a pretty-printed Ion text representation of this value, using the settings ofIonTextWriterBuilder.pretty()
.java.lang.String
toString()
Returns a non-canonical Ion-formatted ASCII representation of this value.java.lang.String
toString(IonTextWriterBuilder writerBuilder)
Returns an Ion text representation of this value, using the settings from the given builder.void
writeTo(IonWriter writer)
Copies this value to the givenIonWriter
.
-
-
-
Field Detail
-
EMPTY_ARRAY
static final IonValue[] EMPTY_ARRAY
A zero-length immutableIonValue
array.
-
-
Method Detail
-
getType
IonType getType()
Gets an enumeration value identifying the core Ion data type of this object.- Returns:
- a non-
null
enumeration value.
-
isNullValue
boolean isNullValue()
Determines whether this in an Ion null value, e.g.,null
ornull.string
. Note that there are unique null values for each Ion type.- Returns:
true
if this value is one of the Ion null values.
-
isReadOnly
boolean isReadOnly()
Determines whether this value is read-only. Such values are safe for simultaneous read from multiple threads.- Returns:
true
if this value is read-only and safe for multi-threaded reads.- See Also:
makeReadOnly()
-
getSymbolTable
SymbolTable getSymbolTable()
Gets the symbol table used to encode this value. The result is either a local or system symbol table (or null).- Returns:
- the symbol table, or
null
if this value is not currently backed by binary-encoded data.
-
getFieldName
java.lang.String getFieldName()
Gets the field name attached to this value, ornull
if this is not part of anIonStruct
.- Throws:
UnknownSymbolException
- if the field name has unknown text.
-
getFieldNameSymbol
SymbolToken getFieldNameSymbol()
Gets the field name attached to this value as an interned symbol (text + ID).- Returns:
- null if this value isn't a struct field.
-
getFieldId
@Deprecated int getFieldId()
Deprecated.UsegetFieldNameSymbol()
instead.Gets the symbol ID of the field name attached to this value.- Returns:
- the symbol ID of the field name, if this is part of an
IonStruct
. If this is not a field, or if the symbol ID cannot be determined, this method returns a value less than one.
-
getContainer
IonContainer getContainer()
Gets the container of this value, ornull
if this is not part of one.
-
removeFromContainer
boolean removeFromContainer()
Removes this value from its container, if any.- Returns:
true
if this value was in a container before this method was called.
-
topLevelValue
IonValue topLevelValue()
Finds the top level value above this value. If this value has no container, or if it's immediate container is a datagram, then this value is returned.- Returns:
- the top level value above this value, never null, and never an
IonDatagram
. - Throws:
java.lang.UnsupportedOperationException
- if this is anIonDatagram
.
-
getTypeAnnotations
java.lang.String[] getTypeAnnotations()
Gets this value's user type annotations as text.- Returns:
- the (ordered) annotations on the current value, or an empty
array (not
null
) if there are none. - Throws:
UnknownSymbolException
- if any annotation has unknown text.
-
getTypeAnnotationSymbols
SymbolToken[] getTypeAnnotationSymbols()
Gets this value's user type annotations as interned symbols (text + ID).- Returns:
- the (ordered) annotations on the current value, or an empty
array (not
null
) if there are none.
-
hasTypeAnnotation
boolean hasTypeAnnotation(java.lang.String annotation)
Determines whether or not the value is annotated with a particular user type annotation.- Parameters:
annotation
- as a string value.- Returns:
true
if this value has the annotation.
-
setTypeAnnotations
void setTypeAnnotations(java.lang.String... annotations)
Replaces all type annotations with the given text.- Parameters:
annotations
- the new annotations. If null or empty array, then all annotations are removed. Any duplicates are preserved.- Throws:
java.lang.NullPointerException
- if any of the annotations are null
-
setTypeAnnotationSymbols
void setTypeAnnotationSymbols(SymbolToken... annotations)
Replaces all type annotations with the given symbol tokens. The contents of theannotations
array are copied into this writer, so the caller does not need to preserve the array.This is an "expert method": correct use requires deep understanding of the Ion binary format. You almost certainly don't want to use it.
- Parameters:
annotations
- the new annotations. If null or empty array, then all annotations are removed. Any duplicates are preserved.
-
clearTypeAnnotations
void clearTypeAnnotations()
Removes all the user type annotations attached to this value.
-
addTypeAnnotation
void addTypeAnnotation(java.lang.String annotation)
Adds a user type annotation to the annotations attached to this value. If the annotation exists the list does not change.- Parameters:
annotation
- as a string value.
-
removeTypeAnnotation
void removeTypeAnnotation(java.lang.String annotation)
Removes a user type annotation from the list of annotations attached to this value. If the annotation appears more than once, only the first occurrance is removed. If the annotation does not exist, the value does not change.- Parameters:
annotation
- as a string value. If null or empty, the method has no effect.
-
writeTo
void writeTo(IonWriter writer)
Copies this value to the givenIonWriter
.This method writes annotations and field names (if in a struct), and performs a deep write, including the contents of any containers encountered.
-
accept
void accept(ValueVisitor visitor) throws java.lang.Exception
Entry point for visitor pattern. Implementations of this method by concrete classes will simply call the appropriatevisit
method on thevisitor
. For example, instances ofIonBool
will invokeValueVisitor.visit(IonBool)
.- Parameters:
visitor
- will have one of itsvisit
methods called.- Throws:
java.lang.Exception
- any exception thrown by the visitor is propagated.java.lang.NullPointerException
- ifvisitor
isnull
.
-
makeReadOnly
void makeReadOnly()
Marks this instance and its children to be immutable. In addition, read-only values are safe for simultaneous use from multiple threads. This may require materializing the Java forms of the values.After this method completes, any attempt to change the state of this instance, or of any contained value, will trigger a
ReadOnlyValueException
.- See Also:
isReadOnly()
-
getSystem
IonSystem getSystem()
Gets the system that constructed this value.- Returns:
- not null.
-
clone
IonValue clone() throws UnknownSymbolException
Creates a copy of this value and all of its children. The cloned value may use the same shared symbol tables, but it will have an independent local symbol table if necessary. The cloned value will be modifiable regardless of whether this instanceisReadOnly()
.The cloned value will be created in the context of the same
ValueFactory
as this instance; if you want a copy using a different factory, then useValueFactory.clone(IonValue)
instead.- Throws:
UnknownSymbolException
- if any part of this value has unknown text but known Sid for its field name, annotation or symbol.
-
toString
java.lang.String toString()
Returns a non-canonical Ion-formatted ASCII representation of this value. All data will be on a single line, with (relatively) minimal whitespace. There is no guarantee that multiple invocations of this method will return identical results, only that they will be equivalent per the Ion data model. For this reason it is erroneous for code to compare two strings returned by this method.For more configurable rendering, see
IonTextWriterBuilder
.This is not the correct way to retrieve the content of an
IonString
orIonSymbol
! UseIonText.stringValue()
for that purpose.ionSystem.newString("Levi's").toString() => "\"Levi's\"" ionSystem.newString("Levi's").stringValue() => "Levi's" ionSystem.newSymbol("Levi's").toString() => "'Levi\\'s'" ionSystem.newSymbol("Levi's").stringValue() => "Levi's"
- Overrides:
toString
in classjava.lang.Object
- Returns:
- Ion text data equivalent to this value.
- See Also:
IonText.stringValue()
,toString(IonTextWriterBuilder)
,toPrettyString()
-
toPrettyString
java.lang.String toPrettyString()
Returns a pretty-printed Ion text representation of this value, using the settings ofIonTextWriterBuilder.pretty()
.The specific configuration may change between releases of this library, so automated processes should not depend on the exact output formatting. In particular, there's currently no promise regarding handling of system data.
- Returns:
- Ion text data equivalent to this value.
-
toString
java.lang.String toString(IonTextWriterBuilder writerBuilder)
Returns an Ion text representation of this value, using the settings from the given builder.- Parameters:
writerBuilder
- the configuration that will be used for writing data to a string.- Returns:
- Ion text data equivalent to this value.
-
equals
boolean equals(java.lang.Object other)
Compares two Ion values for structural equality, which means that they represent the exact same semantics, including annotations, numeric precision, and so on. This is a "deep" comparison that recursively traverses the hierarchy, and as such it should be considered an expensive operation.- Overrides:
equals
in classjava.lang.Object
- Parameters:
other
- The value to compare with.- Returns:
- A boolean, true if the argument is an
IonValue
that is semantically identical within the Ion data model, including precision and annotations. - See Also:
Equivalence
-
hashCode
int hashCode()
Returns a hash code consistent withequals(Object)
.- Overrides:
hashCode
in classjava.lang.Object
-
-