private void validatePropertyDefinition( JcrPropertyDefinition propertyDefinition,
                                             List<Name> supertypes,
                                             List<JcrNodeType> pendingTypes ) throws RepositoryException {
        assert propertyDefinition != null;
        assert supertypes != null;
        assert pendingTypes != null;

        boolean residual = JcrNodeType.RESIDUAL_ITEM_NAME.equals(propertyDefinition.getName());
        if (propertyDefinition.isMandatory() && !propertyDefinition.isProtected() && residual) {
            throw new InvalidNodeTypeDefinitionException(
                                                         JcrI18n.residualPropertyDefinitionsCannotBeMandatory.text(propertyDefinition.getName()));
        }
        if (propertyDefinition.isAutoCreated() && residual) {
            throw new InvalidNodeTypeDefinitionException(
                                                         JcrI18n.residualPropertyDefinitionsCannotBeAutoCreated.text(propertyDefinition.getName()));
        }

        Value[] defaultValues = propertyDefinition.getDefaultValues();
        if (propertyDefinition.isAutoCreated() && !propertyDefinition.isProtected()
            && (defaultValues == null || defaultValues.length == 0)) {
            throw new InvalidNodeTypeDefinitionException(
                                                         JcrI18n.autocreatedPropertyNeedsDefault.text(propertyDefinition.getName(),
                                                                                                      propertyDefinition.getDeclaringNodeType()
                                                                                                                        .getName()));
        }

        if (!propertyDefinition.isMultiple() && (defaultValues != null && defaultValues.length > 1)) {
            throw new InvalidNodeTypeDefinitionException(
                                                         JcrI18n.singleValuedPropertyNeedsSingleValuedDefault.text(propertyDefinition.getName(),
                                                                                                                   propertyDefinition.getDeclaringNodeType()
                                                                                                                                     .getName()));
        }

        Name propName = context.getValueFactories().getNameFactory().create(propertyDefinition.getName());
        propName = propName == null ? JcrNodeType.RESIDUAL_NAME : propName;

        List<JcrPropertyDefinition> propertyDefinitionsFromAncestors = findPropertyDefinitions(supertypes,
                                                                                               propName,
                                                                                               propertyDefinition.isMultiple() ? PropertyCardinality.MULTI_VALUED_ONLY : PropertyCardinality.SINGLE_VALUED_ONLY,
                                                                                               pendingTypes);

        for (JcrPropertyDefinition propertyDefinitionFromAncestor : propertyDefinitionsFromAncestors) {
            if (propertyDefinitionFromAncestor.isProtected()) {
                throw new InvalidNodeTypeDefinitionException(
                                                             JcrI18n.cannotOverrideProtectedDefinition.text(propertyDefinitionFromAncestor.getDeclaringNodeType()
                                                                                                                                          .getName(),
                                                                                                            "property"));
            }

            if (propertyDefinitionFromAncestor.isMandatory() && !propertyDefinition.isMandatory()) {
                throw new InvalidNodeTypeDefinitionException(
                                                             JcrI18n.cannotMakeMandatoryDefinitionOptional.text(propertyDefinitionFromAncestor.getDeclaringNodeType()
                                                                                                                                              .getName(),
                                                                                                                "property"));

            }

            if (!propertyDefinition.isAsOrMoreConstrainedThan(propertyDefinitionFromAncestor, context)) {
                throw new InvalidNodeTypeDefinitionException(
                                                             JcrI18n.constraintsChangedInSubtype.text(propName,
                                                                                                      propertyDefinitionFromAncestor.getDeclaringNodeType()
                                                                                                                                    .getName()));
            }

            if (!isAlwaysSafeConversion(propertyDefinition.getRequiredType(), propertyDefinitionFromAncestor.getRequiredType())) {
                throw new InvalidNodeTypeDefinitionException(
                                                             JcrI18n.cannotRedefineProperty.text(propName,
                                                                                                 org.modeshape.jcr.api.PropertyType.nameFromValue(propertyDefinition.getRequiredType()),
                                                                                                 propertyDefinitionFromAncestor.getDeclaringNodeType()
                                                                                                                               .getName(),
                                                                                                 org.modeshape.jcr.api.PropertyType.nameFromValue(propertyDefinitionFromAncestor.getRequiredType())));

            }
        }
    }
private void validatePropertyDefinition ( JcrPropertyDefinition propertyDefinition , List < Name > supertypes , List < JcrNodeType > pendingTypes ) throws RepositoryException { assert propertyDefinition != null ; assert supertypes != null ; assert pendingTypes != null ; boolean residual = JcrNodeType . RESIDUAL_ITEM_NAME . equals ( propertyDefinition . getName ( ) ) ; if ( propertyDefinition . isMandatory ( ) && ! propertyDefinition . isProtected ( ) && residual ) { throw new InvalidNodeTypeDefinitionException ( JcrI18n . residualPropertyDefinitionsCannotBeMandatory . text ( propertyDefinition . getName ( ) ) ) ; } if ( propertyDefinition . isAutoCreated ( ) && residual ) { throw new InvalidNodeTypeDefinitionException ( JcrI18n . residualPropertyDefinitionsCannotBeAutoCreated . text ( propertyDefinition . getName ( ) ) ) ; } Value [ ] defaultValues = propertyDefinition . getDefaultValues ( ) ; if ( propertyDefinition . isAutoCreated ( ) && ! propertyDefinition . isProtected ( ) && ( defaultValues == null || defaultValues . length == 0 ) ) { throw new InvalidNodeTypeDefinitionException ( JcrI18n . autocreatedPropertyNeedsDefault . text ( propertyDefinition . getName ( ) , propertyDefinition . getDeclaringNodeType ( ) . getName ( ) ) ) ; } if ( ! propertyDefinition . isMultiple ( ) && ( defaultValues != null && defaultValues . length > 1 ) ) { throw new InvalidNodeTypeDefinitionException ( JcrI18n . singleValuedPropertyNeedsSingleValuedDefault . text ( propertyDefinition . getName ( ) , propertyDefinition . getDeclaringNodeType ( ) . getName ( ) ) ) ; } Name propName = context . getValueFactories ( ) . getNameFactory ( ) . create ( propertyDefinition . getName ( ) ) ; propName = propName == null ? JcrNodeType . RESIDUAL_NAME : propName ; List < JcrPropertyDefinition > propertyDefinitionsFromAncestors = findPropertyDefinitions ( supertypes , propName , propertyDefinition . isMultiple ( ) ? PropertyCardinality . MULTI_VALUED_ONLY : PropertyCardinality . SINGLE_VALUED_ONLY , pendingTypes ) ; for ( JcrPropertyDefinition propertyDefinitionFromAncestor : propertyDefinitionsFromAncestors ) { if ( propertyDefinitionFromAncestor . isProtected ( ) ) { throw new InvalidNodeTypeDefinitionException ( JcrI18n . cannotOverrideProtectedDefinition . text ( propertyDefinitionFromAncestor . getDeclaringNodeType ( ) . getName ( ) , "property" ) ) ; } if ( propertyDefinitionFromAncestor . isMandatory ( ) && ! propertyDefinition . isMandatory ( ) ) { throw new InvalidNodeTypeDefinitionException ( JcrI18n . cannotMakeMandatoryDefinitionOptional . text ( propertyDefinitionFromAncestor . getDeclaringNodeType ( ) . getName ( ) , "property" ) ) ; } if ( ! propertyDefinition . isAsOrMoreConstrainedThan ( propertyDefinitionFromAncestor , context ) ) { throw new InvalidNodeTypeDefinitionException ( JcrI18n . constraintsChangedInSubtype . text ( propName , propertyDefinitionFromAncestor . getDeclaringNodeType ( ) . getName ( ) ) ) ; } if ( ! isAlwaysSafeConversion ( propertyDefinition . getRequiredType ( ) , propertyDefinitionFromAncestor . getRequiredType ( ) ) ) { throw new InvalidNodeTypeDefinitionException ( JcrI18n . cannotRedefineProperty . text ( propName , org . modeshape . jcr . api . PropertyType . nameFromValue ( propertyDefinition . getRequiredType ( ) ) , propertyDefinitionFromAncestor . getDeclaringNodeType ( ) . getName ( ) , org . modeshape . jcr . api . PropertyType . nameFromValue ( propertyDefinitionFromAncestor . getRequiredType ( ) ) ) ) ; } } }
Validates that the given property definition is valid under the ModeShape and JCR type rules within the given context.
<p>
ModeShape considers a property definition valid if it meets these criteria:
<ol>
<li>Residual properties cannot be mandatory</li>
<li>If the property is auto-created, it must specify a default value</li>
<li>If the property is single-valued, it can only specify a single default value</li>
<li>If the property overrides an existing property definition from a supertype, the new definition must be mandatory if the
old definition was mandatory</li>
<li>The property cannot override an existing property definition from a supertype if the ancestor definition is protected</li>
<li>If the property overrides an existing property definition from a supertype, the new definition must have the same
required type as the old definition or a required type that can ALWAYS be cast to the required type of the ancestor (see
section 3.6.4 of the JCR 2.0 specification)</li>
</ol>
Note that an empty set of properties would meet the criteria above.
</p>

@param propertyDefinition the property definition to be validated
@param supertypes the names of the supertypes of the node type to which this property belongs
@param pendingTypes the list of types previously registered in this batch but not yet committed to the repository
@throws RepositoryException if the property definition is not valid