mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-07 18:25:23 +00:00
40713: Merged BRANCHES/DEV/BELARUS/V4.1-BUG-FIX-2012_08_15 to BRANCHES/DEV/V4.1-BUG-FIX: 40604: ALF-15274 "I'm following" filter of "My Activities" dashlet doesn't work (PostgreSQL) 40727: Fix for ALF-15469 from Alex Malinovsky - Cannot Edit Online files with special characters in names 40733: Merged DEV (ALF-12358 and ALF-14496) to V4.1-BUG-FIX 38973: DEV for ALF-12358 (upgrades and build plans) 38975: Part of refactoring around the handling of deleted nodes. - Deleted nodes are now treated as real nodes by the NodeDAO 38977: Fixed up queries related to bulk-loading 38978: Fixed up Alfresco side of SOLR tracking APIs to handle removal of alf_node.node_deleted (ALF-12358) 38979: Removed potential contention on cm:name during random file creation 38980: Initial setup for patching of ALF-12358 38981: Merged DEV/BELARUS/ALF-12358-4 to DEV/DEREK/ALF-12358-4 36052: ALF-12358: Concurrency: Possible to create association references to deleted nodes .NodeDeleted. upgrade SQL patch for PostgreSQL is implemented: - SQL create scripts are updated to do not create .alf_node.deleted. column and its indexes; - schema references associated with .alf_node.deleted. column are updated; - Subscriptions DAO and schema reference are updated to use .sys:deleted. type instead of .alf_node.deleted. column; - .NodeStatus. receiving template was modified to receive .typeQNameId. for correct .deleted. state determination; - some other minor fixes 36287: ALF-12358: Concurrency: Possible to create association references to deleted nodes 'NodeDeleted' patch has been implemented for MySQL InnoDB, Alfresco Oracle 9, Alfresco SQL Server and PostgreSQL dialects. Not implemented for DB2 dialect! - DB creating scripts are modified in accordance with removal of 'alf_node.node_deleted' column and respective indexes; - iBATIS schema references are modified in accordance with removal of 'alf_node.node_deleted' column and respective indexes; - the code for handling subscriptions on deleted nodes removed; - subscriptions DAO schema reference is corrected respectively 37284: ALF-12358: Concurrency: Possible to create association references to deleted nodes 'NodeDeletd' updating patch for 4.0 version has been modified to recreate 'alf_node' table for all supported dialects. 'SubscriptionServiceImplTest' has been extended to test whether subscriptions are being removed if node is archived. The new test creates fake user node and applies a custom aspect with 'archive=true' attribute 37905: ALF-12358: Concurrency: Possible to create association references to deleted nodes Maintenance of the .idx_alf_node_txn_type. index has been added into the patch for all the dialects. SQL formatting has been changed to more compact and visually comfortable. Some minor changes for MySQL dialec Also: - Started move to 4.1 scripts - Fixed Schema reference files for alf_node column ordering 38982: ALF-12358: Concurrency: Possible to create association references to deleted nodes - Moving scripts to V4.1 code base - Fixed upgrade with sequences for introduction of 'deleted' qname 38983: Migration to 4.1 fix for ALF-12358 38995: Fix scripts for ALF-12358 - Fixed index removal for indexes that could not possibly have existed - Fixed ALF schema mappings to reflect new index names - Fixed PostgreSQL PK name check 39027: Added in missing index idx_alf_node_txn_type (ALF-12358) - Merge note: Removed redundant index alf_node.fk_alf_node_txn 39028: Fixed fallout from node deletion strategy (ALF-12358) 39222: Minor test enhancements for diagnostics 40738: ALF-11297: resurrect system-build-test (not plugged in yet, still a few failures) 40740: Follow-up for DB2 upgrade for ALF-12358: New alf_node table ID column autoincrement value set 40770: Merged DEV (ALF-12358) to V4.1-BUG-FIX 39223: Merged 3.4.6HF to DEV (ALF-12358) 39218: ALF-15109: Improved fix - must fire cascaded secondary association deletions at DbNodeServiceImpl level to ensure appropriate index events are fired and prevent out of sync indexes! 39259: Merged V3.4.6HF to DEV (ALF-12358) 39240: ALF-15109: Another attempt. Now we are firing all the right events on cascade removal of secondary associations a lot of things are coming out in the wash! - Cascade delete secondary associations in a first recursive pass - Use a List of Pairs rather than a Map to avoid missing multiple associations to the same child 39271: Added policy invocations for peer association removal when an aspect is removed 39401: Utility class to walk a node hierarchy (primary) and gather all association data - Data gathered has to include secondary association pointing out of the hierarchy - Source and target associations gathered as well - TODO: Bulk queries for above 39402: Follow up to ALF-15109: Break node deletion by removing deleteAssocsToAndFrom - TODO: Use NodeHierarchyWalker to gather data, fire policies and execute deletes 39456: NodeHierarchyWalker: tests and fixes 39457: ALF-12358: Remove in-txn manual recording of deleted and new nodes 39917: ALF-12358: Use NodeHierarchyWalker to pick up all associations for a node hierarchy, fire policies and perform deletes - NOTE: Currently, in-process links back to the hierarchy prevent certain tests from passing. - TODO: Add detection for nodes that are about to be deleted 40000: ALF-12358: Added support for 'beforeDeleteNodeAssociationPolicy' 40001: ALF-12358: A node hierarchy walker to predetermine data required for deleting a hierarchy 40002: ALF-12358: Spoof aspect 'sys:pendingDelete' that appears on all nodes within hierarchies being deleted 40003: ALF-12358: Changes to prevent hierarchy modification during delete - The entire hierarchy is read before actual delete starts - All policies (including previously-missing assoc policies) are triggered from the recorded information - Nodes in the delete record cannot have new associations added / removed - All deletes are done on the same information so any underlying data shift causes concurrency violations - Archival: - Archival is a full copy of the hierarchy but all outbound and secondary associations are removed - Archival is followed by a full delete of the original hierarchy 40128: ALF-12358: Test for linking to deleted nodes now fail even after having tested the recovery code - Recovery code shows this when activated: ...ERROR [...NodeDAOImpl] ALF-13066: Orphan child node has been re-homed under lost_found: (49179, ...) 40129: ALF-12358: Added a more verbose message when association deletes don't find required rows 40130: ALF-12358: Avoid incidental removal of associations when removing aspects if the associations are already scheduled for deletion 40131: ALF-12358: Fix fallout for rules linking to avoid multiple deletions of the same association 40371: ALF-12358: Fire beforeDeleteNode even when archiving 40772: Merged DEV (ALF-12358) to V4.1-BUG-FIX 40372: ALF-12358: Fallout in ML code 40397: Fallout from ALF-12358: IMAP pre-commit handling must check for nodes having been deleted - Also fixed some TODOs and line endings for test 40403: PersonService: Reinstated new getPeopleFilteredByProperty method - Also fixed test to rollback transaction after forced catch of exception 40404: Fixed line endings, updated deprecated calls and removed unused code 40494: ALF-12358: Fixed missing before- and after-create policy calls for the archive store 40504: Fixed bug in rev 40494: ALF-12358: Fixed missing before- and after-create policy calls for the archive store - Used incorrect child node reference when calling policies and notifying indexer 40529: ALF-12358: Fixed in-txn holding of nodes pending delete to cater for deletes triggering more deletes 40530: Fallout from ALF-12358: Actions: Association act:scheduledAction multiplicity was not being enforced - act:actionSchedule nodes were not cleaned up when associated actions were deleted - Added onDeleteAssociation handling to clean up act:actionSchedule node - Fixed tests appropriately 40556: Fallout from ALF-12358: Split out negative tests for deleteSite, which were absorbing exceptions 40569: Tagging's beforeCommit behaviour was not checking for nodes having been deleted. - Added 'nodeServiceInternal' and used that to double-check that nodes still exist - Also removed heavily-used call to check if auditing is on 40618: ALF-12358 fallout: Fixed policy callback details for associations of archived nodes - Also some more details when throwing concurrency violation when deleting associations 40673: Fixed fallout from ALF-12358: Multilingual behaviours fixed - Listen to the association being removed from the ML container to the translation - Keep track of containers that must be deleted before committing rather than attempting to delete them immediately; this avoids attempts to delete associations that are about to be deleted (and the thing that ALF-12358 actually fixes). 40680: Follow-up to rev 40673 (ALF-12358): Forgot to remove commented-out code 40781: ALF-15587: Merged PATCHES/V4.0.2 to V4.1-BUG-FIX 40780: Merged DEV to PATCHES/V4.0.2 40777: ALF-15385 : Unable to set bpm:assingee and other properties in Activiti task via JS Added the initialization of runtimeService property. 40787: Merge V4.1 (4.1) to V4.1-BUG-FIX (4.1.1) 40782: Fix ALF-15420: Move: child files/subfolders aren't synced after moving from parent folder and updating in Alfresco on-premise/Cloud - Corrected the handling of moving a sub-folder out of its synced parent 40718: Fixes: ALF-15498: Creates new nodeLock indicator (overrides locked) to cope with differences between content models when a node is locked directly using a nodeLock and when a node is locked due to it being a working copy. 40790: Merged V3.4-BUG-FIX to V4.1-BUG-FIX 40789: ALF-15598: Merged PATCHES/V3.4.9 to V3.4-BUG-FIX 40671: Merged DEV to V3.4.9 (3.4.9.6) 40658: ALF-15505: Build-up of lucene folder segments following CMIS queries (un-closed ResultSet objects?) - Close unclosed ResultSet. - Remove kind="org.alfresco.cmiskind" parameter from query.get and queries.post webscripts and now they use CMISQueryWebScript as implementation. 40795: Fixed txn handling in the event of cleanup failure of test 40797: Fix for ALF-15602 - XSS issue in OpenSearch Explorer webscript - unescaped search terms displayed in page 40810: ALF-12358: Possible build fix (Derek, Neil and Jan to review) - Reinstate invokeBeforeMoveNode which seems to have disappeared in the refactor - Due to extra cascaded calls to onDeleteAssociation, SyncChangeMonitor must ignore certain events 40827: ALF-12358: Possible build fix (Derek, Neil and Jan to review) - SyncChangeMonitor must ignore onDeleteAssociation calls on both sides of the association when a node is deleted 40843: Stop deploying XAM connector to maven repo, it's gone 40845: ALF-15406 Index Tracker seems not to gracefully stop upon shutdown keeping all other threads in waiting - Don't allow Quartz scheduler jobs for the OOoDirect subsystem, checking the connection to backup in a queue. Avoids multiple timeouts. Should just get one now. There is no need for multiple threads to be running anyway. - ALF-610 changes should stop the OOoDirect subsystem from running any of these Quartz jobs in the first place when using the default configuration in an enterprise release. So no timeout? 40848: Merged BRANCHES/DEV/V3.4-BUG-FIX to BRANCHES/DEV/V4.1-BUG-FIX 40847: Fix for ALF-15189 - Incorrect trimming of the date on the Advanced search by date range 40887: ALF-15596: Deadlocks in DescriptorServiceImpl / LicenseComponent threads - Problem discovered by Gab - The two classes are mutually dependent and can end up deadlocking - Removed excessive synchronization from DescriptorServiceImpl - Now two key synchronization points - bootstrap and currentRepoDescriptor updates - Bootstrap synchronization controlled outside this class - no need to defend against it other than throwing IllegalStateException if accessed before bootstrapped - currentRepoDescriptorLock added to regulate currentRepoDescriptor accesses / updates - Uncovered problem in bootstrapping order - descriptorComponent must be bootstrapped before multiTenantBootstrap 40889: ALF-15691: Poor cluster performance in user dashboard due to unnecessary cache replication 40899: ALF-15691: Corrected duplicate property 40900: ALF-12358 / ALF-15688: Finish the job! Make SOLR tracking work again and process deletes (Derek, Andy please review) - select_Txn_Nodes now uses a COALESCE query to substitute the original node ID when recorded in the PROP_ORIGINAL_ID property - NodesGet webscript extended so that it detects deleted nodes in the new way and also includes the noderef - CoreTracker avoids trying to retrieve the metadata of deleted nodes (possible because of NodesGet noderef extension) - SOLRTrackingComponentImpl doesn't barf when getNodesMetadata called for a cascade deleted node by CoreTracker.updateDescendantAuxDocs() 40902: ALF-12358 / ALF-15688: Fixed unit test - Don't expect meta data for deleted nodes anymore (as this is generated on client side) - Also removed stray line of code from CoreTracker 40917: ALF-13750: Merged V3.4-BUG-FIX to V4.1-BUG-FIX 40915: ALF-15708: Trailing whitespace should be trimmed from properties. - Implemented custom properties persister to trim trailing whitespace from properties. 40925: RUSSIAN: Translation updates based on EN r40357 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@40935 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
843 lines
34 KiB
Java
843 lines
34 KiB
Java
/*
|
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
|
*
|
|
* This file is part of Alfresco
|
|
*
|
|
* Alfresco is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Alfresco 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 Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package org.alfresco.repo.domain.node;
|
|
|
|
import java.io.Serializable;
|
|
import java.util.Collection;
|
|
import java.util.Date;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import org.alfresco.repo.node.NodeBulkLoader;
|
|
import org.alfresco.repo.transaction.TransactionalResourceHelper;
|
|
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
|
|
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
|
import org.alfresco.service.cmr.repository.AssociationRef;
|
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
|
import org.alfresco.service.cmr.repository.NodeRef;
|
|
import org.alfresco.service.cmr.repository.Path;
|
|
import org.alfresco.service.cmr.repository.StoreExistsException;
|
|
import org.alfresco.service.cmr.repository.StoreRef;
|
|
import org.alfresco.service.namespace.QName;
|
|
import org.alfresco.util.Pair;
|
|
import org.springframework.dao.ConcurrencyFailureException;
|
|
|
|
/**
|
|
* DAO services for <b>alf_node</b> and related tables
|
|
*
|
|
* @author Derek Hulley
|
|
* @since 3.4
|
|
*/
|
|
public interface NodeDAO extends NodeBulkLoader
|
|
{
|
|
/**
|
|
* Interface used to iterate over pure node results
|
|
*
|
|
* @author Derek Hulley
|
|
* @since 3.4
|
|
*/
|
|
public interface NodeRefQueryCallback
|
|
{
|
|
/**
|
|
* @param nodePair the node result
|
|
* @return Returns <tt>true</tt> if more results are required
|
|
*/
|
|
boolean handle(Pair<Long, NodeRef> nodePair);
|
|
}
|
|
|
|
/*
|
|
* Transaction
|
|
*/
|
|
|
|
/**
|
|
* @param forceNew <tt>true</tt> to ensure that a new transaction entry is created
|
|
* if the current transaction does not have one.
|
|
* @return Returns the ID of the current transaction entry or <tt>null</tt> if
|
|
* there have not been any modifications to nodes registered in the
|
|
* transaction and <tt>forceNew</tt> is <tt>false</tt>
|
|
*/
|
|
public Long getCurrentTransactionId(boolean ensureNew);
|
|
|
|
/*
|
|
* Store
|
|
*/
|
|
|
|
/**
|
|
* Fetch a list of all stores in the repository
|
|
*
|
|
* @return Returns a list of stores
|
|
*/
|
|
public List<Pair<Long, StoreRef>> getStores();
|
|
|
|
/**
|
|
* Find out if a store exists or not
|
|
*
|
|
* @param storeRef the store
|
|
* @return Returns <tt>true</tt> if the store exists otherwise <tt>false</tt>
|
|
*/
|
|
public boolean exists(StoreRef storeRef);
|
|
|
|
/**
|
|
* Creates a unique store for the given protocol and identifier combination.
|
|
* The root node is created with the "root" aspect.
|
|
*
|
|
* @return Returns the root node, which is added automatically.
|
|
* @throws StoreExistsException if the store already exists
|
|
*/
|
|
public Pair<Long, NodeRef> newStore(StoreRef storeRef);
|
|
|
|
/**
|
|
* Changes the old store reference to the new store reference.
|
|
*
|
|
* @param oldStoreRef the existing store
|
|
* @param newStoreRef the new store
|
|
*/
|
|
public void moveStore(StoreRef oldStoreRef, StoreRef newStoreRef);
|
|
|
|
public Pair<Long, NodeRef> getRootNode(StoreRef storeRef);
|
|
|
|
public Set<NodeRef> getAllRootNodes(StoreRef storeRef);
|
|
|
|
/*
|
|
* Node
|
|
*/
|
|
|
|
/**
|
|
* Find out if a node exists. Unpurged deleted nodes do not count as they are the DAO's concern only.
|
|
*
|
|
* @param nodeRef the potentially valid node reference
|
|
* @return Returns <tt>true</tt> if the node is present and undeleted
|
|
*/
|
|
public boolean exists(NodeRef nodeRef);
|
|
|
|
/**
|
|
* Find out if a node exists. Unpurged deleted nodes do not count as they are the DAO's concern only.
|
|
*
|
|
* @param nodeId the potentially valid node ID
|
|
* @return Returns <tt>true</tt> if the node is present and undeleted
|
|
*/
|
|
public boolean exists(Long nodeId);
|
|
|
|
/**
|
|
* @return Returns <tt>true</tt> if the node was last modified in the current
|
|
* transaction, otherwise <tt>false</tt>.
|
|
* @throws InvalidNodeRefException if there is no record of the node, past or present
|
|
*/
|
|
public boolean isInCurrentTxn(Long nodeId);
|
|
|
|
/**
|
|
* Get the current status of the node, including deleted nodes.
|
|
*
|
|
* @param nodeRef the node reference
|
|
* @return Returns the current status of the reference.
|
|
* This will only be <tt>null</tt> if the node never existed or has been
|
|
* purged following deletion.
|
|
*/
|
|
public NodeRef.Status getNodeRefStatus(NodeRef nodeRef);
|
|
|
|
/**
|
|
* Get the current status of the node, including deleted nodes.
|
|
*
|
|
* @param nodeId the node id
|
|
* @return Returns the current status of the reference.
|
|
* This will only be <tt>null</tt> if the node never existed or has been
|
|
* purged following deletion.
|
|
*/
|
|
public NodeRef.Status getNodeIdStatus(Long nodeId);
|
|
|
|
public Pair<Long, NodeRef> getNodePair(NodeRef nodeRef);
|
|
|
|
public Pair<Long, NodeRef> getNodePair(Long nodeId);
|
|
|
|
public QName getNodeType(Long nodeId);
|
|
|
|
public Long getNodeAclId(Long nodeId);
|
|
|
|
/**
|
|
* Create a new node. Note that allowing the <b>uuid</b> to be assigned by passing in a <tt>null</tt>
|
|
* is more efficient.
|
|
*
|
|
* @param parentNodeId the ID of the parent node (may not be <tt>null</tt>)
|
|
* @param assocTypeQName the primary association (may not be <tt>null</tt>)
|
|
* @param assocQName the association path (may not be <tt>null</tt>)
|
|
* @param storeRef the store to which the node must belong
|
|
* @param uuid the node store-unique identifier, or <tt>null</tt> to assign a GUID
|
|
* @param nodeTypeQName the type of the node
|
|
* @parma nodeLocale the locale of the node
|
|
* @param childNodeName the <b>cm:name</b> of the child node or <tt>null</tt> to use the node's UUID
|
|
* @param auditableProperties a map containing any <b>cm:auditable</b> properties for the node
|
|
* @return Returns the details of the child association created
|
|
* @throws InvalidTypeException if the node type is invalid or if the node type
|
|
* is not a valid real node
|
|
* @throws NodeExistsException if the target reference is already taken by a live node
|
|
*/
|
|
public ChildAssocEntity newNode(
|
|
Long parentNodeId,
|
|
QName assocTypeQName,
|
|
QName assocQName,
|
|
StoreRef storeRef,
|
|
String uuid,
|
|
QName nodeTypeQName,
|
|
Locale nodeLocale,
|
|
String childNodeName,
|
|
Map<QName, Serializable> auditableProperties) throws InvalidTypeException;
|
|
|
|
/**
|
|
* Update a node's primary association, giving it a new parent and new association parameters.
|
|
* <p/>
|
|
* <b>**NEW**:</b> If the parent node's store differs from the child node's store, then a new
|
|
* child node's is created.
|
|
*
|
|
* @param childNodeId the child node that is moving
|
|
* @param newParentNodeId the new parent node (may not be <tt>null</tt>)
|
|
* @param assocTypeQName the new association type or <tt>null</tt> to keep the existing type
|
|
* @param assocQName the new association qname or <tt>null</tt> to keep the existing name
|
|
* @return Returns the (first) new association reference and new child reference (second)
|
|
* @throws NodeExistsException if the target UUID of the move (in case of a store move) already exists
|
|
*/
|
|
public Pair<Pair<Long, ChildAssociationRef>, Pair<Long, NodeRef>> moveNode(
|
|
Long childNodeId,
|
|
Long newParentNodeId,
|
|
QName assocTypeQName,
|
|
QName assocQName);
|
|
|
|
/**
|
|
* Update the transaction associated with a lust of nodes
|
|
* @param txnId - the tx id to set
|
|
* @param nodeIds - the nodes to update
|
|
* @return the number of nodes touched
|
|
*/
|
|
public int touchNodes(Long txnId, List<Long> nodeIds);
|
|
|
|
/**
|
|
* @param nodeTypeQName the new type QName for the node or <tt>null</tt> to keep the existing one
|
|
* @param nodeLocale the new locale for the node or <tt>null</tt> to keep the existing one
|
|
* @return <tt>true</tt> if any changes were made
|
|
*/
|
|
public boolean updateNode(Long nodeId, QName nodeTypeQName, Locale nodeLocale);
|
|
|
|
public void setNodeAclId(Long nodeId, Long aclId);
|
|
|
|
public void setPrimaryChildrenSharedAclId(
|
|
Long primaryParentNodeId,
|
|
Long optionalOldSharedAlcIdInAdditionToNull,
|
|
Long newSharedAclId);
|
|
|
|
/**
|
|
* An object that contains data giving a 'view' of the node to be deleted.
|
|
* It is used for ensuring that node cleanup is only done for node-related
|
|
* data that has been handled by the NodeService's policy and related code.
|
|
* <p/>
|
|
* If new data is introduced to a node that has not been covered by the
|
|
* NodeService, then a subsequent node deletion will fail.
|
|
* <p/>
|
|
* This class is NOT thread-safe and should only be used within a transaction.
|
|
* Client code should use the getters to get the ID sets and add any IDs
|
|
* that have been visited during policy triggering.
|
|
*
|
|
* @author Derek Hulley
|
|
* @since 4.1.1
|
|
*/
|
|
public static class NodeView
|
|
{
|
|
private static final String RESOURCE_KEY = "NodeViewMap";
|
|
/**
|
|
* Finds an instance to manage the views for a specific node in this transaction
|
|
*/
|
|
public static NodeView getView(Long nodeId)
|
|
{
|
|
Map<Long, NodeView> nodeViewsById = TransactionalResourceHelper.getMap(RESOURCE_KEY);
|
|
NodeView nodeView = nodeViewsById.get(nodeId);
|
|
if (nodeView == null)
|
|
{
|
|
nodeView = new NodeView();
|
|
nodeViewsById.put(nodeId, nodeView);
|
|
}
|
|
return nodeView;
|
|
}
|
|
|
|
private Set<Long> primaryParentAssocIds = new HashSet<Long>(7);
|
|
private Set<Long> secondaryParentAssocIds = new HashSet<Long>(7);
|
|
private Set<Long> primaryChildAssocIds = new HashSet<Long>(167);
|
|
private Set<Long> secondaryChildAssocIds = new HashSet<Long>(11);
|
|
private Set<Long> targetAssocIds = new HashSet<Long>(11);
|
|
private Set<Long> sourceAssocIds = new HashSet<Long>(11);
|
|
|
|
public Set<Long> getPrimaryParentAssocIds()
|
|
{
|
|
return primaryParentAssocIds;
|
|
}
|
|
public Set<Long> getSecondaryParentAssocIds()
|
|
{
|
|
return secondaryParentAssocIds;
|
|
}
|
|
public Set<Long> getPrimaryChildAssocIds()
|
|
{
|
|
return primaryChildAssocIds;
|
|
}
|
|
public Set<Long> getSecondaryChildAssocIds()
|
|
{
|
|
return secondaryChildAssocIds;
|
|
}
|
|
public Set<Long> getTargetAssocIds()
|
|
{
|
|
return targetAssocIds;
|
|
}
|
|
public Set<Long> getSourceAssocIds()
|
|
{
|
|
return sourceAssocIds;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deletes the node and all entities. Note that the node entry will still exist and be
|
|
* associated with a live transaction.
|
|
*/
|
|
public void deleteNode(Long nodeId);
|
|
|
|
/**
|
|
* Purge deleted nodes where their participating transactions are older than a given time.
|
|
*
|
|
* @param maxTxnCommitTimeMs ignore transactions created <i>after</i> this time
|
|
* @return Returns the number of deleted nodes purged
|
|
*/
|
|
public int purgeNodes(long maxTxnCommitTimeMs);
|
|
|
|
/*
|
|
* Properties
|
|
*/
|
|
|
|
public Serializable getNodeProperty(Long nodeId, QName propertyQName);
|
|
|
|
public Map<QName, Serializable> getNodeProperties(Long nodeId);
|
|
|
|
public boolean setNodeProperties(Long nodeId, Map<QName, Serializable> properties);
|
|
|
|
public boolean addNodeProperty(Long nodeId, QName qname, Serializable value);
|
|
|
|
public boolean addNodeProperties(Long nodeId, Map<QName, Serializable> properties);
|
|
|
|
public boolean removeNodeProperties(Long nodeId, Set<QName> propertyQNames);
|
|
|
|
/**
|
|
* Pull the <b>cm:modified</b> up to the current time without changing any other
|
|
* <b>cm:auditable</b> properties. The change may be done in the current transaction
|
|
* or in a later transaction.
|
|
*
|
|
* @param nodeId the node to change
|
|
* @param modifiedDate the date to set for <b>cm:modified</b>
|
|
* @return Returns <tt>true</tt> if the <b>cm:modified</b> property was actually set
|
|
*/
|
|
public boolean setModifiedDate(Long nodeId, Date date);
|
|
|
|
/*
|
|
* Aspects
|
|
*/
|
|
|
|
public Set<QName> getNodeAspects(Long nodeId);
|
|
|
|
public boolean hasNodeAspect(Long nodeId, QName aspectQName);
|
|
|
|
public boolean addNodeAspects(Long nodeId, Set<QName> aspectQNames);
|
|
|
|
public boolean removeNodeAspects(Long nodeId);
|
|
|
|
public boolean removeNodeAspects(Long nodeId, Set<QName> aspectQNames);
|
|
|
|
/**
|
|
* Get nodes with aspects between the given ranges
|
|
*
|
|
* @param aspectQNames the aspects that must be on the nodes
|
|
* @param minNodeId the minimum node ID (inclusive)
|
|
* @param maxNodeId the maximum node ID (exclusive)
|
|
* @param resultsCallback callback to process results
|
|
*/
|
|
public void getNodesWithAspects(
|
|
Set<QName> aspectQNames,
|
|
Long minNodeId, Long maxNodeId,
|
|
NodeRefQueryCallback resultsCallback);
|
|
|
|
/*
|
|
* Node Assocs
|
|
*/
|
|
|
|
/**
|
|
* Create a new association
|
|
*
|
|
* @param sourceNodeId the association source
|
|
* @param targetNodeId the association target
|
|
* @param assocTypeQName the type of the association (will be resolved to an ID)
|
|
* @param assocIndex the index of the new association (<tt>-1</tt> indicates next value)
|
|
*/
|
|
public Long newNodeAssoc(Long sourceNodeId, Long targetNodeId, QName assocTypeQName, int assocIndex);
|
|
|
|
/**
|
|
* Update an existing assoc's index.
|
|
*
|
|
* @param id the association ID
|
|
* @param assocIndex the new index (greater than 0)
|
|
*/
|
|
public void setNodeAssocIndex(Long id, int assocIndex);
|
|
|
|
/**
|
|
* Remove a specific node association
|
|
*
|
|
* @param assocId the node association ID to remove
|
|
* @return Returns the number of associations removed
|
|
*/
|
|
public int removeNodeAssoc(Long sourceNodeId, Long targetNodeId, QName assocTypeQName);
|
|
|
|
/**
|
|
* Remove all node associations of given IDs
|
|
*
|
|
* @param ids the IDs of the associations to remove
|
|
* @return Returns the number of associations removed
|
|
*/
|
|
public int removeNodeAssocs(List<Long> ids);
|
|
|
|
/**
|
|
* @param nodeId the source or target of the associations
|
|
* @return Returns all the node associations where the node is the <b>source</b> or </b>target</b>
|
|
*/
|
|
public Collection<Pair<Long, AssociationRef>> getNodeAssocsToAndFrom(Long nodeId);
|
|
|
|
/**
|
|
* @param targetNodeId the target of the association
|
|
* @param typeQName the type of the association (optional)
|
|
* @return Returns all the node associations where the node is the </b>target</b>
|
|
*/
|
|
public Collection<Pair<Long, AssociationRef>> getSourceNodeAssocs(Long targetNodeId, QName typeQName);
|
|
|
|
/**
|
|
* @param sourceNodeId the source of the association
|
|
* @param typeQName the type of the association (optional)
|
|
* @return Returns all the node associations where the node is the <b>source</b>
|
|
*/
|
|
public Collection<Pair<Long, AssociationRef>> getTargetNodeAssocs(Long sourceNodeId, QName typeQName);
|
|
|
|
/**
|
|
* @return Returns a specific node association with the given ID
|
|
* or <tt>null</tt> if it doesn't exist
|
|
*/
|
|
public Pair<Long, AssociationRef> getNodeAssocOrNull(Long assocId);
|
|
|
|
/**
|
|
* @return Returns a specific node association with the given ID
|
|
*
|
|
* @throws ConcurrencyFailureException if the association ID is invalid
|
|
*/
|
|
public Pair<Long, AssociationRef> getNodeAssoc(Long assocId);
|
|
|
|
/*
|
|
* Child Assocs
|
|
*/
|
|
|
|
/**
|
|
* Interface used to iterate over results from child association queries
|
|
*
|
|
* @author Derek Hulley
|
|
* @since 3.4
|
|
*/
|
|
public interface ChildAssocRefQueryCallback
|
|
{
|
|
/**
|
|
* @return Return <tt>false</tt> to terminate the query
|
|
* i.e. stop receiving results
|
|
*/
|
|
boolean handle(
|
|
Pair<Long, ChildAssociationRef> childAssocPair,
|
|
Pair<Long, NodeRef> parentNodePair,
|
|
Pair<Long, NodeRef> childNodePair
|
|
);
|
|
|
|
/**
|
|
* @return Return <tt>true</tt> if caching of the results is required
|
|
*/
|
|
boolean preLoadNodes();
|
|
|
|
/**
|
|
* @return Return <tt>true</tt> if child associations must be ordered by
|
|
* index and ID
|
|
*/
|
|
boolean orderResults();
|
|
|
|
/**
|
|
* Called once the iteration of results has concluded
|
|
*/
|
|
void done();
|
|
}
|
|
|
|
/**
|
|
* Create a new child association. The unique enforcement for <b>cm:name</b> will be done
|
|
* as part of the association creation i.e. there is no need to update it after the fact.
|
|
*
|
|
* @param childNodeName the <b>cm:name</b> to apply to the association
|
|
* @return Returns the persisted and filled association's ID
|
|
*/
|
|
public Pair<Long, ChildAssociationRef> newChildAssoc(
|
|
Long parentNodeId,
|
|
Long childNodeId,
|
|
QName assocTypeQName,
|
|
QName assocQName,
|
|
String childNodeName);
|
|
|
|
/**
|
|
* @param assocId the ID of the child association to delete
|
|
*/
|
|
public void deleteChildAssoc(Long assocId);
|
|
|
|
/**
|
|
* Sets the association index ordering.
|
|
*
|
|
* @param parentNodeId the parent node ID
|
|
* @param childNodeId the child node ID
|
|
* @param assocTypeQName the association type
|
|
* @param assocQName the association path qualified name
|
|
* @param newIndex the new index
|
|
* @return Returns the number of associations modified
|
|
*/
|
|
public int setChildAssocIndex(
|
|
Long parentNodeId,
|
|
Long childNodeId,
|
|
QName assocTypeQName,
|
|
QName assocQName,
|
|
int index);
|
|
|
|
/**
|
|
* Bulk-update all unique name (<b>cm:name</b>) index for parent associations of a given node.
|
|
*
|
|
* @param childNodeId the child node who's name is changing
|
|
* @param childName the new <b>cm:name</b> value
|
|
*/
|
|
public void setChildAssocsUniqueName(Long childNodeId, String childName);
|
|
|
|
/**
|
|
* Get a specific association
|
|
*
|
|
* @param assocId the ID of the association
|
|
* @return Returns the association reference or <tt>null</tt> if it doesn't exist
|
|
*/
|
|
public Pair<Long, ChildAssociationRef> getChildAssoc(Long assocId);
|
|
|
|
/**
|
|
* Get a specific child association given all the determining data.
|
|
* <p>
|
|
* The implementation may find multiple entries (there is no constraint to prevent it)
|
|
* although the <b>cm:name</b> 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<Long, ChildAssociationRef> getChildAssoc(
|
|
Long parentNodeId,
|
|
Long childNodeId,
|
|
QName assocTypeQName,
|
|
QName assocQName);
|
|
|
|
/**
|
|
* Get the child associations of a given parent node, optionally filtering on association <tt>QName</tt>
|
|
* and association type <tt>QName</tt>.
|
|
* <p/>
|
|
* This is an efficient query for node paths.
|
|
*
|
|
* @param parentNodeId the parent node ID
|
|
* @param childNodeId the child node ID to filter on; <tt>null</tt> for no filtering
|
|
* @param assocTypeQName the association type qname to filter on; <tt>null<tt> for no filtering
|
|
* @param assocQName the association qname to filter on; <tt>null</tt> for no filtering
|
|
* @param isPrimary filter for primary (<tt>true</tt>) or secondary associations;
|
|
* <tt>null</tt> for no filtering.
|
|
* @param sameStore <tt>null</tt> to ignore, <tt>true</tt> to only get children that are in the
|
|
* same store as the parent, or <tt>false</tt> 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 <tt>QName</tt>
|
|
* and association type <tt>QName</tt>.
|
|
* <p/>
|
|
* This is an efficient query for node paths.
|
|
*
|
|
* @param parentNodeId the parent node ID
|
|
* @param assocTypeQName the association type qname to filter on; <tt>null<tt> for no filtering
|
|
* @param assocQName the association qname to filter on; <tt>null</tt> 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 <tt>QName</tt>.
|
|
*
|
|
* @param parentNodeId the parent node ID
|
|
* @param assocTypeQNames the association type qnames to filter on; <tt>null<tt> for no filtering
|
|
* @param resultsCallback the callback that will be called with the results
|
|
*/
|
|
public void getChildAssocs(
|
|
Long parentNodeId,
|
|
Set<QName> assocTypeQNames,
|
|
ChildAssocRefQueryCallback resultsCallback);
|
|
|
|
/**
|
|
* Get a child association for given parent node, association type and child node name (<b>cm:name</b>).
|
|
*
|
|
* @param parentNodeId the parent Node ID
|
|
* @param assocTypeQName the association type to filter on
|
|
* @param childName the <b>cm:name</b> value to filter on
|
|
* @return Returns an association matching the given parent, type and child name
|
|
* (<b>cm:name</b>) - or <tt>null</tt> if not found
|
|
*/
|
|
public Pair<Long, ChildAssociationRef> getChildAssoc(Long parentNodeId, QName assocTypeQName, String childName);
|
|
|
|
/**
|
|
* Get the child associations of a given parent node, filtering on type <tt>QName</tt> and
|
|
* the <b>cm:name</b> of the child nodes.
|
|
* <p>
|
|
* <b>NOTE: </b>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 <tt>null</tt> 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 (<b>cm:name</b>). These will be matched exactly.
|
|
* @param resultsCallback the callback that will be called with the results
|
|
*/
|
|
public void getChildAssocs(
|
|
Long parentNodeId,
|
|
QName assocTypeQName,
|
|
Collection<String> childNames,
|
|
ChildAssocRefQueryCallback resultsCallback);
|
|
|
|
public void getChildAssocsByChildTypes(
|
|
Long parentNodeId,
|
|
Set<QName> 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 <tt>null</tt>
|
|
* if it is a root node
|
|
*/
|
|
public Pair<Long, ChildAssociationRef> getPrimaryParentAssoc(Long childNodeId);
|
|
|
|
/**
|
|
* Get the parent association of a given parent node, optionally filtering on association <tt>QName</tt>
|
|
* and association type <tt>QName</tt>.
|
|
* <p/>
|
|
* This is an efficient query for node paths.
|
|
*
|
|
* @param childNodeId the child node ID
|
|
* @param assocTypeQName the association type qname to filter on; <tt>null<tt> for no filtering
|
|
* @param assocQName the association qname to filter on; <tt>null</tt> for no filtering
|
|
* @param isPrimary filter for primary (<tt>true</tt>) or secondary associations;
|
|
* <tt>null</tt> 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 <i>primary</i> 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<NodeIdAndAclId> getPrimaryChildrenAcls(Long nodeId);
|
|
|
|
/**
|
|
* Build the paths for a node.
|
|
*
|
|
* When searching for <code>primaryOnly == true</code>, checks that there is exactly
|
|
* one path.
|
|
*
|
|
* @param currentNodePair the leave or child node to start with
|
|
* @param primaryOnly <tt>true</tt> to follow only primary parent associations
|
|
*/
|
|
public List<Path> getPaths(Pair<Long, NodeRef> 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 <i>on or before</i> the given time
|
|
*/
|
|
public Long getMaxTxnIdByCommitTime(long maxCommitTime);
|
|
/**
|
|
* Retrieves a specific transaction.
|
|
*
|
|
* @param txnId the unique transaction ID.
|
|
* @return the requested transaction or <tt>null</tt>
|
|
*/
|
|
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. <tt>null</tt> is allowed.
|
|
* @param remoteOnly <tt>true</tt> if locally-written transactions must be ignored
|
|
*/
|
|
public List<Transaction> getTxnsByCommitTimeAscending(
|
|
Long fromTimeInclusive,
|
|
Long toTimeExclusive,
|
|
int count,
|
|
List<Long> 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. <tt>null</tt> is allowed.
|
|
* @param remoteOnly <tt>true</tt> if locally-written transactions must be ignored
|
|
*/
|
|
public List<Transaction> getTxnsByCommitTimeDescending(
|
|
Long fromTimeInclusive,
|
|
Long toTimeExclusive,
|
|
int count,
|
|
List<Long> 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<Transaction> getTxnsByCommitTimeAscending(List<Long> includeTxnIds);
|
|
|
|
public int getTransactionCount();
|
|
|
|
/**
|
|
* @return Returns the node statuses for a transaction, limited to the store
|
|
*/
|
|
public List<NodeRef.Status> getTxnChangesForStore(StoreRef storeRef, Long txnId);
|
|
|
|
/**
|
|
* @return Returns the node statuses for a transaction, regardless of store
|
|
*/
|
|
public List<NodeRef.Status> getTxnChanges(Long txnId);
|
|
|
|
public List<Long> 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 <tt>null</tt> if there are no transactions
|
|
*/
|
|
public Long getMinTxnCommitTime();
|
|
|
|
/**
|
|
* @return Returns the maximum commit time or <tt>null</tt> if there are no transactions
|
|
*/
|
|
public Long getMaxTxnCommitTime();
|
|
|
|
/**
|
|
* @return Returns the minimum id or <tt>0</tt> 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 <tt>0</tt> 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<NodePropertyEntity> selectProperties(Collection<PropertyDefinition> 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);
|
|
}
|