001/**
002 *   GRANITE DATA SERVICES
003 *   Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 *   This file is part of the Granite Data Services Platform.
006 *
007 *                               ***
008 *
009 *   Community License: GPL 3.0
010 *
011 *   This file is free software: you can redistribute it and/or modify
012 *   it under the terms of the GNU General Public License as published
013 *   by the Free Software Foundation, either version 3 of the License,
014 *   or (at your option) any later version.
015 *
016 *   This file is distributed in the hope that it will be useful, but
017 *   WITHOUT ANY WARRANTY; without even the implied warranty of
018 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
019 *   GNU General Public License for more details.
020 *
021 *   You should have received a copy of the GNU General Public License
022 *   along with this program. If not, see <http://www.gnu.org/licenses/>.
023 *
024 *                               ***
025 *
026 *   Available Commercial License: GraniteDS SLA 1.0
027 *
028 *   This is the appropriate option if you are creating proprietary
029 *   applications and you are not prepared to distribute and share the
030 *   source code of your application under the GPL v3 license.
031 *
032 *   Please visit http://www.granitedataservices.com/license for more
033 *   details.
034 */
035package org.granite.client.tide.data.impl;
036
037import java.util.HashSet;
038import java.util.List;
039import java.util.Map;
040import java.util.Set;
041import java.util.concurrent.ConcurrentHashMap;
042import java.util.concurrent.ConcurrentMap;
043
044import org.granite.client.persistence.Persistence;
045import org.granite.client.platform.Platform;
046import org.granite.client.tide.data.EntityManager;
047import org.granite.client.tide.data.PersistenceManager;
048import org.granite.client.tide.data.spi.DataManager;
049import org.granite.logging.Logger;
050import org.granite.messaging.reflect.Property;
051import org.granite.util.UUIDUtil;
052
053/**
054 * @author William DRAI
055 */
056public abstract class AbstractDataManager implements DataManager {
057        
058        private static final Logger log = Logger.getLogger(AbstractDataManager.class);
059
060    private static ConcurrentMap<Class<?>, Set<String>> lazyPropertiesByClass = new ConcurrentHashMap<Class<?>, Set<String>>(50);
061    
062    
063    protected Persistence persistence = null;
064    
065    public AbstractDataManager() {
066        initPersistence();
067    }
068    
069    protected void initPersistence() {
070        persistence = Platform.persistence();
071    }
072    
073    public boolean isEntity(Object entity) {
074        return entity != null && persistence.isEntity(entity.getClass());
075    }
076    
077    public Object getId(Object entity) {
078        return persistence.getId(entity);
079    }
080    
081    public boolean hasIdProperty(Object entity) {
082        if (entity == null)
083                return false;
084        return persistence.hasIdProperty(entity.getClass());
085    }
086    
087    public String getDetachedState(Object entity) {
088        return persistence.getDetachedState(entity);
089    }
090    
091    public Object getVersion(Object entity) {
092        return persistence.getVersion(entity);
093    }
094    
095    public boolean hasVersionProperty(Object entity) {
096        if (entity == null)
097                return false;
098        return persistence.hasVersionProperty(entity.getClass());
099    }
100    
101    public String getVersionPropertyName(Object entity) {
102        if (entity == null)
103                return null;
104        Property property = persistence.getVersionProperty(entity.getClass());
105        return property != null ? property.getName() : null;
106    }
107    
108    public Object getPropertyValue(Object entity, String name) {
109        if (entity == null)
110                return null;
111        return persistence.getPropertyValue(entity, name, true);
112    }
113    
114    public void setPropertyValue(Object entity, String name, Object value) {
115        if (entity == null)
116                return;
117        persistence.setPropertyValue(entity, name, value);
118    }
119    
120    public String getUid(Object entity) {
121        if (entity == null)
122                return null;
123        
124        if (persistence.hasUidProperty(entity.getClass())) {
125                String uid = persistence.getUid(entity);
126                if (uid == null) {
127                        uid = UUIDUtil.randomUUID();
128                        persistence.setUid(entity, uid);
129                }
130                return uid;
131        }
132        Object id = persistence.getId(entity);
133        if (id != null)
134                return entity.getClass().getSimpleName() + ":" + id.toString();
135        return entity.getClass().getSimpleName() + "::" + System.identityHashCode(entity);
136    }
137    
138    public String getCacheKey(Object entity) {
139        if (entity == null)
140                return null;
141        
142        return entity.getClass().getName() + ":" + getUid(entity);
143    }
144    
145    public boolean isInitialized(Object object) {
146        return persistence.isInitialized(object);
147    }
148    
149    
150    public void copyUid(Object dest, Object obj) {
151        if (isEntity(obj) && persistence.hasUidProperty(obj.getClass()))
152                persistence.setUid(dest, persistence.getUid(obj));
153    }
154    
155    public boolean defineProxy(Object dest, Object obj) {
156        if (!isEntity(dest))
157            return false;
158        
159        try {
160            if (obj != null) {
161                if (persistence.getDetachedState(obj) == null)
162                    return false;
163                persistence.setId(dest, persistence.getId(obj));
164                persistence.setDetachedState(dest, persistence.getDetachedState(obj));
165            }
166            persistence.setInitialized(dest, false);
167            return true;
168        }
169        catch (Exception e) {
170            throw new RuntimeException("Could not proxy class " + obj.getClass());
171        }
172    }
173    
174    public void copyProxyState(Object dest, Object obj) {
175                try {
176                        persistence.setInitialized(dest, persistence.isInitialized(obj));
177                        persistence.setDetachedState(dest, persistence.getDetachedState(obj));
178                }
179            catch (Exception e) {
180                log.error(e, "Could not copy internal state of object " + ObjectUtil.toString(obj));
181            }
182    }
183    
184    public Map<String, Object> getPropertyValues(Object entity, boolean excludeVersion, boolean includeReadOnly) {
185        return persistence.getPropertyValues(entity, true, false, excludeVersion, includeReadOnly);
186    }
187    
188    public Map<String, Object> getPropertyValues(Object entity, boolean excludeIdUid, boolean excludeVersion, boolean includeReadOnly) {
189        return persistence.getPropertyValues(entity, true, excludeIdUid, excludeVersion, includeReadOnly);
190    }
191
192    
193    private Set<String> getLazyPropertyNames(Class<?> entityClass) {
194        Set<String> lazyPropertyNames = lazyPropertiesByClass.get(entityClass);
195        if (lazyPropertyNames == null) {
196                List<Property> lazyProperties = persistence.getLazyProperties(entityClass);
197                lazyPropertyNames = new HashSet<String>();
198                for (Property lazyProperty : lazyProperties)
199                        lazyPropertyNames.add(lazyProperty.getName());
200                
201                lazyPropertiesByClass.putIfAbsent(entityClass, lazyPropertyNames);              
202        }
203        return lazyPropertyNames;
204    }
205    
206    public boolean isLazyProperty(Object entity, String propertyName) {
207                return getLazyPropertyNames(entity.getClass()).contains(propertyName);
208    }
209    
210    public void setLazyProperty(Object entity, String propertyName) {
211        getLazyPropertyNames(entity.getClass()).add(propertyName);      
212    }
213
214    
215    public boolean isDirtyEntity(Object entity) {
216        EntityManager entityManager = PersistenceManager.getEntityManager(entity);
217        if (entityManager == null)
218                throw new IllegalStateException("Non managed entity: " + entity);
219                return entityManager.isDirtyEntity(entity);
220    }
221    
222    public boolean isDeepDirtyEntity(Object entity) {
223        EntityManager entityManager = PersistenceManager.getEntityManager(entity);
224        if (entityManager == null)
225                throw new IllegalStateException("Non managed entity: " + entity);
226                return entityManager.isDeepDirtyEntity(entity);
227    }
228    
229}