/*
* Copyright (C) 2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.services.jcr.impl.core;
import org.exoplatform.services.jcr.access.AccessControlEntry;
import org.exoplatform.services.jcr.access.AccessControlList;
import org.exoplatform.services.jcr.access.AccessManager;
import org.exoplatform.services.jcr.access.PermissionType;
import org.exoplatform.services.jcr.core.ExtendedPropertyType;
import org.exoplatform.services.jcr.core.nodetype.ItemDefinitionData;
import org.exoplatform.services.jcr.core.nodetype.NodeTypeData;
import org.exoplatform.services.jcr.core.nodetype.NodeTypeDataManager;
import org.exoplatform.services.jcr.core.nodetype.PropertyDefinitionData;
import org.exoplatform.services.jcr.core.nodetype.PropertyDefinitionDatas;
import org.exoplatform.services.jcr.core.value.ExtendedValue;
import org.exoplatform.services.jcr.dataflow.ItemState;
import org.exoplatform.services.jcr.datamodel.Identifier;
import org.exoplatform.services.jcr.datamodel.InternalQName;
import org.exoplatform.services.jcr.datamodel.ItemData;
import org.exoplatform.services.jcr.datamodel.ItemType;
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.datamodel.ValueData;
import org.exoplatform.services.jcr.impl.Constants;
import org.exoplatform.services.jcr.impl.core.value.BaseValue;
import org.exoplatform.services.jcr.impl.core.value.PathValue;
import org.exoplatform.services.jcr.impl.core.value.PermissionValue;
import org.exoplatform.services.jcr.impl.core.value.ValueConstraintsMatcher;
import org.exoplatform.services.jcr.impl.core.value.ValueFactoryImpl;
import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
import org.exoplatform.services.jcr.impl.dataflow.TransientValueData;
import org.exoplatform.services.jcr.impl.dataflow.ValueDataConvertor;
import org.exoplatform.services.jcr.util.IdGenerator;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.jcr.AccessDeniedException;
import javax.jcr.InvalidItemStateException;
import javax.jcr.Item;
import javax.jcr.ItemNotFoundException;
import javax.jcr.PathNotFoundException;
import javax.jcr.PropertyType;
import javax.jcr.ReferentialIntegrityException;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.ItemDefinition;
import javax.jcr.version.VersionException;
/**
* Created by The eXo Platform SAS.
*
* @author Gennady Azarenkov
* @version $Id: ItemImpl.java 5537 2012-01-27 14:09:27Z andrew.plotnikov $
*/
public abstract class ItemImpl implements Item
{
/**
* Logger.
*/
private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.ItemImpl");
/**
* Session object.
*/
protected final SessionImpl session;
/**
* ItemData object.
*/
protected ItemData data;
/**
* Item JCRPath.
*/
protected JCRPath location;
/**
* Item QPath.
*/
protected QPath qpath;
protected SessionDataManager dataManager;
protected LocationFactory locationFactory;
protected ValueFactoryImpl valueFactory;
/**
* ItemImpl constructor.
*
* @param data ItemData object
* @param session Session object
* @throws RepositoryException if any Exception is occurred
*/
ItemImpl(ItemData data, SessionImpl session) throws RepositoryException
{
this.session = session;
this.data = data;
this.dataManager = session.getTransientNodesManager();
this.locationFactory = session.getLocationFactory();
this.valueFactory = session.getValueFactory();
}
protected void invalidate()
{
this.data = null;
}
/**
* Return a status of the item state. If the state is invalid the item can't
* be used anymore.
*
* @return boolean flag, true if an item is usable in the session.
*/
public boolean isValid()
{
return data != null;
}
/**
* Checking if this item has valid item state, i.e. wasn't removed (and
* saved).
*
* @return true or throws an InvalidItemStateException exception otherwise
* @throws InvalidItemStateException
*/
protected boolean checkValid() throws InvalidItemStateException
{
try
{
// Currently it only warns, but newer jcr versions (1.15+) will throw an exception
session.checkLive();
}
catch (RepositoryException e)
{
throw new InvalidItemStateException("This kind of operation is forbidden after a session.logout().", e);
}
if (data == null)
{
throw new InvalidItemStateException("Invalid item state. Item was removed or discarded.");
}
session.updateLastAccessTime();
return true;
}
/**
* {@inheritDoc}
*/
public String getPath() throws RepositoryException
{
return getLocation().getAsString(false);
}
/**
* {@inheritDoc}
*/
public String getName() throws RepositoryException
{
return getLocation().getName().getAsString();
}
/**
* {@inheritDoc}
*/
public Item getAncestor(int degree) throws ItemNotFoundException, AccessDeniedException, RepositoryException
{
checkValid();
try
{
// 6.2.8 If depth > n is specified then an ItemNotFoundException is
// thrown.
if (degree < 0)
{
throw new ItemNotFoundException("Can't get ancestor with ancestor's degree < 0.");
}
final QPath myPath = getData().getQPath();
int n = myPath.getDepth() - degree;
if (n == 0)
{
return this;
}
else if (n < 0)
{
throw new ItemNotFoundException("Can't get ancestor with ancestor's degree > depth of this item.");
}
else
{
final QPath ancestorPath = myPath.makeAncestorPath(n);
return dataManager.getItem(ancestorPath, true);
}
}
catch (PathNotFoundException e)
{
throw new ItemNotFoundException(e.getMessage(), e);
}
}
/**
* {@inheritDoc}
*/
public NodeImpl getParent() throws ItemNotFoundException, AccessDeniedException, RepositoryException
{
checkValid();
if (isRoot())
{
throw new ItemNotFoundException("Root node does not have a parent");
}
return parent(true);
}
/**
* {@inheritDoc}
*/
public SessionImpl getSession()
{
return session;
}
/**
* {@inheritDoc}
*/
public int getDepth()
{
return qpath.getDepth();
}
/**
* {@inheritDoc}
*/
public boolean isSame(Item otherItem)
{
if (isValid())
{
if (otherItem == null)
{
return false;
}
if (!this.getClass().equals(otherItem.getClass()))
{
return false;
}
try
{
// identifier is not changed on ItemImpl
return getInternalIdentifier().equals(((ItemImpl)otherItem).getInternalIdentifier());
}
catch (Exception e)
{
LOG.debug("Item.isSame() failed " + e.getMessage());
return false;
}
}
return false;
}
/**
* {@inheritDoc}
*/
public boolean isNew()
{
if (isValid())
{
return dataManager.isNew(getInternalIdentifier());
}
// if was removed (is invalid by check), isn't new
return false;
}
/**
* {@inheritDoc}
*/
public boolean isModified()
{
if (isValid())
{
return dataManager.isModified(getData());
}
// if was removed (is invalid by check), was modified
return true;
}
/**
* {@inheritDoc}
*/
public void remove() throws RepositoryException, ConstraintViolationException, VersionException, LockException
{
checkValid();
if (isRoot())
{
throw new RepositoryException("Can't remove ROOT node.");
}
// Check constraints
ItemDefinition def;
if (isNode())
{
def = ((NodeImpl)this).getDefinition();
}
else
{
def = ((PropertyImpl)this).getDefinition();
}
if (def.isMandatory() || def.isProtected())
{
throw new ConstraintViolationException("Can't remove mandatory or protected item " + getPath());
}
NodeImpl parentNode = parent();
// Check if versionable ancestor is not checked-in
if (!parentNode.checkedOut())
{
throw new VersionException("Node " + parent().getPath() + " or its nearest ancestor is checked-in");
}
// Check locking
if (!parentNode.checkLocking())
{
throw new LockException("Node " + parent().getPath() + " is locked ");
}
// launch event
session.getActionHandler().preRemoveItem(this);
removeVersionable();
// remove from datamanager
dataManager.delete(data);
}
/**
* Check when it's a Node and is versionable will a version history removed.
* Case of last version in version history.
*
* @throws RepositoryException
* @throws ConstraintViolationException
* @throws VersionException
*/
protected void removeVersionable() throws RepositoryException, ConstraintViolationException, VersionException
{
if (isNode())
{
NodeTypeDataManager ntManager = session.getWorkspace().getNodeTypesHolder();
NodeData node = (NodeData)data;
if (ntManager.isNodeType(Constants.MIX_VERSIONABLE, node.getPrimaryTypeName(), node.getMixinTypeNames()))
{
ItemData vhpd =
dataManager.getItemData(node, new QPathEntry(Constants.JCR_VERSIONHISTORY, 1), ItemType.PROPERTY);
if (vhpd != null && !vhpd.isNode())
{
try
{
String vhID = new String(((PropertyData)vhpd).getValues().get(0).getAsByteArray());
dataManager.removeVersionHistory(vhID, null, data.getQPath());
}
catch (IOException e)
{
throw new RepositoryException(e);
}
}
else
{
throw new RepositoryException("Version history not found for " + node.getQPath().getAsString());
}
}
}
}
protected PropertyImpl doUpdateProperty(NodeImpl parentNode, InternalQName propertyName, Value propertyValue,
boolean multiValue, int expectedType) throws ValueFormatException, VersionException, LockException,
ConstraintViolationException, RepositoryException
{
Value[] val = null;
if (propertyValue != null)
{
val = new Value[]{propertyValue};
}
return doUpdateProperty(parentNode, propertyName, val, multiValue, expectedType);
}
protected PropertyImpl doUpdateProperty(NodeImpl parentNode, InternalQName propertyName, Value[] propertyValues,
boolean multiValue, int expectedType) throws ValueFormatException, VersionException, LockException,
ConstraintViolationException, RepositoryException
{
// 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 ");
}
QPath qpath = QPath.makeChildPath(parentNode.getInternalPath(), propertyName);
int state;
String identifier;
int version;
PropertyImpl prevProp;
PropertyDefinitionDatas defs;
ItemImpl prevItem =
dataManager.getItem(parentNode.nodeData(), new QPathEntry(propertyName, 0), true,
dataManager.isNew(parentNode.getIdentifier()), ItemType.PROPERTY, false);
NodeTypeDataManager ntm = session.getWorkspace().getNodeTypesHolder();
NodeData parentData = (NodeData)parentNode.getData();
boolean isMultiValue = multiValue;
PropertyImpl prevProperty = null;
if (prevItem == null || prevItem.isNode())
{ // new property
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 AuditPropertyImpl(prevProp.getData(), 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 ConstraintViolationException("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));
}
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, parentNode.nodeData(), 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);
dataManager.delete(newData);
prop = prevProp;
}
return prop;
}
/**
* {@inheritDoc}
*/
public void save() throws ReferentialIntegrityException, AccessDeniedException, LockException,
ConstraintViolationException, InvalidItemStateException, ReferentialIntegrityException, RepositoryException
{
checkValid();
if (isNew())
{
throw new RepositoryException("It is impossible to call save() on the newly added item " + getPath());
}
NodeTypeDataManager ntManager = session.getWorkspace().getNodeTypesHolder();
if (isNode())
{
// validate
// 1. referenceable nodes - if a node is deleted and then added,
// referential integrity is unchanged ('move' usecase)
QPath path = getInternalPath();
List<ItemState> changes = dataManager.getChangesLog().getDescendantsChanges(path);
List<NodeData> refNodes = new ArrayList<NodeData>();
for (int i = 0, length = changes.size(); i < length; i++)
{
ItemState changedItem = changes.get(i);
if (changedItem.isNode())
{
NodeData refNode = (NodeData)changedItem.getData();
// Check referential integrity (remove of mix:referenceable node)
if (ntManager.isNodeType(Constants.MIX_REFERENCEABLE, refNode.getPrimaryTypeName(),
refNode.getMixinTypeNames()))
{
// mix:referenceable
if (changedItem.isDeleted())
{
refNodes.add(refNode); // add to refs (delete - alway is first)
}
else if (changedItem.isAdded() || changedItem.isRenamed())
{
refNodes.remove(refNode); // remove from refs (add - always at the
// end)
}
}
}
}
// check ref changes
for (int i = 0, length = refNodes.size(); i < length; i++)
{
NodeData refNode = refNodes.get(i);
List<PropertyData> nodeRefs = dataManager.getReferencesData(refNode.getIdentifier(), true);
for (int j = 0, length2 = nodeRefs.size(); j < length2; j++)
{
PropertyData refProp = nodeRefs.get(j);
// if ref property is deleted in this session
ItemState refState = dataManager.getChangesLog().getItemState(refProp.getIdentifier());
if (refState != null && refState.isDeleted())
{
continue;
}
NodeData refParent = (NodeData)dataManager.getItemData(refProp.getParentIdentifier());
AccessControlList acl = refParent.getACL();
AccessManager am = session.getAccessManager();
if (!am.hasPermission(acl, PermissionType.READ, session.getUserState().getIdentity()))
{
throw new AccessDeniedException("Can not delete node " + refNode.getQPath() + " ("
+ refNode.getIdentifier() + ")" + ". It is currently the target of a REFERENCE property and "
+ refProp.getQPath().getAsString());
}
throw new ReferentialIntegrityException("Can not delete node " + refNode.getQPath() + " ("
+ refNode.getIdentifier() + ")" + ". It is currently the target of a REFERENCE property "
+ refProp.getQPath().getAsString());
}
}
}
dataManager.commit(getInternalPath());
}
/**
* {@inheritDoc}
*/
public void refresh(boolean keepChanges) throws InvalidItemStateException, RepositoryException
{
checkValid();
if (keepChanges)
{
dataManager.refresh(this.getData());
}
else
{
dataManager.rollback(this.getData());
}
}
// -------------------- Implementation ----------------------
public ItemData getData()
{
return data;
}
/**
* Get identifier of parent item.
*
* @return parent identifier
*/
public String getParentIdentifier()
{
return getData().getParentIdentifier();
}
public QPath getInternalPath()
{
return getData().getQPath();
}
public InternalQName getInternalName()
{
return getData().getQPath().getName();
}
/**
* Get parent node item. Session pool is ignored.
*
* @return parent item
* @throws RepositoryException if parent item is null
*/
protected NodeImpl parent() throws RepositoryException
{
return parent(false);
}
/**
* Get parent node item.
*
* @param pool - take a parent from session pool
* @return parent item
* @throws RepositoryException if parent item is null
*/
protected NodeImpl parent(final boolean pool) throws RepositoryException
{
NodeImpl parent = (NodeImpl)dataManager.getItemByIdentifier(getParentIdentifier(), pool);
if (parent == null)
{
throw new ItemNotFoundException("FATAL: Parent is null for " + getPath() + " parent UUID: "
+ getParentIdentifier());
}
return parent;
}
/**
* Get and return parent node data.
*
* @return parent node data
* @throws RepositoryException if parent item is null
*/
public NodeData parentData() throws RepositoryException
{
checkValid();
NodeData parent = (NodeData)dataManager.getItemData(getData().getParentIdentifier());
if (parent == null)
{
throw new ItemNotFoundException("FATAL: Parent is null for " + getPath() + " parent UUID: "
+ getData().getParentIdentifier());
}
return parent;
}
protected NodeTypeData[] nodeTypes(NodeData node) throws RepositoryException
{
InternalQName primaryTypeName = node.getPrimaryTypeName();
InternalQName[] mixinNames = node.getMixinTypeNames();
NodeTypeData[] nodeTypes = new NodeTypeData[mixinNames.length + 1];
NodeTypeDataManager ntm = session.getWorkspace().getNodeTypesHolder();
nodeTypes[0] = ntm.getNodeType(primaryTypeName);
for (int i = 1; i <= mixinNames.length; i++)
{
nodeTypes[i] = ntm.getNodeType(mixinNames[i - 1]);
}
return nodeTypes;
}
public String getInternalIdentifier()
{
return data.getIdentifier();
}
/**
* Get item JCRPath location.
*
* @return item JCRPath
*/
public JCRPath getLocation() throws RepositoryException
{
if (this.location == null)
{
this.location = session.getLocationFactory().createJCRPath(qpath);
}
return this.location;
}
/**
* Check if item is root.
*
* @return true if item is root and false in other case
*/
public boolean isRoot()
{
return data.getIdentifier().equals(Constants.ROOT_UUID);
}
/**
* Loads data.
*
* @param data source item data
* @throws RepositoryException if errors occurs
*/
abstract void loadData(ItemData data) throws RepositoryException;
/**
* Loads data using existing parent data (used primary and mixin types for
* Item Definition discovery).
*
* @param data source item data
* @param parent NodeData Items's parent
* @throws RepositoryException if errors occurs
*/
abstract void loadData(ItemData data, NodeData parent) throws RepositoryException;
/**
* Returns Item definition data.
*
* @return
*/
abstract ItemDefinitionData getItemDefinitionData();
public boolean hasPermission(String action) throws RepositoryException
{
checkValid();
NodeData ndata;
if (isNode())
{
ndata = (NodeData)getData();
}
else
{
ndata = parentData();
}
return session.getAccessManager().hasPermission(ndata.getACL(), action, session.getUserState().getIdentity());
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj)
{
if (obj instanceof ItemImpl)
{
ItemImpl otherItem = (ItemImpl)obj;
if (!otherItem.isValid() || !this.isValid())
{
return false;
}
try
{
return getInternalIdentifier().equals(otherItem.getInternalIdentifier());
}
catch (Exception e)
{
return false;
}
}
return false;
}
private ValueData valueData(Value value, int type) throws RepositoryException, ValueFormatException
{
if (value == null)
{
return null;
}
switch (type)
{
case PropertyType.STRING :
return new TransientValueData(value.getString());
case PropertyType.BINARY :
ValueData vd;
if (value instanceof BaseValue || value instanceof ExtendedValue)
{
// create Transient copy
vd = ((BaseValue)getSession().getValueFactory().createValue(value.getStream())).getInternalData();
}
else
{
// third part value impl, convert via String
vd =
((BaseValue)getSession().getValueFactory().createValue(value.getString(), PropertyType.BINARY))
.getInternalData();
}
return vd;
case PropertyType.BOOLEAN :
return new TransientValueData(value.getBoolean());
case PropertyType.LONG :
return new TransientValueData(value.getLong());
case PropertyType.DOUBLE :
return new TransientValueData(value.getDouble());
case PropertyType.DATE :
return new TransientValueData(value.getDate());
case PropertyType.PATH :
ValueData pvd;
if (value instanceof PathValue)
{
pvd = ((PathValue)value).getInternalData();
}
else
{
QPath pathValue = locationFactory.parseJCRPath(value.getString()).getInternalPath();
pvd = new TransientValueData(pathValue);
}
return pvd;
case PropertyType.NAME :
InternalQName nameValue = locationFactory.parseJCRName(value.getString()).getInternalName();
return new TransientValueData(nameValue);
case PropertyType.REFERENCE :
Identifier identifier = new Identifier(value.getString());
return new TransientValueData(identifier);
case ExtendedPropertyType.PERMISSION :
PermissionValue permValue = (PermissionValue)value;
AccessControlEntry ace = new AccessControlEntry(permValue.getIdentity(), permValue.getPermission());
return new TransientValueData(ace);
default :
throw new ValueFormatException("ValueFactory.convert() unknown or unconvertable type " + type);
}
}
private void checkValueConstraints(PropertyDefinitionData def, List<ValueData> newValues, int type)
throws RepositoryException
{
ValueConstraintsMatcher constraints =
new ValueConstraintsMatcher(def.getValueConstraints(), session.getLocationFactory(),
session.getTransientNodesManager(), session.getWorkspace().getNodeTypesHolder());
for (ValueData value : newValues)
{
if (!constraints.match(value, type))
{
String strVal = null;
try
{
if (type != PropertyType.BINARY)
{
strVal = ValueDataConvertor.readString(value);
}
else
{
strVal = "PropertyType.BINARY";
}
}
catch (IOException e)
{
LOG.error("Error of value read: " + e.getMessage(), e);
}
throw new ConstraintViolationException("Can not set value '" + strVal + "' to " + getPath()
+ " due to value constraints ");
}
}
}
}