diff --git a/examples/network/github_timeline.own b/examples/network/github_timeline.own new file mode 100644 index 0000000..2363f3b --- /dev/null +++ b/examples/network/github_timeline.own @@ -0,0 +1,68 @@ +use "std" +use "http" +use "json" +use "functional" + +header = "* Prints current GitHub timeline *" +println "*" * length(header) +println header +println "*" * length(header) + +// Executes in main thread +//http("https://api.github.com/events", def(r) { +// foreach(jsondecode(r), ::show_github_events) +//}) + +// Executes in new thread +thread(::http, "https://api.github.com/events", def(r) { + foreach(jsondecode(r), ::show_github_events) +}) + +def show_github_events(event) { + println event["created_at"] + actor = event["actor"] + println "User: https://github.com/" + actor["login"] + println github_event_type(event) + println "-" * 50 +} + +def github_event_type(event) { + type = event["type"] + repo = event["repo"] + repo = "https://github.com/" + repo["name"] + payload = event["payload"] + + if (type == "CommitCommentEvent") { + comment = payload["comment"] + return "commented commit in " + repo + "\n" + comment["body"] + } + if (type == "CreateEvent") { + return "created " + payload["ref_type"] + " on " + repo + } + if (type == "DeleteEvent") { + return "deleted " + payload["ref_type"] + " on " + repo + } + if (type == "ForkEvent") { + return "forked repository " + repo + } + if (type == "IssueCommentEvent") { + comment = payload["comment"] + issue = payload["issue"] + return "commented issue " + issue["title"] + " on " + repo + "\n" + comment["body"] + } + if (type == "IssuesEvent") { + issue = payload["issue"] + return payload["action"] + " issue '" + issue["title"] + "' on " + repo + } + if (type == "PullRequestEvent") { + pr = payload["pull_request"] + return payload["action"] + " pull request #" + payload["number"] + " '" + pr["title"] + "' on " + repo + } + if (type == "PushEvent") { + return "pushed " + length(payload["commits"]) + " commits to " + repo + } + if (type == "WatchEvent") { + return "start watching repository " + repo + } + return type + " on " + repo +} diff --git a/libs/json-20151123.jar b/libs/json-20151123.jar new file mode 100644 index 0000000..472b253 Binary files /dev/null and b/libs/json-20151123.jar differ diff --git a/nbproject/build-impl.xml b/nbproject/build-impl.xml index b7e2500..6d4a345 100644 --- a/nbproject/build-impl.xml +++ b/nbproject/build-impl.xml @@ -222,6 +222,7 @@ is divided into following sections: + @@ -698,7 +699,7 @@ is divided into following sections: - + @@ -773,7 +774,7 @@ is divided into following sections: - + @@ -800,7 +801,7 @@ is divided into following sections: - + diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties index 1037409..1cc3671 100644 --- a/nbproject/genfiles.properties +++ b/nbproject/genfiles.properties @@ -4,5 +4,5 @@ build.xml.stylesheet.CRC32=8064a381@1.78.0.48 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. nbproject/build-impl.xml.data.CRC32=48c1b1a1 -nbproject/build-impl.xml.script.CRC32=e3eeb3f1 -nbproject/build-impl.xml.stylesheet.CRC32=2d327b5d@1.78.0.48 +nbproject/build-impl.xml.script.CRC32=b8cd7788 +nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.0.48 diff --git a/nbproject/project.properties b/nbproject/project.properties index 9de6066..f4950c5 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -1,9 +1,10 @@ annotation.processing.enabled=true annotation.processing.enabled.in.editor=false -annotation.processing.processor.options= annotation.processing.processors.list= annotation.processing.run.all.processors=true annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +application.title=OwnLang +application.vendor=aNNiMON build.classes.dir=${build.dir}/classes build.classes.excludes=**/*.java,**/*.form # This directory is removed when the project is cleaned: @@ -26,10 +27,21 @@ dist.archive.excludes= dist.dir=dist dist.jar=${dist.dir}/OwnLang.jar dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= excludes= +file.reference.commons-codec-1.6.jar=libs/commons-codec-1.6.jar +file.reference.commons-logging-1.1.3.jar=libs/commons-logging-1.1.3.jar +file.reference.httpclient-4.3.5.jar=libs/httpclient-4.3.5.jar +file.reference.httpcore-4.3.2.jar=libs/httpcore-4.3.2.jar +file.reference.json-20151123.jar=libs/json-20151123.jar includes=** jar.compress=false -javac.classpath= +javac.classpath=\ + ${file.reference.commons-codec-1.6.jar}:\ + ${file.reference.commons-logging-1.1.3.jar}:\ + ${file.reference.httpclient-4.3.5.jar}:\ + ${file.reference.httpcore-4.3.2.jar}:\ + ${file.reference.json-20151123.jar} # Space-separated list of extra javac options javac.compilerargs= javac.deprecation=false diff --git a/program.own b/program.own index 4cc1cfd..7ac6f02 100644 --- a/program.own +++ b/program.own @@ -128,11 +128,25 @@ println "Sum: " + reduce(squares, 0, def(x, y) = x + y) use "http" -http("http://jsonplaceholder.typicode.com/users", "POST", {"name": "OwnLang", "versionCode": 10}, def(v) { +/*http("http://jsonplaceholder.typicode.com/users", "POST", {"name": "OwnLang", "versionCode": 10}, def(v) { println "Added: " + v http("http://jsonplaceholder.typicode.com/users/2", "PATCH", {"name": "Patched Name"}, ::http_get_demo) }) def http_get_demo(v) { println "Updated: " + v http("http://jsonplaceholder.typicode.com/users", ::echo) -} +}*/ + +use "json" +println "json" +println jsonencode({ + "name": "JSON Example", + "version": 1, + "arrayData": [ + 1, 2, 3, 4 + ], + "objectData": { + "key": "value", + 10: "1000" + } +}) \ No newline at end of file diff --git a/src/com/annimon/ownlang/lib/modules/functions/json_decode.java b/src/com/annimon/ownlang/lib/modules/functions/json_decode.java new file mode 100644 index 0000000..97fb9d5 --- /dev/null +++ b/src/com/annimon/ownlang/lib/modules/functions/json_decode.java @@ -0,0 +1,61 @@ +package com.annimon.ownlang.lib.modules.functions; + +import com.annimon.ownlang.lib.*; +import java.util.Iterator; +import org.json.*; + +public final class json_decode implements Function { + + @Override + public Value execute(Value... args) { + if (args.length != 1) throw new RuntimeException("One argument expected"); + try { + final String jsonRaw = args[0].asString(); + final Object root = new JSONTokener(jsonRaw).nextValue(); + return process(root); + } catch (JSONException ex) { + throw new RuntimeException("Error while parsing json", ex); + } + } + + private Value process(Object obj) { + if (obj instanceof JSONObject) { + return process((JSONObject) obj); + } + if (obj instanceof JSONArray) { + return process((JSONArray) obj); + } + if (obj instanceof String) { + return new StringValue((String) obj); + } + if (obj instanceof Number) { + return new NumberValue(((Number) obj).doubleValue()); + } + if (obj instanceof Boolean) { + return NumberValue.fromBoolean((Boolean) obj); + } + // NULL or other + return NumberValue.ZERO; + } + + private MapValue process(JSONObject json) { + final MapValue result = new MapValue(json.length()); + final Iterator it = json.keys(); + while(it.hasNext()) { + final String key = it.next(); + final Value value = process(json.get(key)); + result.set(new StringValue(key), value); + } + return result; + } + + private ArrayValue process(JSONArray json) { + final int length = json.length(); + final ArrayValue result = new ArrayValue(length); + for (int i = 0; i < length; i++) { + final Value value = process(json.get(i)); + result.set(i, value); + } + return result; + } +} \ No newline at end of file diff --git a/src/com/annimon/ownlang/lib/modules/functions/json_encode.java b/src/com/annimon/ownlang/lib/modules/functions/json_encode.java new file mode 100644 index 0000000..8263ac1 --- /dev/null +++ b/src/com/annimon/ownlang/lib/modules/functions/json_encode.java @@ -0,0 +1,53 @@ +package com.annimon.ownlang.lib.modules.functions; + +import com.annimon.ownlang.lib.*; +import java.util.Map; +import org.json.*; + +public final class json_encode implements Function { + + @Override + public Value execute(Value... args) { + if (args.length != 1) throw new RuntimeException("One argument expected"); + try { + final Object root = process(args[0]); + final String jsonRaw = JSONObject.valueToString(root); + return new StringValue(jsonRaw); + } catch (JSONException ex) { + throw new RuntimeException("Error while creating json", ex); + } + } + + private Object process(Value val) { + switch (val.type()) { + case Types.ARRAY: + return process((ArrayValue) val); + case Types.MAP: + return process((MapValue) val); + case Types.NUMBER: + return val.asNumber(); + case Types.STRING: + return val.asString(); + default: + return JSONObject.NULL; + } + } + + private Object process(MapValue map) { + final JSONObject result = new JSONObject(); + for (Map.Entry entry : map) { + final String key = entry.getKey().asString(); + final Object value = process(entry.getValue()); + result.put(key, value); + } + return result; + } + + private Object process(ArrayValue array) { + final JSONArray result = new JSONArray(); + for (Value value : array) { + result.put(process(value)); + } + return result; + } +} \ No newline at end of file diff --git a/src/com/annimon/ownlang/lib/modules/json.java b/src/com/annimon/ownlang/lib/modules/json.java new file mode 100644 index 0000000..6af5997 --- /dev/null +++ b/src/com/annimon/ownlang/lib/modules/json.java @@ -0,0 +1,17 @@ +package com.annimon.ownlang.lib.modules; + +import com.annimon.ownlang.lib.*; +import com.annimon.ownlang.lib.modules.functions.*; + +/** + * + * @author aNNiMON + */ +public final class json implements Module { + + @Override + public void init() { + Functions.set("jsonencode", new json_encode()); + Functions.set("jsondecode", new json_decode()); + } +}