com.avaje.ebeaninternal.server.deploy.BeanRefreshFromCacheHelp Maven / Gradle / Ivy
/**
* Copyright (C) 2009 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.util.HashSet;
import java.util.Set;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.bean.EntityBeanIntercept;
import com.avaje.ebeaninternal.server.query.SqlTreeNode;
/**
* Helper for performing a 'refresh' on an Entity bean.
*
* Note that this does not 'refresh' any OnetoMany or ManyToMany properties. It
* refreshes all the other properties though.
*
*/
public class BeanRefreshFromCacheHelp {
private final BeanDescriptor> desc;
private final EntityBeanIntercept ebi;
private final EntityBean bean;
private final Object cacheBean;
private final Object originalOldValues;
private final boolean isLazyLoad;
private final boolean readOnly;
private final boolean sharedInstance;
private final int parentState;
// set of properties to exclude from the refresh because it is
// not a refresh but rather a lazyLoading event.
private final Set excludes;
private final Set cacheBeanLoadedProps;
private final Set loadedProps;
private final boolean setOriginalOldValues;
public BeanRefreshFromCacheHelp(BeanDescriptor> desc, EntityBeanIntercept ebi, Object cacheBean, boolean isLazyLoad){
this.desc = desc;
this.ebi = ebi;
this.bean = ebi.getOwner();
this.cacheBean = cacheBean;
this.cacheBeanLoadedProps = ((EntityBean)cacheBean)._ebean_getIntercept().getLoadedProps();
if (cacheBeanLoadedProps != null){
loadedProps = new HashSet();
} else {
loadedProps = null;
}
this.isLazyLoad = isLazyLoad;
this.readOnly = ebi.isReadOnly();
this.sharedInstance = ebi.isSharedInstance();
if (sharedInstance){
parentState = SqlTreeNode.SHARED;
} else if (readOnly){
parentState = SqlTreeNode.READONLY;
} else {
parentState = SqlTreeNode.NORMAL;
}
this.excludes = isLazyLoad ? ebi.getLoadedProps() : null;
if (excludes != null){
// lazy loading a "Partial Object"... which already
// contains some properties and perhaps some oldValues
// and these will need to be maintained...
originalOldValues = ebi.getOldValues();
} else {
originalOldValues = null;
}
this.setOriginalOldValues = originalOldValues != null;
}
private boolean includeProperty(BeanProperty prop) {
String name = prop.getName();
if (excludes != null && excludes.contains(name)){
// ignore this property (partial bean lazy loading)
return false;
}
if (cacheBeanLoadedProps != null && !cacheBeanLoadedProps.contains(name)){
return false;
}
if (loadedProps != null){
loadedProps.add(name);
}
return true;
}
private void propagateParentState(Object bean) {
if (bean != null && parentState > 0){
((EntityBean)bean)._ebean_getIntercept().setState(parentState);
}
}
/**
* Refresh the bean from property values in dbBean.
*/
public void refresh() {
// turn off intercepting so lazy loading is
// not invoked when populating the bean
// with PropertyChangeSupport
ebi.setIntercepting(false);
BeanProperty[] props = desc.propertiesBaseScalar();
for (int i = 0; i < props.length; i++) {
BeanProperty prop = props[i];
if (includeProperty(prop)){
Object val = prop.getValue(cacheBean);
if (isLazyLoad) {
prop.setValue(bean, val);
} else {
prop.setValueIntercept(bean, val);
}
if (setOriginalOldValues){
// maintain original oldValues for partially loaded bean
prop.setValue(originalOldValues, val);
}
}
}
BeanPropertyAssocOne>[] ones = desc.propertiesOne();
for (int i = 0; i < ones.length; i++) {
BeanPropertyAssocOne> prop = ones[i];
if (includeProperty(prop)){
// returns a reference from the cache with 'sharedInstance' set
Object val = prop.getValue(cacheBean);
if (!sharedInstance){
// create a copy so that we can change its state...
val = prop.getTargetDescriptor().createCopyForUpdate(val, false);
}
if (isLazyLoad){
prop.setValue(bean, val);
} else {
prop.setValueIntercept(bean, val);
}
if (setOriginalOldValues){
// maintain original oldValues for partially loaded bean
prop.setValue(originalOldValues, val);
}
propagateParentState(val);
}
}
refreshEmbedded();
// set a lazy loading many proxy if required
BeanPropertyAssocMany>[] manys = desc.propertiesMany();
for (int i = 0; i < manys.length; i++) {
BeanPropertyAssocMany> prop = manys[i];
if (includeProperty(prop)){
// set a lazy loading proxy
prop.createReference(bean);
}
}
ebi.setLoadedProps(loadedProps);
// reset the loaded status
ebi.setLoaded();
}
/**
* Refresh the Embedded beans.
*/
private void refreshEmbedded(){
BeanPropertyAssocOne>[] embeds = desc.propertiesEmbedded();
for (int i = 0; i < embeds.length; i++) {
BeanPropertyAssocOne> prop = embeds[i];
if (includeProperty(prop)){
// the original embedded bean
Object oEmb = prop.getValue(bean);
// the new one from the database
Object cacheEmb = prop.getValue(cacheBean);
if (oEmb == null){
// original embedded bean was null
// so just replace the entire embedded bean
if (cacheEmb == null){
prop.setValueIntercept(bean, null);
} else {
Object copyEmb = prop.getTargetDescriptor().createCopyForUpdate(cacheEmb, false);
prop.setValueIntercept(bean, copyEmb);
propagateParentState(copyEmb);
}
} else {
// refresh each property of the original
// embedded bean
if (oEmb instanceof EntityBean){
// turn off interception to stop invoking lazy loading
// but allow PropertyChangeSupport
((EntityBean) oEmb)._ebean_getIntercept().setIntercepting(false);
}
BeanProperty[] props = prop.getProperties();
for (int j = 0; j < props.length; j++) {
Object v = props[j].getValue(cacheEmb);
props[j].setValueIntercept(oEmb, v);
}
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy