001package com.avaje.ebean.common; 002 003import com.avaje.ebean.Ebean; 004import com.avaje.ebean.ExpressionList; 005import com.avaje.ebean.bean.BeanCollection; 006import com.avaje.ebean.bean.BeanCollectionLoader; 007import com.avaje.ebean.bean.EntityBean; 008 009import javax.persistence.PersistenceException; 010import java.util.Set; 011 012/** 013 * Base class for List Set and Map implementations of BeanCollection. 014 * 015 * @author rbygrave 016 */ 017public abstract class AbstractBeanCollection<E> implements BeanCollection<E> { 018 019 private static final long serialVersionUID = 3365725236140187588L; 020 021 protected boolean readOnly; 022 023 protected boolean disableLazyLoad; 024 025 /** 026 * The EbeanServer this is associated with. (used for lazy fetch). 027 */ 028 protected transient BeanCollectionLoader loader; 029 030 protected transient ExpressionList<?> filterMany; 031 032 /** 033 * Flag set when registered with the batch loading context. 034 */ 035 protected boolean registeredWithLoadContext; 036 037 protected String ebeanServerName; 038 039 /** 040 * The owning bean (used for lazy fetch). 041 */ 042 protected EntityBean ownerBean; 043 044 /** 045 * The name of this property in the owning bean (used for lazy fetch). 046 */ 047 protected String propertyName; 048 049 protected ModifyHolder<E> modifyHolder; 050 051 protected ModifyListenMode modifyListenMode; 052 protected boolean modifyAddListening; 053 protected boolean modifyRemoveListening; 054 protected boolean modifyListening; 055 056 /** 057 * Constructor not non-lazy loading collection. 058 */ 059 public AbstractBeanCollection() { 060 } 061 062 /** 063 * Used to create deferred fetch proxy. 064 */ 065 public AbstractBeanCollection(BeanCollectionLoader loader, EntityBean ownerBean, String propertyName) { 066 this.loader = loader; 067 this.ebeanServerName = loader.getName(); 068 this.ownerBean = ownerBean; 069 this.propertyName = propertyName; 070 this.readOnly = ownerBean._ebean_getIntercept().isReadOnly(); 071 } 072 073 public EntityBean getOwnerBean() { 074 return ownerBean; 075 } 076 077 public String getPropertyName() { 078 return propertyName; 079 } 080 081 public ExpressionList<?> getFilterMany() { 082 return filterMany; 083 } 084 085 public void setFilterMany(ExpressionList<?> filterMany) { 086 this.filterMany = filterMany; 087 } 088 089 @Override 090 public void setDisableLazyLoad(boolean disableLazyLoad) { 091 this.disableLazyLoad = disableLazyLoad; 092 } 093 094 protected void lazyLoadCollection(boolean onlyIds) { 095 if (loader == null) { 096 loader = (BeanCollectionLoader) Ebean.getServer(ebeanServerName); 097 } 098 if (loader == null) { 099 String msg = "Lazy loading but LazyLoadEbeanServer is null?" 100 + " The LazyLoadEbeanServer needs to be set after deserialization" 101 + " to support lazy loading."; 102 throw new PersistenceException(msg); 103 } 104 105 loader.loadMany(this, onlyIds); 106 checkEmptyLazyLoad(); 107 } 108 109 public boolean isRegisteredWithLoadContext() { 110 return registeredWithLoadContext; 111 } 112 113 public void setLoader(BeanCollectionLoader loader) { 114 this.registeredWithLoadContext = true; 115 this.loader = loader; 116 this.ebeanServerName = loader.getName(); 117 } 118 119 public boolean isReadOnly() { 120 return readOnly; 121 } 122 123 public void setReadOnly(boolean readOnly) { 124 this.readOnly = readOnly; 125 } 126 127 protected void checkReadOnly() { 128 if (readOnly) { 129 String msg = "This collection is in ReadOnly mode"; 130 throw new IllegalStateException(msg); 131 } 132 } 133 134 // --------------------------------------------------------- 135 // Support for modify additions deletions etc - ManyToMany 136 // --------------------------------------------------------- 137 138 /** 139 * set modifyListening to be on or off. 140 */ 141 public void setModifyListening(ModifyListenMode mode) { 142 143 this.modifyListenMode = mode; 144 this.modifyAddListening = ModifyListenMode.ALL.equals(mode); 145 this.modifyRemoveListening = modifyAddListening || ModifyListenMode.REMOVALS.equals(mode); 146 this.modifyListening = modifyRemoveListening || modifyAddListening; 147 if (modifyListening) { 148 // lose any existing modifications 149 modifyHolder = null; 150 } 151 } 152 153 /** 154 * Return the modify listening mode this collection is using. 155 */ 156 public ModifyListenMode getModifyListenMode() { 157 return modifyListenMode; 158 } 159 160 protected ModifyHolder<E> getModifyHolder() { 161 if (modifyHolder == null) { 162 modifyHolder = new ModifyHolder<E>(); 163 } 164 return modifyHolder; 165 } 166 167 public void modifyAddition(E bean) { 168 if (modifyAddListening) { 169 getModifyHolder().modifyAddition(bean); 170 } 171 } 172 173 public void modifyRemoval(Object bean) { 174 if (modifyRemoveListening) { 175 getModifyHolder().modifyRemoval(bean); 176 } 177 } 178 179 public void modifyReset() { 180 if (modifyHolder != null) { 181 modifyHolder.reset(); 182 } 183 } 184 185 public Set<E> getModifyAdditions() { 186 if (modifyHolder == null) { 187 return null; 188 } else { 189 return modifyHolder.getModifyAdditions(); 190 } 191 } 192 193 public Set<E> getModifyRemovals() { 194 if (modifyHolder == null) { 195 return null; 196 } else { 197 return modifyHolder.getModifyRemovals(); 198 } 199 } 200 201 /** 202 * Return true if there are underlying additions or removals. 203 */ 204 public boolean holdsModifications() { 205 return modifyHolder != null && modifyHolder.hasModifications(); 206 } 207}