Package org.apache.jackrabbit.core.nodetype

Source Code of org.apache.jackrabbit.core.nodetype.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.core.nodetype;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.jcr.NamespaceException;
import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.ValueFormatException;
import javax.jcr.nodetype.InvalidNodeTypeDefinitionException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeDefinition;
import javax.jcr.nodetype.NodeTypeExistsException;
import javax.jcr.nodetype.NodeTypeIterator;
import javax.jcr.nodetype.PropertyDefinition;

import org.apache.commons.collections.map.ReferenceMap;
import org.apache.jackrabbit.api.JackrabbitNodeTypeManager;
import org.apache.jackrabbit.commons.NamespaceHelper;
import org.apache.jackrabbit.commons.iterator.NodeTypeIteratorAdapter;
import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.data.DataStore;
import org.apache.jackrabbit.core.nodetype.xml.NodeTypeReader;
import org.apache.jackrabbit.core.util.Dumpable;
import org.apache.jackrabbit.core.value.InternalValue;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.QNodeTypeDefinition;
import org.apache.jackrabbit.spi.QValueConstraint;
import org.apache.jackrabbit.spi.commons.conversion.NameException;
import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
import org.apache.jackrabbit.spi.commons.nodetype.AbstractNodeTypeManager;
import org.apache.jackrabbit.spi.commons.nodetype.InvalidConstraintException;
import org.apache.jackrabbit.spi.commons.nodetype.compact.CompactNodeTypeDefReader;
import org.apache.jackrabbit.spi.commons.nodetype.compact.ParseException;
import org.apache.jackrabbit.spi.commons.nodetype.constraint.ValueConstraint;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
* A <code>NodeTypeManagerImpl</code> implements a session dependant
* NodeTypeManager.
*/
public class NodeTypeManagerImpl extends AbstractNodeTypeManager implements JackrabbitNodeTypeManager,
        Dumpable, NodeTypeRegistryListener {

    /**
     * The wrapped node type registry.
     */
    private final NodeTypeRegistry ntReg;

    /**
     * Current session.
     */
    private final SessionImpl session;

    /**
     * The value factory obtained from the current session.
     */
    private final ValueFactory valueFactory;

    /**
     * The root node definition.
     */
    private final NodeDefinitionImpl rootNodeDef;

    /**
     * A cache for <code>NodeType</code> instances created by this
     * <code>NodeTypeManager</code>
     */
    private final Map<Name, NodeTypeImpl> ntCache;

    /**
     * A cache for <code>PropertyDefinition</code> instances created by this
     * <code>NodeTypeManager</code>
     */
    private final Map<PropDefId, PropertyDefinitionImpl> pdCache;

    /**
     * A cache for <code>NodeDefinition</code> instances created by this
     * <code>NodeTypeManager</code>
     */
    private final Map<NodeDefId, NodeDefinitionImpl> ndCache;

    private final DataStore store;

    /**
     * Creates a new <code>NodeTypeManagerImpl</code> instance.
     *
     * @param ntReg      node type registry
     * @param session    current session
     * @param store      the data store
     * @throws RepositoryException If an error occurs.
     */
    @SuppressWarnings("unchecked")
    public NodeTypeManagerImpl(
            NodeTypeRegistry ntReg, SessionImpl session, DataStore store)
            throws RepositoryException {
        this.ntReg = ntReg;
        this.session = session;
        this.valueFactory = session.getValueFactory();
        this.ntReg.addListener(this);
        this.store = store;

        // setup caches with soft references to node type
        // & item definition instances
        ntCache = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT);
        pdCache = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT);
        ndCache = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT);

        rootNodeDef =
            new NodeDefinitionImpl(ntReg.getRootNodeDef(), this, session);
        ndCache.put(rootNodeDef.unwrap().getId(), rootNodeDef);
    }

    /**
     * @return the root node definition
     */
    public NodeDefinitionImpl getRootNodeDefinition() {
        return rootNodeDef;
    }

    /**
     * @param id node def id
     * @return the node definition
     */
    public NodeDefinitionImpl getNodeDefinition(NodeDefId id) {
        synchronized (ndCache) {
            NodeDefinitionImpl ndi = ndCache.get(id);
            if (ndi == null) {
                NodeDef nd = ntReg.getNodeDef(id);
                if (nd != null) {
                    ndi = new NodeDefinitionImpl(nd, this, session);
                    ndCache.put(id, ndi);
                }
            }
            return ndi;
        }
    }

    /**
     * @param id prop def id
     * @return the property definition
     */
    public PropertyDefinitionImpl getPropertyDefinition(PropDefId id) {
        synchronized (pdCache) {
            PropertyDefinitionImpl pdi = pdCache.get(id);
            if (pdi == null) {
                PropDef pd = ntReg.getPropDef(id);
                if (pd != null) {
                    pdi = new PropertyDefinitionImpl(pd, this, session, valueFactory);
                    pdCache.put(id, pdi);
                }
            }
            return pdi;
        }
    }

    /**
     * @param name node type name
     * @return node type
     * @throws NoSuchNodeTypeException if the nodetype does not exit
     */
    public NodeTypeImpl getNodeType(Name name) throws NoSuchNodeTypeException {
        synchronized (ntCache) {
            NodeTypeImpl nt = ntCache.get(name);
            if (nt == null) {
                EffectiveNodeType ent = ntReg.getEffectiveNodeType(name);
                NodeTypeDef def = ntReg.getNodeTypeDef(name);
                nt = new NodeTypeImpl(ent, def, this, session, valueFactory, store);
                ntCache.put(name, nt);
            }
            return nt;
        }
    }

    /**
     * @return the node type registry
     */
    public NodeTypeRegistry getNodeTypeRegistry() {
        return ntReg;
    }

    /**
     * Registers the node types defined in the given input stream depending
     * on the content type specified for the stream. This will also register
     * any namespaces identified in the input stream if they have not already
     * been registered.
     *
     * @param in node type XML stream
     * @param contentType type of the input stream
     * @param reregisterExisting flag indicating whether node types should be
     *                           reregistered if they already exist
     * @return registered node types
     * @throws IOException if the input stream could not be read or parsed
     * @throws RepositoryException if the node types are invalid or another
     *                             repository error occurs
     */
    public NodeType[] registerNodeTypes(InputStream in, String contentType,
            boolean reregisterExisting)
            throws IOException, RepositoryException {

        try {
            Map<String, String> namespaceMap = new HashMap<String, String>();
            List<NodeTypeDef> nodeTypeDefs = new ArrayList<NodeTypeDef>();

            if (contentType.equalsIgnoreCase(TEXT_XML)
                    || contentType.equalsIgnoreCase(APPLICATION_XML)) {
                try {
                    NodeTypeReader ntr = new NodeTypeReader(in);

                    Properties namespaces = ntr.getNamespaces();
                    if (namespaces != null) {
                        Enumeration prefixes = namespaces.propertyNames();
                        while (prefixes.hasMoreElements()) {
                            String prefix = (String) prefixes.nextElement();
                            String uri = namespaces.getProperty(prefix);
                            namespaceMap.put(prefix, uri);
                        }
                    }

                    NodeTypeDef[] defs = ntr.getNodeTypeDefs();
                    nodeTypeDefs.addAll(Arrays.asList(defs));
                } catch (NameException e) {
                    throw new RepositoryException("Illegal JCR name", e);
                }
            } else if (contentType.equalsIgnoreCase(TEXT_X_JCR_CND)) {
                try {
                    NamespaceMapping mapping = new NamespaceMapping(session);
                    CompactNodeTypeDefReader reader = new CompactNodeTypeDefReader(
                            new InputStreamReader(in), "cnd input stream", mapping);

                    namespaceMap.putAll(mapping.getPrefixToURIMapping());
                    for (QNodeTypeDefinition ntDef: reader.getNodeTypeDefinitions()) {
                        nodeTypeDefs.add(new NodeTypeDef(ntDef));
                    }
                } catch (ParseException e) {
                    IOException e2 = new IOException(e.getMessage());
                    e2.initCause(e);
                    throw e2;
                }
            } else {
                throw new UnsupportedRepositoryOperationException(
                        "Unsupported content type: " + contentType);
            }

            new NamespaceHelper(session).registerNamespaces(namespaceMap);

            if (reregisterExisting) {
                // split the node types into new and already registered node types.
                // this way we can register new node types together with already
                // registered node types which make circular dependencies possible
                List<NodeTypeDef> newNodeTypeDefs = new ArrayList<NodeTypeDef>();
                List<NodeTypeDef> registeredNodeTypeDefs = new ArrayList<NodeTypeDef>();
                for (NodeTypeDef nodeTypeDef: nodeTypeDefs) {
                    if (ntReg.isRegistered(nodeTypeDef.getName())) {
                        registeredNodeTypeDefs.add(nodeTypeDef);
                    } else {
                        newNodeTypeDefs.add(nodeTypeDef);
                    }
                }

                ArrayList<NodeType> nodeTypes = new ArrayList<NodeType>();

                // register new node types
                nodeTypes.addAll(registerNodeTypes(newNodeTypeDefs));

                // re-register already existing node types
                for (NodeTypeDef nodeTypeDef: registeredNodeTypeDefs) {
                    ntReg.reregisterNodeType(nodeTypeDef);
                    nodeTypes.add(getNodeType(nodeTypeDef.getName()));
                }
                return nodeTypes.toArray(new NodeType[nodeTypes.size()]);
            } else {
                Collection<NodeType> types = registerNodeTypes(nodeTypeDefs);
                return types.toArray(new NodeType[types.size()]);
            }

        } catch (InvalidNodeTypeDefException e) {
            throw new RepositoryException("Invalid node type definition", e);
        }
    }

    //---------------------------------------------< NodeTypeRegistryListener >
    /**
     * {@inheritDoc}
     */
    public void nodeTypeRegistered(Name ntName) {
        // not interested, ignore
    }

    /**
     * {@inheritDoc}
     */
    public void nodeTypeReRegistered(Name ntName) {
        // flush all affected cache entries
        ntCache.remove(ntName);
        synchronized (pdCache) {
            Iterator iter = pdCache.values().iterator();
            while (iter.hasNext()) {
                PropertyDefinitionImpl pd = (PropertyDefinitionImpl) iter.next();
                if (ntName.equals(pd.unwrap().getDeclaringNodeType())) {
                    iter.remove();
                }
            }
        }
        synchronized (ndCache) {
            Iterator iter = ndCache.values().iterator();
            while (iter.hasNext()) {
                NodeDefinitionImpl nd = (NodeDefinitionImpl) iter.next();
                if (ntName.equals(nd.unwrap().getDeclaringNodeType())) {
                    iter.remove();
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public void nodeTypeUnregistered(Name ntName) {
        // flush all affected cache entries
        ntCache.remove(ntName);
        synchronized (pdCache) {
            Iterator iter = pdCache.values().iterator();
            while (iter.hasNext()) {
                PropertyDefinitionImpl pd = (PropertyDefinitionImpl) iter.next();
                if (ntName.equals(pd.unwrap().getDeclaringNodeType())) {
                    iter.remove();
                }
            }
        }
        synchronized (ndCache) {
            Iterator iter = ndCache.values().iterator();
            while (iter.hasNext()) {
                NodeDefinitionImpl nd = (NodeDefinitionImpl) iter.next();
                if (ntName.equals(nd.unwrap().getDeclaringNodeType())) {
                    iter.remove();
                }
            }
        }
    }

    //------------------------------------------------------< NodeTypeManager >
    /**
     * {@inheritDoc}
     */
    public NodeTypeIterator getAllNodeTypes() throws RepositoryException {
        Name[] ntNames = ntReg.getRegisteredNodeTypes();
        Arrays.sort(ntNames);
        ArrayList<NodeType> list = new ArrayList<NodeType>(ntNames.length);
        for (Name ntName : ntNames) {
            list.add(getNodeType(ntName));
        }
        return new NodeTypeIteratorAdapter(list);
    }

    /**
     * {@inheritDoc}
     */
    public NodeTypeIterator getPrimaryNodeTypes() throws RepositoryException {
        Name[] ntNames = ntReg.getRegisteredNodeTypes();
        Arrays.sort(ntNames);
        ArrayList<NodeType> list = new ArrayList<NodeType>(ntNames.length);
        for (Name ntName : ntNames) {
            NodeType nt = getNodeType(ntName);
            if (!nt.isMixin()) {
                list.add(nt);
            }
        }
        return new NodeTypeIteratorAdapter(list);
    }

    /**
     * {@inheritDoc}
     */
    public NodeTypeIterator getMixinNodeTypes() throws RepositoryException {
        Name[] ntNames = ntReg.getRegisteredNodeTypes();
        Arrays.sort(ntNames);
        ArrayList<NodeType> list = new ArrayList<NodeType>(ntNames.length);
        for (Name ntName : ntNames) {
            NodeType nt = getNodeType(ntName);
            if (nt.isMixin()) {
                list.add(nt);
            }
        }
        return new NodeTypeIteratorAdapter(list);
    }

    /**
     * {@inheritDoc}
     */
    public NodeType getNodeType(String nodeTypeName)
            throws NoSuchNodeTypeException {
        try {
            return getNodeType(session.getQName(nodeTypeName));
        } catch (NameException e) {
            throw new NoSuchNodeTypeException(nodeTypeName, e);
        } catch (NamespaceException e) {
            throw new NoSuchNodeTypeException(nodeTypeName, e);
        }
    }

    //--------------------------------------------< JackrabbitNodeTypeManager >

    /**
     * Internal helper method for registering a list of node type definitions.
     * Returns a collection containing the registered node types.
     *
     * @param defs a collection of <code>NodeTypeDef<code> objects
     * @return registered node types
     * @throws InvalidNodeTypeDefException if a nodetype is invalid
     * @throws RepositoryException if an error occurs
     */
    private Collection<NodeType> registerNodeTypes(List<NodeTypeDef> defs)
            throws InvalidNodeTypeDefException, RepositoryException {
        ntReg.registerNodeTypes(defs);

        Set<NodeType> types = new HashSet<NodeType>();
        for (NodeTypeDef def : defs) {
            try {
                types.add(getNodeType(def.getName()));
            } catch (NoSuchNodeTypeException e) {
                // ignore
            }
        }
        return types;
    }

    /**
     * Registers the node types defined in the given XML stream.  This
     * is a trivial implementation that just invokes the existing
     * {@link NodeTypeReader} and {@link NodeTypeRegistry} methods and
     * heuristically creates the returned node type array.  It will also
     * register any namespaces defined in the input source that have not
     * already been registered.
     *
     * {@inheritDoc}
     */
    public NodeType[] registerNodeTypes(InputSource in)
            throws SAXException, RepositoryException {
        try {
            return registerNodeTypes(in.getByteStream(), TEXT_XML);
        } catch (IOException e) {
            throw new SAXException("Error reading node type stream", e);
        }
    }

    private static final String APPLICATION_XML = "application/xml";

    /**
     * Registers the node types defined in the given input stream depending
     * on the content type specified for the stream. This will also register
     * any namespaces identified in the input stream if they have not already
     * been registered.
     *
     * {@inheritDoc}
     */
    public NodeType[] registerNodeTypes(InputStream in, String contentType)
            throws IOException, RepositoryException {
        return registerNodeTypes(in, contentType, false);
    }

    /**
     * Checks whether a node type with the given name exists.
     *
     * @param name node type name
     * @return <code>true</code> if the named node type exists,
     *         <code>false</code> otherwise
     * @throws RepositoryException if the name format is invalid
     */
    public boolean hasNodeType(String name) throws RepositoryException {
        try {
            Name qname = session.getQName(name);
            return getNodeTypeRegistry().isRegistered(qname);
        } catch (NamespaceException e) {
            return false;
        } catch (NameException e) {
           throw new RepositoryException("Invalid name: " + name, e);
        }
    }

    //--------------------------------------------------< new JSR 283 methods >
    /**
     * Registers or updates the specified <code>Collection</code> of
     * <code>NodeTypeDefinition</code> objects. This method is used to register
     * or update a set of node types with mutual dependencies. Returns an
     * iterator over the resulting <code>NodeType</code> objects.
     * <p/>
     * The effect of the method is "all or nothing"; if an error occurs, no node
     * types are registered or updated.
     * <p/>
     * Throws an <code>InvalidNodeTypeDefinitionException</code> if a
     * <code>NodeTypeDefinition</code> within the <code>Collection</code> is
     * invalid or if the <code>Collection</code> contains an object of a type
     * other than <code>NodeTypeDefinition</code>.
     * <p/>
     * Throws a <code>NodeTypeExistsException</code> if <code>allowUpdate</code>
     * is <code>false</code> and a <code>NodeTypeDefinition</code> within the
     * <code>Collection</code> specifies a node type name that is already
     * registered.
     * <p/>
     * Throws an <code>UnsupportedRepositoryOperationException</code> if this
     * implementation does not support node type registration.
     *
     * @param definitions a collection of <code>NodeTypeDefinition</code>s
     * @param allowUpdate a boolean
     * @return the registered node types.
     * @throws InvalidNodeTypeDefinitionException if a
     *  <code>NodeTypeDefinition</code> within the <code>Collection</code> is
     *  invalid or if the <code>Collection</code> contains an object of a type
     *  other than <code>NodeTypeDefinition</code>.
     * @throws NodeTypeExistsException if <code>allowUpdate</code> is
     *  <code>false</code> and a <code>NodeTypeDefinition</code> within the
     *  <code>Collection</code> specifies a node type name that is already
     *  registered.
     * @throws UnsupportedRepositoryOperationException if this implementation
     *  does not support node type registration.
     * @throws RepositoryException if another error occurs.
     * @since JCR 2.0
     */
    public NodeTypeIterator registerNodeTypes(
            NodeTypeDefinition[] definitions, boolean allowUpdate)
            throws InvalidNodeTypeDefinitionException, NodeTypeExistsException,
            UnsupportedRepositoryOperationException, RepositoryException {
        // split the node types into new and already registered node types.
        // this way we can register new node types together with already
        // registered node types which make circular dependencies possible
        List<NodeTypeDef> addedDefs = new ArrayList<NodeTypeDef>();
        List<NodeTypeDef> modifiedDefs = new ArrayList<NodeTypeDef>();
        for (NodeTypeDefinition definition : definitions) {
            // convert to NodeTypeDef
            NodeTypeDef def = toNodeTypeDef(definition);
            if (ntReg.isRegistered(def.getName())) {
              if (allowUpdate) {
                  modifiedDefs.add(def);
              } else {
                  throw new NodeTypeExistsException(definition.getName());
              }
            } else {
                addedDefs.add(def);
            }
        }

        try {
            ArrayList<NodeType> result = new ArrayList<NodeType>();

            // register new node types
            result.addAll(registerNodeTypes(addedDefs));

            // re-register already existing node types
            for (NodeTypeDef nodeTypeDef: modifiedDefs) {
                ntReg.reregisterNodeType(nodeTypeDef);
                result.add(getNodeType(nodeTypeDef.getName()));
            }

            return new NodeTypeIteratorAdapter(result);
        } catch (InvalidNodeTypeDefException e) {
            throw new InvalidNodeTypeDefinitionException(e.getMessage(), e);
        }
    }

    /**
     * Unregisters the specified set of node types. Used to unregister a set of node types with mutual dependencies.
     * <p/>
     * Throws a <code>NoSuchNodeTypeException</code> if one of the names listed is not a registered node type.
     * <p/>
     * Throws an <code>UnsupportedRepositoryOperationException</code>
     * if this implementation does not support node type registration.
     *
     * @param names a <code>String</code> array
     * @throws UnsupportedRepositoryOperationException if this implementation does not support node type registration.
     * @throws NoSuchNodeTypeException if one of the names listed is not a registered node type.
     * @throws RepositoryException if another error occurs.
     * @since JCR 2.0
     */
    public void unregisterNodeTypes(String[] names)
            throws UnsupportedRepositoryOperationException,
            NoSuchNodeTypeException, RepositoryException {
        Set<Name> ntNames = new HashSet<Name>();
        for (String name : names) {
            try {
                ntNames.add(session.getQName(name));
            } catch (NamespaceException e) {
                throw new RepositoryException("Invalid name: " + name, e);
            } catch (NameException e) {
                throw new RepositoryException("Invalid name: " + name, e);
            }
        }
        getNodeTypeRegistry().unregisterNodeTypes(ntNames);
    }

    /**
     * Internal helper method for converting a <code>NodeTypeDefinition</code>
     * (using prefixed JCR names) to a <code>NodeTypeDef</code> (using
     * namespace-qualified names).
     *
     * @param definition the definition
     * @return a <code>NodeTypeDef</code>
     * @throws InvalidNodeTypeDefinitionException if the definiton is invalid
     * @throws RepositoryException if a repository error occurs
     */
    private NodeTypeDef toNodeTypeDef(NodeTypeDefinition definition)
            throws InvalidNodeTypeDefinitionException, RepositoryException {
        NodeTypeDef def = new NodeTypeDef();

        // name
        String name = definition.getName();
        if (name == null) {
            throw new InvalidNodeTypeDefinitionException("No node type name specified");
        }
        try {
            def.setName(session.getQName(name));
        } catch (NamespaceException e) {
            throw new InvalidNodeTypeDefinitionException("Invalid name: " + name, e);
        } catch (NameException e) {
            throw new InvalidNodeTypeDefinitionException("Invalid name: " + name, e);
        }

        // supertypes
        String[] names = definition.getDeclaredSupertypeNames();
        Name[] qnames = new Name[names.length];
        for (int i = 0; i < names.length; i++) {
            try {
                qnames[i] = session.getQName(names[i]);
            } catch (NamespaceException e) {
                throw new InvalidNodeTypeDefinitionException("Invalid supertype name: " + names[i], e);
            } catch (NameException e) {
                throw new InvalidNodeTypeDefinitionException("Invalid supertype name: " + names[i], e);
            }
        }
        def.setSupertypes(qnames);

        // primary item
        name = definition.getPrimaryItemName();
        if (name != null) {
            try {
                def.setPrimaryItemName(session.getQName(name));
            } catch (NamespaceException e) {
                throw new InvalidNodeTypeDefinitionException("Invalid primary item name: " + name, e);
            } catch (NameException e) {
                throw new InvalidNodeTypeDefinitionException("Invalid primary item name: " + name, e);
            }
        }

        // misc. flags
        def.setMixin(definition.isMixin());
        def.setAbstract(definition.isAbstract());
        def.setOrderableChildNodes(definition.hasOrderableChildNodes());

        // child nodes
        NodeDefinition[] ndefs = definition.getDeclaredChildNodeDefinitions();
        if (ndefs != null) {
            NodeDef[] qndefs = new NodeDef[ndefs.length];
            for (int i = 0; i < ndefs.length; i++) {
                NodeDefImpl qndef = new NodeDefImpl();
                // declaring node type
                qndef.setDeclaringNodeType(def.getName());
                // name
                name = ndefs[i].getName();
                if (name != null) {
                    if (name.equals("*")) {
                        qndef.setName(ItemDef.ANY_NAME);
                    } else {
                        try {
                            qndef.setName(session.getQName(name));
                        } catch (NamespaceException e) {
                            throw new InvalidNodeTypeDefinitionException("Invalid node name: " + name, e);
                        } catch (NameException e) {
                            throw new InvalidNodeTypeDefinitionException("Invalid node name: " + name, e);
                        }
                    }
                }
                // default primary type
                name = ndefs[i].getDefaultPrimaryTypeName();
                if (name != null) {
                    try {
                        qndef.setDefaultPrimaryType(session.getQName(name));
                    } catch (NamespaceException e) {
                        throw new InvalidNodeTypeDefinitionException("Invalid default primary type: " + name, e);
                    } catch (NameException e) {
                        throw new InvalidNodeTypeDefinitionException("Invalid default primary type: " + name, e);
                    }
                }
                // required primary types
                names = ndefs[i].getRequiredPrimaryTypeNames();
                qnames = new Name[names.length];
                for (int j = 0; j < names.length; j++) {
                    try {
                        qnames[j] = session.getQName(names[j]);
                    } catch (NamespaceException e) {
                        throw new InvalidNodeTypeDefinitionException("Invalid required primary type: " + names[j], e);
                    } catch (NameException e) {
                        throw new InvalidNodeTypeDefinitionException("Invalid required primary type: " + names[j], e);
                    }
                }
                qndef.setRequiredPrimaryTypes(qnames);

                // misc. flags/attributes
                qndef.setAutoCreated(ndefs[i].isAutoCreated());
                qndef.setMandatory(ndefs[i].isMandatory());
                qndef.setProtected(ndefs[i].isProtected());
                qndef.setOnParentVersion(ndefs[i].getOnParentVersion());
                qndef.setAllowsSameNameSiblings(ndefs[i].allowsSameNameSiblings());

                qndefs[i] = qndef;
            }
            def.setChildNodeDefs(qndefs);
        }

        // properties
        PropertyDefinition[] pdefs = definition.getDeclaredPropertyDefinitions();
        if (pdefs != null) {
            PropDef[] qpdefs = new PropDef[pdefs.length];
            for (int i = 0; i < pdefs.length; i++) {
                PropDefImpl qpdef = new PropDefImpl();
                // declaring node type
                qpdef.setDeclaringNodeType(def.getName());
                // name
                name = pdefs[i].getName();
                if (name != null) {
                    if (name.equals("*")) {
                        qpdef.setName(ItemDef.ANY_NAME);
                    } else {
                        try {
                            qpdef.setName(session.getQName(name));
                        } catch (NamespaceException e) {
                            throw new InvalidNodeTypeDefinitionException("Invalid property name: " + name, e);
                        } catch (NameException e) {
                            throw new InvalidNodeTypeDefinitionException("Invalid property name: " + name, e);
                        }
                    }
                }
                // misc. flags/attributes
                int type = pdefs[i].getRequiredType();
                qpdef.setRequiredType(type);
                qpdef.setAutoCreated(pdefs[i].isAutoCreated());
                qpdef.setMandatory(pdefs[i].isMandatory());
                qpdef.setProtected(pdefs[i].isProtected());
                qpdef.setOnParentVersion(pdefs[i].getOnParentVersion());
                qpdef.setMultiple(pdefs[i].isMultiple());
                // value constraints
                String[] constraints = pdefs[i].getValueConstraints();
                if (constraints != null) {
                    QValueConstraint[] qconstraints = new QValueConstraint[constraints.length];
                    for (int j = 0; j < constraints.length; j++) {
                        try {
                            qconstraints[j] = ValueConstraint.create(type, constraints[j], session);
                        } catch (InvalidConstraintException e) {
                            throw new InvalidNodeTypeDefinitionException(
                                    "Invalid value constraint: " + constraints[j], e);
                        }
                    }
                    qpdef.setValueConstraints(qconstraints);
                }
                // default values
                Value[] values = pdefs[i].getDefaultValues();
                if (values != null) {
                    InternalValue[] qvalues = new InternalValue[values.length];
                    for (int j = 0; j < values.length; j++) {
                        try {
                            qvalues[j] = InternalValue.create(values[j], session);
                        } catch (ValueFormatException e) {
                            throw new InvalidNodeTypeDefinitionException(
                                    "Invalid default value format: " + values[j], e);
                        }
                    }
                    qpdef.setDefaultValues(qvalues);
                }

                qpdefs[i] = qpdef;
            }
            def.setPropertyDefs(qpdefs);
        }

        return def;
    }

    //-------------------------------------------------------------< Dumpable >
    /**
     * {@inheritDoc}
     */
    public void dump(PrintStream ps) {
        ps.println("NodeTypeManager (" + this + ")");
        ps.println();
        ntReg.dump(ps);
    }

}
TOP

Related Classes of org.apache.jackrabbit.core.nodetype.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.