1 package org.ibex.xt.shell;
5 import java.util.regex.*;
9 public abstract class Request implements Serializable {
11 public abstract Response process(JSScope root) throws JSExn;
13 public static class Response implements Serializable {
14 protected Exception ex;
15 public Response() { ex = null; }
16 public Response(Exception e) { ex = e; }
17 public Exception error() { return ex; }
20 public static class Key extends Request {
21 protected String path, matcher;
24 /** Expects a shell-path that uses '.' as a seperator and * for wildcard. */
25 public Key(String c) {
26 int pos = c.lastIndexOf('.');
27 path = c.substring(0, pos);
28 matcher = c.substring(pos + 1).replaceAll("\\*+", ".*");
31 public Key(String path, String matcher) {
32 this.path = path; this.matcher = matcher;
35 /** Returns the object referenced by path. */
36 protected Object path(JSScope root) throws JSExn {
37 String p = path == null ? "" : path.replaceAll("\\.+", "\\.");
38 if (p.length() > 0 && p.charAt(0) == '.')
40 if (p.length() > 0 && p.charAt(p.length() - 1) == '.')
41 p = p.substring(0, p.length() - 1);
43 return p.equals("") ? root : root.get(p);
46 /** Returns the keys in <tt>js</tt> that match <tt>matcher</tt>. */
47 protected List matches(JS js) throws JSExn {
50 Pattern pat = Pattern.compile(m);
51 List keys = new ArrayList();
53 Iterator i = js.keys().iterator(); while(i.hasNext()) {
54 String k = i.next().toString();
55 if (pat.matcher(k).matches()) keys.add(k);
61 /** Returns <tt>o</tt> cast as a JS if it is such and has keys,
62 * otherwise returns null. */
63 protected JS keyed(Object o) {
64 // FIXME: replace this with a canHaveKeys() function in org.ibex.js.JS
65 return o == null || !(o instanceof JS) ||
66 o instanceof JSDate || o instanceof Directory ||
67 o instanceof Grammar || o instanceof JSMath ||
68 o instanceof JSReflection || o instanceof JSRegexp ?
72 public Response process(JSScope root) throws JSExn {
73 JS js = keyed(path(root));
75 // if matcher is exact and a keyed object, return its keys
76 JS o = keyed(js.get(matcher));
77 if (o != null) { js = o; matcher = ".*"; }
79 return js == null ? new Res() : new Res(matches(js));
82 public static class Res extends Response {
84 public Res() { keys = null; }
85 public Res(List l) { keys = l; }
86 public List keys() { return keys; }
87 public boolean isPath() { return keys != null; }
91 public static class IsKey extends Key {
93 public IsKey(String c) { super(c); }
94 public Response process(JSScope root) throws JSExn {
95 JS js = keyed(path(root));
96 return js == null ? new Res(false) : new Res(js.get(matcher) != null);
99 public static class Res extends Response {
100 private boolean exists;
102 public Res(boolean e) { exists = e; }
103 public boolean exists() { return exists; }
107 public static class RemoveKey extends Key {
108 public RemoveKey(String c) { super(c); }
109 public RemoveKey(String p, String m) { super(p, m); }
110 public Response process(JSScope root) throws JSExn {
111 JS js = keyed(path(root));
112 if (js == null) throw new JSExn("no such path");
113 boolean rm = js.containsKey(matcher);
114 if (rm) js.remove(matcher);
118 public static class Res extends Response {
119 private boolean removed;
121 public Res(boolean rm) { removed = rm; }
122 public boolean removed() { return removed; }
126 public static class SetKey extends Key {
129 public SetKey(String p, String m, JS val) { super(p, m); this.value = val; }
131 public Response process(JSScope root) throws JSExn {
132 JS js = keyed(path(root));
133 if (js == null) throw new JSExn("no such path");
135 js.put(matcher, JS.eval(JS.cloneWithNewParentScope(
136 value, new JSResolve(root, js))));
137 return new Res(); // TODO: return put() value when it has one
140 public class Res extends Response {
143 public class JSResolve extends JSScope {
145 public JSResolve(JSScope parent, JS path) { super(parent); this.path = path; }
146 public Object get(Object key) throws JSExn {
147 if (key != null && key instanceof String) {
148 String k = (String)key;
149 if (k.startsWith(".")) k = k.substring(1);
150 else return path.get(k);
152 return super.get(key);
154 public void put(Object key, Object val) throws JSExn {
155 if (key != null && key instanceof String) {
156 String k = (String)key;
157 if (k.startsWith(".")) k = k.substring(1);
158 else { path.put(key, val); return; }
165 /** Runs a series of requests. */
166 public static class Composite extends Request {
167 private boolean breakOnError = false;
168 private Request[] requests;
169 public Composite() {}
170 public Composite(Request[] r, boolean breakOnError) {
172 this.breakOnError = breakOnError;
174 public Composite(List r, boolean breakOnError) {
175 Request[] req = new Request[r.size()];
178 this.breakOnError = breakOnError;
181 public Response process(JSScope root) {
182 Response[] res = new Response[requests.length];
184 for (int i=0; i < requests.length; i++) {
185 try { res[i] = requests[i].process(root); }
187 res[i] = new Response(e);
190 Response[] newres = new Response[i + 1];
191 System.arraycopy(res, 0, newres, 0, newres.length);
201 public static class Res extends Response {
202 private Response[] responses;
204 public Res(Response[] r) { responses = r; }
205 public Response get(int i) { return responses[i]; }
206 public int size() { return responses.length; }
207 public Response[] responses() { return responses; }