Package org.apache.jackrabbit.oak.plugins.type

Source Code of org.apache.jackrabbit.oak.plugins.type.NodeTypeManagerImpl

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jackrabbit.oak.plugins.type;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;

import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.nodetype.ItemDefinition;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeDefinitionTemplate;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeDefinition;
import javax.jcr.nodetype.NodeTypeExistsException;
import javax.jcr.nodetype.NodeTypeIterator;
import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.nodetype.NodeTypeTemplate;
import javax.jcr.nodetype.PropertyDefinition;
import javax.jcr.nodetype.PropertyDefinitionTemplate;
import javax.jcr.version.OnParentVersionAction;

import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader;
import org.apache.jackrabbit.commons.iterator.NodeTypeIteratorAdapter;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.ContentSession;
import org.apache.jackrabbit.oak.api.CoreValueFactory;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.core.DefaultConflictHandler;
import org.apache.jackrabbit.oak.namepath.NameMapper;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

public class NodeTypeManagerImpl implements NodeTypeManager {

    private final ContentSession session;

    private final NameMapper mapper;

    private final ValueFactory factory;

    public NodeTypeManagerImpl(
            ContentSession session, NameMapper mapper, ValueFactory factory) {
        this.session = session;
        this.mapper = mapper;
        this.factory = factory;

        if (session.getCurrentRoot().getTree("/jcr:system/jcr:nodeTypes") == null) {
            try {
                InputStream stream = NodeTypeManagerImpl.class.getResourceAsStream(
                        "builtin_nodetypes.cnd");
                try {
                    CompactNodeTypeDefReader<NodeTypeTemplate, Map<String, String>> reader =
                            new CompactNodeTypeDefReader<NodeTypeTemplate, Map<String, String>>(
                                    new InputStreamReader(stream, "UTF-8"), null, new DefBuilderFactory());
                    Map<String, NodeTypeTemplate> templates = Maps.newHashMap();
                    for (NodeTypeTemplate template : reader.getNodeTypeDefinitions()) {
                        templates.put(template.getName(), template);
                    }
                    for (NodeTypeTemplate template : templates.values()) {
                        if (!template.isMixin()
                                && !"nt:base".equals(template.getName())) {
                            String[] supertypes =
                                    template.getDeclaredSupertypeNames();
                            if (supertypes.length == 0) {
                                template.setDeclaredSuperTypeNames(
                                        new String[] { "nt:base" });
                            } else {
                                // Check whether we need to add the implicit "nt:base" supertype
                                boolean needsNtBase = true;
                                for (String name : supertypes) {
                                    if (!templates.get(name).isMixin()) {
                                        needsNtBase = false;
                                    }
                                }
                                if (needsNtBase) {
                                    String[] withBase = new String[supertypes.length + 1];
                                    withBase[0] = "nt:base";
                                    System.arraycopy(supertypes, 0, withBase, 1, supertypes.length);
                                    template.setDeclaredSuperTypeNames(withBase);
                                }
                            }
                        }
                    }
                    registerNodeTypes(templates.values().toArray(
                            new NodeTypeTemplate[templates.size()]), true);
                } finally {
                    stream.close();
                }
            } catch (Exception e) {
                throw new IllegalStateException(
                        "Unable to load built-in node types", e);
            }
        }
    }

    protected String getOakName(String name) throws RepositoryException {
        return name; // TODO
    }

    /**
     * Called by the {@link NodeTypeManager} implementation methods to
     * refresh the state of the session associated with this instance.
     * That way the session is kept in sync with the latest global state
     * seen by the node type manager.
     *
     * @throws RepositoryException if the session could not be refreshed
     */
    protected void refresh() throws RepositoryException {
    }

    //---------------------------------------------------< NodeTypeManager >--

    @Override
    public boolean hasNodeType(String name) throws RepositoryException {
        Tree types = session.getCurrentRoot().getTree(
                "/jcr:system/jcr:nodeTypes");
        return types != null && types.hasChild(mapper.getOakName(name));
    }

    @Override
    public NodeType getNodeType(String name) throws RepositoryException {
        Tree types = session.getCurrentRoot().getTree(
                "/jcr:system/jcr:nodeTypes");
        if (types != null) {
            Tree type = types.getChild(mapper.getOakName(name));
            if (type != null) {
                return new NodeTypeImpl(this, factory, new NodeUtil(
                        session.getCoreValueFactory(), mapper, type));
            }
        }
        throw new NoSuchNodeTypeException(name);
    }

    @Override
    public NodeTypeIterator getAllNodeTypes() throws RepositoryException {
        List<NodeType> list = Lists.newArrayList();
        Tree types = session.getCurrentRoot().getTree(
                "/jcr:system/jcr:nodeTypes");
        if (types != null) {
            for (Tree type : types.getChildren()) {
                list.add(new NodeTypeImpl(this, factory, new NodeUtil(
                        session.getCoreValueFactory(), mapper, type)));
               
            }
        }
        return new NodeTypeIteratorAdapter(list);
    }

    @Override
    public NodeTypeIterator getPrimaryNodeTypes() throws RepositoryException {
        List<NodeType> list = Lists.newArrayList();
        NodeTypeIterator iterator = getAllNodeTypes();
        while (iterator.hasNext()) {
            NodeType type = iterator.nextNodeType();
            if (!type.isMixin()) {
                list.add(type);
            }
        }
        return new NodeTypeIteratorAdapter(list);
    }

    @Override
    public NodeTypeIterator getMixinNodeTypes() throws RepositoryException {
        List<NodeType> list = Lists.newArrayList();
        NodeTypeIterator iterator = getAllNodeTypes();
        while (iterator.hasNext()) {
            NodeType type = iterator.nextNodeType();
            if (type.isMixin()) {
                list.add(type);
            }
        }
        return new NodeTypeIteratorAdapter(list);
    }

    @Override
    public NodeTypeTemplate createNodeTypeTemplate() throws RepositoryException {
        return new NodeTypeTemplateImpl(this, factory);
    }

    @Override
    public NodeTypeTemplate createNodeTypeTemplate(NodeTypeDefinition ntd) throws RepositoryException {
        return new NodeTypeTemplateImpl(this, factory, ntd);
    }

    @Override
    public NodeDefinitionTemplate createNodeDefinitionTemplate() {
        return new NodeDefinitionTemplateImpl();
    }

    @Override
    public PropertyDefinitionTemplate createPropertyDefinitionTemplate() {
        return new PropertyDefinitionTemplateImpl();
    }

    @Override
    public NodeType registerNodeType(NodeTypeDefinition ntd, boolean allowUpdate) throws RepositoryException {
        // TODO proper node type registration... (OAK-66)
        Root root = session.getCurrentRoot();
        Tree types = getOrCreateNodeTypes(root);
        try {
            NodeType type = internalRegister(types, ntd, allowUpdate);
            root.commit(DefaultConflictHandler.OURS);
            return type;
        } catch (CommitFailedException e) {
            throw new RepositoryException(e);
        }
    }

    @Override
    public NodeTypeIterator registerNodeTypes(NodeTypeDefinition[] ntds, boolean allowUpdate) throws RepositoryException {
        // TODO handle inter-type dependencies (OAK-66)
        Root root = session.getCurrentRoot();
        Tree types = getOrCreateNodeTypes(root);
        try {
            List<NodeType> list = Lists.newArrayList();
            for (NodeTypeDefinition ntd : ntds) {
                list.add(internalRegister(types, ntd, allowUpdate));
            }
            root.commit(DefaultConflictHandler.OURS);
            return new NodeTypeIteratorAdapter(list);
        } catch (CommitFailedException e) {
            throw new RepositoryException(e);
        }
    }

    private NodeType internalRegister(
            Tree types, NodeTypeDefinition ntd, boolean allowUpdate)
            throws RepositoryException {
        String jcrName = ntd.getName();
        String oakName = mapper.getOakName(jcrName);

        Tree type = types.getChild(oakName);
        if (type != null) {
            if (allowUpdate) {
                type.remove();
            } else {
                throw new NodeTypeExistsException(
                        "Node type " + jcrName + " already exists");
            }
        }
        type = types.addChild(oakName);

        CoreValueFactory factory = session.getCoreValueFactory();
        NodeUtil node = new NodeUtil(factory, mapper, type);
        node.setName("jcr:nodeTypeName", jcrName);
        node.setNames("jcr:supertypes", ntd.getDeclaredSupertypeNames());
        node.setBoolean("jcr:isAbstract", ntd.isAbstract());
        node.setBoolean("jcr:isQueryable", ntd.isQueryable());
        node.setBoolean("jcr:isMixin", ntd.isMixin());
        node.setBoolean("jcr:hasOrderableChildNodes", ntd.hasOrderableChildNodes());
        String primaryItemName = ntd.getPrimaryItemName();
        if (primaryItemName != null) {
            node.setName("jcr:primaryItemName", primaryItemName);
        }

        int pdn = 1;
        for (PropertyDefinition pd : ntd.getDeclaredPropertyDefinitions()) {
            Tree def = type.addChild("jcr:propertyDefinition" + pdn++);
            internalRegisterPropertyDefinition(
                    new NodeUtil(factory, mapper, def), pd);
        }

        int ndn = 1;
        for (NodeDefinition nd : ntd.getDeclaredChildNodeDefinitions()) {
            Tree def = type.addChild("jcr:childNodeDefinition" + ndn++);
            internalRegisterNodeDefinition(
                    new NodeUtil(factory, mapper, def), nd);
        }

        return new NodeTypeImpl(this, this.factory, node);
    }

    private void internalRegisterItemDefinition(
            NodeUtil node, ItemDefinition def) {
        String name = def.getName();
        if (!"*".equals(name)) {
            node.setName("jcr:name", name);
        }
        node.setBoolean("jcr:autoCreated", def.isAutoCreated());
        node.setBoolean("jcr:mandatory", def.isMandatory());
        node.setBoolean("jcr:protected", def.isProtected());
        node.setString(
                "jcr:onParentVersion",
                OnParentVersionAction.nameFromValue(def.getOnParentVersion()));
    }

    private void internalRegisterPropertyDefinition(
            NodeUtil node, PropertyDefinition def)
            throws RepositoryException {
        internalRegisterItemDefinition(node, def);

        node.setString(
                "jcr:requiredType",
                PropertyType.nameFromValue(def.getRequiredType()));
        node.setBoolean("jcr:multiple", def.isMultiple());
        node.setBoolean("jcr:isFullTextSearchable", def.isFullTextSearchable());
        node.setBoolean("jcr:isQueryOrderable", def.isQueryOrderable());
        node.setStrings("jcr:availableQueryOperators", def.getAvailableQueryOperators());

        String[] constraints = def.getValueConstraints();
        if (constraints != null) {
            node.setStrings("jcr:valueConstraints", constraints);
        }

        Value[] values = def.getDefaultValues();
        if (values != null) {
            node.setValues("jcr:defaultValues", values);
        }
    }

    private void internalRegisterNodeDefinition(
            NodeUtil node, NodeDefinition def) {
        internalRegisterItemDefinition(node, def);

        node.setBoolean("jcr:sameNameSiblings", def.allowsSameNameSiblings());
        node.setNames(
                "jcr:requiredPrimaryTypes",
                def.getRequiredPrimaryTypeNames());
        String defaultPrimaryType = def.getDefaultPrimaryTypeName();
        if (defaultPrimaryType != null) {
            node.setName("jcr:defaultPrimaryType", defaultPrimaryType);
        }
    }

    private Tree getOrCreateNodeTypes(Root root) {
        Tree types = root.getTree("/jcr:system/jcr:nodeTypes");
        if (types == null) {
            Tree system = root.getTree("/jcr:system");
            if (system == null) {
                system = root.getTree("/").addChild("jcr:system");
            }
            types = system.addChild("jcr:nodeTypes");
        }
        return types;
    }

    @Override
    public void unregisterNodeType(String name) throws RepositoryException {
        Tree type = null;
        Root root = session.getCurrentRoot();
        Tree types = root.getTree("/jcr:system/jcr:nodeTypes");
        if (types != null) {
            type = types.getChild(mapper.getOakName(name));
        }
        if (type == null) {
            // TODO: Degrade gracefully? Or throw NoSuchNodeTypeException?
            throw new RepositoryException(
                    "Node type " + name + " can not be unregistered");
        }

        try {
            type.remove();
            root.commit(DefaultConflictHandler.OURS);
            refresh();
        } catch (CommitFailedException e) {
            throw new RepositoryException(
                    "Failed to unregister node type " + name, e);
        }
    }

    @Override
    public void unregisterNodeTypes(String[] names) throws RepositoryException {
        Root root = session.getCurrentRoot();
        Tree types = root.getTree("/jcr:system/jcr:nodeTypes");
        if (types == null) {
            // TODO: Degrade gracefully? Or throw NoSuchNodeTypeException?
            throw new RepositoryException("Node types can not be unregistered");
        }

        try {
            for (String name : names) {
                Tree type = types.getChild(mapper.getOakName(name));
                if (type == null) {
                    // TODO: Degrade gracefully? Or throw NoSuchNodeTypeException?
                    throw new RepositoryException(
                            "Node type " + name + " can not be unregistered");
                }
                type.remove();
            }
            root.commit(DefaultConflictHandler.OURS);
            refresh();
        } catch (CommitFailedException e) {
            throw new RepositoryException(
                    "Failed to unregister node types", e);
        }
    }

}
TOP

Related Classes of org.apache.jackrabbit.oak.plugins.type.NodeTypeManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.