de.tsl2.nano.service.util.batch.CachingBatchloader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tsl2.nano.serviceaccess Show documentation
Show all versions of tsl2.nano.serviceaccess Show documentation
TSL2 JEE Service Access (Generic Services for Entity Access, JEE File-System-Connector, Generic Featuring, Job-Scheduling, BeanContainer, Batch, Comfortable Bean Query Definitions, JAAS, Authentification, Authorization, )
The newest version!
/*
* File: $HeadURL$
* Id : $Id$
*
* created by: Thomas Schneider, Thomas Schneider
* created on: Oct 10, 2012
*
* Copyright: (c) Thomas Schneider 2012, all rights reserved
*/
package de.tsl2.nano.service.util.batch;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import de.tsl2.nano.core.ManagedException;
import de.tsl2.nano.service.util.IGenericService;
import de.tsl2.nano.service.util.finder.AbstractFinder;
import de.tsl2.nano.serviceaccess.ServiceFactory;
/**
* Batch loader that is optionally able to cache loaded data. Useable to optimize performance on loading several data
* using a single communication line.
*
*
*
* Features:
* - load data through several queries on a single request
* - cache base data for application access
*
*
* @author Thomas Schneider, Thomas Schneider
* @version $Revision$
*/
public class CachingBatchloader {
private static CachingBatchloader self;
/** genService */
IGenericService genService;
/** cache, holding all {@link Part}s where {@link Part#cache} is true */
Map> cache;
/** the next batch {@link Part}s to load through {@link #execute()} */
Collection> nextBatchParts;
/** mode on getting cached data through {@link #get(Class, String)} */
boolean autoExecute = true;
private CachingBatchloader() {
this(ServiceFactory.getGenService());
}
private CachingBatchloader(IGenericService genService) {
this.genService = genService;
nextBatchParts = new LinkedList>();
cache = new HashMap>();
}
public static CachingBatchloader init(IGenericService genService, boolean autoExecute) {
self = new CachingBatchloader(genService);
self.autoExecute = autoExecute;
return self;
}
/**
* instance
*
* @return singelton
*/
public static final CachingBatchloader instance() {
if (self == null) {
self = new CachingBatchloader();
}
return self;
}
public static void reset() {
self = null;
}
/**
* adds the given part to the batch loading list - to be executed later
*
* @param id part id
* @param cache whether to cache the result in memory
* @param finders for getting the data
* @return this instance itself
*/
public CachingBatchloader add(String id, boolean cache, AbstractFinder... finders) {
Class resultType = (Class) finders[0].getResultType();
Part part = new Part(id, resultType, cache);
part.setFinders(finders);
return add(part);
}
/**
* adds the given part to the batch loading list - to be executed later
*
* @param batchPart batch loading part
* @return this instance itself
*/
public CachingBatchloader add(Part> batchPart) {
nextBatchParts.add(batchPart);
return this;
}
/**
* executes all batch parts. nothing will be returned to optimize performance. to access the data, use
* {@link #get(Class, String)} and {@link #getSingle(Class, String)}.
*/
public void execute() {
try {
Part[] loadedParts = genService.findBatch(nextBatchParts.toArray(new Part[0]));
for (int i = 0; i < loadedParts.length; i++) {
if (loadedParts[i].isCache()) {
cache.put(loadedParts[i].getId(), loadedParts[i]);
}
}
} finally {
nextBatchParts.clear();
}
}
/**
* get cached result list
*
* @param result type
* @param type result type
* @param partId part id, identifying the data
* @return data or null
*/
public Collection get(Class type, String partId) {
Part> part = cache.get(partId);
if (part == null && nextBatchParts.contains(new Part(partId))) {
if (autoExecute) {
execute();
part = cache.get(partId);
} else {
throw ManagedException.implementationError("the batch-loading wasn't started yet! you have to call 'execute' before getting the data",
partId);
}
}
return (Collection) (part != null ? part.getResult() : null);
}
/**
* get cached result as single object. use {@link #get(Class, String)} to obtain a list of elements.
*
* @param result type
* @param type result type
* @param partId part id, identifying the data
* @return data or null
*/
public T getSingle(Class type, String partId) {
Collection result = get(type, partId);
if (result != null) {
if (result.size() == 1) {
return result.iterator().next();
} else {
throw ManagedException.implementationError("the cache for " + type
+ "|"
+ partId
+ " is not a single result. the cache contains"
+ result.size()
+ " elements for that!", "getSingle()", "get()");
}
}
return null;
}
/**
* reloads all cache data
*/
public void reloadCache() {
genService = ServiceFactory.getGenService();
nextBatchParts.addAll(cache.values());
execute();
}
/**
* resets the cached data
*
* @param partIds parts to reset - if no parts are given, all parts will be reset.
*/
public void reset(String... partIds) {
nextBatchParts.clear();
if (partIds.length == 0) {
partIds = (String[]) cache.keySet().toArray();
}
for (int i = 0; i < partIds.length; i++) {
if (cache.remove(partIds[i]) == null) {
throw ManagedException.implementationError("cache item couldn't be removed!",
partIds[i],
cache.keySet());
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy