AbstractJcrProperty existing = getProperty(name);
if (existing != null) {
// Found an existing property ...
if (existing.isMultiple()) {
// The cardinality of the new values does not match the cardinality of the existing property ...
I18n msg = JcrI18n.unableToSetMultiValuedPropertyUsingSingleValue;
throw new javax.jcr.ValueFormatException(msg.text(readable(name), location(), workspaceName()));
}
JcrPropertyDefinition propertyDefinition = existing.getDefinition();
if (!skipProtectedValidation && propertyDefinition.isProtected()) {
String text = JcrI18n.cannotSetProtectedPropertyValue.text(value, name, location(), workspaceName());
throw new ConstraintViolationException(text);
}
if (!propertyDefinition.canCastToTypeAndSatisfyConstraints(value, session)) {
String defnName = propertyDefinition.getName();
String nodeTypeName = propertyDefinition.getDeclaringNodeType().getName();
I18n msg = JcrI18n.valueViolatesConstraintsOnDefinition;
throw new ConstraintViolationException(msg.text(existing.getName(), value.getString(), location(), defnName,
nodeTypeName));
}
if (propertyDefinition.getRequiredType() == value.getType()) {
// The new value's type and the existing type are the same, so just delegate to the existing JCR property ...
try {
// set the property via the public method, so that additional checks are performed
existing.setValue(value);
} catch (VersionException e) {
if (skipVersioningValidation) {
// the node is checked in, but we should ignore that, so set the property via the protected method
((JcrSingleValueProperty)existing).internalSetValue(value);
} else {
throw e;
}
}
return existing;
}
}
// Otherwise, we have to create the property, so first find a valid property definition ...
SessionCache cache = sessionCache();
MutableCachedNode node = mutable();
Name primaryType = node.getPrimaryType(cache);
Set<Name> mixinTypes = node.getMixinTypes(cache);
NodeTypes nodeTypes = session.nodeTypes();
JcrPropertyDefinition defn = null;
final boolean skipProtected = !skipProtectedValidation;
defn = nodeTypes.findPropertyDefinition(session, primaryType, mixinTypes, name, value, true, skipProtected, true);
if (defn == null) {
// Failed to find a valid property definition,
// so figure out if there's a definition that would work if it had no constraints ...
defn = nodeTypes.findPropertyDefinition(session, primaryType, mixinTypes, name, value, true, skipProtected, false);
String propName = readable(name);
if (defn != null) {
String defnName = defn.getName();
String nodeTypeName = defn.getDeclaringNodeType().getName();
I18n msg = JcrI18n.valueViolatesConstraintsOnDefinition;
throw new ConstraintViolationException(msg.text(propName, value.getString(), location(), defnName, nodeTypeName));
}
I18n msg = JcrI18n.noPropertyDefinition;
throw new ConstraintViolationException(msg.text(propName, location(), readable(primaryType), readable(mixinTypes)));
}
// The 'findBestPropertyDefinition' method checks constraints for all definitions exception those with a
// require type of REFERENCE. This is because checking such constraints may cause unnecessary loading of nodes.
// Therefore, see if this is the case ...
int requiredType = defn.getRequiredType();
if (requiredType == PropertyType.REFERENCE || requiredType == PropertyType.WEAKREFERENCE) {
// Check that the REFERENCE value satisfies the constraints ...
if (!skipReferenceValidation && !defn.canCastToTypeAndSatisfyConstraints(value, session)) {
// The REFERENCE value did not satisfy the constraints ...
String propName = readable(name);
String defnName = defn.getName();
String nodeTypeName = defn.getDeclaringNodeType().getName();
I18n i18n = JcrI18n.weakReferenceValueViolatesConstraintsOnDefinition;
if (requiredType == PropertyType.REFERENCE) i18n = JcrI18n.referenceValueViolatesConstraintsOnDefinition;
throw new ConstraintViolationException(i18n.text(propName, value.getString(), location(), defnName, nodeTypeName));
}
}
if (!skipVersioningValidation && !isCheckedOut()) {
// Node is not checked out, so changing property is only allowed if OPV of property is 'ignore' ...