package org.etk.orm.core; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.jcr.Node; import javax.jcr.Property; import javax.jcr.RepositoryException; import javax.jcr.UnsupportedRepositoryOperationException; import javax.jcr.Value; import javax.jcr.ValueFactory; import org.etk.orm.api.NoSuchPropertyException; import org.etk.orm.api.ORMIOException; import org.etk.orm.api.Status; import org.etk.orm.api.UndeclaredRepositoryException; import org.etk.orm.plugins.bean.type.TypeConversionException; import org.etk.orm.plugins.common.CloneableInputStream; import org.etk.orm.plugins.jcr.NodeTypeInfo; import org.etk.orm.plugins.jcr.type.PrimaryTypeInfo; import org.etk.orm.plugins.jcr.type.PropertyDefinitionInfo; import org.etk.orm.plugins.vt2.ValueDefinition; class PersistentEntityContextState extends EntityContextState { /** . */ private final DomainSession session; /** . */ private final Map<String, Object> propertyCache; /** . */ private final Node node; /** . */ private final PrimaryTypeInfo typeInfo; PersistentEntityContextState(Node node, DomainSession session) throws RepositoryException { this.session = session; this.propertyCache = session.domain.propertyCacheEnabled ? new HashMap<String, Object>() : null; this.node = node; this.typeInfo = session.domain.nodeInfoManager.getPrimaryTypeInfo(node.getPrimaryNodeType()); } String getId() { try { return node.getUUID(); } catch (UnsupportedRepositoryOperationException e) { return null; } catch (RepositoryException e) { throw new UndeclaredRepositoryException(e); } } String getPath() { try { return node.getPath(); } catch (RepositoryException e) { throw new UndeclaredRepositoryException(e); } } String getLocalName() { try { return node.getName(); } catch (RepositoryException e) { throw new UndeclaredRepositoryException(e); } } Node getNode() { return node; } DomainSession getSession() { return session; } Status getStatus() { return Status.PERSISTENT; } @Override PrimaryTypeInfo getTypeInfo() { return typeInfo; } <V> V getPropertyValue(NodeTypeInfo nodeTypeInfo, String propertyName, ValueDefinition<?, V> vt) { try { // PropertyDefinitionInfo def = nodeTypeInfo.findPropertyDefinition(propertyName); if (def == null) { throw new NoSuchPropertyException("Property " + propertyName + " cannot be loaded from node " + node.getPath() + " with type " + node.getPrimaryNodeType().getName()); } // V value = null; // if (propertyCache != null) { // That must be ok value = (V)propertyCache.get(propertyName); } // if (value == null) { Value jcrValue; Property property = session.getSessionWrapper().getProperty(node, propertyName); if (property != null) { if (def.isMultiple()) { Value[] values = property.getValues(); if (values.length == 0) { jcrValue = null; } else { jcrValue = values[0]; } } else { jcrValue = property.getValue(); } } else { jcrValue = null; } // if (jcrValue != null) { // We use the type from the real value itself when no one was provided if (vt == null) { vt = (ValueDefinition<?, V>)ValueDefinition.get(jcrValue.getType()); } // value = vt.get(jcrValue); // if (propertyCache != null) { if (value instanceof InputStream) { try { value = (V)new CloneableInputStream((InputStream)value); } catch (IOException e) { throw new AssertionError(e); } } } } } // if (value == null) { if (vt != null) { // Let's try default value List<V> defaultValue = vt.getDefaultValue(); // if (defaultValue != null && defaultValue.size() > 0) { value = defaultValue.get(0); } // if (value == null && vt.isPrimitive()) { throw new NullPointerException("Cannot convert null to primitive type " + vt); } } } else { if (propertyCache != null) { if (value instanceof InputStream) { value = (V)((CloneableInputStream)value).clone(); } else if (value instanceof Date) { value = (V)((Date)value).clone(); } } } // return value; } catch (RepositoryException e) { throw new UndeclaredRepositoryException(e); } } <V> List<V> getPropertyValues(NodeTypeInfo nodeTypeInfo, String propertyName, ValueDefinition<?, V> vt, ListType listType) { try { PropertyDefinitionInfo def = nodeTypeInfo.findPropertyDefinition(propertyName); if (def == null) { throw new NoSuchPropertyException("Property " + propertyName + " cannot be from from node " + node.getPath() + " with type " + node.getPrimaryNodeType().getName()); } // Value[] values; Property property = session.getSessionWrapper().getProperty(node, propertyName); if (property != null) { if (def.isMultiple()) { values = property.getValues(); } else { values = new Value[]{property.getValue()}; } } else { values = null; } // Try to determine a vt from the real value if (vt == null) { vt = (ValueDefinition<?, V>)ValueDefinition.get(def.getType()); if (vt == null) { if (values != null && values.length > 0) { vt = (ValueDefinition<?, V>)ValueDefinition.get(values[0].getType()); } } } // List<V> list; if (vt != null) { if (values != null) { list = listType.create(vt, values.length); for (int i = 0;i < values.length;i++) { Value value = values[i]; V v = vt.get(value); list.set(i, v); } } else { List<V> defaultValue = vt.getDefaultValue(); if (defaultValue != null) { if (def.isMultiple()) { list = listType.create(vt, defaultValue.size()); for (int i = 0;i < defaultValue.size();i++) { V v = defaultValue.get(i); list.set(i, v); } } else { if (defaultValue.size() > 0) { list = listType.create(vt, 1); list.set(0, defaultValue.get(0)); } else { list = listType.create(vt, 0); } } } else { list = null; } } } else { if (listType == ListType.LIST) { list = new ArrayList<V>(); } else { throw new AssertionError("this case is not possible"); } } // return list; } catch (RepositoryException e) { throw new UndeclaredRepositoryException(e); } } <V> void setPropertyValue(NodeTypeInfo nodeTypeInfo, String propertyName, ValueDefinition<?, V> vt, V propertyValue) { try { // PropertyDefinitionInfo def = nodeTypeInfo.findPropertyDefinition(propertyName); // if (def == null) { throw new NoSuchPropertyException("Property " + propertyName + " cannot be set on node " + node.getPath() + " with type " + node.getPrimaryNodeType().getName()); } // if (propertyCache != null) { if (propertyValue instanceof InputStream && (propertyValue instanceof CloneableInputStream)) { try { propertyValue = (V)new CloneableInputStream((InputStream)propertyValue); } catch (IOException e) { throw new ORMIOException("Could not read stream", e); } } } // Value jcrValue; if (propertyValue != null) { // if (vt == null) { // We try first the definition type vt = (ValueDefinition<?, V>)ValueDefinition.get(def.getType()); // We had a undefined type so we are going to use a type based on the provided value if (vt == null) { vt = (ValueDefinition<?, V>)ValueDefinition.get(propertyValue); } // if (vt == null) { throw new TypeConversionException("Cannot convert object " + propertyValue + " no converter found"); } } // int expectedType = def.getType(); // ValueFactory valueFactory = session.sessionWrapper.getSession().getValueFactory(); jcrValue = vt.get(valueFactory, expectedType, propertyValue); } else { jcrValue = null; } // if (def.isMultiple()) { if (jcrValue == null) { node.setProperty(propertyName, new Value[0]); } else { node.setProperty(propertyName, new Value[]{jcrValue}); } } else { node.setProperty(propertyName, jcrValue); } // if (propertyCache != null) { if (propertyValue != null) { if (propertyValue instanceof InputStream) { CloneableInputStream stream = ((CloneableInputStream)propertyValue); propertyValue = (V)stream.clone(); } else if (propertyValue instanceof Date) { propertyValue = (V)((Date)propertyValue).clone(); } propertyCache.put(propertyName, propertyValue); } else { propertyCache.remove(propertyName); } } } catch (RepositoryException e) { throw new UndeclaredRepositoryException(e); } } <V> void setPropertyValues(NodeTypeInfo nodeTypeInfo, String propertyName, ValueDefinition<?, V> vt, ListType listType, List<V> propertyValues) { try { PropertyDefinitionInfo def = nodeTypeInfo.findPropertyDefinition(propertyName); if (def == null) { throw new NoSuchPropertyException("Property " + propertyName + " cannot be set on node " + node.getPath() + " with type " + node.getPrimaryNodeType().getName()); } // Value[] jcrValues; if (propertyValues != null) { if (propertyValues.isEmpty()) { jcrValues = new Value[0]; } else { // Determine vt if null if (vt == null) { // We try first the definition type vt = (ValueDefinition<?, V>)ValueDefinition.get(def.getType()); // if (vt == null) { Object propertyValue = propertyValues.get(0); vt = (ValueDefinition<?, V>)ValueDefinition.get(propertyValue); if (vt == null) { throw new TypeConversionException("Cannot convert object " + propertyValue + " no converter found"); } } } // ValueFactory valueFactory = session.sessionWrapper.getSession().getValueFactory(); int size = propertyValues.size(); jcrValues = new Value[size]; for (int i = 0;i < size;i++) { V element = propertyValues.get(i); Value jcrValue = vt.get(valueFactory, def.getType(), element); jcrValues[i] = jcrValue; } } } else { jcrValues = null; } // if (jcrValues != null) { if (def.isMultiple()) { node.setProperty(propertyName, jcrValues); } else { if (jcrValues.length > 1) { throw new IllegalArgumentException("Cannot update with an array of length greater than 1"); } else if (jcrValues.length == 1) { node.setProperty(propertyName, jcrValues[0]); } else { node.setProperty(propertyName, (Value)null); } } } else { if (def.isMultiple()) { node.setProperty(propertyName, (Value[])null); } else { node.setProperty(propertyName, (Value)null); } } } catch (RepositoryException e) { throw new UndeclaredRepositoryException(e); } } public String toString() { return "ObjectStatus[path=" + getPath() + ",status=" + Status.PERSISTENT + "]"; } }