/** * GRANITE DATA SERVICES * Copyright (C) 2006-2015 GRANITE DATA SERVICES S.A.S. * * This file is part of the Granite Data Services Platform. * * *** * * Community License: GPL 3.0 * * This file is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * This file 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * *** * * Available Commercial License: GraniteDS SLA 1.0 * * This is the appropriate option if you are creating proprietary * applications and you are not prepared to distribute and share the * source code of your application under the GPL v3 license. * * Please visit http://www.granitedataservices.com/license for more * details. */ package org.granite.client.tide.data.impl; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.granite.client.persistence.Persistence; import org.granite.client.platform.Platform; import org.granite.client.tide.data.EntityManager; import org.granite.client.tide.data.EntityProxy; import org.granite.client.tide.data.PersistenceManager; import org.granite.client.tide.data.spi.DataManager; import org.granite.logging.Logger; import org.granite.messaging.reflect.Property; import org.granite.util.TypeUtil; import org.granite.util.UUIDUtil; /** * @author William DRAI */ public abstract class AbstractDataManager implements DataManager { private static final Logger log = Logger.getLogger(AbstractDataManager.class); private static ConcurrentMap<Class<?>, Set<String>> lazyPropertiesByClass = new ConcurrentHashMap<Class<?>, Set<String>>(50); protected Persistence persistence = null; public AbstractDataManager() { initPersistence(); } protected void initPersistence() { persistence = Platform.persistence(); } public boolean isEntity(Object entity) { return entity != null && persistence.isEntity(entity instanceof Class<?> ? (Class<?>)entity : entity.getClass()); } public Object getId(Object entity) { return persistence.getId(entity); } public boolean hasIdProperty(Object entity) { if (entity == null) throw new IllegalArgumentException("entity should not be null"); return persistence.hasIdProperty(entity instanceof Class<?> ? (Class<?>) entity : entity.getClass()); } public String getIdPropertyName(Object entity) { if (entity == null) throw new IllegalArgumentException("entity should not be null"); Property property = persistence.getIdProperty(entity instanceof Class<?> ? (Class<?>) entity : entity.getClass()); return property != null ? property.getName() : null; } public String getDetachedState(Object entity) { return persistence.getDetachedState(entity); } public Object getVersion(Object entity) { return persistence.getVersion(entity); } public boolean hasVersionProperty(Object entity) { if (entity == null) throw new IllegalArgumentException("entity should not be null"); return persistence.hasVersionProperty(entity instanceof Class<?> ? (Class<?>)entity : entity.getClass()); } public String getVersionPropertyName(Object entity) { if (entity == null) throw new IllegalArgumentException("entity should not be null"); Property property = persistence.getVersionProperty(entity instanceof Class<?> ? (Class<?>)entity : entity.getClass()); return property != null ? property.getName() : null; } public boolean hasProperty(Object entity, String name) { if (entity == null) return false; if (entity instanceof EntityProxy) return ((EntityProxy)entity).hasProperty(name); return true; } public Object getPropertyValue(Object entity, String name) { if (entity == null) return null; if (entity instanceof EntityProxy) return ((EntityProxy)entity).getProperty(name); return persistence.getPropertyValue(entity, name, true); } public void setPropertyValue(Object entity, String name, Object value) { if (entity == null) return; persistence.setPropertyValue(entity, name, value); } public String getUid(Object entity) { if (entity == null) return null; if (persistence.hasUidProperty(entity.getClass())) { String uid = persistence.getUid(entity); if (uid == null) { uid = UUIDUtil.randomUUID(); persistence.setUid(entity, uid); } return uid; } Object id = persistence.getId(entity); if (id != null) return entity.getClass().getSimpleName() + ":" + id.toString(); return entity.getClass().getSimpleName() + "::" + System.identityHashCode(entity); } public String getUidPropertyName(Object entity) { if (entity == null) throw new IllegalArgumentException("entity should not be null"); Property property = persistence.getUidProperty(entity instanceof Class<?> ? (Class<?>)entity : entity.getClass()); return property != null ? property.getName() : null; } public String getCacheKey(Object entity) { if (entity == null) return null; if (entity instanceof EntityProxy) return ((EntityProxy)entity).getClassName() + ":" + ((EntityProxy)entity).getUid(); return entity.getClass().getName() + ":" + getUid(entity); } public boolean isInitialized(Object object) { if (object == null) return true; return persistence.isInitialized(object); } public void setInitialized(Object object, boolean initialized) { persistence.setInitialized(object, initialized); } public void copyUid(Object dest, Object obj) { if (isEntity(obj) && persistence.hasUidProperty(obj.getClass())) persistence.setUid(dest, persistence.getUid(obj)); } public void initProxy(Object dest, Object id, boolean initialized, String detachedState) { persistence.setId(dest, id); persistence.setInitialized(dest, initialized); persistence.setDetachedState(dest, detachedState); } public boolean defineProxy(Object dest, Object obj) { if (!isEntity(dest)) return false; try { if (obj != null) { if (persistence.getDetachedState(obj) == null) return false; persistence.setId(dest, persistence.getId(obj)); persistence.setDetachedState(dest, persistence.getDetachedState(obj)); } persistence.setInitialized(dest, false); return true; } catch (Exception e) { throw new RuntimeException("Could not proxy class " + obj.getClass()); } } public void copyProxyState(Object dest, Object obj) { if (obj instanceof EntityProxy) return; try { persistence.setInitialized(dest, persistence.isInitialized(obj)); persistence.setDetachedState(dest, persistence.getDetachedState(obj)); } catch (Exception e) { log.error(e, "Could not copy internal state of object " + ObjectUtil.toString(obj)); } } public Map<String, Object> getPropertyValues(Object entity, boolean excludeVersion, boolean includeReadOnly) { return getPropertyValues(entity, false, excludeVersion, includeReadOnly); } public Map<String, Object> getPropertyValues(Object entity, boolean excludeIdUid, boolean excludeVersion, boolean includeReadOnly) { Object object = entity instanceof EntityProxy ? ((EntityProxy)entity).getWrappedObject() : entity; Map<String, Object> propertyValues = persistence.getPropertyValues(object, true, excludeIdUid, excludeVersion, includeReadOnly); if (entity instanceof EntityProxy) { for (Iterator<Map.Entry<String, Object>> ipval = propertyValues.entrySet().iterator(); ipval.hasNext(); ) { Map.Entry<String, Object> pval = ipval.next(); if (!((EntityProxy)entity).hasProperty(pval.getKey())) ipval.remove(); else pval.setValue(((EntityProxy)entity).getProperty(pval.getKey())); } } return propertyValues; } private Set<String> getLazyPropertyNames(Class<?> entityClass) { Set<String> lazyPropertyNames = lazyPropertiesByClass.get(entityClass); if (lazyPropertyNames == null) { List<Property> lazyProperties = persistence.getLazyProperties(entityClass); lazyPropertyNames = new HashSet<String>(); for (Property lazyProperty : lazyProperties) lazyPropertyNames.add(lazyProperty.getName()); lazyPropertiesByClass.putIfAbsent(entityClass, lazyPropertyNames); } return lazyPropertyNames; } public boolean isLazyProperty(Object entity, String propertyName) { return getLazyPropertyNames(entity.getClass()).contains(propertyName); } public void setLazyProperty(Object entity, String propertyName) { getLazyPropertyNames(entity.getClass()).add(propertyName); } public <T> T newInstance(Object source, Class<T> cast) throws IllegalAccessException, InstantiationException { return TypeUtil.newInstance(source.getClass(), cast); } public boolean isDirtyEntity(Object entity) { EntityManager entityManager = PersistenceManager.getEntityManager(entity); if (entityManager == null) throw new IllegalStateException("Non managed entity: " + entity); return entityManager.isDirtyEntity(entity); } public boolean isDeepDirtyEntity(Object entity) { EntityManager entityManager = PersistenceManager.getEntityManager(entity); if (entityManager == null) throw new IllegalStateException("Non managed entity: " + entity); return entityManager.isDeepDirtyEntity(entity); } }