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()
}
}