Author: jukka
Date: Fri Mar 28 19:39:26 2014
New Revision: 1582863
URL: http://svn.apache.org/r1582863
Log:
OAK-1640: When modifying node types, revalidate only affected content
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java?rev=1582863&r1=1582862&r2=1582863&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java
Fri Mar 28 19:39:26 2014
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.oak.plugins.nodetype;
import java.util.List;
+import java.util.Set;
import javax.jcr.PropertyType;
import javax.jcr.Value;
@@ -36,6 +37,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.in;
+import static com.google.common.collect.Iterables.any;
import static org.apache.jackrabbit.JcrConstants.JCR_ISMIXIN;
import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
@@ -68,21 +71,30 @@ class TypeEditor extends DefaultEditor {
private final boolean strict;
+ private final Set<String> typesToCheck;
+
+ private final boolean checkThisNode;
+
private final TypeEditor parent;
private final String nodeName;
private final NodeState types;
- private EffectiveType effective;
+ private final EffectiveType effective;
private final NodeBuilder builder;
TypeEditor(
- boolean strict, NodeState types,
+ boolean strict, Set<String> typesToCheck, NodeState types,
String primary, Iterable<String> mixins, NodeBuilder builder)
throws CommitFailedException {
this.strict = strict;
+ this.typesToCheck = typesToCheck;
+ this.checkThisNode =
+ typesToCheck == null
+ || typesToCheck.contains(primary)
+ || any(mixins, in(typesToCheck));
this.parent = null;
this.nodeName = null;
this.types = checkNotNull(types);
@@ -95,6 +107,11 @@ class TypeEditor extends DefaultEditor {
String primary, Iterable<String> mixins, NodeBuilder builder)
throws CommitFailedException {
this.strict = parent.strict;
+ this.typesToCheck = parent.typesToCheck;
+ this.checkThisNode =
+ typesToCheck == null
+ || typesToCheck.contains(primary)
+ || any(mixins, in(typesToCheck));
this.parent = checkNotNull(parent);
this.nodeName = checkNotNull(name);
this.types = parent.types;
@@ -108,6 +125,8 @@ class TypeEditor extends DefaultEditor {
*/
TypeEditor(EffectiveType effective) {
this.strict = true;
+ this.typesToCheck = null;
+ this.checkThisNode = true;
this.parent = null;
this.nodeName = null;
this.types = EMPTY_NODE;
@@ -156,20 +175,22 @@ class TypeEditor extends DefaultEditor {
@Override
public void propertyChanged(PropertyState before, PropertyState after)
throws CommitFailedException {
- NodeState definition = effective.getDefinition(after);
- if (definition == null) {
- constraintViolation(
- 4, "No matching property definition found for " + after);
- } else if (JCR_UUID.equals(after.getName())
- && effective.isNodeType(MIX_REFERENCEABLE)) {
- // special handling for the jcr:uuid property of mix:referenceable
- // TODO: this should be done in a pluggable extension
- if (!isValidUUID(after.getValue(Type.STRING))) {
+ if (checkThisNode) {
+ NodeState definition = effective.getDefinition(after);
+ if (definition == null) {
constraintViolation(
- 12, "Invalid UUID value in the jcr:uuid property");
+ 4, "No matching property definition found for " +
after);
+ } else if (JCR_UUID.equals(after.getName())
+ && effective.isNodeType(MIX_REFERENCEABLE)) {
+ // special handling for the jcr:uuid property of
mix:referenceable
+ // TODO: this should be done in a pluggable extension
+ if (!isValidUUID(after.getValue(Type.STRING))) {
+ constraintViolation(
+ 12, "Invalid UUID value in the jcr:uuid property");
+ }
+ } else {
+ checkValueConstraints(definition, after);
}
- } else {
- checkValueConstraints(definition, after);
}
}
@@ -177,7 +198,7 @@ class TypeEditor extends DefaultEditor {
public void propertyDeleted(PropertyState before)
throws CommitFailedException {
String name = before.getName();
- if (effective.isMandatoryProperty(name)) {
+ if (checkThisNode && effective.isMandatoryProperty(name)) {
constraintViolation(
22, "Mandatory property " + name + " can not be removed");
}
@@ -188,21 +209,23 @@ class TypeEditor extends DefaultEditor {
throws CommitFailedException {
TypeEditor editor = childNodeChanged(name, MISSING_NODE, after);
- // TODO: add any auto-created items that are still missing
+ if (editor.checkThisNode) {
+ // TODO: add any auto-created items that are still missing
- // verify the presence of all mandatory items
- for (String property : editor.effective.getMandatoryProperties()) {
- if (!after.hasProperty(property)) {
- editor.constraintViolation(
- 21, "Mandatory property " + property
- + " not found in a new node");
+ // verify the presence of all mandatory items
+ for (String property : editor.effective.getMandatoryProperties()) {
+ if (!after.hasProperty(property)) {
+ editor.constraintViolation(
+ 21, "Mandatory property " + property
+ + " not found in a new node");
+ }
}
- }
- for (String child : editor.effective.getMandatoryChildNodes()) {
- if (!after.hasChildNode(child)) {
- editor.constraintViolation(
- 25, "Mandatory child node " + child
- + " not found in a new node");
+ for (String child : editor.effective.getMandatoryChildNodes()) {
+ if (!after.hasChildNode(child)) {
+ editor.constraintViolation(
+ 25, "Mandatory child node " + child
+ + " not found in a new node");
+ }
}
}
@@ -217,7 +240,7 @@ class TypeEditor extends DefaultEditor {
Iterable<String> mixins = after.getNames(JCR_MIXINTYPES);
NodeBuilder childBuilder = builder.getChildNode(name);
- if (primary == null) {
+ if (primary == null && effective != null) {
// no primary type defined, find and apply a default type
primary = effective.getDefaultType(name);
if (primary != null) {
@@ -231,19 +254,19 @@ class TypeEditor extends DefaultEditor {
TypeEditor editor =
new TypeEditor(this, name, primary, mixins, childBuilder);
- if (!effective.isValidChildNode(name, editor.effective)) {
+ if (checkThisNode
+ && !effective.isValidChildNode(name, editor.effective)) {
constraintViolation(
1, "No matching definition found for child node " + name
+ " with effective type " + editor.effective);
}
-
return editor;
}
@Override
public Editor childNodeDeleted(String name, NodeState before)
throws CommitFailedException {
- if (effective.isMandatoryChildNode(name)) {
+ if (checkThisNode && effective.isMandatoryChildNode(name)) {
constraintViolation(
26, "Mandatory child node " + name + " can not be
removed");
}
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java?rev=1582863&r1=1582862&r2=1582863&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java
Fri Mar 28 19:39:26 2014
@@ -19,11 +19,9 @@ package org.apache.jackrabbit.oak.plugin
import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
-import static org.apache.jackrabbit.oak.api.Type.NAME;
import static
org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.MISSING_NODE;
import static
org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_NODE_TYPES;
-import java.util.Collections;
import java.util.Set;
import org.apache.felix.scr.annotations.Component;
@@ -60,38 +58,32 @@ public class TypeEditorProvider implemen
NodeState afterTypes =
after.getChildNode(JCR_SYSTEM).getChildNode(JCR_NODE_TYPES);
- Set<String> modifiedTypes = Collections.emptySet();
+ String primary = after.getName(JCR_PRIMARYTYPE);
+ Iterable<String> mixins = after.getNames(JCR_MIXINTYPES);
+
TypeRegistration registration = new TypeRegistration();
afterTypes.compareAgainstBaseState(beforeTypes, registration);
if (registration.isModified()) {
afterTypes = registration.apply(builder);
- modifiedTypes = registration.getModifiedTypes(beforeTypes);
- }
-
- String primary = after.getName(JCR_PRIMARYTYPE);
- Iterable<String> mixins = after.getNames(JCR_MIXINTYPES);
- if (primary == null && afterTypes.hasChildNode("rep:root")) {
- // no primary type on the root node, set the hardcoded default
- primary = "rep:root";
- builder.setProperty(JCR_PRIMARYTYPE, primary, NAME);
- }
-
- Editor editor = new VisibleEditor(
- new TypeEditor(strict, afterTypes, primary, mixins, builder));
- if (modifiedTypes.isEmpty()) {
- return editor;
- } else {
- // Some node types were modified, so scan the entire repository
- // to make sure that the modified type definitions still apply.
- // TODO: Only check the content that uses the modified node types.
- CommitFailedException exception =
- EditorDiff.process(editor, MISSING_NODE, after);
- if (exception != null) {
- throw exception;
+ Set<String> modifiedTypes =
+ registration.getModifiedTypes(beforeTypes);
+ if (!modifiedTypes.isEmpty()) {
+ // Some node types were modified, so scan the repository
+ // to make sure that the modified definitions still apply.
+ Editor editor = new VisibleEditor(new TypeEditor(
+ strict, modifiedTypes, afterTypes,
+ primary, mixins, builder));
+ CommitFailedException exception =
+ EditorDiff.process(editor, MISSING_NODE, after);
+ if (exception != null) {
+ throw exception;
+ }
}
- return null;
}
+
+ return new VisibleEditor(new TypeEditor(
+ strict, null, afterTypes, primary, mixins, builder));
}
}