001/* 002 * Stallion Core: A Modern Web Framework 003 * 004 * Copyright (C) 2015 - 2016 Stallion Software LLC. 005 * 006 * This program is free software: you can redistribute it and/or modify it under the terms of the 007 * GNU General Public License as published by the Free Software Foundation, either version 2 of 008 * the License, or (at your option) any later version. This program is distributed in the hope that 009 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 011 * License for more details. You should have received a copy of the GNU General Public License 012 * along with this program. If not, see <http://www.gnu.org/licenses/gpl-2.0.html>. 013 * 014 * 015 * 016 */ 017 018package io.stallion.dataAccess; 019 020import io.stallion.dataAccess.filtering.FilterChain; 021import io.stallion.dataAccess.filtering.FilterOperator; 022import io.stallion.reflection.PropertyUtils; 023import io.stallion.services.Log; 024import io.stallion.settings.Settings; 025 026 027import java.util.*; 028 029import static io.stallion.utils.Literals.or; 030import static io.stallion.utils.Literals.set; 031 032/** 033 * The standard implementation of a ModelController. You should almost certainly 034 * use this as the base for your own model controllers. 035 * 036 * @param <T> 037 */ 038public class StandardModelController<T extends Model> implements ModelController<T> { 039 private String bucket; 040 private Stash<T> stash; 041 private Persister persister; 042 private Boolean writable; 043 private ReadOnlyWrapper<T> readOnlyWrapper; 044 private Class<T> modelClass; 045 046 public StandardModelController() { 047 } 048 049 050 051 protected void preInitialize(DataAccessRegistration registration) { 052 053 } 054 055 protected void postInitialize(DataAccessRegistration registration) { 056 057 } 058 059 060 @Override 061 public void init(DataAccessRegistration registration, Persister<T> persister, Stash<T> stash) { 062 this.bucket = registration.getBucket(); 063 this.persister = persister; 064 this.stash = stash; 065 this.writable = registration.isWritable(); 066 this.modelClass = (Class<T>)registration.getModelClass(); 067 if (this instanceof DisplayableModelController) { 068 DisplayableModelController c = (DisplayableModelController)this; 069 c.setDefaultTemplate(or(registration.getTemplatePath(), Settings.instance().getPageTemplate())); 070 } 071 } 072 073 @Override 074 public String getBucket() { 075 return this.bucket; 076 } 077 078 /** 079 * Instantiates a new item instance from the model class. 080 * 081 * @return 082 */ 083 public T newModel() { 084 return newModel(null); 085 } 086 087 /** 088 * Instantiates a new item instance, assigning the values passed in with the map 089 * @param o 090 * @return 091 */ 092 public T newModel(Map o) { 093 return newModel(o, new String[]{}); 094 } 095 096 public T newModel(Map o, String ...fields) { 097 Set fieldSet = null; 098 if (fields != null && fields.length > 0) { 099 fieldSet = set(fields); 100 } 101 102 try { 103 T model = getModelClass().newInstance(); 104 if (o != null && o.size() > 0) { 105 for(Object key: o.keySet()) { 106 if (fieldSet != null && !fieldSet.contains(key)) { 107 continue; 108 } 109 Object value = o.get(key); 110 PropertyUtils.setProperty(model, key.toString(), value); 111 } 112 } 113 return model; 114 } catch (InstantiationException e) { 115 throw new RuntimeException(e); 116 } catch (IllegalAccessException e) { 117 throw new RuntimeException(e); 118 } 119 } 120 121 @Override 122 public T detach(T obj) { 123 return getStash().detach(obj); 124 } 125 126 127 128 @Override 129 public void save(T obj) { 130 T existing = this.forIdWithDeleted(obj.getId()); 131 if (existing == null) { 132 Log.finer("Existing object not found. {0} new={1} id={2}", getBucket(), obj.hashCode(), obj.getId()); 133 onPreCreatePrepare(obj); 134 onPreSavePrepare(obj); 135 onPreCreateValidate(obj); 136 onPreSaveValidate(obj); 137 getStash().save(obj); 138 onPostCreate(obj); 139 } else { 140 Log.finer("Existing found. {0} existing={1} new={2} id={3}", getBucket(), existing.hashCode(), obj.hashCode(), obj.getId()); 141 onPreSavePrepare(obj); 142 onPreSaveValidate(obj); 143 getStash().save(obj); 144 onPostSave(obj); 145 } 146 } 147 148 @Override 149 public void softDelete(T obj) { 150 obj.setDeleted(true); 151 this.save(obj); 152 } 153 154 @Override 155 public void hardDelete(T obj) { 156 getStash().hardDelete(obj); 157 } 158 159 160 @Override 161 public void onPreSavePrepare(T obj) { 162 163 } 164 165 @Override 166 public void onPreSaveValidate(T obj) { 167 168 } 169 170 @Override 171 public void onPreCreatePrepare(T obj) { 172 173 } 174 175 @Override 176 public void onPreCreateValidate(T obj) { 177 178 } 179 180 @Override 181 public void onPostSave(T obj) { 182 183 } 184 185 @Override 186 public void onPostCreate(T obj) { 187 188 } 189 190 191 @Override 192 @Deprecated 193 public void onPreRead() { 194 195 } 196 197 198 public void onPostLoadItem(T item) { 199 200 } 201 202 @Override 203 public FilterChain<T> filterChain() { 204 return getStash().filterChain(); 205 } 206 207 @Override 208 public FilterChain<T> filter(String name, Object value) { 209 return filterChain().filter(name, value); 210 } 211 212 @Override 213 public FilterChain<T> filter(String name, Object value, String op) { 214 return filterChain().filter(name, value, op); 215 } 216 217 @Override 218 public FilterChain<T> filterBy(String name, Object value, FilterOperator op) { 219 return filterChain().filterBy(name, value, op); 220 } 221 222 @Override 223 public FilterChain<T> filterByKey(String keyName, Object value) { 224 return getStash().filterByKey(keyName, value); 225 } 226 227 228 @Override 229 public T originalForId(T id) { 230 return null; 231 } 232 233 234 @Override 235 public T forId(Long id) { 236 T o = getStash().forId(id); 237 if (o == null) { 238 return o; 239 } 240 if (o.getDeleted() != null && o.getDeleted() == true) { 241 return null; 242 } 243 return o; 244 } 245 246 @Override 247 public T forIdWithDeleted(Long id) { 248 return getStash().forId(id); 249 } 250 251 @Override 252 public T originalForId(Long id) { 253 return getStash().originalForId(id); 254 } 255 256 @Override 257 public T forUniqueKey(String keyName, Object keyValue) { 258 return getStash().forUniqueKey(keyName, keyValue); 259 } 260 261 @Override 262 public List<T> listForKey(String keyName, Object value) { 263 return getStash().listForKey(keyName, value); 264 } 265 266 @Override 267 public int countForKey(String keyName, Object value) { 268 return getStash().countForKey(keyName, value); 269 } 270 271 272 @Override 273 public List<T> all() { 274 return filterChain().all(); 275 } 276 277 @Override 278 public void reset() { 279 getStash().reset(); 280 } 281 282 public Persister getPersister() { 283 return this.persister; 284 } 285 286 @Override 287 public Stash<T> getStash() { 288 return this.stash; 289 } 290 291 @Override 292 public Class<T> getModelClass() { 293 return this.modelClass; 294 } 295 296 public void setPersister(Persister persister) { 297 this.persister = persister; 298 } 299 300 @Override 301 public Set<String> getKeyFields() { 302 return getStash().getKeyFields(); 303 } 304 305 @Override 306 public Set<String> getUniqueFields() { 307 return getStash().getUniqueFields(); 308 } 309 310 @Override 311 public Boolean isWritable() { 312 return writable; 313 } 314 315 316 public void setWritable(Boolean writable) { 317 this.writable = writable; 318 } 319 320 public ReadOnlyWrapper<T> getReadonlyWrapper() { 321 if (readOnlyWrapper == null) { 322 readOnlyWrapper = new ReadOnlyWrapper<>(this); 323 } 324 return readOnlyWrapper; 325 } 326}