synchronized void internalMerge()

in jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/EffectiveNodeTypeImpl.java [500:670]


    synchronized void internalMerge(EffectiveNodeTypeImpl other, boolean supertype)
            throws ConstraintViolationException {
        Name[] nta = other.getAllNodeTypes();
        int includedCount = 0;
        for (int i = 0; i < nta.length; i++) {
            if (includesNodeType(nta[i])) {
                // redundant node type
                log.debug("node type '" + nta[i] + "' is already contained.");
                includedCount++;
            }
        }
        if (includedCount == nta.length) {
            // total overlap, ignore
            return;
        }

        // named item definitions
        QItemDefinition[] defs = other.getNamedItemDefs();
        for (int i = 0; i < defs.length; i++) {
            QItemDefinition qDef = defs[i];
            if (includesNodeType(qDef.getDeclaringNodeType())) {
                // ignore redundant definitions
                continue;
            }
            Name name = qDef.getName();
            List<QItemDefinition> existingDefs = namedItemDefs.get(name);
            if (existingDefs != null) {
                if (existingDefs.size() > 0) {
                    // there already exists at least one definition with that name
                    for (int j = 0; j < existingDefs.size(); j++) {
                        QItemDefinition qItemDef = existingDefs.get(j);
                        // make sure none of them is auto-create
                        if (qDef.isAutoCreated() || qItemDef.isAutoCreated()) {
                            // conflict
                            String msg = "The item definition for '" + name
                                    + "' in node type '"
                                    + qDef.getDeclaringNodeType()
                                    + "' conflicts with the one of node type '"
                                    + qItemDef.getDeclaringNodeType()
                                    + "': name collision with auto-create definition";
                            log.debug(msg);
                            throw new ConstraintViolationException(msg);
                        }
                        // check ambiguous definitions
                        if (qDef.definesNode() == qItemDef.definesNode()) {
                            if (!qDef.definesNode()) {
                                // property definition
                                QPropertyDefinition pd = (QPropertyDefinition) qDef;
                                QPropertyDefinition epd = (QPropertyDefinition) qItemDef;
                                // compare type & multiValued flag
                                if (pd.getRequiredType() == epd.getRequiredType()
                                        && pd.isMultiple() == epd.isMultiple()) {
                                    // conflict
                                    String msg = "The property definition for '"
                                            + name + "' in node type '"
                                            + qDef.getDeclaringNodeType()
                                            + "' conflicts with the one of node type '"
                                            + qItemDef.getDeclaringNodeType()
                                            + "': ambiguous property definition. "
                                            + "they must differ in required type "
                                            + "or cardinality.";
                                    log.debug(msg);
                                    throw new ConstraintViolationException(msg);
                                }
                            } else {
                                // child node definition
                                // conflict
                                String msg = "The child node definition for '"
                                        + name + "' in node type '"
                                        + qDef.getDeclaringNodeType()
                                        + "' conflicts with the one of node type '"
                                        + qItemDef.getDeclaringNodeType()
                                        + "': ambiguous child node definition. name must differ.";
                                log.debug(msg);
                                throw new ConstraintViolationException(msg);
                            }
                        }
                    }
                }
            } else {
                existingDefs = new ArrayList<QItemDefinition>();
                namedItemDefs.put(name, existingDefs);
            }
            existingDefs.add(qDef);
        }

        // residual item definitions
        defs = other.getUnnamedItemDefs();
        for (int i = 0; i < defs.length; i++) {
            QItemDefinition qDef = defs[i];
            if (includesNodeType(qDef.getDeclaringNodeType())) {
                // ignore redundant definitions
                continue;
            }
            for (QItemDefinition existing : unnamedItemDefs) {
                // compare with existing definition
                if (qDef.definesNode() == existing.definesNode()) {
                    if (!qDef.definesNode()) {
                        // property definition
                        QPropertyDefinition pd = (QPropertyDefinition) qDef;
                        QPropertyDefinition epd = (QPropertyDefinition) existing;
                        // compare type & multiValued flag
                        if (pd.getRequiredType() == epd.getRequiredType()
                                && pd.isMultiple() == epd.isMultiple()
                                && pd.getOnParentVersion() == epd.getOnParentVersion()) {
                            // conflict
                            // TODO: need to take more aspects into account
                            // TODO: getMatchingPropDef needs to check this as well
                            String msg = "A property definition in node type '"
                                    + qDef.getDeclaringNodeType()
                                    + "' conflicts with node type '"
                                    + existing.getDeclaringNodeType()
                                    + "': ambiguous residual property definition";
                            log.debug(msg);
                            throw new ConstraintViolationException(msg);
                        }
                    } else {
                        // child node definition
                        QNodeDefinition nd = (QNodeDefinition) qDef;
                        QNodeDefinition end = (QNodeDefinition) existing;
                        // compare required & default primary types
                        if (Arrays.equals(nd.getRequiredPrimaryTypes(), end.getRequiredPrimaryTypes())
                                && (nd.getDefaultPrimaryType() == null
                                ? end.getDefaultPrimaryType() == null
                                : nd.getDefaultPrimaryType().equals(end.getDefaultPrimaryType()))) {
                            // conflict
                            String msg = "A child node definition in node type '"
                                    + qDef.getDeclaringNodeType()
                                    + "' conflicts with node type '"
                                    + existing.getDeclaringNodeType()
                                    + "': ambiguous residual child node definition";
                            log.debug(msg);
                            throw new ConstraintViolationException(msg);
                        }
                    }
                }
            }
            unnamedItemDefs.add(qDef);
        }
        for (int i = 0; i < nta.length; i++) {
            allNodeTypes.add(nta[i]);
        }

        if (supertype) {
            // implicit merge as result of inheritance

            // add other merged node types as supertypes
            nta = other.getMergedNodeTypes();
            for (int i = 0; i < nta.length; i++) {
                inheritedNodeTypes.add(nta[i]);
            }
            // add supertypes of other merged node types as supertypes
            nta = other.getInheritedNodeTypes();
            for (int i = 0; i < nta.length; i++) {
                inheritedNodeTypes.add(nta[i]);
            }
        } else {
            // explicit merge

            // merge with other merged node types
            nta = other.getMergedNodeTypes();
            for (int i = 0; i < nta.length; i++) {
                mergedNodeTypes.add(nta[i]);
            }
            // add supertypes of other merged node types as supertypes
            nta = other.getInheritedNodeTypes();
            for (int i = 0; i < nta.length; i++) {
                inheritedNodeTypes.add(nta[i]);
            }
        }
    }