Files
mars-flaim/xflaim/java/xflaim/Query.java
dsandersoremutah 16e2c3fe05 Added more methods to Query class.
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@773 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2006-08-17 22:53:33 +00:00

887 lines
26 KiB
Java

//------------------------------------------------------------------------------
// Desc: Query object
//
// Tabs: 3
//
// Copyright (c) 2003-2006 Novell, Inc. All Rights Reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the GNU General Public
// License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, contact Novell, Inc.
//
// To contact Novell about this file by physical or electronic mail,
// you may find current contact information at www.novell.com
//
// $Id$
//------------------------------------------------------------------------------
package xflaim;
/**
* This class encapsulates the XFlaim IF_Query interface.
*/
public class Query
{
Query(
Db jdb,
int iCollection) throws XFlaimException
{
m_this = _createQuery( iCollection);
if (jdb == null)
{
throw new XFlaimException( -1, "No legal jDb reference");
}
m_jdb = jdb;
}
protected void finalize()
{
// The F_Query and F_Db classes are not thread-safe. The proper way
// of using XFlaim is to get a new instance of Db for each thread.
// Unfortunately, the garbage collector runs in its own thread. This
// leads to a potential race condition down in the C++ code when one
// thread tries to create an already existing query (which results in a
// call to F_Query::AddRef()) and the GC tries to destroy the same
// query (which results in a call to F_Query::Release()).
// We protect against this by synchronizing against the instance of
// Db. Note that we are not protecting any of the accesses to the
// query; only creating and destroying. Query and Db are still
// not completely thread-safe.
synchronized( m_jdb)
{
// Release the associated DOMNode.
if (m_this != 0)
{
_release( m_this);
}
}
// Free our reference to the Db object.
m_jdb = null;
}
public long getThis()
{
return m_this;
}
/**
* Set the language for the query criteria. This affects how string
* comparisons are done. Collation is done according to the language
* specified.
* @param iLanguage Language to be used for string comparisons.
* @throws XFlaimException
*/
public void setLanguage(
int iLanguage) throws XFlaimException
{
_setLanguage( m_this, iLanguage);
}
/**
* Setup the query criteria from the passed in string.
* @param sQuery String containing the query criteria.
* @throws XFlaimException
*/
public void setupQueryExpr(
String sQuery) throws XFlaimException
{
_setupQueryExpr( m_this, m_jdb.m_this, sQuery);
}
/**
* Copy the query criteria from one Query object into this Query object.
* @param querytoCopy Query object whose criteria is to be copied.
* @throws XFlaimException
*/
public void copyCriteria(
Query queryToCopy) throws XFlaimException
{
_copyCriteria( m_this, queryToCopy.m_this);
}
/**
* Add an XPATH component to a query.
* @param iXPathAxis Type of axis for the XPATH component being added.
* Should be one of the constants defined in {@link xflaim.XPathAxis XPathAxis}.
* @param iNodeType An integer representing the type of node for the
* XPATH component.
* (Use the constants in {@link xflaim.FlmDomNodeType FlmDomNodeType}.)
* @param iNameId Name ID for the node in the XPATH component.
* @throws XFlaimException
*/
public void addXPathComponent(
int iXPathAxis,
int iNodeType,
int iNameId) throws XFlaimException
{
_addXPathComponent( m_this, iXPathAxis, iNodeType, iNameId);
}
/**
* Add an operator to a query.
* @param iOperator Operator to be added. Should be one of the constants
* defined in {@link xflaim.QueryOperators QueryOperators}.
* @param iCompareRules. Flags for doing string comparisons. Should be
* logical ORs of the members of {@link xflaim.CompareRules CompareRules}.
* @throws XFlaimException
*/
public void addOperator(
int iOperator,
int iCompareRules) throws XFlaimException
{
_addOperator( m_this, iOperator, iCompareRules);
}
/**
* Add a string value to the query criteria.
* @param sValue String value to be added to criteria.
* @throws XFlaimException
*/
public void addStringValue(
String sValue) throws XFlaimException
{
_addStringValue( m_this, sValue);
}
/**
* Add a binary value to the query criteria.
* @param Value Binary value to be added to criteria.
* @throws XFlaimException
*/
public void addBinaryValue(
byte [] Value) throws XFlaimException
{
_addBinaryValue( m_this, Value);
}
/**
* Add a long value to the query criteria.
* @param lValue Long value to be added to criteria.
* @throws XFlaimException
*/
public void addLongValue(
long lValue) throws XFlaimException
{
_addLongValue( m_this, lValue);
}
/**
* Add a boolean to the query criteria.
* @param bValue Boolean value to be added to criteria.
* @throws XFlaimException
*/
public void addBoolean(
boolean bValue) throws XFlaimException
{
_addBoolean( m_this, bValue, false);
}
/**
* Add an "unknown" predicate to the query criteria.
* @param bValue Boolean value to be added to criteria.
* @throws XFlaimException
*/
public void addUnknown() throws XFlaimException
{
_addBoolean( m_this, false, true);
}
/**
* Gets the first {@link xflaim.DOMNode DOM node} that satisfies the query criteria.
* This may be a document root node, or any node within the document. What
* is returned depends on how the XPATH expression was constructed.
* @param ReusedNode An existing {@link xflaim.DOMNode DOMNode} object
* can optionally be passed in, and it will be reused instead of a new
* object being allocated.
* @param iTimeLimit Time limit (in milliseconds) for operation to complete.
* A value of zero indicates that the operation should not time out.
* @return Returns an instance of {@link xflaim.DOMNode DOMNode}.
* @throws XFlaimException
*/
public DOMNode getFirst(
DOMNode ReusedNode,
int iTimeLimit) throws XFlaimException
{
long lNewNodeRef = 0;
DOMNode NewNode;
long lReusedNodeRef = (ReusedNode != null)
? ReusedNode.getThis()
: 0;
// See to comments in the finalize function for an explanation of this
// call synchronized call
synchronized( m_jdb)
{
lNewNodeRef = _getFirst( m_this, m_jdb.m_this, lReusedNodeRef,
iTimeLimit);
}
if (ReusedNode == null)
{
NewNode = new DOMNode(lNewNodeRef, m_jdb);
}
else
{
NewNode=ReusedNode;
NewNode.setRef( lNewNodeRef, m_jdb);
}
return( NewNode);
}
/**
* Gets the last {@link xflaim.DOMNode DOM node} that satisfies the query criteria.
* This may be a document root node, or any node within the document. What
* is returned depends on how the XPATH expression was constructed.
* @param ReusedNode An existing {@link xflaim.DOMNode DOMNode} object
* can optionally be passed in, and it will be reused instead of a new
* object being allocated.
* @param iTimeLimit Time limit (in milliseconds) for operation to complete.
* A value of zero indicates that the operation should not time out.
* @return Returns an instance of {@link xflaim.DOMNode DOMNode}.
* @throws XFlaimException
*/
public DOMNode getLast(
DOMNode ReusedNode,
int iTimeLimit) throws XFlaimException
{
long lNewNodeRef = 0;
DOMNode NewNode;
long lReusedNodeRef = (ReusedNode != null)
? ReusedNode.getThis()
: 0;
// See to comments in the finalize function for an explanation of this
// call synchronized call
synchronized( m_jdb)
{
lNewNodeRef = _getLast( m_this, m_jdb.m_this, lReusedNodeRef,
iTimeLimit);
}
if (ReusedNode == null)
{
NewNode = new DOMNode(lNewNodeRef, m_jdb);
}
else
{
NewNode=ReusedNode;
NewNode.setRef( lNewNodeRef, m_jdb);
}
return( NewNode);
}
/**
* Gets the next {@link xflaim.DOMNode DOM node} that satisfies the query criteria.
* This may be a document root node, or any node within the document. What
* is returned depends on how the XPATH expression was constructed.
* @param ReusedNode An existing {@link xflaim.DOMNode DOMNode} object
* can optionally be passed in, and it will be reused instead of a new
* object being allocated.
* @param iTimeLimit Time limit (in milliseconds) for operation to complete.
* A value of zero indicates that the operation should not time out.
* @param iNumToSkip Specifies the number of nodes to skip over before
* returning a next node. This includes skipping over the node the
* query is currently positioned on. A value of zero has the same effect
* as a value of one - it will position to the next node and return it.
* @return Returns an instance of {@link xflaim.DOMNode DOMNode}.
* @throws XFlaimException
*/
public DOMNode getNext(
DOMNode ReusedNode,
int iTimeLimit,
int iNumToSkip) throws XFlaimException
{
long lNewNodeRef = 0;
DOMNode NewNode;
long lReusedNodeRef = (ReusedNode != null)
? ReusedNode.getThis()
: 0;
// See to comments in the finalize function for an explanation of this
// call synchronized call
synchronized( m_jdb)
{
lNewNodeRef = _getNext( m_this, m_jdb.m_this, lReusedNodeRef,
iTimeLimit, iNumToSkip);
}
if (ReusedNode == null)
{
NewNode = new DOMNode(lNewNodeRef, m_jdb);
}
else
{
NewNode=ReusedNode;
NewNode.setRef( lNewNodeRef, m_jdb);
}
return( NewNode);
}
/**
* Gets the previous {@link xflaim.DOMNode DOM node} that satisfies the query criteria.
* This may be a document root node, or any node within the document. What
* is returned depends on how the XPATH expression was constructed.
* @param ReusedNode An existing {@link xflaim.DOMNode DOMNode} object
* can optionally be passed in, and it will be reused instead of a new
* object being allocated.
* @param iTimeLimit Time limit (in milliseconds) for operation to complete.
* A value of zero indicates that the operation should not time out.
* @param iNumToSkip Specifies the number of nodes to skip over before
* returning a previous node. This includes skipping over the node the
* query is currently positioned on. A value of zero has the same effect
* as a value of one - it will position to the previous node and return it.
* @return Returns an instance of {@link xflaim.DOMNode DOMNode}.
* @throws XFlaimException
*/
public DOMNode getPrev(
DOMNode ReusedNode,
int iTimeLimit,
int iNumToSkip) throws XFlaimException
{
long lNewNodeRef = 0;
DOMNode NewNode;
long lReusedNodeRef = (ReusedNode != null)
? ReusedNode.getThis()
: 0;
// See to comments in the finalize function for an explanation of this
// call synchronized call
synchronized( m_jdb)
{
lNewNodeRef = _getPrev( m_this, m_jdb.m_this, lReusedNodeRef,
iTimeLimit, iNumToSkip);
}
if (ReusedNode == null)
{
NewNode = new DOMNode(lNewNodeRef, m_jdb);
}
else
{
NewNode=ReusedNode;
NewNode.setRef( lNewNodeRef, m_jdb);
}
return( NewNode);
}
/**
* Gets the current {@link xflaim.DOMNode DOM node} that was last returned by
* calls to getFirst, getLast, getNext, or getPrev.
* This may be a document root node, or any node within the document. What
* is returned depends on how the XPATH expression was constructed.
* @param ReusedNode An existing {@link xflaim.DOMNode DOMNode} object
* can optionally be passed in, and it will be reused instead of a new
* object being allocated.
* @return Returns an instance of {@link xflaim.DOMNode DOMNode}.
* @throws XFlaimException
*/
public DOMNode getCurrent(
DOMNode ReusedNode) throws XFlaimException
{
long lNewNodeRef = 0;
DOMNode NewNode;
long lReusedNodeRef = (ReusedNode != null)
? ReusedNode.getThis()
: 0;
// See to comments in the finalize function for an explanation of this
// call synchronized call
synchronized( m_jdb)
{
lNewNodeRef = _getCurrent( m_this, m_jdb.m_this, lReusedNodeRef);
}
if (ReusedNode == null)
{
NewNode = new DOMNode(lNewNodeRef, m_jdb);
}
else
{
NewNode=ReusedNode;
NewNode.setRef( lNewNodeRef, m_jdb);
}
return( NewNode);
}
/**
* Resets the query criteria and results set for the query.
* @throws XFlaimException
*/
public void resetQuery() throws XFlaimException
{
_resetQuery( m_this);
}
/**
* Returns statistics and optimization information for the query.
* @return Returns an array of {@link xflaim.OptInfo OptInfo} objects.
* @throws XFlaimException
*/
public OptInfo [] getStatsAndOptInfo() throws XFlaimException
{
return( _getStatsAndOptInfo( m_this));
}
/**
* Set duplicate handling for the query.
* @param bRemoveDups Specifies whether duplicates should be removed from
* the result set.
* @throws XFlaimException
*/
public void setDupHandling(
boolean bRemoveDups) throws XFlaimException
{
_setDupHandling( m_this, bRemoveDups);
}
/**
* Set an index for the query.
* @param iIndex Index that the query should use.
* @throws XFlaimException
*/
public void setIndex(
int iIndex) throws XFlaimException
{
_setIndex( m_this, iIndex);
}
/**
* Get the index, if any, being used by the query.
* @return Returns the index being used by the query. NOTE: Zero is returned
* if no indexes are being used. If multiple indexes are being used, only
* the first one will be returned. Call usesMultipeIndexes to determine
* if the query is using multiple indexes. To see the list of indexes,
* call getStatsAndOptInfo.
* @throws XFlaimException
*/
public int getIndex() throws XFlaimException
{
return( _getIndex( m_this, m_jdb.m_this));
}
/**
* Determine if the query is using multiple indexes.
* @return Returns a boolean which indicates if the query is using more than
* one index. If zero or one index is being used, will return false.
* @throws XFlaimException
*/
public boolean usesMultipleIndexes() throws XFlaimException
{
return( _usesMultipleIndexes( m_this, m_jdb.m_this));
}
/**
* Add a sort key to the query.
* @param lSortKeyContext Context that the current sort key is to be added
* relative to - either as a child or a sibling. If this is the first
* sort key, a zero should be passed in here. Otherwise, the value returned
* from a previous call to addSortKey should be passed in.
* @param bChildToContext Indicates whether this sort key should be added as
* a child or a sibling to the sort key context that was passed in the
* lSortKeyContext parameter. NOTE: If lSortKeyContext is zero, then the
* bChildToContext parameter is ignored.
* @param bElement Indicates whether the current key component is an element or an
* attribute.
* @param iNameId Name ID of the current key component.
* @param iCompareRules Flags for doing string comparisons when sorting for
* this sort key component. Should be logical ORs of the members of
* {@link xflaim.CompareRules CompareRules}.
* @param iLimit Limit on the size of the key component. If the component
* is a string element or attribute, it is the number of characters. If the
* component is a binary element or attribute, it is the number of bytes.
* @param iKeyComponent Specifies which key component this sort key component
* is. A value of zero indicates that it is not a key component, but simply
* a context component for other key components.
* @param bSortDescending Indicates that this key component should be
* sorted in descending order.
* @param bSortMissingHigh Indicates that when the value for this key
* component is missing, it should be sorted high instead of low.
* @return Returns a value that can be passed back into subsequent calls
* to addSortKey when this component needs to be used as a context for
* subsequent components.
* one index. If zero or one index is being used, will return false.
* @throws XFlaimException
*/
public long addSortKey(
long lSortKeyContext,
boolean bChildToContext,
boolean bElement,
int iNameId,
int iCompareRules,
int iLimit,
int iKeyComponent,
boolean bSortDescending,
boolean bSortMissingHigh) throws XFlaimException
{
return( _addSortKey( m_this, lSortKeyContext, bChildToContext, bElement,
iNameId, iCompareRules, iLimit, iKeyComponent, bSortDescending,
bSortMissingHigh));
}
/**
* Enable absolute positioning in the query result set.
* @throws XFlaimException
*/
public void enablePositioning() throws XFlaimException
{
_enablePositioning( m_this);
}
/**
* Position to the {@link xflaim.DOMNode DOM node} in the result that is at
* the absolute position specified by the iPosition parameter.
* @param ReusedNode An existing {@link xflaim.DOMNode DOMNode} object
* can optionally be passed in, and it will be reused instead of a new
* object being allocated.
* @param iTimeLimit Time limit (in milliseconds) for operation to complete.
* A value of zero indicates that the operation should not time out.
* @param iPosition Absolute position in the result set to position to.
* @return Returns an instance of {@link xflaim.DOMNode DOMNode}.
* @throws XFlaimException
*/
public DOMNode positionTo(
DOMNode ReusedNode,
int iTimeLimit,
int iPosition) throws XFlaimException
{
long lNewNodeRef = 0;
DOMNode NewNode;
long lReusedNodeRef = (ReusedNode != null)
? ReusedNode.getThis()
: 0;
// See to comments in the finalize function for an explanation of this
// call synchronized call
synchronized( m_jdb)
{
lNewNodeRef = _positionTo( m_this, m_jdb.m_this, lReusedNodeRef,
iTimeLimit, iPosition);
}
if (ReusedNode == null)
{
NewNode = new DOMNode(lNewNodeRef, m_jdb);
}
else
{
NewNode=ReusedNode;
NewNode.setRef( lNewNodeRef, m_jdb);
}
return( NewNode);
}
/**
* Position to the {@link xflaim.DOMNode DOM node} in the result that is at
* the position specified by the searchKey parameter.
* @param ReusedNode An existing {@link xflaim.DOMNode DOMNode} object
* can optionally be passed in, and it will be reused instead of a new
* object being allocated.
* @param iTimeLimit Time limit (in milliseconds) for operation to complete.
* A value of zero indicates that the operation should not time out.
* @param searchKey This is a key that corresponds to the sort key that was
* specified using the addSortKey method. This method looks up the node
* in the result set that has this search key and returns it.
* @param iFlags The search flags that direct how the key is to be used
* to do positioning. This should be values from
* {@link xflaim.SearchFlags SearchFlags} that are ORed together.
* @return Returns an instance of {@link xflaim.DOMNode DOMNode}.
* @throws XFlaimException
*/
public DOMNode positionTo(
DOMNode ReusedNode,
int iTimeLimit,
DataVector searchKey,
int iFlags) throws XFlaimException
{
long lNewNodeRef = 0;
DOMNode NewNode;
long lReusedNodeRef = (ReusedNode != null)
? ReusedNode.getThis()
: 0;
// See to comments in the finalize function for an explanation of this
// call synchronized call
synchronized( m_jdb)
{
lNewNodeRef = _positionTo2( m_this, m_jdb.m_this, lReusedNodeRef,
iTimeLimit, searchKey.getThis(), iFlags);
}
if (ReusedNode == null)
{
NewNode = new DOMNode(lNewNodeRef, m_jdb);
}
else
{
NewNode=ReusedNode;
NewNode.setRef( lNewNodeRef, m_jdb);
}
return( NewNode);
}
/**
* Returns the absolute position within the result set where the query
* is currently positioned.
* @return Returns absolute position.
* @throws XFlaimException
*/
public int getPosition() throws XFlaimException
{
return( _getPosition( m_this, m_jdb.m_this));
}
/**
* Build the result set for the query.
* @param iTimeLimit Time limit (in milliseconds) for operation to complete.
* A value of zero indicates that the operation should not time out.
* @throws XFlaimException
*/
public void buildResultSet(
int iTimeLimit) throws XFlaimException
{
_buildResultSet( m_this, m_jdb.m_this, iTimeLimit);
}
/**
* Stop building the result set for the query.
* @throws XFlaimException
*/
public void stopBuildingResultSet()throws XFlaimException
{
_stopBuildingResultSet( m_this);
}
/**
* Enable encryption for the query result set while it is being built.
* Anything that overflows to disk will be encrypted.
* @throws XFlaimException
*/
public void enableResultSetEncryption() throws XFlaimException
{
_enableResultSetEncryption( m_this);
}
/**
* Return counts about the result set that has either been built or is
* in the process of being built.
* @param iTimeLimit Time limit (in milliseconds) for operation to complete.
* A value of zero indicates that the operation should not time out.
* @param bPartialCountOk Specifies whether the method should wait for
* the result set to be completely built before returning counts. If true,
* the method will return the current counts, even if the result set is
* not completely built.
* @returns {@link xflaim.ResultSetCounts ResultSetCounts} object which
* contains various counts pertaining to the result set for the query.
* @throws XFlaimException
*/
public ResultSetCounts getResultSetCounts(
int iTimeLimit,
boolean bPartialCountOk) throws XFlaimException
{
return( _getResultSetCounts( m_this, m_jdb.m_this,
iTimeLimit, bPartialCountOk));
}
// PRIVATE METHODS
private native void _release(
long lThis);
private native long _createQuery(
int iCollection);
private native void _setLanguage(
long lThis,
int iLanguage) throws XFlaimException;
private native void _setupQueryExpr(
long lThis,
long lDbRef,
String sQuery) throws XFlaimException;
private native void _copyCriteria(
long lThis,
long lQueryToCopy) throws XFlaimException;
private native void _addXPathComponent(
long lThis,
int iXPathAxis,
int iNodeType,
int iNameId) throws XFlaimException;
private native void _addOperator(
long lThis,
int iOperator,
int iCompareRules) throws XFlaimException;
private native void _addStringValue(
long lThis,
String sValue) throws XFlaimException;
private native void _addBinaryValue(
long lThis,
byte [] Value) throws XFlaimException;
private native void _addLongValue(
long lThis,
long lValue) throws XFlaimException;
private native void _addBoolean(
long lThis,
boolean bValue,
boolean bUnknown) throws XFlaimException;
private native long _getFirst(
long lThis,
long lDbRef,
long lReusedNode,
int iTimeLimit) throws XFlaimException;
private native long _getLast(
long lThis,
long lDbRef,
long lReusedNode,
int iTimeLimit) throws XFlaimException;
private native long _getNext(
long lThis,
long lDbRef,
long lReusedNode,
int iTimeLimit,
int iNumToSkip) throws XFlaimException;
private native long _getPrev(
long lThis,
long lDbRef,
long lReusedNode,
int iTimeLimit,
int iNumToSkip) throws XFlaimException;
private native long _getCurrent(
long lThis,
long lDbRef,
long lReusedNode) throws XFlaimException;
private native void _resetQuery(
long lThis) throws XFlaimException;
private native OptInfo [] _getStatsAndOptInfo(
long lThis) throws XFlaimException;
private native void _setDupHandling(
long lThis,
boolean bRemoveDups) throws XFlaimException;
private native void _setIndex(
long lThis,
int iIndex) throws XFlaimException;
private native int _getIndex(
long lThis,
long lDbRef) throws XFlaimException;
private native boolean _usesMultipleIndexes(
long lThis,
long lDbRef) throws XFlaimException;
private native long _addSortKey(
long lThis,
long lSortKeyContext,
boolean bChildToContext,
boolean bElement,
int iNameId,
int iCompareRules,
int iLimit,
int iKeyComponent,
boolean bSortDescending,
boolean bSortMissingHigh) throws XFlaimException;
private native void _enablePositioning(
long lThis) throws XFlaimException;
private native long _positionTo(
long lThis,
long lDbRef,
long lReusedNode,
int iTimeLimit,
int iPosition) throws XFlaimException;
private native long _positionTo2(
long lThis,
long lDbRef,
long lReusedNode,
int iTimeLimit,
long lSearchKeyRef,
int iFlags) throws XFlaimException;
private native int _getPosition(
long lThis,
long lDbRef) throws XFlaimException;
private native void _buildResultSet(
long lThis,
long lDbRef,
int iTimeLimit) throws XFlaimException;
private native void _stopBuildingResultSet(
long lThis) throws XFlaimException;
private native void _enableResultSetEncryption(
long lThis) throws XFlaimException;
private native ResultSetCounts _getResultSetCounts(
long lThis,
long lDbRef,
int iTimeLimit,
boolean bPartialCountOk) throws XFlaimException;
private long m_this;
private Db m_jdb;
}
/*
FUNCTIONS NOT YET IMPLEMENTED
virtual RCODE FLMAPI addFunction(
IF_QueryValFunc * pFuncObj,
FLMBOOL bHasXPathExpr) = 0;
virtual void FLMAPI setQueryStatusObject(
IF_QueryStatus * pQueryStatus) = 0;
virtual void FLMAPI setQueryValidatorObject(
IF_QueryValidator * pQueryValidator) = 0;
*/