package center.task.prm.alg;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import ru.vassaev.core.container.ApplicationManager;
import ru.vassaev.core.exception.SysException;
import ru.vassaev.core.exception.SysRuntimeException;
import ru.vassaev.core.thread.PoolThread;
import ru.vassaev.core.thread.Process;
import ru.vassaev.core.thread.ThreadEventListener;
import ru.vassaev.core.types.TimeList;
import ru.vassaev.core.types.TimeList.Type;
import ru.vassaev.core.util.Strings;
import ru.vassaev.core.util.Xml;
import center.task.CalculateException;
import center.task.Context;
import center.task.Context.WaitValue;
import center.task.prm.Alg;
import center.task.prm.Prm;
public class TheFirst extends Alg {
private final Map<String, Prm> prms;
private String prcpool;
private PoolThread prcs;
public TheFirst(center.task.prm.Type tp, String owner) {
super(tp, owner);
prms = new HashMap<String, Prm>();
}
private long wait;
private Element def;
public TheFirst(center.task.prm.Type tp, String owner, Element e) {
this(tp, owner);
NodeList le = Xml.getElementsByTagName(e, "prm");
for (int i = le.getLength() - 1; i >= 0; i--) {
Prm p = Prm.getLink((Element)le.item(i));
prms.put(p.fullname, p);
}
if (e.hasAttribute("prcpool")) {
prcpool = e.getAttribute("prcpool");
try {
prcs = (PoolThread) ApplicationManager.getPoolByName(prcpool, Process.class);
} catch (SysException e1) {
throw new SysRuntimeException("There is no pool by name '" + prcpool + "'");
}
} else
throw new SysRuntimeException("There is no prcpool attribute");
if (e.hasAttribute("wait")) {
try {
wait = Strings.parseIntegerNvl(e.getAttribute("wait"), 10000);
} catch (NumberFormatException e1) {
throw new SysRuntimeException("Attribute by name 'wait' isn't correct", e1);
}
} else
wait = 10000;
def = (Element) Strings.getXMLObject(e, "default");
}
private class Sync {
boolean parent = false;
String result = null;
}
private class TEL implements ThreadEventListener {
private Sync sync;
private boolean parent;
public TEL(Sync sync, boolean parent) {
super();
this.parent = parent;
this.sync = sync;
}
public Sync getObj(long timeout) {
synchronized(sync) {
if (sync.result != null)
return sync;
try {
sync.wait(timeout);
} catch (InterruptedException e) {
e.printStackTrace();
return null;
}
return sync;
}
}
public void on(EventType tp, Process prc, Object prm) {
System.out.println("+++" + tp.toString() + " " + prm.toString());
if (EventType.FINISH.equals(tp))
synchronized(sync) {
if (sync.result == null) {
sync.result = prm.toString();
sync.parent = parent;
sync.notifyAll();
}
}
}
}
protected Object calculate(TimeList tl, Context cntx)
throws CalculateException {
tl.addPointTime(Type.START);
Object o;
WaitValue wv;
Map<String, WaitValue> r = new HashMap<String, WaitValue>();
Map<String, WaitValue> r_parent = new HashMap<String, WaitValue>();
Sync sync = new Sync();
ArrayList<ThreadEventListener> ntf = new ArrayList<ThreadEventListener>();
TEL tel = new TEL(sync, false);
ntf.add(tel);
ArrayList<ThreadEventListener> ntf_parent = new ArrayList<ThreadEventListener>();
TEL tel_parent = new TEL(sync, true);
ntf_parent.add(tel_parent);
try {
for(Prm p : prms.values()) {
try {
if (p.isParent)
o = p.getObjectWait(cntx, prcs, ntf_parent);
else
o = p.getObjectWait(cntx, prcs, ntf);
if (o != null && o instanceof WaitValue) {
wv = (WaitValue)o;
if (p.isParent)
r_parent.put(p.fullname, wv);
else
r.put(p.fullname, wv);
} else {
return o;
}
} catch (SysException e) {
e.printStackTrace();
}
}
Sync obj = tel.getObj(wait);
if (obj != null)
try {
if (obj.parent)
return r_parent.get(obj.result).getValueIm();
else
return r.get(obj.result).getValueIm();
} catch (Throwable e) {
throw new CalculateException(owner, e);
}
else {
if (def != null)
return Prm.getConst(def);
return null;
}
} finally {
tl.addPointTime(Type.END);
}
}
public Set<String> depedentOn() {
Set<String> list = new HashSet<String>();
for (Prm p : prms.values()) {
if (!p.isParent)
list.add(p.fullname);
}
return list;
}
public Set<String> depedentOnParent() {
Set<String> list = new HashSet<String>();
for (Prm p : prms.values()) {
if (p.isParent)
list.add(p.fullname);
}
return list;
}
}