You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by kw...@apache.org on 2021/06/16 19:09:16 UTC
[jackrabbit-filevault] 01/01: JCRVLT-527 deferred validation of
child nodes
This is an automated email from the ASF dual-hosted git repository.
kwin pushed a commit to branch bugfix/JCRVLT-527-deferred-validation-of-folders
in repository https://gitbox.apache.org/repos/asf/jackrabbit-filevault.git
commit e73cbd324db877337d8906b936c50fd7f363be11
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Wed Jun 16 21:06:38 2021 +0200
JCRVLT-527 deferred validation of child nodes
---
vault-validation/pom.xml | 5 -
.../spi/impl/nodetype/JcrNodeTypeMetaData.java | 9 +-
.../spi/impl/nodetype/JcrNodeTypeMetaDataImpl.java | 132 +++++++++------
.../spi/impl/nodetype/NodeTypeValidator.java | 33 ++--
.../impl/nodetype/JcrNodeTypeMetaDataImplTest.java | 182 ++++++++++-----------
.../spi/impl/nodetype/NodeTypeValidatorTest.java | 61 +++++--
6 files changed, 233 insertions(+), 189 deletions(-)
diff --git a/vault-validation/pom.xml b/vault-validation/pom.xml
index ab6f608..195aa16 100644
--- a/vault-validation/pom.xml
+++ b/vault-validation/pom.xml
@@ -91,11 +91,6 @@
</dependency>
<dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- </dependency>
-
- <dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-spi-commons</artifactId>
</dependency>
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaData.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaData.java
index ea41212..d30e8e4 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaData.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaData.java
@@ -42,7 +42,7 @@ import org.jetbrains.annotations.Nullable;
public interface JcrNodeTypeMetaData {
- void addProperty(@NotNull NodeContext nodeContext, @NotNull NamePathResolver namePathResolver, @NotNull EffectiveNodeTypeProvider effectiveNodeTypeProvider,
+ Collection<ValidationMessage> addProperty(@NotNull NodeContext nodeContext, @NotNull NamePathResolver namePathResolver, @NotNull EffectiveNodeTypeProvider effectiveNodeTypeProvider,
@NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider,
@NotNull ValidationMessageSeverity severity, String name, boolean isMultiValue, Value... values) throws RepositoryException;
@NotNull JcrNodeTypeMetaData addImplicitChildNode(@NotNull NameResolver nameResolver,
@@ -53,17 +53,16 @@ public interface JcrNodeTypeMetaData {
@NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider,
@NotNull ValidationMessageSeverity severity, @NotNull NodeContext nodeContext, @NotNull String primaryType, String... mixinTypes)
throws RepositoryException, NamespaceExceptionInNodeName;
- @NotNull JcrNodeTypeMetaData addUnknownChildNode(@NotNull NameResolver nameResolver, @NotNull String name) throws IllegalNameException, NamespaceException;
+ @NotNull JcrNodeTypeMetaData addUnknownChildNode(@NotNull NameResolver nameResolver, @NotNull NodeContext nodeContext, @NotNull String name) throws IllegalNameException, NamespaceException;
// navigate
@NotNull Collection<@NotNull ? extends JcrNodeTypeMetaData> getChildren();
Optional<JcrNodeTypeMetaData> getNode(NamePathResolver nameResolver, String path)
throws ItemNotFoundException, RepositoryException;
- @NotNull JcrNodeTypeMetaData getOrCreateNode(NamePathResolver nameResolver, String path) throws RepositoryException;
+ @NotNull JcrNodeTypeMetaData getOrCreateNode(NamePathResolver nameResolver, @NotNull NodeContext nodeContext, String path) throws RepositoryException;
@NotNull Collection<ValidationMessage> finalizeValidation(@NotNull NamePathResolver nameResolver,
- @NotNull ValidationMessageSeverity severity, @NotNull WorkspaceFilter filter) throws NamespaceException;
- void fetchAndClearValidationMessages(Collection<ValidationMessage> messages);
+ @NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider, @NotNull ValidationMessageSeverity severity, @NotNull WorkspaceFilter filter) throws NamespaceException;
@NotNull Name getPrimaryNodeType();
String getQualifiedPath(NamePathResolver resolver) throws NamespaceException;
void setNodeTypes(@NotNull NameResolver nameResolver, @NotNull EffectiveNodeTypeProvider effectiveNodeTypeProvider,
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImpl.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImpl.java
index 144bc43..bc04131 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImpl.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImpl.java
@@ -82,10 +82,10 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
static final String MESSAGE_CHILD_NODE_NOT_ALLOWED = "Node '%s [%s]' is not allowed as child of node with types [%s]: %s";
static final String MESSAGE_PROPERTY_OF_NOT_CONTAINED_PARENT_POTENTIALLY_NOT_ALLOWED = "Property '%s' [%s] is not allowed in node with potential default types [%s]: %s";;
static final String MESSAGE_PROPERTY_NOT_ALLOWED = "Property '%s' [%s] is not allowed in node with types [%s]: %s";
- static final String MESSAGE_MANDATORY_CHILD_NODE_MISSING = "Mandatory child node missing: %s inside node with types [%s] at %s";
+ static final String MESSAGE_MANDATORY_CHILD_NODE_MISSING = "Mandatory child node missing: %s inside node with types [%s]";
static final String MESSAGE_MANDATORY_UNCONTAINED_CHILD_NODE_MISSING = "Mandatory child node missing: %s inside node with types [%s] at %s (outside of filter rules)";
- static final String MESSAGE_MANDATORY_PROPERTY_MISSING = "Mandatory property '%s' missing in node with types [%s] at %s";
- static final String MESSAGE_MANDATORY_PROPERTY_WITH_WRONG_TYPE = "Mandatory property '%s' has type '%s' while it should have '%s' in node with types [%s] at %s";
+ static final String MESSAGE_MANDATORY_PROPERTY_MISSING = "Mandatory property '%s' missing in node with types [%s]";
+ static final String MESSAGE_MANDATORY_PROPERTY_WITH_WRONG_TYPE = "Mandatory property '%s' has type '%s' while it should have '%s' in node with types [%s]";
// do not validate protected JCR system properties that are handled by FileVault specially in https://github.com/apache/jackrabbit-filevault/blob/f785fcb24d4cbd01c734e9273310a925c29ae15b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java#L123 and
// https://github.com/apache/jackrabbit-filevault/blob/f785fcb24d4cbd01c734e9273310a925c29ae15b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java#L140
@@ -100,28 +100,28 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
private static final QValueFactory QVALUE_FACTORY = QValueFactoryImpl.getInstance();
private final @NotNull Name name;
+ private final @NotNull NodeContext context;
private @Nullable Name primaryNodeType; // the effectiveNodeType does not remember which one was the primary one!
private @Nullable EffectiveNodeType effectiveNodeType;
private final @NotNull Map<Name, Integer> propertyTypesByName;
private final @NotNull Map<Name, JcrNodeTypeMetaDataImpl> childNodesByName;
private final @Nullable JcrNodeTypeMetaDataImpl parentNode;
- private final Collection<ValidationMessage> messages;
private boolean isAuthenticationOrAuthorizationContext;
private final boolean isImplicit; // if this is true, the node type is set implicitly (not explicitly set in package, used as is in the
// repository)
private boolean isValidationDone;
private final boolean isIncremental;
- private JcrNodeTypeMetaDataImpl(boolean isIncremental, @NotNull Name name, @Nullable Name primaryNodeType, @Nullable EffectiveNodeType effectiveNodeType,
+ private JcrNodeTypeMetaDataImpl(boolean isIncremental, @NotNull NodeContext context, @NotNull Name name, @Nullable Name primaryNodeType, @Nullable EffectiveNodeType effectiveNodeType,
JcrNodeTypeMetaDataImpl parentNode, boolean isAuthenticationOrAuthorizationContext, boolean isImplicit) {
super();
+ this.context = context;
this.name = name; // fully namespaced (taking into account local namespace declaration for Docview XML)
this.primaryNodeType = primaryNodeType;
this.effectiveNodeType = effectiveNodeType;
this.parentNode = parentNode;
this.propertyTypesByName = new HashMap<>();
this.childNodesByName = new HashMap<>();
- this.messages = new ArrayList<>();
this.isAuthenticationOrAuthorizationContext = isAuthenticationOrAuthorizationContext;
this.isImplicit = isImplicit;
this.isValidationDone = false;
@@ -135,7 +135,6 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
+ "propertyTypesByName=" + propertyTypesByName + ", "
+ "childNodes=" + childNodesByName.keySet() + ", "
// + "parentNode path="+(parentNode != null ? + parentNode.getPath() + ", " : "")
- + (messages != null ? "messages=" + messages + ", " : "")
+ "isAuthenticationOrAuthorizationContext=" + isAuthenticationOrAuthorizationContext + "]";
}
@@ -213,7 +212,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
@NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider,
@NotNull NodeContext nodeContext, @Nullable Name implicitNodeType) throws RepositoryException {
JcrNodeTypeMetaDataImpl childNode = addChildNode(nameResolver, effectiveNodeTypeProvider, nodeTypeDefinitionProvider,
- itemDefinitionProvider, true, Text.getName(nodeContext.getNodePath()), implicitNodeType);
+ itemDefinitionProvider, true, nodeContext, Text.getName(nodeContext.getNodePath()), implicitNodeType);
// now validate for validity
Optional<String> constraintViolation = childNode.validateAgainstParentNodeType(effectiveNodeType, nodeTypeDefinitionProvider,
itemDefinitionProvider);
@@ -224,13 +223,13 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
}
@Override
- public @NotNull JcrNodeTypeMetaData addUnknownChildNode(@NotNull NameResolver nameResolver, @NotNull String name)
+ public @NotNull JcrNodeTypeMetaData addUnknownChildNode(@NotNull NameResolver nameResolver, @NotNull NodeContext context, @NotNull String name)
throws IllegalNameException, NamespaceException {
- return addUnknownChildNode(getQName(nameResolver, name, NameType.NODE_NAME));
+ return addUnknownChildNode(context, getQName(nameResolver, name, NameType.NODE_NAME));
}
- private @NotNull JcrNodeTypeMetaDataImpl addUnknownChildNode(@NotNull Name name) throws IllegalNameException {
- JcrNodeTypeMetaDataImpl childNode = new JcrNodeTypeMetaDataImpl(this.isIncremental, name, null, null, this, false, false);
+ private @NotNull JcrNodeTypeMetaDataImpl addUnknownChildNode(@NotNull NodeContext context, @NotNull Name name) throws IllegalNameException {
+ JcrNodeTypeMetaDataImpl childNode = new JcrNodeTypeMetaDataImpl(this.isIncremental, context, name, null, null, this, false, false);
childNodesByName.put(name, childNode);
return childNode;
}
@@ -241,26 +240,13 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
@NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider,
@NotNull ValidationMessageSeverity severity, @NotNull NodeContext nodeContext, @NotNull String primaryType,
String... mixinTypes)
- throws IllegalNameException, NoSuchNodeTypeException, RepositoryException, NamespaceExceptionInNodeName {
+ throws IllegalNameException, RepositoryException, NamespaceExceptionInNodeName {
List<Name> types = getTypes(nameResolver, primaryType, mixinTypes);
String nodeName = Text.getName(nodeContext.getNodePath());
JcrNodeTypeMetaDataImpl childNode = addChildNode(nameResolver, effectiveNodeTypeProvider, nodeTypeDefinitionProvider,
- itemDefinitionProvider, false, nodeName, types.toArray(new Name[0]));
- // now validate for validity
- Optional<String> constraintViolation = childNode.validateAgainstParentNodeType(effectiveNodeType, nodeTypeDefinitionProvider,
- itemDefinitionProvider);
- if (constraintViolation.isPresent()) {
- childNode.messages.add(new ValidationMessage(severity,
- String.format(
- isImplicit ? MESSAGE_CHILD_NODE_OF_NOT_CONTAINED_PARENT_POTENTIALLY_NOT_ALLOWED
- : MESSAGE_CHILD_NODE_NOT_ALLOWED,
- nodeName, primaryType,
- getEffectiveNodeTypeLabel(nameResolver, effectiveNodeType),
- constraintViolation.get()),
- nodeContext));
-
- }
+ itemDefinitionProvider, false, nodeContext, nodeName, types.toArray(new Name[0]));
+ // defer validation
return childNode;
}
@@ -279,7 +265,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
private @NotNull JcrNodeTypeMetaDataImpl addChildNode(@NotNull NameResolver nameResolver,
@NotNull EffectiveNodeTypeProvider effectiveNodeTypeProvider,
@NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider,
- boolean isImplicit, @NotNull String name, @Nullable Name... nodeTypes)
+ boolean isImplicit, @NotNull NodeContext context, @NotNull String name, @Nullable Name... nodeTypes)
throws ConstraintViolationException, NoSuchNodeTypeException, NamespaceExceptionInNodeName, NamespaceException,
IllegalNameException {
@@ -301,7 +287,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
if (!isAuthenticationOrAuthorizationContext) {
isAuthenticationOrAuthorizationContext = this.isAuthenticationOrAuthorizationContext;
}
- JcrNodeTypeMetaDataImpl newNode = new JcrNodeTypeMetaDataImpl(this.isIncremental, qName, newPrimaryNodeType, newEffectiveNodeType, this,
+ JcrNodeTypeMetaDataImpl newNode = new JcrNodeTypeMetaDataImpl(this.isIncremental, context, qName, newPrimaryNodeType, newEffectiveNodeType, this,
isAuthenticationOrAuthorizationContext, isImplicit);
childNodesByName.put(qName, newNode);
return newNode;
@@ -348,15 +334,15 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
}
@Override
- public @NotNull Collection<ValidationMessage> finalizeValidation(@NotNull NamePathResolver namePathResolver,
+ public @NotNull Collection<ValidationMessage> finalizeValidation(@NotNull NamePathResolver namePathResolver, @NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider,
@NotNull ValidationMessageSeverity severity, @NotNull WorkspaceFilter filter) throws NamespaceException {
if (!isValidationDone) {
Collection<ValidationMessage> messages = new LinkedList<>();
// in incremental validations ignore missing mandatory properties and child nodes (as they might not be visible to the validator)
if (!isIncremental) {
messages.add(new ValidationMessage(ValidationMessageSeverity.DEBUG,
- "Validate mandatory children and properties of " + getQualifiedPath(namePathResolver)));
- messages.addAll(validateMandatoryChildNodes(namePathResolver, severity, filter));
+ "Validate children and mandatory properties of " + getQualifiedPath(namePathResolver)));
+ messages.addAll(validateChildNodes(namePathResolver, nodeTypeDefinitionProvider, itemDefinitionProvider, severity, filter));
messages.addAll(validateMandatoryProperties(namePathResolver, severity));
}
// only remove child nodes on 2nd level to be able to validate mandatory properties of parent
@@ -371,14 +357,36 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
}
}
- private Collection<ValidationMessage> validateMandatoryChildNodes(@NotNull NamePathResolver namePathResolver,
+ private Collection<ValidationMessage> validateChildNodes(@NotNull NamePathResolver namePathResolver, @NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider,
@NotNull ValidationMessageSeverity severity, @NotNull WorkspaceFilter filter) {
if (effectiveNodeType == null) {
return Collections.emptyList();
}
- // validate mandatory child nodes of children
Collection<ValidationMessage> messages = new LinkedList<>();
+ // validate child nodes against parent node type definition
+ for (JcrNodeTypeMetaDataImpl childNode : childNodesByName.values()) {
+ Optional<String> constraintViolation;
+ try {
+ constraintViolation = childNode.validateAgainstParentNodeType(effectiveNodeType, nodeTypeDefinitionProvider,
+ itemDefinitionProvider);
+ if (constraintViolation.isPresent()) {
+ messages.add(new ValidationMessage(severity,
+ String.format(
+ isImplicit ? MESSAGE_CHILD_NODE_OF_NOT_CONTAINED_PARENT_POTENTIALLY_NOT_ALLOWED
+ : MESSAGE_CHILD_NODE_NOT_ALLOWED,
+ namePathResolver.getJCRName(childNode.name), namePathResolver.getJCRName(childNode.primaryNodeType),
+ getEffectiveNodeTypeLabel(namePathResolver, effectiveNodeType),
+ constraintViolation.get()), childNode.context));
+
+ }
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Could not validate child node " + childNode.name + " against parent node definition", e);
+ }
+
+ }
+
+ // validate mandatory child nodes of children
for (QNodeDefinition mandatoryNodeType : effectiveNodeType.getMandatoryQNodeDefinitions()) {
// skip auto created ones
if (mandatoryNodeType.isAutoCreated()) {
@@ -398,9 +406,10 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
getNodeDefinitionLabel(namePathResolver, mandatoryNodeType),
getEffectiveNodeTypeLabel(namePathResolver, effectiveNodeType), getQualifiedPath(namePathResolver))));
} else {
- messages.add(new ValidationMessage(severity, String.format(MESSAGE_MANDATORY_UNCONTAINED_CHILD_NODE_MISSING,
+ // if mandatory child nodes are missing outside filter rules, this is not an issue
+ messages.add(new ValidationMessage(ValidationMessageSeverity.DEBUG, String.format(MESSAGE_MANDATORY_UNCONTAINED_CHILD_NODE_MISSING,
getNodeDefinitionLabel(namePathResolver, mandatoryNodeType),
- getEffectiveNodeTypeLabel(namePathResolver, effectiveNodeType), getQualifiedPath(namePathResolver))));
+ getEffectiveNodeTypeLabel(namePathResolver, effectiveNodeType), getQualifiedPath(namePathResolver)), context));
}
} catch (NamespaceException | MalformedPathException e) {
throw new IllegalStateException("Could not give out node types and name for " + mandatoryNodeType, e);
@@ -436,16 +445,16 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
}
@Override
- public @NotNull JcrNodeTypeMetaData getOrCreateNode(NamePathResolver nameResolver, String path) throws RepositoryException {
- return getNode(nameResolver, path, true).get();
+ public @NotNull JcrNodeTypeMetaData getOrCreateNode(NamePathResolver nameResolver, @NotNull NodeContext nodeContext, String path) throws RepositoryException {
+ return getNode(nameResolver, nodeContext, path, true).get();
}
@Override
public Optional<JcrNodeTypeMetaData> getNode(NamePathResolver nameResolver, String path) throws RepositoryException {
- return getNode(nameResolver, path, false);
+ return getNode(nameResolver, null, path, false);
}
- private Optional<JcrNodeTypeMetaData> getNode(NamePathResolver nameResolver, String path, boolean shouldCreateIfMissing)
+ private Optional<JcrNodeTypeMetaData> getNode(NamePathResolver nameResolver, @Nullable NodeContext nodeContext, String path, boolean shouldCreateIfMissing)
throws RepositoryException {
// convert to fully namespaced path
Path qPath = nameResolver.getQPath(path);
@@ -473,7 +482,10 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
JcrNodeTypeMetaDataImpl childNode = currentNode.childNodesByName.get(element.getName());
if (childNode == null) {
if (shouldCreateIfMissing) {
- childNode = currentNode.addUnknownChildNode(element.getName());
+ if (nodeContext == null) {
+ throw new IllegalArgumentException("Node context must be given in case node is created but is null");
+ }
+ childNode = currentNode.addUnknownChildNode(nodeContext, element.getName());
} else {
return Optional.empty();
}
@@ -505,7 +517,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
messages.add(new ValidationMessage(severity,
String.format(MESSAGE_MANDATORY_PROPERTY_MISSING,
nameResolver.getJCRName(mandatoryPropertyDefinition.getName()),
- getEffectiveNodeTypeLabel(nameResolver, effectiveNodeType), getQualifiedPath(nameResolver))));
+ getEffectiveNodeTypeLabel(nameResolver, effectiveNodeType), getQualifiedPath(nameResolver)), context));
} else {
// check type
int actualPropertyType = propertyTypesByName.get(mandatoryPropertyDefinition.getName());
@@ -516,7 +528,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
nameResolver.getJCRName(mandatoryPropertyDefinition.getName()),
PropertyType.nameFromValue(actualPropertyType),
PropertyType.nameFromValue(mandatoryPropertyDefinition.getRequiredType()),
- getEffectiveNodeTypeLabel(nameResolver, effectiveNodeType), getQualifiedPath(nameResolver))));
+ getEffectiveNodeTypeLabel(nameResolver, effectiveNodeType), getQualifiedPath(nameResolver)), context));
}
}
} catch (NamespaceException e) {
@@ -528,10 +540,11 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
}
@Override
- public void addProperty(@NotNull NodeContext nodeContext, @NotNull NamePathResolver namePathResolver,
+ public Collection<ValidationMessage> addProperty(@NotNull NodeContext nodeContext, @NotNull NamePathResolver namePathResolver,
@NotNull EffectiveNodeTypeProvider effectiveNodeTypeProvider,
@NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider,
@NotNull ValidationMessageSeverity severity, String name, boolean isMultiValue, Value... values) throws RepositoryException {
+ Collection<ValidationMessage> messages = new ArrayList<>();
// some sanity checks on multivalue
if (!isMultiValue && values.length > 1) {
throw new IllegalArgumentException("isMultiValue is only supposed to be false if exactly one value is passed but "
@@ -540,7 +553,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
if (values.length == 0) {
// unable to proceed when no value is present
- return;
+ return messages;
}
Name qName;
@@ -565,6 +578,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
constraintViolation.get()),
nodeContext));
}
+ return messages;
}
private @NotNull Optional<String> validatePropertyConstraints(@NotNull NamePathResolver namePathResolver,
@@ -631,7 +645,25 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
public static @NotNull JcrNodeTypeMetaDataImpl createRoot(boolean isIncremental, @NotNull EffectiveNodeTypeProvider effectiveNodeTypeProvider)
throws ConstraintViolationException, NoSuchNodeTypeException {
- return new JcrNodeTypeMetaDataImpl(isIncremental, NameConstants.ROOT, NameConstants.REP_ROOT, effectiveNodeTypeProvider.getEffectiveNodeType(
+ return new JcrNodeTypeMetaDataImpl(isIncremental, new NodeContext() {
+
+ @Override
+ public @NotNull String getNodePath() {
+ return null;
+ }
+
+ @Override
+ @NotNull
+ public java.nio.file.@NotNull Path getFilePath() {
+ return null;
+ }
+
+ @Override
+ public java.nio.file.@NotNull Path getBasePath() {
+ return null;
+ }
+
+ }, NameConstants.ROOT, NameConstants.REP_ROOT, effectiveNodeTypeProvider.getEffectiveNodeType(
new Name[] {
NameConstants.REP_ROOT,
NameConstants.REP_ACCESS_CONTROLLABLE,
@@ -639,12 +671,6 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
null, false, false);
}
- @Override
- public void fetchAndClearValidationMessages(Collection<ValidationMessage> messages) {
- messages.addAll(this.messages);
- this.messages.clear();
- }
-
private Path getPath() {
if (parentNode == null) {
return PathFactoryImpl.getInstance().getRootPath();
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidator.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidator.java
index 2bacdcf..4add3c5 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidator.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidator.java
@@ -121,7 +121,7 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
}
}
Collection<ValidationMessage> messages = new LinkedList<>();
- messages.addAll(getOrCreateNewNode(nodeContext, isImplicit(nodeContext.getNodePath()), node.primary, node.mixins));
+ messages.addAll(getOrCreateNewNode(nodeContext, false, isImplicit(nodeContext.getNodePath()), node.primary, node.mixins));
for (DocViewProperty property : node.props.values()) {
try {
@@ -131,8 +131,6 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
String.format(MESSAGE_INVALID_PROPERTY_VALUE, property.name, e.getLocalizedMessage())));
}
}
- // emit messages
- currentNodeTypeMetaData.fetchAndClearValidationMessages(messages);
// defer checking for missing mandatory properties (as those might be added by some other files)
return messages;
@@ -145,9 +143,9 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
private Collection<ValidationMessage> addProperty(NodeContext nodeContext, String propertyName, boolean isMultiValue, Value... values) {
Collection<ValidationMessage> messages = new ArrayList<>();
try {
- currentNodeTypeMetaData.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
+ messages.addAll(currentNodeTypeMetaData.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
- ntManagerProvider.getItemDefinitionProvider(), defaultSeverity, propertyName, isMultiValue, values);
+ ntManagerProvider.getItemDefinitionProvider(), defaultSeverity, propertyName, isMultiValue, values));
} catch (NoSuchNodeTypeException | NamespaceException e) {
// log each unknown node type/namespace only once!
if (!loggedUnknownNodeTypeMessages.contains(e.getMessage())) {
@@ -171,7 +169,7 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
}
}
- private @NotNull Collection<ValidationMessage> getOrCreateNewNode(NodeContext nodeContext, boolean isImplicit, String primaryType,
+ private @NotNull Collection<ValidationMessage> getOrCreateNewNode(NodeContext nodeContext, boolean isFolder, boolean isImplicit, String primaryType,
String... mixinTypes) {
Optional<JcrNodeTypeMetaData> node = getNode(nodeContext.getNodePath());
if (node.isPresent()) {
@@ -193,11 +191,11 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
}
return Collections.emptyList();
} else {
- return createNewNode(nodeContext, isImplicit, primaryType, mixinTypes);
+ return createNewNode(nodeContext, isFolder, isImplicit, primaryType, mixinTypes);
}
}
- private @NotNull Collection<ValidationMessage> createNewNode(NodeContext nodeContext, boolean isImplicit, String primaryType,
+ private @NotNull Collection<ValidationMessage> createNewNode(NodeContext nodeContext, boolean isFolder, boolean isImplicit, String primaryType,
String... mixinTypes) {
Collection<ValidationMessage> messages = new ArrayList<>();
String nodePath = nodeContext.getNodePath();
@@ -209,7 +207,7 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
try {
//
JcrNodeTypeMetaData parentNode = currentNodeTypeMetaData.getOrCreateNode(ntManagerProvider.getNamePathResolver(),
- parentNodePath);
+ nodeContext, parentNodePath);
try {
if (isImplicit) {
if (!nodePath.equals("/")) {
@@ -224,6 +222,7 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
currentNodeTypeMetaData = parentNode.addChildNode(ntManagerProvider.getNameResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), defaultSeverity, nodeContext, primaryType, mixinTypes);
+
}
} catch (NoSuchNodeTypeException | NamespaceException e) {
// TODO: NoSuchNodeTypeException might be thrown due to previous registration of the namespace for a node name
@@ -238,9 +237,9 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
// now register namespace with an arbitrary namespace url
NameParser.parse(nodeName, new OnDemandRegisterNamespaceResolverWrapper(ntManagerProvider),
NameFactoryImpl.getInstance());
- messages.addAll(createNewNode(nodeContext, isImplicit, primaryType, mixinTypes));
+ messages.addAll(createNewNode(nodeContext, isFolder, isImplicit, primaryType, mixinTypes));
} else {
- currentNodeTypeMetaData = parentNode.addUnknownChildNode(ntManagerProvider.getNameResolver(), nodeName);
+ currentNodeTypeMetaData = parentNode.addUnknownChildNode(ntManagerProvider.getNameResolver(),nodeContext, nodeName);
}
}
} catch (RepositoryException e) {
@@ -285,9 +284,11 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
private @Nullable Collection<ValidationMessage> finalizeValidationForSubtree(JcrNodeTypeMetaData node, NodeContext nodeContext) throws NamespaceException {
Collection<ValidationMessage> messages = new ArrayList<>();
+ messages.add(new ValidationMessage(ValidationMessageSeverity.DEBUG, "Finalize validation for subtree at " + nodeContext));
for (JcrNodeTypeMetaData child : node.getChildren()) {
messages.addAll(finalizeValidationForSubtree(child, nodeContext));
- messages.addAll(child.finalizeValidation(ntManagerProvider.getNamePathResolver(), defaultSeverity, filter));
+ messages.addAll(child.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+ ntManagerProvider.getItemDefinitionProvider(), defaultSeverity, filter));
}
return messages;
}
@@ -299,7 +300,7 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
List<ValidationMessage> messages = new ArrayList<>();
boolean isImplicit = isImplicit(nodeContext.getNodePath());
if (isFolder) {
- messages.addAll(getOrCreateNewNode(nodeContext, isImplicit, JcrConstants.NT_FOLDER));
+ messages.addAll(getOrCreateNewNode(nodeContext, isFolder, isImplicit, JcrConstants.NT_FOLDER));
//
if (!nodeContext.getNodePath().equals("/")) {
messages.addAll(finalizeValidationForSiblings(nodeContext));
@@ -311,19 +312,19 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
// https://jackrabbit.apache.org/filevault/vaultfs.html#Binary_Properties
if (fileName.endsWith(ValidationExecutor.EXTENSION_BINARY)) {
// create parent if it does not exist yet
- messages.addAll(getOrCreateNewNode(nodeContext, isImplicit, JcrConstants.NT_FOLDER));
+ messages.addAll(getOrCreateNewNode(nodeContext, isFolder, isImplicit, JcrConstants.NT_FOLDER));
String propertyName = fileName.substring(0, fileName.length() - ValidationExecutor.EXTENSION_BINARY.length());
messages.addAll(addProperty(nodeContext, propertyName, false, DUMMY_BINARY_VALUE));
} else {
// if binary node is not yet there
- messages.addAll(getOrCreateNewNode(nodeContext, isImplicit, JcrConstants.NT_FILE));
+ messages.addAll(getOrCreateNewNode(nodeContext, isFolder, isImplicit, JcrConstants.NT_FILE));
// if a NT_FILE create a jcr:content sub node of type NT_RESOURCE
if (currentNodeTypeMetaData.getPrimaryNodeType().equals(NameConstants.NT_FILE)) {
// create new node context
nodeContext = new NodeContextImpl(nodeContext.getNodePath() + "/" + JcrConstants.JCR_CONTENT,
nodeContext.getFilePath(), nodeContext.getBasePath());
messages.addAll(
- getOrCreateNewNode(nodeContext, isImplicit(nodeContext.getNodePath()), JcrConstants.NT_RESOURCE));
+ getOrCreateNewNode(nodeContext, isFolder, isImplicit(nodeContext.getNodePath()), JcrConstants.NT_RESOURCE));
}
messages.addAll(addProperty(nodeContext, JcrConstants.JCR_DATA, false, DUMMY_BINARY_VALUE));
messages.addAll(addProperty(nodeContext, JcrConstants.JCR_MIMETYPE, false, DUMMY_STRING_VALUE));
diff --git a/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImplTest.java b/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImplTest.java
index f69d870..0eef044 100644
--- a/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImplTest.java
+++ b/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImplTest.java
@@ -22,7 +22,6 @@ import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
-import java.util.ArrayList;
import java.util.Collection;
import javax.jcr.NamespaceException;
@@ -48,7 +47,6 @@ import org.apache.jackrabbit.vault.validation.spi.ValidationMessage;
import org.apache.jackrabbit.vault.validation.spi.ValidationMessageSeverity;
import org.apache.jackrabbit.vault.validation.spi.util.NodeContextImpl;
import org.hamcrest.MatcherAssert;
-import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -79,19 +77,16 @@ public class JcrNodeTypeMetaDataImplTest {
ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(), severity,
createSimpleNodeContext("my"),
NodeType.NT_FOLDER);
- assertNoValidationErrors(child);
JcrNodeTypeMetaData grandChild = child.addChildNode(ntManagerProvider.getNameResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(),
ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(), severity,
createSimpleNodeContext("test"),
NodeType.NT_FOLDER);
- assertNoValidationErrors(grandChild);
JcrNodeTypeMetaData child2 = root.addChildNode(ntManagerProvider.getNameResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(),
ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(), severity,
createSimpleNodeContext("test2"),
NodeType.NT_FOLDER);
- assertNoValidationErrors(child2);
Assert.assertEquals(child2,
grandChild.getNode(ntManagerProvider.getNamePathResolver(), "/test2").get());
}
@@ -142,81 +137,87 @@ public class JcrNodeTypeMetaDataImplTest {
StandardCharsets.US_ASCII)) {
ntManagerProvider.registerNodeTypes(reader);
}
-
- // add child node with mixin type as primary
+ DefaultWorkspaceFilter filter = new DefaultWorkspaceFilter();
+
+ // add node with mixin type as primary
NodeContext nodeContext = createSimpleNodeContext("name");
+
JcrNodeTypeMetaData node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, nodeContext,
"mix:mimeType");
- assertValidationMessage(node, new ValidationMessage(ValidationMessageSeverity.ERROR,
+ ValidationExecutorTest.assertViolation(root.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+ ntManagerProvider.getItemDefinitionProvider(),
+ ValidationMessageSeverity.ERROR, filter),
+ new ValidationMessage(ValidationMessageSeverity.ERROR,
String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "name", "mix:mimeType", ROOT_NODE_TYPES,
- JcrNodeTypeMetaDataImpl.CONSTRAINT_MIXIN_TYPE_AS_PRIMARY_TYPE),
- nodeContext));
+ JcrNodeTypeMetaDataImpl.CONSTRAINT_MIXIN_TYPE_AS_PRIMARY_TYPE), nodeContext));
- // add child node with abstract type
+ // add node with abstract type
+ root = JcrNodeTypeMetaDataImpl.createRoot(false, ntManagerProvider.getEffectiveNodeTypeProvider());
node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, nodeContext,
"nt:hierarchyNode");
- assertValidationMessage(node, new ValidationMessage(ValidationMessageSeverity.ERROR,
+ ValidationExecutorTest.assertViolation(root.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+ ntManagerProvider.getItemDefinitionProvider(),
+ ValidationMessageSeverity.ERROR, filter),
+ new ValidationMessage(ValidationMessageSeverity.ERROR,
String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "name", "nt:hierarchyNode", ROOT_NODE_TYPES,
- JcrNodeTypeMetaDataImpl.CONSTRAINT_ABSTRACT_TYPE_AS_PRIMARY_TYPE),
- nodeContext));
+ JcrNodeTypeMetaDataImpl.CONSTRAINT_ABSTRACT_TYPE_AS_PRIMARY_TYPE), nodeContext));
+ // add node for version storage
+ root = JcrNodeTypeMetaDataImpl.createRoot(false, ntManagerProvider.getEffectiveNodeTypeProvider());
node = root.addChildNode(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
ValidationMessageSeverity.ERROR,
createSimpleNodeContext("versionedNode"), "rep:versionStorage");
- assertNoValidationErrors(node);
-
// add child node with protected node which is ACL (i.e. accepted)
- JcrNodeTypeMetaData childNode = node.addChildNode(ntManagerProvider.getNamePathResolver(),
+ node.addChildNode(ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(),
ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
ValidationMessageSeverity.ERROR,
createSimpleNodeContext("rep:policy"), "rep:Policy");
- assertNoValidationErrors(childNode);
-
- // add child node with protected node which is not ACL (i.e. accepted)
- childNode = node.addChildNode(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
+ // add child node with protected node which is not ACL (i.e. not accepted)
+ root = JcrNodeTypeMetaDataImpl.createRoot(false, ntManagerProvider.getEffectiveNodeTypeProvider());
+ node.addChildNode(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
ValidationMessageSeverity.ERROR,
nodeContext, "nt:versionHistory");
- assertValidationMessage(childNode, new ValidationMessage(ValidationMessageSeverity.ERROR,
+ ValidationExecutorTest.assertViolation(node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+ ntManagerProvider.getItemDefinitionProvider(),
+ ValidationMessageSeverity.ERROR, filter), new ValidationMessage(ValidationMessageSeverity.ERROR,
String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "name", "nt:versionHistory", "rep:versionStorage",
- JcrNodeTypeMetaDataImpl.CONSTRAINT_CHILD_NODE_PROTECTED),
- nodeContext));
+ JcrNodeTypeMetaDataImpl.CONSTRAINT_CHILD_NODE_PROTECTED), nodeContext));
// add valid child node
+ root = JcrNodeTypeMetaDataImpl.createRoot(false, ntManagerProvider.getEffectiveNodeTypeProvider());
node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("name"),
"my:nodeType1");
- assertNoValidationErrors(node);
-
- // add auto-created child node
+ // below that add auto-created child node
nodeContext = createSimpleNodeContext("my:autoCreatedChild1");
- childNode = node.addChildNode(ntManagerProvider.getNamePathResolver(),
+ node.addChildNode(ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR,
nodeContext, "my:nodeType2");
- assertValidationMessage(childNode, new ValidationMessage(ValidationMessageSeverity.ERROR,
- String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "my:autoCreatedChild1", "my:nodeType2",
- "my:nodeType1",
- JcrNodeTypeMetaDataImpl.CONSTRAINT_CHILD_NODE_AUTO_CREATED),
- nodeContext));
-
- // below that add child node which is not allowed
- nodeContext = createSimpleNodeContext("name2");
- childNode = node.addChildNode(ntManagerProvider.getNamePathResolver(),
+ // and next to it a child node which is not allowed
+ NodeContext nodeContext2 = createSimpleNodeContext("name2");
+ node.addChildNode(ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
- ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, nodeContext,
+ ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, nodeContext2,
"my:nodeType1");
- assertValidationMessage(childNode, new ValidationMessage(ValidationMessageSeverity.ERROR,
+ ValidationExecutorTest.assertViolation(node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+ ntManagerProvider.getItemDefinitionProvider(),
+ ValidationMessageSeverity.ERROR, filter),
+ new ValidationMessage(ValidationMessageSeverity.ERROR,
+ String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "my:autoCreatedChild1", "my:nodeType2",
+ "my:nodeType1",
+ JcrNodeTypeMetaDataImpl.CONSTRAINT_CHILD_NODE_AUTO_CREATED), nodeContext),
+ new ValidationMessage(ValidationMessageSeverity.ERROR,
String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "name2", "my:nodeType1", "my:nodeType1",
- JcrNodeTypeMetaDataImpl.CONSTRAINT_CHILD_NODE_NOT_ALLOWED),
- nodeContext));
+ JcrNodeTypeMetaDataImpl.CONSTRAINT_CHILD_NODE_NOT_ALLOWED), nodeContext2));
}
@Test
@@ -232,16 +233,14 @@ public class JcrNodeTypeMetaDataImplTest {
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("name"),
"my:nodeType1");
- assertNoValidationErrors(node);
DefaultWorkspaceFilter filter = new DefaultWorkspaceFilter();
// mandatory child node missing outside filter
- Collection<ValidationMessage> messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(),
+ Collection<ValidationMessage> messages = root.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+ ntManagerProvider.getItemDefinitionProvider(),
ValidationMessageSeverity.ERROR, filter);
- ValidationExecutorTest.assertViolation(messages, new ValidationMessage(ValidationMessageSeverity.ERROR,
- String.format(JcrNodeTypeMetaDataImpl.MESSAGE_MANDATORY_UNCONTAINED_CHILD_NODE_MISSING, "my:namedChild1 [my:nodeType1]", "my:nodeType1",
- "/name")));
+ MatcherAssert.assertThat(messages, AnyValidationMessageMatcher.noValidationInCollection());
node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
@@ -250,13 +249,15 @@ public class JcrNodeTypeMetaDataImplTest {
// mandatory child node missing inside filter
filter.add(new PathFilterSet("/"));
- messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ValidationMessageSeverity.ERROR, filter);
+ messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+ ntManagerProvider.getItemDefinitionProvider(),ValidationMessageSeverity.ERROR, filter);
ValidationExecutorTest.assertViolation(messages, new ValidationMessage(ValidationMessageSeverity.ERROR,
String.format(JcrNodeTypeMetaDataImpl.MESSAGE_MANDATORY_CHILD_NODE_MISSING, "my:namedChild1 [my:nodeType1]", "my:nodeType1",
"/name2")));
// calling a second time will not lead to anything
- messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ValidationMessageSeverity.ERROR, filter);
+ messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+ ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, filter);
MatcherAssert.assertThat(messages, AnyValidationMessageMatcher.noValidationInCollection());
// now add mandatory child node
@@ -269,40 +270,40 @@ public class JcrNodeTypeMetaDataImplTest {
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("my:namedChild1"),
"my:nodeType1");
- messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ValidationMessageSeverity.ERROR,
+ messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+ ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR,
new DefaultWorkspaceFilter());
MatcherAssert.assertThat(messages, AnyValidationMessageMatcher.noValidationInCollection());
// add arbitrary property to root
- root.addProperty(createSimpleNodeContext("/"), ntManagerProvider.getNamePathResolver(),
+ MatcherAssert.assertThat(root.addProperty(createSimpleNodeContext("/"), ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, "property", false,
- ValueFactoryImpl.getInstance().createValue("foo"));
- assertNoValidationErrors(root);
-
+ ValueFactoryImpl.getInstance().createValue("foo")), AnyValidationMessageMatcher.noValidationInCollection());
+
NodeContext nodeContext = createSimpleNodeContext("nodeForMandatoryProperties");
node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, nodeContext, "my:nodeType2");
- assertNoValidationErrors(node);
- messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ValidationMessageSeverity.ERROR, filter);
+ messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+ ntManagerProvider.getItemDefinitionProvider(),ValidationMessageSeverity.ERROR, filter);
ValidationExecutorTest.assertViolation(messages, new ValidationMessage(ValidationMessageSeverity.ERROR,
String.format(JcrNodeTypeMetaDataImpl.MESSAGE_MANDATORY_PROPERTY_MISSING, "my:mandatoryProperty", "my:nodeType2",
- "/nodeForMandatoryProperties")));
+ "/nodeForMandatoryProperties"), nodeContext));
nodeContext = createSimpleNodeContext("nodeForMandatoryProperties2");
node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, nodeContext, "my:nodeType2");
- assertNoValidationErrors(node);
node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
ValidationMessageSeverity.ERROR,
"my:mandatoryProperty", false, ValueFactoryImpl.getInstance().createValue("foo"));
- messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ValidationMessageSeverity.ERROR, filter);
+ messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+ ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, filter);
ValidationExecutorTest.assertViolation(messages, new ValidationMessage(ValidationMessageSeverity.ERROR,
String.format(JcrNodeTypeMetaDataImpl.MESSAGE_MANDATORY_PROPERTY_WITH_WRONG_TYPE, "my:mandatoryProperty", "String", "Date",
- "my:nodeType2", "/nodeForMandatoryProperties2")));
+ "my:nodeType2"), nodeContext));
}
@Test
@@ -318,7 +319,6 @@ public class JcrNodeTypeMetaDataImplTest {
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("name"),
"my:nodeType1");
- assertNoValidationErrors(node);
DefaultWorkspaceFilter filter = new DefaultWorkspaceFilter();
@@ -329,7 +329,8 @@ public class JcrNodeTypeMetaDataImplTest {
// mandatory child node missing but not reported due to incremental validation
filter.add(new PathFilterSet("/"));
- Collection<ValidationMessage> messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ValidationMessageSeverity.ERROR, filter);
+ Collection<ValidationMessage> messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+ ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, filter);
MatcherAssert.assertThat(messages, AnyValidationMessageMatcher.noValidationInCollection());
// mandatory property missing but not reported due to incremental validation
@@ -337,8 +338,8 @@ public class JcrNodeTypeMetaDataImplTest {
node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, nodeContext, "my:nodeType2");
- assertNoValidationErrors(node);
- messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ValidationMessageSeverity.ERROR, filter);
+ messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+ ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, filter);
MatcherAssert.assertThat(messages, AnyValidationMessageMatcher.noValidationInCollection());
}
@@ -361,72 +362,65 @@ public class JcrNodeTypeMetaDataImplTest {
NodeContext nodeContext = createSimpleNodeContext("/");
// add arbitrary property to root
- root.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
+ MatcherAssert.assertThat(root.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, "property", false,
- ValueFactoryImpl.getInstance().createValue("foo"));
- assertNoValidationErrors(root);
+ ValueFactoryImpl.getInstance().createValue("foo")), AnyValidationMessageMatcher.noValidationInCollection());
JcrNodeTypeMetaData node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("child"),
"my:nodeType3");
- assertNoValidationErrors(node);
// not allowed (wrong type)
- node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
+ ValidationExecutorTest.assertViolation( node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, "property", false,
- ValueFactoryImpl.getInstance().createValue("foo"));
- assertValidationMessage(node,
+ ValueFactoryImpl.getInstance().createValue("foo")),
new ValidationMessage(ValidationMessageSeverity.ERROR,
String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED, "property",
"String", "my:nodeType3", JcrNodeTypeMetaDataImpl.CONSTRAINT_PROPERTY_NOT_ALLOWED),
nodeContext));
// protected but nevertheless allowed
- node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
+ MatcherAssert.assertThat(node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, "jcr:primaryType", false,
- ValueFactoryImpl.getInstance().createValue("foo"));
- assertNoValidationErrors(node);
+ ValueFactoryImpl.getInstance().createValue("foo")), AnyValidationMessageMatcher.noValidationInCollection());
// protected
- node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
+ ValidationExecutorTest.assertViolation(node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
ValidationMessageSeverity.ERROR,
- "my:protected", false, ValueFactoryImpl.getInstance().createValue("foo"));
- assertValidationMessage(node,
+ "my:protected", false, ValueFactoryImpl.getInstance().createValue("foo")),
new ValidationMessage(ValidationMessageSeverity.ERROR, String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED,
"my:protected", "String", "my:nodeType3", JcrNodeTypeMetaDataImpl.CONSTRAINT_PROPERTY_PROTECTED), nodeContext));
// multi value where single value is required
- node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
+ ValidationExecutorTest.assertViolation(node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, "my:property1", true,
- ValueFactoryImpl.getInstance().createValue("foo"), ValueFactoryImpl.getInstance().createValue("bar"));
- assertValidationMessage(node,
+ ValueFactoryImpl.getInstance().createValue("foo"), ValueFactoryImpl.getInstance().createValue("bar")),
new ValidationMessage(ValidationMessageSeverity.ERROR, String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED,
"my:property1", "String", "my:nodeType3", JcrNodeTypeMetaDataImpl.CONSTRAINT_PROPERTY_NOT_ALLOWED), nodeContext));
// constrained property
- node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
+ MatcherAssert.assertThat(node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
ValidationMessageSeverity.ERROR,
- "my:constrainedStringProperty", false, ValueFactoryImpl.getInstance().createValue("prefix1foo"));
- assertNoValidationErrors(root);
+ "my:constrainedStringProperty", false, ValueFactoryImpl.getInstance().createValue("prefix1foo")),
+ AnyValidationMessageMatcher.noValidationInCollection());
- node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
+ MatcherAssert.assertThat(node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
ValidationMessageSeverity.ERROR,
- "my:constrainedStringProperty", false, ValueFactoryImpl.getInstance().createValue("foosuffix1"));
- assertNoValidationErrors(root);
+ "my:constrainedStringProperty", false, ValueFactoryImpl.getInstance().createValue("foosuffix1")),
+ AnyValidationMessageMatcher.noValidationInCollection());
- node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
+ ValidationExecutorTest.assertViolation( node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
ValidationMessageSeverity.ERROR,
- "my:constrainedStringProperty", false, ValueFactoryImpl.getInstance().createValue("foo"));
- assertValidationMessage(node,
+ "my:constrainedStringProperty", false, ValueFactoryImpl.getInstance().createValue("foo")),
new ValidationMessage(ValidationMessageSeverity.ERROR, String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED,
"my:constrainedStringProperty", "String", "my:nodeType3",
String.format(JcrNodeTypeMetaDataImpl.CONSTRAINT_PROPERTY_VALUE,
@@ -434,16 +428,4 @@ public class JcrNodeTypeMetaDataImplTest {
nodeContext));
}
- private static void assertNoValidationErrors(JcrNodeTypeMetaData node) {
- Collection<ValidationMessage> messages = new ArrayList<>();
- node.fetchAndClearValidationMessages(messages);
- MatcherAssert.assertThat(messages, Matchers.empty());
- }
-
- private static void assertValidationMessage(JcrNodeTypeMetaData node, ValidationMessage... expectedMessages) {
- Collection<ValidationMessage> actualMessages = new ArrayList<>();
- node.fetchAndClearValidationMessages(actualMessages);
- MatcherAssert.assertThat(actualMessages, Matchers.contains(expectedMessages));
- }
-
}
diff --git a/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorTest.java b/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorTest.java
index 3790f3c..382649e 100644
--- a/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorTest.java
+++ b/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorTest.java
@@ -48,9 +48,7 @@ import org.apache.jackrabbit.vault.validation.spi.ValidationMessageSeverity;
import org.apache.jackrabbit.vault.validation.spi.util.NodeContextImpl;
import org.apache.jackrabbit.vault.validation.spi.util.classloaderurl.URLFactory;
import org.hamcrest.MatcherAssert;
-import org.junit.Assert;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
public class NodeTypeValidatorTest {
@@ -85,8 +83,7 @@ public class NodeTypeValidatorTest {
}
@Test
- @Ignore
- public void testValidateComplexUnstructuredNodeTypes() throws IOException, RepositoryException, ParseException, ConfigurationException {
+ public void testValidateNotAllowedProperties() throws IOException, RepositoryException, ParseException, ConfigurationException {
NodeContext nodeContext = new NodeContextImpl("/apps/test/node4", Paths.get("node4"), Paths.get(""));
Map<String, DocViewProperty> props = new HashMap<>();
@@ -96,16 +93,16 @@ public class NodeTypeValidatorTest {
new String[] { "nt:unstructured" }, false, PropertyType.STRING));
// no primary type
- DocViewNode node = new DocViewNode("jcr:root", "jcr:root", null, props, null, "sling:Folder");
- Assert.assertNull(validator.validate(node, nodeContext, false));
+ DocViewNode node = new DocViewNode("jcr:root", "jcr:root", null, props, null, "nt:unstructured");
+ MatcherAssert.assertThat(validator.validate(node, nodeContext, false), AnyValidationMessageMatcher.noValidationInCollection());
props.put(NameConstants.JCR_PRIMARYTYPE.toString(),
new DocViewProperty(NameConstants.JCR_PRIMARYTYPE.toString(), new String[] { "value1" }, false, PropertyType.STRING));
node = new DocViewNode("test", "test", null, props, null, "nt:folder");
ValidationExecutorTest.assertViolation(validator.validate(node, nodeContext, false),
new ValidationMessage(ValidationMessageSeverity.ERROR,
- String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED, property, "nt:folder",
- "No property definition found for name!")));
+ String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED, "prop1", "String", "nt:folder",
+ "No applicable property definition found for name and type!"), nodeContext));
}
@Test
@@ -138,15 +135,59 @@ public class NodeTypeValidatorTest {
// nt:unstructured below nt:folder is not allowed
DocViewNode node = new DocViewNode("jcr:root", "jcr:root", null, props, null, JcrConstants.NT_UNSTRUCTURED);
- ValidationExecutorTest.assertViolation(validator.validate(node, nodeContext, false),
+ MatcherAssert.assertThat(validator.validate(node, nodeContext, false), AnyValidationMessageMatcher.noValidationInCollection());
+ ValidationExecutorTest.assertViolation(validator.done(),
new ValidationMessage(ValidationMessageSeverity.ERROR,
String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_OF_NOT_CONTAINED_PARENT_POTENTIALLY_NOT_ALLOWED,
"test", "nt:unstructured", JcrConstants.NT_FOLDER,
"Node type does not allow arbitrary child nodes and does not allow this specific name and node type either!"), nodeContext));
+ }
+
+ // https://issues.apache.org/jira/browse/JCRVLT-527
+ @Test
+ public void testChildFolderBelowTypeNotAllowingNtFolder() {
+ NodeContext nodeContext = new NodeContextImpl("/apps/test", Paths.get("apps","test", ".content.xml"), Paths.get(""));
+ Map<String, DocViewProperty> props = new HashMap<>();
+ props.put(NameConstants.JCR_PRIMARYTYPE.toString(), new DocViewProperty(NameConstants.JCR_PRIMARYTYPE.toString(),
+ new String[] { "rep:AuthorizableFolder" }, false, PropertyType.STRING));
+ DocViewNode node = new DocViewNode("jcr:root", "jcr:root", null, props, null, "rep:AuthorizableFolder");
+
+ MatcherAssert.assertThat(validator.validate(node, nodeContext, true), AnyValidationMessageMatcher.noValidationInCollection());
+
+ // add child as folder first
+ nodeContext = new NodeContextImpl("/apps/test/child", Paths.get("apps", "test", "child"), Paths.get(""));
+ MatcherAssert.assertThat(validator.validateJcrPath(nodeContext, true, false), AnyValidationMessageMatcher.noValidationInCollection());
+
+ // now refine type via .content.xml
+ nodeContext = new NodeContextImpl("/apps/test/child", Paths.get("apps", "test", "child", ".content.xml"), Paths.get(""));
+ props.put(NameConstants.JCR_PRIMARYTYPE.toString(), new DocViewProperty(NameConstants.JCR_PRIMARYTYPE.toString(),
+ new String[] { "rep:SystemUser" }, false, PropertyType.STRING));
+ props.put(NameConstants.REP_PRINCIPAL_NAME.toString(), new DocViewProperty(NameConstants.REP_PRINCIPAL_NAME.toString(),
+ new String[] { "mySystemUser" }, false, PropertyType.STRING));
+ node = new DocViewNode("jcr:root", "jcr:root", null, props, null, "rep:SystemUser");
+
+ MatcherAssert.assertThat(validator.validate(node, nodeContext, true), AnyValidationMessageMatcher.noValidationInCollection());
MatcherAssert.assertThat(validator.done(), AnyValidationMessageMatcher.noValidationInCollection());
}
@Test
+ public void testMissingMandatoryProperty() {
+ // now refine type via .content.xml
+ NodeContext nodeContext = new NodeContextImpl("/apps/test/child", Paths.get("apps", "test", "child", ".content.xml"), Paths.get(""));
+ Map<String, DocViewProperty> props = new HashMap<>();
+ props.put(NameConstants.JCR_PRIMARYTYPE.toString(), new DocViewProperty(NameConstants.JCR_PRIMARYTYPE.toString(),
+ new String[] { "rep:SystemUser" }, false, PropertyType.STRING));
+ DocViewNode node = new DocViewNode("jcr:root", "jcr:root", null, props, null, "rep:SystemUser");
+
+ MatcherAssert.assertThat(validator.validate(node, nodeContext, true), AnyValidationMessageMatcher.noValidationInCollection());
+
+ ValidationExecutorTest.assertViolation(validator.done(),
+ new ValidationMessage(ValidationMessageSeverity.ERROR,
+ String.format(JcrNodeTypeMetaDataImpl.MESSAGE_MANDATORY_PROPERTY_MISSING,
+ "rep:principalName", "rep:SystemUser", nodeContext.getNodePath()), nodeContext));
+ }
+
+ @Test
public void testMissingMandatoryChildNode() {
NodeContext nodeContext = new NodeContextImpl("/apps/test/node4", Paths.get("node4"), Paths.get(""));
@@ -181,7 +222,7 @@ public class NodeTypeValidatorTest {
}
@Test
- public void testPropertyWitInconvertibleValue() {
+ public void testPropertyWithInconvertibleValue() {
NodeContext nodeContext = new NodeContextImpl("/apps/test/node4", Paths.get("node4"), Paths.get(""));
Map<String, DocViewProperty> props = new HashMap<>();