identifier = IdGenerator.generate();
version = -1;
if (propertyValues == null)
{
// new property null values;
TransientPropertyData nullData =
new TransientPropertyData(qpath, identifier, version, PropertyType.UNDEFINED,
parentNode.getInternalIdentifier(), isMultiValue);
PropertyImpl nullProperty = new PropertyImpl(nullData, session);
nullProperty.invalidate();
return nullProperty;
}
defs =
ntm.getPropertyDefinitions(propertyName, parentData.getPrimaryTypeName(), parentData.getMixinTypeNames());
prevProp = null;
state = ItemState.ADDED;
}
else
{
// update of the property
prevProp = (PropertyImpl)prevItem;
prevProperty = new PropertyImpl(prevProp.getData(), prevProp.parentData(), prevProp.getSession());
isMultiValue = prevProp.isMultiValued();
defs =
ntm.getPropertyDefinitions(propertyName, parentData.getPrimaryTypeName(), parentData.getMixinTypeNames());
identifier = prevProp.getInternalIdentifier();
version = prevProp.getData().getPersistedVersion();
if (propertyValues == null)
{
state = ItemState.DELETED;
}
else
{
state = ItemState.UPDATED;
}
}
if (defs == null || defs.getAnyDefinition() == null)
{
throw new RepositoryException("Property definition '" + propertyName.getAsString() + "' is not found.");
}
PropertyDefinitionData def = defs.getDefinition(isMultiValue);
if (def != null && def.isProtected())
{
throw new ConstraintViolationException("Can not set protected property "
+ locationFactory.createJCRPath(qpath).getAsString(false));
}
if (multiValue && (def == null || (prevProp != null && !prevProp.isMultiValued())))
{
throw new ValueFormatException("Can not assign multiple-values Value to a single-valued property "
+ locationFactory.createJCRPath(qpath).getAsString(false));
}
if (!multiValue && (def == null || (prevProp != null && prevProp.isMultiValued())))
{
throw new ValueFormatException("Can not assign single-value Value to a multiple-valued property "
+ locationFactory.createJCRPath(qpath).getAsString(false));
}
// Check if checked-in (versionable)
if (!parentNode.checkedOut())
{
throw new VersionException("Node " + parentNode.getPath() + " or its nearest ancestor is checked-in");
}
// Check is locked
if (!parentNode.checkLocking())
{
throw new LockException("Node " + parentNode.getPath() + " is locked ");
}
List<ValueData> valueDataList = new ArrayList<ValueData>();
// cast to required type if neccessary
int requiredType = def.getRequiredType();
int propType = requiredType;
// if list of values not null
if (propertyValues != null)
{
// All Value objects in the array must be of the same type, otherwise a
// ValueFormatException is thrown.
if (propertyValues.length > 1)
{
if (propertyValues[0] != null)
{
int vType = propertyValues[0].getType();
for (Value val : propertyValues)
{
if (val != null && vType != val.getType())
{
throw new ValueFormatException("All Value objects in the array must be of the same type");
}
}
}
}
// if value count >0 and original type not UNDEFINED
if (propertyValues.length > 0 && requiredType == PropertyType.UNDEFINED)
{
// if type what we expected to be UNDEFINED
// set destination type = type of values else type expectedType
if (expectedType == PropertyType.UNDEFINED)
{
for (Value val : propertyValues)
{
if (val != null)
{
expectedType = val.getType();
break;
}
}
}
propType = expectedType;
}
// fill datas and also remove null values and reorder values
for (Value value : propertyValues)
{
if (value != null)
{
valueDataList.add(valueData(value, propType));
}
else
{
if (log.isDebugEnabled())
{
log.debug("Set null value (" + getPath() + ", multivalued: " + multiValue + ")");
}
}
}
}
// Check value constraints
checkValueConstraints(def, valueDataList, propType);
if (requiredType != PropertyType.UNDEFINED && expectedType != PropertyType.UNDEFINED
&& requiredType != expectedType)
{
throw new ConstraintViolationException(" the type parameter "
+ ExtendedPropertyType.nameFromValue(expectedType) + " and the "
+ "type of the property do not match required type" + ExtendedPropertyType.nameFromValue(requiredType));
}
PropertyImpl prop;
if (state != ItemState.DELETED)
{
// add or update
TransientPropertyData newData =
new TransientPropertyData(qpath, identifier, version, propType, parentNode.getInternalIdentifier(),
multiValue, valueDataList);
ItemState itemState = new ItemState(newData, state, true, qpath, false);
prop = (PropertyImpl)dataManager.update(itemState, true);
// launch event: post-set
session.getActionHandler().postSetProperty(prevProperty, prop, state);
}
else
{
if (def.isMandatory())
{
throw new ConstraintViolationException("Can not remove (by setting null value) mandatory property "
+ locationFactory.createJCRPath(qpath).getAsString(false));
}
TransientPropertyData newData =
new TransientPropertyData(qpath, identifier, version, propType, parentNode.getInternalIdentifier(),
multiValue);
// launch event: pre-remove
session.getActionHandler().preRemoveItem(prevProp);