getChildAssoc(Long assocId);
    
    /**
     * Get a specific child association given all the determining data.
     * 
     * The implementation may find multiple entries (there is no constraint to prevent it)
     * although the cm:name constraint will normally prevent the association from
     * being created twice.  The lowest ID association will always be returned and the
     * others will be cleaned up if the transaction is read-write.
     * 
     * @return Returns a matching association or null if one was not found.
     */
    public Pair getChildAssoc(
            Long parentNodeId,
            Long childNodeId,
            QName assocTypeQName,
            QName assocQName);
    /**
     * Get the child associations of a given parent node, optionally filtering on association QName
     * and association type QName.
     * 
     * This is an efficient query for node paths.
     * 
     * @param parentNodeId          the parent node ID
     * @param childNodeId           the child node ID to filter on; null for no filtering
     * @param assocTypeQName        the association type qname to filter on; null for no filtering
     * @param assocQName            the association qname to filter on; null for no filtering
     * @param isPrimary             filter for primary (true) or secondary associations;
     *                              null for no filtering.
     * @param sameStore             null to ignore, true to only get children that are in the
     *                              same store as the parent, or false to only get children that are in
     *                              a different store from the parent.
     * @param resultsCallback       the callback that will be called with the results
     */
    public void getChildAssocs(
            Long parentNodeId,
            Long childNodeId,
            QName assocTypeQName,
            QName assocQName,
            Boolean isPrimary,
            Boolean sameStore,
            ChildAssocRefQueryCallback resultsCallback);
    /**
     * Gets the first n child associations of a given parent node, optionally filtering on association QName
     * and association type QName.
     * 
     * This is an efficient query for node paths.
     * 
     * @param parentNodeId          the parent node ID
     * @param assocTypeQName        the association type qname to filter on; null for no filtering
     * @param assocQName            the association qname to filter on; null for no filtering
     * @param maxResults            the maximum number of results to return. The query will be terminated efficiently
     *                              after that number of results                             
     * @param resultsCallback       the callback that will be called with the results
     * @return a list of child associations
     */
    public void getChildAssocs(
            Long parentNodeId,
            QName assocTypeQName,
            QName assocQName,
            final int maxResults,
            ChildAssocRefQueryCallback resultsCallback);
    
   /**
     * Get the child associations of a given parent node, optionally filtering on type QName.
     * 
     * @param parentNodeId          the parent node ID
     * @param assocTypeQNames       the association type qnames to filter on; null for no filtering
     * @param resultsCallback       the callback that will be called with the results
     */
    public void getChildAssocs(
            Long parentNodeId,
            Set assocTypeQNames,
            ChildAssocRefQueryCallback resultsCallback);
    /**
     * Get a child association for given parent node, association type and child node name (cm:name).
     * 
     * @param parentNodeId          the parent Node ID
     * @param assocTypeQName        the association type to filter on
     * @param childName             the cm:name value to filter on
     * @return                      Returns an association matching the given parent, type and child name
     *                              (cm:name) - or null if not found
     */
    public Pair getChildAssoc(Long parentNodeId, QName assocTypeQName, String childName);
    /**
     * Get the child associations of a given parent node, filtering on type QName and
     * the cm:name of the child nodes.
     * 
     * NOTE: This method only works if the association type fundamentally supports unique-name enforcement.
     * 
     * @param parentNodeId          the parent node
     * @param assocTypeQName        the type of the association to check; or null for no filtering.
     *                              If the association type is not specified, then the same child node may be
     *                              included several times.
     * @param childNames            the names of the child nodes (cm:name).  These will be matched exactly.
     * @param resultsCallback       the callback that will be called with the results
     */
    public void getChildAssocs(
            Long parentNodeId,
            QName assocTypeQName,
            Collection childNames,
            ChildAssocRefQueryCallback resultsCallback);
    public void getChildAssocsByChildTypes(
            Long parentNodeId,
            Set childNodeTypeQNames,
            ChildAssocRefQueryCallback resultsCallback);
    
    /**
     * Gets the set of child associations of a certain parent node without parent associations of a certain type to
     * other nodes with the same parent! In effect the 'orphans' with respect to a certain association type.
     * 
     * @param parentNodeId          the parent node ID
     * @param assocTypeQName        the association type QName
     * @param resultsCallback       the callback that will be called with the results
     */
    public void getChildAssocsWithoutParentAssocsOfType(
            final Long parentNodeId,
            final QName assocTypeQName,
            ChildAssocRefQueryCallback resultsCallback);
    /**
     * Finds the association between the node's primary parent and the node itself
     * 
     * @return                      Returns the primary (defining) association or null
     *                              if it is a root node
     */
    public Pair getPrimaryParentAssoc(Long childNodeId);
    /**
     * Get the parent association of a given parent node, optionally filtering on association QName
     * and association type QName.
     * 
     * This is an efficient query for node paths.
     * 
     * @param childNodeId           the child node ID
     * @param assocTypeQName        the association type qname to filter on; null for no filtering
     * @param assocQName            the association qname to filter on; null for no filtering
     * @param isPrimary             filter for primary (true) or secondary associations;
     *                              null for no filtering.
     * @param resultsCallback       the callback that will be called with the results
     */
    public void getParentAssocs(
            Long childNodeId,
            QName assocTypeQName,
            QName assocQName,
            Boolean isPrimary,
            ChildAssocRefQueryCallback resultsCallback);
    /**
     * Fetch all primary child node IDs and corresponding ACL IDs. 
     * 
     * @param nodeId                the parent node ID
     * @return                      Returns a list of Node ID - ACL ID pairs
     */
    public List getPrimaryChildrenAcls(Long nodeId);
    
    /**
     * Build the paths for a node.
     * 
     * When searching for primaryOnly == true, checks that there is exactly
     * one path.
     * 
     * @param currentNodePair       the leave or child node to start with
     * @param primaryOnly           true to follow only primary parent associations
     */
    public List getPaths(Pair nodePair, boolean primaryOnly) throws InvalidNodeRefException;
    
    /**
     * Perform a check for cyclic relationships
     */
    public void cycleCheck(Long nodeId);
    /*
     * Transactions
     */
    
    /**
     * Retrieves the maximum transaction ID for which the commit time is less than the given time.
     * 
     * @param maxCommitTime         the max commit time (ms)
     * @return                      the last transaction on or before the given time
     */
    public Long getMaxTxnIdByCommitTime(long maxCommitTime);
    /**
     * Retrieves a specific transaction.
     * 
     * @param txnId                 the unique transaction ID.
     * @return                      the requested transaction or null
     */
    public Transaction getTxnById(Long txnId);
    /**
     * Get all transactions in a given time range.  Since time-based retrieval doesn't guarantee uniqueness
     * for any given millisecond, a list of optional exclusions may be provided.
     * 
     * @param excludeTxnIds         a list of txn IDs to ignore.  null is allowed.
     * @param remoteOnly            true if locally-written transactions must be ignored
     */
    public List getTxnsByCommitTimeAscending(
            Long fromTimeInclusive,
            Long toTimeExclusive,
            int count,
            List excludeTxnIds,
            boolean remoteOnly);
    /**
     * Get all transactions in a given time range.  Since time-based retrieval doesn't guarantee uniqueness
     * for any given millisecond, a list of optional exclusions may be provided.
     * 
     * @param excludeTxnIds         a list of txn IDs to ignore.  null is allowed.
     * @param remoteOnly            true if locally-written transactions must be ignored
     */
    public List getTxnsByCommitTimeDescending(
            Long fromTimeInclusive,
            Long toTimeExclusive,
            int count,
            List excludeTxnIds,
            boolean remoteOnly);
    /**
     * Get a specific list of transactions ordered by commit time.
     * 
     * @param includeTxnIds     a list of transaction IDs to search for
     * @return                  Returns the transactions by commit time for the given IDs
     */
    public List getTxnsByCommitTimeAscending(List includeTxnIds);
    
    public int getTransactionCount();
    
    /**
     * @return              Returns the node statuses for a transaction, limited to the store
     */
    public List getTxnChangesForStore(StoreRef storeRef, Long txnId);
    
    /**
     * @return              Returns the node statuses for a transaction, regardless of store
     */
    public List getTxnChanges(Long txnId);
    
    public List getTxnsUnused(Long minTxnId, long maxCommitTime, int count);
    
    /**
     * Remove unused transactions from commit time 'fromCommitTime' to commit time 'toCommitTime'
     * 
     * @param fromCommitTime	delete unused transactions from commit time
     * @param toCommitTime		delete unused transactions to commit time
     * 
     * @return
     */
    public int deleteTxnsUnused(long fromCommitTime, long toCommitTime);
    
    public void purgeTxn(Long txnId);
    
    /**
     * @return              Returns the minimum commit time or null if there are no transactions
     */
    public Long getMinTxnCommitTime();
    
    /**
     * @return              Returns the maximum commit time or null if there are no transactions
     */
    public Long getMaxTxnCommitTime();
    
    /**
     * @return              Returns the minimum id or 0 if there are no transactions
     */
    public Long getMinTxnId();
    
    /**
     * 
     * @return the commit time of the oldest unused transaction
     */
    public Long getMinUnusedTxnCommitTime();
    
    /**
     * @return              Returns the maximum id or 0 if there are no transactions
     */
    public Long getMaxTxnId();
    
    /**
     * Select children by property values
     */
    public void getChildAssocsByPropertyValue(
            Long parentNodeId,
            QName propertyQName, 
            Serializable nodeValue,
            ChildAssocRefQueryCallback resultsCallback);
    /**
     * Used by the re-encryptor to re-encrypt encryptable properties with a new encryption key.
     */
    public List selectProperties(Collection propertyDefs);
    
    /**
     * Counts the number of child associations directly under parentNodeId.
     * 
     * @param parentNodeId  the parent node id
     * @param isPrimary     count just primary associations?
     */
    public int countChildAssocsByParent(Long parentNodeId, boolean isPrimary);
    /**
     * Get one last transaction in a given time range.
     */
    public List getOneTxnsByCommitTimeDescending(
            Long fromTimeInclusive,
            Long toTimeExclusive,
            boolean remoteOnly);
}