in vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewImporter.java [845:966]
private StackElement addNode(DocViewNode2 docViewNode) throws RepositoryException, IOException {
final Node currentNode = stack.getNode();
Collection<DocViewProperty2> preprocessedProperties = new LinkedList<>(docViewNode.getProperties());
Node existingNode = null;
if (NameConstants.ROOT.equals(docViewNode.getName())) {
// special case for root node update
existingNode = currentNode;
} else {
if (stack.checkForNode() && currentNode.hasNode(docViewNode.getName().toString())) {
existingNode = currentNode.getNode(docViewNode.getName().toString());
}
Optional<String> identifier = docViewNode.getIdentifier();
if (identifier.isPresent()) {
try {
// does uuid already exist in the repo?
Node sameIdNode = session.getNodeByIdentifier(identifier.get());
String newNodePath = currentNode.getPath() + "/" + npResolver.getJCRName(docViewNode.getName());
// edge-case: same node path -> uuid is kept
if (existingNode != null && existingNode.getPath().equals(sameIdNode.getPath())) {
log.debug("Node at {} with existing identifier {} is being updated without modifying its identifier", existingNode.getPath(), docViewNode.getIdentifier());
} else {
log.warn("Node Collision: To-be imported node {} uses a node identifier {} which is already taken by {}, trying to resolve conflict according to policy {}",
newNodePath, docViewNode.getIdentifier(), sameIdNode.getPath(), idConflictPolicy.name());
if (idConflictPolicy == IdConflictPolicy.FAIL) {
// uuid found in path covered by filter
if (isIncluded(sameIdNode, 0)) {
Info sameIdNodeInfo = importInfo.getInfo(sameIdNode.getPath());
// is the conflicting node part of the package (i.e. the package contained duplicate uuids)
if (sameIdNodeInfo != null && sameIdNodeInfo.getType() != Type.DEL) {
throw new ReferentialIntegrityException("Node identifier " + docViewNode.getIdentifier() + " already taken by node " + sameIdNode.getPath() + " from the same package");
} else {
log.warn("Trying to remove existing conflicting node {} (and all its references)", sameIdNode.getPath());
removeReferences(sameIdNode);
String sameIdNodePath = sameIdNode.getPath();
session.removeItem(sameIdNodePath);
log.warn("Node {} and its references removed", sameIdNodePath);
}
existingNode = null;
} else {
// uuid found in path not-covered by filter
throw new ReferentialIntegrityException("Node identifier " + docViewNode.getIdentifier() + " already taken by node " + sameIdNode.getPath());
}
} else if (idConflictPolicy == IdConflictPolicy.LEGACY) {
// is the conflicting node a sibling
if (sameIdNode.getParent().isSame(currentNode)) {
String sameIdNodePath = sameIdNode.getPath();
if (isIncluded(sameIdNode, 0)) {
log.warn("Existing conflicting node {} has same parent as to-be imported one and is contained in the filter, trying to remove it.", sameIdNodePath);
session.removeItem(sameIdNodePath); // references point to new node afterwards
importInfo.onDeleted(sameIdNodePath);
} else {
log.warn("Existing conflicting node {} has same parent as to-be imported one and is not contained in the filter, ignoring new node but continue with children below existing conflicting node", sameIdNodePath);
importInfo.onRemapped(newNodePath, sameIdNodePath);
existingNode = sameIdNode;
}
} else {
log.warn("To-be imported node and existing conflicting node have different parents. Will create new identifier for the former. ({})",
newNodePath);
preprocessedProperties.removeIf(p -> p.getName().equals(NameConstants.JCR_UUID)
|| p.getName().equals(NameConstants.JCR_BASEVERSION)
|| p.getName().equals(NameConstants.JCR_PREDECESSORS)
|| p.getName().equals(NameConstants.JCR_SUCCESSORS)
|| p.getName().equals(NameConstants.JCR_VERSIONHISTORY));
}
}
}
} catch (ItemNotFoundException e) {
// ignore
}
}
}
// check if new node needs to be checked in
preprocessedProperties.removeIf(p -> p.getName().equals(NameConstants.JCR_ISCHECKEDOUT));
boolean isCheckedIn = "false".equals(docViewNode.getPropertyValue(NameConstants.JCR_ISCHECKEDOUT).orElse("true"));
// create or update node
boolean isNew = existingNode == null;
if (isNew) {
// workaround for bug in jcr2spi if mixins are empty
if (!docViewNode.hasProperty(NameConstants.JCR_MIXINTYPES)) {
preprocessedProperties.add(new DocViewProperty2(NameConstants.JCR_MIXINTYPES, Collections.emptyList(), PropertyType.NAME));
}
stack.ensureCheckedOut();
existingNode = createNewNode(currentNode, docViewNode.cloneWithDifferentProperties(preprocessedProperties));
if (existingNode.getDefinition() == null) {
throw new RepositoryException("Child node not allowed.");
}
if (existingNode.isNodeType(JcrConstants.NT_RESOURCE)) {
if (!existingNode.hasProperty(JcrConstants.JCR_DATA)) {
importInfo.onMissing(existingNode.getPath() + "/" + JcrConstants.JCR_DATA);
}
} else if (isCheckedIn) {
// don't rely on isVersionable here, since SPI might not have this info yet
importInfo.registerToVersion(existingNode.getPath());
}
importInfo.onCreated(existingNode.getPath());
} else if (isIncluded(existingNode, existingNode.getDepth() - rootDepth)) {
if (isCheckedIn) {
// don't rely on isVersionable here, since SPI might not have this info yet
importInfo.registerToVersion(existingNode.getPath());
}
ImportMode importMode = wspFilter.getImportMode(existingNode.getPath());
Node updatedNode = updateExistingNode(existingNode, docViewNode.cloneWithDifferentProperties(preprocessedProperties), importMode);
if (updatedNode != null) {
if (updatedNode.isNodeType(JcrConstants.NT_RESOURCE) && !updatedNode.hasProperty(JcrConstants.JCR_DATA)) {
importInfo.onMissing(existingNode.getPath() + "/" + JcrConstants.JCR_DATA);
}
importInfo.onModified(updatedNode.getPath());
existingNode = updatedNode;
} else {
importInfo.onNop(existingNode.getPath());
}
} else {
// remove registered binaries outside of the filter (JCR-126)
binaries.remove(existingNode.getPath());
}
return new StackElement(existingNode, isNew);
}