use of org.apache.jackrabbit.core.state.NodeState in project jackrabbit by apache.
the class NodeImpl method replaceChildNode.
/**
* Replaces the child node with the specified <code>id</code>
* by a new child node with the same id and specified <code>nodeName</code>,
* <code>nodeTypeName</code> and <code>mixinNames</code>.
*
* @param id id of the child node to be replaced
* @param nodeName name of the new node
* @param nodeTypeName name of the new node's node type
* @param mixinNames name of the new node's mixin types
*
* @return the new child node replacing the existing child
* @throws ItemNotFoundException
* @throws NoSuchNodeTypeException
* @throws VersionException
* @throws ConstraintViolationException
* @throws LockException
* @throws RepositoryException
*/
public synchronized NodeImpl replaceChildNode(NodeId id, Name nodeName, Name nodeTypeName, Name[] mixinNames) throws ItemNotFoundException, NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException, RepositoryException {
// check state of this instance
sanityCheck();
Node existing = (Node) itemMgr.getItem(id);
// 'replace' is actually a 'remove existing/add new' operation;
// this unfortunately changes the order of this node's
// child node entries (JCR-1055);
// => backup list of child node entries beforehand in order
// to restore it afterwards
NodeState state = data.getNodeState();
ChildNodeEntry cneExisting = state.getChildNodeEntry(id);
if (cneExisting == null) {
throw new ItemNotFoundException(this + ": no child node entry with id " + id);
}
List<ChildNodeEntry> cneList = new ArrayList<ChildNodeEntry>(state.getChildNodeEntries());
// remove existing
existing.remove();
// create new child node
NodeImpl node = addNode(nodeName, nodeTypeName, id);
if (mixinNames != null) {
for (Name mixinName : mixinNames) {
node.addMixin(mixinName);
}
}
// fetch <code>state</code> again, as it changed while removing child
state = data.getNodeState();
// restore list of child node entries (JCR-1055)
if (cneExisting.getName().equals(nodeName)) {
// restore original child node list
state.setChildNodeEntries(cneList);
} else {
// replace child node entry with different name
// but preserving original position
state.removeAllChildNodeEntries();
for (ChildNodeEntry cne : cneList) {
if (cne.getId().equals(id)) {
// replace entry with different name
state.addChildNodeEntry(nodeName, id);
} else {
state.addChildNodeEntry(cne.getName(), cne.getId());
}
}
}
return node;
}
use of org.apache.jackrabbit.core.state.NodeState in project jackrabbit by apache.
the class NodeImpl method removeChildNode.
protected void removeChildNode(NodeId childId) throws RepositoryException {
// modify the state of 'this', i.e. the parent node
NodeState thisState = (NodeState) getOrCreateTransientItemState();
ChildNodeEntry entry = thisState.getChildNodeEntry(childId);
if (entry == null) {
String msg = "failed to remove child " + childId + " of " + this;
log.debug(msg);
throw new RepositoryException(msg);
}
// notify target of removal
try {
NodeImpl childNode = itemMgr.getNode(childId, getNodeId());
childNode.onRemove(getNodeId());
} catch (ItemNotFoundException e) {
boolean ignoreError = false;
if (sessionContext.getSessionImpl().autoFixCorruptions()) {
// it might be an access right problem
// we need to check if the item doesn't exist in the ism
ItemStateManager ism = sessionContext.getItemStateManager();
if (!ism.hasItemState(childId)) {
log.warn("Node " + childId + " not found, ignore", e);
ignoreError = true;
}
}
if (!ignoreError) {
throw e;
}
}
// remove the child node entry
if (!thisState.removeChildNodeEntry(childId)) {
String msg = "failed to remove child " + childId + " of " + this;
log.debug(msg);
throw new RepositoryException(msg);
}
}
use of org.apache.jackrabbit.core.state.NodeState in project jackrabbit by apache.
the class NodeImpl method getOrCreateTransientItemState.
@Override
protected synchronized ItemState getOrCreateTransientItemState() throws RepositoryException {
synchronized (data) {
if (!isTransient()) {
try {
// make transient (copy-on-write)
NodeState transientState = stateMgr.createTransientNodeState((NodeState) stateMgr.getItemState(getId()), ItemState.STATUS_EXISTING_MODIFIED);
// replace persistent with transient state
data.setState(transientState);
} catch (ItemStateException ise) {
String msg = "failed to create transient state";
log.debug(msg);
throw new RepositoryException(msg, ise);
}
}
return getItemState();
}
}
use of org.apache.jackrabbit.core.state.NodeState in project jackrabbit by apache.
the class SearchIndex method updateNodes.
/**
* This implementation forwards the call to
* {@link MultiIndex#update(Collection, Collection)} and
* transforms the two iterators to the required types.
*
* @param remove ids of nodes to remove.
* @param add NodeStates to add. Calls to <code>next()</code> on this
* iterator may return <code>null</code>, to indicate that a
* node could not be indexed successfully.
* @throws RepositoryException if an error occurs while indexing a node.
* @throws IOException if an error occurs while updating the index.
*/
public void updateNodes(Iterator<NodeId> remove, Iterator<NodeState> add) throws RepositoryException, IOException {
checkOpen();
Map<NodeId, NodeState> aggregateRoots = new HashMap<NodeId, NodeState>();
Set<NodeId> removedIds = new HashSet<NodeId>();
Set<NodeId> addedIds = new HashSet<NodeId>();
Collection<NodeId> removeCollection = new ArrayList<NodeId>();
while (remove.hasNext()) {
NodeId id = remove.next();
removeCollection.add(id);
removedIds.add(id);
}
Collection<Document> addCollection = new ArrayList<Document>();
while (add.hasNext()) {
NodeState state = add.next();
if (state != null) {
NodeId id = state.getNodeId();
addedIds.add(id);
retrieveAggregateRoot(state, aggregateRoots);
try {
addCollection.add(createDocument(state, getNamespaceMappings(), index.getIndexFormatVersion()));
} catch (RepositoryException e) {
log.warn("Exception while creating document for node: " + state.getNodeId() + ": " + e.toString());
}
}
}
index.update(removeCollection, addCollection);
// remove any aggregateRoot nodes that are new
// and therefore already up-to-date
aggregateRoots.keySet().removeAll(addedIds);
// based on removed ids get affected aggregate root nodes
retrieveAggregateRoot(removedIds, aggregateRoots);
// update aggregates if there are any affected
if (!aggregateRoots.isEmpty()) {
Collection<Document> modified = new ArrayList<Document>(aggregateRoots.size());
for (NodeState state : aggregateRoots.values()) {
try {
modified.add(createDocument(state, getNamespaceMappings(), index.getIndexFormatVersion()));
} catch (RepositoryException e) {
log.warn("Exception while creating document for node: " + state.getNodeId(), e);
}
}
index.update(aggregateRoots.keySet(), modified);
}
}
use of org.apache.jackrabbit.core.state.NodeState in project jackrabbit by apache.
the class SearchIndex method checkPendingJournalChanges.
/**
* In the case of an initial index build operation, this checks if there are
* some new nodes pending in the journal and tries to preemptively delete
* them, to keep the index consistent.
*
* See JCR-3162
*
* @param context
* @throws IOException
*/
private void checkPendingJournalChanges(QueryHandlerContext context) {
ClusterNode cn = context.getClusterNode();
if (cn == null) {
return;
}
List<NodeId> addedIds = new ArrayList<NodeId>();
long rev = cn.getRevision();
List<ChangeLogRecord> changes = getChangeLogRecords(rev, context.getWorkspace());
Iterator<ChangeLogRecord> iterator = changes.iterator();
while (iterator.hasNext()) {
ChangeLogRecord record = iterator.next();
for (ItemState state : record.getChanges().addedStates()) {
if (!state.isNode()) {
continue;
}
addedIds.add((NodeId) state.getId());
}
}
if (!addedIds.isEmpty()) {
Collection<NodeState> empty = Collections.emptyList();
try {
updateNodes(addedIds.iterator(), empty.iterator());
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
Aggregations