You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ju...@apache.org on 2013/03/22 13:49:19 UTC
svn commit: r1459750 - in
/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype:
EffectiveNodeType.java EffectiveNodeTypeImpl.java
ReadOnlyNodeTypeManager.java
Author: jukka
Date: Fri Mar 22 12:49:18 2013
New Revision: 1459750
URL: http://svn.apache.org/r1459750
Log:
OAK-702: Optimize access to node type information
Merge EffectiveNodeTypeImpl and EffectiveNodeType (no need for an interface when there's just one implementation) to simplify refactoring
Removed:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeTypeImpl.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeType.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeType.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeType.java?rev=1459750&r1=1459749&r2=1459750&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeType.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeType.java Fri Mar 22 12:49:18 2013
@@ -16,26 +16,63 @@
*/
package org.apache.jackrabbit.oak.plugins.nodetype;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.Value;
import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.ItemDefinition;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.PropertyDefinition;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
/**
* EffectiveNodeType... TODO
*/
-public interface EffectiveNodeType {
+public class EffectiveNodeType {
- Iterable<NodeType> getAllNodeTypes();
+ private static final Logger log = LoggerFactory.getLogger(EffectiveNodeType.class);
- //Iterable<NodeType> getInheritedNodeTypes();
- //Iterable<NodeType> getMergedNodeTypes();
+ private final Collection<NodeType> nodeTypes;
+ private final ReadOnlyNodeTypeManager ntMgr;
+
+ private EffectiveNodeType(Collection<NodeType> nodeTypes, ReadOnlyNodeTypeManager ntMgr) {
+ this.nodeTypes = nodeTypes;
+ this.ntMgr = ntMgr;
+ }
+
+ static EffectiveNodeType create(Collection<NodeType> nodeTypes, ReadOnlyNodeTypeManager ntMgr) throws ConstraintViolationException {
+ if (!isValid(nodeTypes)) {
+ throw new ConstraintViolationException("Invalid effective node type");
+ }
+ return new EffectiveNodeType(nodeTypes, ntMgr);
+ }
+
+ private static boolean isValid(Collection<NodeType> nodeTypes) {
+ // FIXME: add validation
+ return true;
+ }
+
+ public Iterable<NodeType> getAllNodeTypes() {
+ return nodeTypes;
+ }
/**
* Determines whether this effective node type representation includes
@@ -44,7 +81,15 @@ public interface EffectiveNodeType {
* @param nodeTypeName name of node type
* @return {@code true} if the given node type is included, otherwise {@code false}.
*/
- boolean includesNodeType(String nodeTypeName);
+ public boolean includesNodeType(String nodeTypeName) {
+ for (NodeType type : nodeTypes) {
+ if (type.isNodeType(nodeTypeName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Determines whether this effective node type representation includes
@@ -54,7 +99,14 @@ public interface EffectiveNodeType {
* @return {@code true} if all of the given node types are included,
* otherwise {@code false}
*/
- boolean includesNodeTypes(String[] nodeTypeNames);
+ public boolean includesNodeTypes(String[] nodeTypeNames) {
+ for (String ntName : nodeTypeNames) {
+ if (!includesNodeType(ntName)) {
+ return false;
+ }
+ }
+ return true;
+ }
/**
* Determines whether this effective node type supports adding
@@ -62,19 +114,80 @@ public interface EffectiveNodeType {
* @param mixin name of mixin type
* @return {@code true} if the mixin type is supported, otherwise {@code false}
*/
- boolean supportsMixin(String mixin);
-
- Iterable<NodeDefinition> getNodeDefinitions();
-
- Iterable<PropertyDefinition> getPropertyDefinitions();
-
- Iterable<NodeDefinition> getAutoCreateNodeDefinitions();
-
- Iterable<PropertyDefinition> getAutoCreatePropertyDefinitions();
-
- Iterable<NodeDefinition> getMandatoryNodeDefinitions();
-
- Iterable<PropertyDefinition> getMandatoryPropertyDefinitions();
+ public boolean supportsMixin(String mixin) {
+ if (includesNodeType(mixin)) {
+ return true;
+ }
+
+ NodeType mixinType = null;
+ try {
+ mixinType = ntMgr.internalGetNodeType(mixin);
+ if (!mixinType.isMixin() || mixinType.isAbstract()) {
+ return false;
+ }
+ } catch (NoSuchNodeTypeException e) {
+ log.debug("Unknown mixin type " + mixin);
+ }
+
+ if (mixinType != null) {
+ Set<NodeType> newTypes = new HashSet<NodeType>(nodeTypes);
+ newTypes.add(mixinType);
+ return isValid(newTypes);
+ }
+ return false;
+ }
+
+ public Iterable<NodeDefinition> getNodeDefinitions() {
+ List<NodeDefinition> definitions = new ArrayList<NodeDefinition>();
+ for (NodeType nt : nodeTypes) {
+ definitions.addAll(((NodeTypeImpl) nt).internalGetChildDefinitions());
+ }
+ return definitions;
+ }
+
+ public Iterable<PropertyDefinition> getPropertyDefinitions() {
+ List<PropertyDefinition> definitions = new ArrayList<PropertyDefinition>();
+ for (NodeType nt : nodeTypes) {
+ definitions.addAll(((NodeTypeImpl) nt).internalGetPropertyDefinitions());
+ }
+ return definitions;
+ }
+
+ public Iterable<NodeDefinition> getAutoCreateNodeDefinitions() {
+ return Iterables.filter(getNodeDefinitions(), new Predicate<NodeDefinition>() {
+ @Override
+ public boolean apply(NodeDefinition nodeDefinition) {
+ return nodeDefinition.isAutoCreated();
+ }
+ });
+ }
+
+ public Iterable<PropertyDefinition> getAutoCreatePropertyDefinitions() {
+ return Iterables.filter(getPropertyDefinitions(), new Predicate<PropertyDefinition>() {
+ @Override
+ public boolean apply(PropertyDefinition propertyDefinition) {
+ return propertyDefinition.isAutoCreated();
+ }
+ });
+ }
+
+ public Iterable<NodeDefinition> getMandatoryNodeDefinitions() {
+ return Iterables.filter(getNodeDefinitions(), new Predicate<NodeDefinition>() {
+ @Override
+ public boolean apply(NodeDefinition nodeDefinition) {
+ return nodeDefinition.isMandatory();
+ }
+ });
+ }
+
+ public Iterable<PropertyDefinition> getMandatoryPropertyDefinitions() {
+ return Iterables.filter(getPropertyDefinitions(), new Predicate<PropertyDefinition>() {
+ @Override
+ public boolean apply(PropertyDefinition propertyDefinition) {
+ return propertyDefinition.isMandatory();
+ }
+ });
+ }
/**
* Return all node definitions that match the specified oak name.
@@ -83,7 +196,9 @@ public interface EffectiveNodeType {
* @return All node definitions that match the given internal oak name.
*/
@Nonnull
- Iterable<NodeDefinition> getNamedNodeDefinitions(String oakName);
+ public Iterable<NodeDefinition> getNamedNodeDefinitions(String oakName) {
+ return Iterables.filter(getNodeDefinitions(), new DefinitionNamePredicate(oakName));
+ }
/**
* Return all property definitions that match the specified oak name.
@@ -92,7 +207,9 @@ public interface EffectiveNodeType {
* @return All property definitions that match the given internal oak name.
*/
@Nonnull
- Iterable<PropertyDefinition> getNamedPropertyDefinitions(String oakName);
+ public Iterable<PropertyDefinition> getNamedPropertyDefinitions(String oakName) {
+ return Iterables.filter(getPropertyDefinitions(), new DefinitionNamePredicate(oakName));
+ }
/**
* Return all residual node definitions.
@@ -100,7 +217,14 @@ public interface EffectiveNodeType {
* @return All residual node definitions.
*/
@Nonnull
- Iterable<NodeDefinition> getResidualNodeDefinitions();
+ public Iterable<NodeDefinition> getResidualNodeDefinitions() {
+ return Iterables.filter(getNodeDefinitions(), new Predicate<NodeDefinition>() {
+ @Override
+ public boolean apply(NodeDefinition nodeDefinition) {
+ return NodeTypeConstants.RESIDUAL_NAME.equals(nodeDefinition.getName());
+ }
+ });
+ }
/**
* Return all residual property definitions.
@@ -108,17 +232,139 @@ public interface EffectiveNodeType {
* @return All residual property definitions.
*/
@Nonnull
- Iterable<PropertyDefinition> getResidualPropertyDefinitions();
-
- void checkSetProperty(PropertyState property) throws RepositoryException;
-
- void checkRemoveProperty(PropertyState property) throws RepositoryException;
-
- void checkAddChildNode(String name, NodeType nodeType) throws RepositoryException;
-
- void checkRemoveNode(String name, NodeType nodeType) throws RepositoryException;
-
- void checkMandatoryItems(Tree tree) throws ConstraintViolationException;
+ public Iterable<PropertyDefinition> getResidualPropertyDefinitions() {
+ return Iterables.filter(getPropertyDefinitions(), new Predicate<PropertyDefinition>() {
+ @Override
+ public boolean apply(PropertyDefinition propertyDefinition) {
+ return NodeTypeConstants.RESIDUAL_NAME.equals(propertyDefinition.getName());
+ }
+ });
+ }
+
+ public void checkSetProperty(PropertyState property) throws RepositoryException {
+ PropertyDefinition definition = getDefinition(property);
+ if (definition.isProtected()) {
+ return;
+ }
+
+ NodeType nt = definition.getDeclaringNodeType();
+ if (definition.isMultiple()) {
+ List<Value> values = ValueFactoryImpl.createValues(property, ntMgr.getNamePathMapper());
+ if (!nt.canSetProperty(property.getName(), values.toArray(new Value[values.size()]))) {
+ throw new ConstraintViolationException("Cannot set property '" + property.getName() + "' to '" + values + '\'');
+ }
+ } else {
+ Value v = ValueFactoryImpl.createValue(property, ntMgr.getNamePathMapper());
+ if (!nt.canSetProperty(property.getName(), v)) {
+ throw new ConstraintViolationException("Cannot set property '" + property.getName() + "' to '" + v + '\'');
+ }
+ }
+ }
+
+ public void checkRemoveProperty(PropertyState property) throws RepositoryException {
+ PropertyDefinition definition = getDefinition(property);
+ if (definition.isProtected()) {
+ return;
+ }
+
+ if (!definition.getDeclaringNodeType().canRemoveProperty(property.getName())) {
+ throw new ConstraintViolationException("Cannot remove property '" + property.getName() + '\'');
+ }
+ }
+
+ public void checkAddChildNode(String name, NodeType nodeType) throws RepositoryException {
+ NodeDefinition definition = getDefinition(name, nodeType);
+
+ if (definition.isProtected()) {
+ return;
+ }
+
+ if (nodeType == null) {
+ if (!definition.getDeclaringNodeType().canAddChildNode(name)) {
+ throw new ConstraintViolationException("Cannot add node '" + name + '\'');
+ }
+ } else {
+ if (!definition.getDeclaringNodeType().canAddChildNode(name, nodeType.getName())) {
+ throw new ConstraintViolationException("Cannot add node '" + name + "' of type '" + nodeType.getName() + '\'');
+ }
+ }
+ }
+
+ public void checkRemoveNode(String name, NodeType nodeType) throws RepositoryException {
+ NodeDefinition definition = getDefinition(name, nodeType);
+
+ if (definition.isProtected()) {
+ return;
+ }
+
+ if (!definition.getDeclaringNodeType().canRemoveNode(name)) {
+ throw new ConstraintViolationException("Cannot remove node '" + name + '\'');
+ }
+ }
+
+ public void checkMandatoryItems(Tree tree) throws ConstraintViolationException {
+ for (NodeType nodeType : nodeTypes) {
+ for (PropertyDefinition pd : nodeType.getPropertyDefinitions()) {
+ String name = pd.getName();
+ if (pd.isMandatory() && !pd.isProtected() && tree.getProperty(name) == null) {
+ throw new ConstraintViolationException(
+ "Property '" + name + "' in '" + nodeType.getName() + "' is mandatory");
+ }
+ }
+ for (NodeDefinition nd : nodeType.getChildNodeDefinitions()) {
+ String name = nd.getName();
+ if (nd.isMandatory() && !nd.isProtected() && tree.getChild(name) == null) {
+ throw new ConstraintViolationException(
+ "Node '" + name + "' in '" + nodeType.getName() + "' is mandatory");
+ }
+ }
+ }
+ }
+
+ public void checkOrderableChildNodes() throws UnsupportedRepositoryOperationException {
+ Iterable<NodeType> nts = getAllNodeTypes();
+ for (NodeType nt : nts) {
+ if (nt.hasOrderableChildNodes()) {
+ return;
+ }
+ }
+
+ throw new UnsupportedRepositoryOperationException("Child node ordering is not supported on this node");
+ }
+
+ //------------------------------------------------------------< private >---
+
+ private PropertyDefinition getDefinition(PropertyState property) throws RepositoryException {
+ String propertyName = property.getName();
+ int propertyType = property.getType().tag();
+ boolean isMultiple = property.isArray();
+
+ return ntMgr.getDefinition(nodeTypes, propertyName, isMultiple, propertyType, true);
+ }
+
+ private NodeDefinition getDefinition(String nodeName, NodeType nodeType) throws ConstraintViolationException {
+ // FIXME: ugly hack to workaround sns-hack that was used to map sns-item definitions with node types.
+ String nameToCheck = nodeName;
+ if (nodeName.startsWith("jcr:childNodeDefinition") && !nodeName.equals("jcr:childNodeDefinition")) {
+ nameToCheck = nodeName.substring(0, "jcr:childNodeDefinition".length());
+ }
+ if (nodeName.startsWith("jcr:propertyDefinition") && !nodeName.equals("jcr:propertyDefinition")) {
+ nameToCheck = nodeName.substring(0, "jcr:propertyDefinition".length());
+ }
+ return ntMgr.getDefinition(nodeTypes, nameToCheck, nodeType);
+ }
+
+ private static class DefinitionNamePredicate implements Predicate<ItemDefinition> {
+
+ private final String oakName;
+
+ DefinitionNamePredicate(String oakName) {
+ this.oakName = oakName;
+ }
+ @Override
+ public boolean apply(@Nullable ItemDefinition definition) {
+ return definition instanceof ItemDefinitionImpl && ((ItemDefinitionImpl) definition).getOakName().equals(oakName);
+ }
+ }
- void checkOrderableChildNodes() throws UnsupportedRepositoryOperationException;
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java?rev=1459750&r1=1459749&r2=1459750&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java Fri Mar 22 12:49:18 2013
@@ -490,7 +490,7 @@ public abstract class ReadOnlyNodeTypeMa
queue.addAll(Arrays.asList(type.getDeclaredSupertypes()));
}
}
- return EffectiveNodeTypeImpl.create(types.values(), this);
+ return EffectiveNodeType.create(types.values(), this);
}
/**