use of org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry in project jackrabbit by apache.
the class SessionImpl method getVersionState.
/**
* Returns the NodeState of the given Node and asserts that the state is
* listed in the hierarchy built by this Session. If the version
* was obtained from a different session, the 'corresponding' version
* state for this session is retrieved.
*
* @param version
* @return the NodeState associated with the specified version.
*/
NodeState getVersionState(Version version) throws RepositoryException {
NodeState nodeState;
if (version.getSession() == this) {
nodeState = (NodeState) ((NodeImpl) version).getItemState();
} else {
Path p = getQPath(version.getPath());
Path parentPath = p.getAncestor(1);
HierarchyEntry parentEntry = getHierarchyManager().lookup(parentPath);
if (parentEntry != null) {
// make sure the parent entry is up to date
parentEntry.invalidate(false);
}
nodeState = getHierarchyManager().getNodeState(p);
}
return nodeState;
}
use of org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry in project jackrabbit by apache.
the class LazyItemIterator method skip.
/**
* {@inheritDoc}
* @see RangeIterator#skip(long)
*/
public void skip(long skipNum) {
if (skipNum < 0) {
throw new IllegalArgumentException("skipNum must not be negative");
}
if (skipNum == 0) {
return;
}
if (next == null) {
throw new NoSuchElementException();
}
// skip the first (skipNum - 1) items without actually retrieving them
while (--skipNum > 0) {
pos++;
HierarchyEntry entry = iter.next();
// check if item exists but don't build Item instance.
boolean itemExists = false;
while (!itemExists) {
try {
itemExists = itemMgr.itemExists(entry);
} catch (RepositoryException e) {
log.warn("Failed to check that item {} exists", entry, e);
}
if (!itemExists) {
log.debug("Ignoring nonexistent item {}", entry);
entry = iter.next();
}
}
}
// fetch final item (the one to be returned on next())
pos++;
next = prefetchNext();
}
use of org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry in project jackrabbit by apache.
the class TransientItemStateManager method containedInTree.
/**
*
* @param parent
* @param state
* @return
*/
private static boolean containedInTree(ItemState parent, ItemState state) {
HierarchyEntry he = state.getHierarchyEntry();
HierarchyEntry pHe = parent.getHierarchyEntry();
// short cuts first
if (he == pHe || he.getParent() == pHe) {
return true;
}
if (!parent.isNode() || he == pHe.getParent()) {
return false;
}
// none of the simple cases: walk up hierarchy
HierarchyEntry pe = he.getParent();
while (pe != null) {
if (pe == pHe) {
return true;
}
pe = pe.getParent();
}
// state isn't descendant of 'parent'
return false;
}
use of org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry in project jackrabbit by apache.
the class TransientItemStateManager method getChangeLog.
/**
* Create the change log for the tree starting at <code>target</code>. This
* includes a check if the ChangeLog to be created is totally 'self-contained'
* and independent; items within the scope of this update operation (i.e.
* below the target) must not have dependencies outside of this tree (e.g.
* moving a node requires that the target node including both old and new
* parents are saved).
*
* @param target
* @param throwOnStale Throws InvalidItemStateException if either the given
* <code>ItemState</code> or any of its descendants is stale and the flag is true.
* @return
* @throws InvalidItemStateException if a stale <code>ItemState</code> is
* encountered while traversing the state hierarchy. The <code>changeLog</code>
* might have been populated with some transient item states. A client should
* therefore not reuse the <code>changeLog</code> if such an exception is thrown.
* @throws RepositoryException if <code>state</code> is a new item state.
*/
ChangeLog getChangeLog(ItemState target, boolean throwOnStale) throws InvalidItemStateException, ConstraintViolationException, RepositoryException {
// fail-fast test: check status of this item's state
if (target.getStatus() == Status.NEW) {
String msg = "Cannot save/revert an item with status NEW (" + target + ").";
log.debug(msg);
throw new RepositoryException(msg);
}
if (throwOnStale && Status.isStale(target.getStatus())) {
String msg = "Attempt to save/revert an item, that has been externally modified (" + target + ").";
log.debug(msg);
throw new InvalidItemStateException(msg);
}
Set<Operation> ops = new LinkedHashSet<Operation>();
Set<ItemState> affectedStates = new LinkedHashSet<ItemState>();
HierarchyEntry he = target.getHierarchyEntry();
if (he.getParent() == null) {
// simplicity. collecting ops, states can be omitted.
if (throwOnStale && !staleStates.isEmpty()) {
String msg = "Cannot save changes: States has been modified externally.";
log.debug(msg);
throw new InvalidItemStateException(msg);
} else {
affectedStates.addAll(staleStates);
}
ops.addAll(operations);
affectedStates.addAll(addedStates);
affectedStates.addAll(modifiedStates);
affectedStates.addAll(removedStates);
} else {
// - check if there is a stale state in the scope (save only)
if (throwOnStale) {
for (ItemState state : staleStates) {
if (containedInTree(target, state)) {
String msg = "Cannot save changes: States has been modified externally.";
log.debug(msg);
throw new InvalidItemStateException(msg);
}
}
}
// - collect all affected states within the scope of save/undo
Iterator[] its = new Iterator[] { addedStates.iterator(), removedStates.iterator(), modifiedStates.iterator() };
IteratorChain chain = new IteratorChain(its);
if (!throwOnStale) {
chain.addIterator(staleStates.iterator());
}
while (chain.hasNext()) {
ItemState state = (ItemState) chain.next();
if (containedInTree(target, state)) {
affectedStates.add(state);
}
}
// changelog.
for (Operation op : operations) {
Collection<ItemState> opStates = op.getAffectedItemStates();
for (ItemState state : opStates) {
if (affectedStates.contains(state)) {
// operation needs to be included
if (!affectedStates.containsAll(opStates)) {
// incomplete changelog: need to save a parent as well
String msg = "ChangeLog is not self contained.";
throw new ConstraintViolationException(msg);
}
// no violation: add operation an stop iteration over
// all affected states present in the operation.
ops.add(op);
break;
}
}
}
}
ChangeLog cl = new ChangeLog(target, ops, affectedStates);
return cl;
}
use of org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry in project jackrabbit by apache.
the class ChangeLog method persisted.
//-----------------------------------------------< Inform the ChangeLog >---
/**
* Call this method when this change log has been successfully persisted.
* This implementation will call {@link Operation#persisted()} on the
* individual operations followed by setting all remaining modified
* states to EXISTING.
*/
public void persisted() throws RepositoryException {
List<NodeState> changedMixins = new ArrayList<NodeState>();
List<NodeState> changedPrimaryTypes = new ArrayList<NodeState>();
Operation[] ops = operations.toArray(new Operation[operations.size()]);
for (int i = 0; i < ops.length; i++) {
ops[i].persisted();
if (ops[i] instanceof SetMixin) {
changedMixins.add(((SetMixin) ops[i]).getNodeState());
} else if (ops[i] instanceof SetPrimaryType) {
changedPrimaryTypes.add(((SetPrimaryType) ops[i]).getNodeState());
}
}
// operation persistence.
for (ItemState state : affectedStates) {
HierarchyEntry he = state.getHierarchyEntry();
switch(state.getStatus()) {
case Status.EXISTING_MODIFIED:
state.setStatus(Status.EXISTING);
if (state.isNode()) {
if (changedPrimaryTypes.contains(state)) {
// primary type changed for a node -> force reloading upon next
// access in order to be aware of modified definition etc...
he.invalidate(true);
} else if (changedMixins.contains(state)) {
// mixin changed for a node -> force reloading upon next
// access in order to be aware of modified uniqueID.
he.invalidate(false);
}
}
break;
case Status.EXISTING_REMOVED:
he.remove();
break;
case Status.NEW:
// illegal. should not get here.
log.error("ChangeLog still contains NEW state: " + state.getName());
state.setStatus(Status.EXISTING);
break;
case Status.MODIFIED:
case Status._UNDEFINED_:
case Status.STALE_DESTROYED:
case Status.STALE_MODIFIED:
// illegal.
log.error("ChangeLog contains state (" + state.getName() + ") with illegal status " + Status.getName(state.getStatus()));
break;
case Status.EXISTING:
if (state.isNode() && changedMixins.contains(state)) {
// mixin changed for a node -> force reloading upon next
// access in order to be aware of modified uniqueID.
he.invalidate(false);
}
// otherwise: ignore. operations already have been completed
break;
case Status.INVALIDATED:
case Status.REMOVED:
he.invalidate(false);
break;
}
}
}
Aggregations