/** * 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; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import org.granite.binding.PropertyChangeHelper; import org.granite.client.tide.Context; import org.granite.client.tide.ContextAware; import org.granite.client.tide.data.impl.JavaBeanDataManager; import org.granite.client.tide.data.spi.EntityRef; /** * @author William DRAI */ public class ManagedEntity<T> implements ContextAware { private PropertyChangeSupport pcs = new PropertyChangeSupport(this); private T instance = null; private EntityManager entityManager; private JavaBeanDataManager dataManager; private boolean dirty = false; private boolean saved = false; // private List<InstanceBinding<T, ?>> instanceBindings = new ArrayList<InstanceBinding<T, ?>>(); public ManagedEntity() { } public ManagedEntity(EntityManager entityManager) { init(entityManager); } public ManagedEntity(EntityManager entityManager, T value) { init(entityManager); setInstance(value); } public void addPropertyChangeListener(PropertyChangeListener listener) { pcs.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { pcs.removePropertyChangeListener(listener); } public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { pcs.addPropertyChangeListener(propertyName, listener); } public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { pcs.removePropertyChangeListener(propertyName, listener); } public T getInstance() { return instance; } public void setInstance(T instance) { if (instance == this.instance) return; T oldInstance = this.instance; this.instance = instance; instanceChanged(oldInstance, instance); pcs.firePropertyChange("instance", oldInstance, instance); } public void setInstance(EntityRef ref) { @SuppressWarnings("unchecked") T instance = (T)entityManager.getCachedObject(ref, true); setInstance(instance); } public boolean isSaved() { return saved; } private void updateSaved() { boolean saved = getInstance() != null ? getVersion(getInstance()) != null : false; if (saved == this.saved) return; boolean oldSaved = this.saved; this.saved = saved; pcs.firePropertyChange("saved", oldSaved, saved); } public boolean isDirty() { return dirty; } private void updateDirty() { boolean dirty = getInstance() != null ? entityManager.isDeepDirtyEntity(getInstance()) : false; if (dirty == this.dirty) return; boolean oldDirty = this.dirty; this.dirty = dirty; pcs.firePropertyChange("dirty", oldDirty, dirty); } private void instanceChanged(T oldValue, T newValue) { if (oldValue != null) { entityManager.resetEntity(oldValue); // for (InstanceBinding<T, ?> instanceBinding : instanceBindings) // instanceBinding.unbind(oldValue); String versionPropertyName = getVersionPropertyName(oldValue); PropertyChangeHelper.removePropertyChangeListener(oldValue, versionPropertyName, versionChangeListener); } if (newValue == null) return; String versionPropertyName = getVersionPropertyName(newValue); PropertyChangeHelper.addPropertyChangeListener(newValue, versionPropertyName, versionChangeListener); updateDirty(); updateSaved(); EntityManager entityManager = PersistenceManager.getEntityManager(newValue); if (entityManager == null) ManagedEntity.this.entityManager.mergeExternalData(newValue); else if (entityManager != ManagedEntity.this.entityManager) throw new RuntimeException("Entity " + newValue + " cannot be attached: already attached to another entity manager"); // for (InstanceBinding<T, ?> instanceBinding : instanceBindings) // instanceBinding.bind(newValue); } private PropertyChangeListener versionChangeListener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { updateSaved(); } }; @Override public void setContext(Context context) { init(context.getEntityManager()); } private void init(EntityManager entityManager) { if (this.entityManager == null) this.entityManager = entityManager; this.dataManager = (JavaBeanDataManager)this.entityManager.getDataManager(); this.dataManager.addPropertyChangeListener("deepDirtyEntity", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent pce) { if (pce.getSource() == getInstance()) updateDirty(); } }); } // public <P> void addInstanceBinding(Property<P> property, ObservableValueGetter<T, P> propertyGetter) { // InstanceBinding<T, P> instanceBinding = new UnidirectionalInstanceBinding<P>(property, propertyGetter); // instanceBindings.add(instanceBinding); // if (instance != null) // instanceBinding.bind(instance); // } // // public <P> void addBidirectionalInstanceBinding(Property<P> property, PropertyGetter<T, P> propertyGetter) { // InstanceBinding<T, P> instanceBinding = new BidirectionalInstanceBinding<P>(property, propertyGetter); // instanceBindings.add(instanceBinding); // if (instance != null) // instanceBinding.bind(instance); // } public void reset() { if (instance == null) return; entityManager.resetEntity(instance); } private String getVersionPropertyName(Object value) { String versionPropertyName = dataManager.getVersionPropertyName(value); if (versionPropertyName == null) throw new RuntimeException("No version property found on entity " + value); return versionPropertyName; } private Object getVersion(Object value) { return dataManager.getVersion(value); } // private interface InstanceBinding<T, P> { // // public void bind(T instance); // // public void unbind(T instance); // } // // private final class BidirectionalInstanceBinding<P> implements InstanceBinding<T, P> { // // private final // private final PropertyGetter<T, P> entityPropertyGetter; // // public BidirectionalInstanceBinding(Property<P> inputProperty, PropertyGetter<T, P> entityPropertyGetter) { // this.inputProperty = inputProperty; // this.entityPropertyGetter = entityPropertyGetter; // } // // public void bind(T instance) { // this.inputProperty.bindBidirectional(entityPropertyGetter.getProperty(instance)); // } // // public void unbind(T instance) { // this.inputProperty.unbindBidirectional(entityPropertyGetter.getProperty(instance)); // } // } // // private final class UnidirectionalInstanceBinding<P> implements InstanceBinding<T, P> { // // private final Property<P> inputProperty; // private final ObservableValueGetter<T, P> entityPropertyGetter; // // public UnidirectionalInstanceBinding(Property<P> inputProperty, ObservableValueGetter<T, P> entityPropertyGetter) { // this.inputProperty = inputProperty; // this.entityPropertyGetter = entityPropertyGetter; // } // // public void bind(T instance) { // this.inputProperty.bind(entityPropertyGetter.getObservableValue(instance)); // } // // public void unbind(T instance) { // this.inputProperty.unbind(); // } // } // // // public static interface PropertyGetter<T, P> { // // public Property<P> getProperty(T instance); // } // // public static interface ObservableValueGetter<T, P> { // // public ObservableValue<P> getObservableValue(T instance); // } }