package org.nodeclipse.ui.contentassist; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.nodeclipse.ui.util.NodeclipseConsole; import org.nodeclipse.ui.util.ProcessUtils; /** * Node.js Context from Sources all.json. * May be multiple instances, defaultInstance uses bundled all.json file. * * TODO Model population checking is very suitable for Unit Testing * * Example from http.json * <pre> "methods": [ { "textRaw": "http.createServer([requestListener])", "type": "method", "name": "createServer", "desc": "<p>Returns a new web server object.\n\n</p>\n<p>The <code>requestListener</code> is a function which is automatically\nadded to the <code>'request'</code> event.\n\n</p>\n", "signatures": [ { "params": [ { "name": "requestListener", "optional": true } ] } ] }, </pre> * * * @author Paul Verest */ class ContentFromSources { static final String ALL_JSON = "org/nodeclipse/ui/contentassist/all.json"; //public static JSONArray METHODS; JSONObject NodejsContext; Model model; public static boolean checkProperties = true; static ContentFromSources defaultInstance = null; static { defaultInstance = new ContentFromSources(ALL_JSON); } public static ContentFromSources getDefaultInstances() { if (defaultInstance == null) { defaultInstance = new ContentFromSources(ALL_JSON); } return defaultInstance; } public ContentFromSources(String sourcesAllJsonPath) { try { // check if sources to use are selected //String sourcesAllJsonPath = ProcessUtils.getSourcesAllJsonPath(); if ("".equals(sourcesAllJsonPath)) { sourcesAllJsonPath = ALL_JSON; } InputStream is = ContentFromSources.class.getClassLoader().getResourceAsStream(sourcesAllJsonPath); NodejsContext = new JSONObject(inputStream2String(is)); } catch (JSONException e) { log(e.getLocalizedMessage()+"\n"); } catch (IOException e) { log(e.getLocalizedMessage()+"\n"); } // if (defaultInstance == null){ // defaultInstance = this; // } populateModel(); } public static String inputStream2String(InputStream is) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(is)); StringBuilder buffer = new StringBuilder(); // no need for thread-safe StringBuffer buffer = new StringBuffer(); String line = ""; while ((line = in.readLine()) != null) { buffer.append(line); } return buffer.toString(); } /** * Reading JSON file */ private void populateModel(){ // modules30: timers(m8), module, addons, util(m13), Events(c1), domain(m1)(c1), buffer(c2), stream(c4), crypto(m18)(c7), // tls_(ssl)(m5)(c4), stringdecoder(c1), fs(m67)(c4), path(m7), net(m10)(c2), dgram(m1)(c1), dns(m10), http(m4)(c4), https(m3)(c2), // url(m3), querystring(m2), punycode(m4), readline(m1)(c1), repl(m1), vm(m5)(c1), child_process(m4)(c1), assert(m11), tty(m2)(c2), zlib(m14)(c8), os(m13), cluster(m3)(c1) model = new Model(); try { JSONObject nodejsContextJSONObject = NodejsContext; JSONArray modules = nodejsContextJSONObject.getJSONArray("modules"); log("modules"+modules.length()+" "); for (int i = 0; i < modules.length(); i++) { JSONObject module = (JSONObject) modules.get(i); String moduleName = module.getString("name"); debug( ", "+moduleName); Module moduleObj = new Module(moduleName); model.addModule(moduleObj); String moduleDesc = formatedName(moduleName)+module.getString("desc"); Entry moduleEntry = new Entry(moduleObj,EntryType.module,moduleName,moduleName,moduleDesc,null); model.addEntry(moduleEntry); populateCheckProperties(module, moduleName, moduleObj, moduleEntry); if (module.has("methods")) { JSONArray methods = module.getJSONArray("methods"); debug("(m"+methods.length()+")"); for (int j = 0; j < methods.length(); j++) { JSONObject method = (JSONObject) methods.get(j); // example: "textRaw": "http.createServer([requestListener])","type": "method","name": "createServer", String trigger = method.getString("textRaw"); String name = method.getString("name"); String desc = formatedName(name,trigger)+method.getString("desc"); Entry entry = new Entry(moduleObj,EntryType.method,name,trigger,desc,moduleEntry); model.addEntry(entry); } } if (module.has("classes")){ JSONArray classes = module.getJSONArray("classes"); debug("(c"+classes.length()+")"); for (int j = 0; j < classes.length(); j++) { JSONObject clazz = (JSONObject) classes.get(j); // example: "textRaw": "Class: Domain","type": "class","name": "Domain" String trigger = clazz.getString("name"); if (!trigger.startsWith(moduleName)) { trigger=moduleName+'.'+trigger; } String desc = formatedName(trigger,clazz.getString("textRaw"))+clazz.getString("desc"); Entry entry = new Entry(moduleObj,EntryType.clazz,trigger,trigger,desc,moduleEntry); model.addEntry(entry); // Class may have properties, see http.IncomingMessage -> message.httpVersion populateCheckProperties(module, moduleName, moduleObj, entry); } } } } catch (JSONException e) { log(e.getLocalizedMessage()+"\n"+e); } } private void populateCheckProperties(JSONObject obj, String moduleName, Module moduleObj, Entry parent) throws JSONException { if (!checkProperties){ return; } if (obj.has("properties")) { JSONArray properties = obj.getJSONArray("properties"); debug("("+moduleName+".p"+properties.length()+")"); for (int j = 0; j < properties.length(); j++) { JSONObject property = (JSONObject) properties.get(j); // example: see http.json (2 cases) String trigger = property.getString("name"); if (!trigger.startsWith(moduleName)) { trigger=moduleName+'.'+trigger; } String name = property.getString("name"); String desc = formatedName(name,trigger); //+property.getString("desc"); if (property.has("desc")) { desc = desc+property.getString("desc"); }else{ debug("(p"+properties.length()+")"); } Entry entry = new Entry(moduleObj,EntryType.property,name,trigger,desc, null); model.addEntry(entry); // property may have properties, see http.IncomingMessage -> message.httpVersion populateCheckProperties(property, trigger, moduleObj, entry); //TODO methods of properties: http.IncomingMessage -> message.setTimeout(msecs, callback) } } } // href won't be rendered as link private String formatedModuleName(String moduleName) { String res = formatedName(moduleName)+"<a href=\"http://www.nodejs.org/api/"+moduleName+".html\">Node.js Manual & Documentation</a><br/>"; return res; } private String formatedName(String name) { return "<b>"+name+"</b><br/>"; } private String formatedName(String name, String trigger) { return formatedName(name)+"<code>"+trigger+"</code><br/>"; } private static void debug(String s){ //NodeclipseConsole.write(s); System.out.print(s); } private static void log(String s){ //NodeclipseConsole.write(s); System.out.print(s); } //TODO unit tests public static void main(String[] args){ //System.out.println(x); ContentFromSources c = getDefaultInstances(); // new ContentFromSources(ALL_JSON); //c.populateModel(); System.out.println(); System.out.println("- Matches http. :"); List<Entry> matches = c.model.findMatchingEntries("http."); for(Entry entry: matches){ System.out.println(entry); } // modules30 , timers(m8), module, addons, util(m13), Events(c1), domain(m1)(c1), buffer(c2), stream(c4), crypto(m18)(c7), tls_(ssl)(m5)(c4), stringdecoder(c1), fs(m67)(c4), path(m7), net(m10)(c2), dgram(m1)(c1), dns(m10), http(m4)(c4), https(m3)(c2), url(m3), querystring(m2), punycode(m4), readline(m1)(c1), repl(m1), vm(m5)(c1), child_process(m4)(c1), assert(m11), tty(m2)(c2), zlib(m14)(c8), os(m13), cluster(m3)(c1)modules30 , timers(m8), module, addons, util(m13), Events(c1), domain(m1)(c1), buffer(c2), stream(c4), crypto(m18)(c7), tls_(ssl)(m5)(c4), stringdecoder(c1), fs(m67)(c4), path(m7), net(m10)(c2), dgram(m1)(c1), dns(m10), http(m4)(c4), https(m3)(c2), url(m3), querystring(m2), punycode(m4), readline(m1)(c1), repl(m1), vm(m5)(c1), child_process(m4)(c1), assert(m11), tty(m2)(c2), zlib(m14)(c8), os(m13), cluster(m3)(c1) // modules30 , timers(m8), module, addons, util(m13), Events(c1), // domain(m1)(c1), buffer(p1)(c2)(p1)(p1), stream(c4), // crypto(p1)(m18)(c7)(p1)(p1)(p1)(p1)(p1)(p1)(p1), // tls_(ssl)(p1)(m5)(c4)(p1)(p1)(p1)(p1), stringdecoder(c1), // fs(m67)(c4), path(p2)(m7), net(m10)(c2), dgram(m1)(c1), dns(m10), // http(p3)(p7)(m4)(c4)(p3)(p7)(p3)(p7)(p3)(p7)(p3)(p7), // https(p1)(m3)(c2)(p1)(p1), url(m3), querystring(p2)(m2), // punycode(p2)(m4), readline(m1)(c1), repl(m1), vm(m5)(c1), // child_process(m4)(c1), assert(m11), tty(m2)(c2), zlib(m14)(c8), // os(p1)(m13), cluster(p5)(m3)(c1)(p5) // http.Agent // http.ClientRequest // http.Server // http.ServerResponse // http.createClient([port], [host]) // http.createServer([requestListener]) // http.get(options, callback) // http.request(options, callback) // https.Agent // https.Server // https.createServer(options, [requestListener]) // https.get(options, callback) // https.request(options, callback) //TODO this however is not is Editor content assist // follows punycode(p2)(m4), readline(m1)(c1), repl(m1), vm(m5)(c1), child_process(m4)(c1), // assert(m11), tty(m2)(c2), zlib(m14)(c8), os(p1)(m13), cluster(p5)(m3)(c1)(p5) System.out.println("- Matches os. :"); List<Entry> matchesOs = c.model.findMatchingEntries("os."); for(Entry entry: matchesOs){ System.out.println(entry); } // Matches os. : // os.EOL // os.arch() // os.cpus() // os.endianness() // os.freemem() // os.hostname() // os.loadavg() // os.networkInterfaces() // os.platform() // os.release() // os.tmpdir() // os.totalmem() // os.type() // os.uptime() } }