/* * Copyright (C) 2003-2011 eXo Platform SAS. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.etk.model.core; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.jcr.RepositoryException; import org.etk.model.core.entity.EntityTypeInfo; import org.etk.model.plugins.entity.binder.ObjectBinder; import org.etk.model.plugins.instrument.MethodHandler; import org.etk.model.plugins.vt2.ValueDefinition; import org.etk.orm.api.ORMIOException; import org.etk.orm.api.UndeclaredRepositoryException; import org.etk.orm.core.ListType; import org.etk.orm.plugins.common.CloneableInputStream; /** * Created by The eXo Platform SAS * Author : eXoPlatform * exo@exoplatform.com * Jul 15, 2011 */ public abstract class ObjectContext<O extends ObjectContext<O>> implements MethodHandler { /** . */ private final Map<String, Object> propertyCache; public abstract ObjectBinder<O> getMapper(); public abstract Object getObject(); public abstract EntityContext getEntity(); public ObjectContext() { this.propertyCache = new HashMap<String, Object>(); } /** * Returns the type info associated with the context. Null is returned when the context is in transient * state, otherwise the type info of the corresponding node is returned. * * @return the type info */ public abstract EntityTypeInfo getTypeInfo(); public abstract EntitySession getSession(); public final Object invoke(Object o, Method method) throws Throwable { MethodInvoker<O> invoker = getMapper().getInvoker(method); if (invoker != null) { return invoker.invoke((O)this); } else { throw createCannotInvokeError(method); } } public final Object invoke(Object o, Method method, Object arg) throws Throwable { MethodInvoker<O> invoker = getMapper().getInvoker(method); if (invoker != null) { return invoker.invoke((O)this, arg); } else { throw createCannotInvokeError(method, arg); } } public final Object invoke(Object o, Method method, Object[] args) throws Throwable { MethodInvoker<O> invoker = getMapper().getInvoker(method); if (invoker != null) { switch (args.length) { case 0: return invoker.invoke((O)this); case 1: return invoker.invoke((O)this, args[0]); default: return invoker.invoke((O)this, args); } } else { throw createCannotInvokeError(method, (Object[])args); } } private AssertionError createCannotInvokeError(Method method, Object... args) { StringBuilder msg = new StringBuilder("Cannot invoke method ").append(method.getName()).append("("); Class[] parameterTypes = method.getParameterTypes(); for (int i = 0;i < parameterTypes.length;i++) { if (i > 0) { msg.append(','); } msg.append(parameterTypes[i].getName()); } msg.append(") with arguments ("); for (int i = 0;i < args.length;i++) { if (i > 0) { msg.append(','); } msg.append(String.valueOf(args[i])); } msg.append(")"); return new AssertionError(msg); } public final <V> V getPropertyValue(String propertyName, ValueDefinition<?, V> type) throws RepositoryException { EntityTypeInfo typeInfo = getTypeInfo(); return getPropertyValue(typeInfo, propertyName, type); } public final <V> List<V> getPropertyValues(String propertyName, ValueDefinition<?, V> simpleType, ListType listType) throws RepositoryException { // EntityTypeInfo typeInfo = getTypeInfo(); return getPropertyValues(typeInfo, propertyName, simpleType, listType); } public final <V> void setPropertyValue(String propertyName, ValueDefinition<?, V> type, V o) throws RepositoryException { Object object = getObject(); EntityTypeInfo typeInfo = getTypeInfo(); // if (o instanceof InputStream) { CloneableInputStream in; try { in = new CloneableInputStream((InputStream)o); } catch (IOException e) { throw new ORMIOException("Could not read stream", e); } @SuppressWarnings("unchecked") V v = (V)in; setPropertyValue(typeInfo, propertyName, type, v); } else { setPropertyValue(typeInfo, propertyName, type, o); } } public final <V> void setPropertyValues(String propertyName, ValueDefinition<?, V> type, ListType listType, List<V> objects) throws RepositoryException { // EntityTypeInfo typeInfo = getTypeInfo(); // setPropertyValues(typeInfo, propertyName, type, listType, objects); } /** * * @param <V> * @param entityTypeInfo * @param propertyName * @param vt * @return */ private <V> V getPropertyValue(EntityTypeInfo entityTypeInfo, String propertyName, ValueDefinition<?, V> vt) { try { // V value = null; // if (propertyCache != null) { // That must be ok value = (V)propertyCache.get(propertyName); } // if (value == null) { Object propertyValue = entityTypeInfo.getValue(propertyName); vt = (ValueDefinition<?, V>)ValueDefinition.get(propertyValue); value = vt.getValue(propertyValue); } // return value; } catch (RepositoryException e) { throw new UndeclaredRepositoryException(e); } } <V> List<V> getPropertyValues(EntityTypeInfo entityTypeInfo, String propertyName, ValueDefinition<?, V> vt, ListType listType) { return null; } /** * * @param <V> * @param entityTypeInfo * @param propertyName * @param vt * @param propertyValue */ private <V> void setPropertyValue(EntityTypeInfo entityTypeInfo, String propertyName, ValueDefinition<?, V> vt, V propertyValue) { // 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); } } } entityTypeInfo.setProperty(propertyName, propertyValue); // 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); } } } <V> void setPropertyValues(EntityTypeInfo entityTypeInfo, String propertyName, ValueDefinition<?, V> vt, ListType listType, List<V> propertyValues) { } }