in vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewImporter.java [428:513]
public void endDocViewNode(@NotNull String nodePath, @NotNull DocViewNode2 docViewNode, @NotNull Optional<DocViewNode2> parentDocViewNode, int line, int column) throws IOException, RepositoryException {
// currentNode's import is finished, check if any child nodes
// need to be removed
NodeNameList childNames = stack.getChildNames();
Node node = stack.getNode();
int numChildren = 0;
if (node == null) {
DocViewAdapter adapter = stack.getAdapter();
if (adapter != null) {
adapter.endNode();
}
// close transformer if last in stack
if (stack.adapter != null) {
List<String> createdPaths = stack.adapter.close();
for (String createdPath : createdPaths) {
importInfo.onCreated(createdPath);
}
stack.adapter = null;
log.trace("Sysview transformation complete.");
}
} else {
NodeIterator iter = node.getNodes();
while (iter.hasNext()) {
numChildren++;
Node child = iter.nextNode();
String path = child.getPath();
String label = Text.getName(path);
AccessControlHandling acHandling = getAcHandling(npResolver.getQName(child.getName()));
if (!childNames.contains(label)
&& !hints.contains(path)
&& isIncluded(child, child.getDepth() - rootDepth)) {
// if the child is in the filter, it belongs to
// this aggregate and needs to be removed
if (aclManagement.isACLNode(child)) {
if (acHandling == AccessControlHandling.OVERWRITE
|| acHandling == AccessControlHandling.CLEAR) {
importInfo.onDeleted(path);
aclManagement.clearACL(node);
}
} else {
if (wspFilter.getImportMode(path) == ImportMode.REPLACE) {
boolean shouldRemoveChild = true;
// check if child is not protected
if (child.getDefinition().isProtected()) {
log.warn("Refuse to delete protected child node: {}", path);
shouldRemoveChild = false;
// check if child is mandatory (and not residual, https://s.apache.org/jcr-2.0-spec/2.0/3_Repository_Model.html#3.7.2.4%20Mandatory)
} else if (child.getDefinition().isMandatory() && !child.getDefinition().getName().equals("*")) {
// get relevant child node definition from parent's effective node type
EffectiveNodeType ent = EffectiveNodeType.ofNode(child.getParent());
Optional<NodeDefinition> childNodeDefinition = ent.getApplicableChildNodeDefinition(child.getName(), child.getPrimaryNodeType());
if (!childNodeDefinition.isPresent()) {
// this should never happen as then child.getDefinition().isMandatory() would have returned false in the first place...
throw new IllegalStateException("Could not find applicable child node definition for mandatory child node " + child.getPath());
} else {
if (!hasSiblingWithPrimaryTypesAndName(child, childNodeDefinition.get().getRequiredPrimaryTypes(), childNodeDefinition.get().getName())) {
log.warn("Refuse to delete mandatory non-residual child node: {} with no other matching siblings", path);
shouldRemoveChild = false;
}
}
}
if (shouldRemoveChild) {
stashPrincipalAcls(child);
importInfo.onDeleted(path);
child.remove();
}
}
}
} else if (acHandling == AccessControlHandling.CLEAR
&& aclManagement.isACLNode(child)
&& isIncluded(child, child.getDepth() - rootDepth)) {
importInfo.onDeleted(path);
aclManagement.clearACL(node);
}
}
if (isIncluded(node, node.getDepth() - rootDepth)) {
// ensure order
stack.restoreOrder();
}
}
stack = stack.pop();
if (node != null && (numChildren == 0 && !childNames.isEmpty() || stack.isRoot())) {
importInfo.addNameList(node.getPath(), childNames);
}
}