docs: JcrPropertyDefinition findPropertyDefinition( JcrSession session,
                                                    Name primaryTypeName,
                                                    Collection<Name> mixinTypeNames,
                                                    Name propertyName,
                                                    Value value,
                                                    boolean checkMultiValuedDefinitions,
                                                    boolean skipProtected,
                                                    boolean checkTypeAndConstraints ) {
          boolean setToEmpty = value == null;
  
          /*
           * We use this flag to indicate that there was a definition encountered with the same name.  If
           * a named definition (or definitions - for example the same node type could define a LONG and BOOLEAN
           * version of the same property) is encountered and no match is found for the name, then processing should not
           * proceed.  If processing did proceed, a residual definition might be found and matched.  This would
           * lead to a situation where a node defined a type for a named property, but contained a property with
           * the same name and the wrong type.
           */
          boolean matchedOnName = false;
  
          // Look for a single-value property definition on the primary type that matches by name and type ...
          JcrNodeType primaryType = getNodeType(primaryTypeName);
          if (primaryType != null) {
              for (JcrPropertyDefinition definition : primaryType.allSingleValuePropertyDefinitions(propertyName)) {
                  matchedOnName = true;
                  // See if the definition allows the value ...
                  if (skipProtected && definition.isProtected()) return null;
                  if (setToEmpty) {
                      if (!definition.isMandatory()) return definition;
                      // Otherwise this definition doesn't work, so continue with the next ...
                      continue;
                  }
                  assert value != null;
                  // We can use the definition if it matches the type and satisfies the constraints ...
                  int type = definition.getRequiredType();
                  // Don't check constraints on reference properties
                  if (type == PropertyType.REFERENCE && type == value.getType()) return definition;
                  if (type == PropertyType.WEAKREFERENCE && type == value.getType()) return definition;
                  if (type == org.modeshape.jcr.api.PropertyType.SIMPLE_REFERENCE && type == value.getType()) return definition;
                  if (type == PropertyType.UNDEFINED || type == value.getType()) {
                      if (!checkTypeAndConstraints) return definition;
                      if (definition.satisfiesConstraints(value, session)) return definition;
                  }
              }
  
              if (matchedOnName) {
                  if (value != null) {
                      for (JcrPropertyDefinition definition : primaryType.allSingleValuePropertyDefinitions(propertyName)) {
                          // See if the definition allows the value ...
                          if (skipProtected && definition.isProtected()) return null;
                          // Don't check constraints on reference properties
                          int type = definition.getRequiredType();
                          if (type == PropertyType.REFERENCE && definition.canCastToType(value)) {
                              return definition;
                          }
                          if (type == PropertyType.WEAKREFERENCE && definition.canCastToType(value)) {
                              return definition;
                          }
                          if (type == org.modeshape.jcr.api.PropertyType.SIMPLE_REFERENCE && definition.canCastToType(value)) {
                              return definition;
                          }
                          if (!checkTypeAndConstraints) return definition;
                          if (definition.canCastToTypeAndSatisfyConstraints(value, session)) return definition;
                      }
                  }
  
                  if (checkMultiValuedDefinitions) {
                      // Look for a multi-value property definition on the primary type that matches by name and type ...
                      for (JcrPropertyDefinition definition : primaryType.allMultiValuePropertyDefinitions(propertyName)) {
                          // See if the definition allows the value ...
                          if (skipProtected && definition.isProtected()) return null;
                          if (setToEmpty) {
                              if (!definition.isMandatory()) return definition;
                              // Otherwise this definition doesn't work, so continue with the next ...
                              continue;
                          }
                          assert value != null;
                          // We can use the definition if it matches the type and satisfies the constraints ...
                          int type = definition.getRequiredType();
                          // Don't check constraints on reference properties
                          if (type == PropertyType.REFERENCE && type == value.getType()) return definition;
                          if (type == PropertyType.WEAKREFERENCE && type == value.getType()) return definition;
                          if (type == org.modeshape.jcr.api.PropertyType.SIMPLE_REFERENCE && type == value.getType()) return definition;
                          if (type == PropertyType.UNDEFINED || type == value.getType()) {
                              if (!checkTypeAndConstraints) return definition;
                              if (definition.satisfiesConstraints(value, session)) return definition;
                          }
                      }
                      if (value != null) {
                          for (JcrPropertyDefinition definition : primaryType.allMultiValuePropertyDefinitions(propertyName)) {
                              // See if the definition allows the value ...
                              if (skipProtected && definition.isProtected()) return null;
                              assert definition.getRequiredType() != PropertyType.UNDEFINED;
                              // Don't check constraints on reference properties
                              int type = definition.getRequiredType();
                              if (type == PropertyType.REFERENCE && definition.canCastToType(value)) {
                                  return definition;
                              }
                              if (type == PropertyType.WEAKREFERENCE && definition.canCastToType(value)) {
                                  return definition;
                              }
                              if (type == org.modeshape.jcr.api.PropertyType.SIMPLE_REFERENCE && definition.canCastToType(value)) {
                                  return definition;
                              }
                              if (!checkTypeAndConstraints) return definition;
                              if (definition.canCastToTypeAndSatisfyConstraints(value, session)) return definition;
                          }
                      }
                  }
                  return null;
              }
          }
  
          // Look for a single-value property definition on the mixin types that matches by name and type ...
          List<JcrNodeType> mixinTypes = null;
          if (mixinTypeNames != null) {
              mixinTypes = new LinkedList<JcrNodeType>();
              for (Name mixinTypeName : mixinTypeNames) {
                  JcrNodeType mixinType = getNodeType(mixinTypeName);
                  if (mixinType == null) continue;
                  mixinTypes.add(mixinType);
                  for (JcrPropertyDefinition definition : mixinType.allSingleValuePropertyDefinitions(propertyName)) {
                      matchedOnName = true;
                      // See if the definition allows the value ...
                      if (skipProtected && definition.isProtected()) return null;
                      if (setToEmpty) {
                          if (!definition.isMandatory()) return definition;
                          // Otherwise this definition doesn't work, so continue with the next ...
                          continue;
                      }
                      assert value != null;
                      // We can use the definition if it matches the type and satisfies the constraints ...
                      int type = definition.getRequiredType();
                      // Don't check constraints on reference properties
                      if (type == PropertyType.REFERENCE && type == value.getType()) return definition;
                      if (type == PropertyType.WEAKREFERENCE && type == value.getType()) return definition;
                      if (type == org.modeshape.jcr.api.PropertyType.SIMPLE_REFERENCE && type == value.getType()) return definition;
                      if (type == PropertyType.UNDEFINED || type == value.getType()) {
                          if (!checkTypeAndConstraints) return definition;
                          if (definition.satisfiesConstraints(value, session)) return definition;
                      }
                  }
                  if (matchedOnName) {
                      if (value != null) {
                          for (JcrPropertyDefinition definition : mixinType.allSingleValuePropertyDefinitions(propertyName)) {
                              // See if the definition allows the value ...
                              if (skipProtected && definition.isProtected()) return null;
                              assert definition.getRequiredType() != PropertyType.UNDEFINED;
                              // Don't check constraints on reference properties
                              int type = definition.getRequiredType();
                              if (type == PropertyType.REFERENCE && definition.canCastToType(value)) {
                                  return definition;
                              }
                              if (type == PropertyType.WEAKREFERENCE && definition.canCastToType(value)) {
                                  return definition;
                              }
                              if (type == org.modeshape.jcr.api.PropertyType.SIMPLE_REFERENCE && definition.canCastToType(value)) {
                                  return definition;
                              }
                              if (!checkTypeAndConstraints) return definition;
                              if (definition.canCastToTypeAndSatisfyConstraints(value, session)) return definition;
                          }
                      }
  
                      if (checkMultiValuedDefinitions) {
                          for (JcrPropertyDefinition definition : mixinType.allMultiValuePropertyDefinitions(propertyName)) {
                              // See if the definition allows the value ...
                              if (skipProtected && definition.isProtected()) return null;
                              if (setToEmpty) {
                                  if (!definition.isMandatory()) return definition;
                                  // Otherwise this definition doesn't work, so continue with the next ...
                                  continue;
                              }
                              assert value != null;
                              // We can use the definition if it matches the type and satisfies the constraints ...
                              int type = definition.getRequiredType();
                              // Don't check constraints on reference properties
                              if (type == PropertyType.REFERENCE && type == value.getType()) return definition;
                              if (type == PropertyType.WEAKREFERENCE && type == value.getType()) return definition;
                              if (type == org.modeshape.jcr.api.PropertyType.SIMPLE_REFERENCE && type == value.getType()) return definition;
                              if (type == PropertyType.UNDEFINED || type == value.getType()) {
                                  if (!checkTypeAndConstraints) return definition;
                                  if (definition.satisfiesConstraints(value, session)) return definition;
                              }
                          }
                          if (value != null) {
                              for (JcrPropertyDefinition definition : mixinType.allMultiValuePropertyDefinitions(propertyName)) {
                                  matchedOnName = true;
                                  // See if the definition allows the value ...
                                  if (skipProtected && definition.isProtected()) return null;
                                  assert definition.getRequiredType() != PropertyType.UNDEFINED;
                                  // Don't check constraints on reference properties
                                  int type = definition.getRequiredType();
                                  if (type == PropertyType.REFERENCE && definition.canCastToType(value)) {
                                      return definition;
                                  }
                                  if (type == PropertyType.WEAKREFERENCE && definition.canCastToType(value)) {
                                      return definition;
                                  }
                                  if (type == org.modeshape.jcr.api.PropertyType.SIMPLE_REFERENCE
                                      && definition.canCastToType(value)) {
                                      return definition;
                                  }
                                  if (!checkTypeAndConstraints) return definition;
                                  if (definition.canCastToTypeAndSatisfyConstraints(value, session)) return definition;
                              }
                          }
                      }
  
                      return null;
                  }
              }
          }
  
          if (checkMultiValuedDefinitions) {
              if (primaryType != null) {
                  // Look for a multi-value property definition on the primary type that matches by name and type ...
                  for (JcrPropertyDefinition definition : primaryType.allMultiValuePropertyDefinitions(propertyName)) {
                      matchedOnName = true;
                      // See if the definition allows the value ...
                      if (skipProtected && definition.isProtected()) return null;
                      if (setToEmpty) {
                          if (!definition.isMandatory()) return definition;
                          // Otherwise this definition doesn't work, so continue with the next ...
                          continue;
                      }
                      assert value != null;
                      // We can use the definition if it matches the type and satisfies the constraints ...
                      int type = definition.getRequiredType();
                      // Don't check constraints on reference properties
                      if (type == PropertyType.REFERENCE && type == value.getType()) return definition;
                      if (type == PropertyType.WEAKREFERENCE && type == value.getType()) return definition;
                      if (type == org.modeshape.jcr.api.PropertyType.SIMPLE_REFERENCE && type == value.getType()) return definition;
                      if (type == PropertyType.UNDEFINED || type == value.getType()) {
                          if (!checkTypeAndConstraints) return definition;
                          if (definition.satisfiesConstraints(value, session)) return definition;
                      }
                  }
                  if (value != null) {
                      for (JcrPropertyDefinition definition : primaryType.allMultiValuePropertyDefinitions(propertyName)) {
                          matchedOnName = true;
                          // See if the definition allows the value ...
                          if (skipProtected && definition.isProtected()) return null;
                          assert definition.getRequiredType() != PropertyType.UNDEFINED;
                          // Don't check constraints on reference properties
                          int type = definition.getRequiredType();
                          if (type == PropertyType.REFERENCE && definition.canCastToType(value)) {
                              return definition;
                          }
                          if (type == PropertyType.WEAKREFERENCE && definition.canCastToType(value)) {
                              return definition;
                          }
                          if (type == org.modeshape.jcr.api.PropertyType.SIMPLE_REFERENCE && definition.canCastToType(value)) {
                              return definition;
                          }
                          if (!checkTypeAndConstraints) return definition;
                          if (definition.canCastToTypeAndSatisfyConstraints(value, session)) return definition;
                      }
                  }
              }
  
              if (matchedOnName) return null;
  
              if (mixinTypeNames != null) {
                  mixinTypes = new LinkedList<JcrNodeType>();
                  for (Name mixinTypeName : mixinTypeNames) {
                      JcrNodeType mixinType = getNodeType(mixinTypeName);
                      if (mixinType == null) continue;
                      mixinTypes.add(mixinType);
                      for (JcrPropertyDefinition definition : mixinType.allMultiValuePropertyDefinitions(propertyName)) {
                          matchedOnName = true;
                          // See if the definition allows the value ...
                          if (skipProtected && definition.isProtected()) return null;
                          if (setToEmpty) {
                              if (!definition.isMandatory()) return definition;
                              // Otherwise this definition doesn't work, so continue with the next ...
                              continue;
                          }
                          assert value != null;
                          // We can use the definition if it matches the type and satisfies the constraints ...
                          int type = definition.getRequiredType();
                          // Don't check constraints on reference properties
                          if (type == PropertyType.REFERENCE && type == value.getType()) return definition;
                          if (type == PropertyType.WEAKREFERENCE && type == value.getType()) return definition;
                          if (type == org.modeshape.jcr.api.PropertyType.SIMPLE_REFERENCE && type == value.getType()) return definition;
                          if (type == PropertyType.UNDEFINED || type == value.getType()) {
                              if (!checkTypeAndConstraints) return definition;
                              if (definition.satisfiesConstraints(value, session)) return definition;
                          }
                      }
                      if (value != null) {
                          for (JcrPropertyDefinition definition : mixinType.allMultiValuePropertyDefinitions(propertyName)) {
                              matchedOnName = true;
                              // See if the definition allows the value ...
                              if (skipProtected && definition.isProtected()) return null;
                              assert definition.getRequiredType() != PropertyType.UNDEFINED;
                              // Don't check constraints on reference properties
                              int type = definition.getRequiredType();
                              if (type == PropertyType.REFERENCE && definition.canCastToType(value)) {
                                  return definition;
                              }
                              if (type == PropertyType.WEAKREFERENCE && definition.canCastToType(value)) {
                                  return definition;
                              }
                              if (type == org.modeshape.jcr.api.PropertyType.SIMPLE_REFERENCE && definition.canCastToType(value)) {
                                  return definition;
                              }
                              if (!checkTypeAndConstraints) return definition;
                              if (definition.canCastToTypeAndSatisfyConstraints(value, session)) return definition;
                          }
                      }
                  }
              }
              if (matchedOnName) return null;
  
          }
  
          // Nothing was found, so look for residual property definitions ...
          if (!propertyName.equals(JcrNodeType.RESIDUAL_NAME)) return findPropertyDefinition(session, primaryTypeName,
                                                                                             mixinTypeNames,
                                                                                             JcrNodeType.RESIDUAL_NAME, value,
                                                                                             checkMultiValuedDefinitions,
                                                                                             skipProtected, checkTypeAndConstraints);
          return null;
      }