package center.task.prm.alg;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import ru.vassaev.core.exception.SysException;
import ru.vassaev.core.types.TimeList;
import ru.vassaev.core.types.TimeList.Type;
import ru.vassaev.core.util.Strings;
import center.task.CalculateException;
import center.task.Context;
import center.task.prm.Alg;
public class Merge extends Alg {
private static enum ParamType {BIND, SYS, ENV, THR, CHRX}
private final String bind_tag;
private final String chrx_tag;
private final String sys_tag;
private final String env_tag;
private final String thr_tag;
private final Set<String> bind_set;
private class ParamInfo {
String name;
ParamType pt;
public ParamInfo(String name, ParamType pt) {
this.name = name;
this.pt = pt;
}
}
private ArrayList<Object> query;
private void setExpression(Element expr) throws SysException {
bind_set.clear();
query = new ArrayList<Object>();
NodeList nl = expr.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node n = nl.item(i);
short t = n.getNodeType();
if (t == Node.ELEMENT_NODE) {
Element el = (Element) n;
String name = el.getTextContent();
String nn = el.getNodeName();
if (nn.equals(bind_tag)) { // Связанная переменная
query.add(new ParamInfo(name, ParamType.BIND));
bind_set.add(name);
} else if (nn.equals(sys_tag)) { // системное свойство
query.add(new ParamInfo(name, ParamType.SYS));
} else if (nn.equals(env_tag)) { // параметр системы
query.add(new ParamInfo(name, ParamType.ENV));
} else if (nn.equals(thr_tag)) { // параметр времени выполнения
query.add(new ParamInfo(name, ParamType.THR));
} else if (nn.equals(chrx_tag)) { // символ
String encoding = el.getAttribute("encoding");
if (encoding == null || encoding.length() == 0)
encoding = "utf8";
try {
query.add(new String(Strings.parseHexStr2Byte(name), encoding));
} catch (UnsupportedEncodingException e) {
throw new SysException(e);
}
}
} else if (t == Node.TEXT_NODE) {
Text txt = (Text) n;
query.add(txt.getData());
}
}
}
public Merge(center.task.prm.Type tp, String owner, Element e) {
this(tp, owner, e, null);
}
protected Merge(center.task.prm.Type tp, String owner, Element e, String tag) {
super(tp, owner);
if (!e.hasAttribute("bind_tag"))
this.bind_tag = "b";
else
this.bind_tag = e.getAttribute("bind_tag");
if (!e.hasAttribute("sys_tag"))
this.sys_tag = "s";
else
this.sys_tag = e.getAttribute("sys_tag");
if (!e.hasAttribute("env_tag"))
this.env_tag = "е";
else
this.env_tag = e.getAttribute("env_tag");
if (!e.hasAttribute("thr_tag"))
this.thr_tag = "t";
else
this.thr_tag = e.getAttribute("thr_tag");
if (!e.hasAttribute("chrx_tag"))
this.chrx_tag = "x";
else
this.chrx_tag = e.getAttribute("chrx_tag");
bind_set = new HashSet<String>();
Element t = null;
if (tag != null)
t = (Element) Strings.getXMLObject(e, tag);
try {
if (t == null)
setExpression(e);
else
setExpression(t);
} catch (SysException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
protected Object calculate(TimeList tl, Context cntx) throws CalculateException {
try {
tl.addPointTime(Type.START);
StringBuffer sb = new StringBuffer();
String v;
Object o;
ParamInfo pi;
ru.vassaev.core.thread.Process prc = ru.vassaev.core.thread.Process.currentProcess();
int l = query.size();
for (int i = 0; i < l; i++) {
o = query.get(i);
if (o instanceof String)
sb.append(o);
else {
try {
tl.addPointTime(Type.WAIT);
pi = (ParamInfo)o;
if (ParamType.BIND.equals(pi.pt))
v = cntx.getPrmString(pi.name);
else if (ParamType.SYS.equals(pi.pt))
v = System.getProperty(pi.name);
else if (ParamType.THR.equals(pi.pt))
v = Strings.getString(prc.getResourceByName(pi.name));
else
v = System.getenv(pi.name);
tl.addPointTime(Type.END_WAIT);
if (v != null)
sb.append(v);
} catch (SysException e) {
throw new CalculateException(owner, e);
}
}
}
return sb;
} finally {
tl.addPointTime(Type.END);
}
}
public Set<String> depedentOn() {
return new HashSet<String>(bind_set);
}
public Set<String> depedentOnParent() {
return null;
}
}