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; 021 022import java.util.ArrayList; 023import java.util.HashSet; 024import java.util.List; 025import java.util.Set; 026 027/** 028 * The Stash sits between the ModelController and the Persister. ModelController 029 * is what is used externally to access the data. The Persister controls the 030 * interaction between Stallion and the actual data store, whether that be your 031 * file system or database. The Stash can either be a complete pass-through and 032 * do nothing at all, or it can actually sync all the objects from the datastore 033 * into local memory (using LocalMemoryStash). 034 * 035 * 036 * @param <T> 037 */ 038public abstract class Stash<T extends Model> { 039 private ModelController<T> controller; 040 private String bucket; 041 private Persister<T> persister; 042 private Class<? extends T> modelClass; 043 private Set<String> keyFields = new HashSet<>(); 044 private Set<String> uniqueFields = new HashSet<>(); 045 046 /** 047 * Initialized the Stash with required attributes, this is 048 * called via dataAccess registration. 049 * 050 * @param registration 051 * @param controller 052 * @param persister 053 */ 054 public void init(DataAccessRegistration registration, ModelController<T> controller, Persister<T> persister) { 055 this.controller = controller; 056 this.bucket = registration.getBucket(); 057 this.persister = persister; 058 this.modelClass = (Class<? extends T>)registration.getModelClass(); 059 } 060 061 /** 062 * Get the associated controller 063 * @return 064 */ 065 public ModelController<T> getController() { 066 return controller; 067 } 068 069 /** 070 * Get the associated persister 071 * @return 072 */ 073 public Persister<T> getPersister() { 074 return persister; 075 } 076 077 /** 078 * Get the bucket name 079 * @return 080 */ 081 public String getBucket() { 082 return bucket; 083 } 084 085 /** 086 * Get the fields that have been defined as alternative lookup keys. A LocalMemoryStash 087 * will create lookup tables for all these fields, for fast access. 088 * 089 * @return 090 */ 091 public Set<String> getKeyFields() { 092 return keyFields; 093 } 094 095 096 public Stash<T> setKeyFields(Set<String> keyFields) { 097 this.keyFields = keyFields; 098 return this; 099 } 100 101 /** 102 * Get the field names that have been defined as unique keys. A LocalMemoryStash 103 * will create lookup tables for all these fields, for fast access. 104 * @return 105 */ 106 public Set<String> getUniqueFields() { 107 return uniqueFields; 108 } 109 110 111 public Stash<T> setUniqueFields(Set<String> uniqueFields) { 112 this.uniqueFields = uniqueFields; 113 return this; 114 } 115 116 /** 117 * Take the passed in object, find the object in the stash with the same id, and 118 * sync the data of the passed in object to the stashed object. 119 * 120 * This is used when saving a detached object -- first you have to sync the changes 121 * to the stashed version of the object, then persist it. 122 * 123 * By default, sync will not sync builtin or internal fields 124 * 125 * @param obj 126 */ 127 public abstract void sync(T obj); 128 129 130 public void syncForSave(T obj) { 131 sync(obj); 132 } 133 134 /** 135 * Return a cloned version of the object. 136 * 137 * @param obj 138 * @return 139 */ 140 public abstract T detach(T obj); 141 142 /** 143 * Save the object to the stash and the underlying data store 144 * @param obj 145 */ 146 public abstract void save(T obj); 147 148 /** 149 * Remove the object from the stash and the underlying data store 150 * @param obj 151 */ 152 public abstract void hardDelete(T obj); 153 154 /** 155 * Load all items from the datastore into the stash. 156 */ 157 public abstract void loadAll(); 158 159 /** 160 * Re-load the given object from the datastore into the stash 161 * @param obj 162 */ 163 public abstract boolean loadItem(T obj); 164 165 /** 166 * Load or reload the item with the given id from the datastore into the stash 167 * @param id 168 */ 169 public abstract void loadForId(Long id); 170 171 /** 172 * All the items in the stash. 173 * 174 * @return 175 */ 176 public abstract List<T> getItems(); 177 178 /** 179 * Reset the cache, nulling out all existing fields, and then reloading everything from 180 * the database. 181 */ 182 public abstract void reset(); 183 184 /** 185 * Called before any of the data access methods run 186 */ 187 public abstract void onPreRead(); 188 189 /** 190 * Reload from the underlying datastore if the stashed version is older 191 * than the version in the datastore. 192 * 193 * @param obj 194 * @return 195 */ 196 public T reloadIfNewer(T obj) { 197 return obj; 198 } 199 200 /** 201 * Get a cloned/detached object by id 202 * 203 * @param id 204 * @return 205 */ 206 public abstract T forId(Long id); 207 208 /** 209 * Get the original object by id, if modified, the object in the stash 210 * will be modified, so be careful. 211 * 212 * @param id 213 * @return 214 */ 215 public abstract T originalForId(Long id); 216 217 /** 218 * Retrieve an object via unique key. 219 * 220 * @param keyName 221 * @param value 222 * @return 223 */ 224 public abstract T forUniqueKey(String keyName, Object value); 225 226 /** 227 * Retrieve all objects for a given alternative key 228 * 229 * @param keyName 230 * @param value 231 * @return 232 */ 233 public abstract List<T> listForKey(String keyName, Object value); 234 235 /** 236 * Count the number of objects associated with an alternative key 237 * 238 * @param keyName 239 * @param value 240 * @return 241 */ 242 public abstract int countForKey(String keyName, Object value); 243 244 /** 245 * Create a new FilterChain for this stash 246 * 247 * @return 248 */ 249 public abstract FilterChain<T> filterChain(); 250 251 /** 252 * Create a new filterChain, restricting it to items matching the lookupValue for the key 253 * 254 * @param key - a model field that has been defined as a key 255 * @param lookupValue 256 * @return 257 */ 258 public abstract FilterChain<T> filterByKey(String key, Object lookupValue); 259 260 /** 261 * Create a new filter chain using a subset of items 262 * 263 * @param subset 264 * @return 265 */ 266 public abstract FilterChain<T> filterChain(List<T> subset); 267 268 269 270}