package center.task;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import ru.vassaev.core.thread.LogEvent;
import ru.vassaev.core.thread.Processed;
import ru.vassaev.core.thread.PoolThread;
import ru.vassaev.core.thread.ThreadEventListener;
import ru.vassaev.core.types.TimeList;
import ru.vassaev.core.base.Null;
import ru.vassaev.core.base.WValue;
import ru.vassaev.core.exception.SysException;
import ru.vassaev.core.exception.SysRuntimeException;
import ru.vassaev.core.io.OutputByteBuffer;
import ru.vassaev.core.util.Strings;
import center.task.api.ATaskAPI;
import center.task.api.ITaskAPI;
import center.task.prm.IDependentParam;
import center.task.prm.Recipient;
import center.task.prm.Type;
/**
* Контекст задачи
*
* @author Vassaev A.V.
* @version 1.0 1/04/2011
*/
public final class Context {
public long id_task;
public long id_subject;
public ITaskAPI ta;
public final ATaskInfo info;
private final Map<String, WaitValue> prms_eval;
public final Map<String, TimeList> prms_time;
public final Context parent;
public final void setEvent(IDependentParam prm, LogEvent le) {
prm.setEvent(le);
}
/**
* Конструктор
*
* @param id_subject
* - идентификатор приложения
* @param id_task
* - идентификатор задачи
* @param ta
* - API интерфейс
* @param info
* - конфигурация задачи
*/
public Context(long id_subject, long id_task, ITaskAPI ta, ATaskInfo info) {
this.id_task = id_task;
this.id_subject = id_subject;
this.info = info;
this.ta = ta;
this.prms_eval = new HashMap<String, WaitValue>();
this.prms_time = new HashMap<String, TimeList>();
parent = null;
}
public Context(Context parent, long id_subject, long id_task, ITaskAPI ta,
ATaskInfo info) {
this.id_task = id_task;
this.id_subject = id_subject;
this.info = info;
this.ta = ta;
this.prms_eval = new HashMap<String, WaitValue>();
this.prms_time = new HashMap<String, TimeList>();
this.parent = parent;
}
public final Object sync_eval = new Object();
public static final String[] getFullName(String fullname) {
if (fullname == null)
return new String[] { null, null };
int i = fullname.indexOf('/');
if (i > 0)
return new String[] { fullname.substring(0, i), fullname.substring(i + 1) };
else if (i == 0)
return new String[] { null, fullname.substring(i + 1) };
return new String[] { null, fullname };
}
public static final String getFullName(String grp, String name) {
String fullname = grp;// grp
if (fullname != null)
fullname = fullname + "/" + name;
else
fullname = name;// name
return fullname;
}
public PreparedStatement getParamStatement(String[] fn, Connection con)
throws SQLException {
PreparedStatement fnd;
if (fn[0] == null) {
if (fn[1] == null) {
fnd = con.prepareStatement("select *\n"
+ " from params where task_id=? and name is null and grp is null");
fnd.setLong(1, id_task);
} else {
fnd = con.prepareStatement("select *\n"
+ " from params where task_id=? and name=? and grp is null");
fnd.setLong(1, id_task);
fnd.setString(2, fn[1]);
}
} else {
if (fn[1] == null) {
fnd = con.prepareStatement("select *\n"
+ " from params where task_id=? and name is null and grp=?");
fnd.setLong(1, id_task);
fnd.setString(2, fn[0]);
} else {
fnd = con.prepareStatement("select *\n"
+ " from params where task_id=? and name=? and grp=?");
fnd.setLong(1, id_task);
fnd.setString(2, fn[1]);
fnd.setString(3, fn[0]);
}
}
return fnd;
}
public Map<String, Object> getGroupParams(String group) throws SysException {
Map<String, Object> res = ta.getGroupParams(id_task, group);
for (String k : info.prms.keySet()) {
String[] n = getFullName(k);
if (group.equals(n[0])) {
Object o = info.prms.get(k);
if ((o != null) && (o instanceof IDependentParam)) {
IDependentParam p = (IDependentParam) o;
if (res.get(k) == null || p.isNonDB()) {
res.put(k, o);
}
} else if (res.get(k) == null) {
res.put(k, o);
}
}
}
return res;
}
public final String getPrmString(String fullname) throws SysException {
return Strings.getString(getPrmByFullName(fullname));
}
public final String getPrmNvl(String fullname, String nvl)
throws SysException {
Object value = getPrmByFullName(fullname);
if (Null.equ(value))
value = nvl;
return Strings.getString(value);
}
public final long getPrmNvl(String fullname, long nvl) throws SysException {
Object value = getPrmByFullName(fullname);
if (Null.equ(value))
value = nvl;
return Strings.parseIntegerNvl(value, nvl);
}
public final int getPrmNvl(String fullname, int nvl) throws SysException {
Object value = getPrmByFullName(fullname);
if (Null.equ(value))
value = nvl;
return Strings.parseIntegerNvl(value, nvl);
}
public final boolean getPrmNvl(String fullname, boolean nvl)
throws SysException {
Object val = getPrmByFullName(fullname);
if (Null.equ(val))
val = nvl;
return Strings.parseBooleanNvl(val, nvl);
}
public final String getString(Object val) throws CalculateException {
if (Null.equ(val))
return null;
if (val instanceof Type) {
return Strings.getString(((Type) val).getValue(this));
}
return Strings.getString(val);
}
public final OutputByteBuffer getOutputByteBuffer(Object val, String charset)
throws SysException, CalculateException {
if (Null.equ(val))
return null;
if (val instanceof Type) {
val = ((Type) val).getValue(this);
if (Null.equ(val))
return null;
}
if (val instanceof OutputByteBuffer)
return (OutputByteBuffer) val;
try {
return OutputByteBuffer.getOutputByteBuffer(val, charset);
} catch (IOException e) {
throw new SysException(e);
}
}
public final Object getPrmObjNvl(String fullname, Object nvl)
throws SysException {
Object value = getPrmByFullName(fullname);
if (Null.equ(value))
value = nvl;
return value;
}
public final TimeList getTimeList(String name, IDependentParam p) {
TimeList tl;
synchronized (prms_time) {
tl = prms_time.get(name);
if (tl == null) {
if (p != null && p.getTrace())
tl = new TimeList(name, true);
else
tl = new TimeList(name);
prms_time.put(name, tl);
}
}
return tl;
}
public void log(boolean base, Object...objs) throws SysException {
if (!info.log) return;
StringBuffer sb = new StringBuffer();
String s;
for(Object o : objs) {
if (o == null) {
sb.append("null");
continue;
}
synchronized(o) {
s = o.toString();
}
if (s == null) {
sb.append("null");
continue;
}
sb.append(s);
}
try {
ta.log(id_subject, id_task, sb.toString(), base);
} catch (SysException e) {
id_subject = ATaskAPI.getApplicationSubject(ta);
}
}
public Object getObjectByName(String name) throws SysException {
if (name == null)
return null;
if (name.indexOf("tsk.") == 0) {
return ta.getParamTask(id_task, name.substring(4));
} else if (name.indexOf("prm.") == 0) {
return getPrmByFullName(name.substring(4));
}
return null;
}
public class WaitValue extends WValue implements Processed<String> {
private final String gl_name;
private Object def;
private boolean log = true;
private WaitValue(String gl_name) {
super();
this.gl_name = gl_name;
Object o = Context.this.info.getPrmInfo(gl_name);
log = true;
if (o != null && o instanceof IDependentParam)
log = ((IDependentParam) o).getLog();
if (gl_name == null || gl_name.length() == 0)
throw new SysRuntimeException("Parameter can't be named as \"null\"");
}
private WaitValue(String gl_name, Object def) {
this(gl_name);
this.def = def;
}
public Object getValueIm() throws Throwable {
Object value = super.getValueIm();
if (log)
Context.this.log(false, "SYNC:", gl_name, "(IM)=", value);
return value;
}
public Object getValueWait() throws Throwable {
Object value = super.getValueWait();
if (value instanceof WaitValue)
value = ((WaitValue) value).getValueWait();
if (log)
Context.this.log(false, "SYNC:", gl_name, "(WX)=", value);
return value;
}
public Object getValueWait(long timeout) throws Throwable {
long to = timeout;
long start = System.currentTimeMillis();
Object value = super.getValueWait(to);
long end = System.currentTimeMillis();
if (value instanceof WaitValue) {
if (timeout >= 0 && end - start < timeout)
value = ((WaitValue) value).getValueWait(timeout - (end - start));
else
value = ((WaitValue) value).getValueIm();
}
if (log)
Context.this.log(false, "SYNC:", gl_name, "(WT)=", value);
return value;
}
public String toString() {
try {
return "WAIT(" + super.toString() + ")";
} catch (Throwable e) {
return "WAIT(" + super.toString() + ")";
}
}
public void processing(String fullname) throws Throwable {
boolean db = true;
boolean cache = false;
String gl_name = "prm." + fullname;
Object o = info.prms.get(fullname);
IDependentParam p = null;
boolean log = true;
if (o != null && o instanceof IDependentParam) {
p = (IDependentParam) o;
db = !p.isNonDB();
cache = p.isCache();
log = p.getLog();
}
Object result = null;
try {
// Проверить кэшируемость параметра
if (cache) {
synchronized (sync_eval) {
result = prms_eval.get(gl_name);
// Если расчёт не производился, получить новый буфер для расчёта
//System.out.println("001 ::: " + fullname);
if (result == null) {
//System.out.println("002 ::: " + fullname);
prms_eval.put(gl_name, this);
}
}
if (result != null) {
if (log)
Context.this.log(false, "ASYNC:", gl_name, "(CACHE)=", result);
// System.out.println(Context.this.ta.getAlias() + " : " +
// Context.this.id_task + " : ASYNC:" + gl_name + "(CACHE)=" +
// result);
if (!result.equals(this)) {
retValue(result);
//System.out.println("003 ::: " + fullname);
return;
}
result = this.getValueIm();
if (result != null) {
return;
}
}
}
// Если не запрещено из базы
if (db) {
//System.out.println("004 ::: " + fullname);
result = ta.getParam(id_task, fullname);
if (!Null.equ(result)) {
if (log)
Context.this.log(false, "ASYNC:", gl_name, "(DB)=", result);
// System.out.println(Context.this.ta.getAlias() + " : " +
// Context.this.id_task + " : ASYNC:" + gl_name + "(DB)=" + result);
retValue(result);
//System.out.println("005 ::: " + fullname);
return;
}
}
if (p != null) {
TimeList tl = getTimeList(gl_name, p);
result = p.calculate(tl, Context.this);
//System.out.println("006 ::: " + fullname);
if (p.getTrace())
tl.printTrace();
p.executeCopyTo(Context.this, result);
}
if (log)
Context.this.log(false, "ASYNC:", gl_name, "=", result);
// System.out.println(Context.this.ta.getAlias() + " : " +
// Context.this.id_task + " : ASYNC:" + gl_name + "=" + result);
retValue(result);
//System.out.println("007 ::: " + fullname);
} catch (Throwable t) {
retException(t);
throw t;
}
}
}
/**
* Установка параметра Можно установить только либо кэшируемый параметр, либо
* параметр базы данных Параметр, который не кэшируется и не из базы данных
* установить нельзя
*
* @param fullname
* - полное имя параметра в пространстве prm
* @param obj
* - устанавливаемое значение
* @param cloneValue
* - true - копировать параметр
* @throws SysException
*/
@SuppressWarnings("finally")
public final boolean setPrmByFullName(String fullname, Object obj,
boolean cloneValue) throws SysException {
String fn = (fullname == null) ? "" : fullname;
String gl_name = "prm." + fn;
boolean db = true;
boolean cache = false;
IDependentParam p = null;
Map<String, Object> prm = info.getPrmsBySpace("prm");
Object o = prm.get(fn);
boolean log = true;
Object alg = null;
if (o != null && o instanceof IDependentParam) {
p = (IDependentParam) o;
db = !p.isNonDB();
cache = p.isCache();
log = p.getLog();
}
WaitValue v = null;
// Если параметр кэшируемый
if (cache)
try {
synchronized (sync_eval) {
v = prms_eval.get(gl_name);
// Если расчёт не производился, получить новый буфер
if (v == null) {
v = new WaitValue(gl_name, log);
prms_eval.put(gl_name, v);
}
}
} finally {
v.retValue(obj);
return true;
}
// Если не запрещено из базы
if (db) {
long i = ta.setParamObject(id_task, fn, obj);
return (i > 0);
}
if (p != null && (alg = p.getFromSection()) instanceof Recipient) {
((Recipient) alg).adobt(obj);
}
return false;
}
public final boolean setPrmByFullName(String space, String fullname,
Object obj, boolean cloneValue) throws SysException {
String fn = (fullname == null) ? "" : fullname;
String gl_name = space + "." + fn;
boolean db = true;
boolean cache = false;
IDependentParam p = null;
Map<String, Object> prm = info.getPrmsBySpace(space);
Object o = prm.get(fn);
boolean log = true;
if (o != null && o instanceof IDependentParam) {
p = (IDependentParam) o;
db = !p.isNonDB();
cache = p.isCache();
log = p.getLog();
}
WaitValue v = null;
// Если параметр кэшируемый
if (cache)
synchronized (sync_eval) {
v = prms_eval.get(gl_name);
// Если расчёт не производился, получить новый буфер
if (v == null) {
v = new WaitValue(gl_name, log);
prms_eval.put(gl_name, v);
}
v.retValue(obj);
return true;
}
// Если не запрещено из базы
if (db) {
long i = ta.setParamObject(id_task, fn, obj);
return (i > 0);
}
return false;
}
public final boolean isPresentPrm(String space, String fullname) {
Map<String, Object> prm = info.getPrmsBySpace(space);
String fn = (fullname == null) ? "" : fullname;
Object o = prm.get(fn);
if (o != null && o instanceof IDependentParam) {
return true;
}
return false;
}
public final Object getPrm(String space, String fullname, long timeout)
throws Throwable {
//if (fullname.equals("BODY"))
// System.out.println("!!!");
String fn = (fullname == null) ? "" : fullname;
String gl_name = space + "." + fn;
boolean db = true;
boolean cache = false;
IDependentParam p = null;
// TODO надо оптимизировать!!
Map<String, Object> prm = info.getPrmsBySpace(space);
Object o = prm.get(fn);
boolean log = true;
if (o != null && o instanceof IDependentParam) {
p = (IDependentParam) o;
db = !p.isNonDB();
cache = p.isCache();
log = p.getLog();
}
WaitValue v = null;
Object result = null;
// Проверить кэшируемость параметра
if (cache) {
synchronized (sync_eval) {
result = prms_eval.get(gl_name);
// Если расчёт не производился, получить новый буфер для расчёта
//System.out.println("101 ::: " + fullname);
if (result == null) {
v = new WaitValue(gl_name, log);
prms_eval.put(gl_name, v);
//System.out.println("102 ::: " + fullname);
}
}
if (result != null) {
if (result instanceof WaitValue) {
result = ((WaitValue) result).getValueWait(timeout);
//System.out.println("103 ::: (" + timeout + ") " + fullname);
}
if (log)
Context.this.log(false, "SYNC:", gl_name, "(CACHE)=", result);
// System.out.println(Context.this.ta.getAlias() + " : " +
// Context.this.id_task + " : SYNC:" + gl_name + "(CACHE)=" + result);
return result;
} else {
//System.out.println("104 ::: " + fullname);
}
}
// Если не запрещено из базы
if (db && "prm".equals(space)) {
result = ta.getParam(id_task, fn);
if (!Null.equ(result)) {
if (log)
Context.this.log(false, "SYNC:", gl_name, "(DB)=", result);
if (v != null) // Кэшируемый параметр
v.retValue(result);
// System.out.println(Context.this.ta.getAlias() + " : " +
// Context.this.id_task + " : SYNC:" + gl_name + "(DB)=" + result);
//System.out.println("105 ::: " + fullname);
return result;
}
}
if (p != null) {
try {
TimeList tl = getTimeList(gl_name, p);
result = p.calculate(tl, this);
//System.out.println("106 ::: " + fullname);
if (p.getTrace())
tl.printTrace();
} catch (CalculateException e) {
if (v != null)
v.retException(e);
throw e;
}
p.executeCopyTo(this, result);
}
if (log)
Context.this.log(false, "SYNC:", gl_name, "=", result);
if (v != null)
v.retValue(result);
// System.out.println(Context.this.ta.getAlias() + " : " +
// Context.this.id_task + " : SYNC:" + gl_name + "=" + result);
//System.out.println("107 ::: " + fullname);
return result;
}
public final Object getPrmByFullName(String fullname) throws SysException {
try {
return getPrm("prm", fullname, 0);
} catch (SysException e) {
throw e;
} catch (Throwable e) {
throw new SysException(e);
}
}
public final Object getPrmByFullName(String fullname, long timeout)
throws SysException {
try {
return getPrm("prm", fullname, timeout);
} catch (SysException e) {
throw e;
} catch (Throwable e) {
Throwable t = e.getCause();
if (t != null && t instanceof SysException)
throw (SysException) t;
throw new SysException(e);
}
}
public final WaitValue getPrmAsync(PoolThread pool, String fullname)
throws SysException {
WaitValue wv = new WaitValue("prm." + fullname);
pool.start_target("get_" + fullname, wv, fullname, null, null);
return wv;
}
public final WaitValue getPrmAsync(PoolThread pool, String fullname,
Collection<ThreadEventListener> lst) throws SysException {
WaitValue wv = new WaitValue("prm." + fullname);
pool.start_target("get_" + fullname, wv, fullname, null, lst);
return wv;
}
}