public class Controller extends java.lang.Object implements ContextOriginator
The Controller is serially reusable: when one transformation or query is finished, it can be used to run another. However, there is no advantage in doing this rather than allocating a new Controller each time.
A dummy Controller is created when running free-standing XPath expressions.
The Controller holds those parts of the dynamic context that do not vary during the course of a transformation or query, or that do not change once their value has been computed. This also includes those parts of the static context that are required at run-time.
Many methods on the Controller are designed for internal use and should not be considered stable. From release 8.4 onwards, those methods that are considered sufficiently stable to constitute path of the Saxon public API are labelled with the JavaDoc tag "since": the value indicates the release at which the method was added to the public API.
Prior to Saxon 9.6 the Controller implemented (extended) the JAXP Transformer
interface, and advanced applications were able to down-cast the Transformer to a Controller.
This is no longer the case. Instead, the JAXP factory delivers an instance of TransformerImpl
,
from which the Controller is accessible if required. Because the Controller is no longer required
to implement the JAXP interface, it has been possible to make it less monolithic, so some of the
things it did are now done elsewhere: for example, it no longer handles global parameters
XsltController
.Modifier and Type | Field and Description |
---|---|
static java.lang.String |
ANONYMOUS_PRINCIPAL_OUTPUT_URI |
protected UnfailingErrorListener |
errorListener |
protected Executable |
executable |
protected Item<?> |
globalContextItem |
protected boolean |
inUse |
protected Receiver |
principalResult |
protected java.lang.String |
principalResultURI |
protected TraceListener |
traceListener |
protected int |
validationMode |
Constructor and Description |
---|
Controller(Configuration config)
Create a Controller and initialise variables.
|
Controller(Configuration config,
Executable executable)
Create a Controller and initialise variables.
|
Modifier and Type | Method and Description |
---|---|
void |
addTraceListener(TraceListener trace)
Adds the specified trace listener to receive trace events from
this instance.
|
SequenceOutputter |
allocateSequenceOutputter() |
SequenceOutputter |
allocateSequenceOutputter(int size)
Allocate a SequenceOutputter for a new output destination.
|
protected void |
checkReadiness() |
void |
clearDocumentPool()
Clear the document pool.
|
void |
clearGlobalContextItem()
Reset the global context item to null.
|
protected void |
clearPerTransformationData()
Reset variables that need to be reset for each transformation if the controller
is serially reused
|
java.lang.String |
getBaseOutputURI()
Get the base output URI.
|
Bindery |
getBindery(PackageData packageData)
Get the bindery for the global variables in a particular package.
|
CollectionFinder |
getCollectionFinder()
Get the collection finder associated with this configuration.
|
CollectionURIResolver |
getCollectionURIResolver()
Deprecated.
since 9.7. Use
getCollectionFinder() |
Configuration |
getConfiguration()
Get the Configuration associated with this Controller.
|
GroundedValue<?> |
getConvertedParameter(StructuredQName name,
SequenceType requiredType,
XPathContext context)
Get the value of a parameter, converted and/or type-checked
|
DateTimeValue |
getCurrentDateTime()
Get the current date and time for this query or transformation.
|
java.lang.String |
getDefaultCollection()
Get the name of the default collection.
|
DocumentPool |
getDocumentPool()
Get the document pool.
|
UnfailingErrorListener |
getErrorListener()
Get the error listener.
|
Executable |
getExecutable()
Get the Executable object.
|
java.util.function.Function<SequenceIterator<?>,FocusTrackingIterator<?>> |
getFocusTrackerFactory(boolean multithreaded)
Get the factory function that is used to create new instances of FocusTrackingIterator.
|
Item<?> |
getGlobalContextItem()
Get the item used as the context for evaluating global variables.
|
int |
getImplicitTimezone()
Get the implicit timezone offset for this query or transformation
|
IntHashMap<java.util.Map<java.lang.Long,KeyIndex>> |
getLocalIndexes()
Get the table of local indexes supporting xsl:key (or implicit keys created
by the optimizer).
|
TreeModel |
getModel()
Get the tree model that will be used.
|
Sequence<?> |
getParameter(StructuredQName name)
Get the value of a supplied parameter (XSLT) or external variable (XQuery)
|
PathMap |
getPathMapForDocumentProjection()
Get the path map used for document projection, if any.
|
Receiver |
getPrincipalResult()
Get the principal result destination.
|
int |
getRememberedNumber(NodeInfo node)
Get the number of a node if it is the last remembered one.
|
RuleManager |
getRuleManager()
Get the Rule Manager.
|
int |
getSchemaValidationMode()
Ask whether source documents loaded using the doc(), document(), and collection()
functions, or supplied as a StreamSource or SAXSource to the transform() or addParameter() method
should be subjected to schema validation
|
SpaceStrippingRule |
getSpaceStrippingRule()
Return the default whitespace-stripping rules that apply to this transformation or query.
|
javax.xml.transform.URIResolver |
getStandardURIResolver()
Get the fallback URI resolver.
|
StylesheetCache |
getStylesheetCache()
Get the cache of stylesheets (cached during calls on fn:transform()) for this query or transformation.
|
Logger |
getTraceFunctionDestination()
Get the destination for output from the fn:trace() function.
|
TraceListener |
getTraceListener()
Get the TraceListener.
|
UnparsedTextURIResolver |
getUnparsedTextURIResolver()
Get the URI resolver for the unparsed-text() function.
|
javax.xml.transform.URIResolver |
getURIResolver()
Get the URI resolver.
|
java.lang.Object |
getUserData(java.lang.Object key,
java.lang.String name)
Get user data associated with a key.
|
protected void |
handleXPathException(XPathException err) |
void |
initializeController(GlobalParameterSet params)
Initialize the controller ready for a new transformation.
|
boolean |
isStripSourceTree()
Ask whether the transformation will perform whitespace stripping for supplied source trees as defined
by the xsl:strip-space and xsl:preserve-space declarations in the stylesheet.
|
protected boolean |
isStylesheetContainingStripSpace()
Ask whether the executable is a stylesheet whose top-level package
contains an xsl:strip-space declaration requesting stripping of whitespace
from the principal source document to the transformation
|
boolean |
isStylesheetStrippingTypeAnnotations()
Ask whether the executable is a stylesheet whose top-level package
contains requests stripping of type annotations
|
boolean |
isTracing()
Test whether instruction execution is being traced.
|
Builder |
makeBuilder()
Make a builder for the selected tree model.
|
PipelineConfiguration |
makePipelineConfiguration()
Make a PipelineConfiguration based on the properties of this Controller.
|
NodeInfo |
makeSourceTree(javax.xml.transform.Source source,
int validationMode)
Make a source tree from a source supplied as a StreamSource or SAXSource
|
Stripper |
makeStripper(Receiver next)
Make a Stripper configured to implement the whitespace stripping rules.
|
XPathContextMajor |
newXPathContext()
Make an XPathContext object for expression evaluation.
|
void |
pauseTracing(boolean pause)
Pause or resume tracing.
|
void |
preEvaluateGlobals(XPathContext context)
Pre-evaluate global variables (when debugging/tracing).
|
NodeInfo |
prepareInputTree(javax.xml.transform.Source source)
Prepare an input tree for processing.
|
void |
recoverableError(XPathException err)
Report a recoverable error.
|
void |
registerDocument(TreeInfo doc,
DocumentURI uri)
Add a document to the document pool, and check that it is suitable for use in this query or
transformation.
|
void |
registerGlobalVariableDependency(GlobalVariable one,
GlobalVariable two)
Register the dependency of one variable ("one") upon another ("two"), throwing an exception if this would establish
a cycle of dependencies.
|
void |
removeTraceListener(TraceListener trace)
Removes the specified trace listener so that the listener will no longer
receive trace events.
|
void |
reportFatalError(XPathException err)
Report a fatal error
|
void |
reset()
Reset this
Transformer to its original configuration. |
void |
setApplyFunctionConversionRulesToExternalVariables(boolean applyConversionRules) |
void |
setBaseOutputURI(java.lang.String uri)
Set the base output URI.
|
void |
setCollectionFinder(CollectionFinder cf)
Set the collection finder associated with this configuration.
|
void |
setCollectionURIResolver(CollectionURIResolver resolver)
Deprecated.
since 9.7. Use
setCollectionFinder(CollectionFinder) |
void |
setCurrentDateTime(DateTimeValue dateTime)
Set the current date and time for this query or transformation.
|
void |
setDefaultCollection(java.lang.String uri)
Set the name of the default collection.
|
void |
setErrorListener(javax.xml.transform.ErrorListener listener)
Set the error listener.
|
void |
setFocusTrackerFactory(java.util.function.Function<SequenceIterator<?>,FocusTrackingIterator<?>> focusTrackerFactory)
Set a factory function that will be used to create new instances of FocusTrackingIterator.
|
void |
setGlobalContextItem(Item contextItem)
Set the item used as the context for evaluating global variables.
|
void |
setGlobalContextItem(Item contextItem,
boolean alreadyStripped)
Set the item used as the context for evaluating global variables.
|
void |
setMemoizingFocusTrackerFactory()
Set the focus tracker factory function to a function that creates a memoizing focus tracker, which
has the effect that all items read by the focus iterator are accessible to a debugger at any stage
while iterating over the sequence
|
void |
setModel(TreeModel model)
Set the tree model to use.
|
void |
setMultithreadedFocusTrackerFactory(java.util.function.Function<SequenceIterator<?>,FocusTrackingIterator<?>> focusTrackerFactory)
Set a factory function that will be used to create new instances of FocusTrackingIterator for
multithreaded operation.
|
void |
setRememberedNumber(NodeInfo node,
int number)
Set the last remembered node, for node numbering purposes.
|
void |
setSchemaValidationMode(int validationMode)
Say whether source documents loaded using the doc(), document(), and collection()
functions, or supplied as a StreamSource or SAXSource to the transform() or addParameter() method,
should be subjected to schema validation.
|
void |
setStripSourceTrees(boolean strip)
Say whether the transformation should perform whitespace stripping as defined
by the xsl:strip-space and xsl:preserve-space declarations in the stylesheet
in the case where a source tree is supplied to the transformation as a tree
(typically a DOMSource, or a Saxon NodeInfo).
|
void |
setTraceFunctionDestination(Logger stream)
Set the destination for output from the fn:trace() function.
|
void |
setTraceListener(TraceListener listener)
Set a TraceListener, replacing any existing TraceListener
|
void |
setUnparsedTextURIResolver(UnparsedTextURIResolver resolver)
Set an UnparsedTextURIResolver to be used to resolve URIs passed to the XSLT
unparsed-text() function.
|
void |
setURIResolver(javax.xml.transform.URIResolver resolver)
Set an object that will be used to resolve URIs used in
document(), etc.
|
void |
setUseDocumentProjection(PathMap pathMap)
Indicate whether document projection should be used, and supply the PathMap used to control it.
|
void |
setUserData(java.lang.Object key,
java.lang.String name,
java.lang.Object data)
Set user data associated with a key.
|
void |
warning(java.lang.String message,
java.lang.String errorCode,
Location locator)
Report a run-time warning
|
protected Executable executable
protected Item<?> globalContextItem
protected TraceListener traceListener
protected Receiver principalResult
protected java.lang.String principalResultURI
protected UnfailingErrorListener errorListener
protected int validationMode
protected boolean inUse
public static final java.lang.String ANONYMOUS_PRINCIPAL_OUTPUT_URI
public Controller(Configuration config)
config
- The Configuration used by this Controllerpublic Controller(Configuration config, Executable executable)
config
- The Configuration used by this Controllerexecutable
- The executable used by this Controllerpublic void reset()
Reset this Transformer
to its original configuration.
Transformer
is reset to the same state as when it was created with
TransformerFactory.newTransformer()
,
TransformerFactory.newTransformer(javax.xml.transform.Source source)
or
Templates.newTransformer()
.
reset()
is designed to allow the reuse of existing Transformer
s
thus saving resources associated with the creation of new Transformer
s.
The above is from the JAXP specification. With Saxon, it's unlikely that reusing a Transformer will
give any performance benefits over creating a new one. The one case where it might be beneficial is
to reuse the document pool (the set of documents that have been loaded using the doc() or document()
functions). Therefore, this method does not clear the document pool. If you want to clear the document
pool, call the method clearDocumentPool()
as well.
The reset Transformer
is not guaranteed to have the same URIResolver
or ErrorListener
Object
s, e.g. Object.equals(Object obj)
.
It is guaranteed to have a functionally equal URIResolver
and ErrorListener
.
protected void clearPerTransformationData()
public Configuration getConfiguration()
public Sequence<?> getParameter(StructuredQName name)
name
- the QName of the parameterpublic GroundedValue<?> getConvertedParameter(StructuredQName name, SequenceType requiredType, XPathContext context) throws XPathException
name
- the name of the stylesheet parameter (XSLT) or external variable (XQuery)requiredType
- the declared type of the parametercontext
- the dynamic evaluation contextsetApplyFunctionConversionRulesToExternalVariables(boolean)
} is set, the supplied
value is converted to the required type. Otherwise, the supplied value is checked
against the required type.XPathException
public void setBaseOutputURI(java.lang.String uri)
This defaults to the system ID of the Result object for the principal output of the transformation if this is known; if it is not known, it defaults to the current directory.
The base output URI is used for resolving relative URIs in the href
attribute
of the xsl:result-document
instruction.
uri
- the base output URIpublic java.lang.String getBaseOutputURI()
This returns the value set using the setBaseOutputURI(java.lang.String)
method. If no value has been set
explicitly, then the method returns null if called before the transformation, or the computed
default base output URI if called after the transformation.
The base output URI is used for resolving relative URIs in the href
attribute
of the xsl:result-document
instruction.
public Receiver getPrincipalResult()
This method is intended for internal use only. It is typically called by Saxon during the course of a transformation, to discover the result that was supplied in the transform() call.
public SequenceOutputter allocateSequenceOutputter(int size)
size
- the estimated size of the output sequencepublic SequenceOutputter allocateSequenceOutputter()
public PipelineConfiguration makePipelineConfiguration()
This interface is intended primarily for internal use, although it may be necessary for applications to call it directly if they construct pull or push pipelines.
public void setErrorListener(javax.xml.transform.ErrorListener listener)
listener
- the ErrorListener to be usedpublic UnfailingErrorListener getErrorListener()
setErrorListener(ErrorListener)
method; if that was not an UnfailingErrorListener
,
it will have been wrapped in a DelegatingErrorListener
, and it is the DelegatingErrorListener
that this method returns.public void recoverableError(XPathException err) throws XPathException
This method is intended for internal use only.
err
- An exception holding information about the errorXPathException
- if the error listener decides not to
recover from the errorpublic void reportFatalError(XPathException err)
err
- the error to be reportedpublic void warning(java.lang.String message, java.lang.String errorCode, Location locator)
message
- the warning messageerrorCode
- the local part of the error code (in the ERR namespace). May be null.locator
- the location in the source code. May be null.protected void handleXPathException(XPathException err) throws XPathException
XPathException
public Executable getExecutable()
This method is intended for internal use only.
public DocumentPool getDocumentPool()
This method is intended for internal use only.
public void clearDocumentPool()
public Bindery getBindery(PackageData packageData)
This method is intended for internal use only.
packageData
- the package for which the variables are requiredpublic void setGlobalContextItem(Item contextItem) throws XPathException
contextItem
- the context item for evaluating global variables, or null if there is noneXPathException
- if the supplied context item is a node, and if it (a) does not belong
to the right Configuration, or (b) is schema-validated, when the stylesheet or query is
not compiled with schema-awareness enabledpublic void setGlobalContextItem(Item contextItem, boolean alreadyStripped) throws XPathException
contextItem
- the context item for evaluating global variables, or null if there is nonealreadyStripped
- true if any stripping of type annotations or whitespace text node specified
in the stylesheet has already been carried outXPathException
- if the supplied context item is a node, and if it (a) does not belong
to the right Configuration, or (b) is schema-validated, when the stylesheet or query is
not compiled with schema-awareness enabledpublic void clearGlobalContextItem()
public Item<?> getGlobalContextItem()
public void setURIResolver(javax.xml.transform.URIResolver resolver)
resolver
- An object that implements the URIResolver interface, or
null.public javax.xml.transform.URIResolver getURIResolver()
This method changed in Saxon 8.5, to conform to the JAXP specification. If there is no user-specified URIResolver, it now returns null; previously it returned the system default URIResolver.
public javax.xml.transform.URIResolver getStandardURIResolver()
This method is intended for internal use only.
public void setUnparsedTextURIResolver(UnparsedTextURIResolver resolver)
resolver
- the unparsed text URI resolver to be used. This replaces any unparsed text
URI resolver previously registered.public UnparsedTextURIResolver getUnparsedTextURIResolver()
setUnparsedTextURIResolver(net.sf.saxon.lib.UnparsedTextURIResolver)
method.public void setCollectionURIResolver(CollectionURIResolver resolver)
setCollectionFinder(CollectionFinder)
resolver
- the resolver for references to collectionspublic CollectionURIResolver getCollectionURIResolver()
getCollectionFinder()
public CollectionFinder getCollectionFinder()
public void setCollectionFinder(CollectionFinder cf)
cf
- the CollectionFinder to be usedpublic void setDefaultCollection(java.lang.String uri)
uri
- the collection URI of the default collection. May be null, to cause
fallback to the collection name registered with the Configuration. The name will be passed
to the collection URI resolver to identify the documents in the collection, unless
the name is http://saxon.sf.net/collection/empty
which always refers
to the empty collection.public java.lang.String getDefaultCollection()
public int getSchemaValidationMode()
public void setSchemaValidationMode(int validationMode)
validationMode
- the validation (or construction) mode to be used for source documents.
One of Validation.STRIP
, Validation.PRESERVE
, Validation.STRICT
,
Validation.LAX
public void setModel(TreeModel model)
model
- typically one of the constants TreeModel.TINY_TREE
,
TreeModel.TINY_TREE_CONDENSED
, or TreeModel.LINKED_TREE
.
It is also possible to use a user-defined tree model.public TreeModel getModel()
TreeModel.TINY_TREE
,
TreeModel.TINY_TREE_CONDENSED
, or TreeModel.LINKED_TREE
.
It is also possible to use a user-defined tree model.public Builder makeBuilder()
public void setStripSourceTrees(boolean strip)
Generally, stripping whitespace speeds up the transformation if it is done while building the source tree, but slows it down if it is applied to a tree that has already been built. So if the same source tree is used as input to a number of transformations, it is better to strip the whitespace once at the time of tree construction, rather than doing it on-the-fly during each transformation.
strip
- true if whitespace is to be stripped from supplied source trees
as defined by xsl:strip-space; false to suppress whitespace strippingpublic boolean isStripSourceTree()
setStripSourceTrees(boolean)
.protected boolean isStylesheetContainingStripSpace()
public boolean isStylesheetStrippingTypeAnnotations()
public Stripper makeStripper(Receiver next)
xsl:strip-space
and xsl:preserve-space
elements
in the stylesheet. Alternatively, stripping of all whitespace text nodes
may be defined at the level of the Configuration, using the code
Configuration.getParseOptions().setSpaceStrippingRules(AllElementsSpaceStrippingRule.getInstance()
.next
- the Receiver to which the events filtered by this stripper are
to be sent (often a Builder). May be null if the stripper is not being used for filtering
into a Builder or other Receiver.public SpaceStrippingRule getSpaceStrippingRule()
public void registerDocument(TreeInfo doc, DocumentURI uri) throws XPathException
This method is intended for internal use only.
doc
- the root node of the document to be added. Must not be null.uri
- the document-URI property of this document. If non-null, the document is registered
in the document pool with this as its document URI.XPathException
- if an error occurspublic RuleManager getRuleManager()
This method is intended for internal use only.
public void setTraceListener(TraceListener listener)
This method has no effect unless the stylesheet or query was compiled with tracing enabled.
listener
- the TraceListener to be set. May be null, in which case
trace events will not be reportedpublic TraceListener getTraceListener()
addTraceListener(net.sf.saxon.lib.TraceListener)
. If more than one TraceListener has been added,
this method will return a composite TraceListener. Because the form
this takes is implementation-dependent, this method is not part of the
stable Saxon public API.public final boolean isTracing()
addTraceListener(net.sf.saxon.lib.TraceListener)
method, and (b) tracing has not been temporarily
paused using the pauseTracing(boolean)
method.public final void pauseTracing(boolean pause)
pause
- true if tracing is to pause; false if it is to resumepublic void addTraceListener(TraceListener trace)
Configuration.setTraceListener(net.sf.saxon.lib.TraceListener)
or by setting
the attribute FeatureKeys.TRACE_LISTENER
on the
TransformerFactory. Conversely, if this property has been set in the
Configuration or TransformerFactory, the TraceListener will automatically
be added to every Controller that uses that Configuration.trace
- the trace listener. If null is supplied, the call has no effect.public void removeTraceListener(TraceListener trace)
trace
- the trace listener.public void setTraceFunctionDestination(Logger stream)
stream
- the PrintStream to which trace output will be sent. If set to
null, trace output is suppressed entirely. It is the caller's responsibility
to close the stream after use.public Logger getTraceFunctionDestination()
public void initializeController(GlobalParameterSet params) throws XPathException
params
- the values of stylesheet parameters. Changed in 9.9.1.1 so this no longer includes
static parameters (which are already available in the PreparedStylesheet
).XPathException
- if an error occurs, for example if a required parameter is not supplied.public void setApplyFunctionConversionRulesToExternalVariables(boolean applyConversionRules)
public java.lang.Object getUserData(java.lang.Object key, java.lang.String name)
This method is intended primarily for internal use, though it may also be used by advanced applications.
key
- an object acting as a key for this user data value. This must be equal
(in the sense of the equals() method) to the key supplied when the data value was
registered using setUserData(java.lang.Object, java.lang.String, java.lang.Object)
.name
- the name of the required propertypublic void setUserData(java.lang.Object key, java.lang.String name, java.lang.Object data)
This method is intended primarily for internal use, though it may also be used by advanced applications.
key
- an object acting as a key for this user data value. This can be any object, for example
a node or a string. If data for the given object and name already exists, it is overwritten.name
- the name of the required propertydata
- the value of the required property. If null is supplied, any existing entry
for the key is removed.public IntHashMap<java.util.Map<java.lang.Long,KeyIndex>> getLocalIndexes()
public void setRememberedNumber(NodeInfo node, int number)
This method is strictly for internal use only.
node
- the node in questionnumber
- the number of this nodepublic int getRememberedNumber(NodeInfo node)
This method is strictly for internal use only.
node
- the node for which remembered information is requiredprotected void checkReadiness() throws XPathException
XPathException
public NodeInfo makeSourceTree(javax.xml.transform.Source source, int validationMode) throws XPathException
source
- the sourcevalidationMode
- indicates whether the source should be schema-validatedXPathException
- if tree construction failspublic NodeInfo prepareInputTree(javax.xml.transform.Source source)
This method is intended for internal use.
source
- the input tree. Must be either a DOMSource or a NodeInfopublic void preEvaluateGlobals(XPathContext context) throws XPathException
This method is intended for internal use.
context
- the dynamic context for evaluating the global variablesXPathException
public void registerGlobalVariableDependency(GlobalVariable one, GlobalVariable two) throws XPathException
one
- the first (dependent) variabletwo
- the second (dependee) variableXPathException
- if adding this dependency creates a cycle of dependencies among global variables.public void setCurrentDateTime(DateTimeValue dateTime) throws XPathException
Note that comparisons of date/time values currently use the implicit timezone taken from the system clock, not from the value supplied here.
dateTime
- the date/time value to be used as the current date and timejava.lang.IllegalStateException
- if a current date/time has already been
established by calling getCurrentDateTime(), or by a previous call on setCurrentDateTime()XPathException
- if the supplied dateTime contains no timezonepublic DateTimeValue getCurrentDateTime()
public int getImplicitTimezone()
public XPathContextMajor newXPathContext()
This method is intended for internal use.
public void setUseDocumentProjection(PathMap pathMap)
pathMap
- a path map to be used for projecting source documentspublic PathMap getPathMapForDocumentProjection()
public StylesheetCache getStylesheetCache()
public java.util.function.Function<SequenceIterator<?>,FocusTrackingIterator<?>> getFocusTrackerFactory(boolean multithreaded)
multithreaded
- true if the focus tracker must be suitable for executing a multi-threaded
xsl:for-each iterationpublic void setFocusTrackerFactory(java.util.function.Function<SequenceIterator<?>,FocusTrackingIterator<?>> focusTrackerFactory)
focusTrackerFactory
- a factory function that is used to create FocusTrackingIterator instancespublic void setMultithreadedFocusTrackerFactory(java.util.function.Function<SequenceIterator<?>,FocusTrackingIterator<?>> focusTrackerFactory)
focusTrackerFactory
- a factory function that is used to create FocusTrackingIterator instancespublic void setMemoizingFocusTrackerFactory()
Copyright (c) 2004-2020 Saxonica Limited. All rights reserved.