de.tsl2.nano.incubation.specification.Pool Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tsl2.nano.specification Show documentation
Show all versions of tsl2.nano.specification Show documentation
TSL2 Framework Specification (Pools of descripted and runnable Actions and Rules, Generic Tree)
/*
* File: $HeadURL$
* Id : $Id$
*
* created by: Tom, Thomas Schneider
* created on: 26.02.2014
*
* Copyright: (c) Thomas Schneider 2014, all rights reserved
*/
package de.tsl2.nano.incubation.specification;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import de.tsl2.nano.core.ENV;
import de.tsl2.nano.core.ManagedException;
import de.tsl2.nano.core.cls.BeanClass;
import de.tsl2.nano.core.log.LogFactory;
import de.tsl2.nano.core.util.FileUtil;
import de.tsl2.nano.core.util.StringUtil;
import de.tsl2.nano.execution.IPRunnable;
/**
* Generic Pool holding all defined (loaded) instances of an {@link IPRunnable} implementation. Useful for e.g. Rules,
* Queries and Actions.
* The runnable types must registere itself through {@link #registerTypes(Class...)} and must implement IPrefixed, used
* has prefix for the key name. So, on calling get(..) you should give the name with prefix or you provide the runnable type.
*
* should be used as singelton by a service-factory. persists its runnables in a directory, given by
* {@link #getDirectory()} (using the pool instance generic type as directory name).
*
* It is possible to hold different extensions of the given generic type. Then you access them through
* {@link #get(String, Class)} - otherwise it is sufficient to call {@link #get(String)} using internally the default
* type, evaluated by {@link #getType()}.
*
* @author Tom, Thomas Schneider
* @version $Revision$
*/
@SuppressWarnings("rawtypes")
public class Pool {
private static final Log LOG = LogFactory.getLog(Pool.class);
Map runnables;
transient private String expressionPattern;
private static Set> registeredTypes = new HashSet<>();
public static void registerTypes(Class extends IPRunnable>...types) {
for (int i = 0; i < types.length; i++) {
if (!IPrefixed.class.isAssignableFrom(types[i]))
throw new IllegalArgumentException("type " + types[i] + " must implement IPrefixed!");
registeredTypes.add(types[i]);
}
}
private Map runnables() {
if (runnables == null)
loadRunnables();
return runnables;
}
public String getFullExpressionPattern() {
if (registeredTypes.isEmpty())
throw new IllegalStateException("no types registered at pool. please register at least one runnable type!");
if (expressionPattern == null) {
StringBuilder buf = getExpressionPattern();
buf.append(".*");
expressionPattern = buf.toString();
}
return expressionPattern;
}
public StringBuilder getExpressionPattern() {
StringBuilder buf = new StringBuilder("[");
for (Class extends IPRunnable> t : registeredTypes) {
buf.append(((IPrefixed)BeanClass.createInstance(t)).prefix());
}
buf.append("]");
return buf;
}
public void saveAll() {
runnables().forEach( (k, v) -> add(k, v));
}
public void loadRunnables() {
runnables = new HashMap<>();
for (Class extends IPRunnable> type : registeredTypes) {
String dirName = getDirectory(type);
LOG.info("loading " + type.getSimpleName().toLowerCase() + "(s) from " + dirName);
File dir = FileUtil.userDirFile(dirName);
File[] runnableFiles = dir.listFiles();
for (int i = 0; i < runnableFiles.length; i++) {
try {
if (runnableFiles[i].getPath().endsWith(ENV.getFileExtension()))
loadRunnable(runnableFiles[i].getPath(), type);
} catch (Exception e) {
LOG.error(e);
}
}
}
}
public String getDirectory(Class extends IPRunnable> rType) {
String dir = ENV.getConfigPathRel() + "specification/" + (rType != null ? rType.getSimpleName().toLowerCase() + "/" : "");
FileUtil.userDirFile(dir).mkdirs();
return dir;
}
private I loadRunnable(String path, Class type) {
try {
I r = ENV.load(path, type, false);
runnables.put(getPrefixedName(r), r);
return r;
} catch (Exception e) {
ManagedException.forward(e);
return null;
}
}
private String getPrefixedName(IPRunnable r) {
return ((IPrefixed)r).prefix() + r.getName();
}
/**
* gets the runnable by name
*
* @param name rule/query to find
* @return rule/query or null
*/
public IPRunnable get(String name) {
return get(name, null);
}
/**
* gets the runnable by name
*
* @param name runnable to find
* @param type runnable type
* @return runnable or null
*/
@SuppressWarnings("unchecked")
public I get(String name, Class type) {
I runnable = (I) runnables().get(name);
if (runnable == null && type != null && !name.matches(getFullExpressionPattern())) {
String n = ((IPrefixed)BeanClass.createInstance(type)).prefix() + name;
runnable = (I) runnables().get(n);
} else if (runnable == null && type == null && !name.matches(getFullExpressionPattern())) {
//search on all runnable types
StringBuilder pattern = getExpressionPattern();
String prefixes = pattern.substring(1, pattern.length()-1);
for (int i=0; i type) {
name = FileUtil.getValidFileName(name);
return name.matches(".*[.][a-z]{3}") ? name : getDirectory(type) + name + ENV.getFileExtension();
}
/**
* delegates to {@link #add(String, IPRunnable)} using {@link IPRunnable#getName()}
*/
public void add(IPRunnable runnable) {
add(getPrefixedName(runnable), runnable);
}
/**
* adds the given runnable to the pool
*
* @param name runnable name
* @param runnable runnable to add
*/
protected void add(String name, IPRunnable runnable) {
runnables().put(name, runnable);
String fileName = getFileName(runnable.getName(), runnable.getClass());
LOG.info("adding runnable '" + name + "' and saving it to " + fileName);
ENV.save(fileName, runnable);
}
/**
* reset
*/
public void reset() {
runnables = null;
}
// for bean evaluation (reflection) only!
public Map getRunnables() {
return runnables;
}
public void setRunnables(Map runnables) {
this.runnables = runnables;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy