From e661a647f3a38cd4aeef5976c1f64cb97a48a81f Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 23 Sep 2018 11:05:08 +0100 Subject: [PATCH 001/164] Change isSerializedTo to check for Jackson serialization --- .../src/com/google/refine/tests/util/TestUtils.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/main/tests/server/src/com/google/refine/tests/util/TestUtils.java b/main/tests/server/src/com/google/refine/tests/util/TestUtils.java index 630385195..b0984c645 100644 --- a/main/tests/server/src/com/google/refine/tests/util/TestUtils.java +++ b/main/tests/server/src/com/google/refine/tests/util/TestUtils.java @@ -7,6 +7,7 @@ import java.io.File; import java.io.IOException; import java.util.Properties; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -52,6 +53,14 @@ public class TestUtils { */ public static void isSerializedTo(Jsonizable o, String targetJson, Properties options) { equalAsJson(targetJson, JSONUtilities.serialize(o, options)); + + // also check Jackson serialization + try { + equalAsJson(targetJson, mapper.writeValueAsString(o)); + } catch (JsonProcessingException e) { + e.printStackTrace(); + fail("jackson serialization failed"); + } } /** From 7648ca91cadc779c2e7f4f029dd43b5a60c0360d Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 23 Sep 2018 11:27:41 +0100 Subject: [PATCH 002/164] Jackson serialization for GREL functions --- .../refine/expr/functions/Coalesce.java | 25 +++++++++------- .../google/refine/expr/functions/Cross.java | 21 +++++++------- .../refine/expr/functions/FacetCount.java | 21 +++++++------- .../com/google/refine/expr/functions/Get.java | 23 ++++++++------- .../refine/expr/functions/HasField.java | 19 +++++++----- .../google/refine/expr/functions/Jsonize.java | 19 +++++++----- .../google/refine/expr/functions/Length.java | 20 +++++++------ .../google/refine/expr/functions/Slice.java | 23 ++++++++------- .../google/refine/expr/functions/ToDate.java | 24 ++++++++------- .../refine/expr/functions/ToNumber.java | 21 +++++++------- .../refine/expr/functions/ToString.java | 21 +++++++------- .../google/refine/expr/functions/Type.java | 21 +++++++------- .../expr/functions/arrays/ArgsToArray.java | 21 +++++++------- .../refine/expr/functions/arrays/Join.java | 19 +++++++----- .../refine/expr/functions/arrays/Reverse.java | 19 +++++++----- .../refine/expr/functions/arrays/Sort.java | 19 +++++++----- .../refine/expr/functions/arrays/Uniques.java | 19 +++++++----- .../refine/expr/functions/booleans/And.java | 23 ++++++++------- .../refine/expr/functions/booleans/Not.java | 21 +++++++------- .../refine/expr/functions/booleans/Or.java | 23 ++++++++------- .../refine/expr/functions/booleans/Xor.java | 26 ++++++++--------- .../refine/expr/functions/date/DatePart.java | 29 ++++++++++--------- .../refine/expr/functions/date/Inc.java | 21 ++++++++------ .../refine/expr/functions/date/Now.java | 12 ++++---- .../refine/expr/functions/html/InnerHtml.java | 22 +++++++------- .../refine/expr/functions/html/ParseHtml.java | 23 ++++++++------- .../refine/expr/functions/math/ACos.java | 23 ++++++++------- .../refine/expr/functions/math/ASin.java | 23 ++++++++------- .../refine/expr/functions/math/ATan.java | 23 ++++++++------- .../refine/expr/functions/math/ATan2.java | 23 ++++++++------- .../refine/expr/functions/math/Abs.java | 21 +++++++------- .../refine/expr/functions/math/Ceil.java | 21 +++++++------- .../refine/expr/functions/math/Combin.java | 23 ++++++++------- .../refine/expr/functions/math/Cos.java | 23 ++++++++------- .../refine/expr/functions/math/Cosh.java | 23 ++++++++------- .../refine/expr/functions/math/Degrees.java | 23 ++++++++------- .../refine/expr/functions/math/Even.java | 23 ++++++++------- .../refine/expr/functions/math/Exp.java | 21 +++++++------- .../refine/expr/functions/math/Fact.java | 23 ++++++++------- .../refine/expr/functions/math/FactN.java | 23 ++++++++------- .../refine/expr/functions/math/Floor.java | 21 +++++++------- .../math/GreatestCommonDenominator.java | 23 ++++++++------- .../functions/math/LeastCommonMultiple.java | 23 ++++++++------- .../google/refine/expr/functions/math/Ln.java | 21 +++++++------- .../refine/expr/functions/math/Log.java | 21 +++++++------- .../refine/expr/functions/math/Max.java | 21 +++++++------- .../refine/expr/functions/math/Min.java | 21 +++++++------- .../refine/expr/functions/math/Mod.java | 21 +++++++------- .../expr/functions/math/Multinomial.java | 23 ++++++++------- .../refine/expr/functions/math/Odd.java | 23 ++++++++------- .../refine/expr/functions/math/Pow.java | 21 +++++++------- .../refine/expr/functions/math/Quotient.java | 23 ++++++++------- .../refine/expr/functions/math/Radians.java | 23 ++++++++------- .../refine/expr/functions/math/Round.java | 21 +++++++------- .../refine/expr/functions/math/Sin.java | 23 ++++++++------- .../refine/expr/functions/math/Sinh.java | 23 ++++++++------- .../refine/expr/functions/math/Sum.java | 21 +++++++------- .../refine/expr/functions/math/Tan.java | 23 ++++++++------- .../refine/expr/functions/math/Tanh.java | 23 ++++++++------- .../refine/expr/functions/strings/Chomp.java | 20 +++++++------ .../expr/functions/strings/Contains.java | 21 +++++++------- .../refine/expr/functions/strings/Diff.java | 20 ++++++++----- .../expr/functions/strings/EndsWith.java | 21 +++++++------- .../refine/expr/functions/strings/Escape.java | 20 +++++++------ .../refine/expr/functions/strings/Find.java | 21 +++++++------- .../expr/functions/strings/Fingerprint.java | 21 +++++++------- .../expr/functions/strings/IndexOf.java | 21 +++++++------- .../expr/functions/strings/LastIndexOf.java | 21 +++++++------- .../refine/expr/functions/strings/MD5.java | 20 +++++++------ .../refine/expr/functions/strings/Match.java | 21 +++++++------- .../refine/expr/functions/strings/NGram.java | 20 +++++++------ .../functions/strings/NGramFingerprint.java | 21 +++++++------- .../expr/functions/strings/ParseJson.java | 19 +++++++----- .../expr/functions/strings/Partition.java | 23 ++++++++------- .../expr/functions/strings/Phonetic.java | 21 +++++++------- .../expr/functions/strings/RPartition.java | 23 ++++++++------- .../refine/expr/functions/strings/Range.java | 27 ++++++++--------- .../expr/functions/strings/Reinterpret.java | 21 +++++++------- .../expr/functions/strings/Replace.java | 21 +++++++------- .../expr/functions/strings/ReplaceChars.java | 20 +++++++------ .../refine/expr/functions/strings/SHA1.java | 20 +++++++------ .../expr/functions/strings/SmartSplit.java | 25 ++++++++-------- .../refine/expr/functions/strings/Split.java | 20 +++++++------ .../functions/strings/SplitByCharType.java | 20 +++++++------ .../functions/strings/SplitByLengths.java | 21 +++++++------- .../expr/functions/strings/StartsWith.java | 21 +++++++------- .../expr/functions/strings/ToLowercase.java | 21 +++++++------- .../expr/functions/strings/ToTitlecase.java | 20 +++++++------ .../expr/functions/strings/ToUppercase.java | 21 +++++++------- .../refine/expr/functions/strings/Trim.java | 22 +++++++------- .../expr/functions/strings/Unescape.java | 20 +++++++------ .../expr/functions/strings/Unicode.java | 21 +++++++------- .../expr/functions/strings/UnicodeType.java | 21 +++++++------- .../refine/expr/functions/xml/OwnText.java | 22 +++++++------- .../refine/expr/functions/xml/SelectXml.java | 22 +++++++------- .../refine/expr/functions/xml/XmlAttr.java | 22 +++++++------- .../refine/expr/functions/xml/XmlText.java | 22 +++++++------- main/src/com/google/refine/grel/Function.java | 28 ++++++++++++++++++ 98 files changed, 1144 insertions(+), 978 deletions(-) diff --git a/main/src/com/google/refine/expr/functions/Coalesce.java b/main/src/com/google/refine/expr/functions/Coalesce.java index 5ef489c35..e3b384a46 100644 --- a/main/src/com/google/refine/expr/functions/Coalesce.java +++ b/main/src/com/google/refine/expr/functions/Coalesce.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -60,13 +57,19 @@ public class Coalesce implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the first non-null from a series of values"); - writer.key("params"); writer.value("two or more objects"); - writer.key("returns"); writer.value("object or null"); - writer.endObject(); + public String getDescription() { + return "Returns the first non-null from a series of values"; } + + @Override + public String getParams() { + return "two or more objects"; + } + + @Override + public String getReturns() { + return "object or null"; + } + + } diff --git a/main/src/com/google/refine/expr/functions/Cross.java b/main/src/com/google/refine/expr/functions/Cross.java index 70347a941..b9ed764f2 100644 --- a/main/src/com/google/refine/expr/functions/Cross.java +++ b/main/src/com/google/refine/expr/functions/Cross.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.InterProjectModel.ProjectJoin; import com.google.refine.ProjectManager; import com.google.refine.expr.EvalError; @@ -78,13 +75,17 @@ public class Cross implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "join with another project by column"; + } - writer.object(); - writer.key("description"); writer.value("join with another project by column"); - writer.key("params"); writer.value("cell c or string value, string projectName, string columnName"); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "cell c or string value, string projectName, string columnName"; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/expr/functions/FacetCount.java b/main/src/com/google/refine/expr/functions/FacetCount.java index 42e172265..7c4c689b0 100644 --- a/main/src/com/google/refine/expr/functions/FacetCount.java +++ b/main/src/com/google/refine/expr/functions/FacetCount.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.util.ExpressionNominalValueGrouper; import com.google.refine.expr.EvalError; @@ -87,13 +84,17 @@ public class FacetCount implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the facet count corresponding to the given choice value"; + } - writer.object(); - writer.key("description"); writer.value("Returns the facet count corresponding to the given choice value"); - writer.key("params"); writer.value("choiceValue, string facetExpression, string columnName"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "choiceValue, string facetExpression, string columnName"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/Get.java b/main/src/com/google/refine/expr/functions/Get.java index 4e69fc020..d3dad40fd 100644 --- a/main/src/com/google/refine/expr/functions/Get.java +++ b/main/src/com/google/refine/expr/functions/Get.java @@ -39,7 +39,6 @@ import java.util.Properties; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.google.refine.expr.ExpressionUtils; import com.google.refine.expr.HasFields; @@ -166,17 +165,21 @@ public class Get implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value( + public String getDescription() { + return "If o has fields, returns the field named 'from' of o. " + "If o is an array, returns o[from, to]. " + "if o is a string, returns o.substring(from, to)" - ); - writer.key("params"); writer.value("o, number or string from, optional number to"); - writer.key("returns"); writer.value("Depends on actual arguments"); - writer.endObject(); + ; + } + + @Override + public String getParams() { + return "o, number or string from, optional number to"; + } + + @Override + public String getReturns() { + return "Depends on actual arguments"; } } diff --git a/main/src/com/google/refine/expr/functions/HasField.java b/main/src/com/google/refine/expr/functions/HasField.java index 25f8f32e9..8fb0cb282 100644 --- a/main/src/com/google/refine/expr/functions/HasField.java +++ b/main/src/com/google/refine/expr/functions/HasField.java @@ -37,7 +37,6 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.google.refine.expr.HasFields; import com.google.refine.grel.Function; @@ -67,13 +66,17 @@ public class HasField implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns whether o has field name"; + } - writer.object(); - writer.key("description"); writer.value("Returns whether o has field name"); - writer.key("params"); writer.value("o, string name"); - writer.key("returns"); writer.value("boolean"); - writer.endObject(); + @Override + public String getParams() { + return "o, string name"; + } + + @Override + public String getReturns() { + return "boolean"; } } diff --git a/main/src/com/google/refine/expr/functions/Jsonize.java b/main/src/com/google/refine/expr/functions/Jsonize.java index ab0bc9567..1fdd02dbf 100644 --- a/main/src/com/google/refine/expr/functions/Jsonize.java +++ b/main/src/com/google/refine/expr/functions/Jsonize.java @@ -40,7 +40,6 @@ import java.util.Properties; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.google.refine.grel.Function; @@ -79,13 +78,17 @@ public class Jsonize implements Function { @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Quotes a value as a JSON literal value"; + } - writer.object(); - writer.key("description"); writer.value("Quotes a value as a JSON literal value"); - writer.key("params"); writer.value("value"); - writer.key("returns"); writer.value("JSON literal value"); - writer.endObject(); + @Override + public String getParams() { + return "value"; + } + + @Override + public String getReturns() { + return "JSON literal value"; } } diff --git a/main/src/com/google/refine/expr/functions/Length.java b/main/src/com/google/refine/expr/functions/Length.java index bbe7c3a88..e01b45eaf 100644 --- a/main/src/com/google/refine/expr/functions/Length.java +++ b/main/src/com/google/refine/expr/functions/Length.java @@ -37,8 +37,6 @@ import java.util.Collection; import java.util.Properties; import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.expr.HasFieldsList; @@ -72,13 +70,17 @@ public class Length implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the length of o"; + } - writer.object(); - writer.key("description"); writer.value("Returns the length of o"); - writer.key("params"); writer.value("array or string o"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "array or string o"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/Slice.java b/main/src/com/google/refine/expr/functions/Slice.java index c2aa63ae6..b757337ce 100644 --- a/main/src/com/google/refine/expr/functions/Slice.java +++ b/main/src/com/google/refine/expr/functions/Slice.java @@ -38,7 +38,6 @@ import java.util.Properties; import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.ExpressionUtils; import com.google.refine.expr.HasFieldsList; @@ -130,16 +129,20 @@ public class Slice implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value( + public String getDescription() { + return "If o is an array, returns o[from, to]. " + "if o is a string, returns o.substring(from, to)" - ); - writer.key("params"); writer.value("o, number from, optional number to"); - writer.key("returns"); writer.value("Depends on actual arguments"); - writer.endObject(); + ; + } + + @Override + public String getParams() { + return "o, number from, optional number to"; + } + + @Override + public String getReturns() { + return "Depends on actual arguments"; } } diff --git a/main/src/com/google/refine/expr/functions/ToDate.java b/main/src/com/google/refine/expr/functions/ToDate.java index 1a20e8cdf..2eecfe4b8 100644 --- a/main/src/com/google/refine/expr/functions/ToDate.java +++ b/main/src/com/google/refine/expr/functions/ToDate.java @@ -46,12 +46,10 @@ import java.util.Properties; import java.util.TimeZone; import org.apache.commons.lang3.StringUtils; -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; -import com.google.refine.expr.util.CalendarParserException; import com.google.refine.expr.util.CalendarParser; +import com.google.refine.expr.util.CalendarParserException; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; import com.google.refine.util.ParsingUtilities; @@ -188,13 +186,17 @@ public class ToDate implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns o converted to a date object, you can hint if the day or the month is listed first, or give an ordered list of possible formats using this syntax: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html"); - writer.key("params"); writer.value("o, boolean month_first / format1, format2, ... (all optional)"); - writer.key("returns"); writer.value("date"); - writer.endObject(); + public String getDescription() { + return "Returns o converted to a date object, you can hint if the day or the month is listed first, or give an ordered list of possible formats using this syntax: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html"; + } + + @Override + public String getParams() { + return "o, boolean month_first / format1, format2, ... (all optional)"; + } + + @Override + public String getReturns() { + return "date"; } } diff --git a/main/src/com/google/refine/expr/functions/ToNumber.java b/main/src/com/google/refine/expr/functions/ToNumber.java index 4935b3199..e4d6c9a80 100644 --- a/main/src/com/google/refine/expr/functions/ToNumber.java +++ b/main/src/com/google/refine/expr/functions/ToNumber.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -71,14 +68,18 @@ public class ToNumber implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns o converted to a number"; + } - writer.object(); - writer.key("description"); writer.value("Returns o converted to a number"); - writer.key("params"); writer.value("o"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "o"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/ToString.java b/main/src/com/google/refine/expr/functions/ToString.java index 02bdaa203..6e90b684f 100644 --- a/main/src/com/google/refine/expr/functions/ToString.java +++ b/main/src/com/google/refine/expr/functions/ToString.java @@ -37,9 +37,6 @@ import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -72,13 +69,17 @@ public class ToString implements Function { @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns o converted to a string"; + } - writer.object(); - writer.key("description"); writer.value("Returns o converted to a string"); - writer.key("params"); writer.value("o, string format (optional)"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "o, string format (optional)"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/Type.java b/main/src/com/google/refine/expr/functions/Type.java index c22572a54..6c01a6071 100644 --- a/main/src/com/google/refine/expr/functions/Type.java +++ b/main/src/com/google/refine/expr/functions/Type.java @@ -37,9 +37,6 @@ import java.time.OffsetDateTime; import java.util.List; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -72,13 +69,17 @@ public class Type implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the type of o"; + } - writer.object(); - writer.key("description"); writer.value("Returns the type of o"); - writer.key("params"); writer.value("object o"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "object o"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/arrays/ArgsToArray.java b/main/src/com/google/refine/expr/functions/arrays/ArgsToArray.java index 6612e1f9d..0d6c52217 100644 --- a/main/src/com/google/refine/expr/functions/arrays/ArgsToArray.java +++ b/main/src/com/google/refine/expr/functions/arrays/ArgsToArray.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.arrays; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.grel.Function; public class ArgsToArray implements Function { @@ -48,13 +45,17 @@ public class ArgsToArray implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns all arguments passed to it as an array"; + } - writer.object(); - writer.key("description"); writer.value("Returns all arguments passed to it as an array"); - writer.key("params"); writer.value("a1, a2, ..."); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "a1, a2, ..."; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/expr/functions/arrays/Join.java b/main/src/com/google/refine/expr/functions/arrays/Join.java index 2930b27a1..fb3fad9a4 100644 --- a/main/src/com/google/refine/expr/functions/arrays/Join.java +++ b/main/src/com/google/refine/expr/functions/arrays/Join.java @@ -38,7 +38,6 @@ import java.util.Properties; import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.expr.ExpressionUtils; @@ -101,13 +100,17 @@ public class Join implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the string obtained by joining the array a with the separator sep"; + } - writer.object(); - writer.key("description"); writer.value("Returns the string obtained by joining the array a with the separator sep"); - writer.key("params"); writer.value("array a, string sep"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "array a, string sep"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/arrays/Reverse.java b/main/src/com/google/refine/expr/functions/arrays/Reverse.java index be0a3289e..eedc0195e 100644 --- a/main/src/com/google/refine/expr/functions/arrays/Reverse.java +++ b/main/src/com/google/refine/expr/functions/arrays/Reverse.java @@ -38,7 +38,6 @@ import java.util.Properties; import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.expr.ExpressionUtils; @@ -88,13 +87,17 @@ public class Reverse implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Reverses array a"; + } - writer.object(); - writer.key("description"); writer.value("Reverses array a"); - writer.key("params"); writer.value("array a"); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "array a"; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/expr/functions/arrays/Sort.java b/main/src/com/google/refine/expr/functions/arrays/Sort.java index de52ea7dd..090a79968 100644 --- a/main/src/com/google/refine/expr/functions/arrays/Sort.java +++ b/main/src/com/google/refine/expr/functions/arrays/Sort.java @@ -40,7 +40,6 @@ import java.util.Properties; import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; @@ -86,13 +85,17 @@ public class Sort implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Sorts array a"; + } - writer.object(); - writer.key("description"); writer.value("Sorts array a"); - writer.key("params"); writer.value("array a"); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "array a"; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/expr/functions/arrays/Uniques.java b/main/src/com/google/refine/expr/functions/arrays/Uniques.java index 1acd8e41b..0ee2c50ef 100644 --- a/main/src/com/google/refine/expr/functions/arrays/Uniques.java +++ b/main/src/com/google/refine/expr/functions/arrays/Uniques.java @@ -40,7 +40,6 @@ import java.util.Set; import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.expr.ExpressionUtils; @@ -86,13 +85,17 @@ public class Uniques implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns array a with duplicates removed"; + } - writer.object(); - writer.key("description"); writer.value("Returns array a with duplicates removed"); - writer.key("params"); writer.value("array a"); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "array a"; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/expr/functions/booleans/And.java b/main/src/com/google/refine/expr/functions/booleans/And.java index 8794cb865..fea94814a 100644 --- a/main/src/com/google/refine/expr/functions/booleans/And.java +++ b/main/src/com/google/refine/expr/functions/booleans/And.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.booleans; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -58,13 +55,17 @@ public class And implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("AND two or more booleans to yield a boolean"); - writer.key("params"); writer.value("boolean a, boolean b"); - writer.key("returns"); writer.value("boolean"); - writer.endObject(); + public String getDescription() { + return "AND two or more booleans to yield a boolean"; + } + + @Override + public String getParams() { + return "boolean a, boolean b"; + } + + @Override + public String getReturns() { + return "boolean"; } } diff --git a/main/src/com/google/refine/expr/functions/booleans/Not.java b/main/src/com/google/refine/expr/functions/booleans/Not.java index 4b62afb8d..05b2c7968 100644 --- a/main/src/com/google/refine/expr/functions/booleans/Not.java +++ b/main/src/com/google/refine/expr/functions/booleans/Not.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.booleans; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -58,13 +55,17 @@ public class Not implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the opposite of b"; + } - writer.object(); - writer.key("description"); writer.value("Returns the opposite of b"); - writer.key("params"); writer.value("boolean b"); - writer.key("returns"); writer.value("boolean"); - writer.endObject(); + @Override + public String getParams() { + return "boolean b"; + } + + @Override + public String getReturns() { + return "boolean"; } } diff --git a/main/src/com/google/refine/expr/functions/booleans/Or.java b/main/src/com/google/refine/expr/functions/booleans/Or.java index 0b1b10b0e..91b3a2b6c 100644 --- a/main/src/com/google/refine/expr/functions/booleans/Or.java +++ b/main/src/com/google/refine/expr/functions/booleans/Or.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.booleans; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -58,13 +55,17 @@ public class Or implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("OR two or more booleans to yield a boolean"); - writer.key("params"); writer.value("boolean a, boolean b"); - writer.key("returns"); writer.value("boolean"); - writer.endObject(); + public String getDescription() { + return "OR two or more booleans to yield a boolean"; + } + + @Override + public String getParams() { + return "boolean a, boolean b"; + } + + @Override + public String getReturns() { + return "boolean"; } } diff --git a/main/src/com/google/refine/expr/functions/booleans/Xor.java b/main/src/com/google/refine/expr/functions/booleans/Xor.java index 39bc687a6..d104772a5 100644 --- a/main/src/com/google/refine/expr/functions/booleans/Xor.java +++ b/main/src/com/google/refine/expr/functions/booleans/Xor.java @@ -27,9 +27,6 @@ package com.google.refine.expr.functions.booleans; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -45,16 +42,17 @@ public class Xor implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); - writer.value("XORs two or more boolean values"); - writer.key("params"); - writer.value("boolean a, boolean b"); - writer.key("returns"); - writer.value("boolean"); - writer.endObject(); + public String getDescription() { + return "XORs two or more boolean values"; + } + + @Override + public String getParams() { + return "boolean a, boolean b"; + } + + @Override + public String getReturns() { + return "boolean"; } } diff --git a/main/src/com/google/refine/expr/functions/date/DatePart.java b/main/src/com/google/refine/expr/functions/date/DatePart.java index 8b305470c..6f048310a 100644 --- a/main/src/com/google/refine/expr/functions/date/DatePart.java +++ b/main/src/com/google/refine/expr/functions/date/DatePart.java @@ -33,18 +33,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.expr.functions.date; -import java.util.Calendar; -import java.util.Date; -import java.util.Properties; -import java.util.TimeZone; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.OffsetDateTime; import java.time.temporal.TemporalField; import java.time.temporal.WeekFields; - -import org.json.JSONException; -import org.json.JSONWriter; +import java.util.Calendar; +import java.util.Date; +import java.util.Properties; +import java.util.TimeZone; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; @@ -141,11 +138,17 @@ public class DatePart implements Function { } @Override - public void write(JSONWriter writer, Properties options) throws JSONException { - writer.object(); - writer.key("description"); writer.value("Returns part of a date"); - writer.key("params"); writer.value("date d, string part"); - writer.key("returns"); writer.value("date"); - writer.endObject(); + public String getDescription() { + return "Returns part of a date"; + } + + @Override + public String getParams() { + return "date d, string part"; + } + + @Override + public String getReturns() { + return "date"; } } diff --git a/main/src/com/google/refine/expr/functions/date/Inc.java b/main/src/com/google/refine/expr/functions/date/Inc.java index ff521d620..a5a3c1c2e 100644 --- a/main/src/com/google/refine/expr/functions/date/Inc.java +++ b/main/src/com/google/refine/expr/functions/date/Inc.java @@ -38,9 +38,6 @@ import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalUnit; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -88,11 +85,17 @@ public class Inc implements Function { } @Override - public void write(JSONWriter writer, Properties options) throws JSONException { - writer.object(); - writer.key("description"); writer.value("Returns a date changed by the given amount in the given unit of time"); - writer.key("params"); writer.value("date d, number value, string unit (default to 'hour')"); - writer.key("returns"); writer.value("date"); - writer.endObject(); + public String getDescription() { + return "Returns a date changed by the given amount in the given unit of time"; + } + + @Override + public String getParams() { + return "date d, number value, string unit (default to 'hour')"; + } + + @Override + public String getReturns() { + return "date"; } } diff --git a/main/src/com/google/refine/expr/functions/date/Now.java b/main/src/com/google/refine/expr/functions/date/Now.java index 158f81a2e..ba0d88c63 100644 --- a/main/src/com/google/refine/expr/functions/date/Now.java +++ b/main/src/com/google/refine/expr/functions/date/Now.java @@ -53,12 +53,12 @@ public class Now implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the current time"; + } - writer.object(); - writer.key("description"); writer.value("Returns the current time"); - writer.key("returns"); writer.value("date"); - writer.endObject(); + @Override + public String getReturns() { + return "date"; } } diff --git a/main/src/com/google/refine/expr/functions/html/InnerHtml.java b/main/src/com/google/refine/expr/functions/html/InnerHtml.java index 5e9853d46..5a0b8b4f8 100644 --- a/main/src/com/google/refine/expr/functions/html/InnerHtml.java +++ b/main/src/com/google/refine/expr/functions/html/InnerHtml.java @@ -35,8 +35,6 @@ package com.google.refine.expr.functions.html; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; import org.jsoup.nodes.Element; import com.google.refine.expr.EvalError; @@ -61,14 +59,18 @@ public class InnerHtml implements Function { @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("The innerHtml of an HTML element"); - writer.key("params"); writer.value("Element e"); - writer.key("returns"); writer.value("String innerHtml"); - writer.endObject(); + public String getDescription() { + return "The innerHtml of an HTML element"; + } + + @Override + public String getParams() { + return "Element e"; + } + + @Override + public String getReturns() { + return "String innerHtml"; } } diff --git a/main/src/com/google/refine/expr/functions/html/ParseHtml.java b/main/src/com/google/refine/expr/functions/html/ParseHtml.java index 14ae4b3cd..482fd2c7f 100644 --- a/main/src/com/google/refine/expr/functions/html/ParseHtml.java +++ b/main/src/com/google/refine/expr/functions/html/ParseHtml.java @@ -35,8 +35,7 @@ package com.google.refine.expr.functions.html; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; +import org.jsoup.Jsoup; import com.google.refine.expr.EvalError; import com.google.refine.expr.functions.xml.ParseXml; @@ -58,14 +57,18 @@ public class ParseHtml implements Function { @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Parses a string as HTML"); - writer.key("params"); writer.value("string s"); - writer.key("returns"); writer.value("HTML object"); - writer.endObject(); + public String getDescription() { + return "Parses a string as HTML"; + } + + @Override + public String getParams() { + return "string s"; + } + + @Override + public String getReturns() { + return "HTML object"; } } diff --git a/main/src/com/google/refine/expr/functions/math/ACos.java b/main/src/com/google/refine/expr/functions/math/ACos.java index e4b31269e..99a2632fa 100644 --- a/main/src/com/google/refine/expr/functions/math/ACos.java +++ b/main/src/com/google/refine/expr/functions/math/ACos.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class ACos implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the arc cosine of an angle, in the range 0 through PI"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the arc cosine of an angle, in the range 0 through PI"; + } + + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/ASin.java b/main/src/com/google/refine/expr/functions/math/ASin.java index 6abdb5c1b..c7cbbeb7c 100644 --- a/main/src/com/google/refine/expr/functions/math/ASin.java +++ b/main/src/com/google/refine/expr/functions/math/ASin.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class ASin implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the arc sine of an angle in the range of -PI/2 through PI/2"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the arc sine of an angle in the range of -PI/2 through PI/2"; + } + + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/ATan.java b/main/src/com/google/refine/expr/functions/math/ATan.java index 76e85f513..226bd18a6 100644 --- a/main/src/com/google/refine/expr/functions/math/ATan.java +++ b/main/src/com/google/refine/expr/functions/math/ATan.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class ATan implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the arc tangent of an angle in the range of -PI/2 through PI/2"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the arc tangent of an angle in the range of -PI/2 through PI/2"; + } + + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/ATan2.java b/main/src/com/google/refine/expr/functions/math/ATan2.java index e175a5fc3..6b2019dd2 100644 --- a/main/src/com/google/refine/expr/functions/math/ATan2.java +++ b/main/src/com/google/refine/expr/functions/math/ATan2.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -54,13 +51,17 @@ public class ATan2 implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Converts rectangular coordinates (x, y) to polar (r, theta)"); - writer.key("params"); writer.value("number x, number y"); - writer.key("returns"); writer.value("number theta"); - writer.endObject(); + public String getDescription() { + return "Converts rectangular coordinates (x, y) to polar (r, theta)"; + } + + @Override + public String getParams() { + return "number x, number y"; + } + + @Override + public String getReturns() { + return "number theta"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/Abs.java b/main/src/com/google/refine/expr/functions/math/Abs.java index a67734377..14a5cc0cb 100644 --- a/main/src/com/google/refine/expr/functions/math/Abs.java +++ b/main/src/com/google/refine/expr/functions/math/Abs.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class Abs implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the absolute value of a number"; + } - writer.object(); - writer.key("description"); writer.value("Returns the absolute value of a number"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/Ceil.java b/main/src/com/google/refine/expr/functions/math/Ceil.java index 3053df1e9..c986a0429 100644 --- a/main/src/com/google/refine/expr/functions/math/Ceil.java +++ b/main/src/com/google/refine/expr/functions/math/Ceil.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class Ceil implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the ceiling of a number"; + } - writer.object(); - writer.key("description"); writer.value("Returns the ceiling of a number"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/Combin.java b/main/src/com/google/refine/expr/functions/math/Combin.java index 4ad3d849c..0e9a120c0 100644 --- a/main/src/com/google/refine/expr/functions/math/Combin.java +++ b/main/src/com/google/refine/expr/functions/math/Combin.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -87,13 +84,17 @@ public class Combin implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the number of combinations for n elements as divided into k"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the number of combinations for n elements as divided into k"; + } + + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/Cos.java b/main/src/com/google/refine/expr/functions/math/Cos.java index 9f597df62..6d15df4dc 100644 --- a/main/src/com/google/refine/expr/functions/math/Cos.java +++ b/main/src/com/google/refine/expr/functions/math/Cos.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class Cos implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the trigonometric cosine of an angle"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the trigonometric cosine of an angle"; + } + + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/Cosh.java b/main/src/com/google/refine/expr/functions/math/Cosh.java index 867d6dce6..04420734e 100644 --- a/main/src/com/google/refine/expr/functions/math/Cosh.java +++ b/main/src/com/google/refine/expr/functions/math/Cosh.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class Cosh implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the hyperbolic cosine of a value"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the hyperbolic cosine of a value"; + } + + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/Degrees.java b/main/src/com/google/refine/expr/functions/math/Degrees.java index 03aac39d0..96c3e3b85 100644 --- a/main/src/com/google/refine/expr/functions/math/Degrees.java +++ b/main/src/com/google/refine/expr/functions/math/Degrees.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class Degrees implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Converts an angle from radians to degrees."); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Converts an angle from radians to degrees."; + } + + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/Even.java b/main/src/com/google/refine/expr/functions/math/Even.java index 12e678495..22bef743a 100644 --- a/main/src/com/google/refine/expr/functions/math/Even.java +++ b/main/src/com/google/refine/expr/functions/math/Even.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -58,13 +55,17 @@ public class Even implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Rounds the number up to the nearest even integer"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Rounds the number up to the nearest even integer"; + } + + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/Exp.java b/main/src/com/google/refine/expr/functions/math/Exp.java index 273bf732f..52f01b688 100644 --- a/main/src/com/google/refine/expr/functions/math/Exp.java +++ b/main/src/com/google/refine/expr/functions/math/Exp.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.grel.Function; public class Exp implements Function { @@ -51,13 +48,17 @@ public class Exp implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns e^n"; + } - writer.object(); - writer.key("description"); writer.value("Returns e^n"); - writer.key("params"); writer.value("number n"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "number n"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/Fact.java b/main/src/com/google/refine/expr/functions/math/Fact.java index e1f8ab1ec..b9aa916ce 100644 --- a/main/src/com/google/refine/expr/functions/math/Fact.java +++ b/main/src/com/google/refine/expr/functions/math/Fact.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class Fact implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the factorial of a number"); - writer.key("params"); writer.value("number i"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the factorial of a number"; + } + + @Override + public String getParams() { + return "number i"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/FactN.java b/main/src/com/google/refine/expr/functions/math/FactN.java index 9b2254526..dfcb73bbc 100644 --- a/main/src/com/google/refine/expr/functions/math/FactN.java +++ b/main/src/com/google/refine/expr/functions/math/FactN.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -80,13 +77,17 @@ public class FactN implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the factorial of a number"); - writer.key("params"); writer.value("number i"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the factorial of a number"; + } + + @Override + public String getParams() { + return "number i"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/Floor.java b/main/src/com/google/refine/expr/functions/math/Floor.java index ccf9aa35f..2d7602b95 100644 --- a/main/src/com/google/refine/expr/functions/math/Floor.java +++ b/main/src/com/google/refine/expr/functions/math/Floor.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,14 +50,18 @@ public class Floor implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the floor of a number as an integer"; + } - writer.object(); - writer.key("description"); writer.value("Returns the floor of a number as an integer"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/GreatestCommonDenominator.java b/main/src/com/google/refine/expr/functions/math/GreatestCommonDenominator.java index a9702f1f6..c9a115112 100644 --- a/main/src/com/google/refine/expr/functions/math/GreatestCommonDenominator.java +++ b/main/src/com/google/refine/expr/functions/math/GreatestCommonDenominator.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -58,13 +55,17 @@ public class GreatestCommonDenominator implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the greatest common denominator of the two numbers"); - writer.key("params"); writer.value("number d, number e"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the greatest common denominator of the two numbers"; + } + + @Override + public String getParams() { + return "number d, number e"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/LeastCommonMultiple.java b/main/src/com/google/refine/expr/functions/math/LeastCommonMultiple.java index 1fb8054d2..ad6635421 100644 --- a/main/src/com/google/refine/expr/functions/math/LeastCommonMultiple.java +++ b/main/src/com/google/refine/expr/functions/math/LeastCommonMultiple.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -70,13 +67,17 @@ public class LeastCommonMultiple implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the greatest common denominator of the two numbers"); - writer.key("params"); writer.value("number d, number e"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the greatest common denominator of the two numbers"; + } + + @Override + public String getParams() { + return "number d, number e"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/Ln.java b/main/src/com/google/refine/expr/functions/math/Ln.java index 227eb15be..2da1c4249 100644 --- a/main/src/com/google/refine/expr/functions/math/Ln.java +++ b/main/src/com/google/refine/expr/functions/math/Ln.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class Ln implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the natural log of n"; + } - writer.object(); - writer.key("description"); writer.value("Returns the natural log of n"); - writer.key("params"); writer.value("number n"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "number n"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/Log.java b/main/src/com/google/refine/expr/functions/math/Log.java index e24b74955..efeac212d 100644 --- a/main/src/com/google/refine/expr/functions/math/Log.java +++ b/main/src/com/google/refine/expr/functions/math/Log.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class Log implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the base 10 log of n"; + } - writer.object(); - writer.key("description"); writer.value("Returns the base 10 log of n"); - writer.key("params"); writer.value("number n"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "number n"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/Max.java b/main/src/com/google/refine/expr/functions/math/Max.java index a59d86cb8..8fa28325a 100644 --- a/main/src/com/google/refine/expr/functions/math/Max.java +++ b/main/src/com/google/refine/expr/functions/math/Max.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -57,13 +54,17 @@ public class Max implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the greater of two numbers"; + } - writer.object(); - writer.key("description"); writer.value("Returns the greater of two numbers"); - writer.key("params"); writer.value("number a, number b"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "number a, number b"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/Min.java b/main/src/com/google/refine/expr/functions/math/Min.java index 7b7b146c2..fad87784f 100644 --- a/main/src/com/google/refine/expr/functions/math/Min.java +++ b/main/src/com/google/refine/expr/functions/math/Min.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -57,13 +54,17 @@ public class Min implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the smaller of two numbers"; + } - writer.object(); - writer.key("description"); writer.value("Returns the smaller of two numbers"); - writer.key("params"); writer.value("number a, number b"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "number a, number b"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/Mod.java b/main/src/com/google/refine/expr/functions/math/Mod.java index d48f93ced..2851f0d1d 100644 --- a/main/src/com/google/refine/expr/functions/math/Mod.java +++ b/main/src/com/google/refine/expr/functions/math/Mod.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -58,13 +55,17 @@ public class Mod implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns a modulus b"; + } - writer.object(); - writer.key("description"); writer.value("Returns a modulus b"); - writer.key("params"); writer.value("number a, number b"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "number a, number b"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/Multinomial.java b/main/src/com/google/refine/expr/functions/math/Multinomial.java index bf20eaa1a..64fdfe437 100644 --- a/main/src/com/google/refine/expr/functions/math/Multinomial.java +++ b/main/src/com/google/refine/expr/functions/math/Multinomial.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -63,13 +60,17 @@ public class Multinomial implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Calculates the multinomial of a series of numbers"); - writer.key("params"); writer.value("one or more numbers"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Calculates the multinomial of a series of numbers"; + } + + @Override + public String getParams() { + return "one or more numbers"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/Odd.java b/main/src/com/google/refine/expr/functions/math/Odd.java index e43788417..1c5b6198e 100644 --- a/main/src/com/google/refine/expr/functions/math/Odd.java +++ b/main/src/com/google/refine/expr/functions/math/Odd.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -58,13 +55,17 @@ public class Odd implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Rounds the number up to the nearest even integer"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Rounds the number up to the nearest even integer"; + } + + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/Pow.java b/main/src/com/google/refine/expr/functions/math/Pow.java index 32e76c860..dcfa71bdf 100644 --- a/main/src/com/google/refine/expr/functions/math/Pow.java +++ b/main/src/com/google/refine/expr/functions/math/Pow.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.grel.Function; public class Pow implements Function { @@ -54,13 +51,17 @@ public class Pow implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns a^b"; + } - writer.object(); - writer.key("description"); writer.value("Returns a^b"); - writer.key("params"); writer.value("number a, number b"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "number a, number b"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/Quotient.java b/main/src/com/google/refine/expr/functions/math/Quotient.java index c484cfb59..93f6718a4 100644 --- a/main/src/com/google/refine/expr/functions/math/Quotient.java +++ b/main/src/com/google/refine/expr/functions/math/Quotient.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -54,13 +51,17 @@ public class Quotient implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the integer portion of a division"); - writer.key("params"); writer.value("number numerator, number denominator"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the integer portion of a division"; + } + + @Override + public String getParams() { + return "number numerator, number denominator"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/Radians.java b/main/src/com/google/refine/expr/functions/math/Radians.java index c74e0834f..9f1115a15 100644 --- a/main/src/com/google/refine/expr/functions/math/Radians.java +++ b/main/src/com/google/refine/expr/functions/math/Radians.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class Radians implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Converts an angle in degrees to radians"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Converts an angle in degrees to radians"; + } + + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/Round.java b/main/src/com/google/refine/expr/functions/math/Round.java index f88cdadbc..4537c3067 100644 --- a/main/src/com/google/refine/expr/functions/math/Round.java +++ b/main/src/com/google/refine/expr/functions/math/Round.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class Round implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns n rounded"; + } - writer.object(); - writer.key("description"); writer.value("Returns n rounded"); - writer.key("params"); writer.value("number n"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "number n"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/Sin.java b/main/src/com/google/refine/expr/functions/math/Sin.java index b862402ae..599eccb65 100644 --- a/main/src/com/google/refine/expr/functions/math/Sin.java +++ b/main/src/com/google/refine/expr/functions/math/Sin.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class Sin implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the trigonometric sine of an angle"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the trigonometric sine of an angle"; + } + + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/Sinh.java b/main/src/com/google/refine/expr/functions/math/Sinh.java index 9f26a42d9..94d0e2d5e 100644 --- a/main/src/com/google/refine/expr/functions/math/Sinh.java +++ b/main/src/com/google/refine/expr/functions/math/Sinh.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class Sinh implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the hyperbolic sine of an angle"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the hyperbolic sine of an angle"; + } + + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/Sum.java b/main/src/com/google/refine/expr/functions/math/Sum.java index aee0878e2..03da9acc5 100644 --- a/main/src/com/google/refine/expr/functions/math/Sum.java +++ b/main/src/com/google/refine/expr/functions/math/Sum.java @@ -36,9 +36,6 @@ package com.google.refine.expr.functions.math; import java.util.List; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.expr.ExpressionUtils; import com.google.refine.grel.ControlFunctionRegistry; @@ -82,13 +79,17 @@ public class Sum implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Sums numbers in array a"; + } - writer.object(); - writer.key("description"); writer.value("Sums numbers in array a"); - writer.key("params"); writer.value("array a"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "array a"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/math/Tan.java b/main/src/com/google/refine/expr/functions/math/Tan.java index 8eb7f9018..b510c75bb 100644 --- a/main/src/com/google/refine/expr/functions/math/Tan.java +++ b/main/src/com/google/refine/expr/functions/math/Tan.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class Tan implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the trigonometric tangent of an angle"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the trigonometric tangent of an angle"; + } + + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/math/Tanh.java b/main/src/com/google/refine/expr/functions/math/Tanh.java index 0d9d5c6c9..49be8c5ad 100644 --- a/main/src/com/google/refine/expr/functions/math/Tanh.java +++ b/main/src/com/google/refine/expr/functions/math/Tanh.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.math; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -53,13 +50,17 @@ public class Tanh implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Returns the hyperbolic tangent of a value"); - writer.key("params"); writer.value("number d"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + public String getDescription() { + return "Returns the hyperbolic tangent of a value"; + } + + @Override + public String getParams() { + return "number d"; + } + + @Override + public String getReturns() { + return "number"; } } \ No newline at end of file diff --git a/main/src/com/google/refine/expr/functions/strings/Chomp.java b/main/src/com/google/refine/expr/functions/strings/Chomp.java index 8ee9b5ae2..5a0de0ae1 100644 --- a/main/src/com/google/refine/expr/functions/strings/Chomp.java +++ b/main/src/com/google/refine/expr/functions/strings/Chomp.java @@ -36,8 +36,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; import org.apache.commons.lang3.StringUtils; -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.grel.Function; @@ -56,13 +54,17 @@ public class Chomp implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Removes separator from the end of str if it's there, otherwise leave it alone."; + } - writer.object(); - writer.key("description"); writer.value("Removes separator from the end of str if it's there, otherwise leave it alone."); - writer.key("params"); writer.value("string str, string separator"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string str, string separator"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Contains.java b/main/src/com/google/refine/expr/functions/strings/Contains.java index 99737b8de..2e7eb41bc 100644 --- a/main/src/com/google/refine/expr/functions/strings/Contains.java +++ b/main/src/com/google/refine/expr/functions/strings/Contains.java @@ -37,9 +37,6 @@ import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.grel.Function; public class Contains implements Function { @@ -64,13 +61,17 @@ public class Contains implements Function { return null; } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns whether s contains frag"; + } - writer.object(); - writer.key("description"); writer.value("Returns whether s contains frag"); - writer.key("params"); writer.value("string s, string frag"); - writer.key("returns"); writer.value("boolean"); - writer.endObject(); + @Override + public String getParams() { + return "string s, string frag"; + } + + @Override + public String getReturns() { + return "boolean"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Diff.java b/main/src/com/google/refine/expr/functions/strings/Diff.java index 155b0bfea..d6196e39e 100644 --- a/main/src/com/google/refine/expr/functions/strings/Diff.java +++ b/main/src/com/google/refine/expr/functions/strings/Diff.java @@ -37,8 +37,6 @@ import java.time.OffsetDateTime; import java.util.Properties; import org.apache.commons.lang3.StringUtils; -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.grel.Function; @@ -104,12 +102,18 @@ public class Diff implements Function { } @Override - public void write(JSONWriter writer, Properties options) throws JSONException { - writer.object(); - writer.key("description"); writer.value("For strings, returns the portion where they differ. For dates, it returns the difference in given time units"); - writer.key("params"); writer.value("o1, o2, time unit (optional)"); - writer.key("returns"); writer.value("string for strings, number for dates"); - writer.endObject(); + public String getDescription() { + return "For strings, returns the portion where they differ. For dates, it returns the difference in given time units"; + } + + @Override + public String getParams() { + return "o1, o2, time unit (optional)"; + } + + @Override + public String getReturns() { + return "string for strings, number for dates"; } private long getNano(OffsetDateTime odt) { diff --git a/main/src/com/google/refine/expr/functions/strings/EndsWith.java b/main/src/com/google/refine/expr/functions/strings/EndsWith.java index e9d97e391..91d51ea44 100644 --- a/main/src/com/google/refine/expr/functions/strings/EndsWith.java +++ b/main/src/com/google/refine/expr/functions/strings/EndsWith.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -57,13 +54,17 @@ public class EndsWith implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns whether s ends with sub"; + } - writer.object(); - writer.key("description"); writer.value("Returns whether s ends with sub"); - writer.key("params"); writer.value("string s, string sub"); - writer.key("returns"); writer.value("boolean"); - writer.endObject(); + @Override + public String getParams() { + return "string s, string sub"; + } + + @Override + public String getReturns() { + return "boolean"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Escape.java b/main/src/com/google/refine/expr/functions/strings/Escape.java index b25f532de..9f0e5d0e9 100644 --- a/main/src/com/google/refine/expr/functions/strings/Escape.java +++ b/main/src/com/google/refine/expr/functions/strings/Escape.java @@ -38,8 +38,6 @@ import java.net.URLEncoder; import java.util.Properties; import org.apache.commons.lang3.StringEscapeUtils; -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; @@ -85,13 +83,17 @@ public class Escape implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Escapes a string depending on the given escaping mode."; + } - writer.object(); - writer.key("description"); writer.value("Escapes a string depending on the given escaping mode."); - writer.key("params"); writer.value("string s, string mode ['html','xml','csv','url','javascript']"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s, string mode ['html','xml','csv','url','javascript']"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Find.java b/main/src/com/google/refine/expr/functions/strings/Find.java index dfec5d990..1220182e9 100644 --- a/main/src/com/google/refine/expr/functions/strings/Find.java +++ b/main/src/com/google/refine/expr/functions/strings/Find.java @@ -7,9 +7,6 @@ import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -41,13 +38,17 @@ public class Find implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns all the occurances of match given regular expression"; + } - writer.object(); - writer.key("description"); writer.value("Returns all the occurances of match given regular expression"); - writer.key("params"); writer.value("string or regexp"); - writer.key("returns"); writer.value("array of strings"); - writer.endObject(); + @Override + public String getParams() { + return "string or regexp"; + } + + @Override + public String getReturns() { + return "array of strings"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Fingerprint.java b/main/src/com/google/refine/expr/functions/strings/Fingerprint.java index 2ec124915..46cff1b42 100644 --- a/main/src/com/google/refine/expr/functions/strings/Fingerprint.java +++ b/main/src/com/google/refine/expr/functions/strings/Fingerprint.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.clustering.binning.FingerprintKeyer; import com.google.refine.clustering.binning.Keyer; import com.google.refine.grel.Function; @@ -57,13 +54,17 @@ public class Fingerprint implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the fingerprint of s, a derived string that aims to be a more canonical form of it (this is mostly useful for finding clusters of strings related to the same information)."; + } - writer.object(); - writer.key("description"); writer.value("Returns the fingerprint of s, a derived string that aims to be a more canonical form of it (this is mostly useful for finding clusters of strings related to the same information)."); - writer.key("params"); writer.value("string s"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/IndexOf.java b/main/src/com/google/refine/expr/functions/strings/IndexOf.java index a4e0a415c..9edf5d8ca 100644 --- a/main/src/com/google/refine/expr/functions/strings/IndexOf.java +++ b/main/src/com/google/refine/expr/functions/strings/IndexOf.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -57,13 +54,17 @@ public class IndexOf implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the index of sub first ocurring in s"; + } - writer.object(); - writer.key("description"); writer.value("Returns the index of sub first ocurring in s"); - writer.key("params"); writer.value("string s, string sub"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "string s, string sub"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/LastIndexOf.java b/main/src/com/google/refine/expr/functions/strings/LastIndexOf.java index c80dac41b..bab4bf68e 100644 --- a/main/src/com/google/refine/expr/functions/strings/LastIndexOf.java +++ b/main/src/com/google/refine/expr/functions/strings/LastIndexOf.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -57,14 +54,18 @@ public class LastIndexOf implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the index of sub last ocurring in s"; + } - writer.object(); - writer.key("description"); writer.value("Returns the index of sub last ocurring in s"); - writer.key("params"); writer.value("string s, string sub"); - writer.key("returns"); writer.value("number"); - writer.endObject(); + @Override + public String getParams() { + return "string s, string sub"; + } + + @Override + public String getReturns() { + return "number"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/MD5.java b/main/src/com/google/refine/expr/functions/strings/MD5.java index 84213e877..ec2d83136 100644 --- a/main/src/com/google/refine/expr/functions/strings/MD5.java +++ b/main/src/com/google/refine/expr/functions/strings/MD5.java @@ -36,8 +36,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; import org.apache.commons.codec.digest.DigestUtils; -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; @@ -56,13 +54,17 @@ public class MD5 implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the MD5 hash of s"; + } - writer.object(); - writer.key("description"); writer.value("Returns the MD5 hash of s"); - writer.key("params"); writer.value("string s"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Match.java b/main/src/com/google/refine/expr/functions/strings/Match.java index d8f5e0816..141948abf 100644 --- a/main/src/com/google/refine/expr/functions/strings/Match.java +++ b/main/src/com/google/refine/expr/functions/strings/Match.java @@ -37,9 +37,6 @@ import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -78,13 +75,17 @@ public class Match implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns an array of the groups matching the given regular expression"; + } - writer.object(); - writer.key("description"); writer.value("Returns an array of the groups matching the given regular expression"); - writer.key("params"); writer.value("string or regexp"); - writer.key("returns"); writer.value("array of strings"); - writer.endObject(); + @Override + public String getParams() { + return "string or regexp"; + } + + @Override + public String getReturns() { + return "array of strings"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/NGram.java b/main/src/com/google/refine/expr/functions/strings/NGram.java index 4c715a938..e27c9f4c5 100644 --- a/main/src/com/google/refine/expr/functions/strings/NGram.java +++ b/main/src/com/google/refine/expr/functions/strings/NGram.java @@ -36,8 +36,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; import org.apache.commons.lang3.StringUtils; -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; @@ -79,13 +77,17 @@ public class NGram implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns an array of the word ngrams of s"; + } - writer.object(); - writer.key("description"); writer.value("Returns an array of the word ngrams of s"); - writer.key("params"); writer.value("string s, number n"); - writer.key("returns"); writer.value("array of strings"); - writer.endObject(); + @Override + public String getParams() { + return "string s, number n"; + } + + @Override + public String getReturns() { + return "array of strings"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/NGramFingerprint.java b/main/src/com/google/refine/expr/functions/strings/NGramFingerprint.java index d6d1c4da0..c35c03ce9 100644 --- a/main/src/com/google/refine/expr/functions/strings/NGramFingerprint.java +++ b/main/src/com/google/refine/expr/functions/strings/NGramFingerprint.java @@ -36,9 +36,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; import java.util.TreeSet; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.clustering.binning.Keyer; import com.google.refine.clustering.binning.NGramFingerprintKeyer; import com.google.refine.expr.EvalError; @@ -76,13 +73,17 @@ public class NGramFingerprint implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the n-gram fingerprint of s"; + } - writer.object(); - writer.key("description"); writer.value("Returns the n-gram fingerprint of s"); - writer.key("params"); writer.value("string s, number n"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s, number n"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/ParseJson.java b/main/src/com/google/refine/expr/functions/strings/ParseJson.java index 20d1f46ab..3e2725282 100644 --- a/main/src/com/google/refine/expr/functions/strings/ParseJson.java +++ b/main/src/com/google/refine/expr/functions/strings/ParseJson.java @@ -37,7 +37,6 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONTokener; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; @@ -62,13 +61,17 @@ public class ParseJson implements Function { @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Parses a string as JSON"; + } - writer.object(); - writer.key("description"); writer.value("Parses a string as JSON"); - writer.key("params"); writer.value("string s"); - writer.key("returns"); writer.value("JSON object"); - writer.endObject(); + @Override + public String getParams() { + return "string s"; + } + + @Override + public String getReturns() { + return "JSON object"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Partition.java b/main/src/com/google/refine/expr/functions/strings/Partition.java index 7163a5767..ee7acabb9 100644 --- a/main/src/com/google/refine/expr/functions/strings/Partition.java +++ b/main/src/com/google/refine/expr/functions/strings/Partition.java @@ -37,9 +37,6 @@ import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.grel.Function; public class Partition implements Function { @@ -101,14 +98,18 @@ public class Partition implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return + "Returns an array of strings [a,frag,b] where a is the string part before the first occurrence of frag in s and b is what's left. If omitFragment is true, frag is not returned."; + } - writer.object(); - writer.key("description"); writer.value( - "Returns an array of strings [a,frag,b] where a is the string part before the first occurrence of frag in s and b is what's left. If omitFragment is true, frag is not returned."); - writer.key("params"); writer.value("string s, string or regex frag, optional boolean omitFragment"); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "string s, string or regex frag, optional boolean omitFragment"; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Phonetic.java b/main/src/com/google/refine/expr/functions/strings/Phonetic.java index 004e647f5..7c2758fe1 100644 --- a/main/src/com/google/refine/expr/functions/strings/Phonetic.java +++ b/main/src/com/google/refine/expr/functions/strings/Phonetic.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.clustering.binning.ColognePhoneticKeyer; import com.google.refine.clustering.binning.DoubleMetaphoneKeyer; import com.google.refine.clustering.binning.Metaphone3Keyer; @@ -100,13 +97,17 @@ public class Phonetic implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the a phonetic encoding of s (optionally indicating which encoding to use')"; + } - writer.object(); - writer.key("description"); writer.value("Returns the a phonetic encoding of s (optionally indicating which encoding to use')"); - writer.key("params"); writer.value("string s, string encoding (optional, defaults to 'metaphone3')"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s, string encoding (optional, defaults to 'metaphone3')"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/RPartition.java b/main/src/com/google/refine/expr/functions/strings/RPartition.java index 3be977f92..caf155b84 100644 --- a/main/src/com/google/refine/expr/functions/strings/RPartition.java +++ b/main/src/com/google/refine/expr/functions/strings/RPartition.java @@ -37,9 +37,6 @@ import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.grel.Function; public class RPartition implements Function { @@ -102,14 +99,18 @@ public class RPartition implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return + "Returns an array of strings [a,frag,b] where a is the string part before the last occurrence of frag in s and b is what's left. If omitFragment is true, frag is not returned."; + } - writer.object(); - writer.key("description"); writer.value( - "Returns an array of strings [a,frag,b] where a is the string part before the last occurrence of frag in s and b is what's left. If omitFragment is true, frag is not returned."); - writer.key("params"); writer.value("string s, string or regex frag, optional boolean omitFragment"); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "string s, string or regex frag, optional boolean omitFragment"; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Range.java b/main/src/com/google/refine/expr/functions/strings/Range.java index c26d45e5a..815ef639f 100644 --- a/main/src/com/google/refine/expr/functions/strings/Range.java +++ b/main/src/com/google/refine/expr/functions/strings/Range.java @@ -1,11 +1,8 @@ package com.google.refine.expr.functions.strings; +import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.Properties; - -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; @@ -295,14 +292,18 @@ public class Range implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value( - "Returns an array where a and b are the start and the end of the range respectively and c is the step (increment)."); - writer.key("params"); writer.value("A single string 'a', 'a, b' or 'a, b, c' or one, two or three integers a or a, b or a, b, c"); - writer.key("returns"); writer.value("array"); - writer.endObject(); + public String getDescription() { + return + "Returns an array where a and b are the start and the end of the range respectively and c is the step (increment)."; + } + + @Override + public String getParams() { + return "A single string 'a', 'a, b' or 'a, b, c' or one, two or three integers a or a, b or a, b, c"; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Reinterpret.java b/main/src/com/google/refine/expr/functions/strings/Reinterpret.java index d096b90ba..cc7057862 100644 --- a/main/src/com/google/refine/expr/functions/strings/Reinterpret.java +++ b/main/src/com/google/refine/expr/functions/strings/Reinterpret.java @@ -36,9 +36,6 @@ package com.google.refine.expr.functions.strings; import java.io.UnsupportedEncodingException; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.ProjectManager; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; @@ -99,13 +96,17 @@ public class Reinterpret implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns s reinterpreted thru the given encoder."; + } - writer.object(); - writer.key("description"); writer.value("Returns s reinterpreted thru the given encoder."); - writer.key("params"); writer.value("string s, string encoder"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s, string encoder"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Replace.java b/main/src/com/google/refine/expr/functions/strings/Replace.java index 71b96fa71..017dc082e 100644 --- a/main/src/com/google/refine/expr/functions/strings/Replace.java +++ b/main/src/com/google/refine/expr/functions/strings/Replace.java @@ -36,9 +36,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; import java.util.regex.Pattern; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -67,13 +64,17 @@ public class Replace implements Function { @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the string obtained by replacing f with r in s"; + } - writer.object(); - writer.key("description"); writer.value("Returns the string obtained by replacing f with r in s"); - writer.key("params"); writer.value("string s, string or regex f, string r"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s, string or regex f, string r"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/ReplaceChars.java b/main/src/com/google/refine/expr/functions/strings/ReplaceChars.java index 4c32ff606..320df6055 100644 --- a/main/src/com/google/refine/expr/functions/strings/ReplaceChars.java +++ b/main/src/com/google/refine/expr/functions/strings/ReplaceChars.java @@ -36,8 +36,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; import org.apache.commons.lang3.StringUtils; -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; @@ -61,13 +59,17 @@ public class ReplaceChars implements Function { @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the string obtained by replacing all chars in f with the char in s at that same position"; + } - writer.object(); - writer.key("description"); writer.value("Returns the string obtained by replacing all chars in f with the char in s at that same position"); - writer.key("params"); writer.value("string s, string f, string r"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s, string f, string r"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/SHA1.java b/main/src/com/google/refine/expr/functions/strings/SHA1.java index 204b5457e..97eee6946 100644 --- a/main/src/com/google/refine/expr/functions/strings/SHA1.java +++ b/main/src/com/google/refine/expr/functions/strings/SHA1.java @@ -36,8 +36,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; import org.apache.commons.codec.digest.DigestUtils; -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; @@ -56,13 +54,17 @@ public class SHA1 implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the SHA-1 hash of s"; + } - writer.object(); - writer.key("description"); writer.value("Returns the SHA-1 hash of s"); - writer.key("params"); writer.value("string s"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/SmartSplit.java b/main/src/com/google/refine/expr/functions/strings/SmartSplit.java index 937852e1b..6e01ca95b 100644 --- a/main/src/com/google/refine/expr/functions/strings/SmartSplit.java +++ b/main/src/com/google/refine/expr/functions/strings/SmartSplit.java @@ -36,15 +36,12 @@ package com.google.refine.expr.functions.strings; import java.io.IOException; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - -import au.com.bytecode.opencsv.CSVParser; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; +import au.com.bytecode.opencsv.CSVParser; + public class SmartSplit implements Function { static final protected CSVParser s_tabParser = new CSVParser( @@ -104,13 +101,17 @@ public class SmartSplit implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the array of strings obtained by splitting s with separator sep. Handles quotes properly. Guesses tab or comma separator if \"sep\" is not given."; + } - writer.object(); - writer.key("description"); writer.value("Returns the array of strings obtained by splitting s with separator sep. Handles quotes properly. Guesses tab or comma separator if \"sep\" is not given."); - writer.key("params"); writer.value("string s, optional string sep"); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "string s, optional string sep"; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Split.java b/main/src/com/google/refine/expr/functions/strings/Split.java index 2532c9cfc..3a47fd8d8 100644 --- a/main/src/com/google/refine/expr/functions/strings/Split.java +++ b/main/src/com/google/refine/expr/functions/strings/Split.java @@ -37,8 +37,6 @@ import java.util.Properties; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; @@ -76,13 +74,17 @@ public class Split implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the array of strings obtained by splitting s with separator sep. If preserveAllTokens is true, then empty segments are preserved."; + } - writer.object(); - writer.key("description"); writer.value("Returns the array of strings obtained by splitting s with separator sep. If preserveAllTokens is true, then empty segments are preserved."); - writer.key("params"); writer.value("string s, string or regex sep, optional boolean preserveAllTokens"); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "string s, string or regex sep, optional boolean preserveAllTokens"; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/SplitByCharType.java b/main/src/com/google/refine/expr/functions/strings/SplitByCharType.java index 85e316974..4f2980cb8 100644 --- a/main/src/com/google/refine/expr/functions/strings/SplitByCharType.java +++ b/main/src/com/google/refine/expr/functions/strings/SplitByCharType.java @@ -36,8 +36,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; import org.apache.commons.lang3.StringUtils; -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; @@ -58,13 +56,17 @@ public class SplitByCharType implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns an array of strings obtained by splitting s grouping consecutive chars by their unicode type"; + } - writer.object(); - writer.key("description"); writer.value("Returns an array of strings obtained by splitting s grouping consecutive chars by their unicode type"); - writer.key("params"); writer.value("string s"); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "string s"; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/SplitByLengths.java b/main/src/com/google/refine/expr/functions/strings/SplitByLengths.java index dd827797e..41c88ce62 100644 --- a/main/src/com/google/refine/expr/functions/strings/SplitByLengths.java +++ b/main/src/com/google/refine/expr/functions/strings/SplitByLengths.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -71,13 +68,17 @@ public class SplitByLengths implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns the array of strings obtained by splitting s into substrings with the given lengths"; + } - writer.object(); - writer.key("description"); writer.value("Returns the array of strings obtained by splitting s into substrings with the given lengths"); - writer.key("params"); writer.value("string s, number n, ..."); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "string s, number n, ..."; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/StartsWith.java b/main/src/com/google/refine/expr/functions/strings/StartsWith.java index acf9d3d3d..51a803618 100644 --- a/main/src/com/google/refine/expr/functions/strings/StartsWith.java +++ b/main/src/com/google/refine/expr/functions/strings/StartsWith.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -56,13 +53,17 @@ public class StartsWith implements Function { return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects 2 strings"); } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns whether s starts with sub"; + } - writer.object(); - writer.key("description"); writer.value("Returns whether s starts with sub"); - writer.key("params"); writer.value("string s, string sub"); - writer.key("returns"); writer.value("boolean"); - writer.endObject(); + @Override + public String getParams() { + return "string s, string sub"; + } + + @Override + public String getReturns() { + return "boolean"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/ToLowercase.java b/main/src/com/google/refine/expr/functions/strings/ToLowercase.java index f9ec96990..2647b7112 100644 --- a/main/src/com/google/refine/expr/functions/strings/ToLowercase.java +++ b/main/src/com/google/refine/expr/functions/strings/ToLowercase.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -54,13 +51,17 @@ public class ToLowercase implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns s converted to lowercase"; + } - writer.object(); - writer.key("description"); writer.value("Returns s converted to lowercase"); - writer.key("params"); writer.value("string s"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/ToTitlecase.java b/main/src/com/google/refine/expr/functions/strings/ToTitlecase.java index e1bb2d7d8..17a1a3e7e 100644 --- a/main/src/com/google/refine/expr/functions/strings/ToTitlecase.java +++ b/main/src/com/google/refine/expr/functions/strings/ToTitlecase.java @@ -36,8 +36,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; import org.apache.commons.lang3.text.WordUtils; -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; @@ -64,14 +62,18 @@ public class ToTitlecase implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns s converted to titlecase"; + } - writer.object(); - writer.key("description"); writer.value("Returns s converted to titlecase"); - writer.key("params"); writer.value("string s"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/ToUppercase.java b/main/src/com/google/refine/expr/functions/strings/ToUppercase.java index f3b13db41..bfe0e1246 100644 --- a/main/src/com/google/refine/expr/functions/strings/ToUppercase.java +++ b/main/src/com/google/refine/expr/functions/strings/ToUppercase.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; @@ -54,13 +51,17 @@ public class ToUppercase implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns s converted to uppercase"; + } - writer.object(); - writer.key("description"); writer.value("Returns s converted to uppercase"); - writer.key("params"); writer.value("string s"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Trim.java b/main/src/com/google/refine/expr/functions/strings/Trim.java index 9f1051a57..6d75a74ca 100644 --- a/main/src/com/google/refine/expr/functions/strings/Trim.java +++ b/main/src/com/google/refine/expr/functions/strings/Trim.java @@ -35,11 +35,7 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.common.base.CharMatcher; - import com.google.refine.expr.EvalError; import com.google.refine.grel.Function; @@ -56,13 +52,17 @@ public class Trim implements Function { return new EvalError("Invalid parameters"); } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns copy of the string, with leading and trailing whitespace omitted."; + } - writer.object(); - writer.key("description"); writer.value("Returns copy of the string, with leading and trailing whitespace omitted."); - writer.key("params"); writer.value("string s"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Unescape.java b/main/src/com/google/refine/expr/functions/strings/Unescape.java index c3292d351..95a7742ae 100644 --- a/main/src/com/google/refine/expr/functions/strings/Unescape.java +++ b/main/src/com/google/refine/expr/functions/strings/Unescape.java @@ -38,8 +38,6 @@ import java.net.URLDecoder; import java.util.Properties; import org.apache.commons.lang3.StringEscapeUtils; -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; @@ -76,13 +74,17 @@ public class Unescape implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Unescapes all escaped parts of the string depending on the given escaping mode."; + } - writer.object(); - writer.key("description"); writer.value("Unescapes all escaped parts of the string depending on the given escaping mode."); - writer.key("params"); writer.value("string s, string mode ['html','xml','csv','url','javascript']"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s, string mode ['html','xml','csv','url','javascript']"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/Unicode.java b/main/src/com/google/refine/expr/functions/strings/Unicode.java index d1bed5545..69e0f8bee 100644 --- a/main/src/com/google/refine/expr/functions/strings/Unicode.java +++ b/main/src/com/google/refine/expr/functions/strings/Unicode.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.grel.Function; public class Unicode implements Function { @@ -57,13 +54,17 @@ public class Unicode implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns an array of strings describing each character of s in their full unicode notation"; + } - writer.object(); - writer.key("description"); writer.value("Returns an array of strings describing each character of s in their full unicode notation"); - writer.key("params"); writer.value("string s"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/strings/UnicodeType.java b/main/src/com/google/refine/expr/functions/strings/UnicodeType.java index 3ca1e9aeb..7bf2eb0f9 100644 --- a/main/src/com/google/refine/expr/functions/strings/UnicodeType.java +++ b/main/src/com/google/refine/expr/functions/strings/UnicodeType.java @@ -35,9 +35,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.grel.Function; public class UnicodeType implements Function { @@ -94,13 +91,17 @@ public class UnicodeType implements Function { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Returns an array of strings describing each character of s in their full unicode notation"; + } - writer.object(); - writer.key("description"); writer.value("Returns an array of strings describing each character of s in their full unicode notation"); - writer.key("params"); writer.value("string s"); - writer.key("returns"); writer.value("string"); - writer.endObject(); + @Override + public String getParams() { + return "string s"; + } + + @Override + public String getReturns() { + return "string"; } } diff --git a/main/src/com/google/refine/expr/functions/xml/OwnText.java b/main/src/com/google/refine/expr/functions/xml/OwnText.java index 8066b9473..0604f8899 100644 --- a/main/src/com/google/refine/expr/functions/xml/OwnText.java +++ b/main/src/com/google/refine/expr/functions/xml/OwnText.java @@ -35,8 +35,6 @@ package com.google.refine.expr.functions.xml; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; import org.jsoup.nodes.Element; import com.google.refine.expr.EvalError; @@ -62,14 +60,18 @@ public class OwnText implements Function { @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Gets the text owned by this XML/HTML element only; does not get the combined text of all children."); - writer.key("params"); writer.value("Element e"); - writer.key("returns"); writer.value("String ownText"); - writer.endObject(); + public String getDescription() { + return "Gets the text owned by this XML/HTML element only; does not get the combined text of all children."; + } + + @Override + public String getParams() { + return "Element e"; + } + + @Override + public String getReturns() { + return "String ownText"; } } diff --git a/main/src/com/google/refine/expr/functions/xml/SelectXml.java b/main/src/com/google/refine/expr/functions/xml/SelectXml.java index 8bb8d3a84..fff66aac6 100644 --- a/main/src/com/google/refine/expr/functions/xml/SelectXml.java +++ b/main/src/com/google/refine/expr/functions/xml/SelectXml.java @@ -35,8 +35,6 @@ package com.google.refine.expr.functions.xml; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; import org.jsoup.nodes.Element; import com.google.refine.expr.EvalError; @@ -64,14 +62,18 @@ public class SelectXml implements Function { @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Selects an element from an XML or HTML element using selector syntax."); - writer.key("params"); writer.value("Element e, String s"); - writer.key("returns"); writer.value("XML/HTML Elements"); - writer.endObject(); + public String getDescription() { + return "Selects an element from an XML or HTML elementn using selector syntax."; + } + + @Override + public String getParams() { + return "Element e, String s"; + } + + @Override + public String getReturns() { + return "HTML Elements"; } } diff --git a/main/src/com/google/refine/expr/functions/xml/XmlAttr.java b/main/src/com/google/refine/expr/functions/xml/XmlAttr.java index c4746038d..626514efa 100644 --- a/main/src/com/google/refine/expr/functions/xml/XmlAttr.java +++ b/main/src/com/google/refine/expr/functions/xml/XmlAttr.java @@ -35,8 +35,6 @@ package com.google.refine.expr.functions.xml; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; import org.jsoup.nodes.Element; import com.google.refine.expr.EvalError; @@ -64,14 +62,18 @@ public class XmlAttr implements Function { @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Selects a value from an attribute on an xml or html Element."); - writer.key("params"); writer.value("Element e, String s"); - writer.key("returns"); writer.value("String attribute Value"); - writer.endObject(); + public String getDescription() { + return "Selects a value from an attribute on an XML or HTML Element"; + } + + @Override + public String getParams() { + return "Element e, String s"; + } + + @Override + public String getReturns() { + return "String attribute Value"; } } diff --git a/main/src/com/google/refine/expr/functions/xml/XmlText.java b/main/src/com/google/refine/expr/functions/xml/XmlText.java index 014eb8016..8d9167a3b 100644 --- a/main/src/com/google/refine/expr/functions/xml/XmlText.java +++ b/main/src/com/google/refine/expr/functions/xml/XmlText.java @@ -35,8 +35,6 @@ package com.google.refine.expr.functions.xml; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; import org.jsoup.nodes.Element; import com.google.refine.expr.EvalError; @@ -62,14 +60,18 @@ public class XmlText implements Function { @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value("Selects the text from within an element (including all child elements)"); - writer.key("params"); writer.value("Element e"); - writer.key("returns"); writer.value("String text"); - writer.endObject(); + public String getDescription() { + return "Selects the text from within an element (including all child elements)"; + } + + @Override + public String getParams() { + return "Element e"; + } + + @Override + public String getReturns() { + return "String text"; } } diff --git a/main/src/com/google/refine/grel/Function.java b/main/src/com/google/refine/grel/Function.java index 1153bf6f8..c3c346855 100644 --- a/main/src/com/google/refine/grel/Function.java +++ b/main/src/com/google/refine/grel/Function.java @@ -35,6 +35,11 @@ package com.google.refine.grel; import java.util.Properties; +import org.json.JSONWriter; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.Jsonizable; /** @@ -43,4 +48,27 @@ import com.google.refine.Jsonizable; */ public interface Function extends Jsonizable { public Object call(Properties bindings, Object[] args); + + @JsonProperty("description") + public String getDescription(); + + @JsonProperty("params") + @JsonInclude(Include.NON_EMPTY) + default public String getParams() { + return ""; + } + + @JsonProperty("returns") + public String getReturns(); + + @Override + default public void write(JSONWriter writer, Properties options) { + writer.object(); + writer.key("description"); writer.value(getDescription()); + if (!getParams().isEmpty()) { + writer.key("params"); writer.value(getParams()); + } + writer.key("returns"); writer.value(getReturns()); + writer.endObject(); + } } From c140f90db11096534553a15a7202bcf628127d9a Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 23 Sep 2018 14:46:48 +0100 Subject: [PATCH 003/164] Jackson serialization for GREL controls --- main/src/com/google/refine/grel/Control.java | 32 +++++++++++++++++++ .../google/refine/grel/controls/Filter.java | 20 ++++++------ .../google/refine/grel/controls/ForEach.java | 21 ++++++------ .../refine/grel/controls/ForEachIndex.java | 20 ++++++------ .../refine/grel/controls/ForNonBlank.java | 22 +++++++------ .../google/refine/grel/controls/ForRange.java | 20 ++++++------ .../com/google/refine/grel/controls/If.java | 22 +++++++------ .../google/refine/grel/controls/IsBlank.java | 2 +- .../refine/grel/controls/IsEmptyString.java | 2 +- .../google/refine/grel/controls/IsError.java | 2 +- .../refine/grel/controls/IsNonBlank.java | 2 +- .../refine/grel/controls/IsNotNull.java | 2 +- .../google/refine/grel/controls/IsNull.java | 2 +- .../refine/grel/controls/IsNumeric.java | 2 +- .../google/refine/grel/controls/IsTest.java | 18 ++++------- .../com/google/refine/grel/controls/With.java | 23 +++++++------ 16 files changed, 124 insertions(+), 88 deletions(-) diff --git a/main/src/com/google/refine/grel/Control.java b/main/src/com/google/refine/grel/Control.java index a887fb546..a4e475da1 100644 --- a/main/src/com/google/refine/grel/Control.java +++ b/main/src/com/google/refine/grel/Control.java @@ -35,6 +35,13 @@ package com.google.refine.grel; import java.util.Properties; +import org.json.JSONException; +import org.json.JSONWriter; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.expr.Evaluable; @@ -47,4 +54,29 @@ public interface Control extends Jsonizable { public Object call(Properties bindings, Evaluable[] args); public String checkArguments(Evaluable[] args); + + @JsonProperty("description") + public String getDescription(); + + @JsonProperty("params") + @JsonInclude(Include.NON_EMPTY) + default public String getParams() { + return ""; + } + + @JsonProperty("returns") + public String getReturns(); + + @Override + default public void write(JSONWriter writer, Properties options) + throws JSONException { + + writer.object(); + writer.key("description"); writer.value(getDescription()); + if (!getParams().isEmpty()) { + writer.key("params"); writer.value(getParams()); + } + writer.key("returns"); writer.value(getReturns()); + writer.endObject(); + } } diff --git a/main/src/com/google/refine/grel/controls/Filter.java b/main/src/com/google/refine/grel/controls/Filter.java index 1ae69f51c..ebce67b6f 100644 --- a/main/src/com/google/refine/grel/controls/Filter.java +++ b/main/src/com/google/refine/grel/controls/Filter.java @@ -148,15 +148,17 @@ public class Filter implements Control { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Evaluates expression a to an array. Then for each array element, binds its value to variable name v, evaluates expression test which should return a boolean. If the boolean is true, pushes v onto the result array."; + } - writer.object(); - writer.key("description"); writer.value( - "Evaluates expression a to an array. Then for each array element, binds its value to variable name v, evaluates expression test which should return a boolean. If the boolean is true, pushes v onto the result array." - ); - writer.key("params"); writer.value("expression a, variable v, expression test"); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "expression a, variable v, expression test"; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/grel/controls/ForEach.java b/main/src/com/google/refine/grel/controls/ForEach.java index c02cae44b..493c18619 100644 --- a/main/src/com/google/refine/grel/controls/ForEach.java +++ b/main/src/com/google/refine/grel/controls/ForEach.java @@ -40,7 +40,6 @@ import java.util.Properties; import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.expr.Evaluable; @@ -145,15 +144,17 @@ public class ForEach implements Control { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Evaluates expression a to an array. Then for each array element, binds its value to variable name v, evaluates expression e, and pushes the result onto the result array."; + } - writer.object(); - writer.key("description"); writer.value( - "Evaluates expression a to an array. Then for each array element, binds its value to variable name v, evaluates expression e, and pushes the result onto the result array." - ); - writer.key("params"); writer.value("expression a, variable v, expression e"); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "expression a, variable v, expression e"; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/grel/controls/ForEachIndex.java b/main/src/com/google/refine/grel/controls/ForEachIndex.java index 7abe1a912..c673d4916 100644 --- a/main/src/com/google/refine/grel/controls/ForEachIndex.java +++ b/main/src/com/google/refine/grel/controls/ForEachIndex.java @@ -150,15 +150,17 @@ public class ForEachIndex implements Control { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Evaluates expression a to an array. Then for each array element, binds its index to variable i and its value to variable name v, evaluates expression e, and pushes the result onto the result array."; + } - writer.object(); - writer.key("description"); writer.value( - "Evaluates expression a to an array. Then for each array element, binds its index to variable i and its value to variable name v, evaluates expression e, and pushes the result onto the result array." - ); - writer.key("params"); writer.value("expression a, variable i, variable v, expression e"); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "expression a, variable i, variable v, expression e"; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/grel/controls/ForNonBlank.java b/main/src/com/google/refine/grel/controls/ForNonBlank.java index 664c27636..15f0da19b 100644 --- a/main/src/com/google/refine/grel/controls/ForNonBlank.java +++ b/main/src/com/google/refine/grel/controls/ForNonBlank.java @@ -85,16 +85,18 @@ public class ForNonBlank implements Control { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Evaluates expression o. If it is non-blank, binds its value to variable name v, evaluates expression eNonBlank and returns the result. " + + "Otherwise (if o evaluates to blank), evaluates expression eBlank and returns that result instead."; + } - writer.object(); - writer.key("description"); writer.value( - "Evaluates expression o. If it is non-blank, binds its value to variable name v, evaluates expression eNonBlank and returns the result. " + - "Otherwise (if o evaluates to blank), evaluates expression eBlank and returns that result instead." - ); - writer.key("params"); writer.value("expression o, variable v, expression eNonBlank, expression eBlank"); - writer.key("returns"); writer.value("Depends on actual arguments"); - writer.endObject(); + @Override + public String getParams() { + return "expression o, variable v, expression eNonBlank, expression eBlank"; + } + + @Override + public String getReturns() { + return "Depends on actual arguments"; } } diff --git a/main/src/com/google/refine/grel/controls/ForRange.java b/main/src/com/google/refine/grel/controls/ForRange.java index f1a009fe9..61e181b64 100644 --- a/main/src/com/google/refine/grel/controls/ForRange.java +++ b/main/src/com/google/refine/grel/controls/ForRange.java @@ -132,15 +132,17 @@ public class ForRange implements Control { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Iterates over the variable v starting at \"from\", incrementing by \"step\" each time while less than \"to\". At each iteration, evaluates expression e, and pushes the result onto the result array."; + } - writer.object(); - writer.key("description"); writer.value( - "Iterates over the variable v starting at \"from\", incrementing by \"step\" each time while less than \"to\". At each iteration, evaluates expression e, and pushes the result onto the result array." - ); - writer.key("params"); writer.value("number from, number to, number step, variable v, expression e"); - writer.key("returns"); writer.value("array"); - writer.endObject(); + @Override + public String getParams() { + return "number from, number to, number step, variable v, expression e"; + } + + @Override + public String getReturns() { + return "array"; } } diff --git a/main/src/com/google/refine/grel/controls/If.java b/main/src/com/google/refine/grel/controls/If.java index 2139c5160..d4d824b93 100644 --- a/main/src/com/google/refine/grel/controls/If.java +++ b/main/src/com/google/refine/grel/controls/If.java @@ -65,16 +65,18 @@ public class If implements Control { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Evaluates expression o. If it is true, evaluates expression eTrue and returns the result. " + + "Otherwise, evaluates expression eFalse and returns that result instead."; + } - writer.object(); - writer.key("description"); writer.value( - "Evaluates expression o. If it is true, evaluates expression eTrue and returns the result. " + - "Otherwise, evaluates expression eFalse and returns that result instead." - ); - writer.key("params"); writer.value("expression o, expression eTrue, expression eFalse"); - writer.key("returns"); writer.value("Depends on actual arguments"); - writer.endObject(); + @Override + public String getParams() { + return "expression o, expression eTrue, expression eFalse"; + } + + @Override + public String getReturns() { + return "Depends on actual arguments"; } } diff --git a/main/src/com/google/refine/grel/controls/IsBlank.java b/main/src/com/google/refine/grel/controls/IsBlank.java index 4f32e661d..6e1d877ac 100644 --- a/main/src/com/google/refine/grel/controls/IsBlank.java +++ b/main/src/com/google/refine/grel/controls/IsBlank.java @@ -37,7 +37,7 @@ import com.google.refine.expr.ExpressionUtils; public class IsBlank extends IsTest { @Override - protected String getDescription() { + public String getDescription() { return "Returns whether o is null or an empty string"; } diff --git a/main/src/com/google/refine/grel/controls/IsEmptyString.java b/main/src/com/google/refine/grel/controls/IsEmptyString.java index e9154f8e2..cccce3646 100644 --- a/main/src/com/google/refine/grel/controls/IsEmptyString.java +++ b/main/src/com/google/refine/grel/controls/IsEmptyString.java @@ -2,7 +2,7 @@ package com.google.refine.grel.controls; public class IsEmptyString extends IsTest { @Override - protected String getDescription() { + public String getDescription() { return "Returns whether o is an empty string"; } diff --git a/main/src/com/google/refine/grel/controls/IsError.java b/main/src/com/google/refine/grel/controls/IsError.java index d93afa2c7..149c26d7e 100644 --- a/main/src/com/google/refine/grel/controls/IsError.java +++ b/main/src/com/google/refine/grel/controls/IsError.java @@ -37,7 +37,7 @@ import com.google.refine.expr.ExpressionUtils; public class IsError extends IsTest { @Override - protected String getDescription() { + public String getDescription() { return "Returns whether o is an error"; } diff --git a/main/src/com/google/refine/grel/controls/IsNonBlank.java b/main/src/com/google/refine/grel/controls/IsNonBlank.java index 6a7602a7c..d7f6c2d56 100644 --- a/main/src/com/google/refine/grel/controls/IsNonBlank.java +++ b/main/src/com/google/refine/grel/controls/IsNonBlank.java @@ -37,7 +37,7 @@ import com.google.refine.expr.ExpressionUtils; public class IsNonBlank extends IsTest { @Override - protected String getDescription() { + public String getDescription() { return "Returns whether o is not null and not an empty string"; } diff --git a/main/src/com/google/refine/grel/controls/IsNotNull.java b/main/src/com/google/refine/grel/controls/IsNotNull.java index 44d427948..f6e525bc2 100644 --- a/main/src/com/google/refine/grel/controls/IsNotNull.java +++ b/main/src/com/google/refine/grel/controls/IsNotNull.java @@ -35,7 +35,7 @@ package com.google.refine.grel.controls; public class IsNotNull extends IsTest { @Override - protected String getDescription() { + public String getDescription() { return "Returns whether o is not null"; } diff --git a/main/src/com/google/refine/grel/controls/IsNull.java b/main/src/com/google/refine/grel/controls/IsNull.java index cbfbb094e..83ca60e39 100644 --- a/main/src/com/google/refine/grel/controls/IsNull.java +++ b/main/src/com/google/refine/grel/controls/IsNull.java @@ -35,7 +35,7 @@ package com.google.refine.grel.controls; public class IsNull extends IsTest { @Override - protected String getDescription() { + public String getDescription() { return "Returns whether o is null"; } diff --git a/main/src/com/google/refine/grel/controls/IsNumeric.java b/main/src/com/google/refine/grel/controls/IsNumeric.java index 24013793d..b56f08185 100644 --- a/main/src/com/google/refine/grel/controls/IsNumeric.java +++ b/main/src/com/google/refine/grel/controls/IsNumeric.java @@ -37,7 +37,7 @@ import org.apache.commons.lang3.StringUtils; public class IsNumeric extends IsTest { @Override - protected String getDescription() { + public String getDescription() { return "Returns whether o can represent a number"; } diff --git a/main/src/com/google/refine/grel/controls/IsTest.java b/main/src/com/google/refine/grel/controls/IsTest.java index 32c2f2524..307362083 100644 --- a/main/src/com/google/refine/grel/controls/IsTest.java +++ b/main/src/com/google/refine/grel/controls/IsTest.java @@ -35,9 +35,6 @@ package com.google.refine.grel.controls; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.expr.Evaluable; import com.google.refine.grel.Control; @@ -64,17 +61,14 @@ abstract class IsTest implements Control { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getParams() { + return "expression o"; + } - writer.object(); - writer.key("description"); writer.value(getDescription()); - writer.key("params"); writer.value("expression o"); - writer.key("returns"); writer.value("boolean"); - writer.endObject(); + @Override + public String getReturns() { + return "boolean"; } abstract protected boolean test(Object v); - - abstract protected String getDescription(); } diff --git a/main/src/com/google/refine/grel/controls/With.java b/main/src/com/google/refine/grel/controls/With.java index 0833df080..82f80b47d 100644 --- a/main/src/com/google/refine/grel/controls/With.java +++ b/main/src/com/google/refine/grel/controls/With.java @@ -35,9 +35,6 @@ package com.google.refine.grel.controls; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.Evaluable; import com.google.refine.grel.Control; import com.google.refine.grel.ControlFunctionRegistry; @@ -82,15 +79,17 @@ public class With implements Control { } @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { + public String getDescription() { + return "Evaluates expression o and binds its value to variable name v. Then evaluates expression e and returns that result"; + } - writer.object(); - writer.key("description"); writer.value( - "Evaluates expression o and binds its value to variable name v. Then evaluates expression e and returns that result" - ); - writer.key("params"); writer.value("expression o, variable v, expression e"); - writer.key("returns"); writer.value("Depends on actual arguments"); - writer.endObject(); + @Override + public String getParams() { + return "expression o, variable v, expression e"; + } + + @Override + public String getReturns() { + return "Depends on actual arguments"; } } From 539585fc5e9458108c2ae8318e355402723e8344 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 23 Sep 2018 15:11:28 +0100 Subject: [PATCH 004/164] Jackson serialization for cell operations --- .../com/google/refine/browsing/Engine.java | 5 +++ .../google/refine/browsing/EngineConfig.java | 4 ++ .../refine/model/AbstractOperation.java | 13 ++++++ .../EngineDependentMassCellOperation.java | 7 +++ .../operations/EngineDependentOperation.java | 3 ++ .../cell/KeyValueColumnizeOperation.java | 17 ++++++++ .../operations/cell/MassEditOperation.java | 16 +++++++ .../cell/MultiValuedCellJoinOperation.java | 17 ++++++++ .../cell/MultiValuedCellSplitOperation.java | 43 +++++++++++++++++-- .../TransposeRowsIntoColumnsOperation.java | 12 ++++++ .../cell/SplitMultiValuedCellsTests.java | 13 +++++- 11 files changed, 146 insertions(+), 4 deletions(-) diff --git a/main/src/com/google/refine/browsing/Engine.java b/main/src/com/google/refine/browsing/Engine.java index c3e33120d..f0ef66770 100644 --- a/main/src/com/google/refine/browsing/Engine.java +++ b/main/src/com/google/refine/browsing/Engine.java @@ -43,6 +43,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.browsing.facets.Facet; import com.google.refine.browsing.util.ConjunctiveFilteredRecords; @@ -56,8 +58,11 @@ import com.google.refine.model.Row; */ public class Engine implements Jsonizable { static public enum Mode { + @JsonProperty("row-based") RowBased, + @JsonProperty("record-based") RecordBased + } public final static String INCLUDE_DEPENDENT = "includeDependent"; diff --git a/main/src/com/google/refine/browsing/EngineConfig.java b/main/src/com/google/refine/browsing/EngineConfig.java index 0ae50313b..6a058a29f 100644 --- a/main/src/com/google/refine/browsing/EngineConfig.java +++ b/main/src/com/google/refine/browsing/EngineConfig.java @@ -10,6 +10,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.facets.FacetConfig; @@ -30,10 +32,12 @@ public class EngineConfig implements Jsonizable { _mode = mode; } + @JsonProperty("mode") public Mode getMode() { return _mode; } + @JsonProperty("facets") public List getFacetConfigs() { return _facets; } diff --git a/main/src/com/google/refine/model/AbstractOperation.java b/main/src/com/google/refine/model/AbstractOperation.java index af68364e6..f21c930d9 100644 --- a/main/src/com/google/refine/model/AbstractOperation.java +++ b/main/src/com/google/refine/model/AbstractOperation.java @@ -35,8 +35,11 @@ package com.google.refine.model; import java.util.Properties; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.history.HistoryEntry; +import com.google.refine.operations.OperationRegistry; import com.google.refine.process.Process; import com.google.refine.process.QuickHistoryEntryProcess; @@ -61,4 +64,14 @@ abstract public class AbstractOperation implements Jsonizable { protected String getBriefDescription(Project project) { throw new UnsupportedOperationException(); } + + @JsonProperty("op") + public String getOperationId() { + return OperationRegistry.s_opClassToName.get(this.getClass()); + } + + @JsonProperty("description") + public String getJsonDescription() { + return getBriefDescription(null); + } } diff --git a/main/src/com/google/refine/operations/EngineDependentMassCellOperation.java b/main/src/com/google/refine/operations/EngineDependentMassCellOperation.java index d5e02e165..1ebbe8bec 100644 --- a/main/src/com/google/refine/operations/EngineDependentMassCellOperation.java +++ b/main/src/com/google/refine/operations/EngineDependentMassCellOperation.java @@ -36,6 +36,8 @@ package com.google.refine.operations; import java.util.ArrayList; import java.util.List; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; @@ -87,6 +89,11 @@ abstract public class EngineDependentMassCellOperation extends EngineDependentOp cellChanges, column.getName(), _updateRowContextDependencies); } + @JsonProperty("columnName") + protected String getColumnName() { + return _columnName; + } + abstract protected RowVisitor createRowVisitor(Project project, List cellChanges, long historyEntryID) throws Exception; abstract protected String createDescription(Column column, List cellChanges); } diff --git a/main/src/com/google/refine/operations/EngineDependentOperation.java b/main/src/com/google/refine/operations/EngineDependentOperation.java index 8067d160c..3cf969164 100644 --- a/main/src/com/google/refine/operations/EngineDependentOperation.java +++ b/main/src/com/google/refine/operations/EngineDependentOperation.java @@ -33,6 +33,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.model.AbstractOperation; @@ -52,6 +54,7 @@ abstract public class EngineDependentOperation extends AbstractOperation { return engine; } + @JsonProperty("engineConfig") protected EngineConfig getEngineConfig() { return _engineConfig; } diff --git a/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java b/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java index 7ca3380cf..37ca3a7af 100644 --- a/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java +++ b/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java @@ -43,6 +43,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.expr.ExpressionUtils; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; @@ -92,6 +94,21 @@ public class KeyValueColumnizeOperation extends AbstractOperation { writer.key("noteColumnName"); writer.value(_noteColumnName); writer.endObject(); } + + @JsonProperty("keyColumnName") + public String getKeyColumnName() { + return _keyColumnName; + } + + @JsonProperty("valueColumnName") + public String getValueColumnName() { + return _valueColumnName; + } + + @JsonProperty("noteColumnName") + public String getNoteColumnName() { + return _noteColumnName; + } @Override protected String getBriefDescription(Project project) { diff --git a/main/src/com/google/refine/operations/cell/MassEditOperation.java b/main/src/com/google/refine/operations/cell/MassEditOperation.java index b6c21e396..3a288b2fe 100644 --- a/main/src/com/google/refine/operations/cell/MassEditOperation.java +++ b/main/src/com/google/refine/operations/cell/MassEditOperation.java @@ -45,6 +45,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; @@ -67,9 +69,13 @@ public class MassEditOperation extends EngineDependentMassCellOperation { final protected List _edits; static public class Edit implements Jsonizable { + @JsonProperty("from") final public List from; + @JsonProperty("fromBlank") final public boolean fromBlank; + @JsonProperty("fromError") final public boolean fromError; + @JsonProperty("to") final public Serializable to; public Edit(List from, boolean fromBlank, boolean fromError, Serializable to) { @@ -170,6 +176,16 @@ public class MassEditOperation extends EngineDependentMassCellOperation { writer.endArray(); writer.endObject(); } + + @JsonProperty("expression") + public String getExpression() { + return _expression; + } + + @JsonProperty("edits") + public List getEdits() { + return _edits; + } @Override protected String getBriefDescription(Project project) { diff --git a/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java b/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java index 8a7376894..ba1b37a18 100644 --- a/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java +++ b/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java @@ -41,6 +41,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.expr.ExpressionUtils; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; @@ -87,6 +89,21 @@ public class MultiValuedCellJoinOperation extends AbstractOperation { writer.endObject(); } + @JsonProperty("columnName") + public String getColumnName() { + return _columnName; + } + + @JsonProperty("keyColumnName") + public String getKeyColumnName() { + return _keyColumnName; + } + + @JsonProperty("separator") + public String getSeparator() { + return _separator; + } + @Override protected String getBriefDescription(Project project) { return "Join multi-valued cells in column " + _columnName; diff --git a/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java b/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java index 83d2fdbca..d9537f941 100644 --- a/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java +++ b/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java @@ -43,6 +43,10 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; @@ -58,7 +62,7 @@ public class MultiValuedCellSplitOperation extends AbstractOperation { final protected String _keyColumnName; final protected String _mode; final protected String _separator; - final protected boolean _regex; + final protected Boolean _regex; final protected int[] _fieldLengths; @@ -72,7 +76,7 @@ public class MultiValuedCellSplitOperation extends AbstractOperation { obj.getString("separator"), obj.getBoolean("regex") ); - } else { + } else { // mode == "lengths" return new MultiValuedCellSplitOperation( obj.getString("columnName"), obj.getString("keyColumnName"), @@ -106,10 +110,43 @@ public class MultiValuedCellSplitOperation extends AbstractOperation { _mode = "lengths"; _separator = null; - _regex = false; + _regex = null; _fieldLengths = fieldLengths; } + + @JsonProperty("columnName") + public String getColumnName() { + return _columnName; + } + + @JsonProperty("keyColumnName") + public String getKeyColumnName() { + return _keyColumnName; + } + + @JsonProperty("mode") + public String getMode() { + return _mode; + } + + @JsonProperty("separator") + @JsonInclude(Include.NON_NULL) + public String getSeparator() { + return _separator; + } + + @JsonProperty("regex") + @JsonInclude(Include.NON_NULL) + public Boolean getRegex() { + return _regex; + } + + @JsonProperty("fieldLengths") + @JsonInclude(Include.NON_NULL) + public int[] getFieldLengths() { + return _fieldLengths; + } @Override public void write(JSONWriter writer, Properties options) diff --git a/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java b/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java index 0782c70b0..bb145be4a 100644 --- a/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java +++ b/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java @@ -41,6 +41,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; @@ -80,6 +82,16 @@ public class TransposeRowsIntoColumnsOperation extends AbstractOperation { writer.key("rowCount"); writer.value(_rowCount); writer.endObject(); } + + @JsonProperty("rowCount") + public int getRowCount() { + return _rowCount; + } + + @JsonProperty("columnName") + public String getColumnName() { + return _columnName; + } @Override protected String getBriefDescription(Project project) { diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/SplitMultiValuedCellsTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/SplitMultiValuedCellsTests.java index 2db201031..81788b9ac 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/SplitMultiValuedCellsTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/SplitMultiValuedCellsTests.java @@ -72,7 +72,7 @@ public class SplitMultiValuedCellsTests extends RefineTest { } @Test - public void serializeMultiValuedCellSplitOperation() throws JSONException, Exception { + public void serializeMultiValuedCellSplitOperationWithSeparator() throws JSONException, Exception { String json = "{\"op\":\"core/multivalued-cell-split\"," + "\"description\":\"Split multi-valued cells in column Value\"," + "\"columnName\":\"Value\"," @@ -82,6 +82,17 @@ public class SplitMultiValuedCellsTests extends RefineTest { + "\"regex\":false}"; TestUtils.isSerializedTo(MultiValuedCellSplitOperation.reconstruct(project, new JSONObject(json)), json); } + + @Test + public void serializeMultiValuedCellSplitOperationWithLengths() throws JSONException, Exception { + String json = "{\"op\":\"core/multivalued-cell-split\"," + + "\"description\":\"Split multi-valued cells in column Value\"," + + "\"columnName\":\"Value\"," + + "\"keyColumnName\":\"Key\"," + + "\"mode\":\"lengths\"," + + "\"fieldLengths\":[1,1]}"; + TestUtils.isSerializedTo(MultiValuedCellSplitOperation.reconstruct(project, new JSONObject(json)), json); + } /** * Test to demonstrate the intended behaviour of the function, for issue #1268 From a3bba83c630d9ad3c40f5b6188184afff31781ec Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 23 Sep 2018 16:52:07 +0100 Subject: [PATCH 005/164] Jackson serialization for column operations --- .../AddColumnByFetchingURLsCommand.java | 11 +- .../com/google/refine/operations/OnError.java | 5 + ...ColumnAdditionByFetchingURLsOperation.java | 102 ++++++++++++++++-- .../column/ColumnAdditionOperation.java | 27 +++++ .../column/ColumnMoveOperation.java | 13 ++- .../column/ColumnRemovalOperation.java | 7 ++ .../column/ColumnRenameOperation.java | 11 ++ .../column/ColumnReorderOperation.java | 7 ++ .../column/ColumnSplitOperation.java | 56 +++++++++- ...nAdditionByFetchingURLsOperationTests.java | 15 +-- .../column/ColumnSplitOperationTests.java | 21 +++- 11 files changed, 248 insertions(+), 27 deletions(-) diff --git a/main/src/com/google/refine/commands/column/AddColumnByFetchingURLsCommand.java b/main/src/com/google/refine/commands/column/AddColumnByFetchingURLsCommand.java index fa0112e25..13c7ea762 100644 --- a/main/src/com/google/refine/commands/column/AddColumnByFetchingURLsCommand.java +++ b/main/src/com/google/refine/commands/column/AddColumnByFetchingURLsCommand.java @@ -33,9 +33,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.commands.column; +import java.util.Arrays; +import java.util.List; + import javax.servlet.http.HttpServletRequest; -import org.json.JSONArray; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.refine.browsing.EngineConfig; import com.google.refine.commands.EngineDependentCommand; @@ -43,6 +46,7 @@ import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.operations.cell.TextTransformOperation; import com.google.refine.operations.column.ColumnAdditionByFetchingURLsOperation; +import com.google.refine.operations.column.ColumnAdditionByFetchingURLsOperation.HttpHeader; public class AddColumnByFetchingURLsCommand extends EngineDependentCommand { @Override @@ -56,7 +60,8 @@ public class AddColumnByFetchingURLsCommand extends EngineDependentCommand { int delay = Integer.parseInt(request.getParameter("delay")); String onError = request.getParameter("onError"); boolean cacheResponses = Boolean.parseBoolean(request.getParameter("cacheResponses")); - JSONArray httpHeadersJson = new JSONArray(request.getParameter("httpHeaders")); + ObjectMapper mapper = new ObjectMapper(); + List headers = Arrays.asList(mapper.readValue(request.getParameter("httpHeaders"), HttpHeader[].class)); return new ColumnAdditionByFetchingURLsOperation( engineConfig, @@ -67,7 +72,7 @@ public class AddColumnByFetchingURLsCommand extends EngineDependentCommand { columnInsertIndex, delay, cacheResponses, - httpHeadersJson + headers ); } diff --git a/main/src/com/google/refine/operations/OnError.java b/main/src/com/google/refine/operations/OnError.java index 3fc0c7695..a43b604dd 100644 --- a/main/src/com/google/refine/operations/OnError.java +++ b/main/src/com/google/refine/operations/OnError.java @@ -33,8 +33,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations; +import com.fasterxml.jackson.annotation.JsonProperty; + public enum OnError { + @JsonProperty("keep-original") KeepOriginal, + @JsonProperty("set-to-blank") SetToBlank, + @JsonProperty("store-error") StoreError } \ No newline at end of file diff --git a/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java b/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java index fa6a6f12a..8af2c0dcf 100644 --- a/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java @@ -50,10 +50,13 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; +import com.google.refine.Jsonizable; import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; @@ -81,6 +84,27 @@ import com.google.refine.util.ParsingUtilities; public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperation { + public static final class HttpHeader implements Jsonizable { + @JsonProperty("name") + final public String name; + @JsonProperty("value") + final public String value; + + public HttpHeader(String name, String value) { + this.name = name; + this.value = value; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("name"); writer.value(name); + writer.key("value"); writer.value(value); + writer.endObject(); + } + } + final protected String _baseColumnName; final protected String _urlExpression; final protected OnError _onError; @@ -89,10 +113,21 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat final protected int _columnInsertIndex; final protected int _delay; final protected boolean _cacheResponses; - final protected JSONArray _httpHeadersJson; + final protected List _httpHeadersJson; static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { JSONObject engineConfig = obj.getJSONObject("engineConfig"); + + List headers = null; + JSONArray headersJson = obj.optJSONArray("httpHeadersJson"); + if (headersJson != null) { + headers = new ArrayList<>(headersJson.length()); + for (int i = 0; i < headersJson.length(); i++) { + String headerLabel = headersJson.getJSONObject(i).getString("name"); + String headerValue = headersJson.getJSONObject(i).getString("value"); + headers.add(new HttpHeader(headerLabel, headerValue)); + } + } return new ColumnAdditionByFetchingURLsOperation( EngineConfig.reconstruct(engineConfig), @@ -103,7 +138,7 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat obj.getInt("columnInsertIndex"), obj.getInt("delay"), obj.optBoolean("cacheResponses", false), // false for retro-compatibility - obj.optJSONArray("httpHeadersJson") // will be null if it doesn't exist for retro-compatibility + headers // will be null if it doesn't exist for retro-compatibility ); } @@ -116,7 +151,7 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat int columnInsertIndex, int delay, boolean cacheResponses, - JSONArray httpHeadersJson + List httpHeadersJson ) { super(engineConfig); @@ -147,9 +182,56 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat writer.key("onError"); writer.value(TextTransformOperation.onErrorToString(_onError)); writer.key("delay"); writer.value(_delay); writer.key("cacheResponses"); writer.value(_cacheResponses); - writer.key("httpHeadersJson"); writer.value(_httpHeadersJson); + if (_httpHeadersJson != null) { + writer.key("httpHeadersJson"); + writer.array(); + for(HttpHeader header : _httpHeadersJson) { + header.write(writer, options); + } + writer.endArray(); + } writer.endObject(); } + + @JsonProperty("newColumnName") + public String getNewColumnName() { + return _newColumnName; + } + + @JsonProperty("columnInsertIndex") + public int getColumnInsertIndex() { + return _columnInsertIndex; + } + + @JsonProperty("baseColumnName") + public String getBaseColumnName() { + return _baseColumnName; + } + + @JsonProperty("urlExpression") + public String getUrlExpression() { + return _urlExpression; + } + + @JsonProperty("onError") + public OnError getOnError() { + return _onError; + } + + @JsonProperty("delay") + public int getDelay() { + return _delay; + } + + @JsonProperty("httpHeadersJson") + public List getHttpHeadersJson() { + return _httpHeadersJson; + } + + @JsonProperty("cacheResponses") + public boolean getCacheResponses() { + return _cacheResponses; + } @Override protected String getBriefDescription(Project project) { @@ -179,8 +261,7 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat engine, eval, getBriefDescription(null), - _cacheResponses, - _httpHeadersJson + _cacheResponses ); } @@ -197,8 +278,7 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat Engine engine, Evaluable eval, String description, - boolean cacheResponses, - JSONArray httpHeadersJson + boolean cacheResponses ) throws JSONException { super(description); _project = project; @@ -335,9 +415,9 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat try { URLConnection urlConnection = url.openConnection(); if (_httpHeadersJson != null) { - for (int i = 0; i < _httpHeadersJson.length(); i++) { - String headerLabel = _httpHeadersJson.getJSONObject(i).getString("name"); - String headerValue = _httpHeadersJson.getJSONObject(i).getString("value"); + for (int i = 0; i < _httpHeadersJson.size(); i++) { + String headerLabel = _httpHeadersJson.get(i).name; + String headerValue = _httpHeadersJson.get(i).value; if (headerValue != null && !headerValue.isEmpty()) { urlConnection.setRequestProperty(headerLabel, headerValue); } diff --git a/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java b/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java index cf2d3b10b..0d4334a07 100644 --- a/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java @@ -42,6 +42,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; @@ -118,7 +120,32 @@ public class ColumnAdditionOperation extends EngineDependentOperation { writer.key("onError"); writer.value(TextTransformOperation.onErrorToString(_onError)); writer.endObject(); } + + @JsonProperty("newColumnName") + public String getNewColumnName() { + return _newColumnName; + } + + @JsonProperty("columnInsertIndex") + public int getColumnInsertIndex() { + return _columnInsertIndex; + } + + @JsonProperty("baseColumnName") + public String getBaseColumnName() { + return _baseColumnName; + } + + @JsonProperty("expression") + public String getExpression() { + return _expression; + } + @JsonProperty("onError") + public OnError getOnError() { + return _onError; + } + @Override protected String getBriefDescription(Project project) { return "Create column " + _newColumnName + diff --git a/main/src/com/google/refine/operations/column/ColumnMoveOperation.java b/main/src/com/google/refine/operations/column/ColumnMoveOperation.java index c4f18a3fc..a000859da 100644 --- a/main/src/com/google/refine/operations/column/ColumnMoveOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnMoveOperation.java @@ -39,6 +39,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.history.Change; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; @@ -76,7 +78,16 @@ public class ColumnMoveOperation extends AbstractOperation { writer.key("index"); writer.value(_index); writer.endObject(); } - + + @JsonProperty("columnName") + public String getColumnName() { + return _columnName; + } + + @JsonProperty("index") + public int getIndex() { + return _index; + } @Override protected String getBriefDescription(Project project) { diff --git a/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java b/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java index 54fb8116a..5de7a5895 100644 --- a/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java @@ -39,6 +39,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.history.Change; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; @@ -72,6 +74,11 @@ public class ColumnRemovalOperation extends AbstractOperation { writer.key("columnName"); writer.value(_columnName); writer.endObject(); } + + @JsonProperty("columnName") + public String getColumnName() { + return _columnName; + } @Override diff --git a/main/src/com/google/refine/operations/column/ColumnRenameOperation.java b/main/src/com/google/refine/operations/column/ColumnRenameOperation.java index 846f66fbc..0d4b85c9a 100644 --- a/main/src/com/google/refine/operations/column/ColumnRenameOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnRenameOperation.java @@ -39,6 +39,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.history.Change; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; @@ -76,7 +78,16 @@ public class ColumnRenameOperation extends AbstractOperation { writer.key("newColumnName"); writer.value(_newColumnName); writer.endObject(); } + + @JsonProperty("oldColumnName") + public String getOldColumnName() { + return _oldColumnName; + } + @JsonProperty("newColumnName") + public String getNewColumnName() { + return _newColumnName; + } @Override protected String getBriefDescription(Project project) { diff --git a/main/src/com/google/refine/operations/column/ColumnReorderOperation.java b/main/src/com/google/refine/operations/column/ColumnReorderOperation.java index 4920b2e5e..3b7f906a8 100644 --- a/main/src/com/google/refine/operations/column/ColumnReorderOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnReorderOperation.java @@ -41,6 +41,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; @@ -77,6 +79,11 @@ public class ColumnReorderOperation extends AbstractOperation { writer.endArray(); writer.endObject(); } + + @JsonProperty("columnNames") + public List getColumnNames() { + return _columnNames; + } @Override protected String getBriefDescription(Project project) { diff --git a/main/src/com/google/refine/operations/column/ColumnSplitOperation.java b/main/src/com/google/refine/operations/column/ColumnSplitOperation.java index f4c7aeeea..adc7d1860 100644 --- a/main/src/com/google/refine/operations/column/ColumnSplitOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnSplitOperation.java @@ -44,6 +44,10 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; @@ -68,8 +72,8 @@ public class ColumnSplitOperation extends EngineDependentOperation { final protected String _mode; final protected String _separator; - final protected boolean _regex; - final protected int _maxColumns; + final protected Boolean _regex; + final protected Integer _maxColumns; final protected int[] _fieldLengths; @@ -136,8 +140,8 @@ public class ColumnSplitOperation extends EngineDependentOperation { _mode = "lengths"; _separator = null; - _regex = false; - _maxColumns = -1; + _regex = null; + _maxColumns = null; _fieldLengths = fieldLengths; } @@ -167,6 +171,50 @@ public class ColumnSplitOperation extends EngineDependentOperation { } writer.endObject(); } + + @JsonProperty("columnName") + public String getColumnName() { + return _columnName; + } + + @JsonProperty("guessCellType") + public boolean getGuessCellType() { + return _guessCellType; + } + + @JsonProperty("removeOriginalColumn") + public boolean getRemoveOriginalColumn() { + return _removeOriginalColumn; + } + + @JsonProperty("mode") + public String getMode() { + return _mode; + } + + @JsonProperty("separator") + @JsonInclude(Include.NON_NULL) + public String getSeparator() { + return _separator; + } + + @JsonProperty("regex") + @JsonInclude(Include.NON_NULL) + public Boolean getRegex() { + return _regex; + } + + @JsonProperty("maxColumns") + @JsonInclude(Include.NON_NULL) + public Integer getMaxColumns() { + return _maxColumns; + } + + @JsonProperty("fieldLengths") + @JsonInclude(Include.NON_NULL) + public int[] getFieldLengths() { + return _fieldLengths; + } @Override protected String getBriefDescription(Project project) { diff --git a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionByFetchingURLsOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionByFetchingURLsOperationTests.java index cbef00f53..7d29fd608 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionByFetchingURLsOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionByFetchingURLsOperationTests.java @@ -35,9 +35,10 @@ package com.google.refine.tests.operations.column; import java.io.IOException; import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; import java.util.Properties; -import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.slf4j.LoggerFactory; @@ -56,6 +57,7 @@ import com.google.refine.operations.EngineDependentOperation; import com.google.refine.operations.OnError; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.column.ColumnAdditionByFetchingURLsOperation; +import com.google.refine.operations.column.ColumnAdditionByFetchingURLsOperation.HttpHeader; import com.google.refine.process.Process; import com.google.refine.process.ProcessManager; import com.google.refine.tests.RefineTest; @@ -233,11 +235,10 @@ public class ColumnAdditionByFetchingURLsOperationTests extends RefineTest { String userAgentValue = "OpenRefine"; String authorizationValue = "Basic"; String acceptValue = "*/*"; - String jsonString = "[{\"name\": \"authorization\",\"value\": \""+authorizationValue+ - "\"},{\"name\": \"user-agent\",\"value\": \""+userAgentValue+ - "\"},{\"name\": \"accept\",\"value\": \""+acceptValue+"\"}]"; - - JSONArray httpHeadersJson = new JSONArray(jsonString); + List headers = new ArrayList<>(); + headers.add(new HttpHeader("authorization", authorizationValue)); + headers.add(new HttpHeader("user-agent", userAgentValue)); + headers.add(new HttpHeader("accept", acceptValue)); EngineDependentOperation op = new ColumnAdditionByFetchingURLsOperation(engine_config, "fruits", @@ -247,7 +248,7 @@ public class ColumnAdditionByFetchingURLsOperationTests extends RefineTest { 1, 50, true, - httpHeadersJson); + headers); ProcessManager pm = project.getProcessManager(); Process process = op.createProcess(project, options); process.startPerforming(pm); diff --git a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnSplitOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnSplitOperationTests.java index 1aa3a997c..57949edd9 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnSplitOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnSplitOperationTests.java @@ -20,7 +20,7 @@ public class ColumnSplitOperationTests extends RefineTest { } @Test - public void serializeColumnSplitOperation() throws JSONException, Exception { + public void serializeColumnSplitOperationBySeparator() throws JSONException, Exception { String json = "{\n" + " \"op\": \"core/column-split\",\n" + " \"description\": \"Split column ea by separator\",\n" + @@ -39,4 +39,23 @@ public class ColumnSplitOperationTests extends RefineTest { Project project = mock(Project.class); TestUtils.isSerializedTo(ColumnSplitOperation.reconstruct(project, new JSONObject(json)), json); } + + @Test + public void serializeColumnSplitOperationByLengths() throws JSONException, Exception { + String json = "{\n" + + " \"op\": \"core/column-split\",\n" + + " \"description\": \"Split column ea by field lengths\",\n" + + " \"engineConfig\": {\n" + + " \"mode\": \"row-based\",\n" + + " \"facets\": []\n" + + " },\n" + + " \"columnName\": \"ea\",\n" + + " \"guessCellType\": true,\n" + + " \"removeOriginalColumn\": true,\n" + + " \"mode\": \"lengths\",\n" + + " \"fieldLengths\": [1,1]\n" + + " }"; + Project project = mock(Project.class); + TestUtils.isSerializedTo(ColumnSplitOperation.reconstruct(project, new JSONObject(json)), json); + } } From 6daa1b4f5c979d8c7bec629d3761cfe045f7f99d Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Tue, 25 Sep 2018 12:28:39 +0100 Subject: [PATCH 006/164] Jackson serialization for RowReorderOperation --- .../refine/commands/row/GetRowsCommand.java | 16 +-- .../commands/row/ReorderRowsCommand.java | 6 +- .../refine/exporters/TemplatingExporter.java | 7 +- .../operations/row/RowFlagOperation.java | 7 ++ .../operations/row/RowReorderOperation.java | 30 ++++-- .../operations/row/RowStarOperation.java | 7 ++ .../com/google/refine/sorting/BaseSorter.java | 102 +++++++++++------- .../refine/sorting/BooleanCriterion.java | 10 ++ .../com/google/refine/sorting/Criterion.java | 87 +++++++++++++-- .../google/refine/sorting/DateCriterion.java | 9 ++ .../refine/sorting/NumberCriterion.java | 5 + .../refine/sorting/StringCriterion.java | 23 ++-- .../row/RowReorderOperationTests.java | 7 +- 13 files changed, 236 insertions(+), 80 deletions(-) diff --git a/main/src/com/google/refine/commands/row/GetRowsCommand.java b/main/src/com/google/refine/commands/row/GetRowsCommand.java index ca5cdf192..95e0fe266 100644 --- a/main/src/com/google/refine/commands/row/GetRowsCommand.java +++ b/main/src/com/google/refine/commands/row/GetRowsCommand.java @@ -57,6 +57,7 @@ import com.google.refine.importing.ImportingManager; import com.google.refine.model.Project; import com.google.refine.model.Record; import com.google.refine.model.Row; +import com.google.refine.sorting.BaseSorter.SortingConfig; import com.google.refine.sorting.SortingRecordVisitor; import com.google.refine.sorting.SortingRowVisitor; import com.google.refine.util.ParsingUtilities; @@ -120,11 +121,14 @@ public class GetRowsCommand extends Command { RowWritingVisitor rwv = new RowWritingVisitor(start, limit, jsonWriter, options); - JSONObject sortingJson = null; + SortingConfig sortingConfig = null; try{ String json = request.getParameter("sorting"); - sortingJson = (json == null) ? null : + JSONObject sortingJson = (json == null) ? null : ParsingUtilities.evaluateJsonStringToObject(json); + if (sortingJson != null) { + sortingConfig = SortingConfig.reconstruct(project, sortingJson); + } } catch (JSONException e) { } @@ -132,10 +136,10 @@ public class GetRowsCommand extends Command { FilteredRows filteredRows = engine.getAllFilteredRows(); RowVisitor visitor = rwv; - if (sortingJson != null) { + if (sortingConfig != null) { SortingRowVisitor srv = new SortingRowVisitor(visitor); - srv.initializeFromJSON(project, sortingJson); + srv.initializeFromConfig(project, sortingConfig); if (srv.hasCriteria()) { visitor = srv; } @@ -151,10 +155,10 @@ public class GetRowsCommand extends Command { FilteredRecords filteredRecords = engine.getFilteredRecords(); RecordVisitor visitor = rwv; - if (sortingJson != null) { + if (sortingConfig != null) { SortingRecordVisitor srv = new SortingRecordVisitor(visitor); - srv.initializeFromJSON(project, sortingJson); + srv.initializeFromConfig(project, sortingConfig); if (srv.hasCriteria()) { visitor = srv; } diff --git a/main/src/com/google/refine/commands/row/ReorderRowsCommand.java b/main/src/com/google/refine/commands/row/ReorderRowsCommand.java index 49ed991c5..c9825c56e 100644 --- a/main/src/com/google/refine/commands/row/ReorderRowsCommand.java +++ b/main/src/com/google/refine/commands/row/ReorderRowsCommand.java @@ -44,6 +44,7 @@ import com.google.refine.commands.EngineDependentCommand; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.operations.row.RowReorderOperation; +import com.google.refine.sorting.BaseSorter.SortingConfig; import com.google.refine.util.ParsingUtilities; public class ReorderRowsCommand extends EngineDependentCommand { @@ -53,12 +54,13 @@ public class ReorderRowsCommand extends EngineDependentCommand { HttpServletRequest request, EngineConfig engineConfig) throws Exception { String mode = request.getParameter("mode"); - JSONObject sorting = null; + SortingConfig sorting = null; try{ String json = request.getParameter("sorting"); - sorting = (json == null) ? null : ParsingUtilities.evaluateJsonStringToObject(json); + JSONObject sortingJson = (json == null) ? null : ParsingUtilities.evaluateJsonStringToObject(json); + sorting = (sortingJson == null) ? null : SortingConfig.reconstruct(project, sortingJson); } catch (JSONException e) { // ignore } diff --git a/main/src/com/google/refine/exporters/TemplatingExporter.java b/main/src/com/google/refine/exporters/TemplatingExporter.java index 4691ccf7a..43f8d4809 100644 --- a/main/src/com/google/refine/exporters/TemplatingExporter.java +++ b/main/src/com/google/refine/exporters/TemplatingExporter.java @@ -52,6 +52,7 @@ import com.google.refine.expr.ParsingException; import com.google.refine.model.Project; import com.google.refine.sorting.SortingRecordVisitor; import com.google.refine.sorting.SortingRowVisitor; +import com.google.refine.sorting.BaseSorter.SortingConfig; import com.google.refine.templating.Parser; import com.google.refine.templating.Template; import com.google.refine.util.ParsingUtilities; @@ -115,8 +116,9 @@ public class TemplatingExporter implements WriterExporter { if (sortingJson != null) { try { + SortingConfig sorting = SortingConfig.reconstruct(project, sortingJson); SortingRowVisitor srv = new SortingRowVisitor(visitor); - srv.initializeFromJSON(project, sortingJson); + srv.initializeFromConfig(project, sorting); if (srv.hasCriteria()) { visitor = srv; @@ -133,8 +135,9 @@ public class TemplatingExporter implements WriterExporter { if (sortingJson != null) { try { + SortingConfig sorting = SortingConfig.reconstruct(project, sortingJson); SortingRecordVisitor srv = new SortingRecordVisitor(visitor); - srv.initializeFromJSON(project, sortingJson); + srv.initializeFromConfig(project, sorting); if (srv.hasCriteria()) { visitor = srv; diff --git a/main/src/com/google/refine/operations/row/RowFlagOperation.java b/main/src/com/google/refine/operations/row/RowFlagOperation.java index 5dc07a7a2..fe8a1dbfc 100644 --- a/main/src/com/google/refine/operations/row/RowFlagOperation.java +++ b/main/src/com/google/refine/operations/row/RowFlagOperation.java @@ -41,6 +41,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; @@ -84,6 +86,11 @@ public class RowFlagOperation extends EngineDependentOperation { writer.key("flagged"); writer.value(_flagged); writer.endObject(); } + + @JsonProperty("flagged") + public boolean getFlagged() { + return _flagged; + } @Override protected String getBriefDescription(Project project) { diff --git a/main/src/com/google/refine/operations/row/RowReorderOperation.java b/main/src/com/google/refine/operations/row/RowReorderOperation.java index 6df761943..ace36d498 100644 --- a/main/src/com/google/refine/operations/row/RowReorderOperation.java +++ b/main/src/com/google/refine/operations/row/RowReorderOperation.java @@ -41,6 +41,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.RecordVisitor; @@ -52,6 +54,8 @@ import com.google.refine.model.Record; import com.google.refine.model.Row; import com.google.refine.model.changes.RowReorderChange; import com.google.refine.operations.OperationRegistry; +import com.google.refine.sorting.BaseSorter; +import com.google.refine.sorting.BaseSorter.SortingConfig; import com.google.refine.sorting.SortingRecordVisitor; import com.google.refine.sorting.SortingRowVisitor; @@ -60,14 +64,14 @@ public class RowReorderOperation extends AbstractOperation { String mode = obj.getString("mode"); JSONObject sorting = obj.has("sorting") && !obj.isNull("sorting") ? obj.getJSONObject("sorting") : null; - - return new RowReorderOperation(Engine.stringToMode(mode), sorting); + BaseSorter.SortingConfig config = BaseSorter.SortingConfig.reconstruct(project, sorting); + return new RowReorderOperation(Engine.stringToMode(mode), config); } - + final protected Mode _mode; - final protected JSONObject _sorting; + final protected BaseSorter.SortingConfig _sorting; - public RowReorderOperation(Mode mode, JSONObject sorting) { + public RowReorderOperation(Mode mode, BaseSorter.SortingConfig sorting) { _mode = mode; _sorting = sorting; } @@ -80,9 +84,19 @@ public class RowReorderOperation extends AbstractOperation { writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); writer.key("description"); writer.value(getBriefDescription(null)); writer.key("mode"); writer.value(Engine.modeToString(_mode)); - writer.key("sorting"); writer.value(_sorting); + writer.key("sorting"); _sorting.write(writer, options); writer.endObject(); } + + @JsonProperty("mode") + public Mode getMode() { + return _mode; + } + + @JsonProperty("sorting") + public SortingConfig getSortingConfig() { + return _sorting; + } @Override protected String getBriefDescription(Project project) { @@ -100,7 +114,7 @@ public class RowReorderOperation extends AbstractOperation { if (_sorting != null) { SortingRowVisitor srv = new SortingRowVisitor(visitor); - srv.initializeFromJSON(project, _sorting); + srv.initializeFromConfig(project, _sorting); if (srv.hasCriteria()) { visitor = srv; } @@ -112,7 +126,7 @@ public class RowReorderOperation extends AbstractOperation { if (_sorting != null) { SortingRecordVisitor srv = new SortingRecordVisitor(visitor); - srv.initializeFromJSON(project, _sorting); + srv.initializeFromConfig(project, _sorting); if (srv.hasCriteria()) { visitor = srv; } diff --git a/main/src/com/google/refine/operations/row/RowStarOperation.java b/main/src/com/google/refine/operations/row/RowStarOperation.java index db337d06f..5508449b1 100644 --- a/main/src/com/google/refine/operations/row/RowStarOperation.java +++ b/main/src/com/google/refine/operations/row/RowStarOperation.java @@ -41,6 +41,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; @@ -84,6 +86,11 @@ public class RowStarOperation extends EngineDependentOperation { writer.key("starred"); writer.value(_starred); writer.endObject(); } + + @JsonProperty("starred") + public boolean getStarred() { + return _starred; + } @Override protected String getBriefDescription(Project project) { diff --git a/main/src/com/google/refine/sorting/BaseSorter.java b/main/src/com/google/refine/sorting/BaseSorter.java index 5ace4db75..6b807f261 100644 --- a/main/src/com/google/refine/sorting/BaseSorter.java +++ b/main/src/com/google/refine/sorting/BaseSorter.java @@ -34,11 +34,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.sorting; import java.util.List; +import java.util.Properties; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import com.google.refine.Jsonizable; import com.google.refine.expr.EvalError; import com.google.refine.model.Project; import com.google.refine.sorting.Criterion.KeyMaker; @@ -104,26 +110,63 @@ abstract public class BaseSorter { } } - public void initializeFromJSON(Project project, JSONObject obj) throws JSONException { - if (obj.has("criteria") && !obj.isNull("criteria")) { - JSONArray a = obj.getJSONArray("criteria"); - int count = a.length(); - - _criteria = new Criterion[count]; - _keyMakers = new KeyMaker[count]; - _comparatorWrappers = new ComparatorWrapper[count]; - - for (int i = 0; i < count; i++) { - JSONObject obj2 = a.getJSONObject(i); - - _criteria[i] = createCriterionFromJSON(project, obj2); - _keyMakers[i] = _criteria[i].createKeyMaker(); - _comparatorWrappers[i] = new ComparatorWrapper(i); + public final static class SortingConfig implements Jsonizable { + + protected Criterion[] _criteria; + + @JsonCreator + public SortingConfig( + @JsonProperty("criteria") + Criterion[] criteria) { + _criteria = criteria; + } + + @JsonProperty("criteria") + public Criterion[] getCriteria() { + return _criteria; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("criteria"); + for (int i = 0; i != _criteria.length; i++) { + _criteria[i].write(writer, options); } - } else { - _criteria = new Criterion[0]; - _keyMakers = new KeyMaker[0]; - _comparatorWrappers = new ComparatorWrapper[0]; + writer.endObject(); + } + + public static SortingConfig reconstruct(Project project, JSONObject obj) { + Criterion[] criteria; + if (obj != null && obj.has("criteria") && !obj.isNull("criteria")) { + JSONArray a = obj.getJSONArray("criteria"); + int count = a.length(); + + criteria = new Criterion[count]; + + + for (int i = 0; i < count; i++) { + JSONObject obj2 = a.getJSONObject(i); + + criteria[i] = Criterion.reconstruct(obj2); + } + } else { + criteria = new Criterion[0]; + } + return new SortingConfig(criteria); + } + } + + public void initializeFromConfig(Project project, BaseSorter.SortingConfig config) throws JSONException { + _criteria = config.getCriteria(); + int count = _criteria.length; + _keyMakers = new KeyMaker[count]; + _comparatorWrappers = new ComparatorWrapper[count]; + + for (int i = 0; i < count; i++) { + _keyMakers[i] = _criteria[i].createKeyMaker(); + _comparatorWrappers[i] = new ComparatorWrapper(i); } } @@ -131,27 +174,6 @@ abstract public class BaseSorter { return _criteria != null && _criteria.length > 0; } - protected Criterion createCriterionFromJSON(Project project, JSONObject obj) throws JSONException { - String valueType = "string"; - if (obj.has("valueType") && !obj.isNull("valueType")) { - valueType = obj.getString("valueType"); - } - - Criterion c = null; - if ("boolean".equals(valueType)) { - c = new BooleanCriterion(); - } else if ("date".equals(valueType)) { - c = new DateCriterion(); - } else if ("number".equals(valueType)) { - c = new NumberCriterion(); - } else { - c = new StringCriterion(); - } - - c.initializeFromJSON(project, obj); - return c; - } - abstract protected Object makeKey( Project project, KeyMaker keyMaker, Criterion c, Object o, int index); diff --git a/main/src/com/google/refine/sorting/BooleanCriterion.java b/main/src/com/google/refine/sorting/BooleanCriterion.java index 1f56c98de..07746e038 100644 --- a/main/src/com/google/refine/sorting/BooleanCriterion.java +++ b/main/src/com/google/refine/sorting/BooleanCriterion.java @@ -33,6 +33,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.sorting; +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONWriter; + import com.google.refine.expr.EvalError; import com.google.refine.expr.ExpressionUtils; @@ -62,4 +67,9 @@ public class BooleanCriterion extends Criterion { } }; } + + @Override + public String getValueType() { + return "boolean"; + } } diff --git a/main/src/com/google/refine/sorting/Criterion.java b/main/src/com/google/refine/sorting/Criterion.java index a41374fb0..e19b69dd6 100644 --- a/main/src/com/google/refine/sorting/Criterion.java +++ b/main/src/com/google/refine/sorting/Criterion.java @@ -33,18 +33,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.sorting; +import java.util.Properties; + import org.json.JSONException; import org.json.JSONObject; +import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import com.google.refine.Jsonizable; import com.google.refine.expr.ExpressionUtils; import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Record; import com.google.refine.model.Row; -abstract public class Criterion { +abstract public class Criterion implements Jsonizable { public String columnName; - protected int cellIndex; + protected int cellIndex = -2; // These take on positive and negative values to indicate where blanks and errors // go relative to non-blank values. They are also relative to each another. @@ -54,13 +60,10 @@ abstract public class Criterion { public boolean reverse; - public void initializeFromJSON(Project project, JSONObject obj) + public void initializeFromJSON(JSONObject obj) throws JSONException { if (obj.has("column") && !obj.isNull("column")) { columnName = obj.getString("column"); - - Column column = project.columnModel.getColumnByName(columnName); - cellIndex = column != null ? column.getCellIndex() : -1; } if (obj.has("blankPosition") && !obj.isNull("blankPosition")) { @@ -74,7 +77,75 @@ abstract public class Criterion { reverse = obj.getBoolean("reverse"); } } + + public static Criterion reconstruct(JSONObject obj) throws JSONException { + String valueType = "string"; + if (obj.has("valueType") && !obj.isNull("valueType")) { + valueType = obj.getString("valueType"); + } + Criterion c = null; + if ("boolean".equals(valueType)) { + c = new BooleanCriterion(); + } else if ("date".equals(valueType)) { + c = new DateCriterion(); + } else if ("number".equals(valueType)) { + c = new NumberCriterion(); + } else { + c = new StringCriterion(obj.getBoolean("caseSensitive")); + } + + c.initializeFromJSON(obj); + return c; + } + + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("valueType"); writer.value(getValueType()); + writer.key("reverse"); writer.value(getReverse()); + writer.key("column"); writer.value(getColumnName()); + writer.key("blankPosition"); writer.value(getBlankPosition()); + writer.key("errorPosition"); writer.value(getErrorPosition()); + writer.endObject(); + } + + @JsonProperty("valueType") + public abstract String getValueType(); + + @JsonProperty("reverse") + public boolean getReverse() { + return reverse; + } + + @JsonProperty("column") + public String getColumnName() { + return columnName; + } + + @JsonProperty("blankPosition") + public int getBlankPosition() { + return blankPosition; + } + + @JsonProperty("errorPosition") + public int getErrorPosition() { + return errorPosition; + } + + // Returns a cached cell index + // We delay this fetching because the column might not exist + // at deserialization (for instance if the column is created by an operation + // that has not been applied yet). + protected int getCellIndex(Project project) { + if (cellIndex == -2) { + Column column = project.columnModel.getColumnByName(columnName); + cellIndex = column != null ? column.getCellIndex() : -1; + } + return cellIndex; + } // TODO: We'd like things to be more strongly typed a la the following, but // it's too involved to change right now @@ -119,10 +190,10 @@ abstract public class Criterion { } public Object makeKey(Project project, Row row, int rowIndex) { - if (cellIndex < 0) { + if (getCellIndex(project) < 0) { return null; } else { - Object value = row.getCellValue(cellIndex); + Object value = row.getCellValue(getCellIndex(project)); return makeKey(value); } } diff --git a/main/src/com/google/refine/sorting/DateCriterion.java b/main/src/com/google/refine/sorting/DateCriterion.java index a3add8187..161abb2f0 100644 --- a/main/src/com/google/refine/sorting/DateCriterion.java +++ b/main/src/com/google/refine/sorting/DateCriterion.java @@ -35,6 +35,10 @@ package com.google.refine.sorting; import java.time.Instant; import java.time.OffsetDateTime; +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.expr.ExpressionUtils; @@ -63,4 +67,9 @@ public class DateCriterion extends Criterion { } }; } + + @Override + public String getValueType() { + return "date"; + } } diff --git a/main/src/com/google/refine/sorting/NumberCriterion.java b/main/src/com/google/refine/sorting/NumberCriterion.java index 287618c35..ad92f4093 100644 --- a/main/src/com/google/refine/sorting/NumberCriterion.java +++ b/main/src/com/google/refine/sorting/NumberCriterion.java @@ -77,4 +77,9 @@ public class NumberCriterion extends Criterion { } }; } + + @Override + public String getValueType() { + return "number"; + } } diff --git a/main/src/com/google/refine/sorting/StringCriterion.java b/main/src/com/google/refine/sorting/StringCriterion.java index 4807c2507..e3d937fc2 100644 --- a/main/src/com/google/refine/sorting/StringCriterion.java +++ b/main/src/com/google/refine/sorting/StringCriterion.java @@ -36,11 +36,9 @@ package com.google.refine.sorting; import java.text.CollationKey; import java.text.Collator; -import org.json.JSONException; -import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.expr.ExpressionUtils; -import com.google.refine.model.Project; public class StringCriterion extends Criterion { public boolean caseSensitive; @@ -49,21 +47,17 @@ public class StringCriterion extends Criterion { /** * */ - public StringCriterion() { + public StringCriterion(boolean caseSensitive) { super(); collator = Collator.getInstance(); collator.setDecomposition(Collator.FULL_DECOMPOSITION); collator.setStrength(Collator.SECONDARY); + this.caseSensitive = caseSensitive; } - @Override - public void initializeFromJSON(Project project, JSONObject obj) throws JSONException { - super.initializeFromJSON(project, obj); - - if (obj.has("caseSensitive") && !obj.isNull("caseSensitive")) { - caseSensitive = obj.getBoolean("caseSensitive"); - collator.setStrength(Collator.IDENTICAL); - } + @JsonProperty("caseSensitive") + public boolean isCaseSensitive() { + return caseSensitive; } @Override @@ -81,4 +75,9 @@ public class StringCriterion extends Criterion { } }; } + + @Override + public String getValueType() { + return "string"; + } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/row/RowReorderOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/row/RowReorderOperationTests.java index 0bc492d24..bdcfb80a1 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/row/RowReorderOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/row/RowReorderOperationTests.java @@ -20,6 +20,7 @@ import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.row.RowReorderOperation; import com.google.refine.process.Process; +import com.google.refine.sorting.BaseSorter.SortingConfig; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; @@ -49,10 +50,12 @@ public class RowReorderOperationTests extends RefineTest { @Test public void testSortEmptyString() throws Exception { + String sortingJson = "{\"criteria\":[{\"column\":\"key\",\"valueType\":\"number\",\"reverse\":false,\"blankPosition\":2,\"errorPosition\":1}]}"; + SortingConfig sortingConfig = SortingConfig.reconstruct(project, new JSONObject(sortingJson)); project.rows.get(1).cells.set(0, new Cell("", null)); AbstractOperation op = new RowReorderOperation( - Mode.RowBased, - new JSONObject("{\"criteria\":[{\"column\":\"key\",\"valueType\":\"number\",\"reverse\":false,\"blankPosition\":2,\"errorPosition\":1}]}")); + Mode.RowBased, sortingConfig + ); Process process = op.createProcess(project, new Properties()); process.performImmediate(); From 1f403930282eb7573061665c96025d6e8f55edf0 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Tue, 25 Sep 2018 18:21:08 +0100 Subject: [PATCH 007/164] Move SortingConfig to its own file; tests for sorting criteria --- .../refine/commands/row/GetRowsCommand.java | 4 +- .../commands/row/ReorderRowsCommand.java | 4 +- .../refine/exporters/TemplatingExporter.java | 6 +- .../operations/row/RowReorderOperation.java | 9 ++- .../com/google/refine/sorting/BaseSorter.java | 58 +--------------- .../refine/sorting/BooleanCriterion.java | 5 -- .../google/refine/sorting/SortingConfig.java | 67 +++++++++++++++++++ .../row/RowReorderOperationTests.java | 4 +- .../tests/sorting/BooleanCriterionTest.java | 22 ++++++ .../tests/sorting/DateCriterionTest.java | 22 ++++++ .../tests/sorting/NumberCriterionTest.java | 22 ++++++ .../tests/sorting/SortingConfigTests.java | 25 +++++++ 12 files changed, 172 insertions(+), 76 deletions(-) create mode 100644 main/src/com/google/refine/sorting/SortingConfig.java create mode 100644 main/tests/server/src/com/google/refine/tests/sorting/BooleanCriterionTest.java create mode 100644 main/tests/server/src/com/google/refine/tests/sorting/DateCriterionTest.java create mode 100644 main/tests/server/src/com/google/refine/tests/sorting/NumberCriterionTest.java create mode 100644 main/tests/server/src/com/google/refine/tests/sorting/SortingConfigTests.java diff --git a/main/src/com/google/refine/commands/row/GetRowsCommand.java b/main/src/com/google/refine/commands/row/GetRowsCommand.java index 95e0fe266..add2f4314 100644 --- a/main/src/com/google/refine/commands/row/GetRowsCommand.java +++ b/main/src/com/google/refine/commands/row/GetRowsCommand.java @@ -57,7 +57,7 @@ import com.google.refine.importing.ImportingManager; import com.google.refine.model.Project; import com.google.refine.model.Record; import com.google.refine.model.Row; -import com.google.refine.sorting.BaseSorter.SortingConfig; +import com.google.refine.sorting.SortingConfig; import com.google.refine.sorting.SortingRecordVisitor; import com.google.refine.sorting.SortingRowVisitor; import com.google.refine.util.ParsingUtilities; @@ -127,7 +127,7 @@ public class GetRowsCommand extends Command { JSONObject sortingJson = (json == null) ? null : ParsingUtilities.evaluateJsonStringToObject(json); if (sortingJson != null) { - sortingConfig = SortingConfig.reconstruct(project, sortingJson); + sortingConfig = SortingConfig.reconstruct(sortingJson); } } catch (JSONException e) { } diff --git a/main/src/com/google/refine/commands/row/ReorderRowsCommand.java b/main/src/com/google/refine/commands/row/ReorderRowsCommand.java index c9825c56e..244b40c3f 100644 --- a/main/src/com/google/refine/commands/row/ReorderRowsCommand.java +++ b/main/src/com/google/refine/commands/row/ReorderRowsCommand.java @@ -44,7 +44,7 @@ import com.google.refine.commands.EngineDependentCommand; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.operations.row.RowReorderOperation; -import com.google.refine.sorting.BaseSorter.SortingConfig; +import com.google.refine.sorting.SortingConfig; import com.google.refine.util.ParsingUtilities; public class ReorderRowsCommand extends EngineDependentCommand { @@ -60,7 +60,7 @@ public class ReorderRowsCommand extends EngineDependentCommand { String json = request.getParameter("sorting"); JSONObject sortingJson = (json == null) ? null : ParsingUtilities.evaluateJsonStringToObject(json); - sorting = (sortingJson == null) ? null : SortingConfig.reconstruct(project, sortingJson); + sorting = (sortingJson == null) ? null : SortingConfig.reconstruct(sortingJson); } catch (JSONException e) { // ignore } diff --git a/main/src/com/google/refine/exporters/TemplatingExporter.java b/main/src/com/google/refine/exporters/TemplatingExporter.java index 43f8d4809..996ce4591 100644 --- a/main/src/com/google/refine/exporters/TemplatingExporter.java +++ b/main/src/com/google/refine/exporters/TemplatingExporter.java @@ -50,9 +50,9 @@ import com.google.refine.browsing.RecordVisitor; import com.google.refine.browsing.RowVisitor; import com.google.refine.expr.ParsingException; import com.google.refine.model.Project; +import com.google.refine.sorting.SortingConfig; import com.google.refine.sorting.SortingRecordVisitor; import com.google.refine.sorting.SortingRowVisitor; -import com.google.refine.sorting.BaseSorter.SortingConfig; import com.google.refine.templating.Parser; import com.google.refine.templating.Template; import com.google.refine.util.ParsingUtilities; @@ -116,7 +116,7 @@ public class TemplatingExporter implements WriterExporter { if (sortingJson != null) { try { - SortingConfig sorting = SortingConfig.reconstruct(project, sortingJson); + SortingConfig sorting = SortingConfig.reconstruct(sortingJson); SortingRowVisitor srv = new SortingRowVisitor(visitor); srv.initializeFromConfig(project, sorting); @@ -135,7 +135,7 @@ public class TemplatingExporter implements WriterExporter { if (sortingJson != null) { try { - SortingConfig sorting = SortingConfig.reconstruct(project, sortingJson); + SortingConfig sorting = SortingConfig.reconstruct(sortingJson); SortingRecordVisitor srv = new SortingRecordVisitor(visitor); srv.initializeFromConfig(project, sorting); diff --git a/main/src/com/google/refine/operations/row/RowReorderOperation.java b/main/src/com/google/refine/operations/row/RowReorderOperation.java index ace36d498..ee63cd799 100644 --- a/main/src/com/google/refine/operations/row/RowReorderOperation.java +++ b/main/src/com/google/refine/operations/row/RowReorderOperation.java @@ -54,8 +54,7 @@ import com.google.refine.model.Record; import com.google.refine.model.Row; import com.google.refine.model.changes.RowReorderChange; import com.google.refine.operations.OperationRegistry; -import com.google.refine.sorting.BaseSorter; -import com.google.refine.sorting.BaseSorter.SortingConfig; +import com.google.refine.sorting.SortingConfig; import com.google.refine.sorting.SortingRecordVisitor; import com.google.refine.sorting.SortingRowVisitor; @@ -64,14 +63,14 @@ public class RowReorderOperation extends AbstractOperation { String mode = obj.getString("mode"); JSONObject sorting = obj.has("sorting") && !obj.isNull("sorting") ? obj.getJSONObject("sorting") : null; - BaseSorter.SortingConfig config = BaseSorter.SortingConfig.reconstruct(project, sorting); + SortingConfig config = SortingConfig.reconstruct(sorting); return new RowReorderOperation(Engine.stringToMode(mode), config); } final protected Mode _mode; - final protected BaseSorter.SortingConfig _sorting; + final protected SortingConfig _sorting; - public RowReorderOperation(Mode mode, BaseSorter.SortingConfig sorting) { + public RowReorderOperation(Mode mode, SortingConfig sorting) { _mode = mode; _sorting = sorting; } diff --git a/main/src/com/google/refine/sorting/BaseSorter.java b/main/src/com/google/refine/sorting/BaseSorter.java index 6b807f261..1f5346d9d 100644 --- a/main/src/com/google/refine/sorting/BaseSorter.java +++ b/main/src/com/google/refine/sorting/BaseSorter.java @@ -34,17 +34,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.sorting; import java.util.List; -import java.util.Properties; -import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONWriter; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -import com.google.refine.Jsonizable; import com.google.refine.expr.EvalError; import com.google.refine.model.Project; import com.google.refine.sorting.Criterion.KeyMaker; @@ -110,55 +102,7 @@ abstract public class BaseSorter { } } - public final static class SortingConfig implements Jsonizable { - - protected Criterion[] _criteria; - - @JsonCreator - public SortingConfig( - @JsonProperty("criteria") - Criterion[] criteria) { - _criteria = criteria; - } - - @JsonProperty("criteria") - public Criterion[] getCriteria() { - return _criteria; - } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("criteria"); - for (int i = 0; i != _criteria.length; i++) { - _criteria[i].write(writer, options); - } - writer.endObject(); - } - - public static SortingConfig reconstruct(Project project, JSONObject obj) { - Criterion[] criteria; - if (obj != null && obj.has("criteria") && !obj.isNull("criteria")) { - JSONArray a = obj.getJSONArray("criteria"); - int count = a.length(); - - criteria = new Criterion[count]; - - - for (int i = 0; i < count; i++) { - JSONObject obj2 = a.getJSONObject(i); - - criteria[i] = Criterion.reconstruct(obj2); - } - } else { - criteria = new Criterion[0]; - } - return new SortingConfig(criteria); - } - } - - public void initializeFromConfig(Project project, BaseSorter.SortingConfig config) throws JSONException { + public void initializeFromConfig(Project project, SortingConfig config) throws JSONException { _criteria = config.getCriteria(); int count = _criteria.length; _keyMakers = new KeyMaker[count]; diff --git a/main/src/com/google/refine/sorting/BooleanCriterion.java b/main/src/com/google/refine/sorting/BooleanCriterion.java index 07746e038..d3ee789a1 100644 --- a/main/src/com/google/refine/sorting/BooleanCriterion.java +++ b/main/src/com/google/refine/sorting/BooleanCriterion.java @@ -33,11 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.sorting; -import java.util.Properties; - -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.expr.ExpressionUtils; diff --git a/main/src/com/google/refine/sorting/SortingConfig.java b/main/src/com/google/refine/sorting/SortingConfig.java new file mode 100644 index 000000000..cc96ee85e --- /dev/null +++ b/main/src/com/google/refine/sorting/SortingConfig.java @@ -0,0 +1,67 @@ +package com.google.refine.sorting; + +import java.util.Properties; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONWriter; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import com.google.refine.Jsonizable; + +/** + * Stores the configuration of a row/record sorting setup. + * @author Antonin Delpeuch + * + */ +public final class SortingConfig implements Jsonizable { + + protected Criterion[] _criteria; + + @JsonCreator + public SortingConfig( + @JsonProperty("criteria") + Criterion[] criteria) { + _criteria = criteria; + } + + @JsonProperty("criteria") + public Criterion[] getCriteria() { + return _criteria; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("criteria"); + writer.array(); + for (int i = 0; i != _criteria.length; i++) { + _criteria[i].write(writer, options); + } + writer.endArray(); + writer.endObject(); + } + + public static SortingConfig reconstruct(JSONObject obj) { + Criterion[] criteria; + if (obj != null && obj.has("criteria") && !obj.isNull("criteria")) { + JSONArray a = obj.getJSONArray("criteria"); + int count = a.length(); + + criteria = new Criterion[count]; + + for (int i = 0; i < count; i++) { + JSONObject obj2 = a.getJSONObject(i); + + criteria[i] = Criterion.reconstruct(obj2); + } + } else { + criteria = new Criterion[0]; + } + return new SortingConfig(criteria); + } +} \ No newline at end of file diff --git a/main/tests/server/src/com/google/refine/tests/operations/row/RowReorderOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/row/RowReorderOperationTests.java index bdcfb80a1..08b91927b 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/row/RowReorderOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/row/RowReorderOperationTests.java @@ -20,7 +20,7 @@ import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.row.RowReorderOperation; import com.google.refine.process.Process; -import com.google.refine.sorting.BaseSorter.SortingConfig; +import com.google.refine.sorting.SortingConfig; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; @@ -51,7 +51,7 @@ public class RowReorderOperationTests extends RefineTest { @Test public void testSortEmptyString() throws Exception { String sortingJson = "{\"criteria\":[{\"column\":\"key\",\"valueType\":\"number\",\"reverse\":false,\"blankPosition\":2,\"errorPosition\":1}]}"; - SortingConfig sortingConfig = SortingConfig.reconstruct(project, new JSONObject(sortingJson)); + SortingConfig sortingConfig = SortingConfig.reconstruct(new JSONObject(sortingJson)); project.rows.get(1).cells.set(0, new Cell("", null)); AbstractOperation op = new RowReorderOperation( Mode.RowBased, sortingConfig diff --git a/main/tests/server/src/com/google/refine/tests/sorting/BooleanCriterionTest.java b/main/tests/server/src/com/google/refine/tests/sorting/BooleanCriterionTest.java new file mode 100644 index 000000000..3a16d0486 --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/sorting/BooleanCriterionTest.java @@ -0,0 +1,22 @@ +package com.google.refine.tests.sorting; + +import org.json.JSONObject; +import org.testng.annotations.Test; + +import com.google.refine.sorting.Criterion; +import com.google.refine.tests.util.TestUtils; + +public class BooleanCriterionTest { + @Test + public void serializeBooleanCriterion() { + String json = + " {\n" + + " \"errorPosition\": 1,\n" + + " \"valueType\": \"boolean\",\n" + + " \"column\": \"start_year\",\n" + + " \"blankPosition\": 2,\n" + + " \"reverse\": false\n" + + " }\n"; + TestUtils.isSerializedTo(Criterion.reconstruct(new JSONObject(json)), json); + } +} diff --git a/main/tests/server/src/com/google/refine/tests/sorting/DateCriterionTest.java b/main/tests/server/src/com/google/refine/tests/sorting/DateCriterionTest.java new file mode 100644 index 000000000..349384d67 --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/sorting/DateCriterionTest.java @@ -0,0 +1,22 @@ +package com.google.refine.tests.sorting; + +import org.json.JSONObject; +import org.testng.annotations.Test; + +import com.google.refine.sorting.Criterion; +import com.google.refine.tests.util.TestUtils; + +public class DateCriterionTest { + @Test + public void serializeDateCriterion() { + String json = + " {\n" + + " \"errorPosition\": 2,\n" + + " \"valueType\": \"date\",\n" + + " \"column\": \"start_year\",\n" + + " \"blankPosition\": -1,\n" + + " \"reverse\": true\n" + + " }\n"; + TestUtils.isSerializedTo(Criterion.reconstruct(new JSONObject(json)), json); + } +} diff --git a/main/tests/server/src/com/google/refine/tests/sorting/NumberCriterionTest.java b/main/tests/server/src/com/google/refine/tests/sorting/NumberCriterionTest.java new file mode 100644 index 000000000..23aea5080 --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/sorting/NumberCriterionTest.java @@ -0,0 +1,22 @@ +package com.google.refine.tests.sorting; + +import org.json.JSONObject; +import org.testng.annotations.Test; + +import com.google.refine.sorting.Criterion; +import com.google.refine.tests.util.TestUtils; + +public class NumberCriterionTest { + @Test + public void serializeNumberCriterion() { + String json = + " {\n" + + " \"errorPosition\": 2,\n" + + " \"valueType\": \"number\",\n" + + " \"column\": \"start_year\",\n" + + " \"blankPosition\": 1,\n" + + " \"reverse\": true\n" + + " }\n"; + TestUtils.isSerializedTo(Criterion.reconstruct(new JSONObject(json)), json); + } +} diff --git a/main/tests/server/src/com/google/refine/tests/sorting/SortingConfigTests.java b/main/tests/server/src/com/google/refine/tests/sorting/SortingConfigTests.java new file mode 100644 index 000000000..a415eee99 --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/sorting/SortingConfigTests.java @@ -0,0 +1,25 @@ +package com.google.refine.tests.sorting; + +import org.json.JSONObject; +import org.testng.annotations.Test; + +import com.google.refine.sorting.SortingConfig; +import com.google.refine.tests.util.TestUtils; + +public class SortingConfigTests { + @Test + public void serializeSortingConfig() { + String json = "{\n" + + " \"criteria\": [\n" + + " {\n" + + " \"errorPosition\": 1,\n" + + " \"valueType\": \"number\",\n" + + " \"column\": \"start_year\",\n" + + " \"blankPosition\": 2,\n" + + " \"reverse\": false\n" + + " }\n" + + " ]\n" + + " }"; + TestUtils.isSerializedTo(SortingConfig.reconstruct(new JSONObject(json)), json); + } +} From 1fa101c3346b6e2f9f4b13843f6eb93309de8a6a Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Thu, 27 Sep 2018 11:56:42 +0100 Subject: [PATCH 008/164] Jackson serialization for the model classes --- main/src/com/google/refine/model/Cell.java | 98 ++++++++++---- main/src/com/google/refine/model/Column.java | 21 ++- .../com/google/refine/model/ColumnGroup.java | 28 ++++ .../com/google/refine/model/ColumnModel.java | 28 ++++ main/src/com/google/refine/model/Recon.java | 98 +++++++++++++- .../google/refine/model/ReconCandidate.java | 15 +++ .../com/google/refine/model/RecordModel.java | 14 +- main/src/com/google/refine/model/Row.java | 25 ++++ .../refine/model/recon/ReconConfig.java | 9 ++ .../model/recon/StandardReconConfig.java | 48 ++++++- .../src/com/google/refine/util/JsonViews.java | 18 +++ .../google/refine/util/ParsingUtilities.java | 15 +++ .../refine/util/SerializationFilters.java | 55 ++++++++ .../refine/tests/model/ColumnGroupTests.java | 8 +- .../refine/tests/model/ColumnModelTests.java | 45 ++++++- .../tests/model/ReconCandidateTests.java | 12 +- .../google/refine/tests/model/ReconTests.java | 79 +++++++----- .../google/refine/tests/model/RowTests.java | 4 +- .../google/refine/tests/util/TestUtils.java | 120 +++++++++++++++++- 19 files changed, 655 insertions(+), 85 deletions(-) create mode 100644 main/src/com/google/refine/util/JsonViews.java create mode 100644 main/src/com/google/refine/util/SerializationFilters.java diff --git a/main/src/com/google/refine/model/Cell.java b/main/src/com/google/refine/model/Cell.java index 8a0da6054..fcaa86b5e 100644 --- a/main/src/com/google/refine/model/Cell.java +++ b/main/src/com/google/refine/model/Cell.java @@ -44,6 +44,10 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; @@ -57,7 +61,9 @@ import com.google.refine.util.Pool; import com.google.refine.util.StringUtils; public class Cell implements HasFields, Jsonizable { + @JsonIgnore final public Serializable value; + @JsonIgnore final public Recon recon; public Cell(Serializable value, Recon recon) { @@ -88,30 +94,10 @@ public class Cell implements HasFields, Jsonizable { writer.value(((EvalError) value).message); } else { writer.key("v"); - if (value != null) { - Instant instant = null; - if (value instanceof OffsetDateTime) { - instant = ((OffsetDateTime)value).toInstant(); - } else if (value instanceof LocalDateTime) { - instant = ((LocalDateTime)value).toInstant(ZoneOffset.of("Z")); - } - - if (instant != null) { - writer.value(ParsingUtilities.instantToString(instant)); - writer.key("t"); writer.value("date"); - } else if (value instanceof Double - && (((Double)value).isNaN() || ((Double)value).isInfinite())) { - // write as a string - writer.value(((Double)value).toString()); - } else if (value instanceof Float - && (((Float)value).isNaN() || ((Float)value).isInfinite())) { - // TODO: Skip? Write as string? - writer.value(((Float)value).toString()); - } else { - writer.value(value); - } - } else { - writer.value(null); + writer.value(getValueAsString()); + String jsonType = getTypeString(); + if(jsonType != null) { + writer.key("t"); writer.value(jsonType); } } @@ -125,6 +111,70 @@ public class Cell implements HasFields, Jsonizable { writer.endObject(); } + @JsonProperty("e") + @JsonInclude(Include.NON_NULL) + public String getErrorMessage() { + if (ExpressionUtils.isError(value)) { + return ((EvalError) value).message; + } + return null; + } + + @JsonProperty("t") + @JsonInclude(Include.NON_NULL) + public String getTypeString() { + if (value instanceof OffsetDateTime || value instanceof LocalDateTime) { + return "date"; + } + return null; + } + + @JsonProperty("v") + @JsonInclude(Include.NON_NULL) + public String getValueAsString() { + if (value != null && !ExpressionUtils.isError(value)) { + Instant instant = null; + if (value instanceof OffsetDateTime) { + instant = ((OffsetDateTime)value).toInstant(); + } else if (value instanceof LocalDateTime) { + instant = ((LocalDateTime)value).toInstant(ZoneOffset.of("Z")); + } + + if (instant != null) { + return ParsingUtilities.instantToString(instant); + } else if (value instanceof Double + && (((Double)value).isNaN() || ((Double)value).isInfinite())) { + // write as a string + return ((Double)value).toString(); + } else if (value instanceof Float + && (((Float)value).isNaN() || ((Float)value).isInfinite())) { + // TODO: Skip? Write as string? + return ((Float)value).toString(); + } else { + return value.toString(); + } + } else { + return null; + } + } + + /** + * TODO + * - use JsonIdentityInfo on recon + * - implement custom resolver to tie it to a pool + * - figure it all out + * @return + */ + @JsonProperty("r") + @JsonInclude(Include.NON_NULL) + public String getReconIdString() { + if (recon != null) { + return Long.toString(recon.id); + } + // TODO pool the recon?? + return null; + } + public void save(Writer writer, Properties options) { JSONWriter jsonWriter = new JSONWriter(writer); try { diff --git a/main/src/com/google/refine/model/Column.java b/main/src/com/google/refine/model/Column.java index 3eafa45db..e3cdf4538 100644 --- a/main/src/com/google/refine/model/Column.java +++ b/main/src/com/google/refine/model/Column.java @@ -44,6 +44,10 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.InterProjectModel; import com.google.refine.Jsonizable; import com.google.refine.model.recon.ReconConfig; @@ -76,10 +80,12 @@ public class Column implements Jsonizable { _originalName = _name = originalName; } + @JsonProperty("cellIndex") public int getCellIndex() { return _cellIndex; } + @JsonProperty("originalName") public String getOriginalHeaderLabel() { return _originalName; } @@ -88,6 +94,7 @@ public class Column implements Jsonizable { this._name = name; } + @JsonProperty("name") public String getName() { return _name; } @@ -96,6 +103,8 @@ public class Column implements Jsonizable { this._reconConfig = config; } + @JsonProperty("reconConfig") + @JsonInclude(Include.NON_NULL) public ReconConfig getReconConfig() { return _reconConfig; } @@ -104,6 +113,8 @@ public class Column implements Jsonizable { this._reconStats = stats; } + @JsonProperty("reconStats") + @JsonInclude(Include.NON_NULL) public ReconStats getReconStats() { return _reconStats; } @@ -131,6 +142,7 @@ public class Column implements Jsonizable { } writer.endObject(); } + /** * Clear all cached precomputed values. @@ -160,7 +172,7 @@ public class Column implements Jsonizable { _precomputes.put(key, value); } - + @JsonProperty("type") public String getType() { return type; } @@ -171,6 +183,7 @@ public class Column implements Jsonizable { } + @JsonProperty("format") public String getFormat() { return format; } @@ -181,6 +194,7 @@ public class Column implements Jsonizable { } + @JsonProperty("title") public String getTitle() { return title; } @@ -191,6 +205,7 @@ public class Column implements Jsonizable { } + @JsonProperty("description") public String getDescription() { return description; } @@ -200,6 +215,10 @@ public class Column implements Jsonizable { this.description = description; } + @JsonProperty("constraints") + public String getConstraintsString() { + return (new JSONObject(constraints)).toString(); + } public Map getConstraints() { return constraints; diff --git a/main/src/com/google/refine/model/ColumnGroup.java b/main/src/com/google/refine/model/ColumnGroup.java index 9df67f2dc..1ba26d1ad 100644 --- a/main/src/com/google/refine/model/ColumnGroup.java +++ b/main/src/com/google/refine/model/ColumnGroup.java @@ -42,7 +42,13 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonView; + import com.google.refine.Jsonizable; +import com.google.refine.util.JsonViews; import com.google.refine.util.ParsingUtilities; public class ColumnGroup implements Jsonizable { @@ -80,6 +86,28 @@ public class ColumnGroup implements Jsonizable { writer.endObject(); } + @JsonProperty("startColumnIndex") + public int getStartColumnIndex() { + return startColumnIndex; + } + + @JsonProperty("columnSpan") + public int getColumnSpan() { + return columnSpan; + } + + @JsonProperty("keyColumnIndex") + public int getKeyColumnIndex() { + return keyColumnIndex; + } + + @JsonProperty("subgroups") + @JsonView(JsonViews.NonSaveMode.class) + @JsonInclude(Include.NON_EMPTY) + public List getSubGroups() { + return subgroups; + } + public boolean contains(ColumnGroup g) { return (g.startColumnIndex >= startColumnIndex && g.startColumnIndex < startColumnIndex + columnSpan); diff --git a/main/src/com/google/refine/model/ColumnModel.java b/main/src/com/google/refine/model/ColumnModel.java index f310d3807..a4109c1b3 100644 --- a/main/src/com/google/refine/model/ColumnModel.java +++ b/main/src/com/google/refine/model/ColumnModel.java @@ -48,10 +48,17 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; public class ColumnModel implements Jsonizable { + @JsonProperty("columns") final public List columns = new LinkedList(); + @JsonProperty("columnGroups") final public List columnGroups = new LinkedList(); private int _maxCellIndex = -1; @@ -70,6 +77,7 @@ public class ColumnModel implements Jsonizable { this._maxCellIndex = Math.max(this._maxCellIndex, maxCellIndex); } + @JsonIgnore synchronized public int getMaxCellIndex() { return _maxCellIndex; } @@ -86,6 +94,7 @@ public class ColumnModel implements Jsonizable { this._keyColumnIndex = keyColumnIndex; } + @JsonIgnore synchronized public int getKeyColumnIndex() { return _keyColumnIndex; } @@ -166,6 +175,7 @@ public class ColumnModel implements Jsonizable { return _cellIndexToColumn.get(cellIndex); } + @JsonIgnore synchronized public List getColumnNames() { return _columnNames; } @@ -198,6 +208,24 @@ public class ColumnModel implements Jsonizable { writer.endObject(); } + @JsonProperty("keyCellIndex") + @JsonInclude(Include.NON_NULL) + public Integer getJsonKeyCellIndex() { + if(columns.size() > 0) { + return getKeyColumnIndex(); + } + return null; + } + + @JsonProperty("keyColumnName") + @JsonInclude(Include.NON_NULL) + public String getKeyColumnName() { + if(columns.size() > 0) { + return columns.get(_keyColumnIndex).getName(); + } + return null; + } + synchronized public void save(Writer writer, Properties options) throws IOException { writer.write("maxCellIndex="); writer.write(Integer.toString(_maxCellIndex)); writer.write('\n'); writer.write("keyColumnIndex="); writer.write(Integer.toString(_keyColumnIndex)); writer.write('\n'); diff --git a/main/src/com/google/refine/model/Recon.java b/main/src/com/google/refine/model/Recon.java index d131b3f7d..a4b726708 100644 --- a/main/src/com/google/refine/model/Recon.java +++ b/main/src/com/google/refine/model/Recon.java @@ -34,21 +34,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonView; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; + import com.google.refine.Jsonizable; import com.google.refine.expr.HasFields; +import com.google.refine.util.JsonViews; import com.google.refine.util.Pool; +@JsonFilter("reconCandidateFilter") public class Recon implements HasFields, Jsonizable { /** @@ -61,11 +71,15 @@ public class Recon implements HasFields, Jsonizable { private static final String WIKIDATA_IDENTIFIER_SPACE = "http://www.wikidata.org/entity/"; static public enum Judgment { + @JsonProperty("none") None, + @JsonProperty("matched") Matched, + @JsonProperty("new") New } + @Deprecated static public String judgmentToString(Judgment judgment) { if (judgment == Judgment.Matched) { return "matched"; @@ -76,6 +90,7 @@ public class Recon implements HasFields, Jsonizable { } } + @Deprecated static public Judgment stringToJudgment(String s) { if ("matched".equals(s)) { return Judgment.Matched; @@ -186,6 +201,7 @@ public class Recon implements HasFields, Jsonizable { candidates.add(candidate); } + @JsonIgnore public ReconCandidate getBestCandidate() { if (candidates != null && candidates.size() > 0) { return candidates.get(0); @@ -257,6 +273,7 @@ public class Recon implements HasFields, Jsonizable { return "match".equals(name) || "best".equals(name); } + @Deprecated protected String judgmentToString() { return judgmentToString(judgment); } @@ -273,6 +290,81 @@ public class Recon implements HasFields, Jsonizable { return false; } } + + @JsonProperty("id") + public long getId() { + return id; + } + + @JsonProperty("judgmentHistoryEntry") + @JsonView(JsonViews.SaveMode.class) + public long getJudgmentHistoryEntry() { + return judgmentHistoryEntry; + } + + @JsonProperty("service") + public String getServiceURI() { + return service; + } + + @JsonProperty("identifierSpace") + public String getIdentifierSpace() { + return identifierSpace; + } + + @JsonProperty("schemaSpace") + public String getSchemaSpace() { + return schemaSpace; + } + + @JsonProperty("j") + public Judgment getJudgment() { + return judgment; + } + + @JsonProperty("m") + @JsonInclude(Include.NON_NULL) + public ReconCandidate getMatch() { + return match; + } + + @JsonProperty("c") + //@JsonView(JsonViews.SaveMode.class) + public List getCandidates() { + if (candidates != null) { + return candidates; + } + return Collections.emptyList(); + } + + + @JsonProperty("f") + @JsonView(JsonViews.SaveMode.class) + public Object[] getfeatures() { + return features; + } + + @JsonProperty("judgmentAction") + @JsonView(JsonViews.SaveMode.class) + public String getJudgmentAction() { + return judgmentAction; + } + + @JsonProperty("judgmentBatchSize") + @JsonView(JsonViews.SaveMode.class) + public int getJudgmentBatchSize() { + return judgmentBatchSize; + } + + @JsonProperty("matchRank") + @JsonView(JsonViews.SaveMode.class) + @JsonInclude(Include.NON_NULL) + public Integer getMatchRank() { + if (match != null) { + return matchRank; + } + return null; + } @Override public void write(JSONWriter writer, Properties options) diff --git a/main/src/com/google/refine/model/ReconCandidate.java b/main/src/com/google/refine/model/ReconCandidate.java index 76a54d82f..b25b0354c 100644 --- a/main/src/com/google/refine/model/ReconCandidate.java +++ b/main/src/com/google/refine/model/ReconCandidate.java @@ -37,6 +37,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; @@ -47,9 +49,13 @@ import com.google.refine.Jsonizable; import com.google.refine.expr.HasFields; public class ReconCandidate implements HasFields, Jsonizable { + @JsonProperty("id") final public String id; + @JsonProperty("name") final public String name; + @JsonProperty("types") final public String[] types; + @JsonIgnore final public double score; public ReconCandidate(String topicID, String topicName, String[] typeIDs, double score) { @@ -59,6 +65,15 @@ public class ReconCandidate implements HasFields, Jsonizable { this.score = score; } + // Serialize doubles that are ints without trailing ".0" for consistency with previous serialization. + @JsonProperty("score") + public Object getJsonScore() { + if ((double)(int)score == score) { + return (int)score; + } + return score; + } + @Override public Object getField(String name, Properties bindings) { if ("id".equals(name)) { diff --git a/main/src/com/google/refine/model/RecordModel.java b/main/src/com/google/refine/model/RecordModel.java index 47a6e24a7..2d1bf0569 100644 --- a/main/src/com/google/refine/model/RecordModel.java +++ b/main/src/com/google/refine/model/RecordModel.java @@ -45,6 +45,9 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.expr.ExpressionUtils; @@ -85,6 +88,7 @@ public class RecordModel implements Jsonizable { _rowDependencies.get(rowIndex) : null; } + @JsonIgnore public int getRecordCount() { return _records.size(); } @@ -111,11 +115,15 @@ public class RecordModel implements Jsonizable { writer.object(); writer.key("hasRecords"); - writer.value( - _records != null && _rowDependencies != null && - _records.size() < _rowDependencies.size()); + writer.value(hasRecords()); writer.endObject(); } + + @JsonProperty("hasRecords") + public boolean hasRecords() { + return _records != null && _rowDependencies != null && + _records.size() < _rowDependencies.size(); + } static protected class KeyedGroup { int[] cellIndices; diff --git a/main/src/com/google/refine/model/Row.java b/main/src/com/google/refine/model/Row.java index 422fd76ec..780f1fe92 100644 --- a/main/src/com/google/refine/model/Row.java +++ b/main/src/com/google/refine/model/Row.java @@ -39,6 +39,9 @@ import java.util.List; import java.util.Map.Entry; import java.util.Properties; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; @@ -48,6 +51,7 @@ import org.json.JSONWriter; import com.google.refine.Jsonizable; import com.google.refine.expr.CellTuple; import com.google.refine.expr.HasFields; +import com.google.refine.util.JsonViews; import com.google.refine.util.Pool; /** @@ -106,6 +110,7 @@ public class Row implements HasFields, Jsonizable { return "cells".equals(name) || "record".equals(name); } + @JsonIgnore public boolean isEmpty() { for (Cell cell : cells) { if (cell != null && cell.value != null && !isValueBlank(cell.value)) { @@ -204,6 +209,26 @@ public class Row implements HasFields, Jsonizable { writer.endObject(); } + @JsonProperty(FLAGGED) + public boolean isFlagged() { + return flagged; + } + + @JsonProperty(STARRED) + public boolean isStarred() { + return starred; + } + + @JsonProperty("cells") + public List getCells() { + return cells; + } + + /* + @JsonView(JsonViews.SaveMode.class) + public + */ + public void save(Writer writer, Properties options) { JSONWriter jsonWriter = new JSONWriter(writer); try { diff --git a/main/src/com/google/refine/model/recon/ReconConfig.java b/main/src/com/google/refine/model/recon/ReconConfig.java index a85c70cef..7f11af0f8 100644 --- a/main/src/com/google/refine/model/recon/ReconConfig.java +++ b/main/src/com/google/refine/model/recon/ReconConfig.java @@ -47,6 +47,8 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.model.Cell; import com.google.refine.model.Project; @@ -130,4 +132,11 @@ abstract public class ReconConfig implements Jsonizable { LOGGER.error("Save failed",e); } } + + /** + * Returns the identifier for the reconciliation mode, as serialized in JSON. + * This is the same identifier that was used to register the registration mode. + */ + @JsonProperty("mode") + abstract public String getMode(); } diff --git a/main/src/com/google/refine/model/recon/StandardReconConfig.java b/main/src/com/google/refine/model/recon/StandardReconConfig.java index 84adf5273..43e3754b8 100644 --- a/main/src/com/google/refine/model/recon/StandardReconConfig.java +++ b/main/src/com/google/refine/model/recon/StandardReconConfig.java @@ -53,12 +53,17 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +import com.google.refine.Jsonizable; import com.google.refine.expr.ExpressionUtils; import com.google.refine.model.Cell; import com.google.refine.model.Project; import com.google.refine.model.Recon; import com.google.refine.model.Recon.Judgment; import com.google.refine.model.ReconCandidate; +import com.google.refine.model.ReconType; import com.google.refine.model.RecordModel.RowDependency; import com.google.refine.model.Row; import com.google.refine.util.ParsingUtilities; @@ -66,9 +71,12 @@ import com.google.refine.util.ParsingUtilities; public class StandardReconConfig extends ReconConfig { final static Logger logger = LoggerFactory.getLogger("refine-standard-recon"); - static public class ColumnDetail { + static public class ColumnDetail implements Jsonizable { + @JsonProperty("column") final public String columnName; + @JsonProperty("propertyName") final public String propertyName; + @JsonProperty("propertyID") final public String propertyID; public ColumnDetail(String columnName, String propertyName, String propertyID) { @@ -76,6 +84,17 @@ public class StandardReconConfig extends ReconConfig { this.propertyName = propertyName; this.propertyID = propertyID; } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("column"); writer.value(columnName); + writer.key("propertyName"); writer.value(propertyName); + writer.key("propertyID"); writer.value(propertyID); + writer.endObject(); + + } } static public ReconConfig reconstruct(JSONObject obj) throws Exception { @@ -133,14 +152,22 @@ public class StandardReconConfig extends ReconConfig { } } + @JsonProperty("service") final public String service; + @JsonProperty("identifierSpace") final public String identifierSpace; + @JsonProperty("schemaSpace") final public String schemaSpace; + @JsonIgnore final public String typeID; + @JsonIgnore final public String typeName; + @JsonProperty("autoMatch") final public boolean autoMatch; + @JsonProperty("columnDetails") final public List columnDetails; + @JsonProperty("limit") final private int limit; public StandardReconConfig( @@ -210,18 +237,21 @@ public class StandardReconConfig extends ReconConfig { writer.key("columnDetails"); writer.array(); for (ColumnDetail c : columnDetails) { - writer.object(); - writer.key("column"); writer.value(c.columnName); - writer.key("propertyName"); writer.value(c.propertyName); - writer.key("propertyID"); writer.value(c.propertyID); - writer.endObject(); + c.write(writer, options); } writer.endArray(); writer.key("limit"); writer.value(limit); writer.endObject(); } + + @JsonProperty("type") + public ReconType getReconType() { + ReconType t = new ReconType(typeID, typeName); + return t; + } @Override + @JsonIgnore public int getBatchSize() { return 10; } @@ -541,4 +571,10 @@ public class StandardReconConfig extends ReconConfig { } return set; } + + + @Override + public String getMode() { + return "standard-service"; + } } diff --git a/main/src/com/google/refine/util/JsonViews.java b/main/src/com/google/refine/util/JsonViews.java new file mode 100644 index 000000000..45074a41f --- /dev/null +++ b/main/src/com/google/refine/util/JsonViews.java @@ -0,0 +1,18 @@ +package com.google.refine.util; + + +/** + * Set of classes which define JSON visibility of certain fields. + * @author Antonin Delpeuch + * + */ +public class JsonViews { + + public static class SaveMode { + ; + } + + public static class NonSaveMode { + ; + } +} diff --git a/main/src/com/google/refine/util/ParsingUtilities.java b/main/src/com/google/refine/util/ParsingUtilities.java index 26adc6487..1cb62bc47 100644 --- a/main/src/com/google/refine/util/ParsingUtilities.java +++ b/main/src/com/google/refine/util/ParsingUtilities.java @@ -59,7 +59,22 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.ser.FilterProvider; +import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; + public class ParsingUtilities { + + public static final ObjectMapper mapper = new ObjectMapper(); + public static final FilterProvider defaultFilters = new SimpleFilterProvider() + .addFilter("reconCandidateFilter", SerializationFilters.reconCandidateFilter); + public static final FilterProvider saveFilters = new SimpleFilterProvider() + .addFilter("reconCandidateFilter", SerializationFilters.noFilter); + + public static final ObjectWriter saveWriter = mapper.writerWithView(JsonViews.SaveMode.class).with(saveFilters); + public static final ObjectWriter defaultWriter = mapper.writerWithView(JsonViews.NonSaveMode.class).with(defaultFilters); + public static final DateTimeFormatter ISO8601 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'"); static public Properties parseUrlParameters(HttpServletRequest request) { diff --git a/main/src/com/google/refine/util/SerializationFilters.java b/main/src/com/google/refine/util/SerializationFilters.java new file mode 100644 index 000000000..606d463d6 --- /dev/null +++ b/main/src/com/google/refine/util/SerializationFilters.java @@ -0,0 +1,55 @@ +package com.google.refine.util; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; +import com.fasterxml.jackson.databind.ser.PropertyFilter; +import com.fasterxml.jackson.databind.ser.PropertyWriter; +import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; + +import com.google.refine.model.Recon; +import com.google.refine.model.Recon.Judgment; + +public class SerializationFilters { + static class BaseFilter extends SimpleBeanPropertyFilter { + @Override + public void serializeAsField(Object obj, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) + throws Exception { + if (include(writer)) { + writer.serializeAsField(obj, jgen, provider); + } else if (!jgen.canOmitFields()) { + writer.serializeAsOmittedField(obj, jgen, provider); + } + } + + @Override + protected boolean include(BeanPropertyWriter writer) { + return true; + } + + @Override + protected boolean include(PropertyWriter writer) { + return true; + } + } + + public static PropertyFilter noFilter = new BaseFilter(); + public static PropertyFilter reconCandidateFilter = new BaseFilter() { + @Override + public void serializeAsField(Object obj, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) + throws Exception { + if (include(writer)) { + if (!writer.getName().equals("c") || ! (obj instanceof Recon)) { + writer.serializeAsField(obj, jgen, provider); + return; + } + Recon recon = (Recon)obj; + if (recon.judgment == Judgment.None) { + writer.serializeAsField(obj, jgen, provider); + } + } else if (!jgen.canOmitFields()) { + writer.serializeAsOmittedField(obj, jgen, provider); + } + } + }; +} diff --git a/main/tests/server/src/com/google/refine/tests/model/ColumnGroupTests.java b/main/tests/server/src/com/google/refine/tests/model/ColumnGroupTests.java index 83b6d8761..a964b07da 100644 --- a/main/tests/server/src/com/google/refine/tests/model/ColumnGroupTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/ColumnGroupTests.java @@ -1,7 +1,5 @@ package com.google.refine.tests.model; -import java.util.Properties; - import org.testng.annotations.Test; import com.google.refine.model.ColumnGroup; @@ -34,9 +32,7 @@ public class ColumnGroupTests { + " \"keyColumnIndex\":1" + "}]" + "}"; - Properties options = new Properties(); - options.setProperty("mode", "save"); - TestUtils.isSerializedTo(cg, json, options); - TestUtils.isSerializedTo(cg, fullJson); + TestUtils.isSerializedTo(cg, json, true); + TestUtils.isSerializedTo(cg, fullJson, false); } } diff --git a/main/tests/server/src/com/google/refine/tests/model/ColumnModelTests.java b/main/tests/server/src/com/google/refine/tests/model/ColumnModelTests.java index 89f986165..56c17abfd 100644 --- a/main/tests/server/src/com/google/refine/tests/model/ColumnModelTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/ColumnModelTests.java @@ -2,9 +2,50 @@ package com.google.refine.tests.model; import org.testng.annotations.Test; -public class ColumnModelTests { +import com.google.refine.model.ColumnModel; +import com.google.refine.model.Project; +import com.google.refine.tests.RefineTest; +import com.google.refine.tests.util.TestUtils; + +public class ColumnModelTests extends RefineTest { @Test public void serializeColumnModel() { - String json = ""; + Project project = createCSVProject("a,b\n"+ + "e,e"); + String json = "{\n" + + " \"columnGroups\" : [ ],\n" + + " \"columns\" : [ {\n" + + " \"cellIndex\" : 0,\n" + + " \"constraints\" : \"{}\",\n" + + " \"description\" : \"\",\n" + + " \"format\" : \"default\",\n" + + " \"name\" : \"a\",\n" + + " \"originalName\" : \"a\",\n" + + " \"title\" : \"\",\n" + + " \"type\" : \"\"\n" + + " }, {\n" + + " \"cellIndex\" : 1,\n" + + " \"constraints\" : \"{}\",\n" + + " \"description\" : \"\",\n" + + " \"format\" : \"default\",\n" + + " \"name\" : \"b\",\n" + + " \"originalName\" : \"b\",\n" + + " \"title\" : \"\",\n" + + " \"type\" : \"\"\n" + + " } ],\n" + + " \"keyCellIndex\" : 0,\n" + + " \"keyColumnName\" : \"a\"\n" + + " }"; + TestUtils.isSerializedTo(project.columnModel, json); + } + + @Test + public void serializeColumnModelEmpty() { + String json = "{" + + "\"columns\":[]," + + "\"columnGroups\":[]" + + "}"; + ColumnModel m = new ColumnModel(); + TestUtils.isSerializedTo(m, json); } } diff --git a/main/tests/server/src/com/google/refine/tests/model/ReconCandidateTests.java b/main/tests/server/src/com/google/refine/tests/model/ReconCandidateTests.java index 88fed65e4..3a24cd00d 100644 --- a/main/tests/server/src/com/google/refine/tests/model/ReconCandidateTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/ReconCandidateTests.java @@ -7,7 +7,7 @@ import com.google.refine.tests.util.TestUtils; public class ReconCandidateTests { @Test - public void serializeReconCandidate() throws Exception { + public void serializeReconCandidateInt() throws Exception { String json = "{\"id\":\"Q49213\"," + "\"name\":\"University of Texas at Austin\"," + "\"score\":100," @@ -15,4 +15,14 @@ public class ReconCandidateTests { ReconCandidate rc = ReconCandidate.loadStreaming(json); TestUtils.isSerializedTo(rc, json); } + + @Test + public void serializeReconCandidateDouble() throws Exception { + String json = "{\"id\":\"Q49213\"," + + "\"name\":\"University of Texas at Austin\"," + + "\"score\":0.5," + + "\"types\":[\"Q875538\",\"Q15936437\",\"Q20971972\",\"Q23002039\"]}"; + ReconCandidate rc = ReconCandidate.loadStreaming(json); + TestUtils.isSerializedTo(rc, json); + } } diff --git a/main/tests/server/src/com/google/refine/tests/model/ReconTests.java b/main/tests/server/src/com/google/refine/tests/model/ReconTests.java index a4ad792e8..fbfcfbfa0 100644 --- a/main/tests/server/src/com/google/refine/tests/model/ReconTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/ReconTests.java @@ -1,42 +1,44 @@ package com.google.refine.tests.model; -import java.util.Properties; - import org.testng.annotations.Test; import com.google.refine.model.Recon; +import com.google.refine.model.Recon.Judgment; import com.google.refine.tests.util.TestUtils; public class ReconTests { + + String fullJson = "{\"id\":1533651559492945033," + + "\"judgmentHistoryEntry\":1533651616890," + + "\"service\":\"https://tools.wmflabs.org/openrefine-wikidata/en/api\"," + + "\"identifierSpace\":\"http://www.wikidata.org/entity/\"," + + "\"schemaSpace\":\"http://www.wikidata.org/prop/direct/\"," + + "\"j\":\"matched\"," + + "\"m\":{" + + " \"id\":\"Q2892284\"," + + " \"name\":\"Baylor College of Medicine\"," + + " \"score\":98.57142857142858," + + " \"types\":[\"Q16917\",\"Q23002054\",\"Q494230\"]" + + "}," + + "\"c\":[" + + " {\"id\":\"Q2892284\",\"name\":\"Baylor College of Medicine\",\"score\":98.57142857142858,\"types\":[\"Q16917\",\"Q23002054\",\"Q494230\"]}," + + " {\"id\":\"Q16165943\",\"name\":\"Baylor College of Medicine Academy at Ryan\",\"score\":82.14285714285715,\"types\":[\"Q149566\"]}," + + " {\"id\":\"Q30284245\",\"name\":\"Baylor College of Medicine Children\\u2019s Foundation\",\"score\":48.57142857142858,\"types\":[\"Q163740\"]}" + + "]," + + "\"f\":[false,false,1,0.6666666666666666]," + + "\"judgmentAction\":\"mass\"," + + "\"judgmentBatchSize\":1," + + "\"matchRank\":0}"; + @Test - public void serializeRecon() throws Exception { - Properties options = new Properties(); - options.put("mode", "save"); - - String fullJson = "{\"id\":1533651559492945033," - + "\"judgmentHistoryEntry\":1533651616890," - + "\"service\":\"https://tools.wmflabs.org/openrefine-wikidata/en/api\"," - + "\"identifierSpace\":\"http://www.wikidata.org/entity/\"," - + "\"schemaSpace\":\"http://www.wikidata.org/prop/direct/\"," - + "\"j\":\"matched\"," - + "\"m\":{" - + " \"id\":\"Q2892284\"," - + " \"name\":\"Baylor College of Medicine\"," - + " \"score\":98.57142857142858," - + " \"types\":[\"Q16917\",\"Q23002054\",\"Q494230\"]" - + "}," - + "\"c\":[" - + " {\"id\":\"Q2892284\",\"name\":\"Baylor College of Medicine\",\"score\":98.57142857142858,\"types\":[\"Q16917\",\"Q23002054\",\"Q494230\"]}," - + " {\"id\":\"Q16165943\",\"name\":\"Baylor College of Medicine Academy at Ryan\",\"score\":82.14285714285715,\"types\":[\"Q149566\"]}," - + " {\"id\":\"Q30284245\",\"name\":\"Baylor College of Medicine Children\\u2019s Foundation\",\"score\":48.57142857142858,\"types\":[\"Q163740\"]}" - + "]," - + "\"f\":[false,false,1,0.6666666666666666]," - + "\"judgmentAction\":\"mass\"," - + "\"judgmentBatchSize\":1," - + "\"matchRank\":0}"; + public void serializeReconSaveMode() throws Exception { Recon r = Recon.loadStreaming(fullJson, null); - TestUtils.isSerializedTo(r, fullJson, options); + TestUtils.isSerializedTo(r, fullJson, true); + } + @Test + public void serializeReconViewMode() throws Exception { + Recon r = Recon.loadStreaming(fullJson, null); String shortJson = "{\"id\":1533651559492945033," + "\"service\":\"https://tools.wmflabs.org/openrefine-wikidata/en/api\"," + "\"identifierSpace\":\"http://www.wikidata.org/entity/\"," @@ -48,9 +50,26 @@ public class ReconTests { + " \"score\":98.57142857142858," + " \"types\":[\"Q16917\",\"Q23002054\",\"Q494230\"]" + "}}"; - options.put("mode", "normal"); - TestUtils.isSerializedTo(r, shortJson, options); + TestUtils.isSerializedTo(r, shortJson, false); } + @Test + public void serializeReconSaveModeNoMatch() throws Exception { + String json = "{\"id\":1533651559492945033," + + "\"service\":\"https://tools.wmflabs.org/openrefine-wikidata/en/api\"," + + "\"identifierSpace\":\"http://www.wikidata.org/entity/\"," + + "\"schemaSpace\":\"http://www.wikidata.org/prop/direct/\"," + + "\"j\":\"none\"," + + "\"c\":[" + + " {\"id\":\"Q2892284\",\"name\":\"Baylor College of Medicine\",\"score\":98.57142857142858,\"types\":[\"Q16917\",\"Q23002054\",\"Q494230\"]}," + + " {\"id\":\"Q16165943\",\"name\":\"Baylor College of Medicine Academy at Ryan\",\"score\":82.14285714285715,\"types\":[\"Q149566\"]}," + + " {\"id\":\"Q30284245\",\"name\":\"Baylor College of Medicine Children\\u2019s Foundation\",\"score\":48.57142857142858,\"types\":[\"Q163740\"]}" + + "]" + + "}"; + Recon r = Recon.loadStreaming(fullJson, null); + r.match = null; + r.judgment = Judgment.None; + TestUtils.isSerializedTo(r, json); + } } diff --git a/main/tests/server/src/com/google/refine/tests/model/RowTests.java b/main/tests/server/src/com/google/refine/tests/model/RowTests.java index ef0a765e0..6d36f4838 100644 --- a/main/tests/server/src/com/google/refine/tests/model/RowTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/RowTests.java @@ -107,7 +107,7 @@ public class RowTests extends RefineTest { Row row = new Row(5); row.setCell(0, new Cell("I'm not empty", null)); row.save(writer, options); - TestUtils.equalAsJson(writer.getBuffer().toString(), + TestUtils.assertEqualAsJson(writer.getBuffer().toString(), "{\"flagged\":false,\"starred\":false,\"cells\":[{\"v\":\"I'm not empty\"}]}"); } @@ -120,7 +120,7 @@ public class RowTests extends RefineTest { when(options.containsKey("recordIndex")).thenReturn(true); when(options.get("recordIndex")).thenReturn(1); row.save(writer, options); - TestUtils.equalAsJson( + TestUtils.assertEqualAsJson( writer.getBuffer().toString(), "{\"flagged\":false,\"starred\":false,\"cells\":[{\"v\":\"I'm not empty\"}],\"i\":0,\"j\":1}"); } diff --git a/main/tests/server/src/com/google/refine/tests/util/TestUtils.java b/main/tests/server/src/com/google/refine/tests/util/TestUtils.java index b0984c645..0e00b7e0c 100644 --- a/main/tests/server/src/com/google/refine/tests/util/TestUtils.java +++ b/main/tests/server/src/com/google/refine/tests/util/TestUtils.java @@ -5,19 +5,32 @@ import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; +import java.io.LineNumberReader; +import java.io.StringReader; +import java.io.StringWriter; import java.util.Properties; +import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.SerializationFeature; import com.google.refine.Jsonizable; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.JsonViews; +import com.google.refine.util.ParsingUtilities; public class TestUtils { static ObjectMapper mapper = new ObjectMapper(); + static { + mapper = mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); + } /** * Create a temporary directory. NOTE: This is a quick and dirty @@ -38,7 +51,7 @@ public class TestUtils { /** * Compare two JSON strings for equality. */ - public static void equalAsJson(String expected, String actual) { + public static void assertEqualAsJson(String expected, String actual) { try { JsonNode jsonA = mapper.readValue(expected, JsonNode.class); JsonNode jsonB = mapper.readValue(actual, JsonNode.class); @@ -48,19 +61,52 @@ public class TestUtils { } } + public static boolean equalAsJson(String expected, String actual) { + try { + JsonNode jsonA = mapper.readValue(expected, JsonNode.class); + JsonNode jsonB = mapper.readValue(actual, JsonNode.class); + return (jsonA == null && jsonB == null) || jsonA.equals(jsonB); + } catch(Exception e) { + return false; + } + } + /** * Checks that a serializable object is serialized to the target JSON string. + * @throws IOException */ public static void isSerializedTo(Jsonizable o, String targetJson, Properties options) { - equalAsJson(targetJson, JSONUtilities.serialize(o, options)); + String orgJson = JSONUtilities.serialize(o, options); + if(!equalAsJson(targetJson, orgJson)) { + System.out.println("org.json, "+o.getClass().getName()); + try { + jsonDiff(targetJson, orgJson); + } catch (JsonParseException | JsonMappingException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + assertEqualAsJson(targetJson, orgJson); // also check Jackson serialization try { - equalAsJson(targetJson, mapper.writeValueAsString(o)); - } catch (JsonProcessingException e) { - e.printStackTrace(); - fail("jackson serialization failed"); - } + String saveMode = options.getProperty("mode"); + ObjectWriter writer = null; + if("save".equals(saveMode)) { + writer = ParsingUtilities.saveWriter; + } else { + writer = ParsingUtilities.defaultWriter; + } + String jacksonJson = writer.writeValueAsString(o); + if(!equalAsJson(targetJson, jacksonJson)) { + System.out.println("jackson, "+o.getClass().getName()); + jsonDiff(targetJson, jacksonJson); + } + assertEqualAsJson(targetJson, jacksonJson); + } catch (JsonProcessingException e) { + e.printStackTrace(); + fail("jackson serialization failed"); + } } /** @@ -69,4 +115,64 @@ public class TestUtils { public static void isSerializedTo(Jsonizable o, String targetJson) { isSerializedTo(o, targetJson, new Properties()); } + + /** + * Checks that a serializable object is serialized to the target JSON string. + * This specifies the "save mode" for objects that are stored differently depending on + * whether they are written to disk or sent over the network. + */ + public static void isSerializedTo(Jsonizable o, String targetJson, boolean saveMode) { + Properties options = new Properties(); + if(saveMode) { + options.setProperty("mode", "save"); + options.put("mode", "save"); + } + isSerializedTo(o, targetJson, options); + } + + public static void jsonDiff(String a, String b) throws JsonParseException, JsonMappingException { + ObjectMapper myMapper = mapper.copy().configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true) + .configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true) + .configure(SerializationFeature.INDENT_OUTPUT, true); + try { + JsonNode nodeA = myMapper.readValue(a, JsonNode.class); + JsonNode nodeB = myMapper.readValue(b, JsonNode.class); + String prettyA = myMapper.writeValueAsString(myMapper.treeToValue(nodeA, Object.class)); + String prettyB = myMapper.writeValueAsString(myMapper.treeToValue(nodeB, Object.class)); + + // Compute the max line length of A + LineNumberReader readerA = new LineNumberReader(new StringReader(prettyA)); + int maxLength = 0; + String line = readerA.readLine(); + while (line != null) { + if(line.length() > maxLength) { + maxLength = line.length(); + } + line = readerA.readLine(); + } + + // Pad all lines + readerA = new LineNumberReader(new StringReader(prettyA)); + LineNumberReader readerB = new LineNumberReader(new StringReader(prettyB)); + StringWriter writer = new StringWriter(); + String lineA = readerA.readLine(); + String lineB = readerB.readLine(); + while(lineA != null || lineB != null) { + if (lineA == null) { + lineA = ""; + } + if (lineB == null) { + lineB = ""; + } + String paddedLineA = lineA + new String(new char[maxLength + 2 - lineA.length()]).replace("\0", " "); + writer.write(paddedLineA); + writer.write(lineB + "\n"); + lineA = readerA.readLine(); + lineB = readerB.readLine(); + } + System.out.print(writer.toString()); + } catch(IOException e) { + e.printStackTrace(); + } + } } From 761b748faae794de9b33b55e9f8a82dfd81e7aa6 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Thu, 27 Sep 2018 18:52:50 +0100 Subject: [PATCH 009/164] Cleaner double serialization emulation, application wide. --- .../google/refine/model/ReconCandidate.java | 16 ++++---------- .../google/refine/util/ParsingUtilities.java | 10 ++++++++- .../refine/util/SerializationFilters.java | 21 +++++++++++++++++++ 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/main/src/com/google/refine/model/ReconCandidate.java b/main/src/com/google/refine/model/ReconCandidate.java index b25b0354c..7c3f4c9d0 100644 --- a/main/src/com/google/refine/model/ReconCandidate.java +++ b/main/src/com/google/refine/model/ReconCandidate.java @@ -37,13 +37,14 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; +import org.json.JSONException; +import org.json.JSONWriter; + import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.Jsonizable; import com.google.refine.expr.HasFields; @@ -55,7 +56,7 @@ public class ReconCandidate implements HasFields, Jsonizable { final public String name; @JsonProperty("types") final public String[] types; - @JsonIgnore + @JsonProperty("score") final public double score; public ReconCandidate(String topicID, String topicName, String[] typeIDs, double score) { @@ -65,15 +66,6 @@ public class ReconCandidate implements HasFields, Jsonizable { this.score = score; } - // Serialize doubles that are ints without trailing ".0" for consistency with previous serialization. - @JsonProperty("score") - public Object getJsonScore() { - if ((double)(int)score == score) { - return (int)score; - } - return score; - } - @Override public Object getField(String name, Properties bindings) { if ("id".equals(name)) { diff --git a/main/src/com/google/refine/util/ParsingUtilities.java b/main/src/com/google/refine/util/ParsingUtilities.java index 1cb62bc47..3404b79af 100644 --- a/main/src/com/google/refine/util/ParsingUtilities.java +++ b/main/src/com/google/refine/util/ParsingUtilities.java @@ -61,12 +61,20 @@ import org.json.JSONTokener; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; public class ParsingUtilities { public static final ObjectMapper mapper = new ObjectMapper(); + static { + SimpleModule module = new SimpleModule(); + module.addSerializer(Double.class, new SerializationFilters.DoubleSerializer()); + module.addSerializer(double.class, new SerializationFilters.DoubleSerializer()); + mapper.registerModule(module); + } + public static final FilterProvider defaultFilters = new SimpleFilterProvider() .addFilter("reconCandidateFilter", SerializationFilters.reconCandidateFilter); public static final FilterProvider saveFilters = new SimpleFilterProvider() @@ -74,7 +82,7 @@ public class ParsingUtilities { public static final ObjectWriter saveWriter = mapper.writerWithView(JsonViews.SaveMode.class).with(saveFilters); public static final ObjectWriter defaultWriter = mapper.writerWithView(JsonViews.NonSaveMode.class).with(defaultFilters); - + public static final DateTimeFormatter ISO8601 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'"); static public Properties parseUrlParameters(HttpServletRequest request) { diff --git a/main/src/com/google/refine/util/SerializationFilters.java b/main/src/com/google/refine/util/SerializationFilters.java index 606d463d6..c8752c22f 100644 --- a/main/src/com/google/refine/util/SerializationFilters.java +++ b/main/src/com/google/refine/util/SerializationFilters.java @@ -1,11 +1,14 @@ package com.google.refine.util; +import java.io.IOException; + import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.ser.PropertyFilter; import com.fasterxml.jackson.databind.ser.PropertyWriter; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.google.refine.model.Recon; import com.google.refine.model.Recon.Judgment; @@ -52,4 +55,22 @@ public class SerializationFilters { } } }; + + public static class DoubleSerializer extends StdSerializer { + private static final long serialVersionUID = 132345L; + + public DoubleSerializer() { + super(Double.class); + } + + @Override + public void serialize(Double arg0, JsonGenerator gen, SerializerProvider s) + throws IOException { + if (new Double(arg0.intValue()).equals(arg0)) { + gen.writeNumber(arg0.intValue()); + } else { + gen.writeNumber(arg0); + } + } + } } From 8f1c7cc2ab7f354570f277cb8385a4b791779d06 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 28 Sep 2018 08:54:50 +0100 Subject: [PATCH 010/164] Jackson serialization for facets --- .../refine/browsing/DecoratedValue.java | 4 + .../refine/browsing/facets/FacetConfig.java | 8 + .../refine/browsing/facets/ListFacet.java | 130 ++++++++++++++- .../browsing/facets/NominalFacetChoice.java | 5 + .../refine/browsing/facets/RangeFacet.java | 129 ++++++++++++++- .../browsing/facets/ScatterplotFacet.java | 150 ++++++++++++++++++ .../browsing/facets/TextSearchFacet.java | 47 +++++- .../browsing/facets/TimeRangeFacet.java | 121 +++++++++++++- .../refine/util/SerializationFilters.java | 4 +- .../browsing/facets/TimeRangeFacetTests.java | 10 +- .../google/refine/tests/util/TestUtils.java | 1 - 11 files changed, 589 insertions(+), 20 deletions(-) diff --git a/main/src/com/google/refine/browsing/DecoratedValue.java b/main/src/com/google/refine/browsing/DecoratedValue.java index 90bde0930..31c617a97 100644 --- a/main/src/com/google/refine/browsing/DecoratedValue.java +++ b/main/src/com/google/refine/browsing/DecoratedValue.java @@ -39,6 +39,8 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.util.StringUtils; @@ -50,7 +52,9 @@ import com.google.refine.util.StringUtils; * Facet choices that are presented to the user as text are stored as decorated values. */ public class DecoratedValue implements Jsonizable { + @JsonProperty("v") final public Object value; + @JsonProperty("l") final public String label; public DecoratedValue(Object value, String label) { diff --git a/main/src/com/google/refine/browsing/facets/FacetConfig.java b/main/src/com/google/refine/browsing/facets/FacetConfig.java index c6786749e..3971b66d4 100644 --- a/main/src/com/google/refine/browsing/facets/FacetConfig.java +++ b/main/src/com/google/refine/browsing/facets/FacetConfig.java @@ -2,6 +2,8 @@ package com.google.refine.browsing.facets; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.model.Project; @@ -28,4 +30,10 @@ public interface FacetConfig extends Jsonizable { * @return a computed facet on the given project. */ public Facet apply(Project project); + + /** + * The facet type as stored in json. + */ + @JsonProperty("type") + public String getJsonType(); } diff --git a/main/src/com/google/refine/browsing/facets/ListFacet.java b/main/src/com/google/refine/browsing/facets/ListFacet.java index d5cdfa45f..780e73f80 100644 --- a/main/src/com/google/refine/browsing/facets/ListFacet.java +++ b/main/src/com/google/refine/browsing/facets/ListFacet.java @@ -36,12 +36,20 @@ package com.google.refine.browsing.facets; import java.util.LinkedList; import java.util.List; import java.util.Properties; +import java.util.stream.Collectors; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + import com.google.refine.ProjectManager; import com.google.refine.browsing.DecoratedValue; import com.google.refine.browsing.FilteredRecords; @@ -60,24 +68,51 @@ import com.google.refine.model.Project; import com.google.refine.util.JSONUtilities; public class ListFacet implements Facet { + public static final String ERR_TOO_MANY_CHOICES = "Too many choices"; + + /** + * Wrapper to respect the serialization format + */ + public static class DecoratedValueWrapper { + @JsonProperty("v") + public final DecoratedValue value; + @JsonCreator + public DecoratedValueWrapper( + @JsonProperty("v") DecoratedValue value) { + this.value = value; + } + } + /* * Configuration */ public static class ListFacetConfig implements FacetConfig { + @JsonProperty("name") public String name; + @JsonProperty("expression") public String expression; + @JsonProperty("columnName") public String columnName; + @JsonProperty("invert") public boolean invert; // If true, then facet won't show the blank and error choices + @JsonProperty("omitBlank") public boolean omitBlank; + @JsonProperty("omitError") public boolean omitError; + @JsonIgnore public List selection = new LinkedList<>(); + @JsonProperty("selectNumber") public boolean selectNumber; + @JsonProperty("selectDateTime") public boolean selectDateTime; + @JsonProperty("selectBoolean") public boolean selectBoolean; + @JsonProperty("selectBlank") public boolean selectBlank; + @JsonProperty("selectError") public boolean selectError; @Override @@ -107,6 +142,13 @@ public class ListFacet implements Facet { writer.endObject(); } + @JsonProperty("selection") + public List getWrappedSelection() { + return selection.stream() + .map(e -> new DecoratedValueWrapper(e)) + .collect(Collectors.toList()); + } + @Override public void initializeFromJSON(JSONObject o) { name = o.getString("name"); @@ -143,6 +185,27 @@ public class ListFacet implements Facet { facet.initializeFromConfig(this, project); return facet; } + + @Override + public String getJsonType() { + return "list"; + } + } + + /** + * Wrapper class for choice counts and selection status for blank and error + */ + public static class OtherChoice { + @JsonProperty("s") + boolean selected; + @JsonProperty("c") + int count; + public OtherChoice( + @JsonProperty("s") boolean selected, + @JsonProperty("c") int count) { + this.selected = selected; + this.count = count; + } } ListFacetConfig _config = new ListFacetConfig(); @@ -166,6 +229,69 @@ public class ListFacet implements Facet { public ListFacet() { } + + @JsonProperty("name") + public String getName() { + return _config.name; + } + + @JsonProperty("columnName") + public String getColumnName() { + return _config.columnName; + } + + @JsonProperty("expression") + public String getExpression() { + return _config.expression; + } + + @JsonProperty("invert") + public boolean getInvert() { + return _config.invert; + } + + @JsonProperty("error") + @JsonInclude(Include.NON_NULL) + public String getError() { + if (_errorMessage == null && _choices.size() > getLimit()) { + return ERR_TOO_MANY_CHOICES; + } + return _errorMessage; + } + + @JsonProperty("choiceCount") + @JsonInclude(Include.NON_NULL) + public Integer getChoiceCount() { + if (_errorMessage == null && _choices.size() > getLimit()) + return _choices.size(); + return null; + } + + @JsonProperty("choices") + @JsonInclude(Include.NON_NULL) + public List getChoices() { + if (getError() == null) + return _choices; + return null; + } + + @JsonProperty("blankChoice") + @JsonInclude(Include.NON_NULL) + public OtherChoice getBlankChoice() { + if (getError() == null && !_config.omitBlank && (_config.selectBlank || _blankCount > 0)) { + return new OtherChoice(_config.selectBlank, _blankCount); + } + return null; + } + + @JsonProperty("errorChoice") + @JsonInclude(Include.NON_NULL) + public OtherChoice getErrorChoice() { + if (getError() == null && !_config.omitError && (_config.selectError || _errorCount > 0)) { + return new OtherChoice(_config.selectError, _errorCount); + } + return null; + } @Override public void write(JSONWriter writer, Properties options) @@ -180,7 +306,7 @@ public class ListFacet implements Facet { if (_errorMessage != null) { writer.key("error"); writer.value(_errorMessage); } else if (_choices.size() > getLimit()) { - writer.key("error"); writer.value("Too many choices"); + writer.key("error"); writer.value(ERR_TOO_MANY_CHOICES); writer.key("choiceCount"); writer.value(_choices.size()); } else { writer.key("choices"); writer.array(); @@ -359,4 +485,4 @@ public class ListFacet implements Facet { } return a; } -} \ No newline at end of file +} diff --git a/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java b/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java index 96d5674d0..ad59ff61a 100644 --- a/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java +++ b/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java @@ -38,6 +38,8 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.browsing.DecoratedValue; @@ -46,8 +48,11 @@ import com.google.refine.browsing.DecoratedValue; * and a flag of whether it has been selected. */ public class NominalFacetChoice implements Jsonizable { + @JsonProperty("v") final public DecoratedValue decoratedValue; + @JsonProperty("c") public int count; + @JsonProperty("s") public boolean selected; public NominalFacetChoice(DecoratedValue decoratedValue) { diff --git a/main/src/com/google/refine/browsing/facets/RangeFacet.java b/main/src/com/google/refine/browsing/facets/RangeFacet.java index 662253697..48621873b 100644 --- a/main/src/com/google/refine/browsing/facets/RangeFacet.java +++ b/main/src/com/google/refine/browsing/facets/RangeFacet.java @@ -39,6 +39,11 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RecordFilter; @@ -59,22 +64,35 @@ import com.google.refine.model.Project; import com.google.refine.util.JSONUtilities; public class RangeFacet implements Facet { + + public static final String ERR_NO_NUMERIC_VALUE_PRESENT = "No numeric value present."; + /* * Configuration, from the client side */ public static class RangeFacetConfig implements FacetConfig { + @JsonProperty("name") protected String _name; // name of facet + @JsonProperty("expression") protected String _expression; // expression to compute numeric value(s) per row + @JsonProperty("columnName") protected String _columnName; // column to base expression on, if any + @JsonProperty(FROM) protected double _from; // the numeric selection + @JsonProperty(TO) protected double _to; + @JsonProperty("selectNumeric") protected boolean _selectNumeric; // whether the numeric selection applies, default true + @JsonProperty("selectNonNumeric") protected boolean _selectNonNumeric; + @JsonProperty("selectBlank") protected boolean _selectBlank; + @JsonProperty("selectError") protected boolean _selectError; + @JsonIgnore protected boolean _selected; // false if we're certain that all rows will match // and there isn't any filtering to do @@ -122,6 +140,11 @@ public class RangeFacet implements Facet { facet.initializeFromConfig(this, project); return facet; } + + @Override + public String getJsonType() { + return "range"; + } } RangeFacetConfig _config = new RangeFacetConfig(); @@ -141,16 +164,24 @@ public class RangeFacet implements Facet { protected int[] _baseBins; protected int[] _bins; + @JsonProperty("baseNumericCount") protected int _baseNumericCount; + @JsonProperty("baseNonNumericCount") protected int _baseNonNumericCount; + @JsonProperty("baseBlankCount") protected int _baseBlankCount; + @JsonProperty("baseErrorCount") protected int _baseErrorCount; + @JsonProperty("numericCount") protected int _numericCount; + @JsonProperty("nonNumericCount") protected int _nonNumericCount; + @JsonProperty("blankCount") protected int _blankCount; + @JsonProperty("errorCount") protected int _errorCount; - + public RangeFacet() { } @@ -159,6 +190,100 @@ public class RangeFacet implements Facet { protected static final String TO = "to"; protected static final String FROM = "from"; + @JsonProperty("name") + public String getName() { + return _config._name; + } + + @JsonProperty("expression") + public String getExpression() { + return _config._expression; + } + + @JsonProperty("columnName") + public String getColumnName() { + return _config._columnName; + } + + @JsonProperty("error") + @JsonInclude(Include.NON_NULL) + public String getError() { + if (_errorMessage != null) { + return _errorMessage; + } else if (!isFiniteRange()) { + return ERR_NO_NUMERIC_VALUE_PRESENT; + } + return null; + } + + @JsonIgnore + public boolean isFiniteRange() { + return !Double.isInfinite(_min) && !Double.isInfinite(_max); + } + + @JsonProperty(MIN) + @JsonInclude(Include.NON_NULL) + public Double getMin() { + if (getError() == null) { + return _min; + } + return null; + } + + @JsonProperty(MAX) + @JsonInclude(Include.NON_NULL) + public Double getMax() { + if (getError() == null) { + return _max; + } + return null; + } + + @JsonProperty("step") + @JsonInclude(Include.NON_NULL) + public Double getStep() { + if (getError() == null) { + return _step; + } + return null; + } + + @JsonProperty("bins") + @JsonInclude(Include.NON_NULL) + public int[] getBins() { + if (getError() == null) { + return _bins; + } + return null; + } + + @JsonProperty("baseBins") + @JsonInclude(Include.NON_NULL) + public int[] getBaseBins() { + if (getError() == null) { + return _baseBins; + } + return null; + } + + @JsonProperty(FROM) + @JsonInclude(Include.NON_NULL) + public Double getFrom() { + if (getError() == null) { + return _config._from; + } + return null; + } + + @JsonProperty(TO) + @JsonInclude(Include.NON_NULL) + public Double getTo() { + if (getError() == null) { + return _config._to; + } + return null; + } + @Override public void write(JSONWriter writer, Properties options) throws JSONException { @@ -191,7 +316,7 @@ public class RangeFacet implements Facet { writer.key(FROM); writer.value(_config._from); writer.key(TO); writer.value(_config._to); } else { - writer.key("error"); writer.value("No numeric value present."); + writer.key("error"); writer.value(ERR_NO_NUMERIC_VALUE_PRESENT); } writer.key("baseNumericCount"); writer.value(_baseNumericCount); diff --git a/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java b/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java index 3a6862d59..3945251d7 100644 --- a/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java +++ b/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java @@ -51,6 +51,11 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RecordFilter; @@ -80,33 +85,61 @@ public class ScatterplotFacet implements Facet { * Configuration, from the client side */ public static class ScatterplotFacetConfig implements FacetConfig { + @JsonProperty("name") protected String name; // name of facet + @JsonProperty(X_EXPRESSION) protected String expression_x; // expression to compute the x numeric value(s) per row + @JsonProperty(Y_EXPRESSION) protected String expression_y; // expression to compute the y numeric value(s) per row + @JsonProperty(X_COLUMN_NAME) protected String columnName_x; // column to base the x expression on, if any + @JsonProperty(Y_COLUMN_NAME) protected String columnName_y; // column to base the y expression on, if any + @JsonProperty(SIZE) protected int size; + @JsonIgnore protected int dim_x; + @JsonIgnore protected int dim_y; + @JsonIgnore protected String rotation_str; + @JsonIgnore protected int rotation; + @JsonIgnore protected double l; + @JsonProperty(DOT) protected double dot; + @JsonIgnore protected String color_str; + @JsonIgnore protected Color color; + @JsonProperty(FROM_X) protected double from_x; // the numeric selection for the x axis, from 0 to 1 + @JsonProperty(TO_X) protected double to_x; + @JsonProperty(FROM_Y) protected double from_y; // the numeric selection for the y axis, from 0 to 1 + @JsonProperty(TO_Y) protected double to_y; protected boolean selected; // false if we're certain that all rows will match // and there isn't any filtering to do + @JsonProperty(DIM_X) + public String getDimX() { + return dim_x == LIN ? "lin" : "log"; + } + + @JsonProperty(DIM_Y) + public String getDimY() { + return dim_y == LIN ? "lin" : "log"; + } + @Override public void write(JSONWriter writer, Properties options) throws JSONException { @@ -193,6 +226,11 @@ public class ScatterplotFacet implements Facet { return NO_ROTATION; } } + + @Override + public String getJsonType() { + return "scatterplot"; + } } ScatterplotFacetConfig config; @@ -255,6 +293,118 @@ public class ScatterplotFacet implements Facet { } } + @JsonProperty(NAME) + public String getName() { + return config.name; + } + + @JsonProperty(X_COLUMN_NAME) + public String getXColumnName() { + return config.columnName_x; + } + + @JsonProperty(X_EXPRESSION) + public String getXExpression() { + return config.expression_x; + } + + @JsonProperty(Y_COLUMN_NAME) + public String getYColumnName() { + return config.columnName_y; + } + + @JsonProperty(Y_EXPRESSION) + public String getYExpression() { + return config.expression_y; + } + + @JsonProperty(SIZE) + public int getSize() { + return config.size; + } + + @JsonProperty(DIM_X) + public int getDimX() { + return config.dim_x; + } + + @JsonProperty(DIM_Y) + public int getDimY() { + return config.dim_y; + } + + @JsonProperty(DOT) + public double getDot() { + return config.dot; + } + + @JsonProperty(ROTATION) + public double getRotation() { + return config.rotation; + } + + @JsonProperty(COLOR) + public String getColorString() { + return config.color_str; + } + + @JsonProperty(IMAGE) + @JsonInclude(Include.NON_NULL) + public String getImage() { + if(IMAGE_URI) { + return image; + } + return null; + } + + @JsonProperty(ERROR_X) + @JsonInclude(Include.NON_NULL) + public String getErrorX() { + return errorMessage_x; + } + + @JsonProperty(FROM_X) + @JsonInclude(Include.NON_NULL) + public Double getFromX() { + if (errorMessage_x == null && !Double.isInfinite(min_x) && !Double.isInfinite(max_x)) { + return config.from_x; + } + return null; + } + + @JsonProperty(TO_X) + @JsonInclude(Include.NON_NULL) + public Double getToX() { + if (errorMessage_x == null && !Double.isInfinite(min_x) && !Double.isInfinite(max_x)) { + return config.to_x; + } + return null; + } + + @JsonProperty(ERROR_Y) + @JsonInclude(Include.NON_NULL) + public String getErrorY() { + return errorMessage_y; + } + + @JsonProperty(FROM_Y) + @JsonInclude(Include.NON_NULL) + public Double getFromY() { + if (errorMessage_y == null && !Double.isInfinite(min_y) && !Double.isInfinite(max_y)) { + return config.from_y; + } + return null; + } + + @JsonProperty(TO_Y) + @JsonInclude(Include.NON_NULL) + public Double getToY() { + if (errorMessage_y == null && !Double.isInfinite(min_y) && !Double.isInfinite(max_y)) { + return config.to_y; + } + return null; + } + @Override public void write(JSONWriter writer, Properties options) throws JSONException { diff --git a/main/src/com/google/refine/browsing/facets/TextSearchFacet.java b/main/src/com/google/refine/browsing/facets/TextSearchFacet.java index 96f97813b..c627f8258 100644 --- a/main/src/com/google/refine/browsing/facets/TextSearchFacet.java +++ b/main/src/com/google/refine/browsing/facets/TextSearchFacet.java @@ -40,6 +40,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RecordFilter; @@ -58,11 +60,17 @@ public class TextSearchFacet implements Facet { * Configuration */ public static class TextSearchFacetConfig implements FacetConfig { + @JsonProperty("name") protected String _name; + @JsonProperty("columnName") protected String _columnName; + @JsonProperty("query") protected String _query = null; + @JsonProperty("mode") protected String _mode; + @JsonProperty("caseSensitive") protected boolean _caseSensitive; + @JsonProperty("invert") protected boolean _invert; @Override @@ -76,7 +84,7 @@ public class TextSearchFacet implements Facet { writer.key("caseSensitive"); writer.value(_caseSensitive); writer.key("invert"); writer.value(_invert); writer.key("type"); writer.value("text"); - writer.endObject(); + writer.endObject(); } @Override @@ -97,6 +105,11 @@ public class TextSearchFacet implements Facet { } _invert = o.has("invert") && o.getBoolean("invert"); } + + @Override + public String getJsonType() { + return "text"; + } } TextSearchFacetConfig _config = new TextSearchFacetConfig(); @@ -109,7 +122,37 @@ public class TextSearchFacet implements Facet { public TextSearchFacet() { } - + + @JsonProperty("name") + public String getName() { + return _config._name; + } + + @JsonProperty("columnName") + public String getColumnName() { + return _config._columnName; + } + + @JsonProperty("query") + public String getQuery() { + return _config._query; + } + + @JsonProperty("mode") + public String getMode() { + return _config._mode; + } + + @JsonProperty("caseSensitive") + public boolean isCaseSensitive() { + return _config._caseSensitive; + } + + @JsonProperty("invert") + public boolean isInverted() { + return _config._invert; + } + @Override public void write(JSONWriter writer, Properties options) throws JSONException { diff --git a/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java b/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java index 30e1ece0c..98cd0d1ee 100644 --- a/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java +++ b/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java @@ -39,6 +39,11 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RecordFilter; @@ -63,18 +68,28 @@ public class TimeRangeFacet implements Facet { * Configuration, from the client side */ public static class TimeRangeFacetConfig implements FacetConfig { + @JsonProperty("name") protected String _name; // name of facet + @JsonProperty("expression") protected String _expression; // expression to compute numeric value(s) per row + @JsonProperty("columnName") protected String _columnName; // column to base expression on, if any + @JsonProperty(FROM) protected double _from; // the numeric selection + @JsonProperty(TO) protected double _to; + @JsonProperty("selectTime") protected boolean _selectTime; // whether the time selection applies, default true + @JsonProperty("selectNonTime") protected boolean _selectNonTime; + @JsonProperty("selectBlank") protected boolean _selectBlank; + @JsonProperty("selectError") protected boolean _selectError; + @JsonIgnore protected boolean _selected; // false if we're certain that all rows will match // and there isn't any filtering to do @@ -123,6 +138,11 @@ public class TimeRangeFacet implements Facet { facet.initializeFromConfig(this, project); return facet; } + + @Override + public String getJsonType() { + return "timerange"; + } } protected TimeRangeFacetConfig _config; @@ -142,14 +162,22 @@ public class TimeRangeFacet implements Facet { /* * Computed data */ + @JsonProperty("baseTimeCount") protected int _baseTimeCount; + @JsonProperty("baseNonTimeCount") protected int _baseNonTimeCount; + @JsonProperty("baseBlankCount") protected int _baseBlankCount; + @JsonProperty("baseErrorCount") protected int _baseErrorCount; - + + @JsonProperty("timeCount") protected int _timeCount; + @JsonProperty("nonTimeCount") protected int _nonTimeCount; + @JsonProperty("blankCount") protected int _blankCount; + @JsonProperty("errorCount") protected int _errorCount; protected static final String MIN = "min"; @@ -157,6 +185,87 @@ public class TimeRangeFacet implements Facet { protected static final String TO = "to"; protected static final String FROM = "from"; + @JsonProperty("name") + public String getName() { + return _config._name; + } + + @JsonProperty("expression") + public String getExpression() { + return _config._expression; + } + + @JsonProperty("columnName") + public String getColumnName() { + return _config._columnName; + } + + @JsonProperty("error") + @JsonInclude(Include.NON_NULL) + public String getError() { + return _errorMessage; + } + + @JsonProperty(MIN) + @JsonInclude(Include.NON_NULL) + public Double getMin() { + if(getError() == null) { + return _min; + } + return null; + } + + @JsonProperty(MAX) + @JsonInclude(Include.NON_NULL) + public Double getMax() { + if(getError() == null) { + return _max; + } + return null; + } + + @JsonProperty("step") + @JsonInclude(Include.NON_NULL) + public Double getStep() { + return _step; + } + + @JsonProperty("bins") + @JsonInclude(Include.NON_NULL) + public int[] getBins() { + if (getError() == null) { + return _bins; + } + return null; + } + + @JsonProperty("baseBins") + @JsonInclude(Include.NON_NULL) + public int[] getBaseBins() { + if (getError() == null) { + return _baseBins; + } + return null; + } + + @JsonProperty(FROM) + @JsonInclude(Include.NON_NULL) + public Double getFrom() { + if (getError() == null) { + return _config._from; + } + return null; + } + + @JsonProperty(TO) + @JsonInclude(Include.NON_NULL) + public Double getTo() { + if (getError() == null) { + return _config._to; + } + return null; + } + @Override public void write(JSONWriter writer, Properties options) throws JSONException { @@ -169,9 +278,9 @@ public class TimeRangeFacet implements Facet { writer.key("error"); writer.value(_errorMessage); } else { if (!Double.isInfinite(_min) && !Double.isInfinite(_max)) { - writer.key(MIN); writer.value(_min); - writer.key(MAX); writer.value(_max); - writer.key("step"); writer.value(_step); + writer.key(MIN); writer.value((long)_min); + writer.key(MAX); writer.value((long)_max); + writer.key("step"); writer.value((long)_step); writer.key("bins"); writer.array(); for (int b : _bins) { @@ -185,8 +294,8 @@ public class TimeRangeFacet implements Facet { } writer.endArray(); - writer.key(FROM); writer.value(_config._from); - writer.key(TO); writer.value(_config._to); + writer.key(FROM); writer.value((long)_config._from); + writer.key(TO); writer.value((long)_config._to); } writer.key("baseTimeCount"); writer.value(_baseTimeCount); diff --git a/main/src/com/google/refine/util/SerializationFilters.java b/main/src/com/google/refine/util/SerializationFilters.java index c8752c22f..646892b3e 100644 --- a/main/src/com/google/refine/util/SerializationFilters.java +++ b/main/src/com/google/refine/util/SerializationFilters.java @@ -66,8 +66,8 @@ public class SerializationFilters { @Override public void serialize(Double arg0, JsonGenerator gen, SerializerProvider s) throws IOException { - if (new Double(arg0.intValue()).equals(arg0)) { - gen.writeNumber(arg0.intValue()); + if (new Double(arg0.longValue()).equals(arg0)) { + gen.writeNumber(arg0.longValue()); } else { gen.writeNumber(arg0); } diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java index f95c22ceb..16794c035 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java @@ -20,13 +20,13 @@ public class TimeRangeFacetTests extends RefineTest { + "\"name\":\"my column\"," + "\"expression\":\"value\"," + "\"columnName\":\"my column\"," - + "\"min\":1.199329445E12," - + "\"max\":1.51496695E12," - + "\"step\":3.1556952E10," + + "\"min\":1199329445000," + + "\"max\":1514966950000," + + "\"step\":31556952000," + "\"bins\":[1,0,0,0,1,0,0,0,0,0,1]," + "\"baseBins\":[1,0,0,0,1,0,0,0,0,0,1]," - + "\"from\":1.262443349E12," - + "\"to\":1.51496695E12," + + "\"from\":1262443349000," + + "\"to\":1514966950000," + "\"baseTimeCount\":3," + "\"baseNonTimeCount\":1," + "\"baseBlankCount\":0," diff --git a/main/tests/server/src/com/google/refine/tests/util/TestUtils.java b/main/tests/server/src/com/google/refine/tests/util/TestUtils.java index 0e00b7e0c..68f51e3fd 100644 --- a/main/tests/server/src/com/google/refine/tests/util/TestUtils.java +++ b/main/tests/server/src/com/google/refine/tests/util/TestUtils.java @@ -21,7 +21,6 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.google.refine.Jsonizable; import com.google.refine.util.JSONUtilities; -import com.google.refine.util.JsonViews; import com.google.refine.util.ParsingUtilities; From cf45f23e1d77a6b5bab38bfb503d85e2c317b132 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 28 Sep 2018 09:18:52 +0100 Subject: [PATCH 011/164] Jackson serialization for reconciliation operations --- .../commands/recon/ExtendDataCommand.java | 7 +- .../recon/PreviewExtendDataCommand.java | 14 +- .../recon/ReconMatchSpecificTopicCommand.java | 6 +- .../recon/ReconciledDataExtensionJob.java | 186 ++++++++++++++---- .../operations/recon/ExtendDataOperation.java | 42 ++-- .../ReconClearSimilarCellsOperation.java | 12 ++ .../ReconCopyAcrossColumnsOperation.java | 22 +++ .../recon/ReconDiscardJudgmentsOperation.java | 12 ++ .../ReconJudgeSimilarCellsOperation.java | 32 ++- .../recon/ReconMarkNewTopicsOperation.java | 12 ++ .../ReconMatchBestCandidatesOperation.java | 7 + .../ReconMatchSpecificTopicOperation.java | 43 +++- .../operations/recon/ReconOperation.java | 12 ++ .../recon/ExtendDataOperationTests.java | 55 +++++- .../ReconJudgeSimilarCellsOperationTests.java | 6 +- .../recon/ReconJudgeSimilarCellsTests.java | 14 +- .../operations/recon/ReconOperationTests.java | 3 + 17 files changed, 388 insertions(+), 97 deletions(-) diff --git a/main/src/com/google/refine/commands/recon/ExtendDataCommand.java b/main/src/com/google/refine/commands/recon/ExtendDataCommand.java index 292ae79f2..30adcb526 100644 --- a/main/src/com/google/refine/commands/recon/ExtendDataCommand.java +++ b/main/src/com/google/refine/commands/recon/ExtendDataCommand.java @@ -35,13 +35,12 @@ package com.google.refine.commands.recon; import javax.servlet.http.HttpServletRequest; -import org.json.JSONObject; - import com.google.refine.browsing.EngineConfig; import com.google.refine.commands.EngineDependentCommand; -import com.google.refine.operations.recon.ExtendDataOperation; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; +import com.google.refine.model.recon.ReconciledDataExtensionJob.DataExtensionConfig; +import com.google.refine.operations.recon.ExtendDataOperation; import com.google.refine.util.ParsingUtilities; public class ExtendDataCommand extends EngineDependentCommand { @@ -56,7 +55,7 @@ public class ExtendDataCommand extends EngineDependentCommand { String schemaSpace = request.getParameter("schemaSpace"); String jsonString = request.getParameter("extension"); - JSONObject extension = ParsingUtilities.evaluateJsonStringToObject(jsonString); + DataExtensionConfig extension = DataExtensionConfig.reconstruct(ParsingUtilities.evaluateJsonStringToObject(jsonString)); return new ExtendDataOperation( engineConfig, diff --git a/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java b/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java index 037b1e87d..f0c6906a7 100644 --- a/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java +++ b/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java @@ -46,19 +46,19 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.json.JSONArray; -import org.json.JSONObject; import org.json.JSONWriter; import com.google.refine.commands.Command; -import com.google.refine.model.recon.ReconciledDataExtensionJob; -import com.google.refine.model.recon.ReconciledDataExtensionJob.ColumnInfo; -import com.google.refine.model.recon.ReconciledDataExtensionJob.DataExtension; import com.google.refine.model.Cell; +import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.ReconCandidate; import com.google.refine.model.Row; -import com.google.refine.model.Column; import com.google.refine.model.recon.ReconConfig; +import com.google.refine.model.recon.ReconciledDataExtensionJob; +import com.google.refine.model.recon.ReconciledDataExtensionJob.ColumnInfo; +import com.google.refine.model.recon.ReconciledDataExtensionJob.DataExtension; +import com.google.refine.model.recon.ReconciledDataExtensionJob.DataExtensionConfig; import com.google.refine.model.recon.StandardReconConfig; import com.google.refine.util.ParsingUtilities; @@ -79,7 +79,7 @@ public class PreviewExtendDataCommand extends Command { } String jsonString = request.getParameter("extension"); - JSONObject json = ParsingUtilities.evaluateJsonStringToObject(jsonString); + DataExtensionConfig config = DataExtensionConfig.reconstruct(ParsingUtilities.evaluateJsonStringToObject(jsonString)); JSONArray rowIndices = ParsingUtilities.evaluateJsonStringToArray(rowIndicesString); int length = rowIndices.length(); @@ -120,7 +120,7 @@ public class PreviewExtendDataCommand extends Command { } Map reconCandidateMap = new HashMap(); - ReconciledDataExtensionJob job = new ReconciledDataExtensionJob(json, endpoint); + ReconciledDataExtensionJob job = new ReconciledDataExtensionJob(config, endpoint); Map map = job.extend(ids, reconCandidateMap); response.setCharacterEncoding("UTF-8"); diff --git a/main/src/com/google/refine/commands/recon/ReconMatchSpecificTopicCommand.java b/main/src/com/google/refine/commands/recon/ReconMatchSpecificTopicCommand.java index 18ca0b9f5..0951f1c27 100644 --- a/main/src/com/google/refine/commands/recon/ReconMatchSpecificTopicCommand.java +++ b/main/src/com/google/refine/commands/recon/ReconMatchSpecificTopicCommand.java @@ -39,7 +39,6 @@ import com.google.refine.browsing.EngineConfig; import com.google.refine.commands.EngineDependentCommand; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; -import com.google.refine.model.ReconCandidate; import com.google.refine.operations.recon.ReconMatchSpecificTopicOperation; public class ReconMatchSpecificTopicCommand extends EngineDependentCommand { @@ -49,11 +48,10 @@ public class ReconMatchSpecificTopicCommand extends EngineDependentCommand { HttpServletRequest request, EngineConfig engineConfig) throws Exception { String columnName = request.getParameter("columnName"); - ReconCandidate match = new ReconCandidate( + ReconMatchSpecificTopicOperation.ReconItem match = new ReconMatchSpecificTopicOperation.ReconItem( request.getParameter("topicID"), request.getParameter("topicName"), - request.getParameter("types").split(","), - 100 + request.getParameter("types").split(",") ); return new ReconMatchSpecificTopicOperation( diff --git a/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java b/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java index 07f994842..2d971a06d 100644 --- a/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java +++ b/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java @@ -39,7 +39,6 @@ package com.google.refine.model.recon; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.Serializable; import java.io.StringWriter; import java.io.Writer; import java.net.URL; @@ -48,21 +47,155 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; +import java.util.stream.Collectors; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; -import com.google.refine.model.ReconType; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.ObjectMapper; + +import com.google.refine.Jsonizable; +import com.google.refine.expr.functions.ToDate; import com.google.refine.model.ReconCandidate; -import com.google.refine.model.recon.StandardReconConfig; +import com.google.refine.model.ReconType; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; -import com.google.refine.expr.functions.ToDate; public class ReconciledDataExtensionJob { + + + static public class DataExtensionProperty implements Jsonizable { + @JsonProperty("id") + public final String id; + @JsonProperty("name") + public final String name; + @JsonProperty("settings") + @JsonInclude(Include.NON_NULL) + public final Map settings; + + @JsonCreator + public DataExtensionProperty( + @JsonProperty("id") + String id, + @JsonProperty("name") + String name, + @JsonProperty("settings") + Map settings) { + this.id = id; + this.name = name; + this.settings = settings; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("id"); writer.value(id); + if(!"query".equals(options.getProperty("mode"))) { + writer.key("name"); writer.value(name); + } + if (settings != null) { + writer.key("settings"); + writer.object(); + for(Map.Entry entry : settings.entrySet()) { + writer.key(entry.getKey()); + writer.value(entry.getValue()); + } + writer.endObject(); + } + writer.endObject(); + } + + } + + static public class DataExtensionConfig implements Jsonizable { + + @JsonProperty("properties") + public final List properties; + + @JsonCreator + public DataExtensionConfig( + @JsonProperty("properties") + List properties) { + this.properties = properties; + } + + public static DataExtensionConfig reconstruct(JSONObject obj) throws JSONException { + ObjectMapper mapper = new ObjectMapper(); + try { + return mapper.readValue(obj.toString(), DataExtensionConfig.class); + } catch(IOException e) { + throw new JSONException(e.toString()); + } + } + + @Override + public void write(JSONWriter jsonWriter, Properties options) + throws JSONException { + jsonWriter.object(); + jsonWriter.key("properties"); + jsonWriter.array(); + + for (DataExtensionProperty property : properties) { + property.write(jsonWriter, options); + } + jsonWriter.endArray(); + jsonWriter.endObject(); + } + + } + + static public class DataExtensionQuery extends DataExtensionConfig { + + @JsonProperty("ids") + public final List ids; + + @JsonCreator + public DataExtensionQuery( + @JsonProperty("ids") + List ids, + @JsonProperty("properties") + List properties) { + super(properties); + this.ids = ids; + } + + @Override + public void write(JSONWriter jsonWriter, Properties options) + throws JSONException { + jsonWriter.object(); + + if(ids != null) { + jsonWriter.key("ids"); + jsonWriter.array(); + for (String id : ids) { + if (id != null) { + jsonWriter.value(id); + } + } + jsonWriter.endArray(); + } + + jsonWriter.key("properties"); + jsonWriter.array(); + + for (DataExtensionProperty property : properties) { + property.write(jsonWriter, options); + } + jsonWriter.endArray(); + jsonWriter.endObject(); + } + + } + static public class DataExtension { final public Object[][] data; @@ -83,11 +216,11 @@ public class ReconciledDataExtensionJob { } } - final public JSONObject extension; - final public String endpoint; - final public List columns = new ArrayList(); + final public DataExtensionConfig extension; + final public String endpoint; + final public List columns = new ArrayList(); - public ReconciledDataExtensionJob(JSONObject obj, String endpoint) throws JSONException { + public ReconciledDataExtensionJob(DataExtensionConfig obj, String endpoint) throws JSONException { this.extension = obj; this.endpoint = endpoint; } @@ -249,39 +382,12 @@ public class ReconciledDataExtensionJob { } - static protected void formulateQuery(Set ids, JSONObject node, Writer writer) throws JSONException { + static protected void formulateQuery(Set ids, DataExtensionConfig node, Writer writer) throws JSONException { JSONWriter jsonWriter = new JSONWriter(writer); - - jsonWriter.object(); - - jsonWriter.key("ids"); - jsonWriter.array(); - for (String id : ids) { - if (id != null) { - jsonWriter.value(id); - } - } - jsonWriter.endArray(); - - jsonWriter.key("properties"); - jsonWriter.array(); - JSONArray properties = node.getJSONArray("properties"); - int l = properties.length(); - - for (int i = 0; i < l; i++) { - JSONObject property = properties.getJSONObject(i); - jsonWriter.object(); - jsonWriter.key("id"); - jsonWriter.value(property.getString("id")); - if (property.has("settings")) { - JSONObject settings = property.getJSONObject("settings"); - jsonWriter.key("settings"); - jsonWriter.value(settings); - } - jsonWriter.endObject(); - } - jsonWriter.endArray(); - jsonWriter.endObject(); + Properties options = new Properties(); + DataExtensionQuery query = new DataExtensionQuery(ids.stream().collect(Collectors.toList()), node.properties); + options.setProperty("mode", "query"); + query.write(jsonWriter, options); } static protected void gatherColumnInfo(JSONArray meta, List columns) throws JSONException { diff --git a/main/src/com/google/refine/operations/recon/ExtendDataOperation.java b/main/src/com/google/refine/operations/recon/ExtendDataOperation.java index ae00cb5fd..4905bc682 100644 --- a/main/src/com/google/refine/operations/recon/ExtendDataOperation.java +++ b/main/src/com/google/refine/operations/recon/ExtendDataOperation.java @@ -45,6 +45,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; @@ -62,41 +64,51 @@ import com.google.refine.model.changes.DataExtensionChange; import com.google.refine.model.recon.ReconciledDataExtensionJob; import com.google.refine.model.recon.ReconciledDataExtensionJob.ColumnInfo; import com.google.refine.model.recon.ReconciledDataExtensionJob.DataExtension; +import com.google.refine.model.recon.ReconciledDataExtensionJob.DataExtensionConfig; import com.google.refine.operations.EngineDependentOperation; import com.google.refine.operations.OperationRegistry; import com.google.refine.process.LongRunningProcess; import com.google.refine.process.Process; public class ExtendDataOperation extends EngineDependentOperation { - final protected String _baseColumnName; - final protected String _endpoint; - final protected String _identifierSpace; - final protected String _schemaSpace; - final protected JSONObject _extension; - final protected int _columnInsertIndex; + @JsonProperty("baseColumnName") + final protected String _baseColumnName; + @JsonProperty("endpoint") + final protected String _endpoint; + @JsonProperty("identifierSpace") + final protected String _identifierSpace; + @JsonProperty("schemaSpace") + final protected String _schemaSpace; + @JsonProperty("extension") + final protected DataExtensionConfig _extension; + @JsonProperty("columnInsertIndex") + final protected int _columnInsertIndex; + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { JSONObject engineConfig = obj.getJSONObject("engineConfig"); + DataExtensionConfig dataExtensionConfig = DataExtensionConfig.reconstruct(obj.getJSONObject("extension")); + return new ExtendDataOperation( EngineConfig.reconstruct(engineConfig), obj.getString("baseColumnName"), obj.getString("endpoint"), obj.getString("identifierSpace"), obj.getString("schemaSpace"), - obj.getJSONObject("extension"), + dataExtensionConfig, obj.getInt("columnInsertIndex") ); } public ExtendDataOperation( - EngineConfig engineConfig, - String baseColumnName, - String endpoint, - String identifierSpace, - String schemaSpace, - JSONObject extension, - int columnInsertIndex + EngineConfig engineConfig, + String baseColumnName, + String endpoint, + String identifierSpace, + String schemaSpace, + DataExtensionConfig extension, + int columnInsertIndex ) { super(engineConfig); @@ -121,7 +133,7 @@ public class ExtendDataOperation extends EngineDependentOperation { writer.key("endpoint"); writer.value(_endpoint); writer.key("identifierSpace"); writer.value(_identifierSpace); writer.key("schemaSpace"); writer.value(_schemaSpace); - writer.key("extension"); writer.value(_extension); + writer.key("extension"); _extension.write(writer, options); writer.endObject(); } diff --git a/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java b/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java index bebb80494..2b30ce3aa 100644 --- a/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java @@ -40,6 +40,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; @@ -88,6 +90,16 @@ public class ReconClearSimilarCellsOperation extends EngineDependentMassCellOper writer.endObject(); } + @JsonProperty("columnName") + public String getColumnName() { + return _columnName; + } + + @JsonProperty("similarValue") + public String getSimilarValue() { + return _similarValue; + } + @Override protected String getBriefDescription(Project project) { return "Clear recon data for cells containing \"" + diff --git a/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java b/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java index 6141fa136..5d8c5c237 100644 --- a/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java @@ -46,6 +46,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; @@ -118,6 +120,26 @@ public class ReconCopyAcrossColumnsOperation extends EngineDependentOperation { writer.key("applyToJudgedCells"); writer.value(_applyToJudgedCells); writer.endObject(); } + + @JsonProperty("fromColumnName") + public String getFromColumnName() { + return _fromColumnName; + } + + @JsonProperty("toColumnNames") + public String[] getToColumnNames() { + return _toColumnNames; + } + + @JsonProperty("judgments") + public String[] getJudgments() { + return _judgments; + } + + @JsonProperty("applyToJudgedCells") + public boolean getApplyToJudgedCells() { + return _applyToJudgedCells; + } @Override protected HistoryEntry createHistoryEntry(final Project project, final long historyEntryID) throws Exception { diff --git a/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java b/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java index 1873962a9..c95524805 100644 --- a/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java @@ -42,6 +42,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; @@ -86,6 +88,16 @@ public class ReconDiscardJudgmentsOperation extends EngineDependentMassCellOpera writer.key("clearData"); writer.value(_clearData); writer.endObject(); } + + @JsonProperty("columnName") + public String getColumnName() { + return _columnName; + } + + @JsonProperty("clearData") + public boolean getClearData() { + return _clearData; + } @Override protected String getBriefDescription(Project project) { diff --git a/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java b/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java index a3fc92e32..5afc6ce98 100644 --- a/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java @@ -43,6 +43,10 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.expr.ExpressionUtils; @@ -67,7 +71,7 @@ public class ReconJudgeSimilarCellsOperation extends EngineDependentMassCellOper final protected ReconCandidate _match; final protected boolean _shareNewTopics; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { + static public AbstractOperation reconstruct(JSONObject obj) throws JSONException { JSONObject engineConfig = obj.getJSONObject("engineConfig"); ReconCandidate match = null; @@ -137,6 +141,32 @@ public class ReconJudgeSimilarCellsOperation extends EngineDependentMassCellOper writer.endObject(); } + @JsonProperty("columnName") + public String getColumnName() { + return _columnName; + } + + @JsonProperty("similarValue") + public String getSimilarValue() { + return _similarValue; + } + + @JsonProperty("judgment") + public Judgment getJudgment() { + return _judgment; + } + + @JsonProperty("match") + @JsonInclude(Include.NON_NULL) + public ReconCandidate getMatch() { + return _match; + } + + @JsonProperty("shareNewTopics") + public boolean getShareNewTopics() { + return _shareNewTopics; + } + @Override protected String getBriefDescription(Project project) { if (_judgment == Judgment.None) { diff --git a/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java b/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java index cecba3833..363b52564 100644 --- a/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java @@ -42,6 +42,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; @@ -89,6 +91,16 @@ public class ReconMarkNewTopicsOperation extends EngineDependentMassCellOperatio writer.endObject(); } + @JsonProperty("columnName") + public String getColumnName() { + return _columnName; + } + + @JsonProperty("shareNewTopics") + public boolean getShareNewTopics() { + return _shareNewTopics; + } + @Override protected String getBriefDescription(Project project) { return "Mark to create new items for cells in column " + _columnName + diff --git a/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java b/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java index 050eca7b3..c17bf4346 100644 --- a/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java @@ -42,6 +42,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; @@ -84,6 +86,11 @@ public class ReconMatchBestCandidatesOperation extends EngineDependentMassCellOp writer.key("columnName"); writer.value(_columnName); writer.endObject(); } + + @JsonProperty + public String getColumnName() { + return _columnName; + } @Override protected String getBriefDescription(Project project) { diff --git a/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java b/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java index 1bf466eb7..1dce15216 100644 --- a/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java @@ -43,6 +43,10 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; @@ -60,8 +64,35 @@ import com.google.refine.operations.EngineDependentMassCellOperation; import com.google.refine.operations.OperationRegistry; public class ReconMatchSpecificTopicOperation extends EngineDependentMassCellOperation { - final protected ReconCandidate match; + + public static class ReconItem { + @JsonProperty("id") + public final String id; + @JsonProperty("name") + public final String name; + @JsonProperty("types") + public final String[] types; + @JsonCreator + public ReconItem( + @JsonProperty("id") String id, + @JsonProperty("name") String name, + @JsonProperty("types") String[] types) { + this.id = id; + this.name = name; + this.types = types; + } + + @JsonIgnore + public ReconCandidate getCandidate() { + return new ReconCandidate(id, name, types, 100); + } + } + + @JsonProperty("match") + final protected ReconItem match; + @JsonProperty("identifierSpace") final protected String identifierSpace; + @JsonProperty("schemaSpace") final protected String schemaSpace; static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { @@ -78,11 +109,10 @@ public class ReconMatchSpecificTopicOperation extends EngineDependentMassCellOpe return new ReconMatchSpecificTopicOperation( EngineConfig.reconstruct(engineConfig), obj.getString("columnName"), - new ReconCandidate( + new ReconItem( match.getString("id"), match.getString("name"), - typeIDs, - 100 + typeIDs ), obj.getString("identifierSpace"), obj.getString("schemaSpace") @@ -92,7 +122,7 @@ public class ReconMatchSpecificTopicOperation extends EngineDependentMassCellOpe public ReconMatchSpecificTopicOperation( EngineConfig engineConfig, String columnName, - ReconCandidate match, + ReconItem match, String identifierSpace, String schemaSpace ) { @@ -146,6 +176,7 @@ public class ReconMatchSpecificTopicOperation extends EngineDependentMassCellOpe @Override protected RowVisitor createRowVisitor(Project project, List cellChanges, long historyEntryID) throws Exception { Column column = project.columnModel.getColumnByName(_columnName); + ReconCandidate candidate = match.getCandidate(); return new RowVisitor() { int cellIndex; @@ -188,7 +219,7 @@ public class ReconMatchSpecificTopicOperation extends EngineDependentMassCellOpe identifierSpace, schemaSpace); - newRecon.match = match; + newRecon.match = candidate; newRecon.matchRank = -1; newRecon.judgment = Judgment.Matched; newRecon.judgmentAction = "mass"; diff --git a/main/src/com/google/refine/operations/recon/ReconOperation.java b/main/src/com/google/refine/operations/recon/ReconOperation.java index 87e9c4972..567fb6cef 100644 --- a/main/src/com/google/refine/operations/recon/ReconOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconOperation.java @@ -45,6 +45,8 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; @@ -120,6 +122,16 @@ public class ReconOperation extends EngineDependentOperation { writer.key("engineConfig"); getEngineConfig().write(writer, options); writer.endObject(); } + + @JsonProperty("config") + public ReconConfig getReconConfig() { + return _reconConfig; + } + + @JsonProperty("columnName") + public String getColumnName() { + return _columnName; + } static protected class ReconEntry { final public int rowIndex; diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java index d41618800..111da8f76 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java @@ -36,9 +36,12 @@ package com.google.refine.tests.operations.recon; import static org.mockito.Mockito.mock; import java.io.IOException; +import java.io.StringWriter; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Properties; +import java.util.Set; import org.json.JSONException; import org.json.JSONObject; @@ -57,11 +60,13 @@ import com.google.refine.model.Project; import com.google.refine.model.Recon; import com.google.refine.model.ReconCandidate; import com.google.refine.model.Row; -import com.google.refine.process.Process; -import com.google.refine.process.ProcessManager; +import com.google.refine.model.recon.ReconciledDataExtensionJob; +import com.google.refine.model.recon.ReconciledDataExtensionJob.DataExtensionConfig; import com.google.refine.operations.EngineDependentOperation; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.recon.ExtendDataOperation; +import com.google.refine.process.Process; +import com.google.refine.process.ProcessManager; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; @@ -72,6 +77,26 @@ public class ExtendDataOperationTests extends RefineTest { static final String RECON_SERVICE = "https://tools.wmflabs.org/openrefine-wikidata/en/api"; static final String RECON_IDENTIFIER_SPACE = "http://www.wikidata.org/entity/"; static final String RECON_SCHEMA_SPACE = "http://www.wikidata.org/prop/direct/"; + + private String dataExtensionConfigJson = "{" + + " \"properties\":[" + + " {\"name\":\"inception\",\"id\":\"P571\"}," + + " {\"name\":\"headquarters location\",\"id\":\"P159\"}," + + " {\"name\":\"coordinate location\",\"id\":\"P625\"}" + + " ]" + + "}"; + + static public class ReconciledDataExtensionJobStub extends ReconciledDataExtensionJob { + public ReconciledDataExtensionJobStub(DataExtensionConfig obj, String endpoint) throws JSONException { + super(obj, endpoint); + } + + public String formulateQueryStub(Set ids, DataExtensionConfig node) throws JSONException { + StringWriter writer = new StringWriter(); + super.formulateQuery(ids, node, writer); + return writer.toString(); + } + } @Override @BeforeTest @@ -132,6 +157,21 @@ public class ExtendDataOperationTests extends RefineTest { + "}}"; TestUtils.isSerializedTo(ExtendDataOperation.reconstruct(project, new JSONObject(json)), json); } + + @Test + public void serializeDataExtensionConfig() { + TestUtils.isSerializedTo(DataExtensionConfig.reconstruct(new JSONObject(dataExtensionConfigJson)), dataExtensionConfigJson); + } + + @Test + public void testFormulateQuery() { + DataExtensionConfig config = DataExtensionConfig.reconstruct(new JSONObject(dataExtensionConfigJson)); + Set ids = Collections.singleton("Q2"); + String json = "{\"ids\":[\"Q2\"],\"properties\":[{\"id\":\"P571\"},{\"id\":\"P159\"},{\"id\":\"P625\"}]}"; + ReconciledDataExtensionJobStub stub = new ReconciledDataExtensionJobStub(config, "http://endpoint"); + TestUtils.assertEqualAsJson(json, stub.formulateQueryStub(ids, config)); + } + @AfterMethod public void TearDown() { @@ -157,7 +197,7 @@ public class ExtendDataOperationTests extends RefineTest { @Test public void testFetchStrings() throws Exception { - JSONObject extension = new JSONObject("{\"properties\":[{\"id\":\"P297\",\"name\":\"ISO 3166-1 alpha-2 code\"}]}"); + DataExtensionConfig extension = DataExtensionConfig.reconstruct(new JSONObject("{\"properties\":[{\"id\":\"P297\",\"name\":\"ISO 3166-1 alpha-2 code\"}]}")); EngineDependentOperation op = new ExtendDataOperation(engine_config, "country", @@ -194,7 +234,8 @@ public class ExtendDataOperationTests extends RefineTest { @Test public void testFetchCounts() throws Exception { - JSONObject extension = new JSONObject("{\"properties\":[{\"id\":\"P38\",\"name\":\"currency\",\"settings\":{\"count\":\"on\",\"rank\":\"any\"}}]}"); + DataExtensionConfig extension = DataExtensionConfig.reconstruct( + new JSONObject("{\"properties\":[{\"id\":\"P38\",\"name\":\"currency\",\"settings\":{\"count\":\"on\",\"rank\":\"any\"}}]}")); EngineDependentOperation op = new ExtendDataOperation(engine_config, "country", @@ -228,7 +269,8 @@ public class ExtendDataOperationTests extends RefineTest { */ @Test public void testFetchCurrent() throws Exception { - JSONObject extension = new JSONObject("{\"properties\":[{\"id\":\"P38\",\"name\":\"currency\",\"settings\":{\"rank\":\"best\"}}]}"); + DataExtensionConfig extension = DataExtensionConfig.reconstruct( + new JSONObject("{\"properties\":[{\"id\":\"P38\",\"name\":\"currency\",\"settings\":{\"rank\":\"best\"}}]}")); EngineDependentOperation op = new ExtendDataOperation(engine_config, "country", @@ -268,7 +310,8 @@ public class ExtendDataOperationTests extends RefineTest { */ @Test public void testFetchRecord() throws Exception { - JSONObject extension = new JSONObject("{\"properties\":[{\"id\":\"P38\",\"name\":\"currency\",\"settings\":{\"rank\":\"any\"}}]}"); + DataExtensionConfig extension = DataExtensionConfig.reconstruct( + new JSONObject("{\"properties\":[{\"id\":\"P38\",\"name\":\"currency\",\"settings\":{\"rank\":\"any\"}}]}")); EngineDependentOperation op = new ExtendDataOperation(engine_config, "country", diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsOperationTests.java index 117193d58..4662cd016 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsOperationTests.java @@ -1,11 +1,8 @@ package com.google.refine.tests.operations.recon; -import static org.mockito.Mockito.mock; - import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.recon.ReconJudgeSimilarCellsOperation; import com.google.refine.tests.RefineTest; @@ -27,7 +24,6 @@ public class ReconJudgeSimilarCellsOperationTests extends RefineTest { + "\"judgment\":\"matched\"," + "\"match\":{\"id\":\"Q7884717\",\"name\":\"Unicef Indonesia\",\"score\":71.42857142857143,\"types\":[\"Q43229\"]}," + "\"shareNewTopics\":false}"; - Project project = mock(Project.class); - TestUtils.isSerializedTo(ReconJudgeSimilarCellsOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ReconJudgeSimilarCellsOperation.reconstruct(new JSONObject(json)), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java index 5d9f2e063..413797e7f 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java @@ -6,6 +6,7 @@ import static org.junit.Assert.assertNull; import java.util.Collections; import java.util.Properties; +import org.json.JSONException; import org.json.JSONObject; import org.slf4j.LoggerFactory; import org.testng.annotations.BeforeTest; @@ -37,20 +38,15 @@ public class ReconJudgeSimilarCellsTests extends RefineTest { } @Test - public void serializeReconJudgeSimilarCellsOperation() { - AbstractOperation op = new ReconJudgeSimilarCellsOperation( - ENGINE_CONFIG, - "A", - "foo", - Recon.Judgment.New, - null, true); - TestUtils.isSerializedTo(op, "{\"op\":\"core/recon-judge-similar-cells\"," + public void serializeReconJudgeSimilarCellsOperation() throws JSONException { + String json = "{\"op\":\"core/recon-judge-similar-cells\"," + "\"description\":\"Mark to create one single new item for all cells containing \\\"foo\\\" in column A\"," + "\"engineConfig\":{\"mode\":\"row-based\",\"facets\":[]}," + "\"columnName\":\"A\"," + "\"similarValue\":\"foo\"," + "\"judgment\":\"new\"," - + "\"shareNewTopics\":true}"); + + "\"shareNewTopics\":true}"; + TestUtils.isSerializedTo(ReconJudgeSimilarCellsOperation.reconstruct(new JSONObject(json)), json); } @Test diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconOperationTests.java index d5f16b420..4da313b37 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconOperationTests.java @@ -8,6 +8,8 @@ import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; import com.google.refine.model.Project; +import com.google.refine.model.recon.ReconConfig; +import com.google.refine.model.recon.StandardReconConfig; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.recon.ReconOperation; import com.google.refine.tests.RefineTest; @@ -18,6 +20,7 @@ public class ReconOperationTests extends RefineTest { @BeforeSuite public void registerOperation() { OperationRegistry.registerOperation(getCoreModule(), "recon", ReconOperation.class); + ReconConfig.registerReconConfig(getCoreModule(), "standard-service", StandardReconConfig.class); } @Test From 49f1367adc318977cf2d4afbfdf2d235b4c77cf4 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 28 Sep 2018 10:26:43 +0100 Subject: [PATCH 012/164] Jackson serialization for clustering classes --- .../refine/clustering/ClusteredEntry.java | 27 +++++++++++++ .../refine/clustering/ClustererConfig.java | 9 +++++ .../clustering/binning/BinningClusterer.java | 39 ++++++++++++++++++- .../refine/clustering/knn/kNNClusterer.java | 31 +++++++++++++++ 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 main/src/com/google/refine/clustering/ClusteredEntry.java diff --git a/main/src/com/google/refine/clustering/ClusteredEntry.java b/main/src/com/google/refine/clustering/ClusteredEntry.java new file mode 100644 index 000000000..d7dc0d70e --- /dev/null +++ b/main/src/com/google/refine/clustering/ClusteredEntry.java @@ -0,0 +1,27 @@ +package com.google.refine.clustering; + +import java.io.Serializable; +import java.util.Comparator; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ClusteredEntry { + @JsonProperty("v") + protected final Serializable value; + @JsonProperty("c") + protected final int count; + + public ClusteredEntry( + Serializable value, + int count) { + this.value = value; + this.count = count; + } + + public static Comparator comparator = new Comparator() { + @Override + public int compare(ClusteredEntry o1, ClusteredEntry o2) { + return o2.count - o1.count; + } + }; +} diff --git a/main/src/com/google/refine/clustering/ClustererConfig.java b/main/src/com/google/refine/clustering/ClustererConfig.java index d7f5d4842..95930fd99 100644 --- a/main/src/com/google/refine/clustering/ClustererConfig.java +++ b/main/src/com/google/refine/clustering/ClustererConfig.java @@ -2,6 +2,8 @@ package com.google.refine.clustering; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.model.Project; @@ -22,6 +24,7 @@ public abstract class ClustererConfig implements Jsonizable { columnName = o.getString("column"); } + @JsonProperty("column") public String getColumnName() { return columnName; } @@ -32,4 +35,10 @@ public abstract class ClustererConfig implements Jsonizable { * @return */ public abstract Clusterer apply(Project project); + + /** + * Type string used in Json serialization + */ + @JsonProperty("type") + public abstract String getType(); } diff --git a/main/src/com/google/refine/clustering/binning/BinningClusterer.java b/main/src/com/google/refine/clustering/binning/BinningClusterer.java index 1da042dbb..7e93013d1 100644 --- a/main/src/com/google/refine/clustering/binning/BinningClusterer.java +++ b/main/src/com/google/refine/clustering/binning/BinningClusterer.java @@ -43,6 +43,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.TreeMap; +import java.util.stream.Collectors; import org.json.JSONException; import org.json.JSONObject; @@ -50,10 +51,17 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonValue; + import com.google.refine.Jsonizable; import com.google.refine.browsing.Engine; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RowVisitor; +import com.google.refine.clustering.ClusteredEntry; import com.google.refine.clustering.Clusterer; import com.google.refine.clustering.ClustererConfig; import com.google.refine.model.Cell; @@ -63,7 +71,8 @@ import com.google.refine.model.Row; public class BinningClusterer extends Clusterer { public static class BinningClustererConfig extends ClustererConfig { - + + @JsonProperty("function") private String _keyerName; private Keyer _keyer; private BinningParameters _parameters; @@ -80,10 +89,13 @@ public class BinningClusterer extends Clusterer { } } + @JsonIgnore public Keyer getKeyer() { return _keyer; } + @JsonProperty("params") + @JsonInclude(Include.NON_NULL) public BinningParameters getParameters() { return _parameters; } @@ -108,10 +120,17 @@ public class BinningClusterer extends Clusterer { clusterer.initializeFromConfig(project, this); return clusterer; } + + @Override + public String getType() { + return "binning"; + } } public static class BinningParameters implements Jsonizable { + @JsonProperty("ngram-size") + @JsonInclude(Include.NON_DEFAULT) public int ngramSize; @Override @@ -276,4 +295,22 @@ public class BinningClusterer extends Clusterer { } writer.endArray(); } + + protected static Map entryToMap(Entry entry) { + Map map = new HashMap<>(); + map.put("v", entry.getKey()); + map.put("c", entry.getValue()); + return map; + } + + @JsonValue + public List> getJsonRepresentation() { + EntriesComparator c = new EntriesComparator(); + return _clusters.stream() + .map(m -> m.entrySet().stream() + .sorted(c) + .map(e -> new ClusteredEntry(e.getKey(), e.getValue())) + .collect(Collectors.toList())) + .collect(Collectors.toList()); + } } diff --git a/main/src/com/google/refine/clustering/knn/kNNClusterer.java b/main/src/com/google/refine/clustering/knn/kNNClusterer.java index d80f05f7c..10db49280 100644 --- a/main/src/com/google/refine/clustering/knn/kNNClusterer.java +++ b/main/src/com/google/refine/clustering/knn/kNNClusterer.java @@ -44,6 +44,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.Set; +import java.util.stream.Collectors; import org.json.JSONException; import org.json.JSONObject; @@ -51,10 +52,15 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonValue; + import com.google.refine.Jsonizable; import com.google.refine.browsing.Engine; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RowVisitor; +import com.google.refine.clustering.ClusteredEntry; import com.google.refine.clustering.Clusterer; import com.google.refine.clustering.ClustererConfig; import com.google.refine.model.Cell; @@ -76,6 +82,7 @@ import edu.mit.simile.vicino.distances.PPMDistance; public class kNNClusterer extends Clusterer { public static class kNNClustererConfig extends ClustererConfig { + @JsonProperty("function") private String _distanceStr; private Distance _distance; private kNNClustererConfigParameters _parameters; @@ -105,10 +112,12 @@ public class kNNClusterer extends Clusterer { } } + @JsonIgnore public Distance getDistance() { return _distance; } + @JsonProperty("params") public kNNClustererConfigParameters getParameters() { return _parameters; } @@ -119,13 +128,20 @@ public class kNNClusterer extends Clusterer { clusterer.initializeFromConfig(project, this); return clusterer; } + + @Override + public String getType() { + return "knn"; + } } public static class kNNClustererConfigParameters implements Jsonizable { public static final double defaultRadius = 1.0d; public static final int defaultBlockingNgramSize = 6; + @JsonProperty("radius") public double radius = defaultRadius; + @JsonProperty("blocking-ngram-size") public int blockingNgramSize = defaultBlockingNgramSize; @Override @@ -302,6 +318,21 @@ public class kNNClusterer extends Clusterer { writer.endArray(); } + protected List getClusteredEntries(Set s) { + return s.stream() + .map(e -> new ClusteredEntry(e, _counts.get(e))) + .sorted(ClusteredEntry.comparator) + .collect(Collectors.toList()); + } + + @JsonValue + public List> getJsonRepresentation() { + return _clusters.stream() + .filter(m -> m.size() > 1) + .map(m -> getClusteredEntries(m)) + .collect(Collectors.toList()); + } + private void count(Serializable s) { if (_counts.containsKey(s)) { _counts.put(s, _counts.get(s) + 1); From aba8cd843042a3889541197216b359b3b85242cb Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 28 Sep 2018 16:23:02 +0100 Subject: [PATCH 013/164] Jackson serialization for processes --- .../refine/process/LongRunningProcess.java | 15 ++++++++++- .../com/google/refine/process/Process.java | 12 +++++++++ .../google/refine/process/ProcessManager.java | 27 +++++++++++++++++++ .../process/QuickHistoryEntryProcess.java | 18 ++++++++++--- .../tests/process/ProcessManagerTests.java | 16 ++++++----- 5 files changed, 78 insertions(+), 10 deletions(-) diff --git a/main/src/com/google/refine/process/LongRunningProcess.java b/main/src/com/google/refine/process/LongRunningProcess.java index b05b6e876..1e18949f4 100644 --- a/main/src/com/google/refine/process/LongRunningProcess.java +++ b/main/src/com/google/refine/process/LongRunningProcess.java @@ -38,13 +38,21 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.history.HistoryEntry; abstract public class LongRunningProcess extends Process { + @JsonProperty("description") final protected String _description; + @JsonIgnore protected ProcessManager _manager; + @JsonIgnore protected Thread _thread; + @JsonProperty("progress") protected int _progress; // out of 100 + @JsonIgnore protected boolean _canceled; protected LongRunningProcess(String description) { @@ -67,10 +75,15 @@ abstract public class LongRunningProcess extends Process { writer.key("id"); writer.value(hashCode()); writer.key("description"); writer.value(_description); writer.key("immediate"); writer.value(false); - writer.key("status"); writer.value(_thread == null ? "pending" : (_thread.isAlive() ? "running" : "done")); + writer.key("status"); writer.value(getStatus()); writer.key("progress"); writer.value(_progress); writer.endObject(); } + + @JsonProperty("status") + public String getStatus() { + return _thread == null ? "pending" : (_thread.isAlive() ? "running" : "done"); + } @Override public boolean isImmediate() { diff --git a/main/src/com/google/refine/process/Process.java b/main/src/com/google/refine/process/Process.java index 14fbef20f..8b42bab71 100644 --- a/main/src/com/google/refine/process/Process.java +++ b/main/src/com/google/refine/process/Process.java @@ -33,17 +33,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.process; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.history.HistoryEntry; public abstract class Process implements Jsonizable { + @JsonProperty("immediate") abstract public boolean isImmediate(); + @JsonIgnore abstract public boolean isRunning(); + @JsonIgnore abstract public boolean isDone(); + @JsonIgnore abstract public HistoryEntry performImmediate() throws Exception; abstract public void startPerforming(ProcessManager manager); abstract public void cancel(); + + @JsonProperty("id") + public long getId() { + return hashCode(); + } } diff --git a/main/src/com/google/refine/process/ProcessManager.java b/main/src/com/google/refine/process/ProcessManager.java index 94cf150ed..6d22177fb 100644 --- a/main/src/com/google/refine/process/ProcessManager.java +++ b/main/src/com/google/refine/process/ProcessManager.java @@ -37,18 +37,34 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Properties; +import java.util.stream.Collectors; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + import com.google.refine.Jsonizable; import com.google.refine.history.HistoryEntry; import com.google.refine.history.HistoryProcess; public class ProcessManager implements Jsonizable { + @JsonProperty("processes") protected List _processes = Collections.synchronizedList(new LinkedList()); + @JsonIgnore protected List _latestExceptions = null; + public static class ExceptionMessage { + @JsonProperty("message") + public final String message; + public ExceptionMessage(Exception e) { + message = e.getLocalizedMessage(); + } + } + public ProcessManager() { } @@ -78,6 +94,17 @@ public class ProcessManager implements Jsonizable { writer.endObject(); } + + @JsonProperty("exceptions") + @JsonInclude(Include.NON_NULL) + public List getJsonExceptions() { + if (_latestExceptions != null) { + return _latestExceptions.stream() + .map(e -> new ExceptionMessage(e)) + .collect(Collectors.toList()); + } + return null; + } public HistoryEntry queueProcess(Process process) throws Exception { if (process.isImmediate() && _processes.size() == 0) { diff --git a/main/src/com/google/refine/process/QuickHistoryEntryProcess.java b/main/src/com/google/refine/process/QuickHistoryEntryProcess.java index 96ed346b4..9d9c51726 100644 --- a/main/src/com/google/refine/process/QuickHistoryEntryProcess.java +++ b/main/src/com/google/refine/process/QuickHistoryEntryProcess.java @@ -38,6 +38,8 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.history.HistoryEntry; import com.google.refine.model.Project; @@ -58,6 +60,7 @@ abstract public class QuickHistoryEntryProcess extends Process { } @Override + @JsonProperty("immediate") public boolean isImmediate() { return true; } @@ -89,12 +92,21 @@ abstract public class QuickHistoryEntryProcess extends Process { writer.object(); writer.key("id"); writer.value(hashCode()); - writer.key("description"); writer.value(_historyEntry != null ? _historyEntry.description : _briefDescription); + writer.key("description"); writer.value(getDescription()); writer.key("immediate"); writer.value(true); - writer.key("status"); writer.value(_done ? "done" : "pending"); + writer.key("status"); writer.value(getStatus()); writer.endObject(); } - + + @JsonProperty("status") + public String getStatus() { + return _done ? "done" : "pending"; + } + + @JsonProperty("description") + public String getDescription() { + return _historyEntry != null ? _historyEntry.description : _briefDescription; + } @Override public boolean isDone() { diff --git a/main/tests/server/src/com/google/refine/tests/process/ProcessManagerTests.java b/main/tests/server/src/com/google/refine/tests/process/ProcessManagerTests.java index 2e34388c9..26e5b8f47 100644 --- a/main/tests/server/src/com/google/refine/tests/process/ProcessManagerTests.java +++ b/main/tests/server/src/com/google/refine/tests/process/ProcessManagerTests.java @@ -11,20 +11,24 @@ import com.google.refine.util.JSONUtilities; public class ProcessManagerTests { ProcessManager processManager; - Process process; + Process process1, process2; @BeforeMethod public void setUp() { processManager = new ProcessManager(); - process = new LongRunningProcessTests.LongRunningProcessStub("some description"); - + process1 = new LongRunningProcessTests.LongRunningProcessStub("some description"); + process2 = new LongRunningProcessTests.LongRunningProcessStub("some other description"); } @Test public void serializeProcessManager() throws Exception { - processManager.queueProcess(process); - String processJson = JSONUtilities.serialize(process); + processManager.queueProcess(process1); + processManager.queueProcess(process2); + processManager.onFailedProcess(process1, new IllegalArgumentException("unexpected error")); + String processJson = JSONUtilities.serialize(process2); TestUtils.isSerializedTo(processManager, "{" - + "\"processes\":["+processJson+"]}"); + + "\"processes\":["+processJson+"],\n" + + "\"exceptions\":[{\"message\":\"unexpected error\"}]" + + "}"); } } From 418b21dda2ac0bf790f15905058dadda4cddcd19 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 28 Sep 2018 16:24:01 +0100 Subject: [PATCH 014/164] Jackson serialization for history classes --- .../com/google/refine/history/History.java | 4 +++ .../google/refine/history/HistoryEntry.java | 14 ++++++++ .../google/refine/history/HistoryProcess.java | 21 +++++++++++- .../google/refine/util/ParsingUtilities.java | 1 + .../refine/util/SerializationFilters.java | 32 ++++++++++++++++++- .../tests/history/HistoryEntryTests.java | 8 ++--- 6 files changed, 72 insertions(+), 8 deletions(-) diff --git a/main/src/com/google/refine/history/History.java b/main/src/com/google/refine/history/History.java index 8719eb2ee..f41ca0863 100644 --- a/main/src/com/google/refine/history/History.java +++ b/main/src/com/google/refine/history/History.java @@ -49,6 +49,8 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.RefineServlet; @@ -113,7 +115,9 @@ public class History implements Jsonizable { } protected long _projectID; + @JsonProperty("past") protected List _pastEntries; // done changes, can be undone + @JsonProperty("future") protected List _futureEntries; // undone changes, can be redone public History(Project project) { diff --git a/main/src/com/google/refine/history/HistoryEntry.java b/main/src/com/google/refine/history/HistoryEntry.java index e4e0f5961..8c56fb885 100644 --- a/main/src/com/google/refine/history/HistoryEntry.java +++ b/main/src/com/google/refine/history/HistoryEntry.java @@ -44,11 +44,16 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonView; + import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; +import com.google.refine.util.JsonViews; import com.google.refine.util.ParsingUtilities; /** @@ -57,18 +62,26 @@ import com.google.refine.util.ParsingUtilities; */ public class HistoryEntry implements Jsonizable { final static Logger logger = LoggerFactory.getLogger("HistoryEntry"); + @JsonProperty("id") final public long id; + @JsonIgnore final public long projectID; + @JsonProperty("description") final public String description; + @JsonProperty("time") final public OffsetDateTime time; // the manager (deals with IO systems or databases etc.) + @JsonIgnore final public HistoryEntryManager _manager; // the abstract operation, if any, that results in the change + @JsonProperty("operation") + @JsonView(JsonViews.SaveMode.class) final public AbstractOperation operation; // the actual change, loaded on demand + @JsonIgnore private transient Change _change; private final static String OPERATION = "operation"; @@ -77,6 +90,7 @@ public class HistoryEntry implements Jsonizable { this._change = _change; } + @JsonIgnore public Change getChange() { return _change; } diff --git a/main/src/com/google/refine/history/HistoryProcess.java b/main/src/com/google/refine/history/HistoryProcess.java index 0004e2c86..19c8769cd 100644 --- a/main/src/com/google/refine/history/HistoryProcess.java +++ b/main/src/com/google/refine/history/HistoryProcess.java @@ -38,6 +38,9 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.model.Project; import com.google.refine.process.Process; import com.google.refine.process.ProcessManager; @@ -67,6 +70,12 @@ public class HistoryProcess extends Process { } } + @Override + @JsonIgnore + public long getId() { + return super.getId(); + } + @Override public void cancel() { throw new RuntimeException(WARN); @@ -97,9 +106,19 @@ public class HistoryProcess extends Process { writer.object(); writer.key("description"); writer.value(_description); writer.key("immediate"); writer.value(true); - writer.key("status"); writer.value(_done ? "done" : "pending"); + writer.key("status"); writer.value(getStatus()); writer.endObject(); } + + @JsonProperty("status") + public String getStatus() { + return _done ? "done" : "pending"; + } + + @JsonProperty("description") + public String getDescription() { + return _description; + } @Override public boolean isDone() { diff --git a/main/src/com/google/refine/util/ParsingUtilities.java b/main/src/com/google/refine/util/ParsingUtilities.java index 3404b79af..8b51fcc04 100644 --- a/main/src/com/google/refine/util/ParsingUtilities.java +++ b/main/src/com/google/refine/util/ParsingUtilities.java @@ -72,6 +72,7 @@ public class ParsingUtilities { SimpleModule module = new SimpleModule(); module.addSerializer(Double.class, new SerializationFilters.DoubleSerializer()); module.addSerializer(double.class, new SerializationFilters.DoubleSerializer()); + module.addSerializer(OffsetDateTime.class, new SerializationFilters.DateSerializer()); mapper.registerModule(module); } diff --git a/main/src/com/google/refine/util/SerializationFilters.java b/main/src/com/google/refine/util/SerializationFilters.java index 646892b3e..984f2ca96 100644 --- a/main/src/com/google/refine/util/SerializationFilters.java +++ b/main/src/com/google/refine/util/SerializationFilters.java @@ -1,6 +1,7 @@ package com.google.refine.util; import java.io.IOException; +import java.time.OffsetDateTime; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; @@ -13,6 +14,10 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.google.refine.model.Recon; import com.google.refine.model.Recon.Judgment; +/** + * Series of classes which configure JSON serialization at application level. + * @author Antonin Delpeuch + */ public class SerializationFilters { static class BaseFilter extends SimpleBeanPropertyFilter { @Override @@ -37,6 +42,11 @@ public class SerializationFilters { } public static PropertyFilter noFilter = new BaseFilter(); + + /** + * Filter out reconciliation candidates when rendering a matched recon + * in view mode. (In save mode, render them all the time.) + */ public static PropertyFilter reconCandidateFilter = new BaseFilter() { @Override public void serializeAsField(Object obj, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) @@ -55,7 +65,10 @@ public class SerializationFilters { } } }; - + + /** + * Serialize double values as integers if they happen to round to an integer. + */ public static class DoubleSerializer extends StdSerializer { private static final long serialVersionUID = 132345L; @@ -73,4 +86,21 @@ public class SerializationFilters { } } } + + /** + * Serialize dates by ISO format. + */ + public static class DateSerializer extends StdSerializer { + private static final long serialVersionUID = 93872874L; + + public DateSerializer() { + super(OffsetDateTime.class); + } + + @Override + public void serialize(OffsetDateTime arg0, JsonGenerator gen, SerializerProvider s) + throws IOException { + gen.writeString(ParsingUtilities.dateToString(arg0)); + } + } } diff --git a/main/tests/server/src/com/google/refine/tests/history/HistoryEntryTests.java b/main/tests/server/src/com/google/refine/tests/history/HistoryEntryTests.java index 5d1123fbb..b7e60c907 100644 --- a/main/tests/server/src/com/google/refine/tests/history/HistoryEntryTests.java +++ b/main/tests/server/src/com/google/refine/tests/history/HistoryEntryTests.java @@ -2,8 +2,6 @@ package com.google.refine.tests.history; import static org.mockito.Mockito.mock; -import java.util.Properties; - import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; @@ -58,9 +56,7 @@ public class HistoryEntryTests extends RefineTest { + "\"time\":\"2018-08-07T09:06:37Z\"}"; HistoryEntry historyEntry = HistoryEntry.load(project, json); - TestUtils.isSerializedTo(historyEntry, jsonSimple); - Properties options = new Properties(); - options.setProperty("mode", "save"); - TestUtils.isSerializedTo(historyEntry, json, options); + TestUtils.isSerializedTo(historyEntry, jsonSimple, false); + TestUtils.isSerializedTo(historyEntry, json, true); } } From 18c2183cbcf8c254742e26304564681aa67b936d Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sat, 29 Sep 2018 18:09:41 +0100 Subject: [PATCH 015/164] Jackson serialization for preferences --- .../com/google/refine/browsing/Engine.java | 2 + .../refine/preference/PreferenceStore.java | 49 +++++++++++++++++-- .../com/google/refine/preference/TopList.java | 15 +++++- .../preference/PreferenceStoreTests.java | 19 ++++++- 4 files changed, 79 insertions(+), 6 deletions(-) diff --git a/main/src/com/google/refine/browsing/Engine.java b/main/src/com/google/refine/browsing/Engine.java index f0ef66770..4fa193fe1 100644 --- a/main/src/com/google/refine/browsing/Engine.java +++ b/main/src/com/google/refine/browsing/Engine.java @@ -44,6 +44,7 @@ import org.json.JSONObject; import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonValue; import com.google.refine.Jsonizable; import com.google.refine.browsing.facets.Facet; @@ -72,6 +73,7 @@ public class Engine implements Jsonizable { protected Project _project; protected List _facets = new LinkedList(); + @JsonValue protected EngineConfig _config = new EngineConfig(Collections.emptyList(), Mode.RowBased); static public String modeToString(Mode mode) { diff --git a/main/src/com/google/refine/preference/PreferenceStore.java b/main/src/com/google/refine/preference/PreferenceStore.java index e44656c6d..7358ad9d1 100644 --- a/main/src/com/google/refine/preference/PreferenceStore.java +++ b/main/src/com/google/refine/preference/PreferenceStore.java @@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.preference; +import java.io.IOException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Iterator; @@ -40,10 +41,18 @@ import java.util.Map; import java.util.Properties; import java.util.Set; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.RefineServlet; @@ -54,21 +63,40 @@ public class PreferenceStore implements Jsonizable { public static final String USER_NAME = "username"; private boolean dirty = false; - protected Map _prefs = new HashMap(); + protected Map _prefs = new HashMap<>(); + + // Temporary wrapper while serialization has not been migrated yet. + @JsonProperty("entries") + protected Map _prefsJackson = new HashMap<>(); public void put(String key, Object value) { if (value == null) { _prefs.remove(key); + _prefsJackson.remove(key); } else { _prefs.put(key, value); + _prefsJackson.put(key, wrapJSONArray(value)); } dirty = true; } + private Object wrapJSONArray(Object value) { + ObjectMapper mapper = new ObjectMapper(); + if(value != null && value instanceof JSONArray) { + try { + return mapper.readValue(value.toString(), JsonNode.class); + } catch (IOException e) { + return null; + } + } + return value; + } + public Object get(String key) { return _prefs.get(key); } + @JsonIgnore public Set getKeys() { return _prefs.keySet(); } @@ -98,10 +126,24 @@ public class PreferenceStore implements Jsonizable { /** * @return true if the preference store has unsaved changes */ + @JsonIgnore public boolean isDirty() { return dirty; } + /** + * Mark the object as clean every time it is serialized. + * This behaviour is not very clean - it is inherited from + * the previous deserialization code. + * @return + */ + @JsonProperty("makeClean") + @JsonInclude(Include.NON_NULL) + public Integer markAsClean() { + dirty = false; + return null; + } + @SuppressWarnings("unchecked") public void load(JSONObject obj) throws JSONException { if (obj.has("entries") && !obj.isNull("entries")) { @@ -111,8 +153,9 @@ public class PreferenceStore implements Jsonizable { while (i.hasNext()) { String key = i.next(); if (!entries.isNull(key)) { - Object o = entries.get(key); - _prefs.put(key, loadObject(o)); + Object o = entries.get(key), loaded = loadObject(o); + _prefs.put(key, loaded); + _prefsJackson.put(key, wrapJSONArray(loaded)); } } dirty = false; // internal puts don't count diff --git a/main/src/com/google/refine/preference/TopList.java b/main/src/com/google/refine/preference/TopList.java index dfc96f9c4..846d579bd 100644 --- a/main/src/com/google/refine/preference/TopList.java +++ b/main/src/com/google/refine/preference/TopList.java @@ -44,10 +44,14 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; public class TopList implements Jsonizable, Iterable { + @JsonProperty("top") final protected int _top; final protected List _list = new ArrayList(); @@ -56,6 +60,7 @@ public class TopList implements Jsonizable, Iterable { } @SuppressWarnings("unchecked") + @JsonProperty("list") public List getList() { return UnmodifiableList.decorate(_list); } @@ -72,11 +77,16 @@ public class TopList implements Jsonizable, Iterable { { _list.remove(element); } + + @JsonProperty("class") + public String getClassName() { + return this.getClass().getName(); + } @Override public void write(JSONWriter writer, Properties options) throws JSONException { writer.object(); - writer.key("class"); writer.value(this.getClass().getName()); + writer.key("class"); writer.value(getClassName()); writer.key("top"); writer.value(_top); writer.key("list"); @@ -107,7 +117,8 @@ public class TopList implements Jsonizable, Iterable { } } - @Override + @Override + @JsonIgnore public Iterator iterator() { return _list.iterator(); } diff --git a/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java b/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java index 42911dfc5..86778c971 100644 --- a/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java +++ b/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java @@ -1,5 +1,8 @@ package com.google.refine.tests.preference; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + import org.json.JSONObject; import org.testng.annotations.Test; @@ -17,8 +20,22 @@ public class PreferenceStoreTests { + " \"scripting.starred-expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":2147483647,\"list\":[]}," + " \"scripting.expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":100,\"list\":[]}" + "}}"; + String jsonAfter = "{" + + "\"entries\":{" + + " \"reconciliation.standardServices\":[" + + " {\"propose_properties\":{\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/propose_properties\"},\"preview\":{\"width\":320,\"url\":\"https://tools.wmflabs.org/openrefine-wikidata/en/preview?id={{id}}\",\"height\":90},\"view\":{\"url\":\"https://www.wikidata.org/wiki/{{id}}\"},\"ui\":{\"handler\":\"ReconStandardServicePanel\"},\"identifierSpace\":\"http://www.wikidata.org/entity/\",\"name\":\"Wikidata Reconciliation for OpenRefine (en)\",\"suggest\":{\"property\":{\"flyout_service_path\":\"/en/flyout/property?id=${id}\",\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/suggest/property\"},\"type\":{\"flyout_service_path\":\"/en/flyout/type?id=${id}\",\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/suggest/type\"},\"entity\":{\"flyout_service_path\":\"/en/flyout/entity?id=${id}\",\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/suggest/entity\"}},\"defaultTypes\":[{\"name\":\"entity\",\"id\":\"Q35120\"}],\"url\":\"https://tools.wmflabs.org/openrefine-wikidata/en/api\",\"schemaSpace\":\"http://www.wikidata.org/prop/direct/\"}" + + " ]," + + " \"scripting.starred-expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":2147483647,\"list\":[]}," + + " \"scripting.expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":100,\"list\":[]}," + + " \"mypreference\":\"myvalue\"" + + "}}"; PreferenceStore prefStore = new PreferenceStore(); prefStore.load(new JSONObject(json)); - TestUtils.isSerializedTo(prefStore, json); + assertFalse(prefStore.isDirty()); + prefStore.put("mypreference", "myvalue"); + assertTrue(prefStore.isDirty()); + TestUtils.isSerializedTo(prefStore, jsonAfter); + assertFalse(prefStore.isDirty()); } + } From 7d3af420cefa9ecf07362d68699d85a6fdb94da6 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sat, 29 Sep 2018 19:28:55 +0100 Subject: [PATCH 016/164] Jackson serialization for long running processes --- ...ColumnAdditionByFetchingURLsOperation.java | 15 +--- .../operations/recon/ExtendDataOperation.java | 13 ---- .../operations/recon/ReconOperation.java | 47 +++++++++++- ...nAdditionByFetchingURLsOperationTests.java | 48 +++++++++---- .../recon/ExtendDataOperationTests.java | 55 +++++++++----- .../operations/recon/ReconOperationTests.java | 72 ++++++++++++++----- 6 files changed, 172 insertions(+), 78 deletions(-) diff --git a/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java b/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java index 8af2c0dcf..3e623c92b 100644 --- a/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java @@ -316,20 +316,7 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat }); } } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("id"); writer.value(hashCode()); - writer.key("description"); writer.value(_description); - writer.key("immediate"); writer.value(false); - writer.key("status"); writer.value(_thread == null ? "pending" : (_thread.isAlive() ? "running" : "done")); - writer.key("progress"); writer.value(_progress); - writer.endObject(); - } - + @Override protected Runnable getRunnable() { return this; diff --git a/main/src/com/google/refine/operations/recon/ExtendDataOperation.java b/main/src/com/google/refine/operations/recon/ExtendDataOperation.java index 4905bc682..3aaa5858c 100644 --- a/main/src/com/google/refine/operations/recon/ExtendDataOperation.java +++ b/main/src/com/google/refine/operations/recon/ExtendDataOperation.java @@ -178,19 +178,6 @@ public class ExtendDataOperation extends EngineDependentOperation { _job = new ReconciledDataExtensionJob(_extension, _endpoint); } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("id"); writer.value(hashCode()); - writer.key("description"); writer.value(_description); - writer.key("immediate"); writer.value(false); - writer.key("status"); writer.value(_thread == null ? "pending" : (_thread.isAlive() ? "running" : "done")); - writer.key("progress"); writer.value(_progress); - writer.endObject(); - } - @Override protected Runnable getRunnable() { return this; diff --git a/main/src/com/google/refine/operations/recon/ReconOperation.java b/main/src/com/google/refine/operations/recon/ReconOperation.java index 567fb6cef..278b93e35 100644 --- a/main/src/com/google/refine/operations/recon/ReconOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconOperation.java @@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.recon; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -46,6 +47,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; @@ -69,6 +71,7 @@ import com.google.refine.operations.EngineDependentOperation; import com.google.refine.operations.OperationRegistry; import com.google.refine.process.LongRunningProcess; import com.google.refine.process.Process; +import com.google.refine.util.ParsingUtilities; public class ReconOperation extends EngineDependentOperation { final static Logger logger = LoggerFactory.getLogger("recon-operation"); @@ -76,7 +79,7 @@ public class ReconOperation extends EngineDependentOperation { final protected String _columnName; final protected ReconConfig _reconConfig; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { + static public ReconOperation reconstruct(Project project, JSONObject obj) throws Exception { JSONObject engineConfig = obj.getJSONObject("engineConfig"); return new ReconOperation( @@ -159,6 +162,32 @@ public class ReconOperation extends EngineDependentOperation { protected List _entries; protected int _cellIndex; + protected final String _addJudgmentFacetJson = + "{\n" + + " \"action\" : \"createFacet\",\n" + + " \"facetConfig\" : {\n" + + " \"columnName\" : \"researcher\",\n" + + " \"expression\" : \"forNonBlank(cell.recon.judgment, v, v, if(isNonBlank(value), \\\"(unreconciled)\\\", \\\"(blank)\\\"))\",\n" + + " \"name\" : \"researcher: judgment\"\n" + + " },\n" + + " \"facetOptions\" : {\n" + + " \"scroll\" : false\n" + + " },\n" + + " \"facetType\" : \"list\"\n" + + " }"; + protected final String _addScoreFacetJson = + "{\n" + + " \"action\" : \"createFacet\",\n" + + " \"facetConfig\" : {\n" + + " \"columnName\" : \"researcher\",\n" + + " \"expression\" : \"cell.recon.best.score\",\n" + + " \"mode\" : \"range\",\n" + + " \"name\" : \"researcher: best candidate's score\"\n" + + " },\n" + + " \"facetType\" : \"range\"\n" + + "}"; + protected JsonNode _addJudgmentFacet, _addScoreFacet; + public ReconProcess( Project project, EngineConfig engineConfig, @@ -168,6 +197,12 @@ public class ReconOperation extends EngineDependentOperation { _project = project; _engineConfig = engineConfig; _historyEntryID = HistoryEntry.allocateID(); + try { + _addJudgmentFacet = ParsingUtilities.mapper.readValue(_addJudgmentFacetJson, JsonNode.class); + _addScoreFacet = ParsingUtilities.mapper.readValue(_addScoreFacetJson, JsonNode.class); + } catch (IOException e) { + e.printStackTrace(); + } } @Override @@ -214,6 +249,16 @@ public class ReconOperation extends EngineDependentOperation { writer.endObject(); } + @JsonProperty("onDone") + public List onDoneActions() { + List onDone = new ArrayList<>(); + onDone.add(_addJudgmentFacet); + if (_reconConfig instanceof StandardReconConfig) { + onDone.add(_addScoreFacet); + } + return onDone; + } + @Override protected Runnable getRunnable() { return this; diff --git a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionByFetchingURLsOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionByFetchingURLsOperationTests.java index 7d29fd608..4697cf37a 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionByFetchingURLsOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionByFetchingURLsOperationTests.java @@ -49,6 +49,7 @@ import org.testng.annotations.Test; import com.google.refine.browsing.EngineConfig; import com.google.refine.expr.ExpressionUtils; +import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.ModelException; import com.google.refine.model.Project; @@ -67,6 +68,31 @@ import com.google.refine.tests.util.TestUtils; public class ColumnAdditionByFetchingURLsOperationTests extends RefineTest { static final String ENGINE_JSON_URLS = "{\"mode\":\"row-based\"}"; + + private String json = "{\"op\":\"core/column-addition-by-fetching-urls\"," + + "\"description\":\"Create column employments at index 2 by fetching URLs based on column orcid using expression grel:\\\"https://pub.orcid.org/\\\"+value+\\\"/employments\\\"\"," + + "\"engineConfig\":{\"mode\":\"row-based\",\"facets\":[]}," + + "\"newColumnName\":\"employments\"," + + "\"columnInsertIndex\":2," + + "\"baseColumnName\":\"orcid\"," + + "\"urlExpression\":\"grel:\\\"https://pub.orcid.org/\\\"+value+\\\"/employments\\\"\"," + + "\"onError\":\"set-to-blank\"," + + "\"delay\":500," + + "\"cacheResponses\":true," + + "\"httpHeadersJson\":[" + + " {\"name\":\"authorization\",\"value\":\"\"}," + + " {\"name\":\"user-agent\",\"value\":\"OpenRefine 3.0 rc.1 [TRUNK]\"}," + + " {\"name\":\"accept\",\"value\":\"application/json\"}" + + "]}"; + + private String processJson = "" + +"{\n" + + " \"description\" : \"Create column employments at index 2 by fetching URLs based on column orcid using expression grel:\\\"https://pub.orcid.org/\\\"+value+\\\"/employments\\\"\",\n" + + " \"id\" : %d,\n" + + " \"immediate\" : false,\n" + + " \"progress\" : 0,\n" + + " \"status\" : \"pending\"\n" + + " }"; @Override @BeforeTest @@ -99,24 +125,16 @@ public class ColumnAdditionByFetchingURLsOperationTests extends RefineTest { @Test public void serializeColumnAdditionByFetchingURLsOperation() throws JSONException, Exception { - String json = "{\"op\":\"core/column-addition-by-fetching-urls\"," - + "\"description\":\"Create column employments at index 2 by fetching URLs based on column orcid using expression grel:\\\"https://pub.orcid.org/\\\"+value+\\\"/employments\\\"\"," - + "\"engineConfig\":{\"mode\":\"row-based\",\"facets\":[]}," - + "\"newColumnName\":\"employments\"," - + "\"columnInsertIndex\":2," - + "\"baseColumnName\":\"orcid\"," - + "\"urlExpression\":\"grel:\\\"https://pub.orcid.org/\\\"+value+\\\"/employments\\\"\"," - + "\"onError\":\"set-to-blank\"," - + "\"delay\":500," - + "\"cacheResponses\":true," - + "\"httpHeadersJson\":[" - + " {\"name\":\"authorization\",\"value\":\"\"}," - + " {\"name\":\"user-agent\",\"value\":\"OpenRefine 3.0 rc.1 [TRUNK]\"}," - + " {\"name\":\"accept\",\"value\":\"application/json\"}" - + "]}"; TestUtils.isSerializedTo(ColumnAdditionByFetchingURLsOperation.reconstruct(project, new JSONObject(json)), json); } + @Test + public void serializeUrlFetchingProcess() throws Exception { + AbstractOperation op = ColumnAdditionByFetchingURLsOperation.reconstruct(project, new JSONObject(json)); + Process process = op.createProcess(project, new Properties()); + TestUtils.isSerializedTo(process, String.format(processJson, process.hashCode())); + } + /** * Test for caching */ diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java index 111da8f76..528656da4 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java @@ -86,6 +86,34 @@ public class ExtendDataOperationTests extends RefineTest { + " ]" + "}"; + private String operationJson = "{\"op\":\"core/extend-reconciled-data\"," + + "\"description\":\"Extend data at index 3 based on column organization_name\"," + + "\"engineConfig\":{\"mode\":\"row-based\",\"facets\":[" + + " {\"selectNumeric\":true,\"expression\":\"cell.recon.best.score\",\"selectBlank\":false,\"selectNonNumeric\":true,\"selectError\":true,\"name\":\"organization_name: best candidate's score\",\"from\":13,\"to\":101,\"type\":\"range\",\"columnName\":\"organization_name\"}," + + " {\"selectNonTime\":true,\"expression\":\"grel:toDate(value)\",\"selectBlank\":true,\"selectError\":true,\"selectTime\":true,\"name\":\"start_year\",\"from\":410242968000,\"to\":1262309184000,\"type\":\"timerange\",\"columnName\":\"start_year\"}" + + "]}," + + "\"columnInsertIndex\":3," + + "\"baseColumnName\":\"organization_name\"," + + "\"endpoint\":\"https://tools.wmflabs.org/openrefine-wikidata/en/api\"," + + "\"identifierSpace\":\"http://www.wikidata.org/entity/\"," + + "\"schemaSpace\":\"http://www.wikidata.org/prop/direct/\"," + + "\"extension\":{" + + " \"properties\":[" + + " {\"name\":\"inception\",\"id\":\"P571\"}," + + " {\"name\":\"headquarters location\",\"id\":\"P159\"}," + + " {\"name\":\"coordinate location\",\"id\":\"P625\"}" + + " ]" + + "}}"; + + private String processJson = "" + + " {\n" + + " \"description\" : \"Extend data at index 3 based on column organization_name\",\n" + + " \"id\" : %d,\n" + + " \"immediate\" : false,\n" + + " \"progress\" : 0,\n" + + " \"status\" : \"pending\"\n" + + " }"; + static public class ReconciledDataExtensionJobStub extends ReconciledDataExtensionJob { public ReconciledDataExtensionJobStub(DataExtensionConfig obj, String endpoint) throws JSONException { super(obj, endpoint); @@ -137,25 +165,14 @@ public class ExtendDataOperationTests extends RefineTest { @Test public void serializeExtendDataOperation() throws JSONException, Exception { - String json = "{\"op\":\"core/extend-reconciled-data\"," - + "\"description\":\"Extend data at index 3 based on column organization_name\"," - + "\"engineConfig\":{\"mode\":\"row-based\",\"facets\":[" - + " {\"selectNumeric\":true,\"expression\":\"cell.recon.best.score\",\"selectBlank\":false,\"selectNonNumeric\":true,\"selectError\":true,\"name\":\"organization_name: best candidate's score\",\"from\":13,\"to\":101,\"type\":\"range\",\"columnName\":\"organization_name\"}," - + " {\"selectNonTime\":true,\"expression\":\"grel:toDate(value)\",\"selectBlank\":true,\"selectError\":true,\"selectTime\":true,\"name\":\"start_year\",\"from\":410242968000,\"to\":1262309184000,\"type\":\"timerange\",\"columnName\":\"start_year\"}" - + "]}," - + "\"columnInsertIndex\":3," - + "\"baseColumnName\":\"organization_name\"," - + "\"endpoint\":\"https://tools.wmflabs.org/openrefine-wikidata/en/api\"," - + "\"identifierSpace\":\"http://www.wikidata.org/entity/\"," - + "\"schemaSpace\":\"http://www.wikidata.org/prop/direct/\"," - + "\"extension\":{" - + " \"properties\":[" - + " {\"name\":\"inception\",\"id\":\"P571\"}," - + " {\"name\":\"headquarters location\",\"id\":\"P159\"}," - + " {\"name\":\"coordinate location\",\"id\":\"P625\"}" - + " ]" - + "}}"; - TestUtils.isSerializedTo(ExtendDataOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ExtendDataOperation.reconstruct(project, new JSONObject(operationJson)), operationJson); + } + + @Test + public void serializeExtendDataProcess() throws JSONException, Exception { + Process p = ExtendDataOperation.reconstruct(project, new JSONObject(operationJson)) + .createProcess(project, new Properties()); + TestUtils.isSerializedTo(p, String.format(processJson, p.hashCode())); } @Test diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconOperationTests.java index 4da313b37..1fed8577f 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconOperationTests.java @@ -2,6 +2,8 @@ package com.google.refine.tests.operations.recon; import static org.mockito.Mockito.mock; +import java.util.Properties; + import org.json.JSONException; import org.json.JSONObject; import org.testng.annotations.BeforeSuite; @@ -17,6 +19,53 @@ import com.google.refine.tests.util.TestUtils; public class ReconOperationTests extends RefineTest { + private String json= "{" + + "\"op\":\"core/recon\"," + + "\"description\":\"Reconcile cells in column researcher to type Q5\"," + + "\"columnName\":\"researcher\"," + + "\"config\":{" + + " \"mode\":\"standard-service\"," + + " \"service\":\"https://tools.wmflabs.org/openrefine-wikidata/en/api\"," + + " \"identifierSpace\":\"http://www.wikidata.org/entity/\"," + + " \"schemaSpace\":\"http://www.wikidata.org/prop/direct/\"," + + " \"type\":{\"id\":\"Q5\",\"name\":\"human\"}," + + " \"autoMatch\":true," + + " \"columnDetails\":[]," + + " \"limit\":0" + + "}," + + "\"engineConfig\":{\"mode\":\"row-based\",\"facets\":[]}}"; + private Project project = mock(Project.class); + + private String processJson = "" + + " {\n" + + " \"description\" : \"Reconcile cells in column researcher to type Q5\",\n" + + " \"id\" : %d,\n" + + " \"immediate\" : false,\n" + + " \"onDone\" : [ {\n" + + " \"action\" : \"createFacet\",\n" + + " \"facetConfig\" : {\n" + + " \"columnName\" : \"researcher\",\n" + + " \"expression\" : \"forNonBlank(cell.recon.judgment, v, v, if(isNonBlank(value), \\\"(unreconciled)\\\", \\\"(blank)\\\"))\",\n" + + " \"name\" : \"researcher: judgment\"\n" + + " },\n" + + " \"facetOptions\" : {\n" + + " \"scroll\" : false\n" + + " },\n" + + " \"facetType\" : \"list\"\n" + + " }, {\n" + + " \"action\" : \"createFacet\",\n" + + " \"facetConfig\" : {\n" + + " \"columnName\" : \"researcher\",\n" + + " \"expression\" : \"cell.recon.best.score\",\n" + + " \"mode\" : \"range\",\n" + + " \"name\" : \"researcher: best candidate's score\"\n" + + " },\n" + + " \"facetType\" : \"range\"\n" + + " } ],\n" + + " \"progress\" : 0,\n" + + " \"status\" : \"pending\"\n" + + " }"; + @BeforeSuite public void registerOperation() { OperationRegistry.registerOperation(getCoreModule(), "recon", ReconOperation.class); @@ -25,22 +74,13 @@ public class ReconOperationTests extends RefineTest { @Test public void serializeReconOperation() throws JSONException, Exception { - String json = "{" - + "\"op\":\"core/recon\"," - + "\"description\":\"Reconcile cells in column researcher to type Q5\"," - + "\"columnName\":\"researcher\"," - + "\"config\":{" - + " \"mode\":\"standard-service\"," - + " \"service\":\"https://tools.wmflabs.org/openrefine-wikidata/en/api\"," - + " \"identifierSpace\":\"http://www.wikidata.org/entity/\"," - + " \"schemaSpace\":\"http://www.wikidata.org/prop/direct/\"," - + " \"type\":{\"id\":\"Q5\",\"name\":\"human\"}," - + " \"autoMatch\":true," - + " \"columnDetails\":[]," - + " \"limit\":0" - + "}," - + "\"engineConfig\":{\"mode\":\"row-based\",\"facets\":[]}}"; - Project project = mock(Project.class); TestUtils.isSerializedTo(ReconOperation.reconstruct(project, new JSONObject(json)), json); } + + @Test + public void serializeReconProcess() throws JSONException, Exception { + ReconOperation op = ReconOperation.reconstruct(project, new JSONObject(json)); + com.google.refine.process.Process process = op.createProcess(project, new Properties()); + TestUtils.isSerializedTo(process, String.format(processJson, process.hashCode())); + } } From 49b84574dac2966919a5b28dc465e7c6394eb8bc Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sat, 29 Sep 2018 19:42:37 +0100 Subject: [PATCH 017/164] Move EvalErrorTests --- .../src/com/google/refine/{ => tests}/expr/EvalErrorTests.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) rename main/tests/server/src/com/google/refine/{ => tests}/expr/EvalErrorTests.java (81%) diff --git a/main/tests/server/src/com/google/refine/expr/EvalErrorTests.java b/main/tests/server/src/com/google/refine/tests/expr/EvalErrorTests.java similarity index 81% rename from main/tests/server/src/com/google/refine/expr/EvalErrorTests.java rename to main/tests/server/src/com/google/refine/tests/expr/EvalErrorTests.java index 98d734418..c91a152f5 100644 --- a/main/tests/server/src/com/google/refine/expr/EvalErrorTests.java +++ b/main/tests/server/src/com/google/refine/tests/expr/EvalErrorTests.java @@ -1,7 +1,8 @@ -package com.google.refine.expr; +package com.google.refine.tests.expr; import org.testng.annotations.Test; +import com.google.refine.expr.EvalError; import com.google.refine.tests.util.TestUtils; public class EvalErrorTests { From 987c2d1c80f088d114bbc2b85ec04f8b8d9f2e53 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 30 Sep 2018 11:28:41 +0100 Subject: [PATCH 018/164] Jackson serialization for project managers --- .../src/com/google/refine/ProjectManager.java | 10 ++- .../google/refine/io/FileProjectManager.java | 80 ++++++++++++------- .../tests/io/FileProjectManagerTests.java | 45 +++++++++++ .../preference/PreferenceStoreTests.java | 19 +++-- 4 files changed, 118 insertions(+), 36 deletions(-) create mode 100644 main/tests/server/src/com/google/refine/tests/io/FileProjectManagerTests.java diff --git a/main/src/com/google/refine/ProjectManager.java b/main/src/com/google/refine/ProjectManager.java index ee89a7eda..2e90d4624 100644 --- a/main/src/com/google/refine/ProjectManager.java +++ b/main/src/com/google/refine/ProjectManager.java @@ -54,6 +54,9 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.history.HistoryEntryManager; import com.google.refine.model.Project; import com.google.refine.model.metadata.IMetadata; @@ -342,6 +345,7 @@ public abstract class ProjectManager { /** * Gets the InterProjectModel from memory */ + @JsonIgnore public InterProjectModel getInterProjectModel() { return _interProjectModel; } @@ -472,7 +476,7 @@ public abstract class ProjectManager { * Gets all the project Metadata currently held in memory. * @return */ - + @JsonIgnore public Map getAllProjectMetadata() { for(Project project : _projects.values()) { mergeEmptyUserMetadata(project.getMetadata()); @@ -486,6 +490,7 @@ public abstract class ProjectManager { * * @return */ + @JsonIgnore public Map getAllProjectTags() { return _projectsTags; } @@ -517,6 +522,7 @@ public abstract class ProjectManager { * Gets the preference store * @return */ + @JsonProperty("preferences") public PreferenceStore getPreferenceStore() { return _preferenceStore; } @@ -525,6 +531,7 @@ public abstract class ProjectManager { * Gets all expressions from the preference store * @return */ + @JsonIgnore public List getExpressions() { return ((TopList) _preferenceStore.get("scripting.expressions")).getList(); } @@ -533,6 +540,7 @@ public abstract class ProjectManager { * The history entry manager deals with changes * @return manager for handling history */ + @JsonIgnore public abstract HistoryEntryManager getHistoryEntryManager(); diff --git a/main/src/com/google/refine/io/FileProjectManager.java b/main/src/com/google/refine/io/FileProjectManager.java index a59cad8c8..ac8f75829 100644 --- a/main/src/com/google/refine/io/FileProjectManager.java +++ b/main/src/com/google/refine/io/FileProjectManager.java @@ -42,7 +42,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.HashMap; +import java.util.Map.Entry; import java.util.Properties; +import java.util.Set; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; @@ -57,6 +59,10 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.history.HistoryEntryManager; import com.google.refine.model.Project; @@ -67,7 +73,7 @@ import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.preference.TopList; -public class FileProjectManager extends ProjectManager { +public class FileProjectManager extends ProjectManager implements Jsonizable { final static protected String PROJECT_DIR_SUFFIX = ".project"; protected File _workspaceDir; @@ -95,6 +101,7 @@ public class FileProjectManager extends ProjectManager { load(); } + @JsonIgnore public File getWorkspaceDir() { return _workspaceDir; } @@ -107,6 +114,7 @@ public class FileProjectManager extends ProjectManager { return dir; } + @JsonIgnore public File getProjectDir(long projectID) { return getProjectDir(_workspaceDir, projectID); } @@ -267,6 +275,7 @@ public class FileProjectManager extends ProjectManager { @Override protected void saveWorkspace() { synchronized (this) { + // TODO refactor this so that we check if the save is needed before writing to the file! File tempFile = new File(_workspaceDir, "workspace.temp.json"); try { if (!saveToFile(tempFile)) { @@ -294,39 +303,32 @@ public class FileProjectManager extends ProjectManager { } tempFile.renameTo(file); - logger.info("Saved workspace"); } } + + protected boolean saveNeeded() { + boolean projectSaveNeeded = _projectsMetadata.entrySet().stream() + .anyMatch(e -> e.getValue() != null && e.getValue().isDirty()); + return projectSaveNeeded || _preferenceStore.isDirty(); + } + + protected void saveProjectMetadata() throws JSONException, IOException { + for(Entry entry : _projectsMetadata.entrySet()) { + ProjectMetadata metadata = entry.getValue(); + if (metadata != null && metadata.isDirty()) { + ProjectMetadataUtilities.save(metadata, getProjectDir(entry.getKey())); + } + } + } protected boolean saveToFile(File file) throws IOException, JSONException { FileWriter writer = new FileWriter(file); - boolean saveWasNeeded = false; + boolean saveWasNeeded = saveNeeded(); try { JSONWriter jsonWriter = new JSONWriter(writer); - jsonWriter.object(); - jsonWriter.key("projectIDs"); - jsonWriter.array(); - for (Long id : _projectsMetadata.keySet()) { - ProjectMetadata metadata = _projectsMetadata.get(id); - if (metadata != null) { - jsonWriter.value(id); - if (metadata.isDirty()) { - Project project = ProjectManager.singleton.getProject(id); - metadata.setRowCount(project.rows.size()); - ProjectMetadataUtilities.save(metadata, getProjectDir(id)); - saveWasNeeded = true; - } - } - } - jsonWriter.endArray(); - writer.write('\n'); - - jsonWriter.key("preferences"); - saveWasNeeded |= _preferenceStore.isDirty(); - _preferenceStore.write(jsonWriter, new Properties()); - - jsonWriter.endObject(); + write(jsonWriter, new Properties()); + saveProjectMetadata(); } finally { writer.close(); } @@ -370,7 +372,7 @@ public class FileProjectManager extends ProjectManager { } logger.error("Failed to load workspace from any attempted alternatives."); } - + protected boolean loadFromFile(File file) { logger.info("Loading workspace: {}", file.getAbsolutePath()); @@ -484,4 +486,28 @@ public class FileProjectManager extends ProjectManager { gos.close(); } } + + @Override + public void write(JSONWriter jsonWriter, Properties options) + throws JSONException { + jsonWriter.object(); + jsonWriter.key("projectIDs"); + jsonWriter.array(); + for (Long id : _projectsMetadata.keySet()) { + ProjectMetadata metadata = _projectsMetadata.get(id); + if (metadata != null) { + jsonWriter.value(id); + } + } + jsonWriter.endArray(); + + jsonWriter.key("preferences"); + _preferenceStore.write(jsonWriter, new Properties()); + jsonWriter.endObject(); + } + + @JsonProperty("projectIDs") + public Set getProjectIds() { + return _projectsMetadata.keySet(); + } } \ No newline at end of file diff --git a/main/tests/server/src/com/google/refine/tests/io/FileProjectManagerTests.java b/main/tests/server/src/com/google/refine/tests/io/FileProjectManagerTests.java new file mode 100644 index 000000000..80e470c73 --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/io/FileProjectManagerTests.java @@ -0,0 +1,45 @@ +package com.google.refine.tests.io; + +import java.io.File; + +import org.testng.annotations.Test; +import static org.mockito.Mockito.mock; + +import com.google.refine.io.FileProjectManager; +import com.google.refine.model.metadata.ProjectMetadata; +import com.google.refine.tests.RefineTest; +import com.google.refine.tests.util.TestUtils; + +public class FileProjectManagerTests extends RefineTest { + + protected class FileProjectManagerStub extends FileProjectManager { + + protected FileProjectManagerStub(File dir) { + super(dir); + _projectsMetadata.put(1234L, mock(ProjectMetadata.class)); + } + } + + @Test + public void serializeFileProjectManager() { + FileProjectManager manager = new FileProjectManagerStub(workspaceDir); + String json = "{\n" + + " \"preferences\" : {\n" + + " \"entries\" : {\n" + + " \"scripting.expressions\" : {\n" + + " \"class\" : \"com.google.refine.preference.TopList\",\n" + + " \"list\" : [ ],\n" + + " \"top\" : 100\n" + + " },\n" + + " \"scripting.starred-expressions\" : {\n" + + " \"class\" : \"com.google.refine.preference.TopList\",\n" + + " \"list\" : [ ],\n" + + " \"top\" : 2147483647\n" + + " }\n" + + " }\n" + + " },\n" + + " \"projectIDs\" : [ 1234 ]\n" + + " }"; + TestUtils.isSerializedTo(manager, json); + } +} diff --git a/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java b/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java index 86778c971..9a5c1af18 100644 --- a/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java +++ b/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java @@ -7,19 +7,22 @@ import org.json.JSONObject; import org.testng.annotations.Test; import com.google.refine.preference.PreferenceStore; +import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; public class PreferenceStoreTests { + public static String json = "{" + + "\"entries\":{" + + " \"reconciliation.standardServices\":[" + + " {\"propose_properties\":{\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/propose_properties\"},\"preview\":{\"width\":320,\"url\":\"https://tools.wmflabs.org/openrefine-wikidata/en/preview?id={{id}}\",\"height\":90},\"view\":{\"url\":\"https://www.wikidata.org/wiki/{{id}}\"},\"ui\":{\"handler\":\"ReconStandardServicePanel\"},\"identifierSpace\":\"http://www.wikidata.org/entity/\",\"name\":\"Wikidata Reconciliation for OpenRefine (en)\",\"suggest\":{\"property\":{\"flyout_service_path\":\"/en/flyout/property?id=${id}\",\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/suggest/property\"},\"type\":{\"flyout_service_path\":\"/en/flyout/type?id=${id}\",\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/suggest/type\"},\"entity\":{\"flyout_service_path\":\"/en/flyout/entity?id=${id}\",\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/suggest/entity\"}},\"defaultTypes\":[{\"name\":\"entity\",\"id\":\"Q35120\"}],\"url\":\"https://tools.wmflabs.org/openrefine-wikidata/en/api\",\"schemaSpace\":\"http://www.wikidata.org/prop/direct/\"}" + + " ]," + + " \"scripting.starred-expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":2147483647,\"list\":[]}," + + " \"scripting.expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":100,\"list\":[]}" + + "}}"; + @Test public void serializePreferenceStore() { - String json = "{" - + "\"entries\":{" - + " \"reconciliation.standardServices\":[" - + " {\"propose_properties\":{\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/propose_properties\"},\"preview\":{\"width\":320,\"url\":\"https://tools.wmflabs.org/openrefine-wikidata/en/preview?id={{id}}\",\"height\":90},\"view\":{\"url\":\"https://www.wikidata.org/wiki/{{id}}\"},\"ui\":{\"handler\":\"ReconStandardServicePanel\"},\"identifierSpace\":\"http://www.wikidata.org/entity/\",\"name\":\"Wikidata Reconciliation for OpenRefine (en)\",\"suggest\":{\"property\":{\"flyout_service_path\":\"/en/flyout/property?id=${id}\",\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/suggest/property\"},\"type\":{\"flyout_service_path\":\"/en/flyout/type?id=${id}\",\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/suggest/type\"},\"entity\":{\"flyout_service_path\":\"/en/flyout/entity?id=${id}\",\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/suggest/entity\"}},\"defaultTypes\":[{\"name\":\"entity\",\"id\":\"Q35120\"}],\"url\":\"https://tools.wmflabs.org/openrefine-wikidata/en/api\",\"schemaSpace\":\"http://www.wikidata.org/prop/direct/\"}" - + " ]," - + " \"scripting.starred-expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":2147483647,\"list\":[]}," - + " \"scripting.expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":100,\"list\":[]}" - + "}}"; + String jsonAfter = "{" + "\"entries\":{" + " \"reconciliation.standardServices\":[" From bb0b351cefbc8ede90a0282b794944a1e9138974 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 30 Sep 2018 10:48:11 +0100 Subject: [PATCH 019/164] Refactoring JSON production in commands to prepare for Jackson --- .../refine/commands/GetPreferenceCommand.java | 43 +++++---- .../history/GetOperationsCommand.java | 90 ++++++++++++++----- 2 files changed, 91 insertions(+), 42 deletions(-) diff --git a/main/src/com/google/refine/commands/GetPreferenceCommand.java b/main/src/com/google/refine/commands/GetPreferenceCommand.java index 0628efec7..9f26daadc 100644 --- a/main/src/com/google/refine/commands/GetPreferenceCommand.java +++ b/main/src/com/google/refine/commands/GetPreferenceCommand.java @@ -43,28 +43,25 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; -import com.google.refine.model.Project; import com.google.refine.preference.PreferenceStore; import com.google.refine.preference.TopList; public class GetPreferenceCommand extends Command { - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { + protected static class PreferenceValue implements Jsonizable { + @JsonProperty("value") + protected Object pref; - Project project = request.getParameter("project") != null ? getProject(request) : null; - PreferenceStore ps = ProjectManager.singleton.getPreferenceStore(); - - String prefName = request.getParameter("name"); - Object pref = ps.get(prefName); - - try { - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - + protected PreferenceValue(Object o) { + pref = o; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { writer.object(); writer.key("value"); if (pref == null || pref instanceof String || pref instanceof Number || pref instanceof Boolean) { @@ -77,9 +74,19 @@ public class GetPreferenceCommand extends Command { } writer.endObject(); - } catch (JSONException e) { - respondException(response, e); } } + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + PreferenceStore ps = ProjectManager.singleton.getPreferenceStore(); + + String prefName = request.getParameter("name"); + Object pref = ps.get(prefName); + + respondJSON(response, new PreferenceValue(pref)); + } } diff --git a/main/src/com/google/refine/commands/history/GetOperationsCommand.java b/main/src/com/google/refine/commands/history/GetOperationsCommand.java index 32ebc2f54..f03f9aabc 100644 --- a/main/src/com/google/refine/commands/history/GetOperationsCommand.java +++ b/main/src/com/google/refine/commands/history/GetOperationsCommand.java @@ -34,7 +34,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.commands.history; import java.io.IOException; +import java.util.List; import java.util.Properties; +import java.util.stream.Collectors; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -43,41 +45,81 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + +import com.google.refine.Jsonizable; import com.google.refine.commands.Command; import com.google.refine.history.HistoryEntry; +import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; public class GetOperationsCommand extends Command { + protected static class SimpleHistoryEntry implements Jsonizable { + protected HistoryEntry entry; + + public SimpleHistoryEntry(HistoryEntry e) { + entry = e; + } + + @JsonProperty("description") + public String getDescription() { + return entry.description; + } + + @JsonProperty("operation") + @JsonInclude(Include.NON_NULL) + public AbstractOperation getOperation() { + return entry.operation; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("description"); writer.value(entry.description); + if (entry.operation != null) { + writer.key("operation"); + entry.operation.write(writer, options); + } + writer.endObject(); + } + + } + + protected static class HistoryEntries implements Jsonizable { + @JsonProperty("entries") + List entries; + + protected HistoryEntries(List entries) { + this.entries = entries.stream() + .map(e -> new SimpleHistoryEntry(e)) + .collect(Collectors.toList()); + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("entries"); writer.array(); + + for (SimpleHistoryEntry entry : entries) { + entry.write(writer, options); + } + writer.endArray(); + writer.endObject(); + } + } + @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Project project = getProject(request); - try { - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - Properties options = new Properties(); - JSONWriter writer = new JSONWriter(response.getWriter()); - - writer.object(); - writer.key("entries"); writer.array(); - - for (HistoryEntry entry : project.history.getLastPastEntries(-1)) { - writer.object(); - writer.key("description"); writer.value(entry.description); - if (entry.operation != null) { - writer.key("operation"); - entry.operation.write(writer, options); - } - writer.endObject(); - } - writer.endArray(); - writer.endObject(); - } catch (JSONException e) { - respondException(response, e); - } + HistoryEntries entries = new HistoryEntries(project.history.getLastPastEntries(-1)); + respondJSON(response, entries); } } From b6a724b4299f8952d7ffb6003b70d46df6d93fbb Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 30 Sep 2018 10:50:46 +0100 Subject: [PATCH 020/164] Disable Jackson autodetect and annotate remaining classes --- main/src/com/google/refine/expr/EvalError.java | 8 ++++++++ main/src/com/google/refine/model/ReconStats.java | 5 +++++ main/src/com/google/refine/model/ReconType.java | 4 ++++ main/src/com/google/refine/util/ParsingUtilities.java | 5 +++++ 4 files changed, 22 insertions(+) diff --git a/main/src/com/google/refine/expr/EvalError.java b/main/src/com/google/refine/expr/EvalError.java index 5f4912deb..34682cdfc 100644 --- a/main/src/com/google/refine/expr/EvalError.java +++ b/main/src/com/google/refine/expr/EvalError.java @@ -39,6 +39,8 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; /** @@ -50,6 +52,7 @@ import com.google.refine.Jsonizable; public class EvalError implements Serializable, Jsonizable { private static final long serialVersionUID = -102681220092874080L; + @JsonProperty("message") final public String message; public EvalError(String message) { @@ -75,5 +78,10 @@ public class EvalError implements Serializable, Jsonizable { writer.key("message"); writer.value(message); writer.endObject(); } + + @JsonProperty("type") + public String getType() { + return "error"; + } } diff --git a/main/src/com/google/refine/model/ReconStats.java b/main/src/com/google/refine/model/ReconStats.java index a0c3ea6d4..00f555e29 100644 --- a/main/src/com/google/refine/model/ReconStats.java +++ b/main/src/com/google/refine/model/ReconStats.java @@ -40,6 +40,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.expr.ExpressionUtils; import com.google.refine.model.Recon.Judgment; @@ -53,8 +55,11 @@ public class ReconStats implements Jsonizable { ); } + @JsonProperty("nonBlanks") final public int nonBlanks; + @JsonProperty("newTopics") final public int newTopics; + @JsonProperty("matchedTopics") final public int matchedTopics; public ReconStats(int nonBlanks, int newTopics, int matchedTopics) { diff --git a/main/src/com/google/refine/model/ReconType.java b/main/src/com/google/refine/model/ReconType.java index 088da69b5..3f172bf28 100644 --- a/main/src/com/google/refine/model/ReconType.java +++ b/main/src/com/google/refine/model/ReconType.java @@ -39,6 +39,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; /** @@ -47,7 +49,9 @@ import com.google.refine.Jsonizable; * store the (expected) types of new columns. */ public class ReconType implements Jsonizable { + @JsonProperty("id") public String id; + @JsonProperty("name") public String name; public ReconType(String id, String name) { diff --git a/main/src/com/google/refine/util/ParsingUtilities.java b/main/src/com/google/refine/util/ParsingUtilities.java index 8b51fcc04..e067a26fd 100644 --- a/main/src/com/google/refine/util/ParsingUtilities.java +++ b/main/src/com/google/refine/util/ParsingUtilities.java @@ -59,6 +59,9 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; +import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -74,6 +77,8 @@ public class ParsingUtilities { module.addSerializer(double.class, new SerializationFilters.DoubleSerializer()); module.addSerializer(OffsetDateTime.class, new SerializationFilters.DateSerializer()); mapper.registerModule(module); + mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } public static final FilterProvider defaultFilters = new SimpleFilterProvider() From 0583ae659d509d7cce1d60cf94ba1ab471426fff Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 30 Sep 2018 11:32:08 +0100 Subject: [PATCH 021/164] Make FileProjectManagerTests independent from RefineTest --- .../tests/io/FileProjectManagerTests.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/main/tests/server/src/com/google/refine/tests/io/FileProjectManagerTests.java b/main/tests/server/src/com/google/refine/tests/io/FileProjectManagerTests.java index 80e470c73..8d7294e1d 100644 --- a/main/tests/server/src/com/google/refine/tests/io/FileProjectManagerTests.java +++ b/main/tests/server/src/com/google/refine/tests/io/FileProjectManagerTests.java @@ -1,16 +1,24 @@ package com.google.refine.tests.io; -import java.io.File; - -import org.testng.annotations.Test; import static org.mockito.Mockito.mock; +import java.io.File; +import java.io.IOException; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + import com.google.refine.io.FileProjectManager; import com.google.refine.model.metadata.ProjectMetadata; -import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; -public class FileProjectManagerTests extends RefineTest { +public class FileProjectManagerTests { + protected File workspaceDir; + + @BeforeMethod + public void createDirectory() throws IOException { + workspaceDir = TestUtils.createTempDirectory("openrefine-test-workspace-dir"); + } protected class FileProjectManagerStub extends FileProjectManager { From 65231e21400ef7bdf50267792cfd4369e26de956 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 1 Oct 2018 11:57:58 +0100 Subject: [PATCH 022/164] Refactor GetRowsCommand for Jackson migration --- .../refine/commands/row/GetRowsCommand.java | 141 ++++++++++++------ .../commands/row/GetRowsCommandTest.java | 116 ++++++++++++++ 2 files changed, 213 insertions(+), 44 deletions(-) create mode 100644 main/tests/server/src/com/google/refine/tests/commands/row/GetRowsCommandTest.java diff --git a/main/src/com/google/refine/commands/row/GetRowsCommand.java b/main/src/com/google/refine/commands/row/GetRowsCommand.java index add2f4314..60d3bf366 100644 --- a/main/src/com/google/refine/commands/row/GetRowsCommand.java +++ b/main/src/com/google/refine/commands/row/GetRowsCommand.java @@ -35,6 +35,8 @@ package com.google.refine.commands.row; import java.io.IOException; import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; import java.util.Properties; import javax.servlet.ServletException; @@ -45,6 +47,12 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonUnwrapped; + +import com.google.refine.Jsonizable; import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.FilteredRecords; @@ -65,6 +73,82 @@ import com.google.refine.util.Pool; public class GetRowsCommand extends Command { + protected static class WrappedRow implements Jsonizable { + @JsonUnwrapped + protected final Row row; + @JsonProperty("rowIndex") + protected final int rowIndex; + @JsonProperty("recordIndex") + @JsonInclude(Include.NON_NULL) + protected final Integer recordIndex; + + protected WrappedRow(Row rowOrRecord, int rowIndex, Integer recordIndex) { + this.row = rowOrRecord; + this.rowIndex = rowIndex; + this.recordIndex = recordIndex; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + options.put("rowIndex", rowIndex); + if(recordIndex != null) { + options.put("recordIndex", recordIndex); + } + row.write(writer, options); + if(recordIndex != null) { + options.remove("recordIndex"); + } + } + + } + + protected static class JsonResult implements Jsonizable { + @JsonProperty("mode") + protected final Mode mode; + @JsonProperty("rows") + protected final List rows; + @JsonProperty("filtered") + protected final int filtered; + @JsonProperty("total") + protected final int totalCount; + @JsonProperty("start") + protected final int start; + @JsonProperty("limit") + protected final int limit; + @JsonProperty("pool") + protected final Pool pool; + + protected JsonResult(Mode mode, List rows, int filtered, + int totalCount, int start, int limit, Pool pool) { + this.mode = mode; + this.rows = rows; + this.filtered = filtered; + this.totalCount = totalCount; + this.start = start; + this.limit = limit; + this.pool = pool; + } + + @Override + public void write(JSONWriter jsonWriter, Properties options) + throws JSONException { + jsonWriter.object(); + jsonWriter.key("mode"); jsonWriter.value(mode == Mode.RowBased ? "row-based" : "record-based"); + jsonWriter.key("rows"); jsonWriter.array(); + for(WrappedRow row : rows) { + row.write(jsonWriter, options); + } + jsonWriter.endArray(); + jsonWriter.key("filtered"); jsonWriter.value(filtered); + jsonWriter.key("total"); jsonWriter.value(totalCount); + jsonWriter.key("start"); jsonWriter.value(start); + jsonWriter.key("limit"); jsonWriter.value(limit); + jsonWriter.key("pool"); pool.write(jsonWriter, options); + jsonWriter.endObject(); + } + } + @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -117,9 +201,8 @@ public class GetRowsCommand extends Command { } JSONWriter jsonWriter = new JSONWriter(writer); - jsonWriter.object(); - RowWritingVisitor rwv = new RowWritingVisitor(start, limit, jsonWriter, options); + RowWritingVisitor rwv = new RowWritingVisitor(start, limit); SortingConfig sortingConfig = null; try{ @@ -131,7 +214,7 @@ public class GetRowsCommand extends Command { } } catch (JSONException e) { } - + if (engine.getMode() == Mode.RowBased) { FilteredRows filteredRows = engine.getAllFilteredRows(); RowVisitor visitor = rwv; @@ -144,13 +227,7 @@ public class GetRowsCommand extends Command { visitor = srv; } } - - jsonWriter.key("mode"); jsonWriter.value("row-based"); - jsonWriter.key("rows"); jsonWriter.array(); filteredRows.accept(project, visitor); - jsonWriter.endArray(); - jsonWriter.key("filtered"); jsonWriter.value(rwv.total); - jsonWriter.key("total"); jsonWriter.value(project.rows.size()); } else { FilteredRecords filteredRecords = engine.getFilteredRecords(); RecordVisitor visitor = rwv; @@ -163,22 +240,15 @@ public class GetRowsCommand extends Command { visitor = srv; } } - - jsonWriter.key("mode"); jsonWriter.value("record-based"); - jsonWriter.key("rows"); jsonWriter.array(); filteredRecords.accept(project, visitor); - jsonWriter.endArray(); - jsonWriter.key("filtered"); jsonWriter.value(rwv.total); - jsonWriter.key("total"); jsonWriter.value(project.recordModel.getRecordCount()); } - jsonWriter.key("start"); jsonWriter.value(start); - jsonWriter.key("limit"); jsonWriter.value(limit); - jsonWriter.key("pool"); pool.write(jsonWriter, options); - - jsonWriter.endObject(); - + JsonResult result = new JsonResult(engine.getMode(), + rwv.results, rwv.total, + engine.getMode() == Mode.RowBased ? project.rows.size() : project.recordModel.getRecordCount(), + start, limit, pool); + result.write(jsonWriter, options); if (callback != null) { writer.write(")"); } @@ -195,16 +265,14 @@ public class GetRowsCommand extends Command { static protected class RowWritingVisitor implements RowVisitor, RecordVisitor { final int start; final int limit; - final JSONWriter writer; - final Properties options; + public List results; public int total; - public RowWritingVisitor(int start, int limit, JSONWriter writer, Properties options) { + public RowWritingVisitor(int start, int limit) { this.start = start; this.limit = limit; - this.writer = writer; - this.options = options; + this.results = new ArrayList<>(); } @Override @@ -238,29 +306,14 @@ public class GetRowsCommand extends Command { } public boolean internalVisit(Project project, int rowIndex, Row row) { - try { - options.put("rowIndex", rowIndex); - row.write(writer, options); - } catch (JSONException e) { - } + results.add(new WrappedRow(row, rowIndex, null)); return false; } protected boolean internalVisit(Project project, Record record) { - options.put("recordIndex", record.recordIndex); - for (int r = record.fromRowIndex; r < record.toRowIndex; r++) { - try { - Row row = project.rows.get(r); - - options.put("rowIndex", r); - - row.write(writer, options); - - } catch (JSONException e) { - } - - options.remove("recordIndex"); + Row row = project.rows.get(r); + results.add(new WrappedRow(row, r, r == record.fromRowIndex ? record.recordIndex : null)); } return false; } diff --git a/main/tests/server/src/com/google/refine/tests/commands/row/GetRowsCommandTest.java b/main/tests/server/src/com/google/refine/tests/commands/row/GetRowsCommandTest.java new file mode 100644 index 000000000..d35315c7d --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/commands/row/GetRowsCommandTest.java @@ -0,0 +1,116 @@ +package com.google.refine.tests.commands.row; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.refine.commands.Command; +import com.google.refine.commands.row.GetRowsCommand; +import com.google.refine.model.Project; +import com.google.refine.tests.RefineTest; +import com.google.refine.tests.util.TestUtils; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +public class GetRowsCommandTest extends RefineTest { + + HttpServletRequest request = null; + HttpServletResponse response = null; + Command command = null; + Project project = null; + StringWriter writer = null; + + @BeforeMethod + public void setUp() { + request = mock(HttpServletRequest.class); + response = mock(HttpServletResponse.class); + project = createCSVProject("a,b\nc,d\n,f"); + command = new GetRowsCommand(); + writer = new StringWriter(); + when(request.getParameter("project")).thenReturn(String.valueOf(project.id)); + try { + when(response.getWriter()).thenReturn(new PrintWriter(writer)); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Test + public void testJsonOutputRows() throws ServletException, IOException { + String rowJson = "{\n" + + " \"filtered\" : 2,\n" + + " \"limit\" : 2,\n" + + " \"mode\" : \"row-based\",\n" + + " \"pool\" : {\n" + + " \"recons\" : { }\n" + + " },\n" + + " \"rows\" : [ {\n" + + " \"cells\" : [ {\n" + + " \"v\" : \"c\"\n" + + " }, {\n" + + " \"v\" : \"d\"\n" + + " } ],\n" + + " \"flagged\" : false,\n" + + " \"i\" : 0,\n" + + " \"starred\" : false\n" + + " }, {\n" + + " \"cells\" : [ null, {\n" + + " \"v\" : \"f\"\n" + + " } ],\n" + + " \"flagged\" : false,\n" + + " \"i\" : 1,\n" + + " \"starred\" : false\n" + + " } ],\n" + + " \"start\" : 0,\n" + + " \"total\" : 2\n" + + " }"; + + when(request.getParameter("engine")).thenReturn("{\"mode\":\"row-based\",\"facets\":[]}"); + command.doPost(request, response); + TestUtils.assertEqualAsJson(rowJson, writer.toString()); + } + + @Test + public void testJsonOutputRecords() throws ServletException, IOException { + String recordJson = "{\n" + + " \"filtered\" : 1,\n" + + " \"limit\" : 2,\n" + + " \"mode\" : \"record-based\",\n" + + " \"pool\" : {\n" + + " \"recons\" : { }\n" + + " },\n" + + " \"rows\" : [ {\n" + + " \"cells\" : [ {\n" + + " \"v\" : \"c\"\n" + + " }, {\n" + + " \"v\" : \"d\"\n" + + " } ],\n" + + " \"flagged\" : false,\n" + + " \"i\" : 0,\n" + + " \"j\" : 0,\n" + + " \"starred\" : false\n" + + " }, {\n" + + " \"cells\" : [ null, {\n" + + " \"v\" : \"f\"\n" + + " } ],\n" + + " \"flagged\" : false,\n" + + " \"i\" : 1,\n" + + " \"starred\" : false\n" + + " } ],\n" + + " \"start\" : 0,\n" + + " \"total\" : 1\n" + + " }"; + + when(request.getParameter("engine")).thenReturn("{\"mode\":\"record-based\",\"facets\":[]}"); + command.doPost(request, response); + TestUtils.assertEqualAsJson(recordJson, writer.toString()); + } +} From fd69e4b980b4d0f79ec678110967c43f01ed0046 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 1 Oct 2018 15:52:08 +0100 Subject: [PATCH 023/164] Serialization tests for expression commands --- .../expr/GetExpressionHistoryCommand.java | 3 - .../expr/ExpressionCommandTestBase.java | 70 +++++++++++++++++ .../GetExpressionHistoryCommandTests.java | 55 ++++++++++++++ ...GetExpressionLanguageInfoCommandTests.java | 37 +++++++++ .../GetStarredExpressionsCommandTests.java | 44 +++++++++++ .../expr/PreviewExpressionCommandTests.java | 76 +++++++++++++++++++ .../ToggleStarredExpressionCommandTests.java | 49 ++++++++++++ 7 files changed, 331 insertions(+), 3 deletions(-) create mode 100644 main/tests/server/src/com/google/refine/tests/commands/expr/ExpressionCommandTestBase.java create mode 100644 main/tests/server/src/com/google/refine/tests/commands/expr/GetExpressionHistoryCommandTests.java create mode 100644 main/tests/server/src/com/google/refine/tests/commands/expr/GetExpressionLanguageInfoCommandTests.java create mode 100644 main/tests/server/src/com/google/refine/tests/commands/expr/GetStarredExpressionsCommandTests.java create mode 100644 main/tests/server/src/com/google/refine/tests/commands/expr/PreviewExpressionCommandTests.java create mode 100644 main/tests/server/src/com/google/refine/tests/commands/expr/ToggleStarredExpressionCommandTests.java diff --git a/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java b/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java index 950e7eab9..1c1ef7bc4 100644 --- a/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java +++ b/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java @@ -47,7 +47,6 @@ import org.json.JSONWriter; import com.google.refine.ProjectManager; import com.google.refine.commands.Command; -import com.google.refine.model.Project; import com.google.refine.preference.TopList; public class GetExpressionHistoryCommand extends Command { @@ -61,8 +60,6 @@ public class GetExpressionHistoryCommand extends Command { throws ServletException, IOException { try { - Project project = getProject(request); - List localExpressions = toExpressionList(ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")); localExpressions = localExpressions.size() > 20 ? localExpressions.subList(0, 20) : localExpressions; diff --git a/main/tests/server/src/com/google/refine/tests/commands/expr/ExpressionCommandTestBase.java b/main/tests/server/src/com/google/refine/tests/commands/expr/ExpressionCommandTestBase.java new file mode 100644 index 000000000..f2ffb2244 --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/commands/expr/ExpressionCommandTestBase.java @@ -0,0 +1,70 @@ +package com.google.refine.tests.commands.expr; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.FileUtils; +import org.testng.annotations.BeforeMethod; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; + +import com.google.refine.commands.Command; +import com.google.refine.io.FileProjectManager; +import com.google.refine.tests.util.TestUtils; + +public class ExpressionCommandTestBase { + protected HttpServletRequest request = null; + protected HttpServletResponse response = null; + protected Command command = null; + protected StringWriter writer = null; + + @BeforeMethod + public void setUpRequestResponse() { + request = mock(HttpServletRequest.class); + response = mock(HttpServletResponse.class); + writer = new StringWriter(); + try { + when(response.getWriter()).thenReturn(new PrintWriter(writer)); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void initWorkspace(String expressionsJson, String starredExpressionsJson) { + String starred = starredExpressionsJson == null ? "{\"class\":\"com.google.refine.preference.TopList\",\"top\":2147483647," + + "\"list\":[]}" : starredExpressionsJson; + String expressions = expressionsJson == null ? "{\"class\":\"com.google.refine.preference.TopList\",\"top\":100,\"list\":[]}" : expressionsJson; + try { + File workspaceDir = TestUtils.createTempDirectory("openrefine-test-workspace-dir"); + File jsonPath = new File(workspaceDir, "workspace.json"); + FileUtils.writeStringToFile(jsonPath, "{\"projectIDs\":[]\n" + + ",\"preferences\":{\"entries\":{\"scripting.starred-expressions\":" + starred + + ",\"scripting.expressions\":"+expressions+"}}}"); + FileProjectManager.initialize(workspaceDir); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void assertResponseJsonIs(String expectedJson) { + String actualJson = writer.toString(); + if(!TestUtils.equalAsJson(expectedJson, actualJson)) { + try { + TestUtils.jsonDiff(expectedJson, actualJson); + } catch (JsonParseException | JsonMappingException e) { + e.printStackTrace(); + } + } + TestUtils.assertEqualAsJson(expectedJson, actualJson); + } + +} diff --git a/main/tests/server/src/com/google/refine/tests/commands/expr/GetExpressionHistoryCommandTests.java b/main/tests/server/src/com/google/refine/tests/commands/expr/GetExpressionHistoryCommandTests.java new file mode 100644 index 000000000..a563d3dd8 --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/commands/expr/GetExpressionHistoryCommandTests.java @@ -0,0 +1,55 @@ +package com.google.refine.tests.commands.expr; + +import java.io.IOException; + +import javax.servlet.ServletException; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.refine.commands.expr.GetExpressionHistoryCommand; + +public class GetExpressionHistoryCommandTests extends ExpressionCommandTestBase { + + @BeforeMethod + public void setUp() { + command = new GetExpressionHistoryCommand(); + } + + @Test + public void testJsonResponse() throws ServletException, IOException { + + initWorkspace("{\n" + + " \"class\": \"com.google.refine.preference.TopList\",\n" + + " \"top\": 100,\n" + + " \"list\": [\n" + + " \"grel:facetCount(value, 'value', 'Column 1')\",\n" + + " \"grel:facetCount(value, 'value', 'Column 3')\",\n" + + " \"grel:cell.recon.match.id\"" + + "]}", "{\n" + + " \"class\": \"com.google.refine.preference.TopList\",\n" + + " \"top\": 100,\n" + + " \"list\": [\n" + + " \"grel:cell.recon.match.id\"\n" + + "]}"); + + String json = "{\n" + + " \"expressions\" : [ {\n" + + " \"code\" : \"grel:facetCount(value, 'value', 'Column 1')\",\n" + + " \"global\" : false,\n" + + " \"starred\" : false\n" + + " }, {\n" + + " \"code\" : \"grel:facetCount(value, 'value', 'Column 3')\",\n" + + " \"global\" : false,\n" + + " \"starred\" : false\n" + + " }, {\n" + + " \"code\" : \"grel:cell.recon.match.id\",\n" + + " \"global\" : false,\n" + + " \"starred\" : true\n" + + " } ]\n" + + " }"; + command.doGet(request, response); + assertResponseJsonIs(json); + } + +} diff --git a/main/tests/server/src/com/google/refine/tests/commands/expr/GetExpressionLanguageInfoCommandTests.java b/main/tests/server/src/com/google/refine/tests/commands/expr/GetExpressionLanguageInfoCommandTests.java new file mode 100644 index 000000000..b80159be2 --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/commands/expr/GetExpressionLanguageInfoCommandTests.java @@ -0,0 +1,37 @@ +package com.google.refine.tests.commands.expr; + +import java.io.IOException; + +import javax.servlet.ServletException; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.fasterxml.jackson.databind.JsonNode; + +import com.google.refine.commands.expr.GetExpressionLanguageInfoCommand; +import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; + +public class GetExpressionLanguageInfoCommandTests extends ExpressionCommandTestBase { + + @BeforeMethod + public void setUp() { + command = new GetExpressionLanguageInfoCommand(); + } + + @Test + public void testJsonResponse() throws ServletException, IOException { + + initWorkspace(null, null); + + command.doGet(request, response); + String jsonResponse = writer.toString(); + JsonNode result = ParsingUtilities.mapper.readValue(jsonResponse, JsonNode.class); + TestUtils.assertEqualAsJson("{\n" + + " \"description\" : \"Evaluates expression a to an array. Then for each array element, binds its value to variable name v, evaluates expression test which should return a boolean. If the boolean is true, pushes v onto the result array.\",\n" + + " \"params\" : \"expression a, variable v, expression test\",\n" + + " \"returns\" : \"array\"\n" + + " }", result.get("controls").get("filter").toString()); + } +} diff --git a/main/tests/server/src/com/google/refine/tests/commands/expr/GetStarredExpressionsCommandTests.java b/main/tests/server/src/com/google/refine/tests/commands/expr/GetStarredExpressionsCommandTests.java new file mode 100644 index 000000000..f341bdaf8 --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/commands/expr/GetStarredExpressionsCommandTests.java @@ -0,0 +1,44 @@ +package com.google.refine.tests.commands.expr; + +import java.io.IOException; + +import javax.servlet.ServletException; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.refine.commands.expr.GetStarredExpressionsCommand; + +public class GetStarredExpressionsCommandTests extends ExpressionCommandTestBase { + + @BeforeMethod + public void setUp() { + command = new GetStarredExpressionsCommand(); + } + + @Test + public void testJsonResponse() throws ServletException, IOException { + + initWorkspace("{\n" + + " \"class\": \"com.google.refine.preference.TopList\",\n" + + " \"top\": 100,\n" + + " \"list\": [\n" + + " \"grel:facetCount(value, 'value', 'Column 1')\",\n" + + " \"grel:facetCount(value, 'value', 'Column 3')\",\n" + + " \"grel:cell.recon.match.id\"" + + "]}", "{\n" + + " \"class\": \"com.google.refine.preference.TopList\",\n" + + " \"top\": 100,\n" + + " \"list\": [\n" + + " \"grel:cell.recon.match.id\"\n" + + "]}"); + + String json = "{\n" + + " \"expressions\" : [ {\n" + + " \"code\" : \"grel:cell.recon.match.id\"\n" + + " } ]\n" + + " }"; + command.doGet(request, response); + assertResponseJsonIs(json); + } +} diff --git a/main/tests/server/src/com/google/refine/tests/commands/expr/PreviewExpressionCommandTests.java b/main/tests/server/src/com/google/refine/tests/commands/expr/PreviewExpressionCommandTests.java new file mode 100644 index 000000000..268107b51 --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/commands/expr/PreviewExpressionCommandTests.java @@ -0,0 +1,76 @@ +package com.google.refine.tests.commands.expr; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.refine.commands.Command; +import com.google.refine.commands.expr.PreviewExpressionCommand; +import com.google.refine.model.Project; +import com.google.refine.tests.RefineTest; +import com.google.refine.tests.util.TestUtils; + +public class PreviewExpressionCommandTests extends RefineTest { + protected Project project = null; + protected HttpServletRequest request = null; + protected HttpServletResponse response = null; + protected Command command = null; + protected StringWriter writer = null; + + @BeforeMethod + public void setUpRequestResponse() { + request = mock(HttpServletRequest.class); + response = mock(HttpServletResponse.class); + writer = new StringWriter(); + try { + when(response.getWriter()).thenReturn(new PrintWriter(writer)); + } catch (IOException e) { + e.printStackTrace(); + } + command = new PreviewExpressionCommand(); + project = createCSVProject("a,b\nc,d\ne,f\ng,h"); + } + + @Test + public void testJsonResponse() throws ServletException, IOException { + + when(request.getParameter("project")).thenReturn(Long.toString(project.id)); + when(request.getParameter("cellIndex")).thenReturn("1"); + when(request.getParameter("expression")).thenReturn("grel:value + \"_u\""); + when(request.getParameter("rowIndices")).thenReturn("[0,2]"); + + String json = "{\n" + + " \"code\" : \"ok\",\n" + + " \"results\" : [ \"d_u\", \"h_u\" ]\n" + + " }"; + command.doPost(request, response); + TestUtils.assertEqualAsJson(json, writer.toString()); + } + + @Test + public void testParseError() throws ServletException, IOException { + + when(request.getParameter("project")).thenReturn(Long.toString(project.id)); + when(request.getParameter("cellIndex")).thenReturn("1"); + when(request.getParameter("expression")).thenReturn("grel:value +"); + when(request.getParameter("rowIndices")).thenReturn("[0,2]"); + + String json = "{\n" + + " \"code\" : \"error\",\n" + + " \"message\" : \"Parsing error at offset 7: Expecting something more at end of expression\",\n" + + " \"type\" : \"parser\"\n" + + " }"; + command.doPost(request, response); + TestUtils.assertEqualAsJson(json, writer.toString()); + } +} diff --git a/main/tests/server/src/com/google/refine/tests/commands/expr/ToggleStarredExpressionCommandTests.java b/main/tests/server/src/com/google/refine/tests/commands/expr/ToggleStarredExpressionCommandTests.java new file mode 100644 index 000000000..019fa43ba --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/commands/expr/ToggleStarredExpressionCommandTests.java @@ -0,0 +1,49 @@ +package com.google.refine.tests.commands.expr; + +import java.io.IOException; +import static org.mockito.Mockito.when; + +import javax.servlet.ServletException; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.refine.commands.expr.ToggleStarredExpressionCommand; + +public class ToggleStarredExpressionCommandTests extends ExpressionCommandTestBase { + + @BeforeMethod + public void setUp() { + command = new ToggleStarredExpressionCommand(); + } + + @Test + public void testJsonResponse() throws ServletException, IOException { + + initWorkspace("{\n" + + " \"class\": \"com.google.refine.preference.TopList\",\n" + + " \"top\": 100,\n" + + " \"list\": [\n" + + " \"grel:facetCount(value, 'value', 'Column 1')\",\n" + + " \"grel:facetCount(value, 'value', 'Column 3')\",\n" + + " \"grel:cell.recon.match.id\"" + + "]}", "{\n" + + " \"class\": \"com.google.refine.preference.TopList\",\n" + + " \"top\": 100,\n" + + " \"list\": [\n" + + " \"grel:cell.recon.match.id\"\n" + + "]}"); + + String json = "{\n" + + " \"expressions\" : [ {\n" + + " \"code\" : \"grel:facetCount(value, 'value', 'Column 1')\"\n" + + " }, {\n" + + " \"code\" : \"grel:cell.recon.match.id\"\n" + + " } ]\n" + + " }"; + when(request.getParameter("expression")).thenReturn("grel:facetCount(value, 'value', 'Column 1')"); + when(request.getParameter("returnList")).thenReturn("yes"); + command.doPost(request, response); + assertResponseJsonIs(json); + } +} From 553a73ec407ce95c952ee02e0cbc8b10bb280c94 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 1 Oct 2018 17:27:29 +0100 Subject: [PATCH 024/164] Refactor expression commands for Jackson serialization --- .../expr/GetExpressionHistoryCommand.java | 90 ++++++++----- .../GetExpressionLanguageInfoCommand.java | 43 +++++-- .../expr/GetStarredExpressionsCommand.java | 63 +++++++--- .../commands/expr/LogExpressionCommand.java | 2 - .../expr/PreviewExpressionCommand.java | 118 ++++++++++++++---- .../expr/ToggleStarredExpressionCommand.java | 18 +-- .../refine/grel/ControlFunctionRegistry.java | 7 ++ 7 files changed, 238 insertions(+), 103 deletions(-) diff --git a/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java b/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java index 1c1ef7bc4..18385f579 100644 --- a/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java +++ b/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java @@ -37,19 +37,71 @@ import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Properties; import java.util.Set; +import java.util.stream.Collectors; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.commands.Command; import com.google.refine.preference.TopList; public class GetExpressionHistoryCommand extends Command { + + public static class ExpressionState implements Jsonizable { + @JsonProperty("code") + protected String code; + @JsonProperty("global") + protected boolean global = false; + @JsonProperty("starred") + protected boolean starred; + + protected ExpressionState(String code, boolean starred) { + this.code = code; + this.starred = starred; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("code"); writer.value(code); + writer.key("global"); writer.value(false); + writer.key("starred"); writer.value(starred); + writer.endObject(); + } + } + + public static class ExpressionsList implements Jsonizable { + @JsonProperty("expressions") + List expressions; + + protected ExpressionsList(List states) { + this.expressions = states; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("expressions"); + writer.array(); + for (ExpressionState e : expressions) { + e.write(writer, options); + } + writer.endArray(); + writer.endObject(); + } + } static protected List toExpressionList(Object o) { return o == null ? new ArrayList() : ((TopList) o).getList(); @@ -60,40 +112,14 @@ public class GetExpressionHistoryCommand extends Command { throws ServletException, IOException { try { - List localExpressions = toExpressionList(ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")); - localExpressions = localExpressions.size() > 20 ? localExpressions.subList(0, 20) : localExpressions; - List globalExpressions = toExpressionList(ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")); + List expressions = toExpressionList(ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")); Set starredExpressions = new HashSet(((TopList)ProjectManager.singleton.getPreferenceStore().get("scripting.starred-expressions")).getList()); - - Set done = new HashSet(); - - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - writer.object(); - writer.key("expressions"); - writer.array(); - for (String s : localExpressions) { - writer.object(); - writer.key("code"); writer.value(s); - writer.key("global"); writer.value(false); - writer.key("starred"); writer.value(starredExpressions.contains(s)); - writer.endObject(); - done.add(s); - } - for (String s : globalExpressions) { - if (!done.contains(s)) { - writer.object(); - writer.key("code"); writer.value(s); - writer.key("global"); writer.value(true); - writer.key("starred"); writer.value(starredExpressions.contains(s)); - writer.endObject(); - } - } - writer.endArray(); - writer.endObject(); + ExpressionsList expressionsList = new ExpressionsList(expressions.stream() + .map(s -> new ExpressionState(s, starredExpressions.contains(s))) + .collect(Collectors.toList())); + + respondJSON(response, expressionsList); } catch (Exception e) { respondException(response, e); } diff --git a/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java b/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java index 13023b561..b5400d909 100644 --- a/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java +++ b/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java @@ -34,6 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.commands.expr; import java.io.IOException; +import java.util.Map; import java.util.Map.Entry; import java.util.Properties; @@ -41,8 +42,12 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import com.google.refine.Jsonizable; import com.google.refine.commands.Command; import com.google.refine.grel.Control; import com.google.refine.grel.ControlFunctionRegistry; @@ -50,23 +55,27 @@ import com.google.refine.grel.Function; public class GetExpressionLanguageInfoCommand extends Command { - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { + public static class LanguageInfo implements Jsonizable { - try { - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - Properties options = new Properties(); - + @JsonProperty("functions") + Map functions; + @JsonProperty("controls") + Map controls; + + public LanguageInfo() { + functions = ControlFunctionRegistry.getFunctionMap(); + controls = ControlFunctionRegistry.getControlMap(); + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { writer.object(); writer.key("functions"); writer.object(); { - for (Entry entry : ControlFunctionRegistry.getFunctionMapping()) { + for (Entry entry : functions.entrySet()) { writer.key(entry.getKey()); entry.getValue().write(writer, options); } @@ -76,7 +85,7 @@ public class GetExpressionLanguageInfoCommand extends Command { writer.key("controls"); writer.object(); { - for (Entry entry : ControlFunctionRegistry.getControlMapping()) { + for (Entry entry : controls.entrySet()) { writer.key(entry.getKey()); entry.getValue().write(writer, options); } @@ -84,6 +93,16 @@ public class GetExpressionLanguageInfoCommand extends Command { writer.endObject(); writer.endObject(); + } + + } + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + try { + respondJSON(response, new LanguageInfo()); } catch (Exception e) { respondException(response, e); } diff --git a/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java b/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java index b489d248b..acad51a5c 100644 --- a/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java +++ b/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java @@ -2,13 +2,19 @@ package com.google.refine.commands.expr; import java.io.IOException; import java.util.List; +import java.util.Properties; +import java.util.stream.Collectors; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.commands.Command; import com.google.refine.preference.TopList; @@ -16,27 +22,52 @@ import com.google.refine.preference.TopList; public class GetStarredExpressionsCommand extends Command { + protected static class Expression implements Jsonizable { + @JsonProperty("code") + protected String code; + protected Expression(String c) { + code = c; + } + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("code"); writer.value(code); + writer.endObject(); + } + } + + protected static class ExpressionList implements Jsonizable { + @JsonProperty("expressions") + protected List expressions; + protected ExpressionList(List e) { + expressions = e; + } + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("expressions"); + writer.array(); + for (Expression s : expressions) { + s.write(writer, options); + } + writer.endArray(); + writer.endObject(); + } + } + + public static ExpressionList getExpressionsList() { + List starredExpressions = ((TopList)ProjectManager.singleton.getPreferenceStore().get("scripting.starred-expressions")).getList(); + return new ExpressionList(starredExpressions.stream().map(e -> new Expression(e)).collect(Collectors.toList())); + } + @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { - List starredExpressions = ((TopList)ProjectManager.singleton.getPreferenceStore().get("scripting.starred-expressions")).getList(); - - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - writer.object(); - writer.key("expressions"); - writer.array(); - for (String s : starredExpressions) { - writer.object(); - writer.key("code"); writer.value(s); - writer.endObject(); - } - writer.endArray(); - writer.endObject(); + respondJSON(response, getExpressionsList()); } catch (Exception e) { respondException(response, e); } diff --git a/main/src/com/google/refine/commands/expr/LogExpressionCommand.java b/main/src/com/google/refine/commands/expr/LogExpressionCommand.java index 3723869d8..b5bc0bde1 100644 --- a/main/src/com/google/refine/commands/expr/LogExpressionCommand.java +++ b/main/src/com/google/refine/commands/expr/LogExpressionCommand.java @@ -41,7 +41,6 @@ import javax.servlet.http.HttpServletResponse; import com.google.refine.ProjectManager; import com.google.refine.commands.Command; -import com.google.refine.model.Project; import com.google.refine.preference.TopList; public class LogExpressionCommand extends Command { @@ -51,7 +50,6 @@ public class LogExpressionCommand extends Command { throws ServletException, IOException { try { - Project project = getProject(request); String expression = request.getParameter("expression"); ((TopList) ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")) diff --git a/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java b/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java index 000f33acd..2f5941a6f 100644 --- a/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java +++ b/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java @@ -36,6 +36,7 @@ package com.google.refine.commands.expr; import java.io.IOException; import java.io.Serializable; import java.time.OffsetDateTime; +import java.util.ArrayList; import java.util.List; import java.util.Properties; @@ -48,6 +49,12 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonValue; + +import com.google.refine.Jsonizable; import com.google.refine.commands.Command; import com.google.refine.expr.EvalError; import com.google.refine.expr.Evaluable; @@ -64,6 +71,85 @@ import com.google.refine.util.ParsingUtilities; public class PreviewExpressionCommand extends Command { + protected static interface ExpressionValue extends Jsonizable { } + protected static class ErrorMessage implements ExpressionValue { + @JsonProperty("message") + protected String message; + public ErrorMessage(String m) { + message = m; + } + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("message"); writer.value(message); + writer.endObject(); + } + + } + protected static class SuccessfulEvaluation implements ExpressionValue { + @JsonValue + protected String value; + protected SuccessfulEvaluation(String value) { + this.value = value; + } + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.value(value); + } + + } + + protected static class PreviewResult implements Jsonizable { + @JsonProperty("code") + protected String code; + @JsonProperty("message") + @JsonInclude(Include.NON_NULL) + protected String message; + @JsonProperty("type") + @JsonInclude(Include.NON_NULL) + protected String type; + @JsonProperty("results") + List results; + + public PreviewResult(String code, String message, String type) { + this.code = code; + this.message = message; + this.type = type; + this.results = null; + } + + public PreviewResult(List evaluated) { + this.code = "ok"; + this.message = null; + this.type = null; + this.results = evaluated; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("code"); writer.value(code); + if(message != null) { + writer.key("message"); writer.value(message); + } + if(type != null) { + writer.key("type"); writer.value(type); + } + if(results != null) { + writer.key("results"); + writer.array(); + for(ExpressionValue v : results) { + v.write(writer, options); + } + writer.endArray(); + } + writer.endObject(); + } + } + @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -77,7 +163,7 @@ public class PreviewExpressionCommand extends Command { String expression = request.getParameter("expression"); String rowIndicesString = request.getParameter("rowIndices"); if (rowIndicesString == null) { - respond(response, "{ \"code\" : \"error\", \"message\" : \"No row indices specified\" }"); + respondJSON(response, new PreviewResult("error", "No row indices specified", null)); return; } @@ -91,21 +177,13 @@ public class PreviewExpressionCommand extends Command { } } - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - JSONArray rowIndices = ParsingUtilities.evaluateJsonStringToArray(rowIndicesString); int length = rowIndices.length(); - JSONWriter writer = new JSONWriter(response.getWriter()); - writer.object(); - try { Evaluable eval = MetaParser.parse(expression); - writer.key("code"); writer.value("ok"); - writer.key("results"); writer.array(); - + List evaluated = new ArrayList<>(); Properties bindings = ExpressionUtils.createBindings(project); for (int i = 0; i < length; i++) { Object result = null; @@ -140,31 +218,23 @@ public class PreviewExpressionCommand extends Command { } if (result == null) { - writer.value(null); + evaluated.add(null); } else if (ExpressionUtils.isError(result)) { - writer.object(); - writer.key("message"); writer.value(((EvalError) result).message); - writer.endObject(); + evaluated.add(new ErrorMessage(((EvalError) result).message)); } else { StringBuffer sb = new StringBuffer(); writeValue(sb, result, false); - writer.value(sb.toString()); + evaluated.add(new SuccessfulEvaluation(sb.toString())); } } - writer.endArray(); + respondJSON(response, new PreviewResult(evaluated)); } catch (ParsingException e) { - writer.key("code"); writer.value("error"); - writer.key("type"); writer.value("parser"); - writer.key("message"); writer.value(e.getMessage()); + respondJSON(response, new PreviewResult("error", e.getMessage(), "parser")); } catch (Exception e) { - writer.key("code"); writer.value("error"); - writer.key("type"); writer.value("other"); - writer.key("message"); writer.value(e.getMessage()); + respondJSON(response, new PreviewResult("error", e.getMessage(), "other")); } - - writer.endObject(); } catch (Exception e) { respondException(response, e); } diff --git a/main/src/com/google/refine/commands/expr/ToggleStarredExpressionCommand.java b/main/src/com/google/refine/commands/expr/ToggleStarredExpressionCommand.java index e61faf11d..65558ccc4 100644 --- a/main/src/com/google/refine/commands/expr/ToggleStarredExpressionCommand.java +++ b/main/src/com/google/refine/commands/expr/ToggleStarredExpressionCommand.java @@ -7,8 +7,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONWriter; - import com.google.refine.ProjectManager; import com.google.refine.commands.Command; import com.google.refine.preference.TopList; @@ -30,21 +28,7 @@ public class ToggleStarredExpressionCommand extends Command { if(request.getParameter("returnList") != null) { try { - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - writer.object(); - writer.key("expressions"); - writer.array(); - for (String s : starredExpressions) { - writer.object(); - writer.key("code"); - writer.value(s); - writer.endObject(); - } - writer.endArray(); - writer.endObject(); + respondJSON(response, GetStarredExpressionsCommand.getExpressionsList()); } catch (Exception e) { respondException(response, e); } diff --git a/main/src/com/google/refine/grel/ControlFunctionRegistry.java b/main/src/com/google/refine/grel/ControlFunctionRegistry.java index 397bb193d..8745832b9 100644 --- a/main/src/com/google/refine/grel/ControlFunctionRegistry.java +++ b/main/src/com/google/refine/grel/ControlFunctionRegistry.java @@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.grel; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -168,6 +169,9 @@ public class ControlFunctionRegistry { static public Set> getFunctionMapping() { return s_nameToFunction.entrySet(); } + static public Map getFunctionMap() { + return Collections.unmodifiableMap(s_nameToFunction); + } static public Control getControl(String name) { return s_nameToControl.get(name); @@ -178,6 +182,9 @@ public class ControlFunctionRegistry { static public Set> getControlMapping() { return s_nameToControl.entrySet(); } + static public Map getControlMap() { + return Collections.unmodifiableMap(s_nameToControl); + } static public void registerFunction(String name, Function f) { s_nameToFunction.put(name, f); From e99a491338a2ab212b2e694e83ba36a39bd8bf8f Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Tue, 2 Oct 2018 14:03:19 +0100 Subject: [PATCH 025/164] Refactor workspace commands for Jackson serialization --- .../GetAllProjectMetadataCommand.java | 58 ++++++++++++------- .../workspace/GetAllProjectTagsCommand.java | 53 +++++++++++------ 2 files changed, 74 insertions(+), 37 deletions(-) diff --git a/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java b/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java index 0da7fe0c4..e1f2cdf72 100644 --- a/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java +++ b/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java @@ -46,28 +46,39 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonRawValue; + +import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.commands.Command; import com.google.refine.model.metadata.ProjectMetadata; public class GetAllProjectMetadataCommand extends Command { - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { + public static class AllProjectMetadata implements Jsonizable { + @JsonProperty("projects") + protected Map projects; + @JsonProperty("customMetadataColumns") + @JsonInclude(Include.NON_NULL) + @JsonRawValue + protected String customMetadataColumns; - try { - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - Properties options = new Properties(); - - writer.object(); + protected AllProjectMetadata(Map map, String json) { + projects = map; + customMetadataColumns = json; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + + writer.object(); writer.key("projects"); writer.object(); - Map m = ProjectManager.singleton.getAllProjectMetadata(); - for (Entry e : m.entrySet()) { + for (Entry e : projects.entrySet()) { ProjectMetadata pm = e.getValue(); if (pm != null) { writer.key(e.getKey().toString()); @@ -75,15 +86,22 @@ public class GetAllProjectMetadataCommand extends Command { } } writer.endObject(); - - String userMeta = (String)ProjectManager.singleton.getPreferenceStore().get("userMetadata"); - if (userMeta != null) { - writer.key("customMetadataColumns"); - JSONArray customMetadataColumns = new JSONArray(userMeta); - writer.value(customMetadataColumns); - } + if (customMetadataColumns != null) { + writer.key("customMetadataColumns"); + writer.value(new JSONArray(customMetadataColumns)); + } writer.endObject(); + } + } + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + try { + String userMeta = (String)ProjectManager.singleton.getPreferenceStore().get("userMetadata"); + respondJSON(response, new AllProjectMetadata(ProjectManager.singleton.getAllProjectMetadata(), userMeta)); } catch (JSONException e) { respondException(response, e); } diff --git a/main/src/com/google/refine/commands/workspace/GetAllProjectTagsCommand.java b/main/src/com/google/refine/commands/workspace/GetAllProjectTagsCommand.java index 29c2d5539..80fe2a3d1 100644 --- a/main/src/com/google/refine/commands/workspace/GetAllProjectTagsCommand.java +++ b/main/src/com/google/refine/commands/workspace/GetAllProjectTagsCommand.java @@ -26,7 +26,11 @@ package com.google.refine.commands.workspace; import java.io.IOException; +import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.Properties; +import java.util.Set; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -35,33 +39,48 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.commands.Command; public class GetAllProjectTagsCommand extends Command { + + public static class AllProjectsTags implements Jsonizable { + + @JsonProperty("tags") + protected Set tags; + + protected AllProjectsTags(Set tags) { + this.tags = tags; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("tags"); + writer.array(); + if (tags != null) { + for (String tag : tags) { + writer.value(tag); + } + } + writer.endArray(); + writer.endObject(); + } + + } @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - // Properties options = new Properties(); - - writer.object(); - writer.key("tags"); - writer.array(); - Map tags = ProjectManager.singleton.getAllProjectTags(); - if (tags != null) { - for (Map.Entry entry : tags.entrySet()) { - writer.value(entry.getKey()); - } - } - writer.endArray(); - writer.endObject(); + Map tagMap = ProjectManager.singleton.getAllProjectTags(); + Set tags = tagMap == null ? Collections.emptySet() : tagMap.keySet(); + respondJSON(response, new AllProjectsTags(tags)); } catch (JSONException e) { respondException(response, e); } From 1790799bfe4fb4345354b797435045f3037c3ecd Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Wed, 3 Oct 2018 21:33:37 +0100 Subject: [PATCH 026/164] Remove Jsonizable interface and write methods --- .../database/DatabaseModuleImpl.java | 1 - .../PreviewWikibaseSchemaCommand.java | 92 +++++----- .../commands/SaveWikibaseSchemaCommand.java | 3 +- .../wikidata/editing/WikibaseCredentials.java | 26 +-- .../PerformWikibaseEditsOperation.java | 17 +- .../SaveWikibaseSchemaOperation.java | 25 +-- .../org/openrefine/wikidata/qa/QAWarning.java | 3 +- .../wikidata/schema/WbItemDocumentExpr.java | 3 +- .../wikidata/schema/WikibaseSchema.java | 14 +- .../wikidata/utils/JacksonJsonizable.java | 79 -------- .../wikidata/operations/OperationTest.java | 5 +- .../wikidata/schema/WikibaseSchemaTest.java | 14 +- main/src/com/google/refine/Jsonizable.java | 49 ----- .../refine/browsing/DecoratedValue.java | 16 +- .../com/google/refine/browsing/Engine.java | 20 +-- .../google/refine/browsing/EngineConfig.java | 21 +-- .../google/refine/browsing/facets/Facet.java | 3 +- .../refine/browsing/facets/FacetConfig.java | 3 +- .../refine/browsing/facets/ListFacet.java | 36 +--- .../browsing/facets/NominalFacetChoice.java | 18 +- .../refine/browsing/facets/RangeFacet.java | 74 +------- .../browsing/facets/ScatterplotFacet.java | 75 -------- .../browsing/facets/TextSearchFacet.java | 32 +--- .../browsing/facets/TimeRangeFacet.java | 65 ------- .../google/refine/clustering/Clusterer.java | 3 +- .../refine/clustering/ClustererConfig.java | 3 +- .../clustering/binning/BinningClusterer.java | 50 +----- .../refine/clustering/knn/kNNClusterer.java | 58 +----- .../com/google/refine/commands/Command.java | 33 ++-- .../refine/commands/GetPreferenceCommand.java | 25 +-- .../google/refine/commands/HttpUtilities.java | 9 +- .../commands/cell/EditOneCellCommand.java | 46 +++-- .../expr/GetExpressionHistoryCommand.java | 32 +--- .../GetExpressionLanguageInfoCommand.java | 37 +--- .../expr/GetStarredExpressionsCommand.java | 28 +-- .../expr/PreviewExpressionCommand.java | 43 +---- .../history/GetOperationsCommand.java | 37 +--- .../GetImportingJobStatusCommand.java | 44 +++-- .../project/CreateProjectCommand.java | 2 +- .../commands/project/ExportRowsCommand.java | 1 - .../commands/project/GetMetadataCommand.java | 2 +- .../commands/project/GetModelsCommand.java | 90 +++++----- .../recon/ReconClearOneCellCommand.java | 34 ++-- .../recon/ReconJudgeOneCellCommand.java | 13 +- .../refine/commands/row/GetRowsCommand.java | 61 ++----- .../GetAllProjectMetadataCommand.java | 31 +--- .../workspace/GetAllProjectTagsCommand.java | 22 +-- .../src/com/google/refine/expr/EvalError.java | 17 +- .../com/google/refine/expr/MetaParser.java | 4 +- main/src/com/google/refine/grel/Control.java | 19 +- .../refine/grel/ControlFunctionRegistry.java | 6 +- main/src/com/google/refine/grel/Function.java | 16 +- .../src/com/google/refine/history/Change.java | 1 + .../com/google/refine/history/History.java | 27 +-- .../google/refine/history/HistoryEntry.java | 21 +-- .../google/refine/history/HistoryProcess.java | 16 -- .../importing/DefaultImportingController.java | 30 ++-- .../google/refine/importing/ImportingJob.java | 17 +- .../refine/io/FileHistoryEntryManager.java | 12 +- .../google/refine/io/FileProjectManager.java | 32 +--- .../refine/io/ProjectMetadataUtilities.java | 5 +- .../refine/model/AbstractOperation.java | 3 +- main/src/com/google/refine/model/Cell.java | 42 +---- main/src/com/google/refine/model/Column.java | 37 +--- .../com/google/refine/model/ColumnGroup.java | 32 +--- .../com/google/refine/model/ColumnModel.java | 34 +--- .../com/google/refine/model/OverlayModel.java | 3 +- main/src/com/google/refine/model/Project.java | 10 +- main/src/com/google/refine/model/Recon.java | 56 +----- .../google/refine/model/ReconCandidate.java | 27 +-- .../com/google/refine/model/ReconStats.java | 24 +-- .../com/google/refine/model/ReconType.java | 17 +- .../com/google/refine/model/RecordModel.java | 16 +- main/src/com/google/refine/model/Row.java | 71 ++------ .../refine/model/changes/ColumnChange.java | 13 +- .../model/changes/DataExtensionChange.java | 9 +- .../refine/model/changes/MassReconChange.java | 8 +- .../model/metadata/AbstractMetadata.java | 23 --- .../model/metadata/DataPackageMetadata.java | 42 +---- .../refine/model/metadata/IMetadata.java | 16 +- .../model/metadata/ProjectMetadata.java | 168 ++++++------------ .../metadata/validator/ValidateOperation.java | 11 -- .../model/recon/DataExtensionReconConfig.java | 9 +- .../refine/model/recon/ReconConfig.java | 15 +- .../recon/ReconciledDataExtensionJob.java | 88 ++------- .../model/recon/StandardReconConfig.java | 44 +---- .../operations/cell/BlankDownOperation.java | 16 -- .../operations/cell/FillDownOperation.java | 16 -- .../cell/KeyValueColumnizeOperation.java | 20 --- .../operations/cell/MassEditOperation.java | 42 +---- .../cell/MultiValuedCellJoinOperation.java | 17 -- .../cell/MultiValuedCellSplitOperation.java | 27 --- .../cell/TextTransformOperation.java | 19 -- .../TransposeColumnsIntoRowsOperation.java | 26 --- .../TransposeRowsIntoColumnsOperation.java | 16 -- ...ColumnAdditionByFetchingURLsOperation.java | 40 +---- .../column/ColumnAdditionOperation.java | 19 -- .../column/ColumnMoveOperation.java | 17 -- .../column/ColumnRemovalOperation.java | 16 -- .../column/ColumnRenameOperation.java | 17 -- .../column/ColumnReorderOperation.java | 19 -- .../column/ColumnSplitOperation.java | 30 ---- .../operations/recon/ExtendDataOperation.java | 19 -- .../ReconClearSimilarCellsOperation.java | 18 -- .../ReconCopyAcrossColumnsOperation.java | 29 --- .../recon/ReconDiscardJudgmentsOperation.java | 17 -- .../ReconJudgeSimilarCellsOperation.java | 26 +-- .../recon/ReconMarkNewTopicsOperation.java | 17 -- .../ReconMatchBestCandidatesOperation.java | 16 -- .../ReconMatchSpecificTopicOperation.java | 29 --- .../operations/recon/ReconOperation.java | 61 ------- .../operations/row/DenormalizeOperation.java | 15 -- .../operations/row/RowFlagOperation.java | 16 -- .../operations/row/RowRemovalOperation.java | 15 -- .../operations/row/RowReorderOperation.java | 16 -- .../operations/row/RowStarOperation.java | 16 -- .../refine/preference/PreferenceStore.java | 29 +-- .../com/google/refine/preference/TopList.java | 20 +-- .../refine/process/LongRunningProcess.java | 18 -- .../com/google/refine/process/Process.java | 3 +- .../google/refine/process/ProcessManager.java | 35 +--- .../process/QuickHistoryEntryProcess.java | 17 -- .../com/google/refine/sorting/Criterion.java | 19 +- .../google/refine/sorting/DateCriterion.java | 4 - .../google/refine/sorting/SortingConfig.java | 20 +-- .../com/google/refine/util/JSONUtilities.java | 18 +- .../google/refine/util/ParsingUtilities.java | 11 +- main/src/com/google/refine/util/Pool.java | 37 +--- .../google/refine/tests/model/CellTests.java | 5 +- .../google/refine/tests/model/RowTests.java | 9 +- .../recon/ExtendDataOperationTests.java | 4 +- .../ReconJudgeSimilarCellsOperationTests.java | 4 +- .../recon/ReconJudgeSimilarCellsTests.java | 3 +- .../tests/process/ProcessManagerTests.java | 4 +- .../google/refine/tests/util/TestUtils.java | 42 +---- 135 files changed, 508 insertions(+), 2900 deletions(-) delete mode 100644 extensions/wikidata/src/org/openrefine/wikidata/utils/JacksonJsonizable.java delete mode 100644 main/src/com/google/refine/Jsonizable.java diff --git a/extensions/database/src/com/google/refine/extension/database/DatabaseModuleImpl.java b/extensions/database/src/com/google/refine/extension/database/DatabaseModuleImpl.java index d26fefcf8..3d821f4d4 100644 --- a/extensions/database/src/com/google/refine/extension/database/DatabaseModuleImpl.java +++ b/extensions/database/src/com/google/refine/extension/database/DatabaseModuleImpl.java @@ -40,7 +40,6 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.refine.Jsonizable; import edu.mit.simile.butterfly.ButterflyModuleImpl; diff --git a/extensions/wikidata/src/org/openrefine/wikidata/commands/PreviewWikibaseSchemaCommand.java b/extensions/wikidata/src/org/openrefine/wikidata/commands/PreviewWikibaseSchemaCommand.java index eb3749133..ce496df4b 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/commands/PreviewWikibaseSchemaCommand.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/commands/PreviewWikibaseSchemaCommand.java @@ -27,31 +27,55 @@ package org.openrefine.wikidata.commands; import static org.openrefine.wikidata.commands.CommandUtilities.respondError; import java.io.IOException; -import java.io.StringWriter; import java.util.List; -import java.util.Properties; import java.util.stream.Collectors; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONWriter; import org.openrefine.wikidata.qa.EditInspector; import org.openrefine.wikidata.qa.QAWarning; +import org.openrefine.wikidata.qa.QAWarning.Severity; import org.openrefine.wikidata.qa.QAWarningStore; import org.openrefine.wikidata.schema.WikibaseSchema; import org.openrefine.wikidata.updates.ItemUpdate; import org.openrefine.wikidata.updates.scheduler.WikibaseAPIUpdateScheduler; import com.fasterxml.jackson.databind.ObjectMapper; + import com.google.refine.browsing.Engine; import com.google.refine.commands.Command; import com.google.refine.model.Project; public class PreviewWikibaseSchemaCommand extends Command { + + protected static class PreviewResults { + @JsonProperty("warnings") + List warnings; + @JsonProperty("max_severity") + Severity maxSeverity; + @JsonProperty("nb_warnings") + int nbWarnings; + @JsonProperty("edit_count") + int editCount; + @JsonProperty("edits_preview") + List editsPreview; + + protected PreviewResults( + List warnings, + Severity maxSeverity, + int nbWarnings, + int editCount, + List editsPreview) { + this.warnings = warnings; + this.maxSeverity = maxSeverity; + this.nbWarnings = nbWarnings; + this.editCount = editCount; + this.editsPreview = editsPreview; + } + } @Override public void doPost(HttpServletRequest request, HttpServletResponse response) @@ -87,50 +111,24 @@ public class PreviewWikibaseSchemaCommand extends Command { Engine engine = getEngine(request, project); List editBatch = schema.evaluate(project, engine, warningStore); - StringWriter sb = new StringWriter(2048); - JSONWriter writer = new JSONWriter(sb); - writer.object(); + // Inspect the edits and generate warnings + EditInspector inspector = new EditInspector(warningStore); + inspector.inspect(editBatch); + + // Dump the first 10 edits, scheduled with the default scheduler + WikibaseAPIUpdateScheduler scheduler = new WikibaseAPIUpdateScheduler(); + List nonNullEdits = scheduler.schedule(editBatch).stream() + .filter(e -> !e.isNull()) + .collect(Collectors.toList()); + List firstEdits = nonNullEdits.stream() + .limit(10) + .collect(Collectors.toList()); - { - // Inspect the edits and generate warnings - EditInspector inspector = new EditInspector(warningStore); - inspector.inspect(editBatch); - writer.key("warnings"); - writer.array(); - for (QAWarning warning : warningStore.getWarnings()) { - warning.write(writer, new Properties()); - } - writer.endArray(); - - // Add max warning level - writer.key("max_severity"); - writer.value(warningStore.getMaxSeverity().toString()); - - // this is not the length of the warnings array written before, - // but the total number of issues raised (before deduplication) - writer.key("nb_warnings"); - writer.value(warningStore.getNbWarnings()); - - // Dump the first 10 edits, scheduled with the default scheduler - WikibaseAPIUpdateScheduler scheduler = new WikibaseAPIUpdateScheduler(); - List nonNullEdits = scheduler.schedule(editBatch).stream() - .filter(e -> !e.isNull()) - .collect(Collectors.toList()); - writer.key("edit_count"); - writer.value(nonNullEdits.size()); - List firstEdits = nonNullEdits.stream() - .limit(10) - .collect(Collectors.toList()); - ObjectMapper mapper = new ObjectMapper(); - String firstEditsJson = mapper.writeValueAsString(firstEdits); - - writer.key("edits_preview"); - writer.value(new JSONArray(firstEditsJson)); - } - - writer.endObject(); - - respond(response, sb.toString()); + respondJSON(response, new PreviewResults( + warningStore.getWarnings(), + warningStore.getMaxSeverity(), + warningStore.getNbWarnings(), + nonNullEdits.size(), firstEdits)); } catch (Exception e) { respondException(response, e); } diff --git a/extensions/wikidata/src/org/openrefine/wikidata/commands/SaveWikibaseSchemaCommand.java b/extensions/wikidata/src/org/openrefine/wikidata/commands/SaveWikibaseSchemaCommand.java index 9196fcef5..2dc44a39e 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/commands/SaveWikibaseSchemaCommand.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/commands/SaveWikibaseSchemaCommand.java @@ -23,6 +23,8 @@ ******************************************************************************/ package org.openrefine.wikidata.commands; +import static org.openrefine.wikidata.commands.CommandUtilities.respondError; + import java.io.IOException; import java.util.Properties; @@ -34,7 +36,6 @@ import org.json.JSONException; import org.json.JSONObject; import org.openrefine.wikidata.operations.SaveWikibaseSchemaOperation; import org.openrefine.wikidata.schema.WikibaseSchema; -import static org.openrefine.wikidata.commands.CommandUtilities.respondError; import com.google.refine.commands.Command; import com.google.refine.model.AbstractOperation; diff --git a/extensions/wikidata/src/org/openrefine/wikidata/editing/WikibaseCredentials.java b/extensions/wikidata/src/org/openrefine/wikidata/editing/WikibaseCredentials.java index b8de3581f..c8645dcd3 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/editing/WikibaseCredentials.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/editing/WikibaseCredentials.java @@ -23,13 +23,11 @@ ******************************************************************************/ package org.openrefine.wikidata.editing; -import java.util.Properties; - import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; -import com.google.refine.Jsonizable; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * This is just the necessary bits to store Wikidata credentials in OpenRefine's @@ -38,9 +36,11 @@ import com.google.refine.Jsonizable; * @author Antonin Delpeuch * */ -class WikibaseCredentials implements Jsonizable { +class WikibaseCredentials { + @JsonProperty("username") private String username; + @JsonProperty("password") private String password; public WikibaseCredentials() { @@ -64,18 +64,10 @@ class WikibaseCredentials implements Jsonizable { public boolean isNonNull() { return username != null && password != null && !"null".equals(username) && !"null".equals(password); } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("class"); - writer.value(this.getClass().getName()); - writer.key("username"); - writer.value(username); - writer.key("password"); - writer.value(password); - writer.endObject(); + + @JsonProperty("class") + public String getClassName() { + return getClass().getName(); } public static WikibaseCredentials load(JSONObject obj) diff --git a/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java b/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java index d45c08709..86f0129e1 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java @@ -46,6 +46,7 @@ import org.wikidata.wdtk.wikibaseapi.ApiConnection; import org.wikidata.wdtk.wikibaseapi.WikibaseDataEditor; import org.wikidata.wdtk.wikibaseapi.WikibaseDataFetcher; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.refine.browsing.Engine; @@ -64,6 +65,7 @@ public class PerformWikibaseEditsOperation extends EngineDependentOperation { static final Logger logger = LoggerFactory.getLogger(PerformWikibaseEditsOperation.class); + @JsonProperty("summary") private String summary; public PerformWikibaseEditsOperation(EngineConfig engineConfig, String summary) { @@ -84,21 +86,6 @@ public class PerformWikibaseEditsOperation extends EngineDependentOperation { EngineConfig.reconstruct(engineConfig), summary); } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("op"); - writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); - writer.value("Perform Wikibase edits"); - writer.key("summary"); - writer.value(summary); - writer.key("engineConfig"); - getEngineConfig().write(writer, options); - writer.endObject(); - } - @Override protected String getBriefDescription(Project project) { return "Peform edits on Wikidata"; diff --git a/extensions/wikidata/src/org/openrefine/wikidata/operations/SaveWikibaseSchemaOperation.java b/extensions/wikidata/src/org/openrefine/wikidata/operations/SaveWikibaseSchemaOperation.java index 8303469c6..7eccbbafd 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/operations/SaveWikibaseSchemaOperation.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/operations/SaveWikibaseSchemaOperation.java @@ -33,6 +33,8 @@ import org.json.JSONObject; import org.json.JSONWriter; import org.openrefine.wikidata.schema.WikibaseSchema; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.history.Change; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; @@ -44,6 +46,7 @@ import com.google.refine.util.Pool; public class SaveWikibaseSchemaOperation extends AbstractOperation { final public String operationDescription = "Save Wikibase schema"; + @JsonProperty("schema") final protected WikibaseSchema _schema; public SaveWikibaseSchemaOperation(WikibaseSchema schema) { @@ -56,22 +59,9 @@ public class SaveWikibaseSchemaOperation extends AbstractOperation { return new SaveWikibaseSchemaOperation(WikibaseSchema.reconstruct(obj.getJSONObject("schema"))); } - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("op"); - writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); - writer.value(operationDescription); - writer.key("schema"); - _schema.write(writer, options); - writer.endObject(); - - } - @Override protected String getBriefDescription(Project project) { - return "Save Wikibase schema skelton"; + return operationDescription; } @Override @@ -149,12 +139,7 @@ public class SaveWikibaseSchemaOperation extends AbstractOperation { static protected void writeWikibaseSchema(WikibaseSchema s, Writer writer) throws IOException { if (s != null) { - JSONWriter jsonWriter = new JSONWriter(writer); - try { - s.write(jsonWriter, new Properties()); - } catch (JSONException e) { - e.printStackTrace(); - } + ParsingUtilities.defaultWriter.writeValue(writer, s); } } } diff --git a/extensions/wikidata/src/org/openrefine/wikidata/qa/QAWarning.java b/extensions/wikidata/src/org/openrefine/wikidata/qa/QAWarning.java index a5b98dd09..0b58a42f5 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/qa/QAWarning.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/qa/QAWarning.java @@ -28,7 +28,6 @@ import java.util.Map; import java.util.Map.Entry; import org.jsoup.helper.Validate; -import org.openrefine.wikidata.utils.JacksonJsonizable; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -42,7 +41,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; * @author Antonin Delpeuch * */ -public class QAWarning extends JacksonJsonizable implements Comparable { +public class QAWarning implements Comparable { public enum Severity { INFO, // We just report something to the user but it is probably fine diff --git a/extensions/wikidata/src/org/openrefine/wikidata/schema/WbItemDocumentExpr.java b/extensions/wikidata/src/org/openrefine/wikidata/schema/WbItemDocumentExpr.java index dc198adba..3ecbca5cd 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/schema/WbItemDocumentExpr.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/schema/WbItemDocumentExpr.java @@ -30,7 +30,6 @@ import org.jsoup.helper.Validate; import org.openrefine.wikidata.schema.exceptions.SkipSchemaExpressionException; import org.openrefine.wikidata.updates.ItemUpdate; import org.openrefine.wikidata.updates.ItemUpdateBuilder; -import org.openrefine.wikidata.utils.JacksonJsonizable; import org.wikidata.wdtk.datamodel.interfaces.ItemIdValue; import org.wikidata.wdtk.datamodel.interfaces.Statement; @@ -48,7 +47,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; */ @JsonIgnoreProperties(ignoreUnknown = true) @JsonTypeInfo(use = JsonTypeInfo.Id.NONE) -public class WbItemDocumentExpr extends JacksonJsonizable implements WbExpression { +public class WbItemDocumentExpr implements WbExpression { private WbExpression subject; private List nameDescs; diff --git a/extensions/wikidata/src/org/openrefine/wikidata/schema/WikibaseSchema.java b/extensions/wikidata/src/org/openrefine/wikidata/schema/WikibaseSchema.java index 6c5d98c45..5f25306a7 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/schema/WikibaseSchema.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/schema/WikibaseSchema.java @@ -63,6 +63,7 @@ public class WikibaseSchema implements OverlayModel { final static Logger logger = LoggerFactory.getLogger("RdfSchema"); + @JsonProperty("itemDocuments") protected List itemDocumentExprs = new ArrayList(); protected String baseIri = "http://www.wikidata.org/entity/"; @@ -198,19 +199,6 @@ public class WikibaseSchema implements OverlayModel { throw new JSONException(e.toString()); } } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("itemDocuments"); - writer.array(); - for (WbItemDocumentExpr changeExpr : itemDocumentExprs) { - changeExpr.write(writer, options); - } - writer.endArray(); - writer.endObject(); - } static public WikibaseSchema load(Project project, JSONObject obj) throws Exception { diff --git a/extensions/wikidata/src/org/openrefine/wikidata/utils/JacksonJsonizable.java b/extensions/wikidata/src/org/openrefine/wikidata/utils/JacksonJsonizable.java deleted file mode 100644 index b84c79b7d..000000000 --- a/extensions/wikidata/src/org/openrefine/wikidata/utils/JacksonJsonizable.java +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - * MIT License - * - * Copyright (c) 2018 Antonin Delpeuch - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package org.openrefine.wikidata.utils; - -import java.io.IOException; -import java.util.Properties; - -import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONWriter; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -import com.google.refine.Jsonizable; - -/** - * This class is inefficient because it serializes the object to string and then - * deserializes it back. Unfortunately, this is the only simple way to bridge - * Jackson to org.json. This conversion should be removed when (if ?) we migrate - * OpenRefine a better JSON library. - * - * @author Antonin Delpeuch - * - */ -@JsonIgnoreProperties(ignoreUnknown = true) -public abstract class JacksonJsonizable implements Jsonizable { - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - ObjectMapper mapper = new ObjectMapper(); - try { - writer.value(new JSONObject(mapper.writeValueAsString(this))); - } catch (JsonProcessingException e) { - throw new JSONException(e.toString()); - } - } - - public static T fromJSONClass(JSONObject obj, Class klass) - throws JSONException { - ObjectMapper mapper = new ObjectMapper(); - String json = obj.toString(); - try { - return mapper.readValue(json, klass); - } catch (JsonParseException e) { - throw new JSONException(e.toString()); - } catch (JsonMappingException e) { - throw new JSONException(e.toString()); - } catch (IOException e) { - throw new JSONException(e.toString()); - } - } - -} diff --git a/extensions/wikidata/tests/src/org/openrefine/wikidata/operations/OperationTest.java b/extensions/wikidata/tests/src/org/openrefine/wikidata/operations/OperationTest.java index edd29a260..cfc04fb4e 100644 --- a/extensions/wikidata/tests/src/org/openrefine/wikidata/operations/OperationTest.java +++ b/extensions/wikidata/tests/src/org/openrefine/wikidata/operations/OperationTest.java @@ -33,7 +33,6 @@ import java.io.StringWriter; import java.util.Properties; import org.json.JSONObject; -import org.json.JSONWriter; import org.openrefine.wikidata.testing.JacksonSerializationTest; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -43,6 +42,7 @@ import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.tests.RefineTest; +import com.google.refine.util.ParsingUtilities; import com.google.refine.util.Pool; import edu.mit.simile.butterfly.ButterflyModule; @@ -77,8 +77,7 @@ public abstract class OperationTest extends RefineTest { JSONObject json = getJson(); AbstractOperation op = reconstruct(); StringWriter writer = new StringWriter(); - JSONWriter jsonWriter = new JSONWriter(writer); - op.write(jsonWriter, new Properties()); + ParsingUtilities.defaultWriter.writeValue(writer, op); JacksonSerializationTest.assertJsonEquals(json.toString(), writer.toString()); } diff --git a/extensions/wikidata/tests/src/org/openrefine/wikidata/schema/WikibaseSchemaTest.java b/extensions/wikidata/tests/src/org/openrefine/wikidata/schema/WikibaseSchemaTest.java index 72bd2d941..42ba06c8d 100644 --- a/extensions/wikidata/tests/src/org/openrefine/wikidata/schema/WikibaseSchemaTest.java +++ b/extensions/wikidata/tests/src/org/openrefine/wikidata/schema/WikibaseSchemaTest.java @@ -26,16 +26,13 @@ package org.openrefine.wikidata.schema; import static org.junit.Assert.assertEquals; import java.io.IOException; -import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Properties; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.openrefine.wikidata.testing.TestingData; import org.openrefine.wikidata.updates.ItemUpdate; import org.openrefine.wikidata.updates.ItemUpdateBuilder; @@ -58,7 +55,7 @@ import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.model.Project; import com.google.refine.tests.RefineTest; -import com.google.refine.util.ParsingUtilities; +import com.google.refine.tests.util.TestUtils; public class WikibaseSchemaTest extends RefineTest { @@ -103,14 +100,7 @@ public class WikibaseSchemaTest extends RefineTest { throws JSONException, IOException { JSONObject serialized = TestingData.jsonFromFile("schema/history_of_medicine.json"); WikibaseSchema parsed = WikibaseSchema.reconstruct(serialized); - StringWriter writer = new StringWriter(); - JSONWriter jsonWriter = new JSONWriter(writer); - parsed.write(jsonWriter, new Properties()); - writer.close(); - JSONObject newSerialized = ParsingUtilities.evaluateJsonStringToObject(writer.toString()); - // toString because it looks like JSONObject equality isn't great… - assertEquals(TestingData.jsonFromFile("schema/history_of_medicine_normalized.json").toString(), - newSerialized.toString()); + TestUtils.isSerializedTo(parsed, TestingData.jsonFromFile("data/schema/history_of_medicine_normalized.json").toString()); } @Test diff --git a/main/src/com/google/refine/Jsonizable.java b/main/src/com/google/refine/Jsonizable.java deleted file mode 100644 index 630631d96..000000000 --- a/main/src/com/google/refine/Jsonizable.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - -Copyright 2010, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -package com.google.refine; - -import java.util.Properties; - -import org.json.JSONException; -import org.json.JSONWriter; - -/** - * Interface for streaming out JSON, either into HTTP responses or - * serialization files. - * - * @author dfhuynh - */ -public interface Jsonizable { - public void write(JSONWriter writer, Properties options) throws JSONException; -} diff --git a/main/src/com/google/refine/browsing/DecoratedValue.java b/main/src/com/google/refine/browsing/DecoratedValue.java index 31c617a97..fc8ef95e7 100644 --- a/main/src/com/google/refine/browsing/DecoratedValue.java +++ b/main/src/com/google/refine/browsing/DecoratedValue.java @@ -34,14 +34,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.browsing; import java.time.OffsetDateTime; -import java.util.Properties; - -import org.json.JSONException; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.util.StringUtils; /** @@ -51,7 +46,7 @@ import com.google.refine.util.StringUtils; * * Facet choices that are presented to the user as text are stored as decorated values. */ -public class DecoratedValue implements Jsonizable { +public class DecoratedValue { @JsonProperty("v") final public Object value; @JsonProperty("l") @@ -65,13 +60,4 @@ public class DecoratedValue implements Jsonizable { } this.label = label; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("v"); writer.value(value); - writer.key("l"); writer.value(label); - writer.endObject(); - } } diff --git a/main/src/com/google/refine/browsing/Engine.java b/main/src/com/google/refine/browsing/Engine.java index 4fa193fe1..4feb97ec8 100644 --- a/main/src/com/google/refine/browsing/Engine.java +++ b/main/src/com/google/refine/browsing/Engine.java @@ -36,17 +36,14 @@ package com.google.refine.browsing; import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.Properties; import java.util.stream.Collectors; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; -import com.google.refine.Jsonizable; import com.google.refine.browsing.facets.Facet; import com.google.refine.browsing.util.ConjunctiveFilteredRecords; import com.google.refine.browsing.util.ConjunctiveFilteredRows; @@ -57,7 +54,7 @@ import com.google.refine.model.Row; /** * Faceted browsing engine. */ -public class Engine implements Jsonizable { +public class Engine { static public enum Mode { @JsonProperty("row-based") RowBased, @@ -205,19 +202,4 @@ public class Engine implements Jsonizable { throw new InternalError("Unknown mode."); } } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("facets"); - writer.array(); - for (Facet facet : _facets) { - facet.write(writer, options); - } - writer.endArray(); - writer.key(MODE); writer.value(_config.getMode().equals(Mode.RowBased) ? MODE_ROW_BASED : MODE_RECORD_BASED); - writer.endObject(); - } } diff --git a/main/src/com/google/refine/browsing/EngineConfig.java b/main/src/com/google/refine/browsing/EngineConfig.java index 6a058a29f..b0af26097 100644 --- a/main/src/com/google/refine/browsing/EngineConfig.java +++ b/main/src/com/google/refine/browsing/EngineConfig.java @@ -3,16 +3,12 @@ package com.google.refine.browsing; import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.Properties; import org.json.JSONArray; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.facets.FacetConfig; import com.google.refine.browsing.facets.ListFacet.ListFacetConfig; @@ -22,7 +18,7 @@ import com.google.refine.browsing.facets.TextSearchFacet.TextSearchFacetConfig; import com.google.refine.browsing.facets.TimeRangeFacet.TimeRangeFacetConfig; -public class EngineConfig implements Jsonizable { +public class EngineConfig { protected final List _facets; protected final Mode _mode; @@ -88,19 +84,4 @@ public class EngineConfig implements Jsonizable { return new EngineConfig(facets, mode); } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("facets"); - writer.array(); - for (FacetConfig facet : _facets) { - facet.write(writer, options); - } - writer.endArray(); - writer.key(Engine.MODE); writer.value(_mode == Mode.RowBased ? Engine.MODE_ROW_BASED : Engine.MODE_RECORD_BASED); - writer.endObject(); - } - } diff --git a/main/src/com/google/refine/browsing/facets/Facet.java b/main/src/com/google/refine/browsing/facets/Facet.java index 5720806ca..34476870e 100644 --- a/main/src/com/google/refine/browsing/facets/Facet.java +++ b/main/src/com/google/refine/browsing/facets/Facet.java @@ -33,7 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.browsing.facets; -import com.google.refine.Jsonizable; import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RecordFilter; @@ -43,7 +42,7 @@ import com.google.refine.model.Project; /** * Interface of facets. */ -public interface Facet extends Jsonizable { +public interface Facet { public RowFilter getRowFilter(Project project); public RecordFilter getRecordFilter(Project project); diff --git a/main/src/com/google/refine/browsing/facets/FacetConfig.java b/main/src/com/google/refine/browsing/facets/FacetConfig.java index 3971b66d4..22f07e39c 100644 --- a/main/src/com/google/refine/browsing/facets/FacetConfig.java +++ b/main/src/com/google/refine/browsing/facets/FacetConfig.java @@ -4,7 +4,6 @@ import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.model.Project; @@ -17,7 +16,7 @@ import com.google.refine.model.Project; * @author antonin * */ -public interface FacetConfig extends Jsonizable { +public interface FacetConfig { /** * Reads the facet configuration from a JSON object (will be removed once we migrate to Jackson) * @param fo diff --git a/main/src/com/google/refine/browsing/facets/ListFacet.java b/main/src/com/google/refine/browsing/facets/ListFacet.java index 780e73f80..07ecf61f0 100644 --- a/main/src/com/google/refine/browsing/facets/ListFacet.java +++ b/main/src/com/google/refine/browsing/facets/ListFacet.java @@ -35,20 +35,16 @@ package com.google.refine.browsing.facets; import java.util.LinkedList; import java.util.List; -import java.util.Properties; import java.util.stream.Collectors; import org.json.JSONArray; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.ProjectManager; import com.google.refine.browsing.DecoratedValue; @@ -115,33 +111,6 @@ public class ListFacet implements Facet { @JsonProperty("selectError") public boolean selectError; - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("type"); writer.value("list"); - writer.key("name"); writer.value(name); - writer.key("expression"); writer.value(expression); - writer.key("columnName"); writer.value(columnName); - writer.key("invert"); writer.value(invert); - writer.key("selection"); writer.array(); - for (DecoratedValue choice : selection) { - writer.object(); - writer.key("v"); - choice.write(writer, options); - writer.endObject(); - } - writer.endArray(); - writer.key("selectNumber"); writer.value(selectNumber); - writer.key("selectDateTime"); writer.value(selectDateTime); - writer.key("selectBoolean"); writer.value(selectBoolean); - writer.key("omitBlank"); writer.value(omitBlank); - writer.key("selectBlank"); writer.value(selectBlank); - writer.key("omitError"); writer.value(omitError); - writer.key("selectError"); writer.value(selectError); - writer.endObject(); - } - @JsonProperty("selection") public List getWrappedSelection() { return selection.stream() @@ -292,6 +261,7 @@ public class ListFacet implements Facet { } return null; } +<<<<<<< HEAD @Override public void write(JSONWriter writer, Properties options) @@ -353,6 +323,8 @@ public class ListFacet implements Facet { writer.endObject(); } +======= +>>>>>>> Remove Jsonizable interface and write methods protected int getLimit() { Object v = ProjectManager.singleton.getPreferenceStore().get("ui.browsing.listFacet.limit"); diff --git a/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java b/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java index ad59ff61a..f29a6ae96 100644 --- a/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java +++ b/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java @@ -33,21 +33,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.browsing.facets; -import java.util.Properties; - -import org.json.JSONException; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.browsing.DecoratedValue; /** * Store a facet choice that has a decorated value, a count of matched rows, * and a flag of whether it has been selected. */ -public class NominalFacetChoice implements Jsonizable { +public class NominalFacetChoice { @JsonProperty("v") final public DecoratedValue decoratedValue; @JsonProperty("c") @@ -58,14 +52,4 @@ public class NominalFacetChoice implements Jsonizable { public NominalFacetChoice(DecoratedValue decoratedValue) { this.decoratedValue = decoratedValue; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("v"); decoratedValue.write(writer, options); - writer.key("c"); writer.value(count); - writer.key("s"); writer.value(selected); - writer.endObject(); - } } diff --git a/main/src/com/google/refine/browsing/facets/RangeFacet.java b/main/src/com/google/refine/browsing/facets/RangeFacet.java index 48621873b..ce0c68161 100644 --- a/main/src/com/google/refine/browsing/facets/RangeFacet.java +++ b/main/src/com/google/refine/browsing/facets/RangeFacet.java @@ -33,11 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.browsing.facets; -import java.util.Properties; - -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -96,24 +92,6 @@ public class RangeFacet implements Facet { protected boolean _selected; // false if we're certain that all rows will match // and there isn't any filtering to do - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("type"); writer.value("range"); - writer.key("name"); writer.value(_name); - writer.key("expression"); writer.value(_expression); - writer.key("columnName"); writer.value(_columnName); - writer.key(FROM); writer.value(_from); - writer.key(TO); writer.value(_to); - writer.key("selectNumeric"); writer.value(_selectNumeric); - writer.key("selectNonNumeric"); writer.value(_selectNonNumeric); - writer.key("selectError"); writer.value(_selectError); - writer.key("selectBlank"); writer.value(_selectBlank); - writer.endObject(); - - } - @Override public void initializeFromJSON(JSONObject o) { _name = o.getString("name"); @@ -282,56 +260,8 @@ public class RangeFacet implements Facet { return _config._to; } return null; - } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("name"); writer.value(_config._name); - writer.key("expression"); writer.value(_config._expression); - writer.key("columnName"); writer.value(_config._columnName); - - if (_errorMessage != null) { - writer.key("error"); writer.value(_errorMessage); - } else { - if (!Double.isInfinite(_min) && !Double.isInfinite(_max)) { - writer.key(MIN); writer.value(_min); - writer.key(MAX); writer.value(_max); - writer.key("step"); writer.value(_step); - - writer.key("bins"); writer.array(); - for (int b : _bins) { - writer.value(b); - } - writer.endArray(); - - writer.key("baseBins"); writer.array(); - for (int b : _baseBins) { - writer.value(b); - } - writer.endArray(); - - writer.key(FROM); writer.value(_config._from); - writer.key(TO); writer.value(_config._to); - } else { - writer.key("error"); writer.value(ERR_NO_NUMERIC_VALUE_PRESENT); - } - - writer.key("baseNumericCount"); writer.value(_baseNumericCount); - writer.key("baseNonNumericCount"); writer.value(_baseNonNumericCount); - writer.key("baseBlankCount"); writer.value(_baseBlankCount); - writer.key("baseErrorCount"); writer.value(_baseErrorCount); - - writer.key("numericCount"); writer.value(_numericCount); - writer.key("nonNumericCount"); writer.value(_nonNumericCount); - writer.key("blankCount"); writer.value(_blankCount); - writer.key("errorCount"); writer.value(_errorCount); - } - writer.endObject(); - } - + } + public void initializeFromConfig(RangeFacetConfig config, Project project) { _config = config; diff --git a/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java b/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java index 3945251d7..202a04606 100644 --- a/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java +++ b/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java @@ -40,14 +40,11 @@ import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.util.Properties; import javax.imageio.ImageIO; import org.apache.commons.codec.binary.Base64; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -140,36 +137,6 @@ public class ScatterplotFacet implements Facet { return dim_y == LIN ? "lin" : "log"; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - - writer.key("type"); writer.value("scatterplot"); - writer.key(NAME); writer.value(name); - writer.key(X_COLUMN_NAME); writer.value(columnName_x); - writer.key(X_EXPRESSION); writer.value(expression_x); - writer.key(Y_COLUMN_NAME); writer.value(columnName_y); - writer.key(Y_EXPRESSION); writer.value(expression_y); - writer.key(SIZE); writer.value(size); - writer.key(DOT); writer.value(dot); - if(!rotation_str.isEmpty()) { - writer.key(ROTATION); writer.value(rotation_str); - } - writer.key(DIM_X); writer.value(dim_x == LIN ? "lin" : "log"); - writer.key(DIM_Y); writer.value(dim_y == LIN ? "lin" : "log"); - if(!"000000".equals(color_str)) { - writer.key(COLOR); writer.value(color_str); - } - writer.key(FROM_X); writer.value(from_x); - writer.key(TO_X); writer.value(to_x); - writer.key(FROM_Y); writer.value(from_y); - writer.key(TO_Y); writer.value(to_y); - - writer.endObject(); - - } - @Override public ScatterplotFacet apply(Project project) { ScatterplotFacet facet = new ScatterplotFacet(); @@ -404,48 +371,6 @@ public class ScatterplotFacet implements Facet { } return null; } - - @Override - public void write(JSONWriter writer, Properties options) throws JSONException { - - writer.object(); - - writer.key(NAME); writer.value(config.name); - writer.key(X_COLUMN_NAME); writer.value(config.columnName_x); - writer.key(X_EXPRESSION); writer.value(config.expression_x); - writer.key(Y_COLUMN_NAME); writer.value(config.columnName_y); - writer.key(Y_EXPRESSION); writer.value(config.expression_y); - writer.key(SIZE); writer.value(config.size); - writer.key(DOT); writer.value(config.dot); - writer.key(ROTATION); writer.value(config.rotation); - writer.key(DIM_X); writer.value(config.dim_x); - writer.key(DIM_Y); writer.value(config.dim_y); - writer.key(COLOR); writer.value(config.color_str); - - if (IMAGE_URI) { - writer.key(IMAGE); writer.value(image); - } - - if (errorMessage_x != null) { - writer.key(ERROR_X); writer.value(errorMessage_x); - } else { - if (!Double.isInfinite(min_x) && !Double.isInfinite(max_x)) { - writer.key(FROM_X); writer.value(config.from_x); - writer.key(TO_X); writer.value(config.to_x); - } - } - - if (errorMessage_y != null) { - writer.key(ERROR_Y); writer.value(errorMessage_y); - } else { - if (!Double.isInfinite(min_y) && !Double.isInfinite(max_y)) { - writer.key(FROM_Y); writer.value(config.from_y); - writer.key(TO_Y); writer.value(config.to_y); - } - } - - writer.endObject(); - } public void initializeFromConfig(ScatterplotFacetConfig configuration, Project project) { config = configuration; diff --git a/main/src/com/google/refine/browsing/facets/TextSearchFacet.java b/main/src/com/google/refine/browsing/facets/TextSearchFacet.java index c627f8258..5e3780e2a 100644 --- a/main/src/com/google/refine/browsing/facets/TextSearchFacet.java +++ b/main/src/com/google/refine/browsing/facets/TextSearchFacet.java @@ -33,12 +33,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.browsing.facets; -import java.util.Properties; import java.util.regex.Pattern; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -73,20 +71,6 @@ public class TextSearchFacet implements Facet { @JsonProperty("invert") protected boolean _invert; - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("name"); writer.value(_name); - writer.key("columnName"); writer.value(_columnName); - writer.key("query"); writer.value(_query); - writer.key("mode"); writer.value(_mode); - writer.key("caseSensitive"); writer.value(_caseSensitive); - writer.key("invert"); writer.value(_invert); - writer.key("type"); writer.value("text"); - writer.endObject(); - } - @Override public TextSearchFacet apply(Project project) { TextSearchFacet facet = new TextSearchFacet(); @@ -152,21 +136,7 @@ public class TextSearchFacet implements Facet { public boolean isInverted() { return _config._invert; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("name"); writer.value(_config._name); - writer.key("columnName"); writer.value(_config._columnName); - writer.key("query"); writer.value(_config._query); - writer.key("mode"); writer.value(_config._mode); - writer.key("caseSensitive"); writer.value(_config._caseSensitive); - writer.key("invert"); writer.value(_config._invert); - writer.endObject(); - } - + public void initializeFromConfig(TextSearchFacetConfig config, Project project) { _config = config; diff --git a/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java b/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java index 98cd0d1ee..c1042f116 100644 --- a/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java +++ b/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java @@ -33,11 +33,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.browsing.facets; -import java.util.Properties; - import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -93,23 +90,6 @@ public class TimeRangeFacet implements Facet { protected boolean _selected; // false if we're certain that all rows will match // and there isn't any filtering to do - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("type"); writer.value("timerange"); - writer.key("name"); writer.value(_name); - writer.key("expression"); writer.value(_expression); - writer.key("columnName"); writer.value(_columnName); - writer.key("selectTime"); writer.value(_selectTime); - writer.key("selectNonTime"); writer.value(_selectNonTime); - writer.key("selectBlank"); writer.value(_selectBlank); - writer.key("selectError"); writer.value(_selectError); - writer.key(FROM); writer.value((long)_from); - writer.key(TO); writer.value((long)_to); - writer.endObject(); - } - @Override public void initializeFromJSON(JSONObject o) throws JSONException { _name = o.getString("name"); @@ -266,51 +246,6 @@ public class TimeRangeFacet implements Facet { return null; } - @Override - public void write(JSONWriter writer, Properties options) throws JSONException { - - writer.object(); - writer.key("name"); writer.value(_config._name); - writer.key("expression"); writer.value(_config._expression); - writer.key("columnName"); writer.value(_config._columnName); - - if (_errorMessage != null) { - writer.key("error"); writer.value(_errorMessage); - } else { - if (!Double.isInfinite(_min) && !Double.isInfinite(_max)) { - writer.key(MIN); writer.value((long)_min); - writer.key(MAX); writer.value((long)_max); - writer.key("step"); writer.value((long)_step); - - writer.key("bins"); writer.array(); - for (int b : _bins) { - writer.value(b); - } - writer.endArray(); - - writer.key("baseBins"); writer.array(); - for (int b : _baseBins) { - writer.value(b); - } - writer.endArray(); - - writer.key(FROM); writer.value((long)_config._from); - writer.key(TO); writer.value((long)_config._to); - } - - writer.key("baseTimeCount"); writer.value(_baseTimeCount); - writer.key("baseNonTimeCount"); writer.value(_baseNonTimeCount); - writer.key("baseBlankCount"); writer.value(_baseBlankCount); - writer.key("baseErrorCount"); writer.value(_baseErrorCount); - - writer.key("timeCount"); writer.value(_timeCount); - writer.key("nonTimeCount"); writer.value(_nonTimeCount); - writer.key("blankCount"); writer.value(_blankCount); - writer.key("errorCount"); writer.value(_errorCount); - } - writer.endObject(); - } - public void initializeFromConfig(TimeRangeFacetConfig config, Project project) { _config = config; if (_config._columnName.length() > 0) { diff --git a/main/src/com/google/refine/clustering/Clusterer.java b/main/src/com/google/refine/clustering/Clusterer.java index a18e42c81..bfb149498 100644 --- a/main/src/com/google/refine/clustering/Clusterer.java +++ b/main/src/com/google/refine/clustering/Clusterer.java @@ -33,12 +33,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.clustering; -import com.google.refine.Jsonizable; import com.google.refine.browsing.Engine; import com.google.refine.model.Column; import com.google.refine.model.Project; -public abstract class Clusterer implements Jsonizable { +public abstract class Clusterer { protected Project _project; protected int _colindex; diff --git a/main/src/com/google/refine/clustering/ClustererConfig.java b/main/src/com/google/refine/clustering/ClustererConfig.java index 95930fd99..5ac10369f 100644 --- a/main/src/com/google/refine/clustering/ClustererConfig.java +++ b/main/src/com/google/refine/clustering/ClustererConfig.java @@ -4,7 +4,6 @@ import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.model.Project; /** @@ -12,7 +11,7 @@ import com.google.refine.model.Project; * @author Antonin Delpeuch * */ -public abstract class ClustererConfig implements Jsonizable { +public abstract class ClustererConfig { protected String columnName; diff --git a/main/src/com/google/refine/clustering/binning/BinningClusterer.java b/main/src/com/google/refine/clustering/binning/BinningClusterer.java index 7e93013d1..589f610ca 100644 --- a/main/src/com/google/refine/clustering/binning/BinningClusterer.java +++ b/main/src/com/google/refine/clustering/binning/BinningClusterer.java @@ -57,7 +57,6 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; -import com.google.refine.Jsonizable; import com.google.refine.browsing.Engine; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RowVisitor; @@ -99,20 +98,6 @@ public class BinningClusterer extends Clusterer { public BinningParameters getParameters() { return _parameters; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("function"); writer.value(_keyerName); - writer.key("type"); writer.value("binning"); - writer.key("column"); writer.value(getColumnName()); - if(_parameters != null) { - writer.key("params"); - _parameters.write(writer, options); - } - writer.endObject(); - } @Override public BinningClusterer apply(Project project) { @@ -128,21 +113,10 @@ public class BinningClusterer extends Clusterer { } - public static class BinningParameters implements Jsonizable { + public static class BinningParameters { @JsonProperty("ngram-size") @JsonInclude(Include.NON_DEFAULT) public int ngramSize; - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - if(ngramSize > 0) { - writer.key("ngram-size"); - writer.value(ngramSize); - } - writer.endObject(); - } public static BinningParameters reconstruct(JSONObject o) { BinningParameters parameters = new BinningParameters(); @@ -274,28 +248,6 @@ public class BinningClusterer extends Clusterer { Collections.sort(_clusters, new SizeComparator()); } - @Override - public void write(JSONWriter writer, Properties options) throws JSONException { - EntriesComparator c = new EntriesComparator(); - - writer.array(); - for (Map m : _clusters) { - if (m.size() > 1) { - writer.array(); - List> entries = new ArrayList>(m.entrySet()); - Collections.sort(entries,c); - for (Entry e : entries) { - writer.object(); - writer.key("v"); writer.value(e.getKey()); - writer.key("c"); writer.value(e.getValue()); - writer.endObject(); - } - writer.endArray(); - } - } - writer.endArray(); - } - protected static Map entryToMap(Entry entry) { Map map = new HashMap<>(); map.put("v", entry.getKey()); diff --git a/main/src/com/google/refine/clustering/knn/kNNClusterer.java b/main/src/com/google/refine/clustering/knn/kNNClusterer.java index 10db49280..da0a502d8 100644 --- a/main/src/com/google/refine/clustering/knn/kNNClusterer.java +++ b/main/src/com/google/refine/clustering/knn/kNNClusterer.java @@ -34,21 +34,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.clustering.knn; import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Properties; import java.util.Set; import java.util.stream.Collectors; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,7 +51,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; -import com.google.refine.Jsonizable; import com.google.refine.browsing.Engine; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RowVisitor; @@ -86,21 +80,7 @@ public class kNNClusterer extends Clusterer { private String _distanceStr; private Distance _distance; private kNNClustererConfigParameters _parameters; - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("function"); writer.value(_distanceStr); - writer.key("type"); writer.value("knn"); - writer.key("column"); writer.value(getColumnName()); - if(_parameters != null) { - writer.key("params"); - _parameters.write(writer, options); - } - writer.endObject(); - } - + public void initializeFromJSON(JSONObject o) { super.initializeFromJSON(o); _distanceStr = o.getString("function"); @@ -136,7 +116,7 @@ public class kNNClusterer extends Clusterer { } - public static class kNNClustererConfigParameters implements Jsonizable { + public static class kNNClustererConfigParameters { public static final double defaultRadius = 1.0d; public static final int defaultBlockingNgramSize = 6; @JsonProperty("radius") @@ -144,16 +124,6 @@ public class kNNClusterer extends Clusterer { @JsonProperty("blocking-ngram-size") public int blockingNgramSize = defaultBlockingNgramSize; - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("radius"); writer.value(radius); - writer.key("blocking-ngram-size"); - writer.value(blockingNgramSize); - writer.endObject(); - } - public static kNNClustererConfigParameters reconstruct(JSONObject o) { kNNClustererConfigParameters params = new kNNClustererConfigParameters(); if(o.has("radius")) { @@ -294,30 +264,6 @@ public class kNNClusterer extends Clusterer { } } - @Override - public void write(JSONWriter writer, Properties options) throws JSONException { - writer.array(); - for (Set m : _clusters) { - if (m.size() > 1) { - Map internal_counts = new HashMap(); - for (Serializable s : m) { - internal_counts.put(s,_counts.get(s)); - } - List> values = new ArrayList>(internal_counts.entrySet()); - Collections.sort(values, new ValuesComparator()); - writer.array(); - for (Entry e : values) { - writer.object(); - writer.key("v"); writer.value(e.getKey()); - writer.key("c"); writer.value(e.getValue()); - writer.endObject(); - } - writer.endArray(); - } - } - writer.endArray(); - } - protected List getClusteredEntries(Set s) { return s.stream() .map(e -> new ClusteredEntry(e, _counts.get(e))) diff --git a/main/src/com/google/refine/commands/Command.java b/main/src/com/google/refine/commands/Command.java index 9c685e447..39415f4d9 100644 --- a/main/src/com/google/refine/commands/Command.java +++ b/main/src/com/google/refine/commands/Command.java @@ -50,7 +50,8 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.refine.Jsonizable; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.ProjectManager; import com.google.refine.RefineServlet; import com.google.refine.browsing.Engine; @@ -237,6 +238,16 @@ public abstract class Command { } return null; } + + protected static class HistoryEntryResponse { + @JsonProperty("code") + protected String getCode() { return "ok"; } + @JsonProperty("historyEntry") + protected HistoryEntry historyEntry; + protected HistoryEntryResponse(HistoryEntry entry) { + historyEntry = entry; + } + } static protected void performProcessAndRespond( HttpServletRequest request, @@ -244,23 +255,18 @@ public abstract class Command { Project project, Process process ) throws Exception { - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); + HistoryEntry historyEntry = project.processManager.queueProcess(process); if (historyEntry != null) { Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); - Properties options = new Properties(); - - writer.object(); - writer.key("code"); writer.value("ok"); - writer.key("historyEntry"); historyEntry.write(writer, options); - writer.endObject(); + ParsingUtilities.defaultWriter.writeValue(w, new HistoryEntryResponse(historyEntry)); w.flush(); w.close(); } else { + response.setCharacterEncoding("UTF-8"); + response.setHeader("Content-Type", "application/json"); respond(response, "{ \"code\" : \"pending\" }"); } } @@ -293,14 +299,14 @@ public abstract class Command { w.close(); } - static protected void respondJSON(HttpServletResponse response, Jsonizable o) + static protected void respondJSON(HttpServletResponse response, Object o) throws IOException, JSONException { respondJSON(response, o, new Properties()); } static protected void respondJSON( - HttpServletResponse response, Jsonizable o, Properties options) + HttpServletResponse response, Object o, Properties options) throws IOException, JSONException { response.setCharacterEncoding("UTF-8"); @@ -308,9 +314,8 @@ public abstract class Command { response.setHeader("Cache-Control", "no-cache"); Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); + ParsingUtilities.defaultWriter.writeValue(w, o); - o.write(writer, options); w.flush(); w.close(); } diff --git a/main/src/com/google/refine/commands/GetPreferenceCommand.java b/main/src/com/google/refine/commands/GetPreferenceCommand.java index 9f26daadc..cd1681b99 100644 --- a/main/src/com/google/refine/commands/GetPreferenceCommand.java +++ b/main/src/com/google/refine/commands/GetPreferenceCommand.java @@ -34,47 +34,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.commands; import java.io.IOException; -import java.util.Properties; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONException; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.preference.PreferenceStore; -import com.google.refine.preference.TopList; public class GetPreferenceCommand extends Command { - protected static class PreferenceValue implements Jsonizable { + protected static class PreferenceValue { @JsonProperty("value") protected Object pref; protected PreferenceValue(Object o) { pref = o; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("value"); - if (pref == null || pref instanceof String || pref instanceof Number || pref instanceof Boolean) { - writer.value(pref); - } else if (pref instanceof TopList) { - TopList tl = (TopList) pref; - tl.write(writer, new Properties()); - } else { - writer.value(pref.toString()); - } - - writer.endObject(); - } } @Override diff --git a/main/src/com/google/refine/commands/HttpUtilities.java b/main/src/com/google/refine/commands/HttpUtilities.java index 604fa9af9..97d9cc7e2 100644 --- a/main/src/com/google/refine/commands/HttpUtilities.java +++ b/main/src/com/google/refine/commands/HttpUtilities.java @@ -17,7 +17,6 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.refine.Jsonizable; import com.google.refine.RefineServlet; import com.google.refine.util.ParsingUtilities; @@ -56,23 +55,21 @@ abstract public class HttpUtilities { } } - static public void respondJSON(HttpServletResponse response, Jsonizable o) + static public void respondJSON(HttpServletResponse response, Object o) throws IOException, JSONException { respondJSON(response, o, new Properties()); } static public void respondJSON( - HttpServletResponse response, Jsonizable o, Properties options) + HttpServletResponse response, Object o, Properties options) throws IOException, JSONException { response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "application/json"); Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); - - o.write(writer, options); + ParsingUtilities.defaultWriter.writeValue(w, o); w.flush(); w.close(); } diff --git a/main/src/com/google/refine/commands/cell/EditOneCellCommand.java b/main/src/com/google/refine/commands/cell/EditOneCellCommand.java index 266319947..41c7ab0b3 100644 --- a/main/src/com/google/refine/commands/cell/EditOneCellCommand.java +++ b/main/src/com/google/refine/commands/cell/EditOneCellCommand.java @@ -35,13 +35,14 @@ package com.google.refine.commands.cell; import java.io.IOException; import java.io.Serializable; -import java.util.Properties; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.commands.Command; import com.google.refine.history.Change; @@ -55,6 +56,32 @@ import com.google.refine.util.ParsingUtilities; import com.google.refine.util.Pool; public class EditOneCellCommand extends Command { + + protected static class EditResult { + @JsonProperty("code") + protected String code; + @JsonProperty("historyEntry") + @JsonInclude(Include.NON_NULL) + protected HistoryEntry historyEntry; + @JsonProperty("cell") + @JsonInclude(Include.NON_NULL) + protected Cell cell; + @JsonProperty("pool") + @JsonInclude(Include.NON_NULL) + protected Pool pool; + + protected EditResult( + String code, + HistoryEntry historyEntry, + Cell cell, + Pool pool) { + this.code = code; + this.historyEntry = historyEntry; + this.cell = cell; + this.pool = pool; + } + } + @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -96,18 +123,11 @@ public class EditOneCellCommand extends Command { * If the operation has been done, return the new cell's data * so the client side can update the cell's rendering right away. */ - JSONWriter writer = new JSONWriter(response.getWriter()); - Pool pool = new Pool(); - Properties options = new Properties(); - options.put("pool", pool); - - writer.object(); - writer.key("code"); writer.value("ok"); - writer.key("historyEntry"); historyEntry.write(writer, options); - writer.key("cell"); process.newCell.write(writer, options); - writer.key("pool"); pool.write(writer, options); - writer.endObject(); + if(process.newCell != null && process.newCell.recon != null) { + pool.pool(process.newCell.recon); + } + respondJSON(response, new EditResult("ok", historyEntry, process.newCell, pool)); } else { respond(response, "{ \"code\" : \"pending\" }"); } diff --git a/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java b/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java index 18385f579..b4f229be9 100644 --- a/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java +++ b/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java @@ -37,7 +37,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; -import java.util.Properties; import java.util.Set; import java.util.stream.Collectors; @@ -45,19 +44,15 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONException; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.commands.Command; import com.google.refine.preference.TopList; public class GetExpressionHistoryCommand extends Command { - public static class ExpressionState implements Jsonizable { + public static class ExpressionState { @JsonProperty("code") protected String code; @JsonProperty("global") @@ -69,38 +64,15 @@ public class GetExpressionHistoryCommand extends Command { this.code = code; this.starred = starred; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("code"); writer.value(code); - writer.key("global"); writer.value(false); - writer.key("starred"); writer.value(starred); - writer.endObject(); - } } - public static class ExpressionsList implements Jsonizable { + public static class ExpressionsList { @JsonProperty("expressions") List expressions; protected ExpressionsList(List states) { this.expressions = states; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("expressions"); - writer.array(); - for (ExpressionState e : expressions) { - e.write(writer, options); - } - writer.endArray(); - writer.endObject(); - } } static protected List toExpressionList(Object o) { diff --git a/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java b/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java index b5400d909..a47f7b62b 100644 --- a/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java +++ b/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java @@ -35,19 +35,13 @@ package com.google.refine.commands.expr; import java.io.IOException; import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONException; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.commands.Command; import com.google.refine.grel.Control; import com.google.refine.grel.ControlFunctionRegistry; @@ -55,7 +49,7 @@ import com.google.refine.grel.Function; public class GetExpressionLanguageInfoCommand extends Command { - public static class LanguageInfo implements Jsonizable { + public static class LanguageInfo { @JsonProperty("functions") Map functions; @@ -66,35 +60,6 @@ public class GetExpressionLanguageInfoCommand extends Command { functions = ControlFunctionRegistry.getFunctionMap(); controls = ControlFunctionRegistry.getControlMap(); } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - - writer.key("functions"); - writer.object(); - { - for (Entry entry : functions.entrySet()) { - writer.key(entry.getKey()); - entry.getValue().write(writer, options); - } - } - writer.endObject(); - - writer.key("controls"); - writer.object(); - { - for (Entry entry : controls.entrySet()) { - writer.key(entry.getKey()); - entry.getValue().write(writer, options); - } - } - writer.endObject(); - - writer.endObject(); - } - } @Override diff --git a/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java b/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java index acad51a5c..60635c399 100644 --- a/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java +++ b/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java @@ -2,19 +2,14 @@ package com.google.refine.commands.expr; import java.io.IOException; import java.util.List; -import java.util.Properties; import java.util.stream.Collectors; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONException; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.commands.Command; import com.google.refine.preference.TopList; @@ -22,39 +17,20 @@ import com.google.refine.preference.TopList; public class GetStarredExpressionsCommand extends Command { - protected static class Expression implements Jsonizable { + protected static class Expression { @JsonProperty("code") protected String code; protected Expression(String c) { code = c; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("code"); writer.value(code); - writer.endObject(); - } } - protected static class ExpressionList implements Jsonizable { + protected static class ExpressionList { @JsonProperty("expressions") protected List expressions; protected ExpressionList(List e) { expressions = e; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("expressions"); - writer.array(); - for (Expression s : expressions) { - s.write(writer, options); - } - writer.endArray(); - writer.endObject(); - } } public static ExpressionList getExpressionsList() { diff --git a/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java b/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java index 2f5941a6f..e59ad8b5b 100644 --- a/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java +++ b/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java @@ -47,14 +47,12 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; -import com.google.refine.Jsonizable; import com.google.refine.commands.Command; import com.google.refine.expr.EvalError; import com.google.refine.expr.Evaluable; @@ -71,21 +69,13 @@ import com.google.refine.util.ParsingUtilities; public class PreviewExpressionCommand extends Command { - protected static interface ExpressionValue extends Jsonizable { } + protected static interface ExpressionValue { } protected static class ErrorMessage implements ExpressionValue { @JsonProperty("message") protected String message; public ErrorMessage(String m) { message = m; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("message"); writer.value(message); - writer.endObject(); - } - } protected static class SuccessfulEvaluation implements ExpressionValue { @JsonValue @@ -93,15 +83,9 @@ public class PreviewExpressionCommand extends Command { protected SuccessfulEvaluation(String value) { this.value = value; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.value(value); - } - } - protected static class PreviewResult implements Jsonizable { + protected static class PreviewResult { @JsonProperty("code") protected String code; @JsonProperty("message") @@ -111,6 +95,7 @@ public class PreviewExpressionCommand extends Command { @JsonInclude(Include.NON_NULL) protected String type; @JsonProperty("results") + @JsonInclude(Include.NON_NULL) List results; public PreviewResult(String code, String message, String type) { @@ -126,28 +111,6 @@ public class PreviewExpressionCommand extends Command { this.type = null; this.results = evaluated; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("code"); writer.value(code); - if(message != null) { - writer.key("message"); writer.value(message); - } - if(type != null) { - writer.key("type"); writer.value(type); - } - if(results != null) { - writer.key("results"); - writer.array(); - for(ExpressionValue v : results) { - v.write(writer, options); - } - writer.endArray(); - } - writer.endObject(); - } } @Override diff --git a/main/src/com/google/refine/commands/history/GetOperationsCommand.java b/main/src/com/google/refine/commands/history/GetOperationsCommand.java index f03f9aabc..9b3c88829 100644 --- a/main/src/com/google/refine/commands/history/GetOperationsCommand.java +++ b/main/src/com/google/refine/commands/history/GetOperationsCommand.java @@ -35,28 +35,23 @@ package com.google.refine.commands.history; import java.io.IOException; import java.util.List; -import java.util.Properties; import java.util.stream.Collectors; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONException; -import org.json.JSONWriter; - -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.commands.Command; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; public class GetOperationsCommand extends Command { - protected static class SimpleHistoryEntry implements Jsonizable { + protected static class SimpleHistoryEntry { protected HistoryEntry entry; public SimpleHistoryEntry(HistoryEntry e) { @@ -73,22 +68,9 @@ public class GetOperationsCommand extends Command { public AbstractOperation getOperation() { return entry.operation; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("description"); writer.value(entry.description); - if (entry.operation != null) { - writer.key("operation"); - entry.operation.write(writer, options); - } - writer.endObject(); - } - } - protected static class HistoryEntries implements Jsonizable { + protected static class HistoryEntries { @JsonProperty("entries") List entries; @@ -97,19 +79,6 @@ public class GetOperationsCommand extends Command { .map(e -> new SimpleHistoryEntry(e)) .collect(Collectors.toList()); } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("entries"); writer.array(); - - for (SimpleHistoryEntry entry : entries) { - entry.write(writer, options); - } - writer.endArray(); - writer.endObject(); - } } @Override diff --git a/main/src/com/google/refine/commands/importing/GetImportingJobStatusCommand.java b/main/src/com/google/refine/commands/importing/GetImportingJobStatusCommand.java index 7c982c35a..4a06556b1 100644 --- a/main/src/com/google/refine/commands/importing/GetImportingJobStatusCommand.java +++ b/main/src/com/google/refine/commands/importing/GetImportingJobStatusCommand.java @@ -35,20 +35,38 @@ package com.google.refine.commands.importing; import java.io.IOException; import java.io.Writer; -import java.util.Properties; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONException; -import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.commands.Command; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingManager; +import com.google.refine.util.ParsingUtilities; public class GetImportingJobStatusCommand extends Command { + protected static class JobStatusResponse { + @JsonProperty("code") + protected String code; + @JsonProperty("message") + @JsonInclude(Include.NON_NULL) + protected String message; + @JsonProperty("job") + @JsonInclude(Include.NON_NULL) + protected ImportingJob job; + + protected JobStatusResponse(String code, String message, ImportingJob job) { + this.code = code; + this.message = message; + this.job = job; + } + } + @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -57,22 +75,10 @@ public class GetImportingJobStatusCommand extends Command { ImportingJob job = ImportingManager.getJob(jobID); Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); - try { - writer.object(); - if (job == null) { - writer.key("code"); writer.value("error"); - writer.key("message"); writer.value("No such import job"); - } else { - writer.key("code"); writer.value("ok"); - writer.key("job"); job.write(writer, new Properties()); - } - writer.endObject(); - } catch (JSONException e) { - throw new ServletException(e); - } finally { - w.flush(); - w.close(); + if (job == null) { + ParsingUtilities.defaultWriter.writeValue(w, new JobStatusResponse("error", "No such import job", null)); + } else { + ParsingUtilities.defaultWriter.writeValue(w, new JobStatusResponse("ok", null, job)); } } } diff --git a/main/src/com/google/refine/commands/project/CreateProjectCommand.java b/main/src/com/google/refine/commands/project/CreateProjectCommand.java index ece7ef28f..0d5020fe1 100644 --- a/main/src/com/google/refine/commands/project/CreateProjectCommand.java +++ b/main/src/com/google/refine/commands/project/CreateProjectCommand.java @@ -52,8 +52,8 @@ import com.google.refine.commands.Command; import com.google.refine.commands.HttpUtilities; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingManager; -import com.google.refine.importing.ImportingUtilities; import com.google.refine.importing.ImportingManager.Format; +import com.google.refine.importing.ImportingUtilities; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/commands/project/ExportRowsCommand.java b/main/src/com/google/refine/commands/project/ExportRowsCommand.java index 3270c671c..44c031da4 100644 --- a/main/src/com/google/refine/commands/project/ExportRowsCommand.java +++ b/main/src/com/google/refine/commands/project/ExportRowsCommand.java @@ -57,7 +57,6 @@ import com.google.refine.exporters.ExporterRegistry; import com.google.refine.exporters.StreamExporter; import com.google.refine.exporters.WriterExporter; import com.google.refine.exporters.sql.SqlExporterException; - import com.google.refine.model.Project; public class ExportRowsCommand extends Command { diff --git a/main/src/com/google/refine/commands/project/GetMetadataCommand.java b/main/src/com/google/refine/commands/project/GetMetadataCommand.java index 9a7b21de1..a448505e3 100644 --- a/main/src/com/google/refine/commands/project/GetMetadataCommand.java +++ b/main/src/com/google/refine/commands/project/GetMetadataCommand.java @@ -38,7 +38,7 @@ public class GetMetadataCommand extends Command { } IMetadata metadata = MetadataFactory.buildDataPackageMetadata(project); - respondJSONObject(response, metadata.getJSON()); + respondJSON(response, metadata); } catch (JSONException e) { respondException(response, e); } catch (ValidationException e) { diff --git a/main/src/com/google/refine/commands/project/GetModelsCommand.java b/main/src/com/google/refine/commands/project/GetModelsCommand.java index ea433fa9c..876f5fa76 100644 --- a/main/src/com/google/refine/commands/project/GetModelsCommand.java +++ b/main/src/com/google/refine/commands/project/GetModelsCommand.java @@ -34,26 +34,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.commands.project; import java.io.IOException; -import java.util.Properties; +import java.util.HashMap; +import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.json.JSONException; -import org.json.JSONWriter; + +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.commands.Command; -import com.google.refine.commands.HttpUtilities; import com.google.refine.commands.HttpHeadersSupport; import com.google.refine.commands.HttpHeadersSupport.HttpHeaderInfo; - +import com.google.refine.commands.HttpUtilities; import com.google.refine.expr.MetaParser; import com.google.refine.expr.MetaParser.LanguageInfo; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingManager; +import com.google.refine.model.ColumnModel; import com.google.refine.model.OverlayModel; import com.google.refine.model.Project; +import com.google.refine.model.RecordModel; public class GetModelsCommand extends Command { @Override @@ -67,6 +70,32 @@ public class GetModelsCommand extends Command { internalRespond(request, response); } + protected static class ModelsResponse { + @JsonProperty("columnModel") + protected ColumnModel columnModel; + @JsonProperty("recordModel") + protected RecordModel recordModel; + @JsonProperty("overlayModels") + protected Map overlayModels; + @JsonProperty("scripting") + protected Map scripting; + @JsonProperty("httpHeaders") + protected Map httpHeaders; + + protected ModelsResponse( + ColumnModel columns, + RecordModel records, + Map overlays, + Map languageInfos, + Map headers) { + columnModel = columns; + recordModel = records; + overlayModels = overlays; + scripting = languageInfos; + httpHeaders = headers; + } + } + protected void internalRespond(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -86,53 +115,26 @@ public class GetModelsCommand extends Command { } try { - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); response.setHeader("Cache-Control", "no-cache"); - - Properties options = new Properties(); - JSONWriter writer = new JSONWriter(response.getWriter()); - - writer.object(); - writer.key("columnModel"); project.columnModel.write(writer, options); - writer.key("recordModel"); project.recordModel.write(writer, options); - - writer.key("overlayModels"); writer.object(); - for (String modelName : project.overlayModels.keySet()) { - OverlayModel overlayModel = project.overlayModels.get(modelName); - if (overlayModel != null) { - writer.key(modelName); - - project.overlayModels.get(modelName).write(writer, options); - } - } - writer.endObject(); - - writer.key("scripting"); writer.object(); + + Map prefixesMap = new HashMap<>(); for (String languagePrefix : MetaParser.getLanguagePrefixes()) { LanguageInfo info = MetaParser.getLanguageInfo(languagePrefix); - - writer.key(languagePrefix); - writer.object(); - writer.key("name"); writer.value(info.name); - writer.key("defaultExpression"); writer.value(info.defaultExpression); - writer.endObject(); + prefixesMap.put(languagePrefix, info); } - writer.endObject(); - - writer.key("httpHeaders"); - writer.object(); + + Map headersMap = new HashMap<>(); for (String headerLabel : HttpHeadersSupport.getHttpHeaderLabels()) { HttpHeaderInfo info = HttpHeadersSupport.getHttpHeaderInfo(headerLabel); - writer.key(headerLabel); - writer.object(); - writer.key("header"); writer.value(info.header); - writer.key("defaultValue"); writer.value(info.defaultValue); - writer.endObject(); + headersMap.put(headerLabel, info); } - writer.endObject(); - - writer.endObject(); + + respondJSON(response, new ModelsResponse( + project.columnModel, + project.recordModel, + project.overlayModels, + prefixesMap, + headersMap)); } catch (JSONException e) { HttpUtilities.respondException(response, e); } diff --git a/main/src/com/google/refine/commands/recon/ReconClearOneCellCommand.java b/main/src/com/google/refine/commands/recon/ReconClearOneCellCommand.java index e028d90b2..39682064e 100644 --- a/main/src/com/google/refine/commands/recon/ReconClearOneCellCommand.java +++ b/main/src/com/google/refine/commands/recon/ReconClearOneCellCommand.java @@ -42,6 +42,8 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.commands.Command; import com.google.refine.expr.ExpressionUtils; import com.google.refine.history.Change; @@ -57,6 +59,23 @@ import com.google.refine.process.QuickHistoryEntryProcess; import com.google.refine.util.Pool; public class ReconClearOneCellCommand extends Command { + protected static class CellResponse { + @JsonProperty("code") + protected String code = "ok"; + @JsonProperty("historyEntry") + protected HistoryEntry entry; + @JsonProperty("cell") + Cell cell; + @JsonProperty("pool") + Pool pool; + + protected CellResponse(HistoryEntry historyEntry, Cell newCell, Pool newPool) { + entry = historyEntry; + cell = newCell; + pool = newPool; + } + } + @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -80,18 +99,13 @@ public class ReconClearOneCellCommand extends Command { * If the process is done, write back the cell's data so that the * client side can update its UI right away. */ - JSONWriter writer = new JSONWriter(response.getWriter()); - Pool pool = new Pool(); - Properties options = new Properties(); - options.put("pool", pool); + + if(process.newCell != null && process.newCell.recon != null) { + pool.pool(process.newCell.recon); + } - writer.object(); - writer.key("code"); writer.value("ok"); - writer.key("historyEntry"); historyEntry.write(writer, options); - writer.key("cell"); process.newCell.write(writer, options); - writer.key("pool"); pool.write(writer, options); - writer.endObject(); + respondJSON(response, new CellResponse(historyEntry, process.newCell, pool)); } else { respond(response, "{ \"code\" : \"pending\" }"); } diff --git a/main/src/com/google/refine/commands/recon/ReconJudgeOneCellCommand.java b/main/src/com/google/refine/commands/recon/ReconJudgeOneCellCommand.java index 7297fdeea..aceaf4e57 100644 --- a/main/src/com/google/refine/commands/recon/ReconJudgeOneCellCommand.java +++ b/main/src/com/google/refine/commands/recon/ReconJudgeOneCellCommand.java @@ -103,18 +103,13 @@ public class ReconJudgeOneCellCommand extends Command { * If the process is done, write back the cell's data so that the * client side can update its UI right away. */ - JSONWriter writer = new JSONWriter(response.getWriter()); Pool pool = new Pool(); - Properties options = new Properties(); - options.put("pool", pool); + if (process.newCell != null && process.newCell.recon != null) { + pool.pool(process.newCell.recon); + } - writer.object(); - writer.key("code"); writer.value("ok"); - writer.key("historyEntry"); historyEntry.write(writer, options); - writer.key("cell"); process.newCell.write(writer, options); - writer.key("pool"); pool.write(writer, options); - writer.endObject(); + respondJSON(response, new ReconClearOneCellCommand.CellResponse(historyEntry, process.newCell, pool)); } else { respond(response, "{ \"code\" : \"pending\" }"); } diff --git a/main/src/com/google/refine/commands/row/GetRowsCommand.java b/main/src/com/google/refine/commands/row/GetRowsCommand.java index 60d3bf366..9e11f9be7 100644 --- a/main/src/com/google/refine/commands/row/GetRowsCommand.java +++ b/main/src/com/google/refine/commands/row/GetRowsCommand.java @@ -37,7 +37,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; -import java.util.Properties; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -45,14 +44,12 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonUnwrapped; -import com.google.refine.Jsonizable; import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.FilteredRecords; @@ -62,6 +59,7 @@ import com.google.refine.browsing.RowVisitor; import com.google.refine.commands.Command; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingManager; +import com.google.refine.model.Cell; import com.google.refine.model.Project; import com.google.refine.model.Record; import com.google.refine.model.Row; @@ -73,12 +71,12 @@ import com.google.refine.util.Pool; public class GetRowsCommand extends Command { - protected static class WrappedRow implements Jsonizable { + protected static class WrappedRow { @JsonUnwrapped protected final Row row; - @JsonProperty("rowIndex") + @JsonProperty("i") protected final int rowIndex; - @JsonProperty("recordIndex") + @JsonProperty("j") @JsonInclude(Include.NON_NULL) protected final Integer recordIndex; @@ -87,23 +85,9 @@ public class GetRowsCommand extends Command { this.rowIndex = rowIndex; this.recordIndex = recordIndex; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - options.put("rowIndex", rowIndex); - if(recordIndex != null) { - options.put("recordIndex", recordIndex); - } - row.write(writer, options); - if(recordIndex != null) { - options.remove("recordIndex"); - } - } - } - protected static class JsonResult implements Jsonizable { + protected static class JsonResult { @JsonProperty("mode") protected final Mode mode; @JsonProperty("rows") @@ -129,24 +113,6 @@ public class GetRowsCommand extends Command { this.limit = limit; this.pool = pool; } - - @Override - public void write(JSONWriter jsonWriter, Properties options) - throws JSONException { - jsonWriter.object(); - jsonWriter.key("mode"); jsonWriter.value(mode == Mode.RowBased ? "row-based" : "record-based"); - jsonWriter.key("rows"); jsonWriter.array(); - for(WrappedRow row : rows) { - row.write(jsonWriter, options); - } - jsonWriter.endArray(); - jsonWriter.key("filtered"); jsonWriter.value(filtered); - jsonWriter.key("total"); jsonWriter.value(totalCount); - jsonWriter.key("start"); jsonWriter.value(start); - jsonWriter.key("limit"); jsonWriter.value(limit); - jsonWriter.key("pool"); pool.write(jsonWriter, options); - jsonWriter.endObject(); - } } @Override @@ -186,10 +152,10 @@ public class GetRowsCommand extends Command { int limit = Math.min(project.rows.size() - start, Math.max(0, getIntegerParameter(request, "limit", 20))); Pool pool = new Pool(); - Properties options = new Properties(); + /* Properties options = new Properties(); options.put("project", project); options.put("reconCandidateOmitTypes", true); - options.put("pool", pool); + options.put("pool", pool); */ response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", callback == null ? "application/json" : "text/javascript"); @@ -200,8 +166,6 @@ public class GetRowsCommand extends Command { writer.write("("); } - JSONWriter jsonWriter = new JSONWriter(writer); - RowWritingVisitor rwv = new RowWritingVisitor(start, limit); SortingConfig sortingConfig = null; @@ -243,12 +207,21 @@ public class GetRowsCommand extends Command { filteredRecords.accept(project, visitor); } + // Pool all the recons occuring in the rows seen + for(WrappedRow wr : rwv.results) { + for(Cell c : wr.row.cells) { + if(c != null && c.recon != null) { + pool.pool(c.recon); + } + } + } JsonResult result = new JsonResult(engine.getMode(), rwv.results, rwv.total, engine.getMode() == Mode.RowBased ? project.rows.size() : project.recordModel.getRecordCount(), start, limit, pool); - result.write(jsonWriter, options); + + ParsingUtilities.defaultWriter.writeValue(writer, result); if (callback != null) { writer.write(")"); } diff --git a/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java b/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java index e1f2cdf72..4968dffdd 100644 --- a/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java +++ b/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java @@ -35,29 +35,24 @@ package com.google.refine.commands.workspace; import java.io.IOException; import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRawValue; -import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.commands.Command; import com.google.refine.model.metadata.ProjectMetadata; public class GetAllProjectMetadataCommand extends Command { - public static class AllProjectMetadata implements Jsonizable { + public static class AllProjectMetadata { @JsonProperty("projects") protected Map projects; @JsonProperty("customMetadataColumns") @@ -69,30 +64,6 @@ public class GetAllProjectMetadataCommand extends Command { projects = map; customMetadataColumns = json; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - - writer.key("projects"); - writer.object(); - for (Entry e : projects.entrySet()) { - ProjectMetadata pm = e.getValue(); - if (pm != null) { - writer.key(e.getKey().toString()); - pm.write(writer, options); - } - } - writer.endObject(); - - if (customMetadataColumns != null) { - writer.key("customMetadataColumns"); - writer.value(new JSONArray(customMetadataColumns)); - } - writer.endObject(); - } } @Override diff --git a/main/src/com/google/refine/commands/workspace/GetAllProjectTagsCommand.java b/main/src/com/google/refine/commands/workspace/GetAllProjectTagsCommand.java index 80fe2a3d1..49330e8bf 100644 --- a/main/src/com/google/refine/commands/workspace/GetAllProjectTagsCommand.java +++ b/main/src/com/google/refine/commands/workspace/GetAllProjectTagsCommand.java @@ -27,9 +27,7 @@ package com.google.refine.commands.workspace; import java.io.IOException; import java.util.Collections; -import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Set; import javax.servlet.ServletException; @@ -37,17 +35,15 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.json.JSONException; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.commands.Command; public class GetAllProjectTagsCommand extends Command { - public static class AllProjectsTags implements Jsonizable { + public static class AllProjectsTags { @JsonProperty("tags") protected Set tags; @@ -55,22 +51,6 @@ public class GetAllProjectTagsCommand extends Command { protected AllProjectsTags(Set tags) { this.tags = tags; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("tags"); - writer.array(); - if (tags != null) { - for (String tag : tags) { - writer.value(tag); - } - } - writer.endArray(); - writer.endObject(); - } - } @Override diff --git a/main/src/com/google/refine/expr/EvalError.java b/main/src/com/google/refine/expr/EvalError.java index 34682cdfc..c87744c3e 100644 --- a/main/src/com/google/refine/expr/EvalError.java +++ b/main/src/com/google/refine/expr/EvalError.java @@ -34,14 +34,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.expr; import java.io.Serializable; -import java.util.Properties; - -import org.json.JSONException; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; /** * An error that occurs during the evaluation of an Evaluable. Errors are values, too @@ -49,7 +44,7 @@ import com.google.refine.Jsonizable; * thrown because an error might occupy just one element in an array and doesn't need * to make the whole array erroneous. */ -public class EvalError implements Serializable, Jsonizable { +public class EvalError implements Serializable { private static final long serialVersionUID = -102681220092874080L; @JsonProperty("message") @@ -69,16 +64,6 @@ public class EvalError implements Serializable, Jsonizable { return this.message; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("type"); writer.value("error"); - writer.key("message"); writer.value(message); - writer.endObject(); - } - @JsonProperty("type") public String getType() { return "error"; diff --git a/main/src/com/google/refine/expr/MetaParser.java b/main/src/com/google/refine/expr/MetaParser.java index a9d8d8ae5..274b8e0f8 100644 --- a/main/src/com/google/refine/expr/MetaParser.java +++ b/main/src/com/google/refine/expr/MetaParser.java @@ -39,11 +39,11 @@ import java.util.Map; import java.util.Properties; import java.util.Set; +import com.google.refine.grel.Parser; + import clojure.lang.IFn; import clojure.lang.RT; -import com.google.refine.grel.Parser; - abstract public class MetaParser { static public class LanguageInfo { diff --git a/main/src/com/google/refine/grel/Control.java b/main/src/com/google/refine/grel/Control.java index a4e475da1..392017e23 100644 --- a/main/src/com/google/refine/grel/Control.java +++ b/main/src/com/google/refine/grel/Control.java @@ -35,14 +35,10 @@ package com.google.refine.grel; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.expr.Evaluable; /** @@ -50,7 +46,7 @@ import com.google.refine.expr.Evaluable; * decide which part of the code to execute and can affect the environment bindings. * Functions, on the other hand, can't do either. */ -public interface Control extends Jsonizable { +public interface Control { public Object call(Properties bindings, Evaluable[] args); public String checkArguments(Evaluable[] args); @@ -66,17 +62,4 @@ public interface Control extends Jsonizable { @JsonProperty("returns") public String getReturns(); - - @Override - default public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value(getDescription()); - if (!getParams().isEmpty()) { - writer.key("params"); writer.value(getParams()); - } - writer.key("returns"); writer.value(getReturns()); - writer.endObject(); - } } diff --git a/main/src/com/google/refine/grel/ControlFunctionRegistry.java b/main/src/com/google/refine/grel/ControlFunctionRegistry.java index 8745832b9..1ef16e95c 100644 --- a/main/src/com/google/refine/grel/ControlFunctionRegistry.java +++ b/main/src/com/google/refine/grel/ControlFunctionRegistry.java @@ -108,19 +108,19 @@ import com.google.refine.expr.functions.strings.Contains; import com.google.refine.expr.functions.strings.Diff; import com.google.refine.expr.functions.strings.EndsWith; import com.google.refine.expr.functions.strings.Escape; +import com.google.refine.expr.functions.strings.Find; import com.google.refine.expr.functions.strings.Fingerprint; import com.google.refine.expr.functions.strings.IndexOf; import com.google.refine.expr.functions.strings.LastIndexOf; import com.google.refine.expr.functions.strings.MD5; import com.google.refine.expr.functions.strings.Match; -import com.google.refine.expr.functions.strings.Find; import com.google.refine.expr.functions.strings.NGram; import com.google.refine.expr.functions.strings.NGramFingerprint; import com.google.refine.expr.functions.strings.ParseJson; import com.google.refine.expr.functions.strings.Partition; import com.google.refine.expr.functions.strings.Phonetic; -import com.google.refine.expr.functions.strings.Range; import com.google.refine.expr.functions.strings.RPartition; +import com.google.refine.expr.functions.strings.Range; import com.google.refine.expr.functions.strings.Reinterpret; import com.google.refine.expr.functions.strings.Replace; import com.google.refine.expr.functions.strings.ReplaceChars; @@ -144,8 +144,8 @@ import com.google.refine.grel.controls.ForNonBlank; import com.google.refine.grel.controls.ForRange; import com.google.refine.grel.controls.If; import com.google.refine.grel.controls.IsBlank; -import com.google.refine.grel.controls.IsError; import com.google.refine.grel.controls.IsEmptyString; +import com.google.refine.grel.controls.IsError; import com.google.refine.grel.controls.IsNonBlank; import com.google.refine.grel.controls.IsNotNull; import com.google.refine.grel.controls.IsNull; diff --git a/main/src/com/google/refine/grel/Function.java b/main/src/com/google/refine/grel/Function.java index c3c346855..fb1d49482 100644 --- a/main/src/com/google/refine/grel/Function.java +++ b/main/src/com/google/refine/grel/Function.java @@ -35,18 +35,15 @@ package com.google.refine.grel; import java.util.Properties; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; /** * Interface for functions. When a function is called, its arguments have already * been evaluated down into non-error values. */ -public interface Function extends Jsonizable { +public interface Function { public Object call(Properties bindings, Object[] args); @JsonProperty("description") @@ -60,15 +57,4 @@ public interface Function extends Jsonizable { @JsonProperty("returns") public String getReturns(); - - @Override - default public void write(JSONWriter writer, Properties options) { - writer.object(); - writer.key("description"); writer.value(getDescription()); - if (!getParams().isEmpty()) { - writer.key("params"); writer.value(getParams()); - } - writer.key("returns"); writer.value(getReturns()); - writer.endObject(); - } } diff --git a/main/src/com/google/refine/history/Change.java b/main/src/com/google/refine/history/Change.java index d7812a1d6..cb3a9f4cd 100644 --- a/main/src/com/google/refine/history/Change.java +++ b/main/src/com/google/refine/history/Change.java @@ -50,5 +50,6 @@ public interface Change { public void apply(Project project); public void revert(Project project); + public void save(Writer writer, Properties options) throws IOException; } diff --git a/main/src/com/google/refine/history/History.java b/main/src/com/google/refine/history/History.java index f41ca0863..e667e3503 100644 --- a/main/src/com/google/refine/history/History.java +++ b/main/src/com/google/refine/history/History.java @@ -46,12 +46,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.RefineServlet; import com.google.refine.model.Project; @@ -64,7 +60,7 @@ import com.google.refine.util.Pool; * the history entries are much smaller and can be kept in memory, while the change objects * are only loaded into memory on demand. */ -public class History implements Jsonizable { +public class History { static public Change readOneChange(InputStream in, Pool pool) throws Exception { LineNumberReader reader = new LineNumberReader(new InputStreamReader(in, "UTF-8")); try { @@ -263,27 +259,6 @@ public class History implements Jsonizable { } } - @Override - synchronized public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - - writer.key("past"); writer.array(); - for (HistoryEntry entry : _pastEntries) { - entry.write(writer, options); - } - writer.endArray(); - - writer.key("future"); writer.array(); - for (HistoryEntry entry : _futureEntries) { - entry.write(writer, options); - } - writer.endArray(); - - writer.endObject(); - } - /* * NOTE: this method is called from the autosave thread with the Project * lock already held, so no other synchronized method here can aquire that diff --git a/main/src/com/google/refine/history/HistoryEntry.java b/main/src/com/google/refine/history/HistoryEntry.java index 8c56fb885..f2c7f793d 100644 --- a/main/src/com/google/refine/history/HistoryEntry.java +++ b/main/src/com/google/refine/history/HistoryEntry.java @@ -34,13 +34,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.history; import java.io.Writer; -import java.time.ZoneId; import java.time.OffsetDateTime; +import java.time.ZoneId; import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,7 +46,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonView; -import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; @@ -60,7 +57,7 @@ import com.google.refine.util.ParsingUtilities; * This is the metadata of a Change. It's small, so we can load it in order to * obtain information about a change without actually loading the change. */ -public class HistoryEntry implements Jsonizable { +public class HistoryEntry { final static Logger logger = LoggerFactory.getLogger("HistoryEntry"); @JsonProperty("id") final public long id; @@ -117,20 +114,6 @@ public class HistoryEntry implements Jsonizable { } } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("id"); writer.value(id); - writer.key("description"); writer.value(description); - writer.key("time"); writer.value(ParsingUtilities.dateToString(time)); - if ("save".equals(options.getProperty("mode")) && operation != null) { - writer.key(OPERATION); operation.write(writer, options); - } - writer.endObject(); - } - public void save(Writer writer, Properties options){ _manager.save(this, writer, options); } diff --git a/main/src/com/google/refine/history/HistoryProcess.java b/main/src/com/google/refine/history/HistoryProcess.java index 19c8769cd..80a5ccbba 100644 --- a/main/src/com/google/refine/history/HistoryProcess.java +++ b/main/src/com/google/refine/history/HistoryProcess.java @@ -33,11 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.history; -import java.util.Properties; - -import org.json.JSONException; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; @@ -98,17 +93,6 @@ public class HistoryProcess extends Process { public void startPerforming(ProcessManager manager) { throw new RuntimeException(WARN); } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("description"); writer.value(_description); - writer.key("immediate"); writer.value(true); - writer.key("status"); writer.value(getStatus()); - writer.endObject(); - } @JsonProperty("status") public String getStatus() { diff --git a/main/src/com/google/refine/importing/DefaultImportingController.java b/main/src/com/google/refine/importing/DefaultImportingController.java index c226097fb..b7b920dae 100644 --- a/main/src/com/google/refine/importing/DefaultImportingController.java +++ b/main/src/com/google/refine/importing/DefaultImportingController.java @@ -50,6 +50,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.RefineServlet; import com.google.refine.commands.HttpUtilities; import com.google.refine.importing.ImportingManager.Format; @@ -272,6 +274,19 @@ public class DefaultImportingController implements ImportingController { } } + protected static class JobResponse { + @JsonProperty("code") + protected String code; + @JsonProperty("job") + protected ImportingJob job; + + protected JobResponse(String code, ImportingJob job) { + this.code = code; + this.job = job; + } + + } + /** * return the job to the front end. * @param request @@ -284,18 +299,9 @@ public class DefaultImportingController implements ImportingController { throws ServletException, IOException { Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); - try { - writer.object(); - writer.key("code"); writer.value("ok"); - writer.key("job"); job.write(writer, new Properties()); - writer.endObject(); - } catch (JSONException e) { - throw new ServletException(e); - } finally { - w.flush(); - w.close(); - } + ParsingUtilities.defaultWriter.writeValue(w, job); + w.flush(); + w.close(); } static public void writeErrors(JSONWriter writer, List exceptions) throws JSONException { diff --git a/main/src/com/google/refine/importing/ImportingJob.java b/main/src/com/google/refine/importing/ImportingJob.java index 17d644d41..4f52f6c3b 100644 --- a/main/src/com/google/refine/importing/ImportingJob.java +++ b/main/src/com/google/refine/importing/ImportingJob.java @@ -37,22 +37,18 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.Properties; import org.apache.commons.io.FileUtils; import org.json.JSONArray; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; -import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.model.Project; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; -public class ImportingJob implements Jsonizable { +public class ImportingJob { final public long id; final public File dir; // Temporary directory where the data about this job is stored @@ -205,15 +201,4 @@ public class ImportingJob implements Jsonizable { dir2.mkdirs(); return dir2; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - synchronized(lock) { - writer.object(); - writer.key("config"); writer.value(config); - writer.endObject(); - } - } } diff --git a/main/src/com/google/refine/io/FileHistoryEntryManager.java b/main/src/com/google/refine/io/FileHistoryEntryManager.java index 0094fca5d..9d8ce5f16 100644 --- a/main/src/com/google/refine/io/FileHistoryEntryManager.java +++ b/main/src/com/google/refine/io/FileHistoryEntryManager.java @@ -35,6 +35,7 @@ package com.google.refine.io; import java.io.File; import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStreamReader; import java.io.Writer; import java.util.Properties; @@ -42,13 +43,11 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.ProjectManager; import com.google.refine.history.History; import com.google.refine.history.HistoryEntry; import com.google.refine.history.HistoryEntryManager; +import com.google.refine.util.ParsingUtilities; import com.google.refine.util.Pool; @@ -64,10 +63,9 @@ public class FileHistoryEntryManager implements HistoryEntryManager{ @Override public void save(HistoryEntry historyEntry, Writer writer, Properties options) { - JSONWriter jsonWriter = new JSONWriter(writer); try { - historyEntry.write(jsonWriter, options); - } catch (JSONException e) { + ParsingUtilities.defaultWriter.writeValue(writer, historyEntry); + } catch (IOException e) { e.printStackTrace(); } } @@ -116,6 +114,8 @@ public class FileHistoryEntryManager implements HistoryEntryManager{ out.putNextEntry(new ZipEntry("change.txt")); try { History.writeOneChange(out, historyEntry.getChange(), pool); + } catch(Exception e) { + e.printStackTrace(); } finally { out.closeEntry(); } diff --git a/main/src/com/google/refine/io/FileProjectManager.java b/main/src/com/google/refine/io/FileProjectManager.java index ac8f75829..2baa454fc 100644 --- a/main/src/com/google/refine/io/FileProjectManager.java +++ b/main/src/com/google/refine/io/FileProjectManager.java @@ -43,7 +43,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.HashMap; import java.util.Map.Entry; -import java.util.Properties; import java.util.Set; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; @@ -55,14 +54,12 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.history.HistoryEntryManager; import com.google.refine.model.Project; @@ -71,9 +68,10 @@ import com.google.refine.model.metadata.IMetadata; import com.google.refine.model.metadata.MetadataFormat; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.preference.TopList; +import com.google.refine.util.ParsingUtilities; -public class FileProjectManager extends ProjectManager implements Jsonizable { +public class FileProjectManager extends ProjectManager { final static protected String PROJECT_DIR_SUFFIX = ".project"; protected File _workspaceDir; @@ -251,7 +249,9 @@ public class FileProjectManager extends ProjectManager implements Jsonizable { ProjectMetadataUtilities.save(metadata, projectDir); } else if (metadata.getFormatName() == MetadataFormat.DATAPACKAGE_METADATA) { DataPackageMetadata dp = (DataPackageMetadata)metadata; - dp.writeToFile(new File(projectDir, DataPackageMetadata.DEFAULT_FILE_NAME)); + FileWriter writer = new FileWriter(new File(projectDir, DataPackageMetadata.DEFAULT_FILE_NAME)); + ParsingUtilities.defaultWriter.writeValue(writer, dp); + writer.close(); } logger.info("metadata saved in " + metadata.getFormatName()); @@ -326,8 +326,7 @@ public class FileProjectManager extends ProjectManager implements Jsonizable { FileWriter writer = new FileWriter(file); boolean saveWasNeeded = saveNeeded(); try { - JSONWriter jsonWriter = new JSONWriter(writer); - write(jsonWriter, new Properties()); + ParsingUtilities.defaultWriter.writeValue(writer, this); saveProjectMetadata(); } finally { writer.close(); @@ -486,25 +485,6 @@ public class FileProjectManager extends ProjectManager implements Jsonizable { gos.close(); } } - - @Override - public void write(JSONWriter jsonWriter, Properties options) - throws JSONException { - jsonWriter.object(); - jsonWriter.key("projectIDs"); - jsonWriter.array(); - for (Long id : _projectsMetadata.keySet()) { - ProjectMetadata metadata = _projectsMetadata.get(id); - if (metadata != null) { - jsonWriter.value(id); - } - } - jsonWriter.endArray(); - - jsonWriter.key("preferences"); - _preferenceStore.write(jsonWriter, new Properties()); - jsonWriter.endObject(); - } @JsonProperty("projectIDs") public Set getProjectIds() { diff --git a/main/src/com/google/refine/io/ProjectMetadataUtilities.java b/main/src/com/google/refine/io/ProjectMetadataUtilities.java index 6b5a77e94..e41fa500d 100644 --- a/main/src/com/google/refine/io/ProjectMetadataUtilities.java +++ b/main/src/com/google/refine/io/ProjectMetadataUtilities.java @@ -46,13 +46,13 @@ import java.util.List; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.json.JSONException; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.refine.model.Project; import com.google.refine.model.metadata.IMetadata; import com.google.refine.model.metadata.ProjectMetadata; +import com.google.refine.util.ParsingUtilities; public class ProjectMetadataUtilities { final static Logger logger = LoggerFactory.getLogger("project_metadata_utilities"); @@ -78,8 +78,7 @@ public class ProjectMetadataUtilities { protected static void saveToFile(IMetadata projectMeta, File metadataFile) throws JSONException, IOException { Writer writer = new OutputStreamWriter(new FileOutputStream(metadataFile)); try { - JSONWriter jsonWriter = new JSONWriter(writer); - projectMeta.write(jsonWriter, false); + ParsingUtilities.defaultWriter.writeValue(writer, projectMeta); } finally { writer.close(); } diff --git a/main/src/com/google/refine/model/AbstractOperation.java b/main/src/com/google/refine/model/AbstractOperation.java index f21c930d9..414bbe453 100644 --- a/main/src/com/google/refine/model/AbstractOperation.java +++ b/main/src/com/google/refine/model/AbstractOperation.java @@ -37,7 +37,6 @@ import java.util.Properties; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.history.HistoryEntry; import com.google.refine.operations.OperationRegistry; import com.google.refine.process.Process; @@ -47,7 +46,7 @@ import com.google.refine.process.QuickHistoryEntryProcess; * An abstract operation can be applied to different but similar * projects. */ -abstract public class AbstractOperation implements Jsonizable { +abstract public class AbstractOperation { public Process createProcess(Project project, Properties options) throws Exception { return new QuickHistoryEntryProcess(project, getBriefDescription(null)) { @Override diff --git a/main/src/com/google/refine/model/Cell.java b/main/src/com/google/refine/model/Cell.java index fcaa86b5e..33d71b922 100644 --- a/main/src/com/google/refine/model/Cell.java +++ b/main/src/com/google/refine/model/Cell.java @@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model; +import java.io.IOException; import java.io.Serializable; import java.io.Writer; import java.time.Instant; @@ -41,9 +42,6 @@ import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -52,7 +50,6 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; -import com.google.refine.Jsonizable; import com.google.refine.expr.EvalError; import com.google.refine.expr.ExpressionUtils; import com.google.refine.expr.HasFields; @@ -60,7 +57,7 @@ import com.google.refine.util.ParsingUtilities; import com.google.refine.util.Pool; import com.google.refine.util.StringUtils; -public class Cell implements HasFields, Jsonizable { +public class Cell implements HasFields { @JsonIgnore final public Serializable value; @JsonIgnore @@ -85,31 +82,6 @@ public class Cell implements HasFields, Jsonizable { public boolean fieldAlsoHasFields(String name) { return "recon".equals(name); } - - @Override - public void write(JSONWriter writer, Properties options) throws JSONException { - writer.object(); - if (ExpressionUtils.isError(value)) { - writer.key("e"); - writer.value(((EvalError) value).message); - } else { - writer.key("v"); - writer.value(getValueAsString()); - String jsonType = getTypeString(); - if(jsonType != null) { - writer.key("t"); writer.value(jsonType); - } - } - - if (recon != null) { - writer.key("r"); - writer.value(Long.toString(recon.id)); - - Pool pool = (Pool) options.get("pool"); - pool.pool(recon); - } - writer.endObject(); - } @JsonProperty("e") @JsonInclude(Include.NON_NULL) @@ -171,15 +143,17 @@ public class Cell implements HasFields, Jsonizable { if (recon != null) { return Long.toString(recon.id); } - // TODO pool the recon?? return null; } public void save(Writer writer, Properties options) { - JSONWriter jsonWriter = new JSONWriter(writer); try { - write(jsonWriter, options); - } catch (JSONException e) { + Pool pool = (Pool)options.get("pool"); + if(pool != null && recon != null) { + pool.pool(recon); + } + ParsingUtilities.saveWriter.writeValue(writer, this); + } catch (IOException e) { e.printStackTrace(); } } diff --git a/main/src/com/google/refine/model/Column.java b/main/src/com/google/refine/model/Column.java index e3cdf4538..171b7eda5 100644 --- a/main/src/com/google/refine/model/Column.java +++ b/main/src/com/google/refine/model/Column.java @@ -33,23 +33,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model; +import java.io.IOException; import java.io.Writer; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; -import java.util.Properties; import org.apache.commons.lang3.StringUtils; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.InterProjectModel; -import com.google.refine.Jsonizable; import com.google.refine.model.recon.ReconConfig; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; @@ -59,7 +56,7 @@ import io.frictionlessdata.tableschema.TypeInferrer; import io.frictionlessdata.tableschema.exceptions.ConstraintsException; import io.frictionlessdata.tableschema.exceptions.InvalidCastException; -public class Column implements Jsonizable { +public class Column { final private int _cellIndex; final private String _originalName; private String _name; @@ -118,31 +115,6 @@ public class Column implements Jsonizable { public ReconStats getReconStats() { return _reconStats; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("cellIndex"); writer.value(_cellIndex); - writer.key("originalName"); writer.value(_originalName); - writer.key("name"); writer.value(_name); - writer.key("type"); writer.value(type); - writer.key("format"); writer.value(format); - writer.key("title"); writer.value(title); - writer.key("description"); writer.value(description); - writer.key("constraints"); writer.value(new JSONObject(constraints).toString()); - if (_reconConfig != null) { - writer.key("reconConfig"); - _reconConfig.write(writer, options); - } - if (_reconStats != null) { - writer.key("reconStats"); - _reconStats.write(writer, options); - } - writer.endObject(); - } - /** * Clear all cached precomputed values. @@ -230,10 +202,9 @@ public class Column implements Jsonizable { } public void save(Writer writer) { - JSONWriter jsonWriter = new JSONWriter(writer); try { - write(jsonWriter, new Properties()); - } catch (JSONException e) { + ParsingUtilities.defaultWriter.writeValue(writer, this); + } catch (IOException e) { e.printStackTrace(); } } diff --git a/main/src/com/google/refine/model/ColumnGroup.java b/main/src/com/google/refine/model/ColumnGroup.java index 1ba26d1ad..c8a261af2 100644 --- a/main/src/com/google/refine/model/ColumnGroup.java +++ b/main/src/com/google/refine/model/ColumnGroup.java @@ -33,25 +33,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model; +import java.io.IOException; import java.io.Writer; import java.util.LinkedList; import java.util.List; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonView; -import com.google.refine.Jsonizable; import com.google.refine.util.JsonViews; import com.google.refine.util.ParsingUtilities; -public class ColumnGroup implements Jsonizable { +public class ColumnGroup { final public int startColumnIndex; final public int columnSpan; final public int keyColumnIndex; // could be -1 if there is no key cell @@ -66,26 +63,6 @@ public class ColumnGroup implements Jsonizable { internalInitialize(); } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - - writer.key("startColumnIndex"); writer.value(startColumnIndex); - writer.key("columnSpan"); writer.value(columnSpan); - writer.key("keyColumnIndex"); writer.value(keyColumnIndex); - - if (!"save".equals(options.get("mode")) && (subgroups != null) && (subgroups.size() > 0)) { - writer.key("subgroups"); writer.array(); - for (ColumnGroup g : subgroups) { - g.write(writer, options); - } - writer.endArray(); - } - writer.endObject(); - } - @JsonProperty("startColumnIndex") public int getStartColumnIndex() { return startColumnIndex; @@ -114,10 +91,9 @@ public class ColumnGroup implements Jsonizable { } public void save(Writer writer) { - JSONWriter jsonWriter = new JSONWriter(writer); try { - write(jsonWriter, new Properties()); - } catch (JSONException e) { + ParsingUtilities.defaultWriter.writeValue(writer, this); + } catch (IOException e) { e.printStackTrace(); } } diff --git a/main/src/com/google/refine/model/ColumnModel.java b/main/src/com/google/refine/model/ColumnModel.java index a4109c1b3..112ad97b3 100644 --- a/main/src/com/google/refine/model/ColumnModel.java +++ b/main/src/com/google/refine/model/ColumnModel.java @@ -45,17 +45,13 @@ import java.util.List; import java.util.Map; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; -public class ColumnModel implements Jsonizable { +public class ColumnModel { @JsonProperty("columns") final public List columns = new LinkedList(); @JsonProperty("columnGroups") @@ -179,34 +175,6 @@ public class ColumnModel implements Jsonizable { synchronized public List getColumnNames() { return _columnNames; } - - @Override - synchronized public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - - writer.key("columns"); - writer.array(); - for (Column column : columns) { - column.write(writer, options); - } - writer.endArray(); - - if (columns.size() > 0) { - writer.key("keyCellIndex"); writer.value(getKeyColumnIndex()); - writer.key("keyColumnName"); writer.value(columns.get(_keyColumnIndex).getName()); - } - - writer.key("columnGroups"); - writer.array(); - for (ColumnGroup g : _rootColumnGroups) { - g.write(writer, options); - } - writer.endArray(); - - writer.endObject(); - } @JsonProperty("keyCellIndex") @JsonInclude(Include.NON_NULL) diff --git a/main/src/com/google/refine/model/OverlayModel.java b/main/src/com/google/refine/model/OverlayModel.java index 1b1b184b9..7ca914173 100644 --- a/main/src/com/google/refine/model/OverlayModel.java +++ b/main/src/com/google/refine/model/OverlayModel.java @@ -33,9 +33,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model; -import com.google.refine.Jsonizable; -public interface OverlayModel extends Jsonizable { +public interface OverlayModel { public void onBeforeSave(Project project); public void onAfterSave(Project project); diff --git a/main/src/com/google/refine/model/Project.java b/main/src/com/google/refine/model/Project.java index 4b4a511cf..113e591d9 100644 --- a/main/src/com/google/refine/model/Project.java +++ b/main/src/com/google/refine/model/Project.java @@ -48,9 +48,7 @@ import java.util.List; import java.util.Map; import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -160,13 +158,7 @@ public class Project { writer.write(modelName); writer.write("="); - try { - JSONWriter jsonWriter = new JSONWriter(writer); - - overlayModels.get(modelName).write(jsonWriter, options); - } catch (JSONException e) { - e.printStackTrace(); - } + ParsingUtilities.saveWriter.writeValue(writer, overlayModels.get(modelName)); writer.write('\n'); } diff --git a/main/src/com/google/refine/model/Recon.java b/main/src/com/google/refine/model/Recon.java index a4b726708..f96125ed3 100644 --- a/main/src/com/google/refine/model/Recon.java +++ b/main/src/com/google/refine/model/Recon.java @@ -40,9 +40,6 @@ import java.util.List; import java.util.Map; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonFilter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -53,13 +50,12 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; -import com.google.refine.Jsonizable; import com.google.refine.expr.HasFields; import com.google.refine.util.JsonViews; import com.google.refine.util.Pool; @JsonFilter("reconCandidateFilter") -public class Recon implements HasFields, Jsonizable { +public class Recon implements HasFields { /** * Freebase schema URLs kept for compatibility with legacy reconciliation results @@ -366,56 +362,6 @@ public class Recon implements HasFields, Jsonizable { return null; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - boolean saveMode = "save".equals(options.getProperty("mode")); - - writer.object(); - writer.key("id"); writer.value(id); - if (saveMode) { - writer.key("judgmentHistoryEntry"); writer.value(judgmentHistoryEntry); - } - - writer.key("service"); writer.value(service); - writer.key("identifierSpace"); writer.value(identifierSpace); - writer.key("schemaSpace"); writer.value(schemaSpace); - - writer.key("j"); writer.value(judgmentToString()); - if (match != null) { - writer.key("m"); - match.write(writer, options); - } - if (match == null || saveMode) { - writer.key("c"); writer.array(); - if (candidates != null) { - for (ReconCandidate c : candidates) { - c.write(writer, options); - } - } - writer.endArray(); - } - - if (saveMode) { - writer.key("f"); - writer.array(); - for (Object o : features) { - writer.value(o); - } - writer.endArray(); - - writer.key("judgmentAction"); writer.value(judgmentAction); - writer.key("judgmentBatchSize"); writer.value(judgmentBatchSize); - - if (match != null) { - writer.key("matchRank"); writer.value(matchRank); - } - } - - writer.endObject(); - } - static public Recon loadStreaming(String s, Pool pool) throws Exception { JsonFactory jsonFactory = new JsonFactory(); JsonParser jp = jsonFactory.createJsonParser(s); diff --git a/main/src/com/google/refine/model/ReconCandidate.java b/main/src/com/google/refine/model/ReconCandidate.java index 7c3f4c9d0..6b2e86f3a 100644 --- a/main/src/com/google/refine/model/ReconCandidate.java +++ b/main/src/com/google/refine/model/ReconCandidate.java @@ -37,19 +37,14 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; -import com.google.refine.Jsonizable; import com.google.refine.expr.HasFields; -public class ReconCandidate implements HasFields, Jsonizable { +public class ReconCandidate implements HasFields { @JsonProperty("id") final public String id; @JsonProperty("name") @@ -84,26 +79,6 @@ public class ReconCandidate implements HasFields, Jsonizable { public boolean fieldAlsoHasFields(String name) { return false; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("id"); writer.value(id); - writer.key("name"); writer.value(name); - writer.key("score"); writer.value(score); - - /* if (!options.containsKey("reconCandidateOmitTypes")) */ { - writer.key("types"); writer.array(); - for (String typeID : types) { - writer.value(typeID); - } - writer.endArray(); - } - - writer.endObject(); - } static public ReconCandidate loadStreaming(String s) throws Exception { JsonFactory jsonFactory = new JsonFactory(); diff --git a/main/src/com/google/refine/model/ReconStats.java b/main/src/com/google/refine/model/ReconStats.java index 00f555e29..f9b887a19 100644 --- a/main/src/com/google/refine/model/ReconStats.java +++ b/main/src/com/google/refine/model/ReconStats.java @@ -33,20 +33,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model; +import java.io.IOException; import java.io.Writer; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.expr.ExpressionUtils; import com.google.refine.model.Recon.Judgment; +import com.google.refine.util.ParsingUtilities; -public class ReconStats implements Jsonizable { +public class ReconStats { static public ReconStats load(JSONObject obj) throws Exception { return new ReconStats( obj.getInt("nonBlanks"), @@ -67,17 +65,6 @@ public class ReconStats implements Jsonizable { this.newTopics = newTopics; this.matchedTopics = matchedTopics; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("nonBlanks"); writer.value(nonBlanks); - writer.key("newTopics"); writer.value(newTopics); - writer.key("matchedTopics"); writer.value(matchedTopics); - writer.endObject(); - } static public ReconStats create(Project project, int cellIndex) { int nonBlanks = 0; @@ -103,10 +90,9 @@ public class ReconStats implements Jsonizable { } public void save(Writer writer) { - JSONWriter jsonWriter = new JSONWriter(writer); try { - write(jsonWriter, new Properties()); - } catch (JSONException e) { + ParsingUtilities.defaultWriter.writeValue(writer, this); + } catch (IOException e) { e.printStackTrace(); } } diff --git a/main/src/com/google/refine/model/ReconType.java b/main/src/com/google/refine/model/ReconType.java index 3f172bf28..ac023719a 100644 --- a/main/src/com/google/refine/model/ReconType.java +++ b/main/src/com/google/refine/model/ReconType.java @@ -33,22 +33,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model; -import java.util.Properties; - -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; /** * This represents a type from the reconciliation * service. It is used when extending data to * store the (expected) types of new columns. */ -public class ReconType implements Jsonizable { +public class ReconType { @JsonProperty("id") public String id; @JsonProperty("name") @@ -59,16 +54,6 @@ public class ReconType implements Jsonizable { this.name = name; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("id"); writer.value(id); - writer.key("name"); writer.value(name); - writer.endObject(); - } - static public ReconType load(JSONObject obj) throws Exception { if (obj == null) { return null; diff --git a/main/src/com/google/refine/model/RecordModel.java b/main/src/com/google/refine/model/RecordModel.java index 2d1bf0569..fe9ccae13 100644 --- a/main/src/com/google/refine/model/RecordModel.java +++ b/main/src/com/google/refine/model/RecordModel.java @@ -38,20 +38,16 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.expr.ExpressionUtils; -public class RecordModel implements Jsonizable { +public class RecordModel { final static Logger logger = LoggerFactory.getLogger("RecordModel"); final static public class CellDependency { @@ -108,16 +104,6 @@ public class RecordModel implements Jsonizable { } return null; } - - @Override - synchronized public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("hasRecords"); - writer.value(hasRecords()); - writer.endObject(); - } @JsonProperty("hasRecords") public boolean hasRecords() { diff --git a/main/src/com/google/refine/model/Row.java b/main/src/com/google/refine/model/Row.java index 780f1fe92..bfa5f7db6 100644 --- a/main/src/com/google/refine/model/Row.java +++ b/main/src/com/google/refine/model/Row.java @@ -33,32 +33,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model; +import java.io.IOException; import java.io.Writer; import java.util.ArrayList; import java.util.List; -import java.util.Map.Entry; import java.util.Properties; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; -import org.json.JSONException; -import org.json.JSONWriter; -import com.google.refine.Jsonizable; import com.google.refine.expr.CellTuple; import com.google.refine.expr.HasFields; -import com.google.refine.util.JsonViews; +import com.google.refine.util.ParsingUtilities; import com.google.refine.util.Pool; /** * Class representing a single Row which contains a list of {@link Cell}s. There may * be multiple rows in a {@link Record}. */ -public class Row implements HasFields, Jsonizable { +public class Row implements HasFields { public boolean flagged; public boolean starred; final public List cells; @@ -165,50 +161,6 @@ public class Row implements HasFields, Jsonizable { return new CellTuple(project, this); } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key(FLAGGED); writer.value(flagged); - writer.key(STARRED); writer.value(starred); - - writer.key("cells"); writer.array(); - for (Cell cell : cells) { - if (cell != null) { - cell.write(writer, options); - } else { - writer.value(null); - } - } - writer.endArray(); - - if (!"save".equals(options.getProperty("mode"))) { - if (options.containsKey("rowIndex")) { - int rowIndex = (Integer) options.get("rowIndex"); - writer.key("i"); writer.value(rowIndex); - - if (options.containsKey("recordIndex")) { - int recordIndex = (Integer) options.get("recordIndex"); - - writer.key("j"); writer.value(recordIndex); - } - } - - if (options.containsKey("extra")) { - Properties extra = (Properties) options.get("extra"); - if (extra != null) { - for (Entry e : extra.entrySet()) { - writer.key((String) e.getKey()); - writer.value(e.getValue()); - } - } - } - } - - writer.endObject(); - } - @JsonProperty(FLAGGED) public boolean isFlagged() { return flagged; @@ -230,10 +182,21 @@ public class Row implements HasFields, Jsonizable { */ public void save(Writer writer, Properties options) { - JSONWriter jsonWriter = new JSONWriter(writer); + if (options.containsKey("rowIndex")) { + // See GetRowsCommand to serialize a row with indices + throw new IllegalArgumentException("Serializing with row indices is not supported anymore."); + } try { - write(jsonWriter, options); - } catch (JSONException e) { + ParsingUtilities.saveWriter.writeValue(writer, this); + Pool pool = (Pool)options.get("pool"); + if(pool != null) { + for(Cell c : cells) { + if (c != null && c.recon != null) { + pool.pool(c.recon); + } + } + } + } catch (IOException e) { e.printStackTrace(); } } diff --git a/main/src/com/google/refine/model/changes/ColumnChange.java b/main/src/com/google/refine/model/changes/ColumnChange.java index df2956865..55757e801 100644 --- a/main/src/com/google/refine/model/changes/ColumnChange.java +++ b/main/src/com/google/refine/model/changes/ColumnChange.java @@ -40,11 +40,9 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.history.Change; import com.google.refine.model.ColumnGroup; +import com.google.refine.util.ParsingUtilities; abstract public class ColumnChange implements Change { @@ -52,13 +50,8 @@ abstract public class ColumnChange implements Change { List oldColumnGroups) throws IOException { writer.write("oldColumnGroupCount="); writer.write(Integer.toString(oldColumnGroups.size())); writer.write('\n'); - for (ColumnGroup cg : oldColumnGroups) { - JSONWriter jsonWriter = new JSONWriter(writer); - try { - cg.write(jsonWriter, options); - } catch (JSONException e) { - throw new IOException(e); - } + for (ColumnGroup cg : oldColumnGroups) { + ParsingUtilities.saveWriter.writeValue(writer, cg); writer.write('\n'); } } diff --git a/main/src/com/google/refine/model/changes/DataExtensionChange.java b/main/src/com/google/refine/model/changes/DataExtensionChange.java index a034c9ebc..31348540a 100644 --- a/main/src/com/google/refine/model/changes/DataExtensionChange.java +++ b/main/src/com/google/refine/model/changes/DataExtensionChange.java @@ -307,13 +307,8 @@ public class DataExtensionChange implements Change { } writer.write("columnTypeCount="); writer.write(Integer.toString(_columnTypes.size())); writer.write('\n'); for (ReconType type : _columnTypes) { - try { - if(type != null) { - JSONWriter jsonWriter = new JSONWriter(writer); - type.write(jsonWriter, options); - } - } catch (JSONException e) { - // ??? + if(type != null) { + ParsingUtilities.defaultWriter.writeValue(writer, type); } writer.write('\n'); } diff --git a/main/src/com/google/refine/model/changes/MassReconChange.java b/main/src/com/google/refine/model/changes/MassReconChange.java index 5e8eb2a13..0e4df55bb 100644 --- a/main/src/com/google/refine/model/changes/MassReconChange.java +++ b/main/src/com/google/refine/model/changes/MassReconChange.java @@ -50,6 +50,7 @@ import com.google.refine.model.Cell; import com.google.refine.model.Project; import com.google.refine.model.Recon; import com.google.refine.model.Row; +import com.google.refine.util.ParsingUtilities; import com.google.refine.util.Pool; public class MassReconChange implements Change { @@ -110,12 +111,7 @@ public class MassReconChange implements Change { Pool pool = (Pool) options.get("pool"); pool.poolReconCandidates(recon); - JSONWriter jsonWriter = new JSONWriter(writer); - try { - recon.write(jsonWriter, options); - } catch (JSONException e) { - e.printStackTrace(); - } + ParsingUtilities.saveWriter.writeValue(writer, recon); writer.write("\n"); } } diff --git a/main/src/com/google/refine/model/metadata/AbstractMetadata.java b/main/src/com/google/refine/model/metadata/AbstractMetadata.java index 84b0f878e..43a5ac9b5 100644 --- a/main/src/com/google/refine/model/metadata/AbstractMetadata.java +++ b/main/src/com/google/refine/model/metadata/AbstractMetadata.java @@ -2,12 +2,9 @@ package com.google.refine.model.metadata; import java.io.File; import java.time.LocalDateTime; -import java.util.Properties; import org.apache.commons.beanutils.PropertyUtils; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; public abstract class AbstractMetadata implements IMetadata { private MetadataFormat formatName = MetadataFormat.UNKNOWN; @@ -30,9 +27,6 @@ public abstract class AbstractMetadata implements IMetadata { @Override public abstract void loadFromFile(File metadataFile); - @Override - public abstract void writeToFile(File metadataFile); - @Override public boolean isDirty() { return written == null || _modified.isAfter(written); @@ -48,23 +42,6 @@ public abstract class AbstractMetadata implements IMetadata { _modified = LocalDateTime.now(); } - /** - * @param jsonWriter - * writer to save metadatea to - * @param onlyIfDirty - * true to not write unchanged metadata - * @throws JSONException - */ - @Override - public void write(JSONWriter jsonWriter, boolean onlyIfDirty) throws JSONException { - if (!onlyIfDirty || isDirty()) { - Properties options = new Properties(); - options.setProperty("mode", "save"); - - write(jsonWriter, options); - } - } - protected static boolean propertyExists(Object bean, String property) { return PropertyUtils.isReadable(bean, property) && PropertyUtils.isWriteable(bean, property); diff --git a/main/src/com/google/refine/model/metadata/DataPackageMetadata.java b/main/src/com/google/refine/model/metadata/DataPackageMetadata.java index 3ddac2f93..b314d6e74 100644 --- a/main/src/com/google/refine/model/metadata/DataPackageMetadata.java +++ b/main/src/com/google/refine/model/metadata/DataPackageMetadata.java @@ -3,21 +3,20 @@ package com.google.refine.model.metadata; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.StringWriter; import java.util.ArrayList; import java.util.List; -import java.util.Properties; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.everit.json.schema.ValidationException; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonRawValue; +import com.fasterxml.jackson.annotation.JsonValue; + import io.frictionlessdata.datapackage.Package; import io.frictionlessdata.datapackage.Resource; import io.frictionlessdata.datapackage.exceptions.DataPackageException; @@ -30,6 +29,12 @@ public class DataPackageMetadata extends AbstractMetadata { private Package _pkg; + @JsonValue + @JsonRawValue + public String getJson() { + return _pkg.getJson().toString(); + } + public DataPackageMetadata() { setFormatName(MetadataFormat.DATAPACKAGE_METADATA); @@ -61,30 +66,6 @@ public class DataPackageMetadata extends AbstractMetadata { loadFromJSON(new JSONObject(jsonString)); } - /** - * Write the package to a json file. - */ - @Override - public void writeToFile(File metadataFile) { - try { - this._pkg.save(metadataFile.getAbsolutePath()); - } catch (IOException e) { - logger.error("IO exception when writing to file " + metadataFile.getAbsolutePath(), - ExceptionUtils.getStackTrace(e)); - } catch (DataPackageException e) { - logger.error("Data package exception when writing to file " + metadataFile.getAbsolutePath(), - ExceptionUtils.getStackTrace(e)); - } - } - - @Override - public void write(JSONWriter jsonWriter, Properties options) - throws JSONException { - StringWriter sw = new StringWriter(); - _pkg.getJson().write(sw); - jsonWriter = new JSONWriter(sw); - } - @Override public void loadFromStream(InputStream inputStream) { try { @@ -107,11 +88,6 @@ public class DataPackageMetadata extends AbstractMetadata { return listResources; } - - @Override - public JSONObject getJSON() { - return _pkg.getJson(); - } public Package getPackage() { return _pkg; diff --git a/main/src/com/google/refine/model/metadata/IMetadata.java b/main/src/com/google/refine/model/metadata/IMetadata.java index d3d4192d0..8f5f863fd 100644 --- a/main/src/com/google/refine/model/metadata/IMetadata.java +++ b/main/src/com/google/refine/model/metadata/IMetadata.java @@ -5,30 +5,18 @@ import java.io.InputStream; import java.time.LocalDateTime; import java.util.List; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; -import com.google.refine.Jsonizable; /** * Interface to import/export metadata */ -public interface IMetadata extends Jsonizable { +public interface IMetadata { public void loadFromJSON(JSONObject obj); public void loadFromFile(File metadataFile); public void loadFromStream(InputStream inputStream); - public void writeToFile(File metadataFile); - - /** - * @param jsonWriter writer to save metadatea to - * @param onlyIfDirty true to not write unchanged metadata - * @throws JSONException - */ - public void write(JSONWriter jsonWriter, boolean onlyIfDirty); - public MetadataFormat getFormatName(); public void setFormatName(MetadataFormat format); @@ -38,7 +26,5 @@ public interface IMetadata extends Jsonizable { public boolean isDirty(); - public JSONObject getJSON(); - public List validate(); } diff --git a/main/src/com/google/refine/model/metadata/ProjectMetadata.java b/main/src/com/google/refine/model/metadata/ProjectMetadata.java index d12806c3c..d81c1e611 100644 --- a/main/src/com/google/refine/model/metadata/ProjectMetadata.java +++ b/main/src/com/google/refine/model/metadata/ProjectMetadata.java @@ -64,10 +64,19 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonRawValue; +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import com.fasterxml.jackson.annotation.JsonView; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + import com.google.refine.ProjectManager; import com.google.refine.preference.PreferenceStore; import com.google.refine.preference.TopList; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.JsonViews; import com.google.refine.util.ParsingUtilities; public class ProjectMetadata extends AbstractMetadata { @@ -75,36 +84,77 @@ public class ProjectMetadata extends AbstractMetadata { final public static String TEMP_FILE_NAME = "metadata.temp.json"; final public static String OLD_FILE_NAME = "metadata.old.json"; + @JsonProperty("created") private final LocalDateTime _created; + @JsonProperty("name") private String _name = ""; + @JsonProperty("password") + @JsonView(JsonViews.SaveMode.class) private String _password = ""; + @JsonProperty("encoding") + @JsonView(JsonViews.SaveMode.class) private String _encoding = ""; + @JsonProperty("encodingConfidence") + @JsonView(JsonViews.SaveMode.class) private int _encodingConfidence; + @JsonProperty("rowCount") private int _rowCount; // user metadata - private JSONArray _userMetadata = new JSONArray();; + private JSONArray _userMetadata = new JSONArray(); // _tags maps to keywords of the data package metadata + @JsonProperty("tags") private String[] _tags = new String[0]; + @JsonProperty("creator") private String _creator = ""; + @JsonProperty("contributors") private String _contributors = ""; + @JsonProperty("subject") private String _subject = ""; // Several refine projects may be linked + @JsonProperty("description") private String _description = ""; // free form of comment // import options is an array for 1-n data sources private JSONArray _importOptionMetadata = new JSONArray(); - + @JsonUnwrapped private Map _customMetadata = new HashMap(); + @JsonProperty("preferences") + @JsonView(JsonViews.SaveMode.class) private PreferenceStore _preferenceStore = new PreferenceStore(); // below 5 fields are from data package metadata: + @JsonProperty("title") private String title = ""; + @JsonProperty("homepage") private String homepage; + @JsonProperty("image") private String image = ""; + @JsonProperty("license") private String license = ""; + @JsonProperty("version") private String version = ""; + + @JsonProperty("userMetadata") + @JsonRawValue + @JsonInclude(Include.NON_NULL) + public String getJsonUserMetadata() { + if (_userMetadata.length() > 0) { + return _userMetadata.toString(); + } + return null; + } + + @JsonProperty("importOptionMetadata") + @JsonRawValue + @JsonInclude(Include.NON_NULL) + public String getJsonImportOptionMetadata() { + if (_importOptionMetadata.length() > 0) { + return _importOptionMetadata.toString(); + } + return null; + } private final static Logger logger = LoggerFactory.getLogger("project_metadata"); @@ -130,86 +180,12 @@ public class ProjectMetadata extends AbstractMetadata { updateModified(); } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("name"); - writer.value(_name); - writer.key("tags"); - writer.array(); - for (String tag : _tags) { - writer.value(tag); - } - writer.endArray(); - writer.key("created"); writer.value(ParsingUtilities.localDateToString(_created)); - writer.key("modified"); writer.value(ParsingUtilities.localDateToString(_modified)); - writer.key("creator"); writer.value(_creator); - writer.key("contributors"); writer.value(_contributors); - writer.key("subject"); writer.value(_subject); - writer.key("description"); writer.value(_description); - writer.key("rowCount"); writer.value(_rowCount); - writer.key("title"); writer.value(title); - writer.key("homepage"); writer.value(homepage); - writer.key("image"); writer.value(image); - writer.key("license"); writer.value(license); - writer.key("version"); writer.value(version); - - writer.key("customMetadata"); - writer.object(); - - for (String key : _customMetadata.keySet()) { - Serializable value = _customMetadata.get(key); - writer.key(key); - writer.value(value); - } - writer.endObject(); - - // write JSONArray directly - if (_importOptionMetadata.length() > 0) { - writer.key("importOptionMetadata"); - writer.value(_importOptionMetadata); - } - - // write user metadata in {name, value, display} form: - if (_userMetadata.length() > 0) { - writer.key(PreferenceStore.USER_METADATA_KEY); - writer.value(_userMetadata); - } - - if (isSaveMode(options)) { - writer.key("password"); - writer.value(_password); - - writer.key("encoding"); - writer.value(_encoding); - writer.key("encodingConfidence"); - writer.value(_encodingConfidence); - - writer.key("preferences"); - _preferenceStore.write(writer, options); - } - - writer.endObject(); - - if (isSaveMode(options)) { - written = LocalDateTime.now(); - } - } - - public void writeWithoutOption(JSONWriter writer) - throws JSONException { - write(writer, new Properties()); - } - - private boolean isSaveMode(Properties options) { - return "save".equals(options.getProperty("mode")); - } - - public void write(JSONWriter jsonWriter) - throws JSONException { - write(jsonWriter, false); + @JsonProperty("saveModeWritten") + @JsonView(JsonViews.SaveMode.class) + @JsonInclude(Include.NON_NULL) + public String setSaveModeWritten() { + written = LocalDateTime.now(); + return null; } public void loadFromJSON(JSONObject obj) { @@ -555,25 +531,6 @@ public class ProjectMetadata extends AbstractMetadata { loadFromStream(targetStream); } - @Override - public void writeToFile(File metadataFile) { - Writer writer = null; - try { - writer = new OutputStreamWriter(new FileOutputStream(metadataFile)); - - JSONWriter jsonWriter = new JSONWriter(writer); - write(jsonWriter, false); - } catch (FileNotFoundException e) { - logger.error(ExceptionUtils.getStackTrace(e)); - } finally { - try { - writer.close(); - } catch (IOException e) { - logger.error(ExceptionUtils.getStackTrace(e)); - } - } - } - @Override public void loadFromStream(InputStream inputStream) { try (InputStreamReader reader = new InputStreamReader(inputStream)) { @@ -586,15 +543,6 @@ public class ProjectMetadata extends AbstractMetadata { } } - @Override - public JSONObject getJSON() { - StringWriter writer = new StringWriter(); - JSONWriter jsonWriter = new JSONWriter(writer); - writeWithoutOption(jsonWriter); - - return new JSONObject(jsonWriter.toString()); - } - @Override public List validate() { return null; diff --git a/main/src/com/google/refine/model/metadata/validator/ValidateOperation.java b/main/src/com/google/refine/model/metadata/validator/ValidateOperation.java index bb918712a..10d0f3a86 100644 --- a/main/src/com/google/refine/model/metadata/validator/ValidateOperation.java +++ b/main/src/com/google/refine/model/metadata/validator/ValidateOperation.java @@ -1,10 +1,6 @@ package com.google.refine.model.metadata.validator; -import java.util.Properties; - -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; @@ -22,11 +18,4 @@ public class ValidateOperation extends AbstractOperation { return ValidatorInspector.inspect(project, options); } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - // TODO Auto-generated method stub - - } - } diff --git a/main/src/com/google/refine/model/recon/DataExtensionReconConfig.java b/main/src/com/google/refine/model/recon/DataExtensionReconConfig.java index 9c1eede9b..29c8c3590 100644 --- a/main/src/com/google/refine/model/recon/DataExtensionReconConfig.java +++ b/main/src/com/google/refine/model/recon/DataExtensionReconConfig.java @@ -33,21 +33,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model.recon; -import java.util.List; -import java.util.Properties; import java.util.ArrayList; +import java.util.List; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; -import com.google.refine.model.ReconType; import com.google.refine.model.Cell; import com.google.refine.model.Project; import com.google.refine.model.Recon; +import com.google.refine.model.ReconType; import com.google.refine.model.Row; -import com.google.refine.model.recon.StandardReconConfig; -import com.google.refine.model.recon.ReconJob; public class DataExtensionReconConfig extends StandardReconConfig { final public ReconType type; diff --git a/main/src/com/google/refine/model/recon/ReconConfig.java b/main/src/com/google/refine/model/recon/ReconConfig.java index 7f11af0f8..063cc5e13 100644 --- a/main/src/com/google/refine/model/recon/ReconConfig.java +++ b/main/src/com/google/refine/model/recon/ReconConfig.java @@ -33,31 +33,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model.recon; +import java.io.IOException; import java.io.Writer; import java.lang.reflect.Method; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.model.Cell; import com.google.refine.model.Project; import com.google.refine.model.Recon; import com.google.refine.model.Row; +import com.google.refine.util.ParsingUtilities; import edu.mit.simile.butterfly.ButterflyModule; -abstract public class ReconConfig implements Jsonizable { +abstract public class ReconConfig { final static protected Logger LOGGER = LoggerFactory.getLogger("recon-config"); static final public Map>> s_opNameToClass = @@ -125,11 +123,10 @@ abstract public class ReconConfig implements Jsonizable { abstract public Recon createNewRecon(long historyEntryID); public void save(Writer writer) { - JSONWriter jsonWriter = new JSONWriter(writer); try { - write(jsonWriter, new Properties()); - } catch (JSONException e) { - LOGGER.error("Save failed",e); + ParsingUtilities.defaultWriter.writeValue(writer, this); + } catch (IOException e) { + e.printStackTrace(); } } diff --git a/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java b/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java index 2d971a06d..83c78e538 100644 --- a/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java +++ b/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java @@ -47,35 +47,35 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Set; import java.util.stream.Collectors; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.refine.Jsonizable; import com.google.refine.expr.functions.ToDate; import com.google.refine.model.ReconCandidate; import com.google.refine.model.ReconType; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.JsonViews; import com.google.refine.util.ParsingUtilities; public class ReconciledDataExtensionJob { - static public class DataExtensionProperty implements Jsonizable { + static public class DataExtensionProperty { @JsonProperty("id") public final String id; @JsonProperty("name") + @JsonView(JsonViews.NonSaveMode.class) public final String name; @JsonProperty("settings") @JsonInclude(Include.NON_NULL) @@ -92,31 +92,10 @@ public class ReconciledDataExtensionJob { this.id = id; this.name = name; this.settings = settings; - } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("id"); writer.value(id); - if(!"query".equals(options.getProperty("mode"))) { - writer.key("name"); writer.value(name); - } - if (settings != null) { - writer.key("settings"); - writer.object(); - for(Map.Entry entry : settings.entrySet()) { - writer.key(entry.getKey()); - writer.value(entry.getValue()); - } - writer.endObject(); - } - writer.endObject(); - } - + } } - static public class DataExtensionConfig implements Jsonizable { + static public class DataExtensionConfig { @JsonProperty("properties") public final List properties; @@ -135,22 +114,7 @@ public class ReconciledDataExtensionJob { } catch(IOException e) { throw new JSONException(e.toString()); } - } - - @Override - public void write(JSONWriter jsonWriter, Properties options) - throws JSONException { - jsonWriter.object(); - jsonWriter.key("properties"); - jsonWriter.array(); - - for (DataExtensionProperty property : properties) { - property.write(jsonWriter, options); - } - jsonWriter.endArray(); - jsonWriter.endObject(); - } - + } } static public class DataExtensionQuery extends DataExtensionConfig { @@ -166,34 +130,7 @@ public class ReconciledDataExtensionJob { List properties) { super(properties); this.ids = ids; - } - - @Override - public void write(JSONWriter jsonWriter, Properties options) - throws JSONException { - jsonWriter.object(); - - if(ids != null) { - jsonWriter.key("ids"); - jsonWriter.array(); - for (String id : ids) { - if (id != null) { - jsonWriter.value(id); - } - } - jsonWriter.endArray(); - } - - jsonWriter.key("properties"); - jsonWriter.array(); - - for (DataExtensionProperty property : properties) { - property.write(jsonWriter, options); - } - jsonWriter.endArray(); - jsonWriter.endObject(); - } - + } } static public class DataExtension { @@ -382,12 +319,9 @@ public class ReconciledDataExtensionJob { } - static protected void formulateQuery(Set ids, DataExtensionConfig node, Writer writer) throws JSONException { - JSONWriter jsonWriter = new JSONWriter(writer); - Properties options = new Properties(); + static protected void formulateQuery(Set ids, DataExtensionConfig node, Writer writer) throws IOException { DataExtensionQuery query = new DataExtensionQuery(ids.stream().collect(Collectors.toList()), node.properties); - options.setProperty("mode", "query"); - query.write(jsonWriter, options); + ParsingUtilities.saveWriter.writeValue(writer, query); } static protected void gatherColumnInfo(JSONArray meta, List columns) throws JSONException { diff --git a/main/src/com/google/refine/model/recon/StandardReconConfig.java b/main/src/com/google/refine/model/recon/StandardReconConfig.java index 43e3754b8..068bd4b29 100644 --- a/main/src/com/google/refine/model/recon/StandardReconConfig.java +++ b/main/src/com/google/refine/model/recon/StandardReconConfig.java @@ -42,7 +42,6 @@ import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.HashSet; import java.util.List; -import java.util.Properties; import java.util.Set; import org.apache.commons.lang3.StringUtils; @@ -56,7 +55,6 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.expr.ExpressionUtils; import com.google.refine.model.Cell; import com.google.refine.model.Project; @@ -71,7 +69,7 @@ import com.google.refine.util.ParsingUtilities; public class StandardReconConfig extends ReconConfig { final static Logger logger = LoggerFactory.getLogger("refine-standard-recon"); - static public class ColumnDetail implements Jsonizable { + static public class ColumnDetail { @JsonProperty("column") final public String columnName; @JsonProperty("propertyName") @@ -84,17 +82,6 @@ public class StandardReconConfig extends ReconConfig { this.propertyName = propertyName; this.propertyID = propertyID; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("column"); writer.value(columnName); - writer.key("propertyName"); writer.value(propertyName); - writer.key("propertyID"); writer.value(propertyID); - writer.endObject(); - - } } static public ReconConfig reconstruct(JSONObject obj) throws Exception { @@ -214,35 +201,6 @@ public class StandardReconConfig extends ReconConfig { this.columnDetails = columnDetails; this.limit = limit; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("mode"); writer.value("standard-service"); - writer.key("service"); writer.value(service); - writer.key("identifierSpace"); writer.value(identifierSpace); - writer.key("schemaSpace"); writer.value(schemaSpace); - writer.key("type"); - if (typeID == null) { - writer.value(null); - } else { - writer.object(); - writer.key("id"); writer.value(typeID); - writer.key("name"); writer.value(typeName); - writer.endObject(); - } - writer.key("autoMatch"); writer.value(autoMatch); - writer.key("columnDetails"); - writer.array(); - for (ColumnDetail c : columnDetails) { - c.write(writer, options); - } - writer.endArray(); - writer.key("limit"); writer.value(limit); - writer.endObject(); - } @JsonProperty("type") public ReconType getReconType() { diff --git a/main/src/com/google/refine/operations/cell/BlankDownOperation.java b/main/src/com/google/refine/operations/cell/BlankDownOperation.java index 17d2f0b1a..0afda51b2 100644 --- a/main/src/com/google/refine/operations/cell/BlankDownOperation.java +++ b/main/src/com/google/refine/operations/cell/BlankDownOperation.java @@ -34,11 +34,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.cell; import java.util.List; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.EngineConfig; @@ -51,7 +48,6 @@ import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.operations.OperationRegistry; public class BlankDownOperation extends EngineDependentMassCellOperation { @@ -71,18 +67,6 @@ public class BlankDownOperation extends EngineDependentMassCellOperation { super(engineConfig, columnName, true); } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("columnName"); writer.value(_columnName); - writer.endObject(); - } - @Override protected String getBriefDescription(Project project) { return "Blank down cells in column " + _columnName; diff --git a/main/src/com/google/refine/operations/cell/FillDownOperation.java b/main/src/com/google/refine/operations/cell/FillDownOperation.java index 23a42c5a3..1ecca6345 100644 --- a/main/src/com/google/refine/operations/cell/FillDownOperation.java +++ b/main/src/com/google/refine/operations/cell/FillDownOperation.java @@ -34,11 +34,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.cell; import java.util.List; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine.Mode; @@ -52,7 +49,6 @@ import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.operations.OperationRegistry; public class FillDownOperation extends EngineDependentMassCellOperation { @@ -72,18 +68,6 @@ public class FillDownOperation extends EngineDependentMassCellOperation { super(engineConfig, columnName, true); } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("columnName"); writer.value(_columnName); - writer.endObject(); - } - @Override protected String getBriefDescription(Project project) { return "Fill down cells in column " + _columnName; diff --git a/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java b/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java index 37ca3a7af..c4d29535d 100644 --- a/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java +++ b/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java @@ -37,11 +37,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -53,7 +50,6 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowColumnChange; -import com.google.refine.operations.OperationRegistry; import com.google.refine.util.JSONUtilities; public class KeyValueColumnizeOperation extends AbstractOperation { @@ -78,22 +74,6 @@ public class KeyValueColumnizeOperation extends AbstractOperation { _valueColumnName = valueColumnName; _noteColumnName = noteColumnName; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value( - "Columnize by key column " + - _keyColumnName + " and value column " + _valueColumnName + - (_noteColumnName != null ? (" with note column " + _noteColumnName) : "")); - writer.key("keyColumnName"); writer.value(_keyColumnName); - writer.key("valueColumnName"); writer.value(_valueColumnName); - writer.key("noteColumnName"); writer.value(_noteColumnName); - writer.endObject(); - } @JsonProperty("keyColumnName") public String getKeyColumnName() { diff --git a/main/src/com/google/refine/operations/cell/MassEditOperation.java b/main/src/com/google/refine/operations/cell/MassEditOperation.java index 3a288b2fe..d9388b8e1 100644 --- a/main/src/com/google/refine/operations/cell/MassEditOperation.java +++ b/main/src/com/google/refine/operations/cell/MassEditOperation.java @@ -41,13 +41,10 @@ import java.util.Map; import java.util.Properties; import org.json.JSONArray; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.expr.Evaluable; @@ -60,7 +57,6 @@ import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.operations.OperationRegistry; import com.google.refine.util.ParsingUtilities; import com.google.refine.util.StringUtils; @@ -68,7 +64,7 @@ public class MassEditOperation extends EngineDependentMassCellOperation { final protected String _expression; final protected List _edits; - static public class Edit implements Jsonizable { + static public class Edit { @JsonProperty("from") final public List from; @JsonProperty("fromBlank") @@ -84,23 +80,6 @@ public class MassEditOperation extends EngineDependentMassCellOperation { this.fromError = fromError; this.to = to; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("fromBlank"); writer.value(fromBlank); - writer.key("fromError"); writer.value(fromError); - writer.key("from"); - writer.array(); - for (String s : from) { - writer.value(s); - } - writer.endArray(); - writer.key("to"); writer.value(to); - writer.endObject(); - } } static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { @@ -157,25 +136,6 @@ public class MassEditOperation extends EngineDependentMassCellOperation { _expression = expression; _edits = edits; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("columnName"); writer.value(_columnName); - writer.key("expression"); writer.value(_expression); - writer.key("edits"); - writer.array(); - for (Edit edit : _edits) { - edit.write(writer, options); - } - writer.endArray(); - writer.endObject(); - } @JsonProperty("expression") public String getExpression() { diff --git a/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java b/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java index ba1b37a18..112214b14 100644 --- a/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java +++ b/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java @@ -35,11 +35,8 @@ package com.google.refine.operations.cell; import java.util.ArrayList; import java.util.List; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -51,7 +48,6 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowChange; -import com.google.refine.operations.OperationRegistry; public class MultiValuedCellJoinOperation extends AbstractOperation { final protected String _columnName; @@ -75,19 +71,6 @@ public class MultiValuedCellJoinOperation extends AbstractOperation { _keyColumnName = keyColumnName; _separator = separator; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("columnName"); writer.value(_columnName); - writer.key("keyColumnName"); writer.value(_keyColumnName); - writer.key("separator"); writer.value(_separator); - writer.endObject(); - } @JsonProperty("columnName") public String getColumnName() { diff --git a/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java b/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java index d9537f941..180d2c864 100644 --- a/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java +++ b/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java @@ -35,13 +35,10 @@ package com.google.refine.operations.cell; import java.util.ArrayList; import java.util.List; -import java.util.Properties; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -54,7 +51,6 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowChange; -import com.google.refine.operations.OperationRegistry; import com.google.refine.util.JSONUtilities; public class MultiValuedCellSplitOperation extends AbstractOperation { @@ -148,29 +144,6 @@ public class MultiValuedCellSplitOperation extends AbstractOperation { return _fieldLengths; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value("Split multi-valued cells in column " + _columnName); - writer.key("columnName"); writer.value(_columnName); - writer.key("keyColumnName"); writer.value(_keyColumnName); - writer.key("mode"); writer.value(_mode); - if ("separator".equals(_mode)) { - writer.key("separator"); writer.value(_separator); - writer.key("regex"); writer.value(_regex); - } else { - writer.key("fieldLengths"); writer.array(); - for (int l : _fieldLengths) { - writer.value(l); - } - writer.endArray(); - } - writer.endObject(); - } - @Override protected String getBriefDescription(Project project) { return "Split multi-valued cells in column " + _columnName; diff --git a/main/src/com/google/refine/operations/cell/TextTransformOperation.java b/main/src/com/google/refine/operations/cell/TextTransformOperation.java index 6016cb92b..fa3a07c30 100644 --- a/main/src/com/google/refine/operations/cell/TextTransformOperation.java +++ b/main/src/com/google/refine/operations/cell/TextTransformOperation.java @@ -37,9 +37,7 @@ import java.io.Serializable; import java.util.List; import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; @@ -55,7 +53,6 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.operations.EngineDependentMassCellOperation; import com.google.refine.operations.OnError; -import com.google.refine.operations.OperationRegistry; public class TextTransformOperation extends EngineDependentMassCellOperation { final protected String _expression; @@ -110,22 +107,6 @@ public class TextTransformOperation extends EngineDependentMassCellOperation { _repeatCount = repeatCount; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("columnName"); writer.value(_columnName); - writer.key("expression"); writer.value(_expression); - writer.key("onError"); writer.value(onErrorToString(_onError)); - writer.key("repeat"); writer.value(_repeat); - writer.key("repeatCount"); writer.value(_repeatCount); - writer.endObject(); - } - @Override protected String getBriefDescription(Project project) { return "Text transform on cells in column " + _columnName + " using expression " + _expression; diff --git a/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java b/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java index c45e8782c..41dc0774e 100644 --- a/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java +++ b/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java @@ -35,11 +35,8 @@ package com.google.refine.operations.cell; import java.util.ArrayList; import java.util.List; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; @@ -48,7 +45,6 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowColumnChange; -import com.google.refine.operations.OperationRegistry; import com.google.refine.util.JSONUtilities; public class TransposeColumnsIntoRowsOperation extends AbstractOperation { @@ -131,28 +127,6 @@ public class TransposeColumnsIntoRowsOperation extends AbstractOperation { _valueColumnName = valueColumnName; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription()); - writer.key("startColumnName"); writer.value(_startColumnName); - writer.key("columnCount"); writer.value(_columnCount); - writer.key("ignoreBlankCells"); writer.value(_ignoreBlankCells); - writer.key("fillDown"); writer.value(_fillDown); - if (_combinedColumnName != null) { - writer.key("combinedColumnName"); writer.value(_combinedColumnName); - writer.key("prependColumnName"); writer.value(_prependColumnName); - writer.key("separator"); writer.value(_separator); - } else { - writer.key("keyColumnName"); writer.value(_keyColumnName); - writer.key("valueColumnName"); writer.value(_valueColumnName); - } - writer.endObject(); - } - @Override protected String getBriefDescription(Project project) { return getBriefDescription(); diff --git a/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java b/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java index bb145be4a..a5455397f 100644 --- a/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java +++ b/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java @@ -35,11 +35,8 @@ package com.google.refine.operations.cell; import java.util.ArrayList; import java.util.List; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -50,7 +47,6 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowColumnChange; -import com.google.refine.operations.OperationRegistry; public class TransposeRowsIntoColumnsOperation extends AbstractOperation { final protected String _columnName; @@ -70,18 +66,6 @@ public class TransposeRowsIntoColumnsOperation extends AbstractOperation { _columnName = columnName; _rowCount = rowCount; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value("Transpose every " + _rowCount + " cells in column " + _columnName + " into separate columns"); - writer.key("columnName"); writer.value(_columnName); - writer.key("rowCount"); writer.value(_rowCount); - writer.endObject(); - } @JsonProperty("rowCount") public int getRowCount() { diff --git a/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java b/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java index 3e623c92b..f8f7cd4c8 100644 --- a/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java @@ -48,7 +48,6 @@ import java.util.concurrent.TimeUnit; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -56,7 +55,6 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; -import com.google.refine.Jsonizable; import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; @@ -76,7 +74,6 @@ import com.google.refine.model.changes.CellAtRow; import com.google.refine.model.changes.ColumnAdditionChange; import com.google.refine.operations.EngineDependentOperation; import com.google.refine.operations.OnError; -import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.cell.TextTransformOperation; import com.google.refine.process.LongRunningProcess; import com.google.refine.process.Process; @@ -84,7 +81,7 @@ import com.google.refine.util.ParsingUtilities; public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperation { - public static final class HttpHeader implements Jsonizable { + public static final class HttpHeader { @JsonProperty("name") final public String name; @JsonProperty("value") @@ -94,15 +91,6 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat this.name = name; this.value = value; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("name"); writer.value(name); - writer.key("value"); writer.value(value); - writer.endObject(); - } } final protected String _baseColumnName; @@ -166,32 +154,6 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat _cacheResponses = cacheResponses; _httpHeadersJson = httpHeadersJson; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("newColumnName"); writer.value(_newColumnName); - writer.key("columnInsertIndex"); writer.value(_columnInsertIndex); - writer.key("baseColumnName"); writer.value(_baseColumnName); - writer.key("urlExpression"); writer.value(_urlExpression); - writer.key("onError"); writer.value(TextTransformOperation.onErrorToString(_onError)); - writer.key("delay"); writer.value(_delay); - writer.key("cacheResponses"); writer.value(_cacheResponses); - if (_httpHeadersJson != null) { - writer.key("httpHeadersJson"); - writer.array(); - for(HttpHeader header : _httpHeadersJson) { - header.write(writer, options); - } - writer.endArray(); - } - writer.endObject(); - } @JsonProperty("newColumnName") public String getNewColumnName() { diff --git a/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java b/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java index 0d4334a07..ae4b8077e 100644 --- a/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java @@ -38,9 +38,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -63,7 +61,6 @@ import com.google.refine.model.changes.CellAtRow; import com.google.refine.model.changes.ColumnAdditionChange; import com.google.refine.operations.EngineDependentOperation; import com.google.refine.operations.OnError; -import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.cell.TextTransformOperation; public class ColumnAdditionOperation extends EngineDependentOperation { @@ -104,22 +101,6 @@ public class ColumnAdditionOperation extends EngineDependentOperation { _newColumnName = newColumnName; _columnInsertIndex = columnInsertIndex; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("newColumnName"); writer.value(_newColumnName); - writer.key("columnInsertIndex"); writer.value(_columnInsertIndex); - writer.key("baseColumnName"); writer.value(_baseColumnName); - writer.key("expression"); writer.value(_expression); - writer.key("onError"); writer.value(TextTransformOperation.onErrorToString(_onError)); - writer.endObject(); - } @JsonProperty("newColumnName") public String getNewColumnName() { diff --git a/main/src/com/google/refine/operations/column/ColumnMoveOperation.java b/main/src/com/google/refine/operations/column/ColumnMoveOperation.java index a000859da..2b6cc7df0 100644 --- a/main/src/com/google/refine/operations/column/ColumnMoveOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnMoveOperation.java @@ -33,11 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.column; -import java.util.Properties; - -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -46,7 +42,6 @@ import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.model.changes.ColumnMoveChange; -import com.google.refine.operations.OperationRegistry; public class ColumnMoveOperation extends AbstractOperation { final protected String _columnName; @@ -67,18 +62,6 @@ public class ColumnMoveOperation extends AbstractOperation { _index = index; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value("Move column " + _columnName + " to position " + _index); - writer.key("columnName"); writer.value(_columnName); - writer.key("index"); writer.value(_index); - writer.endObject(); - } - @JsonProperty("columnName") public String getColumnName() { return _columnName; diff --git a/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java b/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java index 5de7a5895..8e48c87de 100644 --- a/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java @@ -33,11 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.column; -import java.util.Properties; - -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -47,7 +43,6 @@ import com.google.refine.model.AbstractOperation; import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.changes.ColumnRemovalChange; -import com.google.refine.operations.OperationRegistry; public class ColumnRemovalOperation extends AbstractOperation { final protected String _columnName; @@ -64,17 +59,6 @@ public class ColumnRemovalOperation extends AbstractOperation { _columnName = columnName; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value("Remove column " + _columnName); - writer.key("columnName"); writer.value(_columnName); - writer.endObject(); - } - @JsonProperty("columnName") public String getColumnName() { return _columnName; diff --git a/main/src/com/google/refine/operations/column/ColumnRenameOperation.java b/main/src/com/google/refine/operations/column/ColumnRenameOperation.java index 0d4b85c9a..d76f928a7 100644 --- a/main/src/com/google/refine/operations/column/ColumnRenameOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnRenameOperation.java @@ -33,11 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.column; -import java.util.Properties; - -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -46,7 +42,6 @@ import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.model.changes.ColumnRenameChange; -import com.google.refine.operations.OperationRegistry; public class ColumnRenameOperation extends AbstractOperation { final protected String _oldColumnName; @@ -67,18 +62,6 @@ public class ColumnRenameOperation extends AbstractOperation { _newColumnName = newColumnName; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value("Rename column " + _oldColumnName + " to " + _newColumnName); - writer.key("oldColumnName"); writer.value(_oldColumnName); - writer.key("newColumnName"); writer.value(_newColumnName); - writer.endObject(); - } - @JsonProperty("oldColumnName") public String getOldColumnName() { return _oldColumnName; diff --git a/main/src/com/google/refine/operations/column/ColumnReorderOperation.java b/main/src/com/google/refine/operations/column/ColumnReorderOperation.java index 3b7f906a8..2b1fe8d93 100644 --- a/main/src/com/google/refine/operations/column/ColumnReorderOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnReorderOperation.java @@ -35,11 +35,8 @@ package com.google.refine.operations.column; import java.util.ArrayList; import java.util.List; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -47,7 +44,6 @@ import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.model.changes.ColumnReorderChange; -import com.google.refine.operations.OperationRegistry; import com.google.refine.util.JSONUtilities; public class ColumnReorderOperation extends AbstractOperation { @@ -64,21 +60,6 @@ public class ColumnReorderOperation extends AbstractOperation { public ColumnReorderOperation(List columnNames) { _columnNames = columnNames; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("columnNames"); writer.array(); - for (String n : _columnNames) { - writer.value(n); - } - writer.endArray(); - writer.endObject(); - } @JsonProperty("columnNames") public List getColumnNames() { diff --git a/main/src/com/google/refine/operations/column/ColumnSplitOperation.java b/main/src/com/google/refine/operations/column/ColumnSplitOperation.java index adc7d1860..330efa1e7 100644 --- a/main/src/com/google/refine/operations/column/ColumnSplitOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnSplitOperation.java @@ -36,13 +36,10 @@ package com.google.refine.operations.column; import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import java.util.Properties; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -62,7 +59,6 @@ import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.ColumnSplitChange; import com.google.refine.operations.EngineDependentOperation; -import com.google.refine.operations.OperationRegistry; import com.google.refine.util.JSONUtilities; public class ColumnSplitOperation extends EngineDependentOperation { @@ -145,32 +141,6 @@ public class ColumnSplitOperation extends EngineDependentOperation { _fieldLengths = fieldLengths; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("columnName"); writer.value(_columnName); - writer.key("guessCellType"); writer.value(_guessCellType); - writer.key("removeOriginalColumn"); writer.value(_removeOriginalColumn); - writer.key("mode"); writer.value(_mode); - if ("separator".equals(_mode)) { - writer.key("separator"); writer.value(_separator); - writer.key("regex"); writer.value(_regex); - writer.key("maxColumns"); writer.value(_maxColumns); - } else { - writer.key("fieldLengths"); writer.array(); - for (int l : _fieldLengths) { - writer.value(l); - } - writer.endArray(); - } - writer.endObject(); - } @JsonProperty("columnName") public String getColumnName() { diff --git a/main/src/com/google/refine/operations/recon/ExtendDataOperation.java b/main/src/com/google/refine/operations/recon/ExtendDataOperation.java index 3aaa5858c..fac3243ed 100644 --- a/main/src/com/google/refine/operations/recon/ExtendDataOperation.java +++ b/main/src/com/google/refine/operations/recon/ExtendDataOperation.java @@ -43,7 +43,6 @@ import java.util.Set; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -66,7 +65,6 @@ import com.google.refine.model.recon.ReconciledDataExtensionJob.ColumnInfo; import com.google.refine.model.recon.ReconciledDataExtensionJob.DataExtension; import com.google.refine.model.recon.ReconciledDataExtensionJob.DataExtensionConfig; import com.google.refine.operations.EngineDependentOperation; -import com.google.refine.operations.OperationRegistry; import com.google.refine.process.LongRunningProcess; import com.google.refine.process.Process; @@ -120,23 +118,6 @@ public class ExtendDataOperation extends EngineDependentOperation { _columnInsertIndex = columnInsertIndex; } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("columnInsertIndex"); writer.value(_columnInsertIndex); - writer.key("baseColumnName"); writer.value(_baseColumnName); - writer.key("endpoint"); writer.value(_endpoint); - writer.key("identifierSpace"); writer.value(_identifierSpace); - writer.key("schemaSpace"); writer.value(_schemaSpace); - writer.key("extension"); _extension.write(writer, options); - writer.endObject(); - } - @Override protected String getBriefDescription(Project project) { return "Extend data at index " + _columnInsertIndex + diff --git a/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java b/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java index 2b30ce3aa..8c3f2ca8d 100644 --- a/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java @@ -34,11 +34,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.recon; import java.util.List; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -53,7 +50,6 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.operations.OperationRegistry; public class ReconClearSimilarCellsOperation extends EngineDependentMassCellOperation { final protected String _similarValue; @@ -75,20 +71,6 @@ public class ReconClearSimilarCellsOperation extends EngineDependentMassCellOper super(engineConfig, columnName, false); this._similarValue = similarValue; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("columnName"); writer.value(_columnName); - writer.key("similarValue"); writer.value(_similarValue); - - writer.endObject(); - } @JsonProperty("columnName") public String getColumnName() { diff --git a/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java b/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java index 5d8c5c237..ae9cf5a31 100644 --- a/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java @@ -38,13 +38,10 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Set; import org.apache.commons.lang3.StringUtils; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -63,7 +60,6 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.MassChange; import com.google.refine.operations.EngineDependentOperation; -import com.google.refine.operations.OperationRegistry; import com.google.refine.util.JSONUtilities; public class ReconCopyAcrossColumnsOperation extends EngineDependentOperation { @@ -95,31 +91,6 @@ public class ReconCopyAcrossColumnsOperation extends EngineDependentOperation { _judgments = judgments; _applyToJudgedCells = applyToJudgedCells; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("fromColumnName"); writer.value(_fromColumnName); - writer.key("toColumnNames"); - writer.array(); - for (String s : _toColumnNames) { - writer.value(s); - } - writer.endArray(); - writer.key("judgments"); - writer.array(); - for (String s : _judgments) { - writer.value(s); - } - writer.endArray(); - writer.key("applyToJudgedCells"); writer.value(_applyToJudgedCells); - writer.endObject(); - } @JsonProperty("fromColumnName") public String getFromColumnName() { diff --git a/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java b/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java index c95524805..aeb49118b 100644 --- a/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java @@ -36,11 +36,8 @@ package com.google.refine.operations.recon; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -57,7 +54,6 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.operations.OperationRegistry; public class ReconDiscardJudgmentsOperation extends EngineDependentMassCellOperation { final protected boolean _clearData; @@ -75,19 +71,6 @@ public class ReconDiscardJudgmentsOperation extends EngineDependentMassCellOpera super(engineConfig, columnName, false); _clearData = clearData; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("columnName"); writer.value(_columnName); - writer.key("clearData"); writer.value(_clearData); - writer.endObject(); - } @JsonProperty("columnName") public String getColumnName() { diff --git a/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java b/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java index 5afc6ce98..18521988b 100644 --- a/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java @@ -36,16 +36,14 @@ package com.google.refine.operations.recon; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; @@ -63,7 +61,6 @@ import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.model.recon.ReconConfig; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.operations.OperationRegistry; public class ReconJudgeSimilarCellsOperation extends EngineDependentMassCellOperation { final protected String _similarValue; @@ -71,7 +68,7 @@ public class ReconJudgeSimilarCellsOperation extends EngineDependentMassCellOper final protected ReconCandidate _match; final protected boolean _shareNewTopics; - static public AbstractOperation reconstruct(JSONObject obj) throws JSONException { + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws JSONException { JSONObject engineConfig = obj.getJSONObject("engineConfig"); ReconCandidate match = null; @@ -121,25 +118,6 @@ public class ReconJudgeSimilarCellsOperation extends EngineDependentMassCellOper this._match = match; this._shareNewTopics = shareNewTopics; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("columnName"); writer.value(_columnName); - writer.key("similarValue"); writer.value(_similarValue); - writer.key("judgment"); writer.value(Recon.judgmentToString(_judgment)); - if (_match != null) { - writer.key("match"); _match.write(writer, options); - } - writer.key("shareNewTopics"); writer.value(_shareNewTopics); - - writer.endObject(); - } @JsonProperty("columnName") public String getColumnName() { diff --git a/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java b/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java index 363b52564..8d3efb59b 100644 --- a/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java @@ -36,11 +36,8 @@ package com.google.refine.operations.recon; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -58,7 +55,6 @@ import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.model.recon.ReconConfig; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.operations.OperationRegistry; public class ReconMarkNewTopicsOperation extends EngineDependentMassCellOperation { final protected boolean _shareNewTopics; @@ -77,19 +73,6 @@ public class ReconMarkNewTopicsOperation extends EngineDependentMassCellOperatio super(engineConfig, columnName, false); _shareNewTopics = shareNewTopics; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("columnName"); writer.value(_columnName); - writer.key("shareNewTopics"); writer.value(_shareNewTopics); - writer.endObject(); - } @JsonProperty("columnName") public String getColumnName() { diff --git a/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java b/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java index c17bf4346..9819ecef1 100644 --- a/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java @@ -36,11 +36,8 @@ package com.google.refine.operations.recon; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -58,7 +55,6 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.operations.OperationRegistry; public class ReconMatchBestCandidatesOperation extends EngineDependentMassCellOperation { static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { @@ -74,18 +70,6 @@ public class ReconMatchBestCandidatesOperation extends EngineDependentMassCellOp public ReconMatchBestCandidatesOperation(EngineConfig engineConfig, String columnName) { super(engineConfig, columnName, false); } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("columnName"); writer.value(_columnName); - writer.endObject(); - } @JsonProperty public String getColumnName() { diff --git a/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java b/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java index 1dce15216..3e7f85ccf 100644 --- a/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java @@ -36,12 +36,9 @@ package com.google.refine.operations.recon; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; import org.json.JSONArray; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -61,7 +58,6 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.operations.OperationRegistry; public class ReconMatchSpecificTopicOperation extends EngineDependentMassCellOperation { @@ -131,31 +127,6 @@ public class ReconMatchSpecificTopicOperation extends EngineDependentMassCellOpe this.identifierSpace = identifierSpace; this.schemaSpace = schemaSpace; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("columnName"); writer.value(_columnName); - writer.key("match"); - writer.object(); - writer.key("id"); writer.value(match.id); - writer.key("name"); writer.value(match.name); - writer.key("types"); - writer.array(); - for (String typeID : match.types) { - writer.value(typeID); - } - writer.endArray(); - writer.endObject(); - writer.key("identifierSpace"); writer.value(identifierSpace); - writer.key("schemaSpace"); writer.value(schemaSpace); - writer.endObject(); - } @Override protected String getBriefDescription(Project project) { diff --git a/main/src/com/google/refine/operations/recon/ReconOperation.java b/main/src/com/google/refine/operations/recon/ReconOperation.java index 278b93e35..34593b77c 100644 --- a/main/src/com/google/refine/operations/recon/ReconOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconOperation.java @@ -40,9 +40,7 @@ import java.util.List; import java.util.Map; import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,7 +54,6 @@ import com.google.refine.browsing.RowVisitor; import com.google.refine.expr.ExpressionUtils; import com.google.refine.history.Change; import com.google.refine.history.HistoryEntry; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; @@ -68,7 +65,6 @@ import com.google.refine.model.recon.ReconConfig; import com.google.refine.model.recon.ReconJob; import com.google.refine.model.recon.StandardReconConfig; import com.google.refine.operations.EngineDependentOperation; -import com.google.refine.operations.OperationRegistry; import com.google.refine.process.LongRunningProcess; import com.google.refine.process.Process; import com.google.refine.util.ParsingUtilities; @@ -112,19 +108,6 @@ public class ReconOperation extends EngineDependentOperation { protected String getBriefDescription(Project project) { return _reconConfig.getBriefDescription(project, _columnName); } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("columnName"); writer.value(_columnName); - writer.key("config"); _reconConfig.write(writer, options); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.endObject(); - } @JsonProperty("config") public ReconConfig getReconConfig() { @@ -205,50 +188,6 @@ public class ReconOperation extends EngineDependentOperation { } } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("id"); writer.value(hashCode()); - writer.key("description"); writer.value(_description); - writer.key("immediate"); writer.value(false); - writer.key("status"); writer.value(_thread == null ? "pending" : (_thread.isAlive() ? "running" : "done")); - writer.key("progress"); writer.value(_progress); - writer.key("onDone"); - writer.array(); - writer.object(); - writer.key("action"); writer.value("createFacet"); - writer.key("facetType"); writer.value("list"); - writer.key("facetConfig"); - writer.object(); - writer.key("name"); writer.value(_columnName + ": judgment"); - writer.key("columnName"); writer.value(_columnName); - writer.key("expression"); writer.value("forNonBlank(cell.recon.judgment, v, v, if(isNonBlank(value), \"(unreconciled)\", \"(blank)\"))"); - writer.endObject(); - writer.key("facetOptions"); - writer.object(); - writer.key("scroll"); writer.value(false); - writer.endObject(); - writer.endObject(); - - if (_reconConfig instanceof StandardReconConfig) { - writer.object(); - writer.key("action"); writer.value("createFacet"); - writer.key("facetType"); writer.value("range"); - writer.key("facetConfig"); - writer.object(); - writer.key("name"); writer.value(_columnName + ": best candidate's score"); - writer.key("columnName"); writer.value(_columnName); - writer.key("expression"); writer.value("cell.recon.best.score"); - writer.key("mode"); writer.value("range"); - writer.endObject(); - writer.endObject(); - } - writer.endArray(); - writer.endObject(); - } - @JsonProperty("onDone") public List onDoneActions() { List onDone = new ArrayList<>(); diff --git a/main/src/com/google/refine/operations/row/DenormalizeOperation.java b/main/src/com/google/refine/operations/row/DenormalizeOperation.java index 605654ed7..9daf246e9 100644 --- a/main/src/com/google/refine/operations/row/DenormalizeOperation.java +++ b/main/src/com/google/refine/operations/row/DenormalizeOperation.java @@ -35,11 +35,8 @@ package com.google.refine.operations.row; import java.util.ArrayList; import java.util.List; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; @@ -49,7 +46,6 @@ import com.google.refine.model.RecordModel.CellDependency; import com.google.refine.model.RecordModel.RowDependency; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowChange; -import com.google.refine.operations.OperationRegistry; public class DenormalizeOperation extends AbstractOperation { static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { @@ -58,17 +54,6 @@ public class DenormalizeOperation extends AbstractOperation { public DenormalizeOperation() { } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value("Denormalize"); - writer.endObject(); - } - @Override protected String getBriefDescription(Project project) { diff --git a/main/src/com/google/refine/operations/row/RowFlagOperation.java b/main/src/com/google/refine/operations/row/RowFlagOperation.java index fe8a1dbfc..b251d5ba8 100644 --- a/main/src/com/google/refine/operations/row/RowFlagOperation.java +++ b/main/src/com/google/refine/operations/row/RowFlagOperation.java @@ -35,11 +35,8 @@ package com.google.refine.operations.row; import java.util.ArrayList; import java.util.List; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -55,7 +52,6 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.MassChange; import com.google.refine.model.changes.RowFlagChange; import com.google.refine.operations.EngineDependentOperation; -import com.google.refine.operations.OperationRegistry; public class RowFlagOperation extends EngineDependentOperation { final protected boolean _flagged; @@ -74,18 +70,6 @@ public class RowFlagOperation extends EngineDependentOperation { super(engineConfig); _flagged = flagged; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("flagged"); writer.value(_flagged); - writer.endObject(); - } @JsonProperty("flagged") public boolean getFlagged() { diff --git a/main/src/com/google/refine/operations/row/RowRemovalOperation.java b/main/src/com/google/refine/operations/row/RowRemovalOperation.java index 3d7ee7a44..3445fadfe 100644 --- a/main/src/com/google/refine/operations/row/RowRemovalOperation.java +++ b/main/src/com/google/refine/operations/row/RowRemovalOperation.java @@ -35,11 +35,8 @@ package com.google.refine.operations.row; import java.util.ArrayList; import java.util.List; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; @@ -51,7 +48,6 @@ import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.RowRemovalChange; import com.google.refine.operations.EngineDependentOperation; -import com.google.refine.operations.OperationRegistry; public class RowRemovalOperation extends EngineDependentOperation { static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { @@ -66,17 +62,6 @@ public class RowRemovalOperation extends EngineDependentOperation { super(engineConfig); } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.endObject(); - } - @Override protected String getBriefDescription(Project project) { return "Remove rows"; diff --git a/main/src/com/google/refine/operations/row/RowReorderOperation.java b/main/src/com/google/refine/operations/row/RowReorderOperation.java index ee63cd799..340687732 100644 --- a/main/src/com/google/refine/operations/row/RowReorderOperation.java +++ b/main/src/com/google/refine/operations/row/RowReorderOperation.java @@ -35,11 +35,8 @@ package com.google.refine.operations.row; import java.util.ArrayList; import java.util.List; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -53,7 +50,6 @@ import com.google.refine.model.Project; import com.google.refine.model.Record; import com.google.refine.model.Row; import com.google.refine.model.changes.RowReorderChange; -import com.google.refine.operations.OperationRegistry; import com.google.refine.sorting.SortingConfig; import com.google.refine.sorting.SortingRecordVisitor; import com.google.refine.sorting.SortingRowVisitor; @@ -74,18 +70,6 @@ public class RowReorderOperation extends AbstractOperation { _mode = mode; _sorting = sorting; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("mode"); writer.value(Engine.modeToString(_mode)); - writer.key("sorting"); _sorting.write(writer, options); - writer.endObject(); - } @JsonProperty("mode") public Mode getMode() { diff --git a/main/src/com/google/refine/operations/row/RowStarOperation.java b/main/src/com/google/refine/operations/row/RowStarOperation.java index 5508449b1..d7be153b4 100644 --- a/main/src/com/google/refine/operations/row/RowStarOperation.java +++ b/main/src/com/google/refine/operations/row/RowStarOperation.java @@ -35,11 +35,8 @@ package com.google.refine.operations.row; import java.util.ArrayList; import java.util.List; -import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -55,7 +52,6 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.MassChange; import com.google.refine.model.changes.RowStarChange; import com.google.refine.operations.EngineDependentOperation; -import com.google.refine.operations.OperationRegistry; public class RowStarOperation extends EngineDependentOperation { final protected boolean _starred; @@ -74,18 +70,6 @@ public class RowStarOperation extends EngineDependentOperation { super(engineConfig); _starred = starred; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("starred"); writer.value(_starred); - writer.endObject(); - } @JsonProperty("starred") public boolean getStarred() { diff --git a/main/src/com/google/refine/preference/PreferenceStore.java b/main/src/com/google/refine/preference/PreferenceStore.java index 7358ad9d1..3e64a4a77 100644 --- a/main/src/com/google/refine/preference/PreferenceStore.java +++ b/main/src/com/google/refine/preference/PreferenceStore.java @@ -38,25 +38,22 @@ import java.lang.reflect.Method; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import java.util.Properties; import java.util.Set; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.RefineServlet; -public class PreferenceStore implements Jsonizable { +public class PreferenceStore { public static final String USER_METADATA_KEY = "userMetadata"; // use to populate "creator" filed in metadata. https://github.com/OpenRefine/OpenRefine/issues/1393 @@ -101,28 +98,6 @@ public class PreferenceStore implements Jsonizable { return _prefs.keySet(); } - @Override - public void write(JSONWriter writer, Properties options) throws JSONException { - writer.object(); - - writer.key("entries"); - writer.object(); - for (String k : _prefs.keySet()) { - writer.key(k); - - Object o = _prefs.get(k); - if (o instanceof Jsonizable) { - ((Jsonizable) o).write(writer, options); - } else { - writer.value(o); - } - } - writer.endObject(); - - writer.endObject(); - dirty = false; - } - /** * @return true if the preference store has unsaved changes */ diff --git a/main/src/com/google/refine/preference/TopList.java b/main/src/com/google/refine/preference/TopList.java index 846d579bd..79b9802f3 100644 --- a/main/src/com/google/refine/preference/TopList.java +++ b/main/src/com/google/refine/preference/TopList.java @@ -36,20 +36,17 @@ package com.google.refine.preference; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import java.util.Properties; import org.apache.commons.collections.list.UnmodifiableList; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; -public class TopList implements Jsonizable, Iterable { +public class TopList implements Iterable { @JsonProperty("top") final protected int _top; @@ -82,21 +79,6 @@ public class TopList implements Jsonizable, Iterable { public String getClassName() { return this.getClass().getName(); } - - @Override - public void write(JSONWriter writer, Properties options) throws JSONException { - writer.object(); - writer.key("class"); writer.value(getClassName()); - - writer.key("top"); writer.value(_top); - writer.key("list"); - writer.array(); - for (String element : _list) { - writer.value(element); - } - writer.endArray(); - writer.endObject(); - } static public TopList load(JSONObject obj) throws JSONException { int top = obj.has("top") && !obj.isNull("top") ? obj.getInt("top") : 10; diff --git a/main/src/com/google/refine/process/LongRunningProcess.java b/main/src/com/google/refine/process/LongRunningProcess.java index 1e18949f4..b8e12c669 100644 --- a/main/src/com/google/refine/process/LongRunningProcess.java +++ b/main/src/com/google/refine/process/LongRunningProcess.java @@ -33,11 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.process; -import java.util.Properties; - -import org.json.JSONException; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; @@ -67,19 +62,6 @@ abstract public class LongRunningProcess extends Process { } } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("id"); writer.value(hashCode()); - writer.key("description"); writer.value(_description); - writer.key("immediate"); writer.value(false); - writer.key("status"); writer.value(getStatus()); - writer.key("progress"); writer.value(_progress); - writer.endObject(); - } - @JsonProperty("status") public String getStatus() { return _thread == null ? "pending" : (_thread.isAlive() ? "running" : "done"); diff --git a/main/src/com/google/refine/process/Process.java b/main/src/com/google/refine/process/Process.java index 8b42bab71..21af244fa 100644 --- a/main/src/com/google/refine/process/Process.java +++ b/main/src/com/google/refine/process/Process.java @@ -36,10 +36,9 @@ package com.google.refine.process; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.history.HistoryEntry; -public abstract class Process implements Jsonizable { +public abstract class Process { @JsonProperty("immediate") abstract public boolean isImmediate(); diff --git a/main/src/com/google/refine/process/ProcessManager.java b/main/src/com/google/refine/process/ProcessManager.java index 6d22177fb..3f5a48283 100644 --- a/main/src/com/google/refine/process/ProcessManager.java +++ b/main/src/com/google/refine/process/ProcessManager.java @@ -36,22 +36,17 @@ package com.google.refine.process; import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.Properties; import java.util.stream.Collectors; -import org.json.JSONException; -import org.json.JSONWriter; - -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.history.HistoryEntry; import com.google.refine.history.HistoryProcess; -public class ProcessManager implements Jsonizable { +public class ProcessManager { @JsonProperty("processes") protected List _processes = Collections.synchronizedList(new LinkedList()); @JsonIgnore @@ -69,32 +64,6 @@ public class ProcessManager implements Jsonizable { } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("processes"); writer.array(); - synchronized (_processes) { - for (Process p : _processes) { - p.write(writer, options); - } - } - writer.endArray(); - - if (_latestExceptions != null) { - writer.key("exceptions"); writer.array(); - for (Exception e : _latestExceptions) { - writer.object(); - writer.key("message"); writer.value(e.getLocalizedMessage()); - writer.endObject(); - } - writer.endArray(); - } - - writer.endObject(); - } - @JsonProperty("exceptions") @JsonInclude(Include.NON_NULL) public List getJsonExceptions() { diff --git a/main/src/com/google/refine/process/QuickHistoryEntryProcess.java b/main/src/com/google/refine/process/QuickHistoryEntryProcess.java index 9d9c51726..7f16f68e4 100644 --- a/main/src/com/google/refine/process/QuickHistoryEntryProcess.java +++ b/main/src/com/google/refine/process/QuickHistoryEntryProcess.java @@ -33,11 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.process; -import java.util.Properties; - -import org.json.JSONException; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.history.HistoryEntry; @@ -85,18 +80,6 @@ abstract public class QuickHistoryEntryProcess extends Process { public void startPerforming(ProcessManager manager) { throw new RuntimeException("Not a long-running process"); } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("id"); writer.value(hashCode()); - writer.key("description"); writer.value(getDescription()); - writer.key("immediate"); writer.value(true); - writer.key("status"); writer.value(getStatus()); - writer.endObject(); - } @JsonProperty("status") public String getStatus() { diff --git a/main/src/com/google/refine/sorting/Criterion.java b/main/src/com/google/refine/sorting/Criterion.java index e19b69dd6..4cae65d14 100644 --- a/main/src/com/google/refine/sorting/Criterion.java +++ b/main/src/com/google/refine/sorting/Criterion.java @@ -33,22 +33,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.sorting; -import java.util.Properties; - import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.expr.ExpressionUtils; import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Record; import com.google.refine.model.Row; -abstract public class Criterion implements Jsonizable { +abstract public class Criterion { public String columnName; protected int cellIndex = -2; @@ -99,19 +95,6 @@ abstract public class Criterion implements Jsonizable { return c; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("valueType"); writer.value(getValueType()); - writer.key("reverse"); writer.value(getReverse()); - writer.key("column"); writer.value(getColumnName()); - writer.key("blankPosition"); writer.value(getBlankPosition()); - writer.key("errorPosition"); writer.value(getErrorPosition()); - writer.endObject(); - } - @JsonProperty("valueType") public abstract String getValueType(); diff --git a/main/src/com/google/refine/sorting/DateCriterion.java b/main/src/com/google/refine/sorting/DateCriterion.java index 161abb2f0..363888b4e 100644 --- a/main/src/com/google/refine/sorting/DateCriterion.java +++ b/main/src/com/google/refine/sorting/DateCriterion.java @@ -35,10 +35,6 @@ package com.google.refine.sorting; import java.time.Instant; import java.time.OffsetDateTime; -import java.util.Properties; - -import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.expr.ExpressionUtils; diff --git a/main/src/com/google/refine/sorting/SortingConfig.java b/main/src/com/google/refine/sorting/SortingConfig.java index cc96ee85e..a1c342d92 100644 --- a/main/src/com/google/refine/sorting/SortingConfig.java +++ b/main/src/com/google/refine/sorting/SortingConfig.java @@ -1,23 +1,18 @@ package com.google.refine.sorting; -import java.util.Properties; - import org.json.JSONArray; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; /** * Stores the configuration of a row/record sorting setup. * @author Antonin Delpeuch * */ -public final class SortingConfig implements Jsonizable { +public final class SortingConfig { protected Criterion[] _criteria; @@ -32,19 +27,6 @@ public final class SortingConfig implements Jsonizable { public Criterion[] getCriteria() { return _criteria; } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("criteria"); - writer.array(); - for (int i = 0; i != _criteria.length; i++) { - _criteria[i].write(writer, options); - } - writer.endArray(); - writer.endObject(); - } public static SortingConfig reconstruct(JSONObject obj) { Criterion[] criteria; diff --git a/main/src/com/google/refine/util/JSONUtilities.java b/main/src/com/google/refine/util/JSONUtilities.java index db88eeb79..925adcc1a 100644 --- a/main/src/com/google/refine/util/JSONUtilities.java +++ b/main/src/com/google/refine/util/JSONUtilities.java @@ -33,25 +33,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.util; -import java.io.StringWriter; -import java.io.Writer; import java.time.LocalDateTime; -import java.time.ZoneId; import java.time.OffsetDateTime; +import java.time.ZoneId; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Properties; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; -import com.google.refine.Jsonizable; public class JSONUtilities { static public JSONObject getObject(JSONObject obj, String key) { @@ -376,16 +372,4 @@ public class JSONUtilities { destArray.put(srcArray.get(i)); } } - - static public String serialize(Jsonizable obj, Properties options) { - Writer w = new StringWriter(); - JSONWriter jsonWriter = new JSONWriter(w); - obj.write(jsonWriter, options); - return w.toString(); - } - - static public String serialize(Jsonizable obj) { - Properties options = new Properties(); - return serialize(obj, options); - } } diff --git a/main/src/com/google/refine/util/ParsingUtilities.java b/main/src/com/google/refine/util/ParsingUtilities.java index e067a26fd..6b906ce17 100644 --- a/main/src/com/google/refine/util/ParsingUtilities.java +++ b/main/src/com/google/refine/util/ParsingUtilities.java @@ -61,6 +61,8 @@ import org.json.JSONTokener; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; @@ -69,13 +71,18 @@ import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; public class ParsingUtilities { - - public static final ObjectMapper mapper = new ObjectMapper(); + public static JsonFactory jsonFactory = new JsonFactory(); + static { + jsonFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); + } + public static final ObjectMapper mapper = new ObjectMapper(jsonFactory); static { SimpleModule module = new SimpleModule(); module.addSerializer(Double.class, new SerializationFilters.DoubleSerializer()); module.addSerializer(double.class, new SerializationFilters.DoubleSerializer()); module.addSerializer(OffsetDateTime.class, new SerializationFilters.DateSerializer()); + + mapper.registerModule(module); mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); diff --git a/main/src/com/google/refine/util/Pool.java b/main/src/com/google/refine/util/Pool.java index 941d01388..0ac44ab0e 100644 --- a/main/src/com/google/refine/util/Pool.java +++ b/main/src/com/google/refine/util/Pool.java @@ -44,13 +44,9 @@ import java.io.Writer; import java.util.Collection; import java.util.HashMap; import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.Jsonizable; import com.google.refine.RefineServlet; import com.google.refine.model.Recon; import com.google.refine.model.ReconCandidate; @@ -59,7 +55,8 @@ import com.google.refine.model.ReconCandidate; * A serializable pool of ReconCandidates indexed by ID. * */ -public class Pool implements Jsonizable { +public class Pool { + @JsonProperty("recons") final protected Map recons = new HashMap(); // This is only for backward compatibility while loading old project files @@ -104,23 +101,12 @@ public class Pool implements Jsonizable { public void save(Writer writer) throws IOException { writer.write(RefineServlet.VERSION); writer.write('\n'); - - Properties options = new Properties(); - options.setProperty("mode", "save"); - options.put("pool", this); Collection recons2 = recons.values(); writer.write("reconCount=" + recons2.size()); writer.write('\n'); for (Recon recon : recons2) { - JSONWriter jsonWriter = new JSONWriter(writer); - try { - recon.write(jsonWriter, options); - - writer.write('\n'); - } catch (JSONException e) { - e.printStackTrace(); - } + ParsingUtilities.saveWriter.writeValue(writer, recon); } } @@ -167,19 +153,4 @@ public class Pool implements Jsonizable { } } } - - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("recons"); - writer.object(); - for (Entry entry : recons.entrySet()) { - writer.key(entry.getKey().toString()); - entry.getValue().write(writer, options); - } - writer.endObject(); - writer.endObject(); - } } diff --git a/main/tests/server/src/com/google/refine/tests/model/CellTests.java b/main/tests/server/src/com/google/refine/tests/model/CellTests.java index cab82c55d..1083cb772 100644 --- a/main/tests/server/src/com/google/refine/tests/model/CellTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/CellTests.java @@ -36,11 +36,8 @@ public class CellTests { when(pool.getRecon("1533649346002675326")).thenReturn(recon); String json = "{\"v\":\"http://www.wikidata.org/entity/Q41522540\",\"r\":\"1533649346002675326\"}"; - Properties options = mock(Properties.class); - when(options.get("pool")).thenReturn(pool); Cell c = Cell.loadStreaming(json, pool); - TestUtils.isSerializedTo(c, json, options); - verify(pool, times(1)).pool(recon); + TestUtils.isSerializedTo(c, json); } @Test diff --git a/main/tests/server/src/com/google/refine/tests/model/RowTests.java b/main/tests/server/src/com/google/refine/tests/model/RowTests.java index 6d36f4838..5241be71e 100644 --- a/main/tests/server/src/com/google/refine/tests/model/RowTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/RowTests.java @@ -111,7 +111,8 @@ public class RowTests extends RefineTest { "{\"flagged\":false,\"starred\":false,\"cells\":[{\"v\":\"I'm not empty\"}]}"); } - @Test + // This way of serializing a row with indices is now deprecated, see GetRowsCommand. + @Test(expectedExceptions=IllegalArgumentException.class) public void saveRowWithRecordIndex() { Row row = new Row(5); row.setCell(0, new Cell("I'm not empty", null)); @@ -120,9 +121,6 @@ public class RowTests extends RefineTest { when(options.containsKey("recordIndex")).thenReturn(true); when(options.get("recordIndex")).thenReturn(1); row.save(writer, options); - TestUtils.assertEqualAsJson( - writer.getBuffer().toString(), - "{\"flagged\":false,\"starred\":false,\"cells\":[{\"v\":\"I'm not empty\"}],\"i\":0,\"j\":1}"); } @Test @@ -150,8 +148,7 @@ public class RowTests extends RefineTest { + " {\"v\":\"\"}" + "]}"; Row row = Row.load(json, pool); - when(options.get("pool")).thenReturn(pool); - TestUtils.isSerializedTo(row, json, options); + TestUtils.isSerializedTo(row, json); } @Test diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java index 528656da4..02df8cfb5 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java @@ -119,7 +119,7 @@ public class ExtendDataOperationTests extends RefineTest { super(obj, endpoint); } - public String formulateQueryStub(Set ids, DataExtensionConfig node) throws JSONException { + public String formulateQueryStub(Set ids, DataExtensionConfig node) throws IOException { StringWriter writer = new StringWriter(); super.formulateQuery(ids, node, writer); return writer.toString(); @@ -181,7 +181,7 @@ public class ExtendDataOperationTests extends RefineTest { } @Test - public void testFormulateQuery() { + public void testFormulateQuery() throws IOException { DataExtensionConfig config = DataExtensionConfig.reconstruct(new JSONObject(dataExtensionConfigJson)); Set ids = Collections.singleton("Q2"); String json = "{\"ids\":[\"Q2\"],\"properties\":[{\"id\":\"P571\"},{\"id\":\"P159\"},{\"id\":\"P625\"}]}"; diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsOperationTests.java index 4662cd016..76cf1e39e 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsOperationTests.java @@ -2,7 +2,9 @@ package com.google.refine.tests.operations.recon; import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; +import static org.mockito.Mockito.mock; +import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.recon.ReconJudgeSimilarCellsOperation; import com.google.refine.tests.RefineTest; @@ -24,6 +26,6 @@ public class ReconJudgeSimilarCellsOperationTests extends RefineTest { + "\"judgment\":\"matched\"," + "\"match\":{\"id\":\"Q7884717\",\"name\":\"Unicef Indonesia\",\"score\":71.42857142857143,\"types\":[\"Q43229\"]}," + "\"shareNewTopics\":false}"; - TestUtils.isSerializedTo(ReconJudgeSimilarCellsOperation.reconstruct(new JSONObject(json)), json); + TestUtils.isSerializedTo(ReconJudgeSimilarCellsOperation.reconstruct(mock(Project.class), new JSONObject(json)), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java index 413797e7f..79075a6fa 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java @@ -2,6 +2,7 @@ package com.google.refine.tests.operations.recon; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.mock; import java.util.Collections; import java.util.Properties; @@ -46,7 +47,7 @@ public class ReconJudgeSimilarCellsTests extends RefineTest { + "\"similarValue\":\"foo\"," + "\"judgment\":\"new\"," + "\"shareNewTopics\":true}"; - TestUtils.isSerializedTo(ReconJudgeSimilarCellsOperation.reconstruct(new JSONObject(json)), json); + TestUtils.isSerializedTo(ReconJudgeSimilarCellsOperation.reconstruct(mock(Project.class), new JSONObject(json)), json); } @Test diff --git a/main/tests/server/src/com/google/refine/tests/process/ProcessManagerTests.java b/main/tests/server/src/com/google/refine/tests/process/ProcessManagerTests.java index 26e5b8f47..7cd3d0a2d 100644 --- a/main/tests/server/src/com/google/refine/tests/process/ProcessManagerTests.java +++ b/main/tests/server/src/com/google/refine/tests/process/ProcessManagerTests.java @@ -6,7 +6,7 @@ import org.testng.annotations.Test; import com.google.refine.process.Process; import com.google.refine.process.ProcessManager; import com.google.refine.tests.util.TestUtils; -import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class ProcessManagerTests { @@ -25,7 +25,7 @@ public class ProcessManagerTests { processManager.queueProcess(process1); processManager.queueProcess(process2); processManager.onFailedProcess(process1, new IllegalArgumentException("unexpected error")); - String processJson = JSONUtilities.serialize(process2); + String processJson = ParsingUtilities.defaultWriter.writeValueAsString(process2); TestUtils.isSerializedTo(processManager, "{" + "\"processes\":["+processJson+"],\n" + "\"exceptions\":[{\"message\":\"unexpected error\"}]" diff --git a/main/tests/server/src/com/google/refine/tests/util/TestUtils.java b/main/tests/server/src/com/google/refine/tests/util/TestUtils.java index 68f51e3fd..f35f20184 100644 --- a/main/tests/server/src/com/google/refine/tests/util/TestUtils.java +++ b/main/tests/server/src/com/google/refine/tests/util/TestUtils.java @@ -8,7 +8,6 @@ import java.io.IOException; import java.io.LineNumberReader; import java.io.StringReader; import java.io.StringWriter; -import java.util.Properties; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonProcessingException; @@ -19,8 +18,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.SerializationFeature; -import com.google.refine.Jsonizable; -import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; @@ -54,6 +51,9 @@ public class TestUtils { try { JsonNode jsonA = mapper.readValue(expected, JsonNode.class); JsonNode jsonB = mapper.readValue(actual, JsonNode.class); + if (!jsonA.equals(jsonB)) { + jsonDiff(expected, actual); + } assertEquals(jsonA, jsonB); } catch(Exception e) { fail("\""+expected+"\" and \""+actual+"\" are not equal as JSON strings."); @@ -74,24 +74,12 @@ public class TestUtils { * Checks that a serializable object is serialized to the target JSON string. * @throws IOException */ - public static void isSerializedTo(Jsonizable o, String targetJson, Properties options) { - String orgJson = JSONUtilities.serialize(o, options); - if(!equalAsJson(targetJson, orgJson)) { - System.out.println("org.json, "+o.getClass().getName()); - try { - jsonDiff(targetJson, orgJson); - } catch (JsonParseException | JsonMappingException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - assertEqualAsJson(targetJson, orgJson); - + public static void isSerializedTo(Object o, String targetJson, boolean saveMode) { + // also check Jackson serialization try { - String saveMode = options.getProperty("mode"); ObjectWriter writer = null; - if("save".equals(saveMode)) { + if(saveMode) { writer = ParsingUtilities.saveWriter; } else { writer = ParsingUtilities.defaultWriter; @@ -111,22 +99,8 @@ public class TestUtils { /** * Checks that a serializable object is serialized to the target JSON string. */ - public static void isSerializedTo(Jsonizable o, String targetJson) { - isSerializedTo(o, targetJson, new Properties()); - } - - /** - * Checks that a serializable object is serialized to the target JSON string. - * This specifies the "save mode" for objects that are stored differently depending on - * whether they are written to disk or sent over the network. - */ - public static void isSerializedTo(Jsonizable o, String targetJson, boolean saveMode) { - Properties options = new Properties(); - if(saveMode) { - options.setProperty("mode", "save"); - options.put("mode", "save"); - } - isSerializedTo(o, targetJson, options); + public static void isSerializedTo(Object o, String targetJson) { + isSerializedTo(o, targetJson, false); } public static void jsonDiff(String a, String b) throws JsonParseException, JsonMappingException { From fec28b99bc113ba2fd8ceb9d9b4e9aa5f479fbf8 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Thu, 4 Oct 2018 17:13:43 +0100 Subject: [PATCH 027/164] Various serialization fixes --- main/src/com/google/refine/browsing/Engine.java | 5 ++++- .../com/google/refine/browsing/facets/ListFacet.java | 6 ++++-- .../google/refine/commands/GetPreferenceCommand.java | 11 ++++++++--- .../google/refine/commands/HttpHeadersSupport.java | 6 ++++++ main/src/com/google/refine/expr/MetaParser.java | 6 ++++++ .../src/com/google/refine/importing/ImportingJob.java | 8 ++++++++ .../refine/operations/recon/ReconOperation.java | 8 ++++---- .../com/google/refine/preference/PreferenceStore.java | 2 +- main/src/com/google/refine/util/Pool.java | 1 + .../refine/tests/browsing/facets/ListFacetTests.java | 2 +- 10 files changed, 43 insertions(+), 12 deletions(-) diff --git a/main/src/com/google/refine/browsing/Engine.java b/main/src/com/google/refine/browsing/Engine.java index 4feb97ec8..204e8a11e 100644 --- a/main/src/com/google/refine/browsing/Engine.java +++ b/main/src/com/google/refine/browsing/Engine.java @@ -41,6 +41,7 @@ import java.util.stream.Collectors; import org.json.JSONException; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; @@ -69,8 +70,9 @@ public class Engine { public final static String MODE_RECORD_BASED = "record-based"; protected Project _project; + @JsonProperty("facets") protected List _facets = new LinkedList(); - @JsonValue + @JsonIgnore protected EngineConfig _config = new EngineConfig(Collections.emptyList(), Mode.RowBased); static public String modeToString(Mode mode) { @@ -84,6 +86,7 @@ public class Engine { _project = project; } + @JsonProperty("engine-mode") public Mode getMode() { return _config.getMode(); } diff --git a/main/src/com/google/refine/browsing/facets/ListFacet.java b/main/src/com/google/refine/browsing/facets/ListFacet.java index 07ecf61f0..521af7858 100644 --- a/main/src/com/google/refine/browsing/facets/ListFacet.java +++ b/main/src/com/google/refine/browsing/facets/ListFacet.java @@ -231,16 +231,18 @@ public class ListFacet implements Facet { @JsonProperty("choiceCount") @JsonInclude(Include.NON_NULL) public Integer getChoiceCount() { - if (_errorMessage == null && _choices.size() > getLimit()) + if (_errorMessage == null && _choices.size() > getLimit()) { return _choices.size(); + } return null; } @JsonProperty("choices") @JsonInclude(Include.NON_NULL) public List getChoices() { - if (getError() == null) + if (getError() == null) { return _choices; + } return null; } diff --git a/main/src/com/google/refine/commands/GetPreferenceCommand.java b/main/src/com/google/refine/commands/GetPreferenceCommand.java index cd1681b99..2d133c041 100644 --- a/main/src/com/google/refine/commands/GetPreferenceCommand.java +++ b/main/src/com/google/refine/commands/GetPreferenceCommand.java @@ -43,14 +43,19 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.ProjectManager; import com.google.refine.preference.PreferenceStore; +import com.google.refine.preference.TopList; public class GetPreferenceCommand extends Command { protected static class PreferenceValue { @JsonProperty("value") - protected Object pref; + protected Object value; - protected PreferenceValue(Object o) { - pref = o; + protected PreferenceValue(Object pref) { + if (pref == null || pref instanceof String || pref instanceof Number || pref instanceof Boolean || pref instanceof TopList) { + value = pref; + } else { + value = pref.toString(); + } } } diff --git a/main/src/com/google/refine/commands/HttpHeadersSupport.java b/main/src/com/google/refine/commands/HttpHeadersSupport.java index 6bac9db5b..e7cd88b3e 100644 --- a/main/src/com/google/refine/commands/HttpHeadersSupport.java +++ b/main/src/com/google/refine/commands/HttpHeadersSupport.java @@ -37,6 +37,9 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.RefineServlet; abstract public class HttpHeadersSupport { @@ -44,8 +47,11 @@ abstract public class HttpHeadersSupport { static final protected Map s_headers = new HashMap(); static public class HttpHeaderInfo { + @JsonIgnore final public String name; + @JsonProperty("header") final public String header; + @JsonProperty("defaultValue") final public String defaultValue; HttpHeaderInfo(String header, String defaultValue) { diff --git a/main/src/com/google/refine/expr/MetaParser.java b/main/src/com/google/refine/expr/MetaParser.java index 274b8e0f8..03ec48949 100644 --- a/main/src/com/google/refine/expr/MetaParser.java +++ b/main/src/com/google/refine/expr/MetaParser.java @@ -39,6 +39,9 @@ import java.util.Map; import java.util.Properties; import java.util.Set; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.grel.Parser; import clojure.lang.IFn; @@ -47,8 +50,11 @@ import clojure.lang.RT; abstract public class MetaParser { static public class LanguageInfo { + @JsonProperty("name") final public String name; + @JsonIgnore final public LanguageSpecificParser parser; + @JsonProperty("defaultExpression") final public String defaultExpression; LanguageInfo(String name, LanguageSpecificParser parser, String defaultExpression) { diff --git a/main/src/com/google/refine/importing/ImportingJob.java b/main/src/com/google/refine/importing/ImportingJob.java index 4f52f6c3b..27b0c65e9 100644 --- a/main/src/com/google/refine/importing/ImportingJob.java +++ b/main/src/com/google/refine/importing/ImportingJob.java @@ -42,6 +42,9 @@ import org.apache.commons.io.FileUtils; import org.json.JSONArray; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonRawValue; + import com.google.refine.ProjectManager; import com.google.refine.model.Project; import com.google.refine.model.metadata.ProjectMetadata; @@ -77,6 +80,11 @@ public class ImportingJob { dir.mkdirs(); } + @JsonProperty("config") + @JsonRawValue + public String getJsonConfig() { + return config.toString(); + } public JSONObject getOrCreateDefaultConfig() { return config; diff --git a/main/src/com/google/refine/operations/recon/ReconOperation.java b/main/src/com/google/refine/operations/recon/ReconOperation.java index 34593b77c..976b1acb3 100644 --- a/main/src/com/google/refine/operations/recon/ReconOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconOperation.java @@ -149,9 +149,9 @@ public class ReconOperation extends EngineDependentOperation { "{\n" + " \"action\" : \"createFacet\",\n" + " \"facetConfig\" : {\n" + - " \"columnName\" : \"researcher\",\n" + + " \"columnName\" : \"" + _columnName + "\",\n" + " \"expression\" : \"forNonBlank(cell.recon.judgment, v, v, if(isNonBlank(value), \\\"(unreconciled)\\\", \\\"(blank)\\\"))\",\n" + - " \"name\" : \"researcher: judgment\"\n" + + " \"name\" : \"" + _columnName + ": judgment\"\n" + " },\n" + " \"facetOptions\" : {\n" + " \"scroll\" : false\n" + @@ -162,10 +162,10 @@ public class ReconOperation extends EngineDependentOperation { "{\n" + " \"action\" : \"createFacet\",\n" + " \"facetConfig\" : {\n" + - " \"columnName\" : \"researcher\",\n" + + " \"columnName\" : \"" + _columnName + "\",\n" + " \"expression\" : \"cell.recon.best.score\",\n" + " \"mode\" : \"range\",\n" + - " \"name\" : \"researcher: best candidate's score\"\n" + + " \"name\" : \"" + _columnName + ": best candidate's score\"\n" + " },\n" + " \"facetType\" : \"range\"\n" + "}"; diff --git a/main/src/com/google/refine/preference/PreferenceStore.java b/main/src/com/google/refine/preference/PreferenceStore.java index 3e64a4a77..25a27fba2 100644 --- a/main/src/com/google/refine/preference/PreferenceStore.java +++ b/main/src/com/google/refine/preference/PreferenceStore.java @@ -79,7 +79,7 @@ public class PreferenceStore { private Object wrapJSONArray(Object value) { ObjectMapper mapper = new ObjectMapper(); - if(value != null && value instanceof JSONArray) { + if(value != null && (value instanceof JSONArray || value instanceof JSONObject)) { try { return mapper.readValue(value.toString(), JsonNode.class); } catch (IOException e) { diff --git a/main/src/com/google/refine/util/Pool.java b/main/src/com/google/refine/util/Pool.java index 0ac44ab0e..ddb9ea39e 100644 --- a/main/src/com/google/refine/util/Pool.java +++ b/main/src/com/google/refine/util/Pool.java @@ -107,6 +107,7 @@ public class Pool { for (Recon recon : recons2) { ParsingUtilities.saveWriter.writeValue(writer, recon); + writer.write('\n'); } } diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java index 6a18c1782..92a77bf63 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java @@ -33,7 +33,7 @@ public class ListFacetTests extends RefineTest { + "\"expression\":\"value+\\\"bar\\\"\"," + "\"columnName\":\"Column A\"," + "\"invert\":false," - + "\"error\":\"No column named Column A\"}\" are not equal as JSON strings.\n" + + + "\"error\":\"No column named Column A\"" + "}"; private static String jsonFacet = "{" From f6fc47a8f9fbd773f7623c86c48ba1e5e035c71e Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Thu, 4 Oct 2018 17:54:22 +0100 Subject: [PATCH 028/164] Fix serialization of StandardReconConfig with no type --- .../google/refine/model/recon/StandardReconConfig.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/main/src/com/google/refine/model/recon/StandardReconConfig.java b/main/src/com/google/refine/model/recon/StandardReconConfig.java index 068bd4b29..b6156d29a 100644 --- a/main/src/com/google/refine/model/recon/StandardReconConfig.java +++ b/main/src/com/google/refine/model/recon/StandardReconConfig.java @@ -53,6 +53,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.expr.ExpressionUtils; @@ -203,9 +205,12 @@ public class StandardReconConfig extends ReconConfig { } @JsonProperty("type") + @JsonInclude(Include.NON_NULL) public ReconType getReconType() { - ReconType t = new ReconType(typeID, typeName); - return t; + if (typeID != null) { + return new ReconType(typeID, typeName); + } + return null; } @Override From bd5a8f9ece0624001cbccc712da47ac7fa364532 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Thu, 4 Oct 2018 18:04:16 +0100 Subject: [PATCH 029/164] Fix serialization issues in Wikidata extension --- .../operations/PerformWikibaseEditsOperation.java | 2 +- .../schema/entityvalues/PrefetchedEntityIdValue.java | 4 ++++ .../wikidata/schema/entityvalues/ReconEntityIdValue.java | 8 ++++++++ .../schema/entityvalues/SuggestedEntityIdValue.java | 7 +++++++ .../wikidata/testing/JacksonSerializationTest.java | 6 ++++-- 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java b/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java index 86f0129e1..c92433489 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java @@ -88,7 +88,7 @@ public class PerformWikibaseEditsOperation extends EngineDependentOperation { @Override protected String getBriefDescription(Project project) { - return "Peform edits on Wikidata"; + return "Peform Wikibase edits"; } @Override diff --git a/extensions/wikidata/src/org/openrefine/wikidata/schema/entityvalues/PrefetchedEntityIdValue.java b/extensions/wikidata/src/org/openrefine/wikidata/schema/entityvalues/PrefetchedEntityIdValue.java index ee98c58ab..abe75df96 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/schema/entityvalues/PrefetchedEntityIdValue.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/schema/entityvalues/PrefetchedEntityIdValue.java @@ -27,6 +27,8 @@ import java.util.List; import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * An entity id value that also comes with a label and possibly types. * @@ -47,6 +49,7 @@ public interface PrefetchedEntityIdValue extends EntityIdValue { * * @return the preferred label of the entity */ + @JsonProperty("label") public String getLabel(); /** @@ -56,5 +59,6 @@ public interface PrefetchedEntityIdValue extends EntityIdValue { * * Empty lists should be returned for */ + @JsonProperty("types") public List getTypes(); } diff --git a/extensions/wikidata/src/org/openrefine/wikidata/schema/entityvalues/ReconEntityIdValue.java b/extensions/wikidata/src/org/openrefine/wikidata/schema/entityvalues/ReconEntityIdValue.java index f55bc3c8c..56703e9ed 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/schema/entityvalues/ReconEntityIdValue.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/schema/entityvalues/ReconEntityIdValue.java @@ -33,6 +33,7 @@ import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue; import org.wikidata.wdtk.datamodel.interfaces.ValueVisitor; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.model.Recon; @@ -72,6 +73,7 @@ public abstract class ReconEntityIdValue implements PrefetchedEntityIdValue { return !isMatched(); } + @JsonProperty("label") public String getLabel() { if (isMatched()) { return _recon.match.name; @@ -80,6 +82,7 @@ public abstract class ReconEntityIdValue implements PrefetchedEntityIdValue { } } + @JsonProperty("types") public List getTypes() { if (isMatched()) { return Arrays.asList(_recon.match.types); @@ -89,6 +92,7 @@ public abstract class ReconEntityIdValue implements PrefetchedEntityIdValue { } @Override + @JsonProperty("entityType") public abstract String getEntityType(); /** @@ -96,6 +100,7 @@ public abstract class ReconEntityIdValue implements PrefetchedEntityIdValue { * * @return the reconciliation id of the reconciled cell */ + @JsonProperty("reconInternalId") public long getReconInternalId() { return getRecon().id; } @@ -114,6 +119,7 @@ public abstract class ReconEntityIdValue implements PrefetchedEntityIdValue { * Returns the id of the reconciled item */ @Override + @JsonProperty("id") public String getId() { if (isMatched()) { return _recon.match.id; @@ -126,6 +132,7 @@ public abstract class ReconEntityIdValue implements PrefetchedEntityIdValue { } @Override + @JsonProperty("siteIri") public String getSiteIri() { if (isMatched()) { return _recon.identifierSpace; @@ -135,6 +142,7 @@ public abstract class ReconEntityIdValue implements PrefetchedEntityIdValue { } @Override + @JsonProperty("iri") public String getIri() { return getSiteIri() + getId(); } diff --git a/extensions/wikidata/src/org/openrefine/wikidata/schema/entityvalues/SuggestedEntityIdValue.java b/extensions/wikidata/src/org/openrefine/wikidata/schema/entityvalues/SuggestedEntityIdValue.java index d2b97edea..9898ec3c1 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/schema/entityvalues/SuggestedEntityIdValue.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/schema/entityvalues/SuggestedEntityIdValue.java @@ -30,6 +30,8 @@ import org.wikidata.wdtk.datamodel.helpers.Hash; import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue; import org.wikidata.wdtk.datamodel.interfaces.ValueVisitor; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * An EntityIdValue that we have obtained from a suggest widget in the schema * alignment dialog. @@ -50,26 +52,31 @@ public abstract class SuggestedEntityIdValue implements PrefetchedEntityIdValue } @Override + @JsonProperty("id") public String getId() { return _id; } @Override + @JsonProperty("siteIri") public String getSiteIri() { return _siteIRI; } @Override + @JsonProperty("label") public String getLabel() { return _label; } @Override + @JsonProperty("types") public List getTypes() { return new ArrayList<>(); } @Override + @JsonProperty("iri") public String getIri() { return getSiteIri() + getId(); } diff --git a/extensions/wikidata/tests/src/org/openrefine/wikidata/testing/JacksonSerializationTest.java b/extensions/wikidata/tests/src/org/openrefine/wikidata/testing/JacksonSerializationTest.java index 9f608547a..ab61ee7cc 100644 --- a/extensions/wikidata/tests/src/org/openrefine/wikidata/testing/JacksonSerializationTest.java +++ b/extensions/wikidata/tests/src/org/openrefine/wikidata/testing/JacksonSerializationTest.java @@ -33,15 +33,17 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.refine.util.ParsingUtilities; + public class JacksonSerializationTest { - private static ObjectMapper mapper = new ObjectMapper(); + private static ObjectMapper mapper = ParsingUtilities.mapper; public static void testSerialize(Object pojo, String expectedJson) { // Test that the pojo is correctly serialized try { - String actualJson = mapper.writeValueAsString(pojo); + String actualJson = ParsingUtilities.defaultWriter.writeValueAsString(pojo); assertJsonEquals(expectedJson, actualJson); } catch (JsonProcessingException e) { e.printStackTrace(); From c7c5fd4120815e9672522cf84548da8ade1c8e34 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Thu, 4 Oct 2018 18:36:49 +0100 Subject: [PATCH 030/164] Reorganize imports --- .../com/google/refine/browsing/Engine.java | 1 - .../clustering/binning/BinningClusterer.java | 3 -- .../commands/auth/AuthorizeCommand.java | 6 +-- .../cell/SplitMultiValueCellsCommand.java | 2 +- .../recon/ReconClearOneCellCommand.java | 3 -- .../recon/ReconJudgeOneCellCommand.java | 3 -- .../google/refine/exporters/CsvExporter.java | 4 +- .../CustomizableTabularExporterUtilities.java | 2 - .../exporters/sql/SqlInsertBuilder.java | 1 - .../refine/expr/functions/date/Now.java | 3 -- .../refine/expr/functions/strings/Trim.java | 1 + .../refine/grel/ast/FieldAccessorExpr.java | 1 - .../google/refine/grel/controls/Filter.java | 1 - .../refine/grel/controls/ForEachIndex.java | 1 - .../refine/grel/controls/ForNonBlank.java | 3 -- .../google/refine/grel/controls/ForRange.java | 3 -- .../com/google/refine/grel/controls/If.java | 3 -- .../refine/importers/ExcelImporter.java | 2 +- .../google/refine/importers/JsonImporter.java | 9 ++-- .../google/refine/importers/MarcImporter.java | 1 - .../google/refine/importers/OdsImporter.java | 2 +- .../importers/SeparatorBasedImporter.java | 6 +-- .../refine/importers/WikitextImporter.java | 53 +++++++++---------- .../google/refine/importing/UrlRewriter.java | 2 + .../model/changes/DataExtensionChange.java | 10 ++-- .../refine/model/changes/MassChange.java | 4 +- .../refine/model/changes/MassReconChange.java | 3 -- .../model/metadata/ProjectMetadata.java | 10 +--- .../com/google/refine/oauth/Credentials.java | 4 +- 29 files changed, 52 insertions(+), 95 deletions(-) diff --git a/main/src/com/google/refine/browsing/Engine.java b/main/src/com/google/refine/browsing/Engine.java index 204e8a11e..6ff493b1c 100644 --- a/main/src/com/google/refine/browsing/Engine.java +++ b/main/src/com/google/refine/browsing/Engine.java @@ -43,7 +43,6 @@ import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonValue; import com.google.refine.browsing.facets.Facet; import com.google.refine.browsing.util.ConjunctiveFilteredRecords; diff --git a/main/src/com/google/refine/clustering/binning/BinningClusterer.java b/main/src/com/google/refine/clustering/binning/BinningClusterer.java index 589f610ca..b09cd6dcd 100644 --- a/main/src/com/google/refine/clustering/binning/BinningClusterer.java +++ b/main/src/com/google/refine/clustering/binning/BinningClusterer.java @@ -41,13 +41,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Properties; import java.util.TreeMap; import java.util.stream.Collectors; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/main/src/com/google/refine/commands/auth/AuthorizeCommand.java b/main/src/com/google/refine/commands/auth/AuthorizeCommand.java index 57ecb3f56..1e6f44896 100644 --- a/main/src/com/google/refine/commands/auth/AuthorizeCommand.java +++ b/main/src/com/google/refine/commands/auth/AuthorizeCommand.java @@ -42,14 +42,14 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import oauth.signpost.OAuthConsumer; -import oauth.signpost.OAuthProvider; - import com.google.refine.commands.Command; import com.google.refine.oauth.Credentials; import com.google.refine.oauth.OAuthUtilities; import com.google.refine.oauth.Provider; +import oauth.signpost.OAuthConsumer; +import oauth.signpost.OAuthProvider; + public class AuthorizeCommand extends Command { private static final String OAUTH_VERIFIER_PARAM = "oauth_verifier"; diff --git a/main/src/com/google/refine/commands/cell/SplitMultiValueCellsCommand.java b/main/src/com/google/refine/commands/cell/SplitMultiValueCellsCommand.java index 355fc1406..d762bd0c3 100644 --- a/main/src/com/google/refine/commands/cell/SplitMultiValueCellsCommand.java +++ b/main/src/com/google/refine/commands/cell/SplitMultiValueCellsCommand.java @@ -46,8 +46,8 @@ import com.google.refine.commands.Command; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.operations.cell.MultiValuedCellSplitOperation; -import com.google.refine.util.ParsingUtilities; import com.google.refine.process.Process; +import com.google.refine.util.ParsingUtilities; public class SplitMultiValueCellsCommand extends Command { @Override diff --git a/main/src/com/google/refine/commands/recon/ReconClearOneCellCommand.java b/main/src/com/google/refine/commands/recon/ReconClearOneCellCommand.java index 39682064e..128c4dbad 100644 --- a/main/src/com/google/refine/commands/recon/ReconClearOneCellCommand.java +++ b/main/src/com/google/refine/commands/recon/ReconClearOneCellCommand.java @@ -34,14 +34,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.commands.recon; import java.io.IOException; -import java.util.Properties; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONWriter; - import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.commands.Command; diff --git a/main/src/com/google/refine/commands/recon/ReconJudgeOneCellCommand.java b/main/src/com/google/refine/commands/recon/ReconJudgeOneCellCommand.java index aceaf4e57..778ec2cd4 100644 --- a/main/src/com/google/refine/commands/recon/ReconJudgeOneCellCommand.java +++ b/main/src/com/google/refine/commands/recon/ReconJudgeOneCellCommand.java @@ -34,14 +34,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.commands.recon; import java.io.IOException; -import java.util.Properties; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONWriter; - import com.google.refine.commands.Command; import com.google.refine.expr.ExpressionUtils; import com.google.refine.history.Change; diff --git a/main/src/com/google/refine/exporters/CsvExporter.java b/main/src/com/google/refine/exporters/CsvExporter.java index 50c717e11..55fa25aff 100644 --- a/main/src/com/google/refine/exporters/CsvExporter.java +++ b/main/src/com/google/refine/exporters/CsvExporter.java @@ -43,13 +43,13 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import au.com.bytecode.opencsv.CSVWriter; - import com.google.refine.browsing.Engine; import com.google.refine.model.Project; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; +import au.com.bytecode.opencsv.CSVWriter; + public class CsvExporter implements WriterExporter{ final static Logger logger = LoggerFactory.getLogger("CsvExporter"); diff --git a/main/src/com/google/refine/exporters/CustomizableTabularExporterUtilities.java b/main/src/com/google/refine/exporters/CustomizableTabularExporterUtilities.java index eb19a68e7..00c203ad6 100644 --- a/main/src/com/google/refine/exporters/CustomizableTabularExporterUtilities.java +++ b/main/src/com/google/refine/exporters/CustomizableTabularExporterUtilities.java @@ -33,8 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.exporters; -import java.net.MalformedURLException; -import java.net.URL; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.time.OffsetDateTime; diff --git a/main/src/com/google/refine/exporters/sql/SqlInsertBuilder.java b/main/src/com/google/refine/exporters/sql/SqlInsertBuilder.java index 1c7efe69f..2abedf0f5 100755 --- a/main/src/com/google/refine/exporters/sql/SqlInsertBuilder.java +++ b/main/src/com/google/refine/exporters/sql/SqlInsertBuilder.java @@ -35,7 +35,6 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.json.JSONArray; import org.json.JSONObject; diff --git a/main/src/com/google/refine/expr/functions/date/Now.java b/main/src/com/google/refine/expr/functions/date/Now.java index ba0d88c63..b72d18b02 100644 --- a/main/src/com/google/refine/expr/functions/date/Now.java +++ b/main/src/com/google/refine/expr/functions/date/Now.java @@ -37,9 +37,6 @@ import java.time.OffsetDateTime; import java.time.ZoneId; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.grel.Function; public class Now implements Function { diff --git a/main/src/com/google/refine/expr/functions/strings/Trim.java b/main/src/com/google/refine/expr/functions/strings/Trim.java index 6d75a74ca..68e6efd10 100644 --- a/main/src/com/google/refine/expr/functions/strings/Trim.java +++ b/main/src/com/google/refine/expr/functions/strings/Trim.java @@ -36,6 +36,7 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; import com.google.common.base.CharMatcher; + import com.google.refine.expr.EvalError; import com.google.refine.grel.Function; diff --git a/main/src/com/google/refine/grel/ast/FieldAccessorExpr.java b/main/src/com/google/refine/grel/ast/FieldAccessorExpr.java index 13baf2021..9677106ea 100644 --- a/main/src/com/google/refine/grel/ast/FieldAccessorExpr.java +++ b/main/src/com/google/refine/grel/ast/FieldAccessorExpr.java @@ -38,7 +38,6 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONObject; -import com.google.refine.expr.EvalError; import com.google.refine.expr.Evaluable; import com.google.refine.expr.ExpressionUtils; import com.google.refine.expr.HasFields; diff --git a/main/src/com/google/refine/grel/controls/Filter.java b/main/src/com/google/refine/grel/controls/Filter.java index ebce67b6f..a2bb4000d 100644 --- a/main/src/com/google/refine/grel/controls/Filter.java +++ b/main/src/com/google/refine/grel/controls/Filter.java @@ -40,7 +40,6 @@ import java.util.Properties; import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.expr.Evaluable; diff --git a/main/src/com/google/refine/grel/controls/ForEachIndex.java b/main/src/com/google/refine/grel/controls/ForEachIndex.java index c673d4916..5535a19f6 100644 --- a/main/src/com/google/refine/grel/controls/ForEachIndex.java +++ b/main/src/com/google/refine/grel/controls/ForEachIndex.java @@ -39,7 +39,6 @@ import java.util.Properties; import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONWriter; import com.google.refine.expr.EvalError; import com.google.refine.expr.Evaluable; diff --git a/main/src/com/google/refine/grel/controls/ForNonBlank.java b/main/src/com/google/refine/grel/controls/ForNonBlank.java index 15f0da19b..640a2e889 100644 --- a/main/src/com/google/refine/grel/controls/ForNonBlank.java +++ b/main/src/com/google/refine/grel/controls/ForNonBlank.java @@ -35,9 +35,6 @@ package com.google.refine.grel.controls; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.Evaluable; import com.google.refine.expr.ExpressionUtils; import com.google.refine.grel.Control; diff --git a/main/src/com/google/refine/grel/controls/ForRange.java b/main/src/com/google/refine/grel/controls/ForRange.java index 61e181b64..d69c37d1e 100644 --- a/main/src/com/google/refine/grel/controls/ForRange.java +++ b/main/src/com/google/refine/grel/controls/ForRange.java @@ -37,9 +37,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.EvalError; import com.google.refine.expr.Evaluable; import com.google.refine.expr.ExpressionUtils; diff --git a/main/src/com/google/refine/grel/controls/If.java b/main/src/com/google/refine/grel/controls/If.java index d4d824b93..f863d8d9f 100644 --- a/main/src/com/google/refine/grel/controls/If.java +++ b/main/src/com/google/refine/grel/controls/If.java @@ -35,9 +35,6 @@ package com.google.refine.grel.controls; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.expr.Evaluable; import com.google.refine.expr.ExpressionUtils; import com.google.refine.grel.Control; diff --git a/main/src/com/google/refine/importers/ExcelImporter.java b/main/src/com/google/refine/importers/ExcelImporter.java index f4ee09048..78d912084 100644 --- a/main/src/com/google/refine/importers/ExcelImporter.java +++ b/main/src/com/google/refine/importers/ExcelImporter.java @@ -66,8 +66,8 @@ import com.google.refine.model.Cell; import com.google.refine.model.Project; import com.google.refine.model.Recon; import com.google.refine.model.Recon.Judgment; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.model.ReconCandidate; +import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; public class ExcelImporter extends TabularImportingParserBase { diff --git a/main/src/com/google/refine/importers/JsonImporter.java b/main/src/com/google/refine/importers/JsonImporter.java index 2a0a9a74c..4c7661549 100644 --- a/main/src/com/google/refine/importers/JsonImporter.java +++ b/main/src/com/google/refine/importers/JsonImporter.java @@ -39,15 +39,16 @@ import java.io.InputStream; import java.io.Serializable; import java.util.List; +import org.json.JSONArray; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonParser.NumberType; import com.fasterxml.jackson.core.JsonToken; -import org.json.JSONArray; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.google.refine.importers.tree.ImportColumnGroup; import com.google.refine.importers.tree.TreeImportingParserBase; diff --git a/main/src/com/google/refine/importers/MarcImporter.java b/main/src/com/google/refine/importers/MarcImporter.java index 5d561483e..4c1c35717 100644 --- a/main/src/com/google/refine/importers/MarcImporter.java +++ b/main/src/com/google/refine/importers/MarcImporter.java @@ -41,7 +41,6 @@ import java.io.InputStream; import java.io.OutputStream; import org.json.JSONObject; -import org.marc4j.MarcException; import org.marc4j.MarcPermissiveStreamReader; import org.marc4j.MarcWriter; import org.marc4j.MarcXmlWriter; diff --git a/main/src/com/google/refine/importers/OdsImporter.java b/main/src/com/google/refine/importers/OdsImporter.java index f35ff2cd3..a03f3ff66 100644 --- a/main/src/com/google/refine/importers/OdsImporter.java +++ b/main/src/com/google/refine/importers/OdsImporter.java @@ -61,8 +61,8 @@ import com.google.refine.model.Cell; import com.google.refine.model.Project; import com.google.refine.model.Recon; import com.google.refine.model.Recon.Judgment; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.model.ReconCandidate; +import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; diff --git a/main/src/com/google/refine/importers/SeparatorBasedImporter.java b/main/src/com/google/refine/importers/SeparatorBasedImporter.java index 2c483019e..80920aaae 100644 --- a/main/src/com/google/refine/importers/SeparatorBasedImporter.java +++ b/main/src/com/google/refine/importers/SeparatorBasedImporter.java @@ -50,18 +50,16 @@ import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringEscapeUtils; -import org.apache.commons.lang3.StringUtils; - import org.json.JSONObject; -import au.com.bytecode.opencsv.CSVParser; - import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Project; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; +import au.com.bytecode.opencsv.CSVParser; + public class SeparatorBasedImporter extends TabularImportingParserBase { public SeparatorBasedImporter() { super(false); diff --git a/main/src/com/google/refine/importers/WikitextImporter.java b/main/src/com/google/refine/importers/WikitextImporter.java index 2fbb6ad23..8bc509759 100644 --- a/main/src/com/google/refine/importers/WikitextImporter.java +++ b/main/src/com/google/refine/importers/WikitextImporter.java @@ -10,52 +10,48 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.json.JSONObject; -import com.google.common.io.CharStreams; -import de.fau.cs.osr.ptk.common.AstVisitor; - import org.sweble.wikitext.parser.ParserConfig; -import org.sweble.wikitext.parser.utils.SimpleParserConfig; +import org.sweble.wikitext.parser.WikitextEncodingValidator; import org.sweble.wikitext.parser.WikitextParser; +import org.sweble.wikitext.parser.WikitextPreprocessor; +import org.sweble.wikitext.parser.encval.ValidatedWikitext; +import org.sweble.wikitext.parser.nodes.WtBody; import org.sweble.wikitext.parser.nodes.WtBold; +import org.sweble.wikitext.parser.nodes.WtExternalLink; +import org.sweble.wikitext.parser.nodes.WtImageLink; +import org.sweble.wikitext.parser.nodes.WtInternalLink; import org.sweble.wikitext.parser.nodes.WtItalics; +import org.sweble.wikitext.parser.nodes.WtLinkTitle; +import org.sweble.wikitext.parser.nodes.WtLinkTitle.WtNoLinkTitle; +import org.sweble.wikitext.parser.nodes.WtName; import org.sweble.wikitext.parser.nodes.WtNewline; import org.sweble.wikitext.parser.nodes.WtNode; +import org.sweble.wikitext.parser.nodes.WtParsedWikitextPage; +import org.sweble.wikitext.parser.nodes.WtPreproWikitextPage; import org.sweble.wikitext.parser.nodes.WtSection; +import org.sweble.wikitext.parser.nodes.WtTable; +import org.sweble.wikitext.parser.nodes.WtTableCaption; +import org.sweble.wikitext.parser.nodes.WtTableCell; +import org.sweble.wikitext.parser.nodes.WtTableHeader; +import org.sweble.wikitext.parser.nodes.WtTableRow; import org.sweble.wikitext.parser.nodes.WtTagExtension; import org.sweble.wikitext.parser.nodes.WtTagExtensionBody; import org.sweble.wikitext.parser.nodes.WtTemplate; import org.sweble.wikitext.parser.nodes.WtTemplateArgument; import org.sweble.wikitext.parser.nodes.WtTemplateArguments; import org.sweble.wikitext.parser.nodes.WtText; -import org.sweble.wikitext.parser.nodes.WtInternalLink; -import org.sweble.wikitext.parser.nodes.WtExternalLink; -import org.sweble.wikitext.parser.nodes.WtImageLink; -import org.sweble.wikitext.parser.nodes.WtLinkTitle; -import org.sweble.wikitext.parser.nodes.WtLinkTitle.WtNoLinkTitle; import org.sweble.wikitext.parser.nodes.WtUrl; -import org.sweble.wikitext.parser.nodes.WtTable; -import org.sweble.wikitext.parser.nodes.WtTableHeader; -import org.sweble.wikitext.parser.nodes.WtTableRow; -import org.sweble.wikitext.parser.nodes.WtTableCell; -import org.sweble.wikitext.parser.nodes.WtTableCaption; -import org.sweble.wikitext.parser.nodes.WtXmlAttributes; -import org.sweble.wikitext.parser.nodes.WtXmlAttribute; -import org.sweble.wikitext.parser.nodes.WtName; import org.sweble.wikitext.parser.nodes.WtValue; -import org.sweble.wikitext.parser.nodes.WtParsedWikitextPage; -import org.sweble.wikitext.parser.nodes.WtBody; +import org.sweble.wikitext.parser.nodes.WtXmlAttribute; +import org.sweble.wikitext.parser.nodes.WtXmlAttributes; import org.sweble.wikitext.parser.nodes.WtXmlEmptyTag; import org.sweble.wikitext.parser.nodes.WtXmlEndTag; import org.sweble.wikitext.parser.nodes.WtXmlStartTag; - -import org.sweble.wikitext.parser.WikitextEncodingValidator; -import org.sweble.wikitext.parser.WikitextPreprocessor; -import org.sweble.wikitext.parser.encval.ValidatedWikitext; -import org.sweble.wikitext.parser.nodes.WtPreproWikitextPage; import org.sweble.wikitext.parser.parser.PreprocessorToParserTransformer; import org.sweble.wikitext.parser.preprocessor.PreprocessedWikitext; +import org.sweble.wikitext.parser.utils.SimpleParserConfig; -import xtc.parser.ParseException; +import com.google.common.io.CharStreams; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Cell; @@ -64,10 +60,13 @@ import com.google.refine.model.Project; import com.google.refine.model.Recon; import com.google.refine.model.ReconStats; import com.google.refine.model.metadata.ProjectMetadata; +import com.google.refine.model.recon.ReconJob; +import com.google.refine.model.recon.StandardReconConfig; import com.google.refine.model.recon.StandardReconConfig.ColumnDetail; import com.google.refine.util.JSONUtilities; -import com.google.refine.model.recon.StandardReconConfig; -import com.google.refine.model.recon.ReconJob; + +import de.fau.cs.osr.ptk.common.AstVisitor; +import xtc.parser.ParseException; public class WikitextImporter extends TabularImportingParserBase { diff --git a/main/src/com/google/refine/importing/UrlRewriter.java b/main/src/com/google/refine/importing/UrlRewriter.java index d7332750e..7563fe1cc 100644 --- a/main/src/com/google/refine/importing/UrlRewriter.java +++ b/main/src/com/google/refine/importing/UrlRewriter.java @@ -37,6 +37,8 @@ import java.io.IOException; import java.net.MalformedURLException; import java.util.List; +import com.google.refine.model.metadata.DataPackageUrlRewriter; + /** * Given a URL rewrittenUrl, the interface will rewrite it into different URLS based on the rewrittenUrl * The result will be stored in the Result and can be used for download, parsing etc. diff --git a/main/src/com/google/refine/model/changes/DataExtensionChange.java b/main/src/com/google/refine/model/changes/DataExtensionChange.java index 31348540a..ce3bccc96 100644 --- a/main/src/com/google/refine/model/changes/DataExtensionChange.java +++ b/main/src/com/google/refine/model/changes/DataExtensionChange.java @@ -43,13 +43,6 @@ import java.util.List; import java.util.Map; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONWriter; - -import com.google.refine.model.ReconType; -import com.google.refine.model.recon.DataExtensionReconConfig; -import com.google.refine.model.recon.ReconciledDataExtensionJob.DataExtension; import com.google.refine.history.Change; import com.google.refine.model.Cell; import com.google.refine.model.Column; @@ -59,7 +52,10 @@ import com.google.refine.model.Recon; import com.google.refine.model.Recon.Judgment; import com.google.refine.model.ReconCandidate; import com.google.refine.model.ReconStats; +import com.google.refine.model.ReconType; import com.google.refine.model.Row; +import com.google.refine.model.recon.DataExtensionReconConfig; +import com.google.refine.model.recon.ReconciledDataExtensionJob.DataExtension; import com.google.refine.util.ParsingUtilities; import com.google.refine.util.Pool; diff --git a/main/src/com/google/refine/model/changes/MassChange.java b/main/src/com/google/refine/model/changes/MassChange.java index cdef9f84a..efb6feb81 100644 --- a/main/src/com/google/refine/model/changes/MassChange.java +++ b/main/src/com/google/refine/model/changes/MassChange.java @@ -34,14 +34,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model.changes; import java.io.IOException; -import com.google.common.collect.Lists; - import java.io.LineNumberReader; import java.io.Writer; import java.util.ArrayList; import java.util.List; import java.util.Properties; +import com.google.common.collect.Lists; + import com.google.refine.history.Change; import com.google.refine.history.History; import com.google.refine.model.Project; diff --git a/main/src/com/google/refine/model/changes/MassReconChange.java b/main/src/com/google/refine/model/changes/MassReconChange.java index 0e4df55bb..41869af00 100644 --- a/main/src/com/google/refine/model/changes/MassReconChange.java +++ b/main/src/com/google/refine/model/changes/MassReconChange.java @@ -41,9 +41,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.ProjectManager; import com.google.refine.history.Change; import com.google.refine.model.Cell; diff --git a/main/src/com/google/refine/model/metadata/ProjectMetadata.java b/main/src/com/google/refine/model/metadata/ProjectMetadata.java index d81c1e611..0bf01d540 100644 --- a/main/src/com/google/refine/model/metadata/ProjectMetadata.java +++ b/main/src/com/google/refine/model/metadata/ProjectMetadata.java @@ -34,15 +34,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model.metadata; import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.OutputStreamWriter; import java.io.Serializable; -import java.io.StringWriter; -import java.io.Writer; import java.lang.reflect.InvocationTargetException; import java.time.LocalDateTime; import java.util.ArrayList; @@ -50,7 +45,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Properties; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.io.FileUtils; @@ -60,17 +54,15 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.annotation.JsonView; -import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.google.refine.ProjectManager; import com.google.refine.preference.PreferenceStore; diff --git a/main/src/com/google/refine/oauth/Credentials.java b/main/src/com/google/refine/oauth/Credentials.java index d28cdd2bf..7c4aa6381 100644 --- a/main/src/com/google/refine/oauth/Credentials.java +++ b/main/src/com/google/refine/oauth/Credentials.java @@ -37,11 +37,11 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import com.google.refine.util.CookiesUtilities; + import oauth.signpost.OAuth; import oauth.signpost.http.HttpParameters; -import com.google.refine.util.CookiesUtilities; - public class Credentials { private static final String TOKEN = "oauth_token"; From f263d8a1292c346480bcbbf012e8d1cb9b7de5c9 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 5 Oct 2018 10:16:33 +0100 Subject: [PATCH 031/164] Migrate commands out of JSONWriter --- .../google/refine/commands/HttpUtilities.java | 32 ++++---- .../column/GetColumnsInfoCommand.java | 51 +++++------- .../GetImportingConfigurationCommand.java | 26 ++----- .../commands/lang/GetLanguagesCommand.java | 77 +++++++++---------- .../refine/importing/ImportingManager.java | 48 ++++-------- 5 files changed, 95 insertions(+), 139 deletions(-) diff --git a/main/src/com/google/refine/commands/HttpUtilities.java b/main/src/com/google/refine/commands/HttpUtilities.java index 97d9cc7e2..b43a2d522 100644 --- a/main/src/com/google/refine/commands/HttpUtilities.java +++ b/main/src/com/google/refine/commands/HttpUtilities.java @@ -13,10 +13,11 @@ import javax.servlet.http.HttpServletResponse; import org.apache.velocity.VelocityContext; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.core.JsonGenerator; + import com.google.refine.RefineServlet; import com.google.refine.util.ParsingUtilities; @@ -43,11 +44,11 @@ abstract public class HttpUtilities { Writer w = response.getWriter(); try { - JSONWriter writer = new JSONWriter(w); - writer.object(); - writer.key("status"); writer.value(status); - writer.key("message"); writer.value(message); - writer.endObject(); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); + writer.writeStartObject(); + writer.writeStringField("status", status); + writer.writeStringField("message", message); + writer.writeEndObject(); w.flush(); w.close(); } catch (JSONException e) { @@ -84,21 +85,24 @@ abstract public class HttpUtilities { } try { - JSONObject o = new JSONObject(); - o.put("code", "error"); - o.put("message", e.getMessage()); - StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); pw.flush(); sw.flush(); - - o.put("stack", sw.toString()); - + response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "application/json"); - respond(response, o.toString()); + + Writer w = response.getWriter(); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); + writer.writeStartObject(); + writer.writeStringField("code", "error"); + writer.writeStringField("message", e.getMessage()); + writer.writeStringField("stack", sw.toString()); + writer.writeEndObject(); + w.flush(); + w.close(); } catch (JSONException e1) { e.printStackTrace(response.getWriter()); } diff --git a/main/src/com/google/refine/commands/column/GetColumnsInfoCommand.java b/main/src/com/google/refine/commands/column/GetColumnsInfoCommand.java index b31e4f91d..87e4f5f7d 100644 --- a/main/src/com/google/refine/commands/column/GetColumnsInfoCommand.java +++ b/main/src/com/google/refine/commands/column/GetColumnsInfoCommand.java @@ -39,8 +39,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONException; -import org.json.JSONWriter; +import com.fasterxml.jackson.core.JsonGenerator; import com.google.refine.browsing.util.ExpressionBasedRowEvaluable; import com.google.refine.browsing.util.NumericBinIndex; @@ -51,6 +50,7 @@ import com.google.refine.expr.MetaParser; import com.google.refine.expr.ParsingException; import com.google.refine.model.Column; import com.google.refine.model.Project; +import com.google.refine.util.ParsingUtilities; public class GetColumnsInfoCommand extends Command { @@ -59,25 +59,20 @@ public class GetColumnsInfoCommand extends Command { throws ServletException, IOException { try { - //long start = System.currentTimeMillis(); - response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "application/json"); Project project = getProject(request); - //Engine engine = getEngine(request, project); - JSONWriter writer = new JSONWriter(response.getWriter()); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(response.getWriter()); - writer.array(); + writer.writeStartArray(); for (Column column : project.columnModel.columns) { - writer.object(); + writer.writeStartObject(); write(project, column, writer); - writer.endObject(); + writer.writeEndObject(); } - writer.endArray(); - - //Refine.log("Obtained columns info in " + (System.currentTimeMillis() - start) + "ms"); + writer.writeEndArray(); } catch (Exception e) { e.printStackTrace(); respondException(response, e); @@ -101,33 +96,23 @@ public class GetColumnsInfoCommand extends Command { return index; } - private void write(Project project, Column column, JSONWriter writer) throws JSONException { + private void write(Project project, Column column, JsonGenerator writer) throws IOException { NumericBinIndex columnIndex = getBinIndex(project, column); if (columnIndex != null) { - writer.key("name"); - writer.value(column.getName()); + writer.writeStringField("name", column.getName()); boolean is_numeric = columnIndex.isNumeric(); - writer.key("is_numeric"); - writer.value(is_numeric); - writer.key("numeric_row_count"); - writer.value(columnIndex.getNumericRowCount()); - writer.key("non_numeric_row_count"); - writer.value(columnIndex.getNonNumericRowCount()); - writer.key("error_row_count"); - writer.value(columnIndex.getErrorRowCount()); - writer.key("blank_row_count"); - writer.value(columnIndex.getBlankRowCount()); + writer.writeBooleanField("is_numeric", is_numeric); + writer.writeNumberField("numeric_row_count", columnIndex.getNumericRowCount()); + writer.writeNumberField("non_numeric_row_count", columnIndex.getNonNumericRowCount()); + writer.writeNumberField("error_row_count", columnIndex.getErrorRowCount()); + writer.writeNumberField("blank_row_count", columnIndex.getBlankRowCount()); if (is_numeric) { - writer.key("min"); - writer.value(columnIndex.getMin()); - writer.key("max"); - writer.value(columnIndex.getMax()); - writer.key("step"); - writer.value(columnIndex.getStep()); + writer.writeNumberField("min", columnIndex.getMin()); + writer.writeNumberField("max", columnIndex.getMax()); + writer.writeNumberField("step", columnIndex.getStep()); } } else { - writer.key("error"); - writer.value("error finding numeric information on the '" + column.getName() + "' column"); + writer.writeStringField("error", "error finding numeric information on the '" + column.getName() + "' column"); } } } diff --git a/main/src/com/google/refine/commands/importing/GetImportingConfigurationCommand.java b/main/src/com/google/refine/commands/importing/GetImportingConfigurationCommand.java index e07e5a774..3dcc418fe 100644 --- a/main/src/com/google/refine/commands/importing/GetImportingConfigurationCommand.java +++ b/main/src/com/google/refine/commands/importing/GetImportingConfigurationCommand.java @@ -34,36 +34,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.commands.importing; import java.io.IOException; -import java.io.Writer; -import java.util.Properties; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONException; -import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.commands.Command; -import com.google.refine.importing.ImportingManager; +import com.google.refine.importing.ImportingManager.ImportingConfiguration; public class GetImportingConfigurationCommand extends Command { + + public static class ConfigurationResponse { + @JsonProperty("config") + ImportingConfiguration config = new ImportingConfiguration(); + } @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - Writer w = response.getWriter(); - response.setContentType("application/json"); - JSONWriter writer = new JSONWriter(w); - try { - writer.object(); - writer.key("config"); ImportingManager.writeConfiguration(writer, new Properties()); - writer.endObject(); - } catch (JSONException e) { - throw new ServletException(e); - } finally { - w.flush(); - w.close(); - } + respondJSON(response, new ConfigurationResponse()); } } diff --git a/main/src/com/google/refine/commands/lang/GetLanguagesCommand.java b/main/src/com/google/refine/commands/lang/GetLanguagesCommand.java index d44322bd2..cd0ea55c9 100644 --- a/main/src/com/google/refine/commands/lang/GetLanguagesCommand.java +++ b/main/src/com/google/refine/commands/lang/GetLanguagesCommand.java @@ -36,15 +36,18 @@ package com.google.refine.commands.lang; import java.io.File; import java.io.FileFilter; import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.filefilter.WildcardFileFilter; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; + +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.commands.Command; @@ -52,6 +55,38 @@ import edu.mit.simile.butterfly.ButterflyModule; public class GetLanguagesCommand extends Command { + public static class LanguageRecord { + @JsonProperty("code") + protected String code; + @JsonProperty("label") + protected String label; + public LanguageRecord(String code, String label) { + this.code = code; + this.label = label; + } + } + + public class LanguagesResponse { + @JsonProperty("languages") + List languages; + + public LanguagesResponse(ButterflyModule module) throws UnsupportedEncodingException { + languages = new ArrayList<>(); + languages.add(new LanguageRecord("en", "English")); + FileFilter fileFilter = new WildcardFileFilter("translation-*.json"); + for (File file : new File(module.getPath() + File.separator + "langs").listFiles(fileFilter)) { + String lang = file.getName().split("-")[1].split("\\.")[0]; + if (!"en".equals(lang) && !"default".equals(lang)) { + JSONObject json = LoadLanguageCommand.loadLanguage(servlet, "core", lang); + if (json != null && json.has("name")) { + String label = json.getString("name"); + languages.add(new LanguageRecord(lang, label)); + } + } + } + } + } + public GetLanguagesCommand() { super(); } @@ -73,42 +108,6 @@ public class GetLanguagesCommand extends Command { ButterflyModule module = this.servlet.getModule(modname); - try { - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - - writer.object(); - writer.key("languages"); - writer.array(); - writeLangData(writer, "en", "English"); // we always have English and it's always first - - FileFilter fileFilter = new WildcardFileFilter("translation-*.json"); - for (File file : new File(module.getPath() + File.separator + "langs").listFiles(fileFilter)) { - String lang = file.getName().split("-")[1].split("\\.")[0]; - if (!"en".equals(lang) && !"default".equals(lang)) { - JSONObject json = LoadLanguageCommand.loadLanguage(this.servlet, "core", lang); - if (json != null && json.has("name")) { - String label = json.getString("name"); - writeLangData(writer, lang, label); - } - } - } - - writer.endArray(); - writer.endObject(); - } catch (JSONException e) { - respondException(response, e); - } + respondJSON(response, new LanguagesResponse(module)); } - - private void writeLangData(JSONWriter writer, String lang, String label) - throws JSONException { - writer.object(); - writer.key("code"); writer.value(lang); - writer.key("label"); writer.value(label); - writer.endObject(); - } - } diff --git a/main/src/com/google/refine/importing/ImportingManager.java b/main/src/com/google/refine/importing/ImportingManager.java index ea0540e24..53b041adf 100644 --- a/main/src/com/google/refine/importing/ImportingManager.java +++ b/main/src/com/google/refine/importing/ImportingManager.java @@ -55,15 +55,21 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.RefineServlet; import edu.mit.simile.butterfly.ButterflyModule; public class ImportingManager { static public class Format { + @JsonProperty("id") final public String id; + @JsonProperty("label") final public String label; + @JsonProperty("download") final public boolean download; + @JsonProperty("uiClass") final public String uiClass; final public ImportingParser parser; @@ -223,41 +229,13 @@ public class ImportingManager { } } - static public void writeConfiguration(JSONWriter writer, Properties options) throws JSONException { - writer.object(); - - writer.key("formats"); - writer.object(); - for (String format : formatToRecord.keySet()) { - Format record = formatToRecord.get(format); - - writer.key(format); - writer.object(); - writer.key("id"); writer.value(record.id); - writer.key("label"); writer.value(record.label); - writer.key("download"); writer.value(record.download); - writer.key("uiClass"); writer.value(record.uiClass); - writer.endObject(); - } - writer.endObject(); - - writer.key("mimeTypeToFormat"); - writer.object(); - for (String mimeType : mimeTypeToFormat.keySet()) { - writer.key(mimeType); - writer.value(mimeTypeToFormat.get(mimeType)); - } - writer.endObject(); - - writer.key("extensionToFormat"); - writer.object(); - for (String extension : extensionToFormat.keySet()) { - writer.key(extension); - writer.value(extensionToFormat.get(extension)); - } - writer.endObject(); - - writer.endObject(); + static public class ImportingConfiguration { + @JsonProperty("formats") + public Map getFormats() { return formatToRecord; } + @JsonProperty("mimeTypeToFormat") + public Map getMimeTypeToFormat() { return mimeTypeToFormat; } + @JsonProperty("extensionToFormat") + public Map getExtensionToFormat() { return extensionToFormat; } } static public String getFormatFromFileName(String fileName) { From 9219ef36aa2c42bf95e0a002b31c8324ecc03414 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 5 Oct 2018 16:20:07 +0100 Subject: [PATCH 032/164] Jackson serialization for the remaining commands --- .../com/google/refine/commands/Command.java | 32 +++-- .../commands/GetAllPreferencesCommand.java | 31 ++--- .../recon/GuessTypesOfColumnCommand.java | 100 +++++++------- .../recon/PreviewExtendDataCommand.java | 124 ++++++++---------- .../recon/ReconciledDataExtensionJob.java | 5 +- 5 files changed, 138 insertions(+), 154 deletions(-) diff --git a/main/src/com/google/refine/commands/Command.java b/main/src/com/google/refine/commands/Command.java index 39415f4d9..7664c977c 100644 --- a/main/src/com/google/refine/commands/Command.java +++ b/main/src/com/google/refine/commands/Command.java @@ -46,11 +46,11 @@ import javax.servlet.http.HttpServletResponse; import org.apache.velocity.VelocityContext; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonGenerator; import com.google.refine.ProjectManager; import com.google.refine.RefineServlet; @@ -290,11 +290,11 @@ public abstract class Command { throws IOException, JSONException { Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); - writer.object(); - writer.key("status"); writer.value(status); - writer.key("message"); writer.value(message); - writer.endObject(); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); + writer.writeStartObject(); + writer.writeStringField("status", status); + writer.writeStringField("message", message); + writer.writeEndObject(); w.flush(); w.close(); } @@ -343,9 +343,14 @@ public abstract class Command { } try { - JSONObject o = new JSONObject(); - o.put("code", "error"); - o.put("message", e.getMessage()); + response.setCharacterEncoding("UTF-8"); + response.setHeader("Content-Type", "application/json"); + + Writer w = response.getWriter(); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); + writer.writeStartObject(); + writer.writeStringField("code", "error"); + writer.writeStringField("message", e.getMessage()); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); @@ -353,11 +358,10 @@ public abstract class Command { pw.flush(); sw.flush(); - o.put("stack", sw.toString()); - - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - respond(response, o.toString()); + writer.writeStringField("stack", sw.toString()); + writer.writeEndObject(); + w.flush(); + w.close(); } catch (JSONException e1) { e.printStackTrace(response.getWriter()); } diff --git a/main/src/com/google/refine/commands/GetAllPreferencesCommand.java b/main/src/com/google/refine/commands/GetAllPreferencesCommand.java index 8b2c6bc74..cdf641e08 100644 --- a/main/src/com/google/refine/commands/GetAllPreferencesCommand.java +++ b/main/src/com/google/refine/commands/GetAllPreferencesCommand.java @@ -34,14 +34,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.commands; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONException; -import org.json.JSONWriter; - import com.google.refine.ProjectManager; import com.google.refine.model.Project; import com.google.refine.preference.PreferenceStore; @@ -56,26 +55,16 @@ public class GetAllPreferencesCommand extends Command { project.getMetadata().getPreferenceStore() : ProjectManager.singleton.getPreferenceStore(); - try { - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - - writer.object(); - - for (String key : ps.getKeys()) { - Object pref = ps.get(key); - if (pref == null || pref instanceof String || pref instanceof Number || pref instanceof Boolean) { - writer.key(key); - writer.value(pref); - } + Map map = new HashMap<>(); + + for (String key : ps.getKeys()) { + Object pref = ps.get(key); + if (pref == null || pref instanceof String || pref instanceof Number || pref instanceof Boolean) { + map.put(key, pref); } - - writer.endObject(); - } catch (JSONException e) { - respondException(response, e); } + + respondJSON(response, map); } } diff --git a/main/src/com/google/refine/commands/recon/GuessTypesOfColumnCommand.java b/main/src/com/google/refine/commands/recon/GuessTypesOfColumnCommand.java index 3d920d145..9759a80ae 100644 --- a/main/src/com/google/refine/commands/recon/GuessTypesOfColumnCommand.java +++ b/main/src/com/google/refine/commands/recon/GuessTypesOfColumnCommand.java @@ -55,7 +55,10 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.commands.Command; import com.google.refine.expr.ExpressionUtils; @@ -66,6 +69,27 @@ import com.google.refine.util.ParsingUtilities; public class GuessTypesOfColumnCommand extends Command { + + protected static class TypesResponse { + @JsonProperty("code") + protected String code; + @JsonProperty("message") + @JsonInclude(Include.NON_NULL) + protected String message; + @JsonProperty("types") + @JsonInclude(Include.NON_NULL) + List types; + + protected TypesResponse( + String code, + String message, + List types) { + this.code = code; + this.message = message; + this.types = types; + } + } + @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -75,35 +99,14 @@ public class GuessTypesOfColumnCommand extends Command { String columnName = request.getParameter("columnName"); String serviceUrl = request.getParameter("service"); - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - writer.object(); - Column column = project.columnModel.getColumnByName(columnName); if (column == null) { - writer.key("code"); writer.value("error"); - writer.key("message"); writer.value("No such column"); + respondJSON(response, new TypesResponse("error", "No such column", null)); } else { - List typeGroups = guessTypes(project, column, serviceUrl); - - writer.key("code"); writer.value("ok"); - writer.key("types"); writer.array(); - - for (TypeGroup tg : typeGroups) { - writer.object(); - writer.key("id"); writer.value(tg.id); - writer.key("name"); writer.value(tg.name); - writer.key("score"); writer.value(tg.score); - writer.key("count"); writer.value(tg.count); - writer.endObject(); - } - - writer.endArray(); + List typeGroups = guessTypes(project, column, serviceUrl); + respondJSON(response, new TypesResponse("ok", null, typeGroups)); } - - writer.endObject(); + } catch (Exception e) { respondException(response, e); } @@ -111,6 +114,18 @@ public class GuessTypesOfColumnCommand extends Command { final static int SAMPLE_SIZE = 10; + protected static class IndividualQuery { + @JsonProperty("query") + protected String query; + @JsonProperty("limit") + protected int limit; + + protected IndividualQuery(String query, int limit) { + this.query = query; + this.limit = limit; + } + } + /** * Run relevance searches for the first n cells in the given column and * count the types of the results. Return a sorted list of types, from most @@ -144,25 +159,12 @@ public class GuessTypesOfColumnCommand extends Command { } } - StringWriter stringWriter = new StringWriter(); - try { - JSONWriter jsonWriter = new JSONWriter(stringWriter); - jsonWriter.object(); - for (int i = 0; i < samples.size(); i++) { - jsonWriter.key("q" + i); - jsonWriter.object(); - - jsonWriter.key("query"); jsonWriter.value(samples.get(i)); - jsonWriter.key("limit"); jsonWriter.value(3); - - jsonWriter.endObject(); - } - jsonWriter.endObject(); - } catch (JSONException e) { - logger.error("Error constructing query", e); + Map queryMap = new HashMap<>(); + for (int i = 0; i < samples.size(); i++) { + queryMap.put("q" + i, new IndividualQuery(samples.get(i), 3)); } - String queriesString = stringWriter.toString(); + String queriesString = ParsingUtilities.defaultWriter.writeValueAsString(queryMap); try { URL url = new URL(serviceUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); @@ -264,10 +266,14 @@ public class GuessTypesOfColumnCommand extends Command { } static protected class TypeGroup { - String id; - String name; - int count; - double score; + @JsonProperty("id") + protected String id; + @JsonProperty("name") + protected String name; + @JsonProperty("count") + protected int count; + @JsonProperty("score") + protected double score; TypeGroup(String id, String name, double score) { this.id = id; diff --git a/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java b/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java index f0c6906a7..c8d13a2aa 100644 --- a/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java +++ b/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java @@ -46,7 +46,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.json.JSONArray; -import org.json.JSONWriter; + +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.commands.Command; import com.google.refine.model.Cell; @@ -64,6 +65,19 @@ import com.google.refine.util.ParsingUtilities; public class PreviewExtendDataCommand extends Command { + protected static class PreviewResponse { + public PreviewResponse(List columns2, List> rows2) { + columns = columns2; + rows = rows2; + } + @JsonProperty("code") + protected String code = "ok"; + @JsonProperty("columns") + protected List columns; + @JsonProperty("rows") + protected List> rows; + } + @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -122,77 +136,45 @@ public class PreviewExtendDataCommand extends Command { Map reconCandidateMap = new HashMap(); ReconciledDataExtensionJob job = new ReconciledDataExtensionJob(config, endpoint); Map map = job.extend(ids, reconCandidateMap); - - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - writer.object(); - writer.key("code"); writer.value("ok"); - writer.key("columns"); - writer.array(); - for (ColumnInfo info : job.columns) { - writer.object(); - writer.key("name"); - writer.value(info.name); - writer.key("id"); - writer.value(info.id); - writer.endObject(); - } - writer.endArray(); - - writer.key("rows"); - writer.array(); - for (int r = 0; r < topicNames.size(); r++) { - String id = topicIds.get(r); - String topicName = topicNames.get(r); - - if (id != null && map.containsKey(id)) { - DataExtension ext = map.get(id); - boolean first = true; - - if (ext.data.length > 0) { - for (Object[] row : ext.data) { - writer.array(); - if (first) { - writer.value(topicName); - first = false; - } else { - writer.value(null); - } - - for (Object cell : row) { - if (cell != null && cell instanceof ReconCandidate) { - ReconCandidate rc = (ReconCandidate) cell; - writer.object(); - writer.key("id"); writer.value(rc.id); - writer.key("name"); writer.value(rc.name); - writer.endObject(); - } else { - writer.value(cell); - } - } - - writer.endArray(); - } - continue; - } - } - - writer.array(); - if (id != null) { - writer.object(); - writer.key("id"); writer.value(id); - writer.key("name"); writer.value(topicName); - writer.endObject(); - } else { - writer.value(""); - } - writer.endArray(); - } - writer.endArray(); + List> rows = new ArrayList<>(); + + for (int r = 0; r < topicNames.size(); r++) { + String id = topicIds.get(r); + String topicName = topicNames.get(r); - writer.endObject(); + if (id != null && map.containsKey(id)) { + DataExtension ext = map.get(id); + boolean first = true; + + if (ext.data.length > 0) { + for (Object[] row : ext.data) { + List jsonRow = new ArrayList<>(); + if (first) { + jsonRow.add(topicName); + first = false; + } else { + jsonRow.add(null); + } + + for (Object cell : row) { + jsonRow.add(cell); + } + rows.add(jsonRow); + } + continue; + } + } + + List supplement = new ArrayList<>(); + if (id != null) { + supplement.add(new ReconCandidate(id, topicName, new String[0], 100)); + } else { + supplement.add(""); + } + rows.add(supplement); + } + + respondJSON(response, new PreviewResponse(job.columns, rows)); } catch (Exception e) { respondException(response, e); } diff --git a/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java b/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java index 83c78e538..47f575600 100644 --- a/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java +++ b/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java @@ -141,8 +141,11 @@ public class ReconciledDataExtensionJob { } } + // Json serialization is used in PreviewExtendDataCommand static public class ColumnInfo { + @JsonProperty("name") final public String name; + @JsonProperty("id") final public String id; final public ReconType expectedType; @@ -320,7 +323,7 @@ public class ReconciledDataExtensionJob { static protected void formulateQuery(Set ids, DataExtensionConfig node, Writer writer) throws IOException { - DataExtensionQuery query = new DataExtensionQuery(ids.stream().collect(Collectors.toList()), node.properties); + DataExtensionQuery query = new DataExtensionQuery(ids.stream().filter(e -> e != null).collect(Collectors.toList()), node.properties); ParsingUtilities.saveWriter.writeValue(writer, query); } From 7156c49c4d4df200a06d7868becad55cee811158 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 7 Oct 2018 14:59:45 +0100 Subject: [PATCH 033/164] Remove remaining uses of org.json.JSONWriter in the core backend --- .../refine/exporters/TemplatingExporter.java | 42 +++-- .../importing/DefaultImportingController.java | 31 ++-- .../refine/importing/ImportingManager.java | 3 - .../model/recon/StandardReconConfig.java | 166 ++++++++++-------- .../com/google/refine/util/JSONUtilities.java | 17 -- 5 files changed, 137 insertions(+), 122 deletions(-) diff --git a/main/src/com/google/refine/exporters/TemplatingExporter.java b/main/src/com/google/refine/exporters/TemplatingExporter.java index 996ce4591..05568fbf5 100644 --- a/main/src/com/google/refine/exporters/TemplatingExporter.java +++ b/main/src/com/google/refine/exporters/TemplatingExporter.java @@ -34,13 +34,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.exporters; import java.io.IOException; -import java.io.StringWriter; import java.io.Writer; import java.util.Properties; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; + +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine.Mode; @@ -63,6 +63,26 @@ public class TemplatingExporter implements WriterExporter { public String getContentType() { return "application/x-unknown"; } + + protected static class TemplateConfig { + @JsonProperty("template") + protected String template; + @JsonProperty("prefix") + protected String prefix; + @JsonProperty("suffix") + protected String suffix; + @JsonProperty("separator") + protected String separator; + + protected TemplateConfig( + String template, String prefix, + String suffix, String separator) { + this.template = template; + this.prefix = prefix; + this.suffix = suffix; + this.separator = separator; + } + } @Override public void export(Project project, Properties options, Engine engine, Writer writer) throws IOException { @@ -94,20 +114,10 @@ public class TemplatingExporter implements WriterExporter { template.setSeparator(separatorString); if (!"true".equals(options.getProperty("preview"))) { - StringWriter stringWriter = new StringWriter(); - JSONWriter jsonWriter = new JSONWriter(stringWriter); - try { - jsonWriter.object(); - jsonWriter.key("template"); jsonWriter.value(templateString); - jsonWriter.key("prefix"); jsonWriter.value(prefixString); - jsonWriter.key("suffix"); jsonWriter.value(suffixString); - jsonWriter.key("separator"); jsonWriter.value(separatorString); - jsonWriter.endObject(); - } catch (JSONException e) { - // ignore - } - - project.getMetadata().getPreferenceStore().put("exporters.templating.template", stringWriter.toString()); + TemplateConfig config = new TemplateConfig(templateString, prefixString, + suffixString, separatorString); + project.getMetadata().getPreferenceStore().put("exporters.templating.template", + ParsingUtilities.defaultWriter.writeValueAsString(config)); } if (engine.getMode() == Mode.RowBased) { diff --git a/main/src/com/google/refine/importing/DefaultImportingController.java b/main/src/com/google/refine/importing/DefaultImportingController.java index b7b920dae..6c5647261 100644 --- a/main/src/com/google/refine/importing/DefaultImportingController.java +++ b/main/src/com/google/refine/importing/DefaultImportingController.java @@ -48,9 +48,9 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonGenerator; import com.google.refine.RefineServlet; import com.google.refine.commands.HttpUtilities; @@ -187,22 +187,21 @@ public class DefaultImportingController implements ImportingController { ImportingUtilities.previewParse(job, format, optionObj, exceptions); Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); try { - writer.object(); + writer.writeStartObject(); if (exceptions.size() == 0) { job.project.update(); // update all internal models, indexes, caches, etc. - writer.key("status"); writer.value("ok"); + writer.writeStringField("status", "ok"); } else { - writer.key("status"); writer.value("error"); - writer.key("errors"); - writer.array(); + writer.writeStringField("status", "error"); + writer.writeArrayFieldStart("errors"); writeErrors(writer, exceptions); - writer.endArray(); + writer.writeEndArray(); } - writer.endObject(); - } catch (JSONException e) { + writer.writeEndObject(); + } catch (IOException e) { throw new ServletException(e); } finally { w.flush(); @@ -304,17 +303,15 @@ public class DefaultImportingController implements ImportingController { w.close(); } - static public void writeErrors(JSONWriter writer, List exceptions) throws JSONException { + static public void writeErrors(JsonGenerator writer, List exceptions) throws IOException { for (Exception e : exceptions) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); - writer.object(); - writer.key("message"); - writer.value(e.getLocalizedMessage()); - writer.key("stack"); - writer.value(sw.toString()); - writer.endObject(); + writer.writeStartObject(); + writer.writeStringField("message", e.getLocalizedMessage()); + writer.writeStringField("stack", sw.toString()); + writer.writeEndObject(); } } diff --git a/main/src/com/google/refine/importing/ImportingManager.java b/main/src/com/google/refine/importing/ImportingManager.java index 53b041adf..39792c34d 100644 --- a/main/src/com/google/refine/importing/ImportingManager.java +++ b/main/src/com/google/refine/importing/ImportingManager.java @@ -43,15 +43,12 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.apache.commons.io.FileUtils; -import org.json.JSONException; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/main/src/com/google/refine/model/recon/StandardReconConfig.java b/main/src/com/google/refine/model/recon/StandardReconConfig.java index b6156d29a..692e0958e 100644 --- a/main/src/com/google/refine/model/recon/StandardReconConfig.java +++ b/main/src/com/google/refine/model/recon/StandardReconConfig.java @@ -40,15 +40,17 @@ import java.net.HttpURLConnection; import java.net.URL; import java.time.OffsetDateTime; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,6 +58,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; import com.google.refine.expr.ExpressionUtils; import com.google.refine.model.Cell; @@ -234,19 +237,70 @@ public class StandardReconConfig extends ReconConfig { */ StandardReconJob job = new StandardReconJob(); try { - StringWriter stringWriter = new StringWriter(); - JSONWriter jsonWriter = new JSONWriter(stringWriter); - jsonWriter.object(); - jsonWriter.key("query"); - jsonWriter.value(query); - jsonWriter.endObject(); + String queryJson = ParsingUtilities.defaultWriter.writeValueAsString( + Collections.singletonMap("query", query)); job.text = query; - job.code = stringWriter.toString(); + job.code = queryJson; return job; - } catch (JSONException je) { + } catch (JsonProcessingException e) { + e.printStackTrace(); return null; } } + + protected static class QueryProperty { + @JsonProperty("pid") + String pid; + @JsonProperty("v") + Object v; + + protected QueryProperty( + String pid, + Object v) { + this.pid = pid; + this.v = v; + } + } + + protected static class ReconQuery { + @JsonProperty("query") + protected String query; + + @JsonProperty("type") + @JsonInclude(Include.NON_NULL) + protected String typeID; + + @JsonProperty("type_strict") + @JsonInclude(Include.NON_NULL) + public String isTypeStrict() { + if(typeID != null) { + return "should"; + } + return null; + } + + @JsonProperty("properties") + @JsonInclude(Include.NON_EMPTY) + protected List properties; + + // Only send limit if it's non-default to preserve backward compatibility with + // services which might choke on this + @JsonProperty("limit") + @JsonInclude(Include.NON_DEFAULT) + protected int limit; + + public ReconQuery( + String query, + String typeID, + List properties, + int limit) { + this.query = query; + this.typeID = typeID; + this.properties = properties; + this.limit = limit; + } + + } @Override public ReconJob createJob(Project project, int rowIndex, Row row, @@ -254,74 +308,48 @@ public class StandardReconConfig extends ReconConfig { StandardReconJob job = new StandardReconJob(); - try { - StringWriter stringWriter = new StringWriter(); - JSONWriter jsonWriter = new JSONWriter(stringWriter); - - jsonWriter.object(); - jsonWriter.key("query"); jsonWriter.value(cell.value.toString()); - if (typeID != null) { - jsonWriter.key("type"); jsonWriter.value(typeID); - jsonWriter.key("type_strict"); jsonWriter.value("should"); - } + List properties = new ArrayList<>(); - if (columnDetails.size() > 0) { - jsonWriter.key("properties"); - jsonWriter.array(); + for (ColumnDetail c : columnDetails) { + int detailCellIndex = project.columnModel.getColumnByName(c.columnName).getCellIndex(); + + Cell cell2 = row.getCell(detailCellIndex); + if (cell2 == null || !ExpressionUtils.isNonBlankData(cell2.value)) { + int cellIndex = project.columnModel.getColumnByName(columnName).getCellIndex(); - for (ColumnDetail c : columnDetails) { - int detailCellIndex = project.columnModel.getColumnByName(c.columnName).getCellIndex(); - - Cell cell2 = row.getCell(detailCellIndex); - if (cell2 == null || !ExpressionUtils.isNonBlankData(cell2.value)) { - int cellIndex = project.columnModel.getColumnByName(columnName).getCellIndex(); + RowDependency rd = project.recordModel.getRowDependency(rowIndex); + if (rd != null && rd.cellDependencies != null) { + int contextRowIndex = rd.cellDependencies[cellIndex].rowIndex; + if (contextRowIndex >= 0 && contextRowIndex < project.rows.size()) { + Row row2 = project.rows.get(contextRowIndex); - RowDependency rd = project.recordModel.getRowDependency(rowIndex); - if (rd != null && rd.cellDependencies != null) { - int contextRowIndex = rd.cellDependencies[cellIndex].rowIndex; - if (contextRowIndex >= 0 && contextRowIndex < project.rows.size()) { - Row row2 = project.rows.get(contextRowIndex); - - cell2 = row2.getCell(detailCellIndex); - } - } - } - - if (cell2 != null && ExpressionUtils.isNonBlankData(cell2.value)) { - jsonWriter.object(); - - jsonWriter.key("pid"); jsonWriter.value(c.propertyID); - jsonWriter.key("v"); - if (cell2.recon != null && cell2.recon.match != null) { - jsonWriter.object(); - jsonWriter.key("id"); jsonWriter.value(cell2.recon.match.id); - jsonWriter.key("name"); jsonWriter.value(cell2.recon.match.name); - jsonWriter.endObject(); - } else if (cell2.value instanceof OffsetDateTime) { - jsonWriter.value(ParsingUtilities.dateToString((OffsetDateTime) cell2.value)); - } else { - jsonWriter.value(cell2.value.toString()); - } - - jsonWriter.endObject(); + cell2 = row2.getCell(detailCellIndex); } } - - jsonWriter.endArray(); } - // Only send limit if it's non-default to preserve backward compatibility with - // services which might choke on this - if (limit != 0) { - jsonWriter.key("limit"); jsonWriter.value(limit); + if (cell2 != null && ExpressionUtils.isNonBlankData(cell2.value)) { + Object v = null; + if (cell2.recon != null && cell2.recon.match != null) { + Map recon = new HashMap<>(); + recon.put("id", cell2.recon.match.id); + recon.put("name", cell2.recon.match.name); + v = recon; + } else { + v = cell2.value; + } + properties.add(new QueryProperty(c.propertyID, v)); + } + } - - jsonWriter.endObject(); - - job.text = cell.value.toString(); - job.code = stringWriter.toString(); - } catch (JSONException e) { - // + + ReconQuery query = new ReconQuery(cell.value.toString(), typeID, properties, limit); + + job.text = cell.value.toString(); + try { + job.code = ParsingUtilities.defaultWriter.writeValueAsString(query); + } catch (JsonProcessingException e) { + e.printStackTrace(); } return job; } diff --git a/main/src/com/google/refine/util/JSONUtilities.java b/main/src/com/google/refine/util/JSONUtilities.java index 925adcc1a..ea94a17e8 100644 --- a/main/src/com/google/refine/util/JSONUtilities.java +++ b/main/src/com/google/refine/util/JSONUtilities.java @@ -46,7 +46,6 @@ import java.util.Map; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; public class JSONUtilities { @@ -172,22 +171,6 @@ public class JSONUtilities { } } - static public void writeStringList(JSONWriter writer, List list) throws JSONException { - writer.array(); - for (String s : list) { - writer.value(s); - } - writer.endArray(); - } - - static public void writeStringArray(JSONWriter writer, String[] strings) throws JSONException { - writer.array(); - for (String s : strings) { - writer.value(s); - } - writer.endArray(); - } - static public void putField(JSONObject obj, String key, Object value) throws JSONException { if (value instanceof Integer) { obj.put(key, ((Integer) value).intValue()); From c9620a5d9ae3610ffbcdd486697169b441f066d8 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Thu, 11 Oct 2018 11:44:54 +0100 Subject: [PATCH 034/164] Add missing .flush(); .close() on JsonGenerator --- .../google/refine/extension/database/DatabaseModuleImpl.java | 3 --- .../wikidata/operations/PerformWikibaseEditsOperation.java | 3 --- .../wikidata/operations/SaveWikibaseSchemaOperation.java | 3 --- .../src/org/openrefine/wikidata/schema/WikibaseSchema.java | 2 -- main/src/com/google/refine/commands/Command.java | 4 ++++ main/src/com/google/refine/commands/HttpUtilities.java | 4 ++++ .../google/refine/commands/column/GetColumnsInfoCommand.java | 2 ++ .../google/refine/importing/DefaultImportingController.java | 4 +++- .../tests/commands/recon/ReconJudgeOneCellCommandTest.java | 2 -- 9 files changed, 13 insertions(+), 14 deletions(-) diff --git a/extensions/database/src/com/google/refine/extension/database/DatabaseModuleImpl.java b/extensions/database/src/com/google/refine/extension/database/DatabaseModuleImpl.java index 3d821f4d4..3ac87a524 100644 --- a/extensions/database/src/com/google/refine/extension/database/DatabaseModuleImpl.java +++ b/extensions/database/src/com/google/refine/extension/database/DatabaseModuleImpl.java @@ -35,12 +35,9 @@ import java.util.Properties; import javax.servlet.ServletConfig; -import org.json.JSONException; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import edu.mit.simile.butterfly.ButterflyModuleImpl; diff --git a/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java b/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java index c92433489..99adcc54d 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java @@ -31,9 +31,7 @@ import java.util.Properties; import java.util.Random; import org.apache.commons.lang.Validate; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.openrefine.wikidata.editing.ConnectionManager; import org.openrefine.wikidata.editing.EditBatchProcessor; import org.openrefine.wikidata.editing.NewItemLibrary; @@ -56,7 +54,6 @@ import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.operations.EngineDependentOperation; -import com.google.refine.operations.OperationRegistry; import com.google.refine.process.LongRunningProcess; import com.google.refine.process.Process; import com.google.refine.util.Pool; diff --git a/extensions/wikidata/src/org/openrefine/wikidata/operations/SaveWikibaseSchemaOperation.java b/extensions/wikidata/src/org/openrefine/wikidata/operations/SaveWikibaseSchemaOperation.java index 7eccbbafd..0459ab2b2 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/operations/SaveWikibaseSchemaOperation.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/operations/SaveWikibaseSchemaOperation.java @@ -28,9 +28,7 @@ import java.io.LineNumberReader; import java.io.Writer; import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.openrefine.wikidata.schema.WikibaseSchema; import com.fasterxml.jackson.annotation.JsonProperty; @@ -39,7 +37,6 @@ import com.google.refine.history.Change; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; -import com.google.refine.operations.OperationRegistry; import com.google.refine.util.ParsingUtilities; import com.google.refine.util.Pool; diff --git a/extensions/wikidata/src/org/openrefine/wikidata/schema/WikibaseSchema.java b/extensions/wikidata/src/org/openrefine/wikidata/schema/WikibaseSchema.java index 5f25306a7..fefbb0f3f 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/schema/WikibaseSchema.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/schema/WikibaseSchema.java @@ -26,11 +26,9 @@ package org.openrefine.wikidata.schema; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.Properties; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.openrefine.wikidata.qa.QAWarningStore; import org.openrefine.wikidata.schema.exceptions.SkipSchemaExpressionException; import org.openrefine.wikidata.updates.ItemUpdate; diff --git a/main/src/com/google/refine/commands/Command.java b/main/src/com/google/refine/commands/Command.java index 7664c977c..680b4daa7 100644 --- a/main/src/com/google/refine/commands/Command.java +++ b/main/src/com/google/refine/commands/Command.java @@ -295,6 +295,8 @@ public abstract class Command { writer.writeStringField("status", status); writer.writeStringField("message", message); writer.writeEndObject(); + writer.flush(); + writer.close(); w.flush(); w.close(); } @@ -360,6 +362,8 @@ public abstract class Command { writer.writeStringField("stack", sw.toString()); writer.writeEndObject(); + writer.flush(); + writer.close(); w.flush(); w.close(); } catch (JSONException e1) { diff --git a/main/src/com/google/refine/commands/HttpUtilities.java b/main/src/com/google/refine/commands/HttpUtilities.java index b43a2d522..09a8cdd27 100644 --- a/main/src/com/google/refine/commands/HttpUtilities.java +++ b/main/src/com/google/refine/commands/HttpUtilities.java @@ -49,6 +49,8 @@ abstract public class HttpUtilities { writer.writeStringField("status", status); writer.writeStringField("message", message); writer.writeEndObject(); + writer.flush(); + writer.close(); w.flush(); w.close(); } catch (JSONException e) { @@ -101,6 +103,8 @@ abstract public class HttpUtilities { writer.writeStringField("message", e.getMessage()); writer.writeStringField("stack", sw.toString()); writer.writeEndObject(); + writer.flush(); + writer.close(); w.flush(); w.close(); } catch (JSONException e1) { diff --git a/main/src/com/google/refine/commands/column/GetColumnsInfoCommand.java b/main/src/com/google/refine/commands/column/GetColumnsInfoCommand.java index 87e4f5f7d..e8683a124 100644 --- a/main/src/com/google/refine/commands/column/GetColumnsInfoCommand.java +++ b/main/src/com/google/refine/commands/column/GetColumnsInfoCommand.java @@ -73,6 +73,8 @@ public class GetColumnsInfoCommand extends Command { writer.writeEndObject(); } writer.writeEndArray(); + writer.flush(); + writer.close(); } catch (Exception e) { e.printStackTrace(); respondException(response, e); diff --git a/main/src/com/google/refine/importing/DefaultImportingController.java b/main/src/com/google/refine/importing/DefaultImportingController.java index 6c5647261..65fb583ad 100644 --- a/main/src/com/google/refine/importing/DefaultImportingController.java +++ b/main/src/com/google/refine/importing/DefaultImportingController.java @@ -201,6 +201,8 @@ public class DefaultImportingController implements ImportingController { writer.writeEndArray(); } writer.writeEndObject(); + writer.flush(); + writer.close(); } catch (IOException e) { throw new ServletException(e); } finally { @@ -298,7 +300,7 @@ public class DefaultImportingController implements ImportingController { throws ServletException, IOException { Writer w = response.getWriter(); - ParsingUtilities.defaultWriter.writeValue(w, job); + ParsingUtilities.defaultWriter.writeValue(w, new JobResponse("ok",job)); w.flush(); w.close(); } diff --git a/main/tests/server/src/com/google/refine/tests/commands/recon/ReconJudgeOneCellCommandTest.java b/main/tests/server/src/com/google/refine/tests/commands/recon/ReconJudgeOneCellCommandTest.java index 96cbaf7ac..6f848de51 100644 --- a/main/tests/server/src/com/google/refine/tests/commands/recon/ReconJudgeOneCellCommandTest.java +++ b/main/tests/server/src/com/google/refine/tests/commands/recon/ReconJudgeOneCellCommandTest.java @@ -6,12 +6,10 @@ import static org.mockito.Mockito.when; import java.io.IOException; import java.io.PrintWriter; import java.util.Collections; -import java.util.Properties; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONObject; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; From 47d80002a8616576fe3d83a5559ea9c0a33530a7 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Thu, 11 Oct 2018 17:34:32 +0100 Subject: [PATCH 035/164] Migrate GData extension out of JSONWriter --- .../gdata/GDataImportingController.java | 75 ++++++++++--------- .../refine/extension/gdata/UploadCommand.java | 28 ++++--- 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java b/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java index 1f98f0a3d..8b243bbe6 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java @@ -14,10 +14,11 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.core.JsonGenerator; + import com.google.api.services.drive.Drive; import com.google.api.services.drive.model.File; import com.google.api.services.drive.model.FileList; @@ -86,11 +87,10 @@ public class GDataImportingController implements ImportingController { } Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); try { - writer.object(); - writer.key("documents"); - writer.array(); + writer.writeStartObject(); + writer.writeArrayFieldStart("documents"); try { listSpreadsheets(GoogleAPIExtension.getDriveService(token), writer); @@ -98,18 +98,20 @@ public class GDataImportingController implements ImportingController { } catch (Exception e) { logger.error("doListDocuments exception:" + ExceptionUtils.getStackTrace(e)); } finally { - writer.endArray(); - writer.endObject(); + writer.writeEndArray(); + writer.writeEndObject(); } } catch (JSONException e) { throw new ServletException(e); } finally { + writer.flush(); + writer.close(); w.flush(); w.close(); } } - private void listSpreadsheets(Drive drive, JSONWriter writer) + private void listSpreadsheets(Drive drive, JsonGenerator writer) throws IOException, JSONException { com.google.api.services.drive.Drive.Files.List files = drive.files().list(); files.setQ("mimeType = 'application/vnd.google-apps.spreadsheet'"); @@ -117,30 +119,30 @@ public class GDataImportingController implements ImportingController { FileList fileList = files.execute(); for (File entry : fileList.getFiles()) { - writer.object(); - writer.key("docId"); writer.value(entry.getId()); - writer.key("docLink"); writer.value(entry.getWebViewLink()); - writer.key("docSelfLink"); writer.value(entry.getWebViewLink()); - writer.key("title"); writer.value(entry.getName()); + writer.writeStartObject(); + writer.writeStringField("docId", entry.getId()); + writer.writeStringField("docLink", entry.getWebViewLink()); + writer.writeStringField("docSelfLink", entry.getWebViewLink()); + writer.writeStringField("title", entry.getName()); - writer.key("type"); writer.value("spreadsheet"); + writer.writeStringField("type", "spreadsheet"); com.google.api.client.util.DateTime updated = entry.getModifiedTime(); if (updated != null) { - writer.key("updated"); writer.value(updated.toString()); + writer.writeStringField("updated", updated.toString()); } - writer.key("authors"); writer.array(); + writer.writeArrayFieldStart("authors"); for (User user : entry.getOwners()) { - writer.value(user.getDisplayName()); + writer.writeString(user.getDisplayName()); } - writer.endArray(); + writer.writeEndArray(); - writer.endObject(); + writer.writeEndObject(); } } - private void listFusionTables(Fusiontables service, JSONWriter writer) + private void listFusionTables(Fusiontables service, JsonGenerator writer) throws IOException, JSONException { Fusiontables.Table.List listTables = service.table().list(); @@ -155,13 +157,13 @@ public class GDataImportingController implements ImportingController { String link = "https://www.google.com/fusiontables/DataSource?docid=" + id; // Add JSON object to our stream - writer.object(); - writer.key("docId"); writer.value(id); - writer.key("docLink"); writer.value(link); - writer.key("docSelfLink"); writer.value(link); - writer.key("title"); writer.value(name); - writer.key("type"); writer.value("table"); - writer.endObject(); + writer.writeStartObject(); + writer.writeStringField("docId", id); + writer.writeStringField("docLink", link); + writer.writeStringField("docSelfLink", link); + writer.writeStringField("title", name); + writer.writeStringField("type", "table"); + writer.writeEndObject(); } } @@ -253,25 +255,26 @@ public class GDataImportingController implements ImportingController { ); Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); try { - writer.object(); + writer.writeStartObject(); if (exceptions.size() == 0) { job.project.update(); // update all internal models, indexes, caches, etc. - writer.key("status"); writer.value("ok"); + writer.writeStringField("status", "ok"); } else { - writer.key("status"); writer.value("error"); + writer.writeStringField("status", "error"); - writer.key("errors"); - writer.array(); + writer.writeArrayFieldStart("errors"); DefaultImportingController.writeErrors(writer, exceptions); - writer.endArray(); + writer.writeEndArray(); } - writer.endObject(); - } catch (JSONException e) { + writer.writeEndObject(); + } catch (IOException e) { throw new ServletException(e); } finally { + writer.flush(); + writer.close(); w.flush(); w.close(); } diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/UploadCommand.java b/extensions/gdata/src/com/google/refine/extension/gdata/UploadCommand.java index 8a32541cc..f1879065a 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/UploadCommand.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/UploadCommand.java @@ -15,11 +15,12 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.exception.ExceptionUtils; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.commons.codec.binary.Base64; +import com.fasterxml.jackson.core.JsonGenerator; + import com.google.api.client.http.FileContent; import com.google.api.services.drive.Drive; import com.google.api.services.drive.model.File; @@ -34,6 +35,7 @@ import com.google.refine.commands.project.ExportRowsCommand; import com.google.refine.exporters.CustomizableTabularExporterUtilities; import com.google.refine.io.FileProjectManager; import com.google.refine.model.Project; +import com.google.refine.util.ParsingUtilities; public class UploadCommand extends Command { static final Logger logger = LoggerFactory.getLogger("gdata_upload"); @@ -61,31 +63,33 @@ public class UploadCommand extends Command { response.setHeader("Content-Type", "application/json"); Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); try { - writer.object(); + writer.writeStartObject(); List exceptions = new LinkedList(); String url = upload(project, engine, params, token, name, exceptions); if (url != null) { - writer.key("status"); writer.value("ok"); - writer.key("url"); writer.value(url); + writer.writeStringField("status", "ok"); + writer.writeStringField("url", url); } else if (exceptions.size() == 0) { - writer.key("status"); writer.value("error"); - writer.key("message"); writer.value("No such format"); + writer.writeStringField("status", "error"); + writer.writeStringField("message", "No such format"); } else { for (Exception e : exceptions) { logger.warn(e.getLocalizedMessage(), e); } - writer.key("status"); writer.value("error"); - writer.key("message"); writer.value(exceptions.get(0).getLocalizedMessage()); + writer.writeStringField("status", "error"); + writer.writeStringField("message", exceptions.get(0).getLocalizedMessage()); } } catch (Exception e) { e.printStackTrace(); - writer.key("status"); writer.value("error"); - writer.key("message"); writer.value(e.getMessage()); + writer.writeStringField("status", "error"); + writer.writeStringField("message", e.getMessage()); } finally { - writer.endObject(); + writer.writeEndObject(); + writer.flush(); + writer.close(); w.flush(); w.close(); } From be9ebdcad9aa806b2c55c9f61841551e83b30906 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Thu, 11 Oct 2018 19:54:56 +0100 Subject: [PATCH 036/164] Migrate database extension out of JSONWriter --- .../database/DatabaseImportController.java | 26 ++---- .../database/cmd/ConnectCommand.java | 24 ++--- .../database/cmd/DatabaseCommand.java | 5 +- .../database/cmd/ExecuteQueryCommand.java | 22 +++-- .../database/cmd/SavedConnectionCommand.java | 92 ++++++++----------- .../database/cmd/TestConnectCommand.java | 22 ++--- .../database/cmd/TestQueryCommand.java | 22 +++-- 7 files changed, 96 insertions(+), 117 deletions(-) diff --git a/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java b/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java index e79153c68..1fce41bc7 100644 --- a/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java +++ b/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java @@ -41,10 +41,11 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.core.JsonGenerator; + import com.google.refine.ProjectManager; import com.google.refine.RefineServlet; import com.google.refine.commands.HttpUtilities; @@ -207,30 +208,23 @@ public class DatabaseImportController implements ImportingController { optionObj, exceptions ); -// String exStr = getExceptionString(exceptions); -// logger.info("exceptions::" + exStr); - Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); try { - writer.object(); + writer.writeStartObject(); if (exceptions.size() == 0) { job.project.update(); // update all internal models, indexes, caches, etc. - writer.key("status"); - writer.value("ok"); + writer.writeStringField("status", "ok"); } else { - writer.key("status"); - writer.value("error"); - writer.key("message"); - writer.value(getExceptionString(exceptions)); -// writer.array(); -// writeErrors(writer, exceptions); -// writer.endArray(); + writer.writeStringField("status", "error"); + writer.writeStringField("message", getExceptionString(exceptions)); } - writer.endObject(); + writer.writeEndObject(); } catch (JSONException e) { throw new ServletException(e); } finally { + writer.flush(); + writer.close(); w.flush(); w.close(); } diff --git a/extensions/database/src/com/google/refine/extension/database/cmd/ConnectCommand.java b/extensions/database/src/com/google/refine/extension/database/cmd/ConnectCommand.java index 014b30930..0ba564b65 100644 --- a/extensions/database/src/com/google/refine/extension/database/cmd/ConnectCommand.java +++ b/extensions/database/src/com/google/refine/extension/database/cmd/ConnectCommand.java @@ -37,15 +37,17 @@ import javax.servlet.http.HttpServletResponse; import org.apache.http.HttpStatus; import org.codehaus.jackson.map.ObjectMapper; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.core.JsonGenerator; + //import com.google.refine.ProjectManager; import com.google.refine.extension.database.DatabaseConfiguration; import com.google.refine.extension.database.DatabaseService; import com.google.refine.extension.database.DatabaseServiceException; import com.google.refine.extension.database.model.DatabaseInfo; +import com.google.refine.util.ParsingUtilities; public class ConnectCommand extends DatabaseCommand { @@ -66,7 +68,7 @@ public class ConnectCommand extends DatabaseCommand { response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "application/json"); Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); ObjectMapper mapperObj = new ObjectMapper(); try { @@ -74,22 +76,20 @@ public class ConnectCommand extends DatabaseCommand { .connect(databaseConfiguration); String databaseInfoString = mapperObj.writeValueAsString(databaseInfo); response.setStatus(HttpStatus.SC_OK); - writer.object(); - writer.key("code"); - writer.value("ok"); - writer.key("databaseInfo"); - writer.value(databaseInfoString); - - writer.endObject(); + writer.writeStartObject(); + writer.writeStringField("code", "ok"); + writer.writeStringField("databaseInfo", databaseInfoString); + writer.writeEndObject(); } catch (DatabaseServiceException e) { logger.error("ConnectCommand::Post::DatabaseServiceException::{}", e); - sendError(HttpStatus.SC_UNAUTHORIZED,response, writer, e); + sendError(HttpStatus.SC_UNAUTHORIZED,response, e); }catch (Exception e) { logger.error("ConnectCommand::Post::Exception::{}", e); - sendError(HttpStatus.SC_UNAUTHORIZED,response, writer, e); + sendError(HttpStatus.SC_UNAUTHORIZED,response, e); } finally { - // w.flush(); + writer.flush(); + writer.close(); w.close(); } } catch (Exception e) { diff --git a/extensions/database/src/com/google/refine/extension/database/cmd/DatabaseCommand.java b/extensions/database/src/com/google/refine/extension/database/cmd/DatabaseCommand.java index ccd967d95..171dccac1 100644 --- a/extensions/database/src/com/google/refine/extension/database/cmd/DatabaseCommand.java +++ b/extensions/database/src/com/google/refine/extension/database/cmd/DatabaseCommand.java @@ -33,7 +33,6 @@ import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -82,7 +81,7 @@ public abstract class DatabaseCommand extends Command { * @param e * @throws IOException */ - protected void sendError(int status, HttpServletResponse response, JSONWriter writer, Exception e) + protected void sendError(int status, HttpServletResponse response, Exception e) throws IOException { //logger.info("sendError::{}", writer); @@ -97,7 +96,7 @@ public abstract class DatabaseCommand extends Command { * @param e * @throws IOException */ - protected void sendError(int status, HttpServletResponse response, JSONWriter writer, DatabaseServiceException e) + protected void sendError(int status, HttpServletResponse response, DatabaseServiceException e) throws IOException { String message = ""; diff --git a/extensions/database/src/com/google/refine/extension/database/cmd/ExecuteQueryCommand.java b/extensions/database/src/com/google/refine/extension/database/cmd/ExecuteQueryCommand.java index 90a0dd387..888536dac 100644 --- a/extensions/database/src/com/google/refine/extension/database/cmd/ExecuteQueryCommand.java +++ b/extensions/database/src/com/google/refine/extension/database/cmd/ExecuteQueryCommand.java @@ -37,15 +37,17 @@ import javax.servlet.http.HttpServletResponse; import org.apache.http.HttpStatus; import org.codehaus.jackson.map.ObjectMapper; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.core.JsonGenerator; + //import com.google.refine.ProjectManager; import com.google.refine.extension.database.DatabaseConfiguration; import com.google.refine.extension.database.DatabaseService; import com.google.refine.extension.database.DatabaseServiceException; import com.google.refine.extension.database.model.DatabaseInfo; +import com.google.refine.util.ParsingUtilities; public class ExecuteQueryCommand extends DatabaseCommand { @@ -69,7 +71,7 @@ public class ExecuteQueryCommand extends DatabaseCommand { response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "application/json"); Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); try { DatabaseInfo databaseInfo = DatabaseService.get(databaseConfiguration.getDatabaseType()) @@ -84,22 +86,22 @@ public class ExecuteQueryCommand extends DatabaseCommand { } - writer.object(); - writer.key("code"); - writer.value("ok"); - writer.key("QueryResult"); - writer.value(jsonStr); - writer.endObject(); + writer.writeStartObject(); + writer.writeStringField("code", "ok"); + writer.writeStringField("QueryResult", jsonStr); + writer.writeEndObject(); } catch (DatabaseServiceException e) { logger.error("QueryCommand::Post::DatabaseServiceException::{}", e); - sendError(HttpStatus.SC_BAD_REQUEST, response, writer, e); + sendError(HttpStatus.SC_BAD_REQUEST, response, e); } catch (Exception e) { logger.error("QueryCommand::Post::Exception::{}", e); - sendError(HttpStatus.SC_BAD_REQUEST,response, writer, e); + sendError(HttpStatus.SC_BAD_REQUEST,response, e); } finally { + writer.flush(); + writer.close(); w.close(); } } catch (Exception e) { diff --git a/extensions/database/src/com/google/refine/extension/database/cmd/SavedConnectionCommand.java b/extensions/database/src/com/google/refine/extension/database/cmd/SavedConnectionCommand.java index 74b3af2ea..0d52e3d77 100644 --- a/extensions/database/src/com/google/refine/extension/database/cmd/SavedConnectionCommand.java +++ b/extensions/database/src/com/google/refine/extension/database/cmd/SavedConnectionCommand.java @@ -38,12 +38,14 @@ import javax.servlet.http.HttpServletResponse; import org.apache.http.HttpStatus; import org.json.JSONException; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.core.JsonGenerator; + import com.google.refine.extension.database.DatabaseConfiguration; import com.google.refine.extension.database.DatabaseUtils; +import com.google.refine.util.ParsingUtilities; public class SavedConnectionCommand extends DatabaseCommand { @@ -120,51 +122,38 @@ public class SavedConnectionCommand extends DatabaseCommand { private void writeSavedConnectionResponse(HttpServletResponse response, DatabaseConfiguration savedConnection) throws IOException, JSONException { Writer w = response.getWriter(); try { - JSONWriter writer = new JSONWriter(w); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); - writer.object(); - writer.key(DatabaseUtils.SAVED_CONNECTION_KEY); - writer.array(); + writer.writeStartObject(); + writer.writeArrayFieldStart(DatabaseUtils.SAVED_CONNECTION_KEY); - writer.object(); - writer.key("connectionName"); - writer.value(savedConnection.getConnectionName()); + writer.writeStartObject(); + writer.writeStringField("connectionName", savedConnection.getConnectionName()); - writer.key("databaseType"); - writer.value(savedConnection.getDatabaseType()); + writer.writeStringField("databaseType", savedConnection.getDatabaseType()); - writer.key("databaseHost"); - writer.value(savedConnection.getDatabaseHost()); + writer.writeStringField("databaseHost", savedConnection.getDatabaseHost()); - writer.key("databasePort"); - writer.value(savedConnection.getDatabasePort()); + writer.writeNumberField("databasePort", savedConnection.getDatabasePort()); - writer.key("databaseName"); - writer.value(savedConnection.getDatabaseName()); - - writer.key("databasePassword"); + writer.writeStringField("databaseName", savedConnection.getDatabaseName()); - // String dbPasswd = savedConnection.getDatabasePassword(); if(dbPasswd != null && !dbPasswd.isEmpty()) { dbPasswd = DatabaseUtils.decrypt(savedConnection.getDatabasePassword()); - //logger.info("Decrypted Password::" + dbPasswd); } - writer.value(dbPasswd); - // - - // writer.value(savedConnection.getDatabasePassword()); + writer.writeStringField("databasePassword", dbPasswd); - writer.key("databaseSchema"); - writer.value(savedConnection.getDatabaseSchema()); + writer.writeStringField("databaseSchema", savedConnection.getDatabaseSchema()); - writer.key("databaseUser"); - writer.value(savedConnection.getDatabaseUser()); + writer.writeStringField("databaseUser", savedConnection.getDatabaseUser()); - writer.endObject(); - writer.endArray(); + writer.writeEndObject(); + writer.writeEndArray(); - writer.endObject(); + writer.writeEndObject(); + writer.flush(); + writer.close(); }finally { w.flush(); @@ -183,54 +172,47 @@ public class SavedConnectionCommand extends DatabaseCommand { try { List savedConnections = DatabaseUtils.getSavedConnections(); - JSONWriter writer = new JSONWriter(w); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); - writer.object(); - writer.key(DatabaseUtils.SAVED_CONNECTION_KEY); - writer.array(); + writer.writeStartObject(); + writer.writeArrayFieldStart(DatabaseUtils.SAVED_CONNECTION_KEY); int size = savedConnections.size(); for (int i = 0; i < size; i++) { - writer.object(); + writer.writeStartObject(); DatabaseConfiguration dbConfig = (DatabaseConfiguration) savedConnections.get(i); - writer.key("connectionName"); - writer.value(dbConfig.getConnectionName()); + writer.writeStringField("connectionName", dbConfig.getConnectionName()); - writer.key("databaseType"); - writer.value(dbConfig.getDatabaseType()); + writer.writeStringField("databaseType", dbConfig.getDatabaseType()); - writer.key("databaseHost"); - writer.value(dbConfig.getDatabaseHost()); + writer.writeStringField("databaseHost", dbConfig.getDatabaseHost()); - writer.key("databasePort"); - writer.value(dbConfig.getDatabasePort()); + writer.writeNumberField("databasePort", dbConfig.getDatabasePort()); - writer.key("databaseName"); - writer.value(dbConfig.getDatabaseName()); + writer.writeStringField("databaseName", dbConfig.getDatabaseName()); - writer.key("databasePassword"); String dbPasswd = dbConfig.getDatabasePassword(); if(dbPasswd != null && !dbPasswd.isEmpty()) { dbPasswd = DatabaseUtils.decrypt(dbConfig.getDatabasePassword()); } // writer.value(dbConfig.getDatabasePassword()); - writer.value(dbPasswd); + writer.writeStringField("databasePassword", dbPasswd); - writer.key("databaseSchema"); - writer.value(dbConfig.getDatabaseSchema()); + writer.writeStringField("databaseSchema", dbConfig.getDatabaseSchema()); - writer.key("databaseUser"); - writer.value(dbConfig.getDatabaseUser()); + writer.writeStringField("databaseUser", dbConfig.getDatabaseUser()); - writer.endObject(); + writer.writeEndObject(); } - writer.endArray(); - writer.endObject(); + writer.writeEndArray(); + writer.writeEndObject(); + writer.flush(); + writer.close(); // logger.info("Saved Connection Get Response sent"); } finally { w.flush(); diff --git a/extensions/database/src/com/google/refine/extension/database/cmd/TestConnectCommand.java b/extensions/database/src/com/google/refine/extension/database/cmd/TestConnectCommand.java index b4cd0dd0b..78ad4b27b 100644 --- a/extensions/database/src/com/google/refine/extension/database/cmd/TestConnectCommand.java +++ b/extensions/database/src/com/google/refine/extension/database/cmd/TestConnectCommand.java @@ -36,13 +36,15 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.http.HttpStatus; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.core.JsonGenerator; + import com.google.refine.extension.database.DatabaseConfiguration; import com.google.refine.extension.database.DatabaseService; import com.google.refine.extension.database.DatabaseServiceException; +import com.google.refine.util.ParsingUtilities; @@ -69,7 +71,7 @@ public class TestConnectCommand extends DatabaseCommand { response.setHeader("Content-Type", "application/json"); Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); try { @@ -77,20 +79,18 @@ public class TestConnectCommand extends DatabaseCommand { .testConnection(databaseConfiguration); response.setStatus(HttpStatus.SC_OK); - writer.object(); + writer.writeStartObject(); - writer.key("connectionResult"); - writer.value(connectionTestResult); - writer.key("code"); - writer.value("ok"); - writer.endObject(); + writer.writeBooleanField("connectionResult", connectionTestResult); + writer.writeStringField("code", "ok"); + writer.writeEndObject(); } catch (DatabaseServiceException e) { logger.error("TestConnectCommand::Post::DatabaseServiceException::{}", e); - sendError(HttpStatus.SC_UNAUTHORIZED,response, writer, e); + sendError(HttpStatus.SC_UNAUTHORIZED,response, e); } finally { - // writer.endObject(); - // w.flush(); + writer.flush(); + writer.close(); w.close(); } } catch (Exception e) { diff --git a/extensions/database/src/com/google/refine/extension/database/cmd/TestQueryCommand.java b/extensions/database/src/com/google/refine/extension/database/cmd/TestQueryCommand.java index a728fc1bd..90e42ece4 100644 --- a/extensions/database/src/com/google/refine/extension/database/cmd/TestQueryCommand.java +++ b/extensions/database/src/com/google/refine/extension/database/cmd/TestQueryCommand.java @@ -37,15 +37,17 @@ import javax.servlet.http.HttpServletResponse; import org.apache.http.HttpStatus; import org.codehaus.jackson.map.ObjectMapper; -import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.core.JsonGenerator; + //import com.google.refine.ProjectManager; import com.google.refine.extension.database.DatabaseConfiguration; import com.google.refine.extension.database.DatabaseService; import com.google.refine.extension.database.DatabaseServiceException; import com.google.refine.extension.database.model.DatabaseInfo; +import com.google.refine.util.ParsingUtilities; public class TestQueryCommand extends DatabaseCommand { @@ -70,7 +72,7 @@ public class TestQueryCommand extends DatabaseCommand { response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "application/json"); Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); try { DatabaseInfo databaseInfo = DatabaseService.get(dbConfig.getDatabaseType()) @@ -83,22 +85,22 @@ public class TestQueryCommand extends DatabaseCommand { logger.debug("TestQueryCommand::Post::Result::{} " ,jsonStr); } - writer.object(); - writer.key("code"); - writer.value("ok"); - writer.key("QueryResult"); - writer.value(jsonStr); - writer.endObject(); + writer.writeStartObject(); + writer.writeStringField("code", "ok"); + writer.writeStringField("QueryResult", jsonStr); + writer.writeEndObject(); } catch (DatabaseServiceException e) { logger.error("TestQueryCommand::Post::DatabaseServiceException::{}", e); - sendError(HttpStatus.SC_BAD_REQUEST, response, writer, e); + sendError(HttpStatus.SC_BAD_REQUEST, response, e); } catch (Exception e) { logger.error("TestQueryCommand::Post::Exception::{}", e); - sendError(HttpStatus.SC_BAD_REQUEST,response, writer, e); + sendError(HttpStatus.SC_BAD_REQUEST,response, e); } finally { + writer.flush(); + writer.close(); w.close(); } } catch (Exception e) { From 790b1fbc6078a938a0759ac5fec3551361d014f0 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Thu, 11 Oct 2018 19:55:31 +0100 Subject: [PATCH 037/164] Migrate wikidata extension out of JSONWriter --- .../wikidata/commands/CommandUtilities.java | 16 +++++++----- .../wikidata/commands/LoginCommand.java | 26 +++++++++++-------- .../PerformWikibaseEditsOperation.java | 2 +- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/extensions/wikidata/src/org/openrefine/wikidata/commands/CommandUtilities.java b/extensions/wikidata/src/org/openrefine/wikidata/commands/CommandUtilities.java index 74f1cbdfd..c82bd4986 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/commands/CommandUtilities.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/commands/CommandUtilities.java @@ -5,7 +5,9 @@ import java.io.Writer; import javax.servlet.http.HttpServletResponse; -import org.json.JSONWriter; +import com.fasterxml.jackson.core.JsonGenerator; + +import com.google.refine.util.ParsingUtilities; public class CommandUtilities { @@ -21,11 +23,13 @@ public class CommandUtilities { public static void respondError(HttpServletResponse response, String errorMessage) throws IOException { Writer w = response.getWriter(); - JSONWriter writer = new JSONWriter(w); - writer.object(); - writer.key("code"); writer.value("error"); - writer.key("message"); writer.value(errorMessage); - writer.endObject(); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); + writer.writeStartObject(); + writer.writeStringField("code", "error"); + writer.writeStringField("message", errorMessage); + writer.writeEndObject(); + writer.flush(); + writer.close(); w.flush(); w.close(); } diff --git a/extensions/wikidata/src/org/openrefine/wikidata/commands/LoginCommand.java b/extensions/wikidata/src/org/openrefine/wikidata/commands/LoginCommand.java index 951741ddf..289ce8962 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/commands/LoginCommand.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/commands/LoginCommand.java @@ -24,17 +24,19 @@ package org.openrefine.wikidata.commands; import java.io.IOException; -import java.io.StringWriter; +import java.io.Writer; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.json.JSONException; -import org.json.JSONWriter; import org.openrefine.wikidata.editing.ConnectionManager; +import com.fasterxml.jackson.core.JsonGenerator; + import com.google.refine.commands.Command; +import com.google.refine.util.ParsingUtilities; public class LoginCommand extends Command { @@ -53,20 +55,22 @@ public class LoginCommand extends Command { response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "application/json"); - StringWriter sb = new StringWriter(2048); - JSONWriter writer = new JSONWriter(sb); + Writer w = response.getWriter(); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); try { - writer.object(); - writer.key("logged_in"); - writer.value(manager.isLoggedIn()); - writer.key("username"); - writer.value(manager.getUsername()); - writer.endObject(); + writer.writeStartObject(); + writer.writeBooleanField("logged_in", manager.isLoggedIn()); + writer.writeStringField("username", manager.getUsername()); + writer.writeEndObject(); } catch (JSONException e) { logger.error(e.getMessage()); + } finally { + writer.flush(); + writer.close(); + w.flush(); + w.close(); } - respond(response, sb.toString()); } @Override diff --git a/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java b/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java index 99adcc54d..9ae696a7a 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java @@ -85,7 +85,7 @@ public class PerformWikibaseEditsOperation extends EngineDependentOperation { @Override protected String getBriefDescription(Project project) { - return "Peform Wikibase edits"; + return "Perform Wikibase edits"; } @Override From bc6f1b0146ad35744b69e56ee5fab615f6998158 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Thu, 11 Oct 2018 19:57:41 +0100 Subject: [PATCH 038/164] Fix failing tests after JSONWriter replacement --- .../src/com/google/refine/commands/Command.java | 13 ++++++------- .../refine/tests/browsing/EngineTests.java | 2 +- .../util/CancelProcessesCommandTests.java | 17 +++++++++++++---- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/main/src/com/google/refine/commands/Command.java b/main/src/com/google/refine/commands/Command.java index 680b4daa7..f60dc15cb 100644 --- a/main/src/com/google/refine/commands/Command.java +++ b/main/src/com/google/refine/commands/Command.java @@ -348,18 +348,17 @@ public abstract class Command { response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "application/json"); - Writer w = response.getWriter(); - JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); - writer.writeStartObject(); - writer.writeStringField("code", "error"); - writer.writeStringField("message", e.getMessage()); - StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); pw.flush(); sw.flush(); - + + Writer w = response.getWriter(); + JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w); + writer.writeStartObject(); + writer.writeStringField("code", "error"); + writer.writeStringField("message", e.getMessage()); writer.writeStringField("stack", sw.toString()); writer.writeEndObject(); writer.flush(); diff --git a/main/tests/server/src/com/google/refine/tests/browsing/EngineTests.java b/main/tests/server/src/com/google/refine/tests/browsing/EngineTests.java index e997d1274..e6d875452 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/EngineTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/EngineTests.java @@ -13,6 +13,6 @@ public class EngineTests { public void serializeEngine() { Project project = mock(Project.class); Engine engine = new Engine(project); - TestUtils.isSerializedTo(engine, "{\"mode\":\"row-based\",\"facets\":[]}"); + TestUtils.isSerializedTo(engine, "{\"engine-mode\":\"row-based\",\"facets\":[]}"); } } diff --git a/main/tests/server/src/com/google/refine/tests/commands/util/CancelProcessesCommandTests.java b/main/tests/server/src/com/google/refine/tests/commands/util/CancelProcessesCommandTests.java index 350d45a9b..a1ed70c2a 100644 --- a/main/tests/server/src/com/google/refine/tests/commands/util/CancelProcessesCommandTests.java +++ b/main/tests/server/src/com/google/refine/tests/commands/util/CancelProcessesCommandTests.java @@ -41,6 +41,7 @@ import static org.mockito.Mockito.when; import java.io.IOException; import java.io.PrintWriter; +import java.io.StringWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -58,6 +59,7 @@ import com.google.refine.commands.history.CancelProcessesCommand; import com.google.refine.model.Project; import com.google.refine.process.ProcessManager; import com.google.refine.tests.RefineTest; +import com.google.refine.tests.util.TestUtils; public class CancelProcessesCommandTests extends RefineTest { @@ -80,6 +82,7 @@ public class CancelProcessesCommandTests extends RefineTest { ProjectManager projMan = null; Project proj = null; ProcessManager processMan = null; + StringWriter sw = null; PrintWriter pw = null; @BeforeMethod @@ -88,7 +91,8 @@ public class CancelProcessesCommandTests extends RefineTest { ProjectManager.singleton = projMan; proj = mock(Project.class); processMan = mock(ProcessManager.class); - pw = mock(PrintWriter.class); + sw = new StringWriter(); + pw = new PrintWriter(sw); request = mock(HttpServletRequest.class); response = mock(HttpServletResponse.class); @@ -102,7 +106,7 @@ public class CancelProcessesCommandTests extends RefineTest { projMan = null; ProjectManager.singleton = null; proj = null; - pw = null; + sw = null; request = null; response = null; } @@ -186,7 +190,7 @@ public class CancelProcessesCommandTests extends RefineTest { } catch (IOException e) { Assert.fail(); } - verify(pw, times(1)).write("{ \"code\" : \"ok\" }"); + TestUtils.assertEqualAsJson("{ \"code\" : \"ok\" }", sw.toString()); } @Test @@ -195,6 +199,11 @@ public class CancelProcessesCommandTests extends RefineTest { when(request.getParameter("project")).thenReturn(PROJECT_ID); when(projMan.getProject(anyLong())) .thenReturn(null); + try { + when(response.getWriter()).thenReturn(pw); + } catch (IOException e1) { + Assert.fail(); + } // run try { @@ -238,7 +247,7 @@ public class CancelProcessesCommandTests extends RefineTest { verify(projMan, times(1)).getProject(PROJECT_ID_LONG); verify(processMan, times(1)).cancelAll(); - verify(response, times(3)).setCharacterEncoding("UTF-8"); + verify(response, times(2)).setCharacterEncoding("UTF-8"); //omitted other verifications for brevity. //assumption is that expecting response.setCharacterEncoding times(3) //implies it has Command.respondException has been called as expected From 9c788769afe3968e43c88aa1a33e51c459a9351b Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 12 Oct 2018 10:42:30 +0100 Subject: [PATCH 039/164] Restore JSON property autodetect --- .../src/org/openrefine/wikidata/schema/WikibaseSchema.java | 3 +++ main/src/com/google/refine/browsing/Engine.java | 5 +++++ main/src/com/google/refine/importing/ImportingManager.java | 2 ++ main/src/com/google/refine/util/ParsingUtilities.java | 2 +- 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/extensions/wikidata/src/org/openrefine/wikidata/schema/WikibaseSchema.java b/extensions/wikidata/src/org/openrefine/wikidata/schema/WikibaseSchema.java index fefbb0f3f..48a54d470 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/schema/WikibaseSchema.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/schema/WikibaseSchema.java @@ -36,6 +36,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonParseException; @@ -84,6 +85,7 @@ public class WikibaseSchema implements OverlayModel { /** * @return the site IRI of the Wikibase instance referenced by this schema */ + @JsonIgnore public String getBaseIri() { return baseIri; } @@ -91,6 +93,7 @@ public class WikibaseSchema implements OverlayModel { /** * @return the list of document expressions for this schema */ + @JsonIgnore public List getItemDocumentExpressions() { return itemDocumentExprs; } diff --git a/main/src/com/google/refine/browsing/Engine.java b/main/src/com/google/refine/browsing/Engine.java index 6ff493b1c..dd0249e3a 100644 --- a/main/src/com/google/refine/browsing/Engine.java +++ b/main/src/com/google/refine/browsing/Engine.java @@ -68,6 +68,7 @@ public class Engine { public final static String MODE_ROW_BASED = "row-based"; public final static String MODE_RECORD_BASED = "record-based"; + @JsonIgnore protected Project _project; @JsonProperty("facets") protected List _facets = new LinkedList(); @@ -93,6 +94,7 @@ public class Engine { _config = new EngineConfig(_config.getFacetConfigs(), mode); } + @JsonIgnore public FilteredRows getAllRows() { return new FilteredRows() { @Override @@ -114,6 +116,7 @@ public class Engine { }; } + @JsonIgnore public FilteredRows getAllFilteredRows() { return getFilteredRows(null); } @@ -136,6 +139,7 @@ public class Engine { throw new InternalError("Unknown mode."); } + @JsonIgnore public FilteredRecords getAllRecords() { return new FilteredRecords() { @Override @@ -154,6 +158,7 @@ public class Engine { }; } + @JsonIgnore public FilteredRecords getFilteredRecords() { return getFilteredRecords(null); } diff --git a/main/src/com/google/refine/importing/ImportingManager.java b/main/src/com/google/refine/importing/ImportingManager.java index 39792c34d..ec29caacd 100644 --- a/main/src/com/google/refine/importing/ImportingManager.java +++ b/main/src/com/google/refine/importing/ImportingManager.java @@ -52,6 +52,7 @@ import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.RefineServlet; @@ -68,6 +69,7 @@ public class ImportingManager { final public boolean download; @JsonProperty("uiClass") final public String uiClass; + @JsonIgnore final public ImportingParser parser; private Format( diff --git a/main/src/com/google/refine/util/ParsingUtilities.java b/main/src/com/google/refine/util/ParsingUtilities.java index 6b906ce17..06a605729 100644 --- a/main/src/com/google/refine/util/ParsingUtilities.java +++ b/main/src/com/google/refine/util/ParsingUtilities.java @@ -84,7 +84,7 @@ public class ParsingUtilities { mapper.registerModule(module); - mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE); + // mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } From 75b642f9bf14763c74af02d0a9f9db6a7b012857 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 12 Oct 2018 11:08:50 +0100 Subject: [PATCH 040/164] Fix serialization of local dates --- .../model/metadata/AbstractMetadata.java | 6 +++++ .../google/refine/util/ParsingUtilities.java | 7 ++---- .../refine/util/SerializationFilters.java | 22 +++++++++++++++++-- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/main/src/com/google/refine/model/metadata/AbstractMetadata.java b/main/src/com/google/refine/model/metadata/AbstractMetadata.java index 43a5ac9b5..5433cdbd0 100644 --- a/main/src/com/google/refine/model/metadata/AbstractMetadata.java +++ b/main/src/com/google/refine/model/metadata/AbstractMetadata.java @@ -6,10 +6,16 @@ import java.time.LocalDateTime; import org.apache.commons.beanutils.PropertyUtils; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + public abstract class AbstractMetadata implements IMetadata { + @JsonIgnore private MetadataFormat formatName = MetadataFormat.UNKNOWN; + @JsonIgnore protected LocalDateTime written = null; + @JsonProperty("modified") protected LocalDateTime _modified; public MetadataFormat getFormatName() { diff --git a/main/src/com/google/refine/util/ParsingUtilities.java b/main/src/com/google/refine/util/ParsingUtilities.java index 06a605729..f4426a989 100644 --- a/main/src/com/google/refine/util/ParsingUtilities.java +++ b/main/src/com/google/refine/util/ParsingUtilities.java @@ -59,8 +59,6 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; -import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; -import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.DeserializationFeature; @@ -80,11 +78,10 @@ public class ParsingUtilities { SimpleModule module = new SimpleModule(); module.addSerializer(Double.class, new SerializationFilters.DoubleSerializer()); module.addSerializer(double.class, new SerializationFilters.DoubleSerializer()); - module.addSerializer(OffsetDateTime.class, new SerializationFilters.DateSerializer()); - + module.addSerializer(OffsetDateTime.class, new SerializationFilters.OffsetDateSerializer()); + module.addSerializer(LocalDateTime.class, new SerializationFilters.LocalDateSerializer()); mapper.registerModule(module); - // mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } diff --git a/main/src/com/google/refine/util/SerializationFilters.java b/main/src/com/google/refine/util/SerializationFilters.java index 984f2ca96..4c937c25f 100644 --- a/main/src/com/google/refine/util/SerializationFilters.java +++ b/main/src/com/google/refine/util/SerializationFilters.java @@ -1,6 +1,7 @@ package com.google.refine.util; import java.io.IOException; +import java.time.LocalDateTime; import java.time.OffsetDateTime; import com.fasterxml.jackson.core.JsonGenerator; @@ -90,10 +91,10 @@ public class SerializationFilters { /** * Serialize dates by ISO format. */ - public static class DateSerializer extends StdSerializer { + public static class OffsetDateSerializer extends StdSerializer { private static final long serialVersionUID = 93872874L; - public DateSerializer() { + public OffsetDateSerializer() { super(OffsetDateTime.class); } @@ -103,4 +104,21 @@ public class SerializationFilters { gen.writeString(ParsingUtilities.dateToString(arg0)); } } + + /** + * Serialize dates by ISO format. + */ + public static class LocalDateSerializer extends StdSerializer { + private static final long serialVersionUID = 93872874L; + + public LocalDateSerializer() { + super(LocalDateTime.class); + } + + @Override + public void serialize(LocalDateTime arg0, JsonGenerator gen, SerializerProvider s) + throws IOException { + gen.writeString(ParsingUtilities.localDateToString(arg0)); + } + } } From 0698b9c84ec65bb3849c8a8d0c3dd804c8efe047 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 12 Oct 2018 12:42:01 +0100 Subject: [PATCH 041/164] Unify JSON testing in Wikidata extension --- .../src/org/openrefine/wikidata/operations/OperationTest.java | 3 ++- main/src/com/google/refine/importing/ImportingJob.java | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/extensions/wikidata/tests/src/org/openrefine/wikidata/operations/OperationTest.java b/extensions/wikidata/tests/src/org/openrefine/wikidata/operations/OperationTest.java index cfc04fb4e..a6969c0f0 100644 --- a/extensions/wikidata/tests/src/org/openrefine/wikidata/operations/OperationTest.java +++ b/extensions/wikidata/tests/src/org/openrefine/wikidata/operations/OperationTest.java @@ -42,6 +42,7 @@ import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.tests.RefineTest; +import com.google.refine.tests.util.TestUtils; import com.google.refine.util.ParsingUtilities; import com.google.refine.util.Pool; @@ -78,7 +79,7 @@ public abstract class OperationTest extends RefineTest { AbstractOperation op = reconstruct(); StringWriter writer = new StringWriter(); ParsingUtilities.defaultWriter.writeValue(writer, op); - JacksonSerializationTest.assertJsonEquals(json.toString(), writer.toString()); + TestUtils.assertEqualAsJson(json.toString(), writer.toString()); } protected LineNumberReader makeReader(String input) { diff --git a/main/src/com/google/refine/importing/ImportingJob.java b/main/src/com/google/refine/importing/ImportingJob.java index 27b0c65e9..a19af621a 100644 --- a/main/src/com/google/refine/importing/ImportingJob.java +++ b/main/src/com/google/refine/importing/ImportingJob.java @@ -42,6 +42,7 @@ import org.apache.commons.io.FileUtils; import org.json.JSONArray; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRawValue; @@ -86,6 +87,7 @@ public class ImportingJob { return config.toString(); } + @JsonIgnore public JSONObject getOrCreateDefaultConfig() { return config; } @@ -137,6 +139,7 @@ public class ImportingJob { } + @JsonIgnore public JSONObject getRetrievalRecord() { synchronized(config) { return JSONUtilities.getObject(config,"retrievalRecord"); @@ -152,6 +155,7 @@ public class ImportingJob { return fileRecordObject.has("metaDataFormat"); } + @JsonIgnore public List getSelectedFileRecords() { List results = new ArrayList(); From 1c34b237e413b187e860d2bad009af5d3e69b358 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 12 Oct 2018 15:32:41 +0100 Subject: [PATCH 042/164] Unify JSON testing in Wikidata extension --- .../operations/SaveWikibaseSchemaOperation.java | 4 +++- .../wikidata/testing/JacksonSerializationTest.java | 14 ++------------ 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/extensions/wikidata/src/org/openrefine/wikidata/operations/SaveWikibaseSchemaOperation.java b/extensions/wikidata/src/org/openrefine/wikidata/operations/SaveWikibaseSchemaOperation.java index 0459ab2b2..13e043bd1 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/operations/SaveWikibaseSchemaOperation.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/operations/SaveWikibaseSchemaOperation.java @@ -31,6 +31,7 @@ import java.util.Properties; import org.json.JSONObject; import org.openrefine.wikidata.schema.WikibaseSchema; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.history.Change; @@ -42,7 +43,8 @@ import com.google.refine.util.Pool; public class SaveWikibaseSchemaOperation extends AbstractOperation { - final public String operationDescription = "Save Wikibase schema"; + @JsonIgnore + final public static String operationDescription = "Save Wikibase schema"; @JsonProperty("schema") final protected WikibaseSchema _schema; diff --git a/extensions/wikidata/tests/src/org/openrefine/wikidata/testing/JacksonSerializationTest.java b/extensions/wikidata/tests/src/org/openrefine/wikidata/testing/JacksonSerializationTest.java index ab61ee7cc..e50b975da 100644 --- a/extensions/wikidata/tests/src/org/openrefine/wikidata/testing/JacksonSerializationTest.java +++ b/extensions/wikidata/tests/src/org/openrefine/wikidata/testing/JacksonSerializationTest.java @@ -33,6 +33,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.refine.tests.util.TestUtils; import com.google.refine.util.ParsingUtilities; public class JacksonSerializationTest { @@ -44,7 +45,7 @@ public class JacksonSerializationTest { try { String actualJson = ParsingUtilities.defaultWriter.writeValueAsString(pojo); - assertJsonEquals(expectedJson, actualJson); + TestUtils.assertEqualAsJson(expectedJson, actualJson); } catch (JsonProcessingException e) { e.printStackTrace(); Assert.fail("Failed to serialize object"); @@ -68,15 +69,4 @@ public class JacksonSerializationTest { testSerialize(pojo, json); testDeserialize(targetClass, pojo, json); } - - public static void assertJsonEquals(String expectedJson, String actualJson) { - JsonNode parsedExpectedJson; - try { - parsedExpectedJson = mapper.readValue(expectedJson, JsonNode.class); - JsonNode parsedActualJson = mapper.readValue(actualJson, JsonNode.class); - assertEquals(parsedExpectedJson, parsedActualJson); - } catch (IOException e) { - Assert.fail("Invalid JSON"); - } - } } From 8b41c4e08a74dd775ffc3e7e822cdcf3c470431a Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 14 Oct 2018 22:50:33 +0100 Subject: [PATCH 043/164] Merge Jsonizable removal with master --- .../ReconUseValuesAsIdentifiersOperation.java | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java b/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java index 0e6f65d92..fda3726cf 100644 --- a/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java @@ -4,9 +4,7 @@ import java.util.Collections; import java.util.List; import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; -import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; @@ -64,20 +62,6 @@ public class ReconUseValuesAsIdentifiersOperation extends EngineDependentMassCel ); } - @Override - public void write(JSONWriter writer, Properties options) - throws JSONException { - writer.object(); - writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value(getBriefDescription(null)); - writer.key("engineConfig"); getEngineConfig().write(writer, options); - writer.key("columnName"); writer.value(_columnName); - writer.key("service"); writer.value(service); - writer.key("schemaSpace"); writer.value(schemaSpace); - writer.key("identifierSpace"); writer.value(identifierSpace); - writer.endObject(); - } - @Override public String getBriefDescription(Project project) { return "Use values as reconciliation identifiers in column " + _columnName; From 0dae0811b070b57b67a909334573c640e96bc53e Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 21 Oct 2018 16:31:58 +0100 Subject: [PATCH 044/164] Jackson deserialization for ReconConfig --- .../commands/recon/ReconcileCommand.java | 8 +- .../model/changes/DataExtensionChange.java | 2 +- .../refine/model/changes/ReconChange.java | 8 +- .../refine/model/recon/ReconConfig.java | 53 +++++++------ .../model/recon/ReconConfigResolver.java | 34 +++++++++ .../model/recon/StandardReconConfig.java | 76 ++++++++----------- .../operations/recon/ReconOperation.java | 2 +- .../refine/tests/model/ReconTypeTest.java | 3 +- .../model/recon/StandardReconConfigTests.java | 13 +++- 9 files changed, 110 insertions(+), 89 deletions(-) create mode 100644 main/src/com/google/refine/model/recon/ReconConfigResolver.java diff --git a/main/src/com/google/refine/commands/recon/ReconcileCommand.java b/main/src/com/google/refine/commands/recon/ReconcileCommand.java index 7861e0db6..21866ed80 100644 --- a/main/src/com/google/refine/commands/recon/ReconcileCommand.java +++ b/main/src/com/google/refine/commands/recon/ReconcileCommand.java @@ -35,9 +35,6 @@ package com.google.refine.commands.recon; import javax.servlet.http.HttpServletRequest; -import org.json.JSONObject; -import org.json.JSONTokener; - import com.google.refine.browsing.EngineConfig; import com.google.refine.commands.EngineDependentCommand; import com.google.refine.model.AbstractOperation; @@ -54,9 +51,6 @@ public class ReconcileCommand extends EngineDependentCommand { String columnName = request.getParameter("columnName"); String configString = request.getParameter("config"); - JSONTokener t = new JSONTokener(configString); - JSONObject config = (JSONObject) t.nextValue(); - - return new ReconOperation(engineConfig, columnName, ReconConfig.reconstruct(config)); + return new ReconOperation(engineConfig, columnName, ReconConfig.reconstruct(configString)); } } diff --git a/main/src/com/google/refine/model/changes/DataExtensionChange.java b/main/src/com/google/refine/model/changes/DataExtensionChange.java index ce3bccc96..1bb2a35c7 100644 --- a/main/src/com/google/refine/model/changes/DataExtensionChange.java +++ b/main/src/com/google/refine/model/changes/DataExtensionChange.java @@ -393,7 +393,7 @@ public class DataExtensionChange implements Change { if (line == null || line.length() == 0) { columnTypes.add(null); } else { - columnTypes.add(ReconType.load(ParsingUtilities.evaluateJsonStringToObject(line))); + columnTypes.add(ReconType.load(line)); } } } else if ("dataExtensionCount".equals(field)) { diff --git a/main/src/com/google/refine/model/changes/ReconChange.java b/main/src/com/google/refine/model/changes/ReconChange.java index 9b5508c5d..76440cdbc 100644 --- a/main/src/com/google/refine/model/changes/ReconChange.java +++ b/main/src/com/google/refine/model/changes/ReconChange.java @@ -174,19 +174,19 @@ public class ReconChange extends MassCellChange { if ("newReconConfig".equals(field)) { if (value.length() > 0) { - newReconConfig = ReconConfig.reconstruct(ParsingUtilities.evaluateJsonStringToObject(value)); + newReconConfig = ReconConfig.reconstruct(value); } } else if ("newReconStats".equals(field)) { if (value.length() > 0) { - newReconStats = ReconStats.load(ParsingUtilities.evaluateJsonStringToObject(value)); + newReconStats = ParsingUtilities.mapper.readValue(value, ReconStats.class); } } else if ("oldReconConfig".equals(field)) { if (value.length() > 0) { - oldReconConfig = ReconConfig.reconstruct(ParsingUtilities.evaluateJsonStringToObject(value)); + oldReconConfig = ReconConfig.reconstruct(value); } } else if ("oldReconStats".equals(field)) { if (value.length() > 0) { - oldReconStats = ReconStats.load(ParsingUtilities.evaluateJsonStringToObject(value)); + oldReconStats = ParsingUtilities.mapper.readValue(value, ReconStats.class); } } else if ("commonColumnName".equals(field)) { commonColumnName = value; diff --git a/main/src/com/google/refine/model/recon/ReconConfig.java b/main/src/com/google/refine/model/recon/ReconConfig.java index 063cc5e13..aa3459a89 100644 --- a/main/src/com/google/refine/model/recon/ReconConfig.java +++ b/main/src/com/google/refine/model/recon/ReconConfig.java @@ -35,17 +35,17 @@ package com.google.refine.model.recon; import java.io.IOException; import java.io.Writer; -import java.lang.reflect.Method; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver; import com.google.refine.model.Cell; import com.google.refine.model.Project; @@ -55,6 +55,11 @@ import com.google.refine.util.ParsingUtilities; import edu.mit.simile.butterfly.ButterflyModule; +@JsonTypeInfo( + use=JsonTypeInfo.Id.CUSTOM, + include=JsonTypeInfo.As.PROPERTY, + property="mode") +@JsonTypeIdResolver(ReconConfigResolver.class) abstract public class ReconConfig { final static protected Logger LOGGER = LoggerFactory.getLogger("recon-config"); @@ -77,35 +82,29 @@ abstract public class ReconConfig { classes.add(klass); } - static public ReconConfig reconstruct(JSONObject obj) throws Exception { - try { - String mode = obj.getString("mode"); - - // Backward compatibility - if ("extend".equals(mode) || "strict".equals(mode)) { - mode = "freebase/" + mode; - } else if ("heuristic".equals(mode)) { - mode = "core/standard-service"; // legacy - } else if (!mode.contains("/")) { - mode = "core/" + mode; - } - - // TODO: This can fail silently if the Freebase extension is not installed. - List> classes = s_opNameToClass.get(mode); - if (classes != null && classes.size() > 0) { - Class klass = classes.get(classes.size() - 1); - - Method reconstruct = klass.getMethod("reconstruct", JSONObject.class); - if (reconstruct != null) { - return (ReconConfig) reconstruct.invoke(null, obj); - } - } - } catch (Exception e) { - LOGGER.error("Reconstruct failed",e); + static public Class getClassFromMode(String mode) { + // Backward compatibility + if ("extend".equals(mode) || "strict".equals(mode)) { + mode = "freebase/" + mode; + } else if ("heuristic".equals(mode)) { + mode = "core/standard-service"; // legacy + } else if (!mode.contains("/")) { + mode = "core/" + mode; + } + + // TODO: This can fail silently if the Freebase extension is not installed. + List> classes = s_opNameToClass.get(mode); + System.out.println(classes); + if (classes != null && classes.size() > 0) { + return classes.get(classes.size() - 1); } return null; } + static public ReconConfig reconstruct(String json) throws Exception { + return ParsingUtilities.mapper.readValue(json, ReconConfig.class); + } + abstract public int getBatchSize(); abstract public String getBriefDescription(Project project, String columnName); diff --git a/main/src/com/google/refine/model/recon/ReconConfigResolver.java b/main/src/com/google/refine/model/recon/ReconConfigResolver.java new file mode 100644 index 000000000..ed8aaffef --- /dev/null +++ b/main/src/com/google/refine/model/recon/ReconConfigResolver.java @@ -0,0 +1,34 @@ +package com.google.refine.model.recon; + +import java.io.IOException; + +import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; +import com.fasterxml.jackson.databind.DatabindContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase; +import com.fasterxml.jackson.databind.type.TypeFactory; + +public class ReconConfigResolver extends TypeIdResolverBase { + + protected TypeFactory factory = TypeFactory.defaultInstance(); + + @Override + public Id getMechanism() { + return Id.NAME; + } + + @Override + public String idFromValue(Object instance) { + return ((ReconConfig)instance).getMode(); + } + + @Override + public String idFromValueAndType(Object instance, Class type) { + return ReconConfig.s_opClassToName.get(type); + } + + @Override + public JavaType typeFromId(DatabindContext context, String id) throws IOException { + return factory.constructSimpleType(ReconConfig.getClassFromMode(id), new JavaType[0]); + } +} diff --git a/main/src/com/google/refine/model/recon/StandardReconConfig.java b/main/src/com/google/refine/model/recon/StandardReconConfig.java index 692e0958e..a8b568feb 100644 --- a/main/src/com/google/refine/model/recon/StandardReconConfig.java +++ b/main/src/com/google/refine/model/recon/StandardReconConfig.java @@ -34,11 +34,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model.recon; import java.io.DataOutputStream; +import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.net.HttpURLConnection; import java.net.URL; -import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -54,6 +54,7 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -82,56 +83,22 @@ public class StandardReconConfig extends ReconConfig { @JsonProperty("propertyID") final public String propertyID; - public ColumnDetail(String columnName, String propertyName, String propertyID) { + @JsonCreator + public ColumnDetail( + @JsonProperty("column") + String columnName, + @JsonProperty("propertyName") + String propertyName, + @JsonProperty("propertyID") + String propertyID) { this.columnName = columnName; this.propertyName = propertyName; this.propertyID = propertyID; } } - static public ReconConfig reconstruct(JSONObject obj) throws Exception { - List columnDetails = null; - if (obj.has("columnDetails")) { - JSONArray columnDetailsA = obj.getJSONArray("columnDetails"); - int l = columnDetailsA.length(); - - columnDetails = new ArrayList(l); - for (int i = 0; i < l; i++) { - JSONObject o = columnDetailsA.getJSONObject(i); - - if (o.has("property")) { // legacy - JSONObject p = o.getJSONObject("property"); - columnDetails.add(new ColumnDetail( - o.getString("column"), - p.has("name") ? p.getString("name") : null, - p.has("id") ? p.getString("id") : null - )); - } else { - columnDetails.add(new ColumnDetail( - o.getString("column"), - o.has("propertyName") ? o.getString("propertyName") : null, - o.has("propertyID") ? o.getString("propertyID") : null - )); - } - } - } else { - columnDetails = new ArrayList(); - } - - JSONObject t = obj.has("type") && !obj.isNull("type") ? obj.getJSONObject("type") : null; - - int limit = obj.has("limit") && !obj.isNull("limit") ? obj.getInt("limit") : 0; - - return new StandardReconConfig( - obj.getString("service"), - obj.has("identifierSpace") ? obj.getString("identifierSpace") : null, - obj.has("schemaSpace") ? obj.getString("schemaSpace") : null, - t == null ? null : t.getString("id"), - t == null ? null : (t.has("name") ? t.getString("name") : null), - obj.getBoolean("autoMatch"), - columnDetails, - limit - ); + static public ReconConfig reconstruct(String json) throws IOException { + return ParsingUtilities.mapper.readValue(json, ReconConfig.class); } static protected class StandardReconJob extends ReconJob { @@ -162,6 +129,25 @@ public class StandardReconConfig extends ReconConfig { @JsonProperty("limit") final private int limit; + @JsonCreator + public StandardReconConfig( + @JsonProperty("service") + String service, + @JsonProperty("identifierSpace") + String identifierSpace, + @JsonProperty("schemaSpace") + String schemaSpace, + @JsonProperty("type") + ReconType type, + @JsonProperty("autoMatch") + boolean autoMatch, + @JsonProperty("columnDetails") + List columnDetails, + @JsonProperty("limit") + int limit) { + this(service, identifierSpace, schemaSpace, type.id, type.name, autoMatch, columnDetails, limit); + } + public StandardReconConfig( String service, String identifierSpace, diff --git a/main/src/com/google/refine/operations/recon/ReconOperation.java b/main/src/com/google/refine/operations/recon/ReconOperation.java index 976b1acb3..612b7d57e 100644 --- a/main/src/com/google/refine/operations/recon/ReconOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconOperation.java @@ -81,7 +81,7 @@ public class ReconOperation extends EngineDependentOperation { return new ReconOperation( EngineConfig.reconstruct(engineConfig), obj.getString("columnName"), - ReconConfig.reconstruct(obj.getJSONObject("config")) + ReconConfig.reconstruct(obj.getJSONObject("config").toString()) ); } diff --git a/main/tests/server/src/com/google/refine/tests/model/ReconTypeTest.java b/main/tests/server/src/com/google/refine/tests/model/ReconTypeTest.java index 9e66b7ca8..e52dcd59d 100644 --- a/main/tests/server/src/com/google/refine/tests/model/ReconTypeTest.java +++ b/main/tests/server/src/com/google/refine/tests/model/ReconTypeTest.java @@ -1,7 +1,6 @@ package com.google.refine.tests.model; import org.json.JSONException; -import org.json.JSONObject; import org.testng.annotations.Test; import com.google.refine.model.ReconType; @@ -11,7 +10,7 @@ public class ReconTypeTest { @Test public void serializeReconType() throws JSONException, Exception { String json = "{\"id\":\"Q7540126\",\"name\":\"headquarters\"}"; - ReconType rt = ReconType.load(new JSONObject(json)); + ReconType rt = ReconType.load(json); TestUtils.isSerializedTo(rt, json); } } diff --git a/main/tests/server/src/com/google/refine/tests/model/recon/StandardReconConfigTests.java b/main/tests/server/src/com/google/refine/tests/model/recon/StandardReconConfigTests.java index 470f1ecfe..41e55d4c4 100644 --- a/main/tests/server/src/com/google/refine/tests/model/recon/StandardReconConfigTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/recon/StandardReconConfigTests.java @@ -2,18 +2,27 @@ package com.google.refine.tests.model.recon; import java.util.ArrayList; -import org.json.JSONObject; import org.slf4j.LoggerFactory; import org.testng.Assert; +import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.refine.model.recon.ReconConfig; import com.google.refine.model.recon.StandardReconConfig; +import com.google.refine.operations.OperationRegistry; +import com.google.refine.operations.recon.ReconOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; public class StandardReconConfigTests extends RefineTest { + + @BeforeMethod + public void registerOperation() { + OperationRegistry.registerOperation(getCoreModule(), "recon", ReconOperation.class); + ReconConfig.registerReconConfig(getCoreModule(), "standard-service", StandardReconConfig.class); + } + @Override @BeforeTest @@ -74,7 +83,7 @@ public class StandardReconConfigTests extends RefineTest { " ],\n" + " \"limit\": 0\n" + " }"; - ReconConfig config = StandardReconConfig.reconstruct(new JSONObject(json)); + ReconConfig config = ReconConfig.reconstruct(json); TestUtils.isSerializedTo(config, json); } } From 599edd374f16961e77c59b26153c0034d003e12d Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 21 Oct 2018 16:36:59 +0100 Subject: [PATCH 045/164] Jackson deserialization for ReconType --- .../com/google/refine/model/ReconType.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/main/src/com/google/refine/model/ReconType.java b/main/src/com/google/refine/model/ReconType.java index ac023719a..65a6d34e9 100644 --- a/main/src/com/google/refine/model/ReconType.java +++ b/main/src/com/google/refine/model/ReconType.java @@ -33,10 +33,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model; -import org.json.JSONObject; +import java.io.IOException; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.refine.util.ParsingUtilities; + /** * This represents a type from the reconciliation @@ -49,20 +52,17 @@ public class ReconType { @JsonProperty("name") public String name; - public ReconType(String id, String name) { + @JsonCreator + public ReconType( + @JsonProperty("id") + String id, + @JsonProperty("name") + String name) { this.id = id; this.name = name; } - static public ReconType load(JSONObject obj) throws Exception { - if (obj == null) { - return null; - } - - ReconType type = new ReconType( - obj.getString("id"), - obj.getString("name") - ); - return type; + static public ReconType load(String json) throws IOException { + return ParsingUtilities.mapper.readValue(json, ReconType.class); } } From af866363ca7a5ff4c782d2506ea5fa42ad1831c0 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 21 Oct 2018 16:37:18 +0100 Subject: [PATCH 046/164] Jackson deserialization for ReconStats --- .../com/google/refine/model/ReconStats.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/main/src/com/google/refine/model/ReconStats.java b/main/src/com/google/refine/model/ReconStats.java index f9b887a19..89650c791 100644 --- a/main/src/com/google/refine/model/ReconStats.java +++ b/main/src/com/google/refine/model/ReconStats.java @@ -36,23 +36,14 @@ package com.google.refine.model; import java.io.IOException; import java.io.Writer; -import org.json.JSONObject; - +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.expr.ExpressionUtils; import com.google.refine.model.Recon.Judgment; import com.google.refine.util.ParsingUtilities; -public class ReconStats { - static public ReconStats load(JSONObject obj) throws Exception { - return new ReconStats( - obj.getInt("nonBlanks"), - obj.getInt("newTopics"), - obj.getInt("matchedTopics") - ); - } - +public class ReconStats { @JsonProperty("nonBlanks") final public int nonBlanks; @JsonProperty("newTopics") @@ -60,7 +51,14 @@ public class ReconStats { @JsonProperty("matchedTopics") final public int matchedTopics; - public ReconStats(int nonBlanks, int newTopics, int matchedTopics) { + @JsonCreator + public ReconStats( + @JsonProperty("nonBlanks") + int nonBlanks, + @JsonProperty("newTopics") + int newTopics, + @JsonProperty("matchedTopics") + int matchedTopics) { this.nonBlanks = nonBlanks; this.newTopics = newTopics; this.matchedTopics = matchedTopics; From ccc8f6470e8aec2c86701b831f8cb2a27d2252b6 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 21 Oct 2018 16:37:35 +0100 Subject: [PATCH 047/164] Jackson deserialization for Column --- main/src/com/google/refine/model/Column.java | 63 ++++++++++---------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/main/src/com/google/refine/model/Column.java b/main/src/com/google/refine/model/Column.java index 171b7eda5..3fee69f4e 100644 --- a/main/src/com/google/refine/model/Column.java +++ b/main/src/com/google/refine/model/Column.java @@ -39,16 +39,15 @@ import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; -import org.apache.commons.lang3.StringUtils; -import org.json.JSONObject; - +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; import com.google.refine.InterProjectModel; import com.google.refine.model.recon.ReconConfig; -import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; import io.frictionlessdata.tableschema.Field; @@ -72,7 +71,12 @@ public class Column { transient protected Map _precomputes; - public Column(int cellIndex, String originalName) { + @JsonCreator + public Column( + @JsonProperty("cellIndex") + int cellIndex, + @JsonProperty("originalName") + String originalName) { _cellIndex = cellIndex; _originalName = _name = originalName; } @@ -87,6 +91,7 @@ public class Column { return _originalName; } + @JsonProperty("name") public void setName(String name) { this._name = name; } @@ -96,6 +101,7 @@ public class Column { return _name; } + @JsonProperty("reconConfig") public void setReconConfig(ReconConfig config) { this._reconConfig = config; } @@ -106,6 +112,7 @@ public class Column { return _reconConfig; } + @JsonProperty("reconStats") public void setReconStats(ReconStats stats) { this._reconStats = stats; } @@ -149,7 +156,7 @@ public class Column { return type; } - + @JsonProperty("type") public void setType(String type) { this.type = type; } @@ -160,7 +167,7 @@ public class Column { return format; } - + @JsonProperty("format") public void setFormat(String format) { this.format = format; } @@ -171,25 +178,38 @@ public class Column { return title; } - + @JsonProperty("title") public void setTitle(String title) { this.title = title; } - @JsonProperty("description") public String getDescription() { return description; } - + @JsonProperty("description") public void setDescription(String description) { this.description = description; } @JsonProperty("constraints") public String getConstraintsString() { - return (new JSONObject(constraints)).toString(); + try { + return ParsingUtilities.mapper.writeValueAsString(constraints); + } catch (JsonProcessingException e) { + e.printStackTrace(); + return "{}"; + } + } + + @JsonProperty("constraints") + public void setConstraintsJson(String json) { + try { + setConstraints(ParsingUtilities.mapper.readValue(json, new TypeReference>() {})); + } catch (IOException e) { + e.printStackTrace(); + } } public Map getConstraints() { @@ -210,26 +230,7 @@ public class Column { } static public Column load(String s) throws Exception { - JSONObject obj = ParsingUtilities.evaluateJsonStringToObject(s); - Column column = new Column(obj.getInt("cellIndex"), obj.getString("originalName")); - - column._name = obj.getString("name"); - column.type = JSONUtilities.getString(obj, Field.JSON_KEY_TYPE, StringUtils.EMPTY); - column.format = JSONUtilities.getString(obj, Field.JSON_KEY_FORMAT, StringUtils.EMPTY); - column.title = JSONUtilities.getString(obj, Field.JSON_KEY_TITLE, StringUtils.EMPTY); - column.description = JSONUtilities.getString(obj, Field.JSON_KEY_DESCRIPTION, StringUtils.EMPTY); - if (obj.has(Field.JSON_KEY_CONSTRAINTS)) { - column.constraints = new JSONObject(obj.getString(Field.JSON_KEY_CONSTRAINTS)).toMap(); - } - - if (obj.has("reconConfig")) { - column._reconConfig = ReconConfig.reconstruct(obj.getJSONObject("reconConfig")); - } - if (obj.has("reconStats")) { - column._reconStats = ReconStats.load(obj.getJSONObject("reconStats")); - } - - return column; + return ParsingUtilities.mapper.readValue(s, Column.class); } @Override From 8758ed2cffd3be146fc964552545a1cf1bee2706 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 21 Oct 2018 16:37:51 +0100 Subject: [PATCH 048/164] Jackson deserialization for ReconCandidate --- .../google/refine/model/ReconCandidate.java | 24 ++++++++++++------- .../model/recon/DataExtensionReconConfig.java | 18 -------------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/main/src/com/google/refine/model/ReconCandidate.java b/main/src/com/google/refine/model/ReconCandidate.java index 6b2e86f3a..d81e0f760 100644 --- a/main/src/com/google/refine/model/ReconCandidate.java +++ b/main/src/com/google/refine/model/ReconCandidate.java @@ -37,12 +37,14 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.google.refine.expr.HasFields; +import com.google.refine.util.ParsingUtilities; public class ReconCandidate implements HasFields { @JsonProperty("id") @@ -54,10 +56,19 @@ public class ReconCandidate implements HasFields { @JsonProperty("score") final public double score; - public ReconCandidate(String topicID, String topicName, String[] typeIDs, double score) { + @JsonCreator + public ReconCandidate( + @JsonProperty("id") + String topicID, + @JsonProperty("name") + String topicName, + @JsonProperty("types") + String[] typeIDs, + @JsonProperty("score") + double score) { this.id = topicID; this.name = topicName; - this.types = typeIDs; + this.types = typeIDs == null ? new String[0] : typeIDs; this.score = score; } @@ -81,15 +92,10 @@ public class ReconCandidate implements HasFields { } static public ReconCandidate loadStreaming(String s) throws Exception { - JsonFactory jsonFactory = new JsonFactory(); - JsonParser jp = jsonFactory.createJsonParser(s); - - if (jp.nextToken() != JsonToken.START_OBJECT) { - return null; - } - return loadStreaming(jp); + return ParsingUtilities.mapper.readValue(s, ReconCandidate.class); } + @Deprecated static public ReconCandidate loadStreaming(JsonParser jp) throws Exception { JsonToken t = jp.getCurrentToken(); if (t == JsonToken.VALUE_NULL || t != JsonToken.START_OBJECT) { diff --git a/main/src/com/google/refine/model/recon/DataExtensionReconConfig.java b/main/src/com/google/refine/model/recon/DataExtensionReconConfig.java index 29c8c3590..7cf6dbce0 100644 --- a/main/src/com/google/refine/model/recon/DataExtensionReconConfig.java +++ b/main/src/com/google/refine/model/recon/DataExtensionReconConfig.java @@ -36,8 +36,6 @@ package com.google.refine.model.recon; import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; - import com.google.refine.model.Cell; import com.google.refine.model.Project; import com.google.refine.model.Recon; @@ -49,22 +47,6 @@ public class DataExtensionReconConfig extends StandardReconConfig { private final static String WARN = "Not implemented"; - static public ReconConfig reconstruct(JSONObject obj) throws Exception { - JSONObject type = obj.getJSONObject("type"); - - ReconType typ = null; - if(obj.has("id")) { - typ = new ReconType(obj.getString("id"), - obj.has("name") ? obj.getString("name") : obj.getString("id")); - } - - return new DataExtensionReconConfig( - obj.getString("service"), - obj.has("identifierSpace") ? obj.getString("identifierSpace") : null, - obj.has("schemaSpace") ? obj.getString("schemaSpace") : null, - typ); - } - public DataExtensionReconConfig( String service, String identifierSpace, From adb2e13874d28f005a70ce9b82700400ca8f9032 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 21 Oct 2018 17:28:43 +0100 Subject: [PATCH 049/164] Jackson deserialization for Cell --- main/src/com/google/refine/model/Cell.java | 40 +++++++++++++++++----- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/main/src/com/google/refine/model/Cell.java b/main/src/com/google/refine/model/Cell.java index 33d71b922..43175da11 100644 --- a/main/src/com/google/refine/model/Cell.java +++ b/main/src/com/google/refine/model/Cell.java @@ -42,6 +42,8 @@ import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.util.Properties; +import com.fasterxml.jackson.annotation.JacksonInject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -49,6 +51,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.InjectableValues; import com.google.refine.expr.EvalError; import com.google.refine.expr.ExpressionUtils; @@ -159,16 +162,37 @@ public class Cell implements HasFields { } static public Cell loadStreaming(String s, Pool pool) throws Exception { - JsonFactory jsonFactory = new JsonFactory(); - JsonParser jp = jsonFactory.createJsonParser(s); - - if (jp.nextToken() != JsonToken.START_OBJECT) { - return null; - } - - return loadStreaming(jp, pool); + InjectableValues injectableValues = new InjectableValues.Std() + .addValue("pool", pool); + return ParsingUtilities.mapper.setInjectableValues(injectableValues) + .readValue(s, Cell.class); } + @JsonCreator + static public Cell deserialize( + @JsonProperty("v") + Object value, + @JsonProperty("t") + String type, + @JsonProperty("r") + String reconId, + @JsonProperty("e") + String error, + @JacksonInject("pool") + Pool pool) { + Recon recon = null; + if(reconId != null) { + recon = pool.getRecon(reconId); + } + if (type != null && "date".equals(type)) { + value = ParsingUtilities.stringToDate((String) value); + } + if (error != null) { + value = new EvalError(error); + } + return new Cell((Serializable)value, recon); + } + static public Cell loadStreaming(JsonParser jp, Pool pool) throws Exception { JsonToken t = jp.getCurrentToken(); if (t == JsonToken.VALUE_NULL || t != JsonToken.START_OBJECT) { From 487f6bc1314fb8a0a134eb0b34a07380ee0b14d6 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 21 Oct 2018 17:45:05 +0100 Subject: [PATCH 050/164] Jackson deserialization for Row --- main/src/com/google/refine/model/Cell.java | 57 ------------------- main/src/com/google/refine/model/Row.java | 54 +++++++----------- .../google/refine/tests/model/CellTests.java | 6 +- 3 files changed, 22 insertions(+), 95 deletions(-) diff --git a/main/src/com/google/refine/model/Cell.java b/main/src/com/google/refine/model/Cell.java index 43175da11..61394c809 100644 --- a/main/src/com/google/refine/model/Cell.java +++ b/main/src/com/google/refine/model/Cell.java @@ -48,9 +48,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.InjectableValues; import com.google.refine.expr.EvalError; @@ -192,60 +189,6 @@ public class Cell implements HasFields { } return new Cell((Serializable)value, recon); } - - static public Cell loadStreaming(JsonParser jp, Pool pool) throws Exception { - JsonToken t = jp.getCurrentToken(); - if (t == JsonToken.VALUE_NULL || t != JsonToken.START_OBJECT) { - return null; - } - - Serializable value = null; - String type = null; - Recon recon = null; - - while (jp.nextToken() != JsonToken.END_OBJECT) { - String fieldName = jp.getCurrentName(); - jp.nextToken(); - - if ("r".equals(fieldName)) { - if (jp.getCurrentToken() == JsonToken.VALUE_STRING) { - String reconID = jp.getText(); - - recon = pool.getRecon(reconID); - } else { - // legacy - recon = Recon.loadStreaming(jp, pool); - } - } else if ("e".equals(fieldName)) { - value = new EvalError(jp.getText()); - } else if ("v".equals(fieldName)) { - JsonToken token = jp.getCurrentToken(); - - if (token == JsonToken.VALUE_STRING) { - value = jp.getText(); - } else if (token == JsonToken.VALUE_NUMBER_INT) { - value = jp.getLongValue(); - } else if (token == JsonToken.VALUE_NUMBER_FLOAT) { - value = jp.getDoubleValue(); - } else if (token == JsonToken.VALUE_TRUE) { - value = true; - } else if (token == JsonToken.VALUE_FALSE) { - value = false; - } - } else if ("t".equals(fieldName)) { - type = jp.getText(); - } - } - - if (value != null) { - if (type != null && "date".equals(type)) { - value = ParsingUtilities.stringToDate((String) value); - } - return new Cell(value, recon); - } else { - return null; - } - } @Override public String toString() { diff --git a/main/src/com/google/refine/model/Row.java b/main/src/com/google/refine/model/Row.java index bfa5f7db6..846271f41 100644 --- a/main/src/com/google/refine/model/Row.java +++ b/main/src/com/google/refine/model/Row.java @@ -36,14 +36,17 @@ package com.google.refine.model; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Properties; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.InjectableValues; import com.google.refine.expr.CellTuple; import com.google.refine.expr.HasFields; @@ -206,40 +209,25 @@ public class Row implements HasFields { loadStreaming(s, pool); } + @JsonCreator + static public Row deserialize( + @JsonProperty(STARRED) + boolean starred, + @JsonProperty(FLAGGED) + boolean flagged, + @JsonProperty("cells") + List cells) { + if (cells == null) { + cells = new ArrayList<>(); + } + return new Row(cells, flagged, starred); + } + static public Row loadStreaming(String s, Pool pool) throws Exception { - JsonFactory jsonFactory = new JsonFactory(); - JsonParser jp = jsonFactory.createJsonParser(s); - - if (jp.nextToken() != JsonToken.START_OBJECT) { - return null; - } - - List cells = new ArrayList(); - boolean starred = false; - boolean flagged = false; - - while (jp.nextToken() != JsonToken.END_OBJECT) { - String fieldName = jp.getCurrentName(); - jp.nextToken(); - - if (STARRED.equals(fieldName)) { - starred = jp.getBooleanValue(); - } else if (FLAGGED.equals(fieldName)) { - flagged = jp.getBooleanValue(); - } else if ("cells".equals(fieldName)) { - if (jp.getCurrentToken() != JsonToken.START_ARRAY) { - return null; - } - - while (jp.nextToken() != JsonToken.END_ARRAY) { - Cell cell = Cell.loadStreaming(jp, pool); - - cells.add(cell); - } - } - } - - return (cells.size() > 0) ? new Row(cells, flagged, starred) : new Row(0); + InjectableValues injectableValues = new InjectableValues.Std() + .addValue("pool", pool); + return ParsingUtilities.mapper.setInjectableValues(injectableValues) + .readValue(s, Row.class); } @Override diff --git a/main/tests/server/src/com/google/refine/tests/model/CellTests.java b/main/tests/server/src/com/google/refine/tests/model/CellTests.java index 1083cb772..ded99c68b 100644 --- a/main/tests/server/src/com/google/refine/tests/model/CellTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/CellTests.java @@ -1,14 +1,10 @@ package com.google.refine.tests.model; -import org.testng.annotations.Test; - import static org.junit.Assert.assertNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import java.util.Properties; +import org.testng.annotations.Test; import com.google.refine.model.Cell; import com.google.refine.model.Recon; From bbf6dcd767950802dd9781c22afa5806fe54a394 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 21 Oct 2018 17:50:16 +0100 Subject: [PATCH 051/164] Jackson deserialization for ColumnGroup --- .../com/google/refine/model/ColumnGroup.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/main/src/com/google/refine/model/ColumnGroup.java b/main/src/com/google/refine/model/ColumnGroup.java index c8a261af2..c6059d4e9 100644 --- a/main/src/com/google/refine/model/ColumnGroup.java +++ b/main/src/com/google/refine/model/ColumnGroup.java @@ -38,8 +38,7 @@ import java.io.Writer; import java.util.LinkedList; import java.util.List; -import org.json.JSONObject; - +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; @@ -56,7 +55,14 @@ public class ColumnGroup { transient public ColumnGroup parentGroup; transient public List subgroups; - public ColumnGroup(int startColumnIndex, int columnSpan, int keyColumnIndex) { + @JsonCreator + public ColumnGroup( + @JsonProperty("startColumnIndex") + int startColumnIndex, + @JsonProperty("columnSpan") + int columnSpan, + @JsonProperty("keyColumnIndex") + int keyColumnIndex) { this.startColumnIndex = startColumnIndex; this.columnSpan = columnSpan; this.keyColumnIndex = keyColumnIndex; @@ -98,14 +104,8 @@ public class ColumnGroup { } } - static public ColumnGroup load(String s) throws Exception { - JSONObject obj = ParsingUtilities.evaluateJsonStringToObject(s); - - return new ColumnGroup( - obj.getInt("startColumnIndex"), - obj.getInt("columnSpan"), - obj.getInt("keyColumnIndex") - ); + static public ColumnGroup load(String s) throws IOException { + return ParsingUtilities.mapper.readValue(s, ColumnGroup.class); } protected void internalInitialize() { From ba7879621db25f829d6d6cda677ad7ed9fe84b11 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 21 Oct 2018 17:53:19 +0100 Subject: [PATCH 052/164] Jackson deserialization for Project --- main/src/com/google/refine/model/Project.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/main/src/com/google/refine/model/Project.java b/main/src/com/google/refine/model/Project.java index 113e591d9..fee610280 100644 --- a/main/src/com/google/refine/model/Project.java +++ b/main/src/com/google/refine/model/Project.java @@ -40,7 +40,6 @@ import java.io.LineNumberReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; -import java.lang.reflect.Method; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.HashMap; @@ -48,7 +47,6 @@ import java.util.List; import java.util.Map; import java.util.Properties; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -217,13 +215,10 @@ public class Project { Class klass = s_overlayModelClasses.get(modelName); try { - Method loadMethod = klass.getMethod("load", Project.class, JSONObject.class); - JSONObject obj = ParsingUtilities.evaluateJsonStringToObject(value); - - OverlayModel overlayModel = (OverlayModel) loadMethod.invoke(null, project, obj); + OverlayModel overlayModel = ParsingUtilities.mapper.readValue(value, klass); project.overlayModels.put(modelName, overlayModel); - } catch (Exception e) { + } catch (IOException e) { logger.error("Failed to load overlay model " + modelName); } } From d4bdd37bda7ad99049821c088356b091dddb3f32 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 21 Oct 2018 18:35:23 +0100 Subject: [PATCH 053/164] Jackson deserialization for Recon --- main/src/com/google/refine/model/Recon.java | 159 ++++++------------ .../google/refine/model/ReconCandidate.java | 1 - main/src/com/google/refine/model/Row.java | 4 - .../refine/model/changes/MassReconChange.java | 2 +- main/src/com/google/refine/util/Pool.java | 2 +- .../google/refine/tests/model/CellTests.java | 2 +- .../google/refine/tests/model/ReconTests.java | 6 +- .../google/refine/tests/model/RowTests.java | 2 +- 8 files changed, 59 insertions(+), 119 deletions(-) diff --git a/main/src/com/google/refine/model/Recon.java b/main/src/com/google/refine/model/Recon.java index f96125ed3..caa1373e6 100644 --- a/main/src/com/google/refine/model/Recon.java +++ b/main/src/com/google/refine/model/Recon.java @@ -46,13 +46,10 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonView; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; import com.google.refine.expr.HasFields; import com.google.refine.util.JsonViews; -import com.google.refine.util.Pool; +import com.google.refine.util.ParsingUtilities; @JsonFilter("reconCandidateFilter") public class Recon implements HasFields { @@ -111,20 +108,32 @@ public class Recon implements HasFields { s_featureMap.put("nameWordDistance", Feature_nameWordDistance); } + @JsonIgnore final public long id; + @JsonIgnore public String service = "unknown"; + @JsonIgnore public String identifierSpace = null; + @JsonIgnore public String schemaSpace = null; + @JsonIgnore public Object[] features = new Object[Feature_max]; + @JsonIgnore public List candidates; + @JsonIgnore public Judgment judgment = Judgment.None; + @JsonIgnore public String judgmentAction = "unknown"; + @JsonIgnore public long judgmentHistoryEntry; + @JsonIgnore public int judgmentBatchSize = 0; + @JsonIgnore public ReconCandidate match = null; + @JsonIgnore public int matchRank = -1; @Deprecated @@ -362,110 +371,46 @@ public class Recon implements HasFields { return null; } - static public Recon loadStreaming(String s, Pool pool) throws Exception { - JsonFactory jsonFactory = new JsonFactory(); - JsonParser jp = jsonFactory.createJsonParser(s); - - if (jp.nextToken() != JsonToken.START_OBJECT) { - return null; - } - return loadStreaming(jp, pool); + static public Recon loadStreaming(String s) throws Exception { + return ParsingUtilities.mapper.readValue(s, Recon.class); } - static public Recon loadStreaming(JsonParser jp, Pool pool) throws Exception { - JsonToken t = jp.getCurrentToken(); - if (t == JsonToken.VALUE_NULL || t != JsonToken.START_OBJECT) { - return null; - } - - Recon recon = null; - long id = -1; - long judgmentHistoryEntry = -1; - - while (jp.nextToken() != JsonToken.END_OBJECT) { - String fieldName = jp.getCurrentName(); - jp.nextToken(); - - if ("id".equals(fieldName)) { - id = jp.getLongValue(); - } else if ("judgmentHistoryEntry".equals(fieldName)) { - judgmentHistoryEntry = jp.getLongValue(); - if (recon != null) { - recon.judgmentHistoryEntry = judgmentHistoryEntry; - } - } else { - if (recon == null) { - recon = new Recon(id, judgmentHistoryEntry); - } - - if ("j".equals(fieldName)) { - recon.judgment = stringToJudgment(jp.getText()); - } else if ("m".equals(fieldName)) { - if (jp.getCurrentToken() == JsonToken.VALUE_STRING) { - // legacy case - String candidateID = jp.getText(); - recon.match = pool.getReconCandidate(candidateID); - } else { - recon.match = ReconCandidate.loadStreaming(jp); - } - } else if ("f".equals(fieldName)) { - if (jp.getCurrentToken() != JsonToken.START_ARRAY) { - return null; - } - - int feature = 0; - while (jp.nextToken() != JsonToken.END_ARRAY) { - if (feature < recon.features.length) { - JsonToken token = jp.getCurrentToken(); - if (token == JsonToken.VALUE_STRING) { - recon.features[feature++] = jp.getText(); - } else if (token == JsonToken.VALUE_NUMBER_INT) { - recon.features[feature++] = jp.getLongValue(); - } else if (token == JsonToken.VALUE_NUMBER_FLOAT) { - recon.features[feature++] = jp.getDoubleValue(); - } else if (token == JsonToken.VALUE_FALSE) { - recon.features[feature++] = false; - } else if (token == JsonToken.VALUE_TRUE) { - recon.features[feature++] = true; - } - } - } - } else if ("c".equals(fieldName)) { - if (jp.getCurrentToken() != JsonToken.START_ARRAY) { - return null; - } - - while (jp.nextToken() != JsonToken.END_ARRAY) { - if (jp.getCurrentToken() == JsonToken.VALUE_STRING) { - // legacy case - String candidateID = jp.getText(); - recon.addCandidate(pool.getReconCandidate(candidateID)); - } else { - recon.addCandidate(ReconCandidate.loadStreaming(jp)); - } - } - } else if ("service".equals(fieldName)) { - recon.service = jp.getText(); - } else if ("identifierSpace".equals(fieldName)) { - recon.identifierSpace = jp.getText(); - if ("null".equals(recon.identifierSpace)) { - recon.identifierSpace = FREEBASE_IDENTIFIER_SPACE; - } - } else if ("schemaSpace".equals(fieldName)) { - recon.schemaSpace = jp.getText(); - if ("null".equals(recon.schemaSpace)) { - recon.schemaSpace = FREEBASE_SCHEMA_SPACE; - } - } else if ("judgmentAction".equals(fieldName)) { - recon.judgmentAction = jp.getText(); - } else if ("judgmentBatchSize".equals(fieldName)) { - recon.judgmentBatchSize = jp.getIntValue(); - } else if ("matchRank".equals(fieldName)) { - recon.matchRank = jp.getIntValue(); - } - } - } - - return recon; + public Recon( + @JsonProperty("id") + long id, + @JsonProperty("judgmentHistoryEntry") + long judgmentHistoryEntry, + @JsonProperty("j") + Judgment judgment, + @JsonProperty("m") + ReconCandidate match, + @JsonProperty("f") + Object[] features, + @JsonProperty("c") + List candidates, + @JsonProperty("service") + String service, + @JsonProperty("identifierSpace") + String identifierSpace, + @JsonProperty("schemaSpace") + String schemaSpace, + @JsonProperty("judgmentAction") + String judgmentAction, + @JsonProperty("judgmentBatchSize") + Integer judgmentBatchSize, + @JsonProperty("matchRank") + Integer matchRank) { + this.id = id; + this.judgmentHistoryEntry = judgmentHistoryEntry; + this.judgment = judgment != null ? judgment : Judgment.None; + this.match = match; + this.features = features != null ? features : new Object[Feature_max]; + this.candidates = candidates != null ? candidates : new ArrayList<>(); + this.service = service != null ? service : "unknown"; + this.identifierSpace = identifierSpace; + this.schemaSpace = schemaSpace; + this.judgmentAction = judgmentAction != null ? judgmentAction : "unknown"; + this.judgmentBatchSize = judgmentBatchSize != null ? judgmentBatchSize : 0; + this.matchRank = matchRank != null ? matchRank : -1; } } diff --git a/main/src/com/google/refine/model/ReconCandidate.java b/main/src/com/google/refine/model/ReconCandidate.java index d81e0f760..6e2a1e3da 100644 --- a/main/src/com/google/refine/model/ReconCandidate.java +++ b/main/src/com/google/refine/model/ReconCandidate.java @@ -39,7 +39,6 @@ import java.util.Properties; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; diff --git a/main/src/com/google/refine/model/Row.java b/main/src/com/google/refine/model/Row.java index 846271f41..3e161f3f7 100644 --- a/main/src/com/google/refine/model/Row.java +++ b/main/src/com/google/refine/model/Row.java @@ -36,16 +36,12 @@ package com.google.refine.model; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Properties; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.InjectableValues; import com.google.refine.expr.CellTuple; diff --git a/main/src/com/google/refine/model/changes/MassReconChange.java b/main/src/com/google/refine/model/changes/MassReconChange.java index 41869af00..3b5541699 100644 --- a/main/src/com/google/refine/model/changes/MassReconChange.java +++ b/main/src/com/google/refine/model/changes/MassReconChange.java @@ -140,7 +140,7 @@ public class MassReconChange implements Change { for (int i = 0; i < count; i++) { String line = reader.readLine(); - Recon recon = Recon.loadStreaming(line, pool); + Recon recon = Recon.loadStreaming(line); recons.put(recon.id, recon); } diff --git a/main/src/com/google/refine/util/Pool.java b/main/src/com/google/refine/util/Pool.java index ddb9ea39e..d91ca0f9a 100644 --- a/main/src/com/google/refine/util/Pool.java +++ b/main/src/com/google/refine/util/Pool.java @@ -145,7 +145,7 @@ public class Pool { for (int i = 0; i < count; i++) { line = reader2.readLine(); if (line != null) { - Recon recon = Recon.loadStreaming(line, this); + Recon recon = Recon.loadStreaming(line); if (recon != null) { pool(recon); } diff --git a/main/tests/server/src/com/google/refine/tests/model/CellTests.java b/main/tests/server/src/com/google/refine/tests/model/CellTests.java index ded99c68b..bbe58fb2e 100644 --- a/main/tests/server/src/com/google/refine/tests/model/CellTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/CellTests.java @@ -28,7 +28,7 @@ public class CellTests { @Test public void serializeCellWithRecon() throws Exception { - recon = Recon.loadStreaming(reconJson, pool); + recon = Recon.loadStreaming(reconJson); when(pool.getRecon("1533649346002675326")).thenReturn(recon); String json = "{\"v\":\"http://www.wikidata.org/entity/Q41522540\",\"r\":\"1533649346002675326\"}"; diff --git a/main/tests/server/src/com/google/refine/tests/model/ReconTests.java b/main/tests/server/src/com/google/refine/tests/model/ReconTests.java index fbfcfbfa0..dda2ce67c 100644 --- a/main/tests/server/src/com/google/refine/tests/model/ReconTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/ReconTests.java @@ -32,13 +32,13 @@ public class ReconTests { @Test public void serializeReconSaveMode() throws Exception { - Recon r = Recon.loadStreaming(fullJson, null); + Recon r = Recon.loadStreaming(fullJson); TestUtils.isSerializedTo(r, fullJson, true); } @Test public void serializeReconViewMode() throws Exception { - Recon r = Recon.loadStreaming(fullJson, null); + Recon r = Recon.loadStreaming(fullJson); String shortJson = "{\"id\":1533651559492945033," + "\"service\":\"https://tools.wmflabs.org/openrefine-wikidata/en/api\"," + "\"identifierSpace\":\"http://www.wikidata.org/entity/\"," @@ -66,7 +66,7 @@ public class ReconTests { + " {\"id\":\"Q30284245\",\"name\":\"Baylor College of Medicine Children\\u2019s Foundation\",\"score\":48.57142857142858,\"types\":[\"Q163740\"]}" + "]" + "}"; - Recon r = Recon.loadStreaming(fullJson, null); + Recon r = Recon.loadStreaming(fullJson); r.match = null; r.judgment = Judgment.None; TestUtils.isSerializedTo(r, json); diff --git a/main/tests/server/src/com/google/refine/tests/model/RowTests.java b/main/tests/server/src/com/google/refine/tests/model/RowTests.java index 5241be71e..4108ccfc8 100644 --- a/main/tests/server/src/com/google/refine/tests/model/RowTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/RowTests.java @@ -136,7 +136,7 @@ public class RowTests extends RefineTest { + "\"c\":[{\"id\":\"Q551479\",\"name\":\"La Monnaie\",\"score\":100,\"types\":[\"Q153562\"]}]," + "\"f\":[false,false,34,0],\"judgmentAction\":\"auto\",\"judgmentBatchSize\":1,\"matchRank\":0}"; Pool pool = mock(Pool.class); - Recon recon = Recon.loadStreaming(reconJson, pool); + Recon recon = Recon.loadStreaming(reconJson); when(pool.getRecon("1533649346002675326")).thenReturn(recon); String json = "{\"flagged\":false," From 9c58b8f51f893fe7113ef933ef4c7a2b69d21a04 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 21 Oct 2018 18:54:06 +0100 Subject: [PATCH 054/164] Fix constraints initialization --- main/src/com/google/refine/model/Column.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/src/com/google/refine/model/Column.java b/main/src/com/google/refine/model/Column.java index 3fee69f4e..29f0d52e0 100644 --- a/main/src/com/google/refine/model/Column.java +++ b/main/src/com/google/refine/model/Column.java @@ -36,6 +36,7 @@ package com.google.refine.model; import java.io.IOException; import java.io.Writer; import java.lang.reflect.Method; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -67,7 +68,7 @@ public class Column { private String format = Field.FIELD_FORMAT_DEFAULT; private String title = ""; private String description = ""; - private Map constraints = null; + private Map constraints = Collections.emptyMap(); transient protected Map _precomputes; From 121dd76fa1c3b8f10eb05547f5e39406c21b60eb Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 21 Oct 2018 19:25:34 +0100 Subject: [PATCH 055/164] Jackson deserialization for DecoratedValue --- main/src/com/google/refine/browsing/DecoratedValue.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/main/src/com/google/refine/browsing/DecoratedValue.java b/main/src/com/google/refine/browsing/DecoratedValue.java index fc8ef95e7..67aa8a09d 100644 --- a/main/src/com/google/refine/browsing/DecoratedValue.java +++ b/main/src/com/google/refine/browsing/DecoratedValue.java @@ -35,6 +35,7 @@ package com.google.refine.browsing; import java.time.OffsetDateTime; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.util.StringUtils; @@ -52,7 +53,12 @@ public class DecoratedValue { @JsonProperty("l") final public String label; - public DecoratedValue(Object value, String label) { + @JsonCreator + public DecoratedValue( + @JsonProperty("v") + Object value, + @JsonProperty("l") + String label) { if (value instanceof OffsetDateTime) { this.value = StringUtils.toString(value); } else { From 39498233fba580ee46fa09c1206fe7c9667ddb3d Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 21 Oct 2018 19:26:12 +0100 Subject: [PATCH 056/164] Jackson deserialization for ListFacetConfig --- .../google/refine/browsing/facets/ListFacet.java | 7 +++++++ .../tests/browsing/facets/ListFacetTests.java | 16 ++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/main/src/com/google/refine/browsing/facets/ListFacet.java b/main/src/com/google/refine/browsing/facets/ListFacet.java index 521af7858..768b287a1 100644 --- a/main/src/com/google/refine/browsing/facets/ListFacet.java +++ b/main/src/com/google/refine/browsing/facets/ListFacet.java @@ -118,6 +118,13 @@ public class ListFacet implements Facet { .collect(Collectors.toList()); } + @JsonProperty("selection") + public void setSelection(List wrapped) { + selection = wrapped.stream() + .map(e -> e.value) + .collect(Collectors.toList()); + } + @Override public void initializeFromJSON(JSONObject o) { name = o.getString("name"); diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java index 92a77bf63..f462f4710 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java @@ -1,14 +1,20 @@ package com.google.refine.tests.browsing.facets; +import java.io.IOException; + import org.json.JSONObject; import org.testng.annotations.Test; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.facets.Facet; import com.google.refine.browsing.facets.ListFacet.ListFacetConfig; import com.google.refine.model.Project; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ListFacetTests extends RefineTest { @@ -66,14 +72,13 @@ public class ListFacetTests extends RefineTest { } @Test - public void serializeListFacet() { + public void serializeListFacet() throws JsonParseException, JsonMappingException, IOException { Project project = createCSVProject("Column A\n" + "foo\n" + "bar\n"); Engine engine = new Engine(project); - ListFacetConfig facetConfig = new ListFacetConfig(); - facetConfig.initializeFromJSON(new JSONObject(jsonConfig)); + ListFacetConfig facetConfig = ParsingUtilities.mapper.readValue(jsonConfig, ListFacetConfig.class); Facet facet = facetConfig.apply(project); facet.computeChoices(project, engine.getAllFilteredRows()); @@ -82,13 +87,12 @@ public class ListFacetTests extends RefineTest { } @Test - public void serializeListFacetWithError() { + public void serializeListFacetWithError() throws JsonParseException, JsonMappingException, IOException { Project project = createCSVProject("other column\n" + "foo\n" + "bar\n"); - ListFacetConfig facetConfig = new ListFacetConfig(); - facetConfig.initializeFromJSON(new JSONObject(jsonConfig)); + ListFacetConfig facetConfig = ParsingUtilities.mapper.readValue(jsonConfig, ListFacetConfig.class); Facet facet = facetConfig.apply(project); TestUtils.isSerializedTo(facet, jsonFacetError); } From d8bc841daed5f1d2d7425abeb216608eec9281af Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sun, 21 Oct 2018 19:57:13 +0100 Subject: [PATCH 057/164] Jackson deserialization for RangeFacetConfig --- .../refine/browsing/facets/RangeFacet.java | 35 ++++++++++++++++++- .../browsing/facets/RangeFacetTests.java | 17 +++++---- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/main/src/com/google/refine/browsing/facets/RangeFacet.java b/main/src/com/google/refine/browsing/facets/RangeFacet.java index ce0c68161..0915c4f2b 100644 --- a/main/src/com/google/refine/browsing/facets/RangeFacet.java +++ b/main/src/com/google/refine/browsing/facets/RangeFacet.java @@ -35,6 +35,7 @@ package com.google.refine.browsing.facets; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -92,6 +93,38 @@ public class RangeFacet implements Facet { protected boolean _selected; // false if we're certain that all rows will match // and there isn't any filtering to do + @JsonCreator + public RangeFacetConfig( + @JsonProperty("name") + String name, + @JsonProperty("expression") + String expression, + @JsonProperty("columnName") + String columnName, + @JsonProperty(FROM) + Double from, + @JsonProperty(TO) + Double to, + @JsonProperty("selectNumeric") + Boolean selectNumeric, + @JsonProperty("selectNonNumeric") + Boolean selectNonNumeric, + @JsonProperty("selectBlank") + Boolean selectBlank, + @JsonProperty("selectError") + Boolean selectError) { + _name = name; + _expression = expression; + _columnName = columnName; + _from = from == null ? 0 : from; + _to = to == null ? 0 : to; + _selectNumeric = selectNumeric == null ? true : selectNumeric; + _selectNonNumeric = selectNonNumeric == null ? true : selectNonNumeric; + _selectBlank = selectBlank == null ? true : selectBlank; + _selectError = selectError == null ? true : selectError; + _selected = !_selectNumeric || !_selectNonNumeric || !_selectBlank || !_selectError || from != null || to != null; + } + @Override public void initializeFromJSON(JSONObject o) { _name = o.getString("name"); @@ -124,7 +157,7 @@ public class RangeFacet implements Facet { return "range"; } } - RangeFacetConfig _config = new RangeFacetConfig(); + RangeFacetConfig _config = null; /* * Derived configuration data diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/RangeFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/RangeFacetTests.java index 6ad39158d..21374439d 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/RangeFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/RangeFacetTests.java @@ -1,8 +1,12 @@ package com.google.refine.tests.browsing.facets; -import org.json.JSONObject; +import java.io.IOException; + import org.testng.annotations.Test; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.facets.RangeFacet; import com.google.refine.browsing.facets.RangeFacet.RangeFacetConfig; @@ -10,6 +14,7 @@ import com.google.refine.model.Cell; import com.google.refine.model.Project; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class RangeFacetTests extends RefineTest { public static String configJson = "{\n" + @@ -46,14 +51,13 @@ public class RangeFacetTests extends RefineTest { + "\"errorCount\":0}"; @Test - public void serializeRangeFacetConfig() { - RangeFacetConfig config = new RangeFacetConfig(); - config.initializeFromJSON(new JSONObject(configJson)); + public void serializeRangeFacetConfig() throws JsonParseException, JsonMappingException, IOException { + RangeFacetConfig config = ParsingUtilities.mapper.readValue(configJson, RangeFacetConfig.class); TestUtils.isSerializedTo(config, configJson); } @Test - public void serializeRangeFacet() { + public void serializeRangeFacet() throws JsonParseException, JsonMappingException, IOException { Project project = createCSVProject("my column\n" + "89.2\n" + "-45.9\n" @@ -63,8 +67,7 @@ public class RangeFacetTests extends RefineTest { project.rows.get(1).cells.set(0, new Cell(-45.9, null)); project.rows.get(3).cells.set(0, new Cell(0.4, null)); Engine engine = new Engine(project); - RangeFacetConfig config = new RangeFacetConfig(); - config.initializeFromJSON(new JSONObject(configJson)); + RangeFacetConfig config = ParsingUtilities.mapper.readValue(configJson, RangeFacetConfig.class); RangeFacet facet = config.apply(project); facet.computeChoices(project, engine.getAllFilteredRows()); TestUtils.isSerializedTo(facet, facetJson); From e11145ce0d7463590a9e7f683e1f4858c6bfa7d0 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 09:29:16 +0100 Subject: [PATCH 058/164] Jackson deserialization for ScatterplotFacetConfig --- .../google/refine/browsing/facets/ScatterplotFacet.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java b/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java index 202a04606..5d5685b55 100644 --- a/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java +++ b/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java @@ -124,8 +124,11 @@ public class ScatterplotFacet implements Facet { @JsonProperty(TO_Y) protected double to_y; - protected boolean selected; // false if we're certain that all rows will match + // false if we're certain that all rows will match // and there isn't any filtering to do + protected boolean isSelected() { + return from_x > 0 || to_x < 1 || from_y > 0 || to_y < 1; + } @JsonProperty(DIM_X) public String getDimX() { @@ -154,7 +157,6 @@ public class ScatterplotFacet implements Facet { if (o.has(FROM_X) && o.has(TO_X)) { from_x = o.getDouble(FROM_X); to_x = o.getDouble(TO_X); - selected = true; } else { from_x = 0; to_x = 1; @@ -164,7 +166,6 @@ public class ScatterplotFacet implements Facet { if (o.has(FROM_Y) && o.has(TO_Y)) { from_y = o.getDouble(FROM_Y); to_y = o.getDouble(TO_Y); - selected = true; } else { from_y = 0; to_y = 1; @@ -423,7 +424,7 @@ public class ScatterplotFacet implements Facet { @Override public RowFilter getRowFilter(Project project) { - if (config.selected && + if (config.isSelected() && eval_x != null && errorMessage_x == null && eval_y != null && errorMessage_y == null) { From c4caf1eba73bf721011aa18f93e0c8991d39a6eb Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 09:47:14 +0100 Subject: [PATCH 059/164] Jackson deserialization for TimeRangeFacetConfig --- .../browsing/facets/TimeRangeFacet.java | 37 +++++-------------- .../browsing/facets/TimeRangeFacetTests.java | 16 ++++---- 2 files changed, 18 insertions(+), 35 deletions(-) diff --git a/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java b/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java index c1042f116..38afab3c1 100644 --- a/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java +++ b/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java @@ -73,9 +73,9 @@ public class TimeRangeFacet implements Facet { protected String _columnName; // column to base expression on, if any @JsonProperty(FROM) - protected double _from; // the numeric selection + protected double _from = 0; // the numeric selection @JsonProperty(TO) - protected double _to; + protected double _to = 0; @JsonProperty("selectTime") protected boolean _selectTime; // whether the time selection applies, default true @@ -86,31 +86,12 @@ public class TimeRangeFacet implements Facet { @JsonProperty("selectError") protected boolean _selectError; + // false if we're certain that all rows will match + // and there isn't any filtering to do @JsonIgnore - protected boolean _selected; // false if we're certain that all rows will match - // and there isn't any filtering to do - - @Override - public void initializeFromJSON(JSONObject o) throws JSONException { - _name = o.getString("name"); - _expression = o.getString("expression"); - _columnName = o.getString("columnName"); - - if (o.has(FROM) || o.has(TO)) { - _from = o.has(FROM) ? o.getDouble(FROM) : 0; - _to = o.has(TO) ? o.getDouble(TO) : 0; - _selected = true; - } - - _selectTime = JSONUtilities.getBoolean(o, "selectTime", true); - _selectNonTime = JSONUtilities.getBoolean(o, "selectNonTime", true); - _selectBlank = JSONUtilities.getBoolean(o, "selectBlank", true); - _selectError = JSONUtilities.getBoolean(o, "selectError", true); - - if (!_selectTime || !_selectNonTime || !_selectBlank || !_selectError) { - _selected = true; - } - } + protected boolean isSelected() { + return _from != 0 || _to != 0 || !_selectTime || !_selectNonTime || !_selectBlank || !_selectError; + }; @Override public TimeRangeFacet apply(Project project) { @@ -268,7 +249,7 @@ public class TimeRangeFacet implements Facet { @Override public RowFilter getRowFilter(Project project) { - if (_eval != null && _errorMessage == null && _config._selected) { + if (_eval != null && _errorMessage == null && _config.isSelected()) { return new ExpressionTimeComparisonRowFilter( getRowEvaluable(project), _config._selectTime, _config._selectNonTime, _config._selectBlank, _config._selectError) { @@ -338,7 +319,7 @@ public class TimeRangeFacet implements Facet { _baseBlankCount = index.getBlankRowCount(); _baseErrorCount = index.getErrorRowCount(); - if (_config._selected) { + if (_config.isSelected()) { _config._from = Math.max(_config._from, _min); _config._to = Math.min(_config._to, _max); } else { diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java index 16794c035..a0741a03c 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java @@ -1,10 +1,13 @@ package com.google.refine.tests.browsing.facets; +import java.io.IOException; import java.time.OffsetDateTime; -import org.json.JSONObject; import org.testng.annotations.Test; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.facets.TimeRangeFacet; import com.google.refine.browsing.facets.TimeRangeFacet.TimeRangeFacetConfig; @@ -12,6 +15,7 @@ import com.google.refine.model.Cell; import com.google.refine.model.Project; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class TimeRangeFacetTests extends RefineTest { @@ -50,14 +54,13 @@ public class TimeRangeFacetTests extends RefineTest { " }"; @Test - public void serializeTimeRangeFacetConfig() { - TimeRangeFacetConfig config = new TimeRangeFacetConfig(); - config.initializeFromJSON(new JSONObject(configJson)); + public void serializeTimeRangeFacetConfig() throws JsonParseException, JsonMappingException, IOException { + TimeRangeFacetConfig config = ParsingUtilities.mapper.readValue(configJson, TimeRangeFacetConfig.class); TestUtils.isSerializedTo(config, configJson); } @Test - public void serializeTimeRangeFacet() { + public void serializeTimeRangeFacet() throws JsonParseException, JsonMappingException, IOException { Project project = createCSVProject("my column\n" + "placeholder\n" + "nontime\n" @@ -68,8 +71,7 @@ public class TimeRangeFacetTests extends RefineTest { project.rows.get(3).cells.set(0, new Cell(OffsetDateTime.parse("2012-04-05T02:00:01Z"), null)); Engine engine = new Engine(project); - TimeRangeFacetConfig config = new TimeRangeFacetConfig(); - config.initializeFromJSON(new JSONObject(configJson)); + TimeRangeFacetConfig config = ParsingUtilities.mapper.readValue(configJson, TimeRangeFacetConfig.class); TimeRangeFacet facet = config.apply(project); facet.computeChoices(project, engine.getAllFilteredRows()); TestUtils.isSerializedTo(facet, facetJson); From ae61368796b8987f4aa1bad95d082da3dfb3df47 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 09:47:57 +0100 Subject: [PATCH 060/164] Jackson deserialization for TextSearchFacetConfig --- .../browsing/facets/TextSearchFacetTests.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java index 870c5f36e..5d8903bc8 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java @@ -36,13 +36,15 @@ package com.google.refine.tests.browsing.facets; import java.io.IOException; import org.json.JSONException; -import org.json.JSONObject; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; + import com.google.refine.browsing.RowFilter; import com.google.refine.browsing.facets.TextSearchFacet; import com.google.refine.browsing.facets.TextSearchFacet.TextSearchFacetConfig; @@ -50,6 +52,7 @@ import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class TextSearchFacetTests extends RefineTest { @@ -89,10 +92,9 @@ public class TextSearchFacetTests extends RefineTest { + "Abc\n"); } - private void configureFilter(String filter) { + private void configureFilter(String filter) throws JsonParseException, JsonMappingException, IOException { //Add the facet to the project and create a row filter - textfilterconfig = new TextSearchFacetConfig(); - textfilterconfig.initializeFromJSON(new JSONObject(filter)); + textfilterconfig = ParsingUtilities.mapper.readValue(filter, TextSearchFacetConfig.class); textfilter = textfilterconfig.apply(project); rowfilter = textfilter.getRowFilter(project); } @@ -194,16 +196,14 @@ public class TextSearchFacetTests extends RefineTest { } @Test - public void serializeTextSearchFacetConfig() { - TextSearchFacetConfig config = new TextSearchFacetConfig(); - config.initializeFromJSON(new JSONObject(sensitiveConfigJson)); + public void serializeTextSearchFacetConfig() throws JsonParseException, JsonMappingException, IOException { + TextSearchFacetConfig config = ParsingUtilities.mapper.readValue(sensitiveConfigJson, TextSearchFacetConfig.class); TestUtils.isSerializedTo(config, sensitiveConfigJson); } @Test - public void serializeTextSearchFacet() { - TextSearchFacetConfig config = new TextSearchFacetConfig(); - config.initializeFromJSON(new JSONObject(sensitiveConfigJson)); + public void serializeTextSearchFacet() throws JsonParseException, JsonMappingException, IOException { + TextSearchFacetConfig config = ParsingUtilities.mapper.readValue(sensitiveConfigJson, TextSearchFacetConfig.class); TextSearchFacet facet = config.apply(project); TestUtils.isSerializedTo(facet, sensitiveFacetJson); } From 393eec15867a5375343f7157a3a4b34cfba6b340 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 10:07:50 +0100 Subject: [PATCH 061/164] Jackson deserialization for EngineConfig --- .../google/refine/browsing/EngineConfig.java | 68 +++++-------------- .../refine/browsing/facets/FacetConfig.java | 25 ++++--- .../browsing/facets/FacetConfigResolver.java | 36 ++++++++++ .../refine/browsing/facets/ListFacet.java | 34 ---------- .../refine/browsing/facets/RangeFacet.java | 23 ------- .../browsing/facets/ScatterplotFacet.java | 48 ++----------- .../browsing/facets/TextSearchFacet.java | 13 ---- .../browsing/facets/TimeRangeFacet.java | 4 -- .../tests/browsing/facets/ListFacetTests.java | 6 +- .../facets/ScatterplotFacetTests.java | 17 +++-- 10 files changed, 86 insertions(+), 188 deletions(-) create mode 100644 main/src/com/google/refine/browsing/facets/FacetConfigResolver.java diff --git a/main/src/com/google/refine/browsing/EngineConfig.java b/main/src/com/google/refine/browsing/EngineConfig.java index b0af26097..3e9a4c4e4 100644 --- a/main/src/com/google/refine/browsing/EngineConfig.java +++ b/main/src/com/google/refine/browsing/EngineConfig.java @@ -1,21 +1,17 @@ package com.google.refine.browsing; +import java.io.IOException; import java.util.Collections; -import java.util.LinkedList; import java.util.List; -import org.json.JSONArray; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.facets.FacetConfig; -import com.google.refine.browsing.facets.ListFacet.ListFacetConfig; -import com.google.refine.browsing.facets.RangeFacet.RangeFacetConfig; -import com.google.refine.browsing.facets.ScatterplotFacet.ScatterplotFacetConfig; -import com.google.refine.browsing.facets.TextSearchFacet.TextSearchFacetConfig; -import com.google.refine.browsing.facets.TimeRangeFacet.TimeRangeFacetConfig; +import com.google.refine.util.ParsingUtilities; public class EngineConfig { @@ -23,9 +19,14 @@ public class EngineConfig { protected final List _facets; protected final Mode _mode; - public EngineConfig(List facets, Mode mode) { - _facets = facets; - _mode = mode; + @JsonCreator + public EngineConfig( + @JsonProperty("facets") + List facets, + @JsonProperty("mode") + Mode mode) { + _facets = facets == null ? Collections.emptyList() : facets; + _mode = mode == null ? Mode.RowBased : mode; } @JsonProperty("mode") @@ -39,49 +40,14 @@ public class EngineConfig { } public static EngineConfig reconstruct(JSONObject o) { - if (o == null) { + if(o == null) { return new EngineConfig(Collections.emptyList(), Mode.RowBased); } - - List facets = new LinkedList<>(); - if (o.has("facets") && !o.isNull("facets")) { - JSONArray a = o.getJSONArray("facets"); - int length = a.length(); - - for (int i = 0; i < length; i++) { - JSONObject fo = a.getJSONObject(i); - String type = fo.has("type") ? fo.getString("type") : "list"; - - FacetConfig facet = null; - if ("list".equals(type)) { - facet = new ListFacetConfig(); - } else if ("range".equals(type)) { - facet = new RangeFacetConfig(); - } else if ("timerange".equals(type)) { - facet = new TimeRangeFacetConfig(); - } else if ("scatterplot".equals(type)) { - facet = new ScatterplotFacetConfig(); - } else if ("text".equals(type)) { - facet = new TextSearchFacetConfig(); - } - - if (facet != null) { - facet.initializeFromJSON(fo); - facets.add(facet); - } - } + try { + return ParsingUtilities.mapper.readValue(o.toString(), EngineConfig.class); + } catch (IOException e) { + e.printStackTrace(); + return null; } - - Mode mode = Mode.RowBased; - // for backward compatibility - if (o.has(Engine.INCLUDE_DEPENDENT) && !o.isNull(Engine.INCLUDE_DEPENDENT)) { - mode = o.getBoolean(Engine.INCLUDE_DEPENDENT) ? Mode.RecordBased : Mode.RowBased; - } - - if (o.has(Engine.MODE) && !o.isNull(Engine.MODE)) { - mode = Engine.MODE_ROW_BASED.equals(o.getString(Engine.MODE)) ? Mode.RowBased : Mode.RecordBased; - } - - return new EngineConfig(facets, mode); } } diff --git a/main/src/com/google/refine/browsing/facets/FacetConfig.java b/main/src/com/google/refine/browsing/facets/FacetConfig.java index 22f07e39c..07ffc9156 100644 --- a/main/src/com/google/refine/browsing/facets/FacetConfig.java +++ b/main/src/com/google/refine/browsing/facets/FacetConfig.java @@ -1,8 +1,9 @@ package com.google.refine.browsing.facets; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonSubTypes.Type; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.google.refine.model.Project; @@ -13,16 +14,20 @@ import com.google.refine.model.Project; * of operations. It does not contain the actual values displayed by * the facet. * - * @author antonin + * @author Antonin Delpeuch * */ -public interface FacetConfig { - /** - * Reads the facet configuration from a JSON object (will be removed once we migrate to Jackson) - * @param fo - */ - public void initializeFromJSON(JSONObject fo); - +@JsonTypeInfo( + use=JsonTypeInfo.Id.NAME, + include=JsonTypeInfo.As.PROPERTY, + property="type") +@JsonSubTypes({ + @Type(value = ListFacet.ListFacetConfig.class, name = "list"), + @Type(value = RangeFacet.RangeFacetConfig.class, name = "range"), + @Type(value = TimeRangeFacet.TimeRangeFacetConfig.class, name = "timerange"), + @Type(value = TextSearchFacet.TextSearchFacetConfig.class, name = "text"), + @Type(value = ScatterplotFacet.ScatterplotFacetConfig.class, name = "scatterplot") }) +public interface FacetConfig { /** * Instantiates the given facet on a particular project. * @param project diff --git a/main/src/com/google/refine/browsing/facets/FacetConfigResolver.java b/main/src/com/google/refine/browsing/facets/FacetConfigResolver.java new file mode 100644 index 000000000..0cfac814c --- /dev/null +++ b/main/src/com/google/refine/browsing/facets/FacetConfigResolver.java @@ -0,0 +1,36 @@ +package com.google.refine.browsing.facets; + +import java.io.IOException; + +import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; +import com.fasterxml.jackson.databind.DatabindContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase; +import com.fasterxml.jackson.databind.type.TypeFactory; + +import com.google.refine.model.recon.ReconConfig; + +public class FacetConfigResolver extends TypeIdResolverBase { + + protected TypeFactory factory = TypeFactory.defaultInstance(); + + @Override + public Id getMechanism() { + return Id.NAME; + } + + @Override + public String idFromValue(Object instance) { + return ((ReconConfig)instance).getMode(); + } + + @Override + public String idFromValueAndType(Object instance, Class type) { + return ReconConfig.s_opClassToName.get(type); + } + + @Override + public JavaType typeFromId(DatabindContext context, String id) throws IOException { + return factory.constructSimpleType(ReconConfig.getClassFromMode(id), new JavaType[0]); + } +} diff --git a/main/src/com/google/refine/browsing/facets/ListFacet.java b/main/src/com/google/refine/browsing/facets/ListFacet.java index 768b287a1..f1f2ebff9 100644 --- a/main/src/com/google/refine/browsing/facets/ListFacet.java +++ b/main/src/com/google/refine/browsing/facets/ListFacet.java @@ -37,9 +37,6 @@ import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; -import org.json.JSONArray; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -61,7 +58,6 @@ import com.google.refine.expr.MetaParser; import com.google.refine.expr.ParsingException; import com.google.refine.model.Column; import com.google.refine.model.Project; -import com.google.refine.util.JSONUtilities; public class ListFacet implements Facet { public static final String ERR_TOO_MANY_CHOICES = "Too many choices"; @@ -125,36 +121,6 @@ public class ListFacet implements Facet { .collect(Collectors.toList()); } - @Override - public void initializeFromJSON(JSONObject o) { - name = o.getString("name"); - expression = o.getString("expression"); - columnName = o.getString("columnName"); - invert = o.has("invert") && o.getBoolean("invert"); - - JSONArray a = o.getJSONArray("selection"); - int length = a.length(); - - for (int i = 0; i < length; i++) { - JSONObject oc = a.getJSONObject(i); - JSONObject ocv = oc.getJSONObject("v"); - - DecoratedValue decoratedValue = new DecoratedValue( - ocv.get("v"), ocv.getString("l")); - - selection.add(decoratedValue); - } - - omitBlank = JSONUtilities.getBoolean(o, "omitBlank", false); - omitError = JSONUtilities.getBoolean(o, "omitError", false); - - selectNumber = JSONUtilities.getBoolean(o, "selectNumber", false); - selectDateTime = JSONUtilities.getBoolean(o, "selectDateTime", false); - selectBoolean = JSONUtilities.getBoolean(o, "selectBoolean", false); - selectBlank = JSONUtilities.getBoolean(o, "selectBlank", false); - selectError = JSONUtilities.getBoolean(o, "selectError", false); - } - @Override public Facet apply(Project project) { ListFacet facet = new ListFacet(); diff --git a/main/src/com/google/refine/browsing/facets/RangeFacet.java b/main/src/com/google/refine/browsing/facets/RangeFacet.java index 0915c4f2b..4e978849a 100644 --- a/main/src/com/google/refine/browsing/facets/RangeFacet.java +++ b/main/src/com/google/refine/browsing/facets/RangeFacet.java @@ -33,8 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.browsing.facets; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -58,7 +56,6 @@ import com.google.refine.expr.MetaParser; import com.google.refine.expr.ParsingException; import com.google.refine.model.Column; import com.google.refine.model.Project; -import com.google.refine.util.JSONUtilities; public class RangeFacet implements Facet { @@ -125,26 +122,6 @@ public class RangeFacet implements Facet { _selected = !_selectNumeric || !_selectNonNumeric || !_selectBlank || !_selectError || from != null || to != null; } - @Override - public void initializeFromJSON(JSONObject o) { - _name = o.getString("name"); - _expression = o.getString("expression"); - _columnName = o.getString("columnName"); - if (o.has(FROM) || o.has(TO)) { - _from = o.has(FROM) ? o.getDouble(FROM) : 0; - _to = o.has(TO) ? o.getDouble(TO) : 0; - _selected = true; - } - _selectNumeric = JSONUtilities.getBoolean(o, "selectNumeric", true); - _selectNonNumeric = JSONUtilities.getBoolean(o, "selectNonNumeric", true); - _selectBlank = JSONUtilities.getBoolean(o, "selectBlank", true); - _selectError = JSONUtilities.getBoolean(o, "selectError", true); - - if (!_selectNumeric || !_selectNonNumeric || !_selectBlank || !_selectError) { - _selected = true; - } - } - @Override public RangeFacet apply(Project project) { RangeFacet facet = new RangeFacet(); diff --git a/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java b/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java index 5d5685b55..f2f3d3243 100644 --- a/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java +++ b/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java @@ -44,7 +44,6 @@ import java.io.IOException; import javax.imageio.ImageIO; import org.apache.commons.codec.binary.Base64; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -111,9 +110,11 @@ public class ScatterplotFacet implements Facet { protected double dot; @JsonIgnore - protected String color_str; + protected String color_str = "000000"; @JsonIgnore - protected Color color; + protected Color getColor() { + return new Color(Integer.parseInt(color_str,16)); + } @JsonProperty(FROM_X) protected double from_x; // the numeric selection for the x axis, from 0 to 1 @@ -147,43 +148,6 @@ public class ScatterplotFacet implements Facet { return facet; } - @Override - public void initializeFromJSON(JSONObject o) { - name = o.getString(NAME); - l = size = (o.has(SIZE)) ? o.getInt(SIZE) : 100; - dot = (o.has(DOT)) ? o.getInt(DOT) : 0.5d; - - dim_x = (o.has(DIM_X)) ? getAxisDim(o.getString(DIM_X)) : LIN; - if (o.has(FROM_X) && o.has(TO_X)) { - from_x = o.getDouble(FROM_X); - to_x = o.getDouble(TO_X); - } else { - from_x = 0; - to_x = 1; - } - - dim_y = (o.has(DIM_Y)) ? getAxisDim(o.getString(DIM_Y)) : LIN; - if (o.has(FROM_Y) && o.has(TO_Y)) { - from_y = o.getDouble(FROM_Y); - to_y = o.getDouble(TO_Y); - } else { - from_y = 0; - to_y = 1; - } - - rotation_str = (o.has(ROTATION) ? o.getString(ROTATION) : ""); - rotation = getRotation(rotation_str); - - color_str = (o.has(COLOR)) ? o.getString(COLOR) : "000000"; - color = new Color(Integer.parseInt(color_str,16)); - - columnName_x = o.getString(X_COLUMN_NAME); - expression_x = o.getString(X_EXPRESSION); - - columnName_y = o.getString(Y_COLUMN_NAME); - expression_y = o.getString(Y_EXPRESSION); - } - public static int getRotation(String rotation) { rotation = rotation.toLowerCase(); if ("cw".equals(rotation) || "right".equals(rotation)) { @@ -469,7 +433,7 @@ public class ScatterplotFacet implements Facet { if (index_x.isNumeric() && index_y.isNumeric()) { ScatterplotDrawingRowVisitor drawer = new ScatterplotDrawingRowVisitor( columnIndex_x, columnIndex_y, min_x, max_x, min_y, max_y, - config.size, config.dim_x, config.dim_y, config.rotation, config.dot, config.color + config.size, config.dim_x, config.dim_y, config.rotation, config.dot, config.getColor() ); filteredRows.accept(project, drawer); @@ -500,7 +464,7 @@ public class ScatterplotFacet implements Facet { if (index_x.isNumeric() && index_y.isNumeric()) { ScatterplotDrawingRowVisitor drawer = new ScatterplotDrawingRowVisitor( columnIndex_x, columnIndex_y, min_x, max_x, min_y, max_y, - config.size, config.dim_x, config.dim_y, config.rotation, config.dot, config.color + config.size, config.dim_x, config.dim_y, config.rotation, config.dot, config.getColor() ); filteredRecords.accept(project, drawer); diff --git a/main/src/com/google/refine/browsing/facets/TextSearchFacet.java b/main/src/com/google/refine/browsing/facets/TextSearchFacet.java index 5e3780e2a..4a5ea6733 100644 --- a/main/src/com/google/refine/browsing/facets/TextSearchFacet.java +++ b/main/src/com/google/refine/browsing/facets/TextSearchFacet.java @@ -36,7 +36,6 @@ package com.google.refine.browsing.facets; import java.util.regex.Pattern; import org.json.JSONException; -import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonProperty; @@ -78,18 +77,6 @@ public class TextSearchFacet implements Facet { return facet; } - @Override - public void initializeFromJSON(JSONObject o) { - _name = o.getString("name"); - _columnName = o.getString("columnName"); - _mode = o.getString("mode"); - _caseSensitive = o.getBoolean("caseSensitive"); - if (!o.isNull("query")) { - _query = o.getString("query"); - } - _invert = o.has("invert") && o.getBoolean("invert"); - } - @Override public String getJsonType() { return "text"; diff --git a/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java b/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java index 38afab3c1..63ecfcc39 100644 --- a/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java +++ b/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java @@ -33,9 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.browsing.facets; -import org.json.JSONException; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -58,7 +55,6 @@ import com.google.refine.expr.MetaParser; import com.google.refine.expr.ParsingException; import com.google.refine.model.Column; import com.google.refine.model.Project; -import com.google.refine.util.JSONUtilities; public class TimeRangeFacet implements Facet { /* diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java index f462f4710..200134d6f 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java @@ -2,7 +2,6 @@ package com.google.refine.tests.browsing.facets; import java.io.IOException; -import org.json.JSONObject; import org.testng.annotations.Test; import com.fasterxml.jackson.core.JsonParseException; @@ -65,9 +64,8 @@ public class ListFacetTests extends RefineTest { + "]}"; @Test - public void serializeListFacetConfig() { - ListFacetConfig facetConfig = new ListFacetConfig(); - facetConfig.initializeFromJSON(new JSONObject(jsonConfig)); + public void serializeListFacetConfig() throws JsonParseException, JsonMappingException, IOException { + ListFacetConfig facetConfig = ParsingUtilities.mapper.readValue(jsonConfig, ListFacetConfig.class); TestUtils.isSerializedTo(facetConfig, jsonConfig); } diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/ScatterplotFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/ScatterplotFacetTests.java index 6c0c0b3c0..29e7e9112 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/ScatterplotFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/ScatterplotFacetTests.java @@ -1,8 +1,12 @@ package com.google.refine.tests.browsing.facets; -import org.json.JSONObject; +import java.io.IOException; + import org.testng.annotations.Test; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.facets.ScatterplotFacet; import com.google.refine.browsing.facets.ScatterplotFacet.ScatterplotFacetConfig; @@ -10,6 +14,7 @@ import com.google.refine.model.Cell; import com.google.refine.model.Project; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ScatterplotFacetTests extends RefineTest { public static String configJson = "{\n" + @@ -48,14 +53,13 @@ public class ScatterplotFacetTests extends RefineTest { + "}"; @Test - public void serializeScatterplotFacetConfig() { - ScatterplotFacetConfig config = new ScatterplotFacetConfig(); - config.initializeFromJSON(new JSONObject(configJson)); + public void serializeScatterplotFacetConfig() throws JsonParseException, JsonMappingException, IOException { + ScatterplotFacetConfig config = ParsingUtilities.mapper.readValue(configJson, ScatterplotFacetConfig.class); TestUtils.isSerializedTo(config, configJson); } @Test - public void serializeScatterplotFacet() { + public void serializeScatterplotFacet() throws JsonParseException, JsonMappingException, IOException { Project project = createCSVProject("my column,e\n" + "89.2,89.2\n" + "-45.9,-45.9\n" + @@ -69,8 +73,7 @@ public class ScatterplotFacetTests extends RefineTest { project.rows.get(3).cells.set(0, new Cell(0.4, null)); project.rows.get(3).cells.set(1, new Cell(0.4, null)); - ScatterplotFacetConfig config = new ScatterplotFacetConfig(); - config.initializeFromJSON(new JSONObject(configJson)); + ScatterplotFacetConfig config = ParsingUtilities.mapper.readValue(configJson, ScatterplotFacetConfig.class); ScatterplotFacet facet = config.apply(project); facet.computeChoices(project, engine.getAllFilteredRows()); From eb666198400b8aa9811dee180630d901a12f5524 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 10:11:23 +0100 Subject: [PATCH 062/164] Jackson deserialization for ExtendDataOperation --- .../commands/recon/ExtendDataCommand.java | 3 +-- .../recon/PreviewExtendDataCommand.java | 2 +- .../recon/ReconciledDataExtensionJob.java | 4 ++-- .../operations/recon/ExtendDataOperation.java | 24 +++++++++---------- .../recon/ExtendDataOperationTests.java | 12 +++++----- 5 files changed, 21 insertions(+), 24 deletions(-) diff --git a/main/src/com/google/refine/commands/recon/ExtendDataCommand.java b/main/src/com/google/refine/commands/recon/ExtendDataCommand.java index 30adcb526..760c69e62 100644 --- a/main/src/com/google/refine/commands/recon/ExtendDataCommand.java +++ b/main/src/com/google/refine/commands/recon/ExtendDataCommand.java @@ -41,7 +41,6 @@ import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.model.recon.ReconciledDataExtensionJob.DataExtensionConfig; import com.google.refine.operations.recon.ExtendDataOperation; -import com.google.refine.util.ParsingUtilities; public class ExtendDataCommand extends EngineDependentCommand { @Override @@ -55,7 +54,7 @@ public class ExtendDataCommand extends EngineDependentCommand { String schemaSpace = request.getParameter("schemaSpace"); String jsonString = request.getParameter("extension"); - DataExtensionConfig extension = DataExtensionConfig.reconstruct(ParsingUtilities.evaluateJsonStringToObject(jsonString)); + DataExtensionConfig extension = DataExtensionConfig.reconstruct(jsonString); return new ExtendDataOperation( engineConfig, diff --git a/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java b/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java index c8d13a2aa..f42675fa0 100644 --- a/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java +++ b/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java @@ -93,7 +93,7 @@ public class PreviewExtendDataCommand extends Command { } String jsonString = request.getParameter("extension"); - DataExtensionConfig config = DataExtensionConfig.reconstruct(ParsingUtilities.evaluateJsonStringToObject(jsonString)); + DataExtensionConfig config = DataExtensionConfig.reconstruct(jsonString); JSONArray rowIndices = ParsingUtilities.evaluateJsonStringToArray(rowIndicesString); int length = rowIndices.length(); diff --git a/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java b/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java index 47f575600..13a630e5c 100644 --- a/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java +++ b/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java @@ -107,10 +107,10 @@ public class ReconciledDataExtensionJob { this.properties = properties; } - public static DataExtensionConfig reconstruct(JSONObject obj) throws JSONException { + public static DataExtensionConfig reconstruct(String json) throws JSONException { ObjectMapper mapper = new ObjectMapper(); try { - return mapper.readValue(obj.toString(), DataExtensionConfig.class); + return mapper.readValue(json, DataExtensionConfig.class); } catch(IOException e) { throw new JSONException(e.toString()); } diff --git a/main/src/com/google/refine/operations/recon/ExtendDataOperation.java b/main/src/com/google/refine/operations/recon/ExtendDataOperation.java index fac3243ed..e0aa039e4 100644 --- a/main/src/com/google/refine/operations/recon/ExtendDataOperation.java +++ b/main/src/com/google/refine/operations/recon/ExtendDataOperation.java @@ -44,6 +44,7 @@ import java.util.Set; import org.json.JSONException; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.Engine; @@ -67,6 +68,7 @@ import com.google.refine.model.recon.ReconciledDataExtensionJob.DataExtensionCon import com.google.refine.operations.EngineDependentOperation; import com.google.refine.process.LongRunningProcess; import com.google.refine.process.Process; +import com.google.refine.util.ParsingUtilities; public class ExtendDataOperation extends EngineDependentOperation { @JsonProperty("baseColumnName") @@ -84,28 +86,24 @@ public class ExtendDataOperation extends EngineDependentOperation { static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - - DataExtensionConfig dataExtensionConfig = DataExtensionConfig.reconstruct(obj.getJSONObject("extension")); - - return new ExtendDataOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("baseColumnName"), - obj.getString("endpoint"), - obj.getString("identifierSpace"), - obj.getString("schemaSpace"), - dataExtensionConfig, - obj.getInt("columnInsertIndex") - ); + return ParsingUtilities.mapper.readValue(obj.toString(), ExtendDataOperation.class); } + @JsonCreator public ExtendDataOperation( + @JsonProperty("engineConfig") EngineConfig engineConfig, + @JsonProperty("baseColumnName") String baseColumnName, + @JsonProperty("endpoint") String endpoint, + @JsonProperty("identifierSpace") String identifierSpace, + @JsonProperty("schemaSpace") String schemaSpace, + @JsonProperty("extension") DataExtensionConfig extension, + @JsonProperty("columnInsertIndex") int columnInsertIndex ) { super(engineConfig); diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java index 02df8cfb5..17cdb98ba 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java @@ -177,12 +177,12 @@ public class ExtendDataOperationTests extends RefineTest { @Test public void serializeDataExtensionConfig() { - TestUtils.isSerializedTo(DataExtensionConfig.reconstruct(new JSONObject(dataExtensionConfigJson)), dataExtensionConfigJson); + TestUtils.isSerializedTo(DataExtensionConfig.reconstruct(dataExtensionConfigJson), dataExtensionConfigJson); } @Test public void testFormulateQuery() throws IOException { - DataExtensionConfig config = DataExtensionConfig.reconstruct(new JSONObject(dataExtensionConfigJson)); + DataExtensionConfig config = DataExtensionConfig.reconstruct(dataExtensionConfigJson); Set ids = Collections.singleton("Q2"); String json = "{\"ids\":[\"Q2\"],\"properties\":[{\"id\":\"P571\"},{\"id\":\"P159\"},{\"id\":\"P625\"}]}"; ReconciledDataExtensionJobStub stub = new ReconciledDataExtensionJobStub(config, "http://endpoint"); @@ -214,7 +214,7 @@ public class ExtendDataOperationTests extends RefineTest { @Test public void testFetchStrings() throws Exception { - DataExtensionConfig extension = DataExtensionConfig.reconstruct(new JSONObject("{\"properties\":[{\"id\":\"P297\",\"name\":\"ISO 3166-1 alpha-2 code\"}]}")); + DataExtensionConfig extension = DataExtensionConfig.reconstruct("{\"properties\":[{\"id\":\"P297\",\"name\":\"ISO 3166-1 alpha-2 code\"}]}"); EngineDependentOperation op = new ExtendDataOperation(engine_config, "country", @@ -252,7 +252,7 @@ public class ExtendDataOperationTests extends RefineTest { @Test public void testFetchCounts() throws Exception { DataExtensionConfig extension = DataExtensionConfig.reconstruct( - new JSONObject("{\"properties\":[{\"id\":\"P38\",\"name\":\"currency\",\"settings\":{\"count\":\"on\",\"rank\":\"any\"}}]}")); + "{\"properties\":[{\"id\":\"P38\",\"name\":\"currency\",\"settings\":{\"count\":\"on\",\"rank\":\"any\"}}]}"); EngineDependentOperation op = new ExtendDataOperation(engine_config, "country", @@ -287,7 +287,7 @@ public class ExtendDataOperationTests extends RefineTest { @Test public void testFetchCurrent() throws Exception { DataExtensionConfig extension = DataExtensionConfig.reconstruct( - new JSONObject("{\"properties\":[{\"id\":\"P38\",\"name\":\"currency\",\"settings\":{\"rank\":\"best\"}}]}")); + "{\"properties\":[{\"id\":\"P38\",\"name\":\"currency\",\"settings\":{\"rank\":\"best\"}}]}"); EngineDependentOperation op = new ExtendDataOperation(engine_config, "country", @@ -328,7 +328,7 @@ public class ExtendDataOperationTests extends RefineTest { @Test public void testFetchRecord() throws Exception { DataExtensionConfig extension = DataExtensionConfig.reconstruct( - new JSONObject("{\"properties\":[{\"id\":\"P38\",\"name\":\"currency\",\"settings\":{\"rank\":\"any\"}}]}")); + "{\"properties\":[{\"id\":\"P38\",\"name\":\"currency\",\"settings\":{\"rank\":\"any\"}}]}"); EngineDependentOperation op = new ExtendDataOperation(engine_config, "country", From f573f37a9752cb4c001ba7fe3c2e80a21ed1c366 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 10:13:28 +0100 Subject: [PATCH 063/164] Jackson deserialization for ReconClearSimilarCellsOperation --- .../recon/ReconClearSimilarCellsOperation.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java b/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java index 8c3f2ca8d..c342878d8 100644 --- a/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java @@ -33,10 +33,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.recon; +import java.io.IOException; import java.util.List; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.EngineConfig; @@ -50,22 +52,22 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.operations.EngineDependentMassCellOperation; +import com.google.refine.util.ParsingUtilities; public class ReconClearSimilarCellsOperation extends EngineDependentMassCellOperation { final protected String _similarValue; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - return new ReconClearSimilarCellsOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("columnName"), - obj.getString("similarValue") - ); + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), ReconClearSimilarCellsOperation.class); } + @JsonCreator public ReconClearSimilarCellsOperation( - EngineConfig engineConfig, + @JsonProperty("engineConfig") + EngineConfig engineConfig, + @JsonProperty("columnName") String columnName, + @JsonProperty("similarValue") String similarValue ) { super(engineConfig, columnName, false); From e40d68afaf752269f1f657cc0f3e97f5a6359dc6 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 10:15:56 +0100 Subject: [PATCH 064/164] Jackson deserialization for ReconCopyAcrossColumnsOperation --- .../ReconCopyAcrossColumnsOperation.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java b/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java index ae9cf5a31..ddbcda50d 100644 --- a/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java @@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.recon; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -43,6 +44,7 @@ import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.Engine; @@ -61,6 +63,7 @@ import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.MassChange; import com.google.refine.operations.EngineDependentOperation; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class ReconCopyAcrossColumnsOperation extends EngineDependentOperation { final protected String _fromColumnName; @@ -68,22 +71,21 @@ public class ReconCopyAcrossColumnsOperation extends EngineDependentOperation { final protected String[] _judgments; final protected boolean _applyToJudgedCells; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - return new ReconCopyAcrossColumnsOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("fromColumnName"), - JSONUtilities.getStringArray(obj, "toColumnNames"), - JSONUtilities.getStringArray(obj, "judgments"), - obj.getBoolean("applyToJudgedCells") - ); + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), ReconCopyAcrossColumnsOperation.class); } + @JsonCreator public ReconCopyAcrossColumnsOperation( + @JsonProperty("engineConfig") EngineConfig engineConfig, + @JsonProperty("fromColumnName") String fromColumnName, + @JsonProperty("toColumnNames") String[] toColumnNames, + @JsonProperty("judgments") String[] judgments, + @JsonProperty("applyToJudgedCells") boolean applyToJudgedCells) { super(engineConfig); _fromColumnName = fromColumnName; From 408703f13c652027f978fec21c07a35f29275c67 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 10:17:43 +0100 Subject: [PATCH 065/164] Jackson deserialization for ReconDiscardJudgmentsOperation --- .../recon/ReconDiscardJudgmentsOperation.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java b/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java index aeb49118b..e58fa16f6 100644 --- a/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java @@ -33,12 +33,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.recon; +import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.EngineConfig; @@ -54,20 +56,23 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.operations.EngineDependentMassCellOperation; +import com.google.refine.util.ParsingUtilities; public class ReconDiscardJudgmentsOperation extends EngineDependentMassCellOperation { final protected boolean _clearData; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - return new ReconDiscardJudgmentsOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("columnName"), - obj.has("clearData") && obj.getBoolean("clearData") - ); + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), ReconDiscardJudgmentsOperation.class); } - public ReconDiscardJudgmentsOperation(EngineConfig engineConfig, String columnName, boolean clearData) { + @JsonCreator + public ReconDiscardJudgmentsOperation( + @JsonProperty("engineConfig") + EngineConfig engineConfig, + @JsonProperty("columnName") + String columnName, + @JsonProperty("clearData") + boolean clearData) { super(engineConfig, columnName, false); _clearData = clearData; } From 3271e53ecf5fb19e4b417f5b16bcf200e0e52b2b Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 10:27:39 +0100 Subject: [PATCH 066/164] Jackson deserialization for ReconJudgeSimilarCellsOperation --- .../ReconJudgeSimilarCellsOperation.java | 60 ++++++------------- .../recon/ReconJudgeSimilarCellsTests.java | 18 +++++- 2 files changed, 34 insertions(+), 44 deletions(-) diff --git a/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java b/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java index 18521988b..561fffcce 100644 --- a/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java @@ -33,14 +33,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.recon; - import java.util.HashMap; + import java.io.IOException; +import java.util.HashMap; import java.util.List; import java.util.Map; -import org.json.JSONArray; -import org.json.JSONException; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; @@ -61,6 +61,7 @@ import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.model.recon.ReconConfig; import com.google.refine.operations.EngineDependentMassCellOperation; +import com.google.refine.util.ParsingUtilities; public class ReconJudgeSimilarCellsOperation extends EngineDependentMassCellOperation { final protected String _similarValue; @@ -68,55 +69,30 @@ public class ReconJudgeSimilarCellsOperation extends EngineDependentMassCellOper final protected ReconCandidate _match; final protected boolean _shareNewTopics; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws JSONException { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - - ReconCandidate match = null; - if (obj.has("match")) { - JSONObject matchObj = obj.getJSONObject("match"); - - JSONArray types = matchObj.getJSONArray("types"); - String[] typeIDs = new String[types.length()]; - for (int i = 0; i < typeIDs.length; i++) { - typeIDs[i] = types.getString(i); - } - - match = new ReconCandidate( - matchObj.getString("id"), - matchObj.getString("name"), - typeIDs, - matchObj.getDouble("score") - ); - } - - Judgment judgment = Judgment.None; - if (obj.has("judgment")) { - judgment = Recon.stringToJudgment(obj.getString("judgment")); - } - - return new ReconJudgeSimilarCellsOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("columnName"), - obj.getString("similarValue"), - judgment, - match, - obj.has("shareNewTopics") ? obj.getBoolean("shareNewTopics") : false - ); + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), ReconJudgeSimilarCellsOperation.class); } - + + @JsonCreator public ReconJudgeSimilarCellsOperation( - EngineConfig engineConfig, - String columnName, + @JsonProperty("engineConfig") + EngineConfig engineConfig, + @JsonProperty("columnName") + String columnName, + @JsonProperty("similarValue") String similarValue, + @JsonProperty("judgment") Judgment judgment, + @JsonProperty("match") ReconCandidate match, - boolean shareNewTopics + @JsonProperty("shareNewTopics") + Boolean shareNewTopics ) { super(engineConfig, columnName, false); this._similarValue = similarValue; this._judgment = judgment; this._match = match; - this._shareNewTopics = shareNewTopics; + this._shareNewTopics = shareNewTopics == null ? false : shareNewTopics; } @JsonProperty("columnName") diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java index 79075a6fa..8587fa417 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java @@ -4,10 +4,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.mockito.Mockito.mock; +import java.io.IOException; import java.util.Collections; import java.util.Properties; -import org.json.JSONException; import org.json.JSONObject; import org.slf4j.LoggerFactory; import org.testng.annotations.BeforeTest; @@ -39,7 +39,7 @@ public class ReconJudgeSimilarCellsTests extends RefineTest { } @Test - public void serializeReconJudgeSimilarCellsOperation() throws JSONException { + public void serializeReconJudgeSimilarCellsOperation() throws IOException { String json = "{\"op\":\"core/recon-judge-similar-cells\"," + "\"description\":\"Mark to create one single new item for all cells containing \\\"foo\\\" in column A\"," + "\"engineConfig\":{\"mode\":\"row-based\",\"facets\":[]}," @@ -50,6 +50,20 @@ public class ReconJudgeSimilarCellsTests extends RefineTest { TestUtils.isSerializedTo(ReconJudgeSimilarCellsOperation.reconstruct(mock(Project.class), new JSONObject(json)), json); } + @Test + public void serializeReconJudgeSimilarCellsOperationMatch() throws IOException { + String json = "{\"op\":\"core/recon-judge-similar-cells\"," + + "\"description\":\"Match item Douglas Adams (Q42) for cells containing \\\"foo\\\" in column A\"," + + "\"engineConfig\":{\"mode\":\"row-based\",\"facets\":[]}," + + "\"columnName\":\"A\"," + + "\"similarValue\":\"foo\"," + + "\"judgment\":\"matched\"," + + "\"match\":{\"id\":\"Q42\",\"name\":\"Douglas Adams\",\"types\":[\"Q5\"],\"score\":85}," + + "\"shareNewTopics\":false" + + "}"; + TestUtils.isSerializedTo(ReconJudgeSimilarCellsOperation.reconstruct(mock(Project.class), new JSONObject(json)), json); + } + @Test public void testMarkNewTopics() throws Exception { Project project = createCSVProject( From d908635c1f90ceebf49f1bbdfd0609342c673437 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 10:32:02 +0100 Subject: [PATCH 067/164] Jackson deserialization for ReconMarkNewTopicsOperation --- .../recon/ReconMarkNewTopicsOperation.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java b/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java index 8d3efb59b..549f5cee2 100644 --- a/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java @@ -33,12 +33,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.recon; +import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.EngineConfig; @@ -55,21 +57,23 @@ import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.model.recon.ReconConfig; import com.google.refine.operations.EngineDependentMassCellOperation; +import com.google.refine.util.ParsingUtilities; public class ReconMarkNewTopicsOperation extends EngineDependentMassCellOperation { final protected boolean _shareNewTopics; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - - return new ReconMarkNewTopicsOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("columnName"), - obj.has("shareNewTopics") ? obj.getBoolean("shareNewTopics") : false - ); + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), ReconMarkNewTopicsOperation.class); } - public ReconMarkNewTopicsOperation(EngineConfig engineConfig, String columnName, boolean shareNewTopics) { + @JsonCreator + public ReconMarkNewTopicsOperation( + @JsonProperty("engineConfig") + EngineConfig engineConfig, + @JsonProperty("columnName") + String columnName, + @JsonProperty("shareNewTopics") + boolean shareNewTopics) { super(engineConfig, columnName, false); _shareNewTopics = shareNewTopics; } From fb584e0b5f78e970e39c4a5215f563850e73e7f9 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 10:36:03 +0100 Subject: [PATCH 068/164] Jackson deserialization for ReconMatchBestCandidatesOperation --- .../ReconMatchBestCandidatesOperation.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java b/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java index 9819ecef1..46aaf45d9 100644 --- a/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java @@ -39,6 +39,7 @@ import java.util.Map; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.EngineConfig; @@ -55,19 +56,19 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.operations.EngineDependentMassCellOperation; +import com.google.refine.util.ParsingUtilities; public class ReconMatchBestCandidatesOperation extends EngineDependentMassCellOperation { static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - String columnName = obj.getString("columnName"); - - return new ReconMatchBestCandidatesOperation( - EngineConfig.reconstruct(engineConfig), - columnName - ); + return ParsingUtilities.mapper.readValue(obj.toString(), ReconMatchBestCandidatesOperation.class); } - public ReconMatchBestCandidatesOperation(EngineConfig engineConfig, String columnName) { + @JsonCreator + public ReconMatchBestCandidatesOperation( + @JsonProperty("engineConfig") + EngineConfig engineConfig, + @JsonProperty("columnName") + String columnName) { super(engineConfig, columnName, false); } From 08c2b8fb2b536fd2f8c2073d6bd0413abec1687e Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 10:36:16 +0100 Subject: [PATCH 069/164] Jackson deserialization for ReconMatchSpecificTopicOperation --- .../ReconMatchSpecificTopicOperation.java | 30 +++++-------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java b/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java index 3e7f85ccf..709146811 100644 --- a/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java @@ -37,7 +37,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.json.JSONArray; import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonCreator; @@ -58,6 +57,7 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.operations.EngineDependentMassCellOperation; +import com.google.refine.util.ParsingUtilities; public class ReconMatchSpecificTopicOperation extends EngineDependentMassCellOperation { @@ -92,34 +92,20 @@ public class ReconMatchSpecificTopicOperation extends EngineDependentMassCellOpe final protected String schemaSpace; static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - - JSONObject match = obj.getJSONObject("match"); - - JSONArray types = match.getJSONArray("types"); - String[] typeIDs = new String[types.length()]; - for (int i = 0; i < typeIDs.length; i++) { - typeIDs[i] = types.getString(i); - } - - return new ReconMatchSpecificTopicOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("columnName"), - new ReconItem( - match.getString("id"), - match.getString("name"), - typeIDs - ), - obj.getString("identifierSpace"), - obj.getString("schemaSpace") - ); + return ParsingUtilities.mapper.readValue(obj.toString(), ReconMatchSpecificTopicOperation.class); } + @JsonCreator public ReconMatchSpecificTopicOperation( + @JsonProperty("engineConfig") EngineConfig engineConfig, + @JsonProperty("columnName") String columnName, + @JsonProperty("match") ReconItem match, + @JsonProperty("identifierSpace") String identifierSpace, + @JsonProperty("schemaSpace") String schemaSpace ) { super(engineConfig, columnName, false); From 0a5ea4e3dd75930df149fa574b6b8a9a27f432ae Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 10:38:55 +0100 Subject: [PATCH 070/164] Jackson deserialization for ReconOperation --- .../refine/operations/recon/ReconOperation.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/main/src/com/google/refine/operations/recon/ReconOperation.java b/main/src/com/google/refine/operations/recon/ReconOperation.java index 612b7d57e..92bd12b12 100644 --- a/main/src/com/google/refine/operations/recon/ReconOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconOperation.java @@ -44,6 +44,7 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; @@ -75,19 +76,17 @@ public class ReconOperation extends EngineDependentOperation { final protected String _columnName; final protected ReconConfig _reconConfig; - static public ReconOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - - return new ReconOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("columnName"), - ReconConfig.reconstruct(obj.getJSONObject("config").toString()) - ); + static public ReconOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), ReconOperation.class); } + @JsonCreator public ReconOperation( + @JsonProperty("engineConfig") EngineConfig engineConfig, + @JsonProperty("columnName") String columnName, + @JsonProperty("config") ReconConfig reconConfig ) { super(engineConfig); From c58854d947bb96db2c944b440e246cccc3fd1e53 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 10:41:41 +0100 Subject: [PATCH 071/164] Jackson deserialization for ReconUseValuesAsIdsOperation --- .../ReconUseValuesAsIdentifiersOperation.java | 22 +++++++++---------- ...=> ReconUseValuesAsIdsOperationTests.java} | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) rename main/tests/server/src/com/google/refine/tests/operations/recon/{ReconUseValuesAsIdsOperation.java => ReconUseValuesAsIdsOperationTests.java} (97%) diff --git a/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java b/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java index fda3726cf..b60744119 100644 --- a/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java @@ -1,11 +1,12 @@ package com.google.refine.operations.recon; +import java.io.IOException; import java.util.Collections; import java.util.List; -import java.util.Properties; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; @@ -24,7 +25,7 @@ import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.model.recon.StandardReconConfig; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.operations.OperationRegistry; +import com.google.refine.util.ParsingUtilities; public class ReconUseValuesAsIdentifiersOperation extends EngineDependentMassCellOperation { @@ -38,11 +39,17 @@ public class ReconUseValuesAsIdentifiersOperation extends EngineDependentMassCel @JsonIgnore protected StandardReconConfig reconConfig; + @JsonCreator public ReconUseValuesAsIdentifiersOperation( + @JsonProperty("engineConfig") EngineConfig engineConfig, + @JsonProperty("columnName") String columnName, + @JsonProperty("service") String service, + @JsonProperty("identifierSpace") String identifierSpace, + @JsonProperty("schemaSpace") String schemaSpace) { super(engineConfig, columnName, false); this.service = service; @@ -51,15 +58,8 @@ public class ReconUseValuesAsIdentifiersOperation extends EngineDependentMassCel this.reconConfig = new StandardReconConfig(service, identifierSpace, schemaSpace, null, null, true, Collections.emptyList()); } - static public ReconUseValuesAsIdentifiersOperation reconstruct(JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - return new ReconUseValuesAsIdentifiersOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("columnName"), - obj.getString("service"), - obj.getString("identifierSpace"), - obj.getString("schemaSpace") - ); + static public ReconUseValuesAsIdentifiersOperation reconstruct(JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), ReconUseValuesAsIdentifiersOperation.class); } @Override diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconUseValuesAsIdsOperation.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconUseValuesAsIdsOperationTests.java similarity index 97% rename from main/tests/server/src/com/google/refine/tests/operations/recon/ReconUseValuesAsIdsOperation.java rename to main/tests/server/src/com/google/refine/tests/operations/recon/ReconUseValuesAsIdsOperationTests.java index 2b11c86a3..3a6d94036 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconUseValuesAsIdsOperation.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconUseValuesAsIdsOperationTests.java @@ -18,7 +18,7 @@ import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; -public class ReconUseValuesAsIdsOperation extends RefineTest { +public class ReconUseValuesAsIdsOperationTests extends RefineTest { String json = "{" + "\"op\":\"core/recon-use-values-as-identifiers\"," + "\"description\":\"Use values as reconciliation identifiers in column ids\"," From 3b9fd23b9cf86a2f5681887136f0aa08156e05fa Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 10:42:40 +0100 Subject: [PATCH 072/164] Jackson deserialization for DenormalizeOperation --- .../com/google/refine/operations/row/DenormalizeOperation.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main/src/com/google/refine/operations/row/DenormalizeOperation.java b/main/src/com/google/refine/operations/row/DenormalizeOperation.java index 9daf246e9..da4b3a6d2 100644 --- a/main/src/com/google/refine/operations/row/DenormalizeOperation.java +++ b/main/src/com/google/refine/operations/row/DenormalizeOperation.java @@ -38,6 +38,8 @@ import java.util.List; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; + import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; @@ -52,6 +54,7 @@ public class DenormalizeOperation extends AbstractOperation { return new DenormalizeOperation(); } + @JsonCreator public DenormalizeOperation() { } From 5f196286181cd07daea5f7637cd7b8dc07da01d6 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 10:51:12 +0100 Subject: [PATCH 073/164] Jackson deserialization for RowFlagOperation --- .../refine/operations/row/RowFlagOperation.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/main/src/com/google/refine/operations/row/RowFlagOperation.java b/main/src/com/google/refine/operations/row/RowFlagOperation.java index b251d5ba8..5a998edda 100644 --- a/main/src/com/google/refine/operations/row/RowFlagOperation.java +++ b/main/src/com/google/refine/operations/row/RowFlagOperation.java @@ -38,6 +38,7 @@ import java.util.List; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.Engine; @@ -52,21 +53,21 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.MassChange; import com.google.refine.model.changes.RowFlagChange; import com.google.refine.operations.EngineDependentOperation; +import com.google.refine.util.ParsingUtilities; public class RowFlagOperation extends EngineDependentOperation { final protected boolean _flagged; static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - boolean flagged = obj.getBoolean("flagged"); - - return new RowFlagOperation( - EngineConfig.reconstruct(engineConfig), - flagged - ); + return ParsingUtilities.mapper.readValue(obj.toString(), RowFlagOperation.class); } - public RowFlagOperation(EngineConfig engineConfig, boolean flagged) { + @JsonCreator + public RowFlagOperation( + @JsonProperty("engineConfig") + EngineConfig engineConfig, + @JsonProperty("flagged") + boolean flagged) { super(engineConfig); _flagged = flagged; } From 242a3abb7d7c31d85aa34fbe860e55cff707cc3e Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 10:54:44 +0100 Subject: [PATCH 074/164] Jackson deserialization for RowRemovalOperation --- .../operations/row/RowRemovalOperation.java | 20 +++++++++++-------- .../row/RowRemovalOperationTests.java | 4 +++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/main/src/com/google/refine/operations/row/RowRemovalOperation.java b/main/src/com/google/refine/operations/row/RowRemovalOperation.java index 3445fadfe..ba2dd823f 100644 --- a/main/src/com/google/refine/operations/row/RowRemovalOperation.java +++ b/main/src/com/google/refine/operations/row/RowRemovalOperation.java @@ -33,11 +33,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.row; - import java.util.ArrayList; + import java.io.IOException; +import java.util.ArrayList; import java.util.List; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; @@ -48,17 +52,17 @@ import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.RowRemovalChange; import com.google.refine.operations.EngineDependentOperation; +import com.google.refine.util.ParsingUtilities; public class RowRemovalOperation extends EngineDependentOperation { - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - - return new RowRemovalOperation( - EngineConfig.reconstruct(engineConfig) - ); + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), RowRemovalOperation.class); } - public RowRemovalOperation(EngineConfig engineConfig) { + @JsonCreator + public RowRemovalOperation( + @JsonProperty("engineConfig") + EngineConfig engineConfig) { super(engineConfig); } diff --git a/main/tests/server/src/com/google/refine/tests/operations/row/RowRemovalOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/row/RowRemovalOperationTests.java index 375e2aca9..4be80efd3 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/row/RowRemovalOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/row/RowRemovalOperationTests.java @@ -2,6 +2,8 @@ package com.google.refine.tests.operations.row; import static org.mockito.Mockito.mock; +import java.io.IOException; + import org.json.JSONException; import org.json.JSONObject; import org.testng.annotations.BeforeSuite; @@ -20,7 +22,7 @@ public class RowRemovalOperationTests extends RefineTest { } @Test - public void serializeRowRemovalOperation() throws JSONException, Exception { + public void serializeRowRemovalOperation() throws JSONException, IOException { Project project = mock(Project.class); String json = "{" + "\"op\":\"core/row-removal\"," From 5f671e5e812ffe7e75aa1d527b855d015f718cec Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 11:22:27 +0100 Subject: [PATCH 075/164] Jackson deserialization for sorting Criterion and subclasses --- .../com/google/refine/sorting/Criterion.java | 82 +++++-------------- .../google/refine/sorting/SortingConfig.java | 24 ++---- .../refine/sorting/StringCriterion.java | 11 +-- .../tests/sorting/BooleanCriterionTest.java | 9 +- .../tests/sorting/DateCriterionTest.java | 8 +- .../tests/sorting/NumberCriterionTest.java | 8 +- .../tests/sorting/SortingConfigTests.java | 5 +- 7 files changed, 52 insertions(+), 95 deletions(-) diff --git a/main/src/com/google/refine/sorting/Criterion.java b/main/src/com/google/refine/sorting/Criterion.java index 4cae65d14..a9d01ac26 100644 --- a/main/src/com/google/refine/sorting/Criterion.java +++ b/main/src/com/google/refine/sorting/Criterion.java @@ -33,91 +33,53 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.sorting; +import java.io.IOException; + import org.json.JSONException; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.google.refine.expr.ExpressionUtils; import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Record; import com.google.refine.model.Row; +import com.google.refine.util.ParsingUtilities; +@JsonTypeInfo( + use=JsonTypeInfo.Id.NAME, + include=JsonTypeInfo.As.PROPERTY, + property="valueType") +@JsonSubTypes({ + @Type(value = BooleanCriterion.class, name = "boolean"), + @Type(value = DateCriterion.class, name = "date"), + @Type(value = NumberCriterion.class, name = "number"), + @Type(value = StringCriterion.class, name = "string") }) abstract public class Criterion { + @JsonProperty("column") public String columnName; + @JsonIgnore protected int cellIndex = -2; // These take on positive and negative values to indicate where blanks and errors // go relative to non-blank values. They are also relative to each another. // Blanks and errors are not affected by the reverse flag. + @JsonProperty("blankPosition") public int blankPosition = 1; + @JsonProperty("errorPosition") public int errorPosition = 2; - public boolean reverse; + @JsonProperty("reverse") + public boolean reverse = false; - public void initializeFromJSON(JSONObject obj) - throws JSONException { - if (obj.has("column") && !obj.isNull("column")) { - columnName = obj.getString("column"); - } - - if (obj.has("blankPosition") && !obj.isNull("blankPosition")) { - blankPosition = obj.getInt("blankPosition"); - } - if (obj.has("errorPosition") && !obj.isNull("errorPosition")) { - errorPosition = obj.getInt("errorPosition"); - } - - if (obj.has("reverse") && !obj.isNull("reverse")) { - reverse = obj.getBoolean("reverse"); - } - } - - public static Criterion reconstruct(JSONObject obj) throws JSONException { - String valueType = "string"; - if (obj.has("valueType") && !obj.isNull("valueType")) { - valueType = obj.getString("valueType"); - } - - Criterion c = null; - if ("boolean".equals(valueType)) { - c = new BooleanCriterion(); - } else if ("date".equals(valueType)) { - c = new DateCriterion(); - } else if ("number".equals(valueType)) { - c = new NumberCriterion(); - } else { - c = new StringCriterion(obj.getBoolean("caseSensitive")); - } - - c.initializeFromJSON(obj); - return c; - } - @JsonProperty("valueType") public abstract String getValueType(); - @JsonProperty("reverse") - public boolean getReverse() { - return reverse; - } - - @JsonProperty("column") - public String getColumnName() { - return columnName; - } - - @JsonProperty("blankPosition") - public int getBlankPosition() { - return blankPosition; - } - - @JsonProperty("errorPosition") - public int getErrorPosition() { - return errorPosition; - } - // Returns a cached cell index // We delay this fetching because the column might not exist // at deserialization (for instance if the column is created by an operation diff --git a/main/src/com/google/refine/sorting/SortingConfig.java b/main/src/com/google/refine/sorting/SortingConfig.java index a1c342d92..a8e2e172b 100644 --- a/main/src/com/google/refine/sorting/SortingConfig.java +++ b/main/src/com/google/refine/sorting/SortingConfig.java @@ -1,11 +1,14 @@ package com.google.refine.sorting; -import org.json.JSONArray; +import java.io.IOException; + import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.refine.util.ParsingUtilities; + /** * Stores the configuration of a row/record sorting setup. @@ -28,22 +31,7 @@ public final class SortingConfig { return _criteria; } - public static SortingConfig reconstruct(JSONObject obj) { - Criterion[] criteria; - if (obj != null && obj.has("criteria") && !obj.isNull("criteria")) { - JSONArray a = obj.getJSONArray("criteria"); - int count = a.length(); - - criteria = new Criterion[count]; - - for (int i = 0; i < count; i++) { - JSONObject obj2 = a.getJSONObject(i); - - criteria[i] = Criterion.reconstruct(obj2); - } - } else { - criteria = new Criterion[0]; - } - return new SortingConfig(criteria); + public static SortingConfig reconstruct(JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), SortingConfig.class); } } \ No newline at end of file diff --git a/main/src/com/google/refine/sorting/StringCriterion.java b/main/src/com/google/refine/sorting/StringCriterion.java index e3d937fc2..78234f767 100644 --- a/main/src/com/google/refine/sorting/StringCriterion.java +++ b/main/src/com/google/refine/sorting/StringCriterion.java @@ -36,30 +36,27 @@ package com.google.refine.sorting; import java.text.CollationKey; import java.text.Collator; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.expr.ExpressionUtils; public class StringCriterion extends Criterion { + @JsonProperty("caseSensitive") public boolean caseSensitive; + @JsonIgnore Collator collator; /** * */ - public StringCriterion(boolean caseSensitive) { + public StringCriterion() { super(); collator = Collator.getInstance(); collator.setDecomposition(Collator.FULL_DECOMPOSITION); collator.setStrength(Collator.SECONDARY); - this.caseSensitive = caseSensitive; } - @JsonProperty("caseSensitive") - public boolean isCaseSensitive() { - return caseSensitive; - } - @Override public KeyMaker createKeyMaker() { return new KeyMaker() { diff --git a/main/tests/server/src/com/google/refine/tests/sorting/BooleanCriterionTest.java b/main/tests/server/src/com/google/refine/tests/sorting/BooleanCriterionTest.java index 3a16d0486..c009683da 100644 --- a/main/tests/server/src/com/google/refine/tests/sorting/BooleanCriterionTest.java +++ b/main/tests/server/src/com/google/refine/tests/sorting/BooleanCriterionTest.java @@ -1,14 +1,17 @@ package com.google.refine.tests.sorting; -import org.json.JSONObject; +import java.io.IOException; + +import org.json.JSONException; import org.testng.annotations.Test; import com.google.refine.sorting.Criterion; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class BooleanCriterionTest { @Test - public void serializeBooleanCriterion() { + public void serializeBooleanCriterion() throws JSONException, IOException { String json = " {\n" + " \"errorPosition\": 1,\n" + @@ -17,6 +20,6 @@ public class BooleanCriterionTest { " \"blankPosition\": 2,\n" + " \"reverse\": false\n" + " }\n"; - TestUtils.isSerializedTo(Criterion.reconstruct(new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, Criterion.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/sorting/DateCriterionTest.java b/main/tests/server/src/com/google/refine/tests/sorting/DateCriterionTest.java index 349384d67..73b3347b0 100644 --- a/main/tests/server/src/com/google/refine/tests/sorting/DateCriterionTest.java +++ b/main/tests/server/src/com/google/refine/tests/sorting/DateCriterionTest.java @@ -1,14 +1,16 @@ package com.google.refine.tests.sorting; -import org.json.JSONObject; +import java.io.IOException; + import org.testng.annotations.Test; import com.google.refine.sorting.Criterion; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class DateCriterionTest { @Test - public void serializeDateCriterion() { + public void serializeDateCriterion() throws IOException { String json = " {\n" + " \"errorPosition\": 2,\n" + @@ -17,6 +19,6 @@ public class DateCriterionTest { " \"blankPosition\": -1,\n" + " \"reverse\": true\n" + " }\n"; - TestUtils.isSerializedTo(Criterion.reconstruct(new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, Criterion.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/sorting/NumberCriterionTest.java b/main/tests/server/src/com/google/refine/tests/sorting/NumberCriterionTest.java index 23aea5080..52962f205 100644 --- a/main/tests/server/src/com/google/refine/tests/sorting/NumberCriterionTest.java +++ b/main/tests/server/src/com/google/refine/tests/sorting/NumberCriterionTest.java @@ -1,14 +1,16 @@ package com.google.refine.tests.sorting; -import org.json.JSONObject; +import java.io.IOException; + import org.testng.annotations.Test; import com.google.refine.sorting.Criterion; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class NumberCriterionTest { @Test - public void serializeNumberCriterion() { + public void serializeNumberCriterion() throws IOException { String json = " {\n" + " \"errorPosition\": 2,\n" + @@ -17,6 +19,6 @@ public class NumberCriterionTest { " \"blankPosition\": 1,\n" + " \"reverse\": true\n" + " }\n"; - TestUtils.isSerializedTo(Criterion.reconstruct(new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, Criterion.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/sorting/SortingConfigTests.java b/main/tests/server/src/com/google/refine/tests/sorting/SortingConfigTests.java index a415eee99..75903a1e0 100644 --- a/main/tests/server/src/com/google/refine/tests/sorting/SortingConfigTests.java +++ b/main/tests/server/src/com/google/refine/tests/sorting/SortingConfigTests.java @@ -1,5 +1,8 @@ package com.google.refine.tests.sorting; +import java.io.IOException; + +import org.json.JSONException; import org.json.JSONObject; import org.testng.annotations.Test; @@ -8,7 +11,7 @@ import com.google.refine.tests.util.TestUtils; public class SortingConfigTests { @Test - public void serializeSortingConfig() { + public void serializeSortingConfig() throws JSONException, IOException { String json = "{\n" + " \"criteria\": [\n" + " {\n" + From c4429cbdffd1ea3259251dc5cb2c59a9aafe6e15 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 11:26:09 +0100 Subject: [PATCH 076/164] Jackson deserialization for RowReorderOperation --- .../operations/row/RowReorderOperation.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/main/src/com/google/refine/operations/row/RowReorderOperation.java b/main/src/com/google/refine/operations/row/RowReorderOperation.java index 340687732..97c7e3ced 100644 --- a/main/src/com/google/refine/operations/row/RowReorderOperation.java +++ b/main/src/com/google/refine/operations/row/RowReorderOperation.java @@ -33,11 +33,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.row; - import java.util.ArrayList; + import java.io.IOException; +import java.util.ArrayList; import java.util.List; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.Engine; @@ -53,20 +55,22 @@ import com.google.refine.model.changes.RowReorderChange; import com.google.refine.sorting.SortingConfig; import com.google.refine.sorting.SortingRecordVisitor; import com.google.refine.sorting.SortingRowVisitor; +import com.google.refine.util.ParsingUtilities; public class RowReorderOperation extends AbstractOperation { - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - String mode = obj.getString("mode"); - JSONObject sorting = obj.has("sorting") && !obj.isNull("sorting") ? - obj.getJSONObject("sorting") : null; - SortingConfig config = SortingConfig.reconstruct(sorting); - return new RowReorderOperation(Engine.stringToMode(mode), config); + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), RowReorderOperation.class); } final protected Mode _mode; final protected SortingConfig _sorting; - public RowReorderOperation(Mode mode, SortingConfig sorting) { + @JsonCreator + public RowReorderOperation( + @JsonProperty("mode") + Mode mode, + @JsonProperty("sorting") + SortingConfig sorting) { _mode = mode; _sorting = sorting; } From 0c87687e9262ac2a73cc74f8f6225eed7d82854d Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 11:27:31 +0100 Subject: [PATCH 077/164] Jackson deserialization for RowStarOperation --- .../operations/row/RowStarOperation.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/main/src/com/google/refine/operations/row/RowStarOperation.java b/main/src/com/google/refine/operations/row/RowStarOperation.java index d7be153b4..ed88f6d31 100644 --- a/main/src/com/google/refine/operations/row/RowStarOperation.java +++ b/main/src/com/google/refine/operations/row/RowStarOperation.java @@ -33,11 +33,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.row; - import java.util.ArrayList; + import java.io.IOException; +import java.util.ArrayList; import java.util.List; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.Engine; @@ -52,21 +54,21 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.MassChange; import com.google.refine.model.changes.RowStarChange; import com.google.refine.operations.EngineDependentOperation; +import com.google.refine.util.ParsingUtilities; public class RowStarOperation extends EngineDependentOperation { final protected boolean _starred; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - boolean starred = obj.getBoolean("starred"); - - return new RowStarOperation( - EngineConfig.reconstruct(engineConfig), - starred - ); + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), RowStarOperation.class); } - public RowStarOperation(EngineConfig engineConfig, boolean starred) { + @JsonCreator + public RowStarOperation( + @JsonProperty("engineConfig") + EngineConfig engineConfig, + @JsonProperty("starred") + boolean starred) { super(engineConfig); _starred = starred; } From a07f825aad6f9b451d754814e413377831bede39 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 11:34:02 +0100 Subject: [PATCH 078/164] Jackson deserialization for ColumnAdditionByFetchingURLsOperation --- ...ColumnAdditionByFetchingURLsOperation.java | 45 ++++++++----------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java b/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java index f8f7cd4c8..daec11954 100644 --- a/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java @@ -45,10 +45,10 @@ import java.util.List; import java.util.Properties; import java.util.concurrent.TimeUnit; -import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.cache.CacheBuilder; @@ -74,7 +74,6 @@ import com.google.refine.model.changes.CellAtRow; import com.google.refine.model.changes.ColumnAdditionChange; import com.google.refine.operations.EngineDependentOperation; import com.google.refine.operations.OnError; -import com.google.refine.operations.cell.TextTransformOperation; import com.google.refine.process.LongRunningProcess; import com.google.refine.process.Process; import com.google.refine.util.ParsingUtilities; @@ -87,7 +86,12 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat @JsonProperty("value") final public String value; - public HttpHeader(String name, String value) { + @JsonCreator + public HttpHeader( + @JsonProperty("name") + String name, + @JsonProperty("value") + String value) { this.name = name; this.value = value; } @@ -104,41 +108,28 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat final protected List _httpHeadersJson; static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - - List headers = null; - JSONArray headersJson = obj.optJSONArray("httpHeadersJson"); - if (headersJson != null) { - headers = new ArrayList<>(headersJson.length()); - for (int i = 0; i < headersJson.length(); i++) { - String headerLabel = headersJson.getJSONObject(i).getString("name"); - String headerValue = headersJson.getJSONObject(i).getString("value"); - headers.add(new HttpHeader(headerLabel, headerValue)); - } - } - - return new ColumnAdditionByFetchingURLsOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("baseColumnName"), - obj.getString("urlExpression"), - TextTransformOperation.stringToOnError(obj.getString("onError")), - obj.getString("newColumnName"), - obj.getInt("columnInsertIndex"), - obj.getInt("delay"), - obj.optBoolean("cacheResponses", false), // false for retro-compatibility - headers // will be null if it doesn't exist for retro-compatibility - ); + return ParsingUtilities.mapper.readValue(obj.toString(), ColumnAdditionByFetchingURLsOperation.class); } + @JsonCreator public ColumnAdditionByFetchingURLsOperation( + @JsonProperty("engineConfig") EngineConfig engineConfig, + @JsonProperty("baseColumnName") String baseColumnName, + @JsonProperty("urlExpression") String urlExpression, + @JsonProperty("onError") OnError onError, + @JsonProperty("newColumnName") String newColumnName, + @JsonProperty("columnInsertIndex") int columnInsertIndex, + @JsonProperty("delay") int delay, + @JsonProperty("cacheResponses") boolean cacheResponses, + @JsonProperty("httpHeadersJson") List httpHeadersJson ) { super(engineConfig); From 99852a193ce536049070c7d5187c07c1e0349277 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 11:36:27 +0100 Subject: [PATCH 079/164] Jackson deserialization for ColumnAdditionOperation --- .../column/ColumnAdditionOperation.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java b/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java index ae4b8077e..e32034361 100644 --- a/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java @@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.column; +import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -40,6 +41,7 @@ import java.util.Properties; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.Engine; @@ -61,7 +63,7 @@ import com.google.refine.model.changes.CellAtRow; import com.google.refine.model.changes.ColumnAdditionChange; import com.google.refine.operations.EngineDependentOperation; import com.google.refine.operations.OnError; -import com.google.refine.operations.cell.TextTransformOperation; +import com.google.refine.util.ParsingUtilities; public class ColumnAdditionOperation extends EngineDependentOperation { final protected String _baseColumnName; @@ -71,25 +73,23 @@ public class ColumnAdditionOperation extends EngineDependentOperation { final protected String _newColumnName; final protected int _columnInsertIndex; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - - return new ColumnAdditionOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("baseColumnName"), - obj.getString("expression"), - TextTransformOperation.stringToOnError(obj.getString("onError")), - obj.getString("newColumnName"), - obj.getInt("columnInsertIndex") - ); + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), ColumnAdditionOperation.class); } + @JsonCreator public ColumnAdditionOperation( + @JsonProperty("engineConfig") EngineConfig engineConfig, + @JsonProperty("baseColumnName") String baseColumnName, + @JsonProperty("expression") String expression, + @JsonProperty("onError") OnError onError, - String newColumnName, + @JsonProperty("newColumnName") + String newColumnName, + @JsonProperty("columnInsertIndex") int columnInsertIndex ) { super(engineConfig); From 9af5b0a877c7486d3b29f6b2bd0ae53248286b29 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 11:39:51 +0100 Subject: [PATCH 080/164] Jackson deserialization for ColumnMoveOperation --- .../operations/column/ColumnMoveOperation.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/main/src/com/google/refine/operations/column/ColumnMoveOperation.java b/main/src/com/google/refine/operations/column/ColumnMoveOperation.java index 2b6cc7df0..ed764a731 100644 --- a/main/src/com/google/refine/operations/column/ColumnMoveOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnMoveOperation.java @@ -33,8 +33,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.column; +import java.io.IOException; + import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.history.Change; @@ -42,20 +45,21 @@ import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.model.changes.ColumnMoveChange; +import com.google.refine.util.ParsingUtilities; public class ColumnMoveOperation extends AbstractOperation { final protected String _columnName; final protected int _index; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return new ColumnMoveOperation( - obj.getString("columnName"), - obj.getInt("index") - ); + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), ColumnMoveOperation.class); } + @JsonCreator public ColumnMoveOperation( + @JsonProperty("columnName") String columnName, + @JsonProperty("index") int index ) { _columnName = columnName; From a05b1bcad321c1f37307574d9c817385e1be2edd Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 11:40:01 +0100 Subject: [PATCH 081/164] Jackson deserialization for ColumnRemovalOperation --- .../operations/column/ColumnRemovalOperation.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java b/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java index 8e48c87de..2d90a32ae 100644 --- a/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java @@ -33,8 +33,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.column; +import java.io.IOException; + import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.history.Change; @@ -43,17 +46,18 @@ import com.google.refine.model.AbstractOperation; import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.changes.ColumnRemovalChange; +import com.google.refine.util.ParsingUtilities; public class ColumnRemovalOperation extends AbstractOperation { final protected String _columnName; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return new ColumnRemovalOperation( - obj.getString("columnName") - ); + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), ColumnRemovalOperation.class); } + @JsonCreator public ColumnRemovalOperation( + @JsonProperty("columnName") String columnName ) { _columnName = columnName; From 332132d720d30cc7e6d4cb4123d9d0685e080690 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 11:42:05 +0100 Subject: [PATCH 082/164] Jackson deserialization for ColumnReorderOperation --- .../operations/column/ColumnReorderOperation.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/main/src/com/google/refine/operations/column/ColumnReorderOperation.java b/main/src/com/google/refine/operations/column/ColumnReorderOperation.java index 2b1fe8d93..4202d2341 100644 --- a/main/src/com/google/refine/operations/column/ColumnReorderOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnReorderOperation.java @@ -33,31 +33,30 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.column; -import java.util.ArrayList; import java.util.List; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.model.changes.ColumnReorderChange; -import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class ColumnReorderOperation extends AbstractOperation { static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - List columnNames = new ArrayList(); - - JSONUtilities.getStringList(obj, "columnNames", columnNames); - - return new ColumnReorderOperation(columnNames); + return ParsingUtilities.mapper.readValue(obj.toString(), ColumnReorderOperation.class); } final protected List _columnNames; - public ColumnReorderOperation(List columnNames) { + @JsonCreator + public ColumnReorderOperation( + @JsonProperty("columnNames") + List columnNames) { _columnNames = columnNames; } From eb49db31e220870701d2b05084753e0285dc80c9 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 12:05:45 +0100 Subject: [PATCH 083/164] Jackson deserialization for ColumnSplitOperation --- .../column/ColumnSplitOperation.java | 58 +++++++++++++------ 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/main/src/com/google/refine/operations/column/ColumnSplitOperation.java b/main/src/com/google/refine/operations/column/ColumnSplitOperation.java index 330efa1e7..1ac7388d1 100644 --- a/main/src/com/google/refine/operations/column/ColumnSplitOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnSplitOperation.java @@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.column; +import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -41,6 +42,7 @@ import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; @@ -59,7 +61,7 @@ import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.ColumnSplitChange; import com.google.refine.operations.EngineDependentOperation; -import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class ColumnSplitOperation extends EngineDependentOperation { final protected String _columnName; @@ -73,28 +75,46 @@ public class ColumnSplitOperation extends EngineDependentOperation { final protected int[] _fieldLengths; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - String mode = obj.getString("mode"); - + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), ColumnSplitOperation.class); + } + + @JsonCreator + public static ColumnSplitOperation deserialize( + @JsonProperty("engineConfig") + EngineConfig engineConfig, + @JsonProperty("columnName") + String columnName, + @JsonProperty("guessCellType") + boolean guessCellType, + @JsonProperty("removeOriginalColumn") + boolean removeOriginalColumn, + @JsonProperty("mode") + String mode, + @JsonProperty("separator") + String separator, + @JsonProperty("regex") + Boolean regex, + @JsonProperty("maxColumns") + Integer maxColumns, + @JsonProperty("fieldLengths") + int[] fieldLengths) { if ("separator".equals(mode)) { return new ColumnSplitOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("columnName"), - obj.getBoolean("guessCellType"), - obj.getBoolean("removeOriginalColumn"), - obj.getString("separator"), - obj.getBoolean("regex"), - obj.getInt("maxColumns") - ); + engineConfig, + columnName, + guessCellType, + removeOriginalColumn, + separator, + regex, + maxColumns); } else { return new ColumnSplitOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("columnName"), - obj.getBoolean("guessCellType"), - obj.getBoolean("removeOriginalColumn"), - JSONUtilities.getIntArray(obj, "fieldLengths") - ); + engineConfig, + columnName, + guessCellType, + removeOriginalColumn, + fieldLengths); } } From 3aa4e1a544d4ca0e4dda14ac26528ffa38f9e30e Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 12:09:12 +0100 Subject: [PATCH 084/164] Jackson deserialization for BlankDownOperation --- .../google/refine/operations/cell/BlankDownOperation.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/main/src/com/google/refine/operations/cell/BlankDownOperation.java b/main/src/com/google/refine/operations/cell/BlankDownOperation.java index 0afda51b2..767cd102d 100644 --- a/main/src/com/google/refine/operations/cell/BlankDownOperation.java +++ b/main/src/com/google/refine/operations/cell/BlankDownOperation.java @@ -37,6 +37,9 @@ import java.util.List; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; @@ -60,8 +63,11 @@ public class BlankDownOperation extends EngineDependentMassCellOperation { ); } + @JsonCreator public BlankDownOperation( - EngineConfig engineConfig, + @JsonProperty("engineConfig") + EngineConfig engineConfig, + @JsonProperty("columnName") String columnName ) { super(engineConfig, columnName, true); From 379a12d3498a0ef4059b13f961846b69bcc6fb56 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 12:11:25 +0100 Subject: [PATCH 085/164] Jackson deserialization for FillDownOperation --- .../google/refine/operations/cell/FillDownOperation.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/main/src/com/google/refine/operations/cell/FillDownOperation.java b/main/src/com/google/refine/operations/cell/FillDownOperation.java index 1ecca6345..b1b78b4d6 100644 --- a/main/src/com/google/refine/operations/cell/FillDownOperation.java +++ b/main/src/com/google/refine/operations/cell/FillDownOperation.java @@ -37,6 +37,9 @@ import java.util.List; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.EngineConfig; @@ -61,8 +64,11 @@ public class FillDownOperation extends EngineDependentMassCellOperation { ); } + @JsonCreator public FillDownOperation( - EngineConfig engineConfig, + @JsonProperty("engineConfig") + EngineConfig engineConfig, + @JsonProperty("columnName") String columnName ) { super(engineConfig, columnName, true); From 0cf8c2dd048c789d4b8bb6976be09df63ec9f3f7 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 12:15:12 +0100 Subject: [PATCH 086/164] Jackson deserialization for MultiValuedCellJoinOperation --- .../refine/operations/cell/BlankDownOperation.java | 8 ++------ .../refine/operations/cell/FillDownOperation.java | 8 ++------ .../cell/MultiValuedCellJoinOperation.java | 12 +++++++----- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/main/src/com/google/refine/operations/cell/BlankDownOperation.java b/main/src/com/google/refine/operations/cell/BlankDownOperation.java index 767cd102d..4ed6c4fd6 100644 --- a/main/src/com/google/refine/operations/cell/BlankDownOperation.java +++ b/main/src/com/google/refine/operations/cell/BlankDownOperation.java @@ -51,16 +51,12 @@ import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.operations.EngineDependentMassCellOperation; +import com.google.refine.util.ParsingUtilities; public class BlankDownOperation extends EngineDependentMassCellOperation { static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - - return new BlankDownOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("columnName") - ); + return ParsingUtilities.mapper.readValue(obj.toString(), BlankDownOperation.class); } @JsonCreator diff --git a/main/src/com/google/refine/operations/cell/FillDownOperation.java b/main/src/com/google/refine/operations/cell/FillDownOperation.java index b1b78b4d6..b672f9558 100644 --- a/main/src/com/google/refine/operations/cell/FillDownOperation.java +++ b/main/src/com/google/refine/operations/cell/FillDownOperation.java @@ -52,16 +52,12 @@ import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.operations.EngineDependentMassCellOperation; +import com.google.refine.util.ParsingUtilities; public class FillDownOperation extends EngineDependentMassCellOperation { static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - - return new FillDownOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("columnName") - ); + return ParsingUtilities.mapper.readValue(obj.toString(), FillDownOperation.class); } @JsonCreator diff --git a/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java b/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java index 112214b14..9f24bfb3d 100644 --- a/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java +++ b/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java @@ -38,6 +38,7 @@ import java.util.List; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.expr.ExpressionUtils; @@ -48,6 +49,7 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowChange; +import com.google.refine.util.ParsingUtilities; public class MultiValuedCellJoinOperation extends AbstractOperation { final protected String _columnName; @@ -55,16 +57,16 @@ public class MultiValuedCellJoinOperation extends AbstractOperation { final protected String _separator; static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return new MultiValuedCellJoinOperation( - obj.getString("columnName"), - obj.getString("keyColumnName"), - obj.getString("separator") - ); + return ParsingUtilities.mapper.readValue(obj.toString(), MultiValuedCellJoinOperation.class); } + @JsonCreator public MultiValuedCellJoinOperation( + @JsonProperty("columnName") String columnName, + @JsonProperty("keyColumnName") String keyColumnName, + @JsonProperty("separator") String separator ) { _columnName = columnName; From 50ee6ecc6122c7767b8f9a58fd09f3a4a1e29dcc Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 13:13:38 +0100 Subject: [PATCH 087/164] Jackson deserialization for KeyValueColumnizeOperation --- .../cell/KeyValueColumnizeOperation.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java b/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java index c4d29535d..cfb9398f5 100644 --- a/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java +++ b/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java @@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.cell; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -40,6 +41,7 @@ import java.util.Map; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.expr.ExpressionUtils; @@ -50,24 +52,24 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowColumnChange; -import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class KeyValueColumnizeOperation extends AbstractOperation { final protected String _keyColumnName; final protected String _valueColumnName; final protected String _noteColumnName; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return new KeyValueColumnizeOperation( - obj.getString("keyColumnName"), - obj.getString("valueColumnName"), - JSONUtilities.getString(obj, "noteColumnName", null) - ); + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), KeyValueColumnizeOperation.class); } + @JsonCreator public KeyValueColumnizeOperation( + @JsonProperty("keyColumnName") String keyColumnName, + @JsonProperty("valueColumnName") String valueColumnName, + @JsonProperty("noteColumnName") String noteColumnName ) { _keyColumnName = keyColumnName; From d493bf0720baeb64f2fd668cfb09bce28fd1dd5e Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 13:25:28 +0100 Subject: [PATCH 088/164] Jackson deserialization for MassEditOperation --- .../refine/commands/cell/MassEditCommand.java | 7 +- .../operations/cell/MassEditOperation.java | 75 +++++++------------ .../operations/cell/MassOperationTests.java | 14 ++-- 3 files changed, 41 insertions(+), 55 deletions(-) diff --git a/main/src/com/google/refine/commands/cell/MassEditCommand.java b/main/src/com/google/refine/commands/cell/MassEditCommand.java index 557dba000..4b5911a03 100644 --- a/main/src/com/google/refine/commands/cell/MassEditCommand.java +++ b/main/src/com/google/refine/commands/cell/MassEditCommand.java @@ -33,13 +33,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.commands.cell; +import java.util.List; + import javax.servlet.http.HttpServletRequest; +import com.fasterxml.jackson.core.type.TypeReference; + import com.google.refine.browsing.EngineConfig; import com.google.refine.commands.EngineDependentCommand; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.operations.cell.MassEditOperation; +import com.google.refine.operations.cell.MassEditOperation.Edit; import com.google.refine.util.ParsingUtilities; public class MassEditCommand extends EngineDependentCommand { @@ -55,7 +60,7 @@ public class MassEditCommand extends EngineDependentCommand { engineConfig, columnName, expression, - MassEditOperation.reconstructEdits(ParsingUtilities.evaluateJsonStringToArray(editsString)) + ParsingUtilities.mapper.readValue(ParsingUtilities.evaluateJsonStringToArray(editsString).toString(), MassEditOperation.new TypeReference>() {}) ); } } diff --git a/main/src/com/google/refine/operations/cell/MassEditOperation.java b/main/src/com/google/refine/operations/cell/MassEditOperation.java index d9388b8e1..50f800834 100644 --- a/main/src/com/google/refine/operations/cell/MassEditOperation.java +++ b/main/src/com/google/refine/operations/cell/MassEditOperation.java @@ -40,9 +40,9 @@ import java.util.List; import java.util.Map; import java.util.Properties; -import org.json.JSONArray; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.EngineConfig; @@ -74,61 +74,40 @@ public class MassEditOperation extends EngineDependentMassCellOperation { @JsonProperty("to") final public Serializable to; - public Edit(List from, boolean fromBlank, boolean fromError, Serializable to) { + public Edit( + List from, + boolean fromBlank, + boolean fromError, + Serializable to) { this.from = from; this.fromBlank = fromBlank; this.fromError = fromError; this.to = to; } + + @JsonCreator + public static Edit deserialize( + @JsonProperty("from") + List from, + @JsonProperty("fromBlank") + boolean fromBlank, + @JsonProperty("fromError") + boolean fromError, + @JsonProperty("to") + Object to, + @JsonProperty("type") + String type) { + Serializable serializable = (Serializable)to; + if ("date".equals(type)) { + serializable = ParsingUtilities.stringToDate((String) to); + } + return new Edit(from == null ? new ArrayList<>() : from, + fromBlank, fromError, serializable); + } } static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.has("engineConfig") && !obj.isNull("engineConfig") ? - obj.getJSONObject("engineConfig") : null; - - return new MassEditOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("columnName"), - obj.getString("expression"), - reconstructEdits(obj.getJSONArray("edits")) - ); - } - - static public List reconstructEdits(JSONArray editsA) throws Exception { - int editCount = editsA.length(); - - List edits = new ArrayList(editCount); - for (int i = 0; i < editCount; i++) { - JSONObject editO = editsA.getJSONObject(i); - - List from = null; - if (editO.has("from") && !editO.isNull("from")) { - JSONArray fromA = editO.getJSONArray("from"); - int fromCount = fromA.length(); - - from = new ArrayList(fromCount); - for (int j = 0; j < fromCount; j++) { - from.add(fromA.get(j).toString()); - } - } else { - from = new ArrayList(); - } - - boolean fromBlank = (editO.has("fromBlank") && editO.getBoolean("fromBlank") || from.get(0).length() == 0 && from.size() == 1); - boolean fromError = editO.has("fromError") && editO.getBoolean("fromError"); - - Serializable to = (Serializable) editO.get("to"); - if (editO.has("type")) { - String type = editO.getString("type"); - if ("date".equals(type)) { - to = ParsingUtilities.stringToDate((String) to); - } - } - - edits.add(new Edit(from, fromBlank, fromError, to)); - } - - return edits; + return ParsingUtilities.mapper.readValue(obj.toString(), MassEditOperation.class); } public MassEditOperation(EngineConfig engineConfig, String columnName, String expression, List edits) { diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java index eb1e448e8..da41c8c02 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java @@ -9,6 +9,8 @@ import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; import static org.mockito.Mockito.mock; +import com.fasterxml.jackson.core.type.TypeReference; + import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.cell.MassEditOperation; @@ -42,7 +44,7 @@ public class MassOperationTests extends RefineTest { public void testReconstructEditString() throws Exception { editsString = "[{\"from\":[\"String\"],\"to\":\"newString\",\"type\":\"text\"}]"; - editList = MassEditOperation.reconstructEdits(ParsingUtilities.evaluateJsonStringToArray(editsString)); + editList = ParsingUtilities.mapper.readValue(ParsingUtilities.evaluateJsonStringToArray(editsString).toString(), new TypeReference>() {}); Assert.assertEquals(editList.get(0).from.size(), 1); Assert.assertEquals(editList.get(0).from.get(0), "String"); @@ -55,7 +57,7 @@ public class MassOperationTests extends RefineTest { public void testReconstructEditMultiString() throws Exception { editsString = "[{\"from\":[\"String1\",\"String2\"],\"to\":\"newString\",\"type\":\"text\"}]"; - editList = MassEditOperation.reconstructEdits(ParsingUtilities.evaluateJsonStringToArray(editsString)); + editList = ParsingUtilities.mapper.readValue(ParsingUtilities.evaluateJsonStringToArray(editsString).toString(), new TypeReference>() {}); Assert.assertEquals(editList.get(0).from.size(), 2); Assert.assertEquals(editList.get(0).from.get(0), "String1"); @@ -69,7 +71,7 @@ public class MassOperationTests extends RefineTest { public void testReconstructEditBoolean() throws Exception { editsString = "[{\"from\":[true],\"to\":\"newString\",\"type\":\"text\"}]"; - editList = MassEditOperation.reconstructEdits(ParsingUtilities.evaluateJsonStringToArray(editsString)); + editList = ParsingUtilities.mapper.readValue(ParsingUtilities.evaluateJsonStringToArray(editsString).toString(), new TypeReference>() {}); Assert.assertEquals(editList.get(0).from.size(), 1); Assert.assertEquals(editList.get(0).from.get(0), "true"); @@ -82,7 +84,7 @@ public class MassOperationTests extends RefineTest { public void testReconstructEditNumber() throws Exception { editsString = "[{\"from\":[1],\"to\":\"newString\",\"type\":\"text\"}]"; - editList = MassEditOperation.reconstructEdits(ParsingUtilities.evaluateJsonStringToArray(editsString)); + editList = ParsingUtilities.mapper.readValue(ParsingUtilities.evaluateJsonStringToArray(editsString).toString(), new TypeReference>() {}); Assert.assertEquals(editList.get(0).from.size(), 1); Assert.assertEquals(editList.get(0).from.get(0), "1"); @@ -95,7 +97,7 @@ public class MassOperationTests extends RefineTest { public void testReconstructEditDate() throws Exception { editsString = "[{\"from\":[\"2018-10-04T00:00:00Z\"],\"to\":\"newString\",\"type\":\"text\"}]"; - editList = MassEditOperation.reconstructEdits(ParsingUtilities.evaluateJsonStringToArray(editsString)); + editList = ParsingUtilities.mapper.readValue(ParsingUtilities.evaluateJsonStringToArray(editsString).toString(), new TypeReference>() {}); Assert.assertEquals(editList.get(0).from.get(0), "2018-10-04T00:00:00Z"); Assert.assertEquals(editList.get(0).to,"newString" ); @@ -107,7 +109,7 @@ public class MassOperationTests extends RefineTest { public void testReconstructEditEmpty() throws Exception { editsString = "[{\"from\":[\"\"],\"to\":\"newString\",\"type\":\"text\"}]"; - editList = MassEditOperation.reconstructEdits(ParsingUtilities.evaluateJsonStringToArray(editsString)); + editList = ParsingUtilities.mapper.readValue(ParsingUtilities.evaluateJsonStringToArray(editsString).toString(), new TypeReference>() {}); Assert.assertEquals(editList.get(0).from.size(), 1); Assert.assertEquals(editList.get(0).from.get(0), ""); From 6ad6b45048df1e0bb5fc42ad15d860512c737d1c Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 13:33:18 +0100 Subject: [PATCH 089/164] Jackson deserialization for MultiValuedCellSplitOperation --- .../cell/MultiValuedCellSplitOperation.java | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java b/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java index 180d2c864..d0b66d123 100644 --- a/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java +++ b/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java @@ -40,6 +40,7 @@ import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; @@ -51,7 +52,7 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowChange; -import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class MultiValuedCellSplitOperation extends AbstractOperation { final protected String _columnName; @@ -63,21 +64,34 @@ public class MultiValuedCellSplitOperation extends AbstractOperation { final protected int[] _fieldLengths; static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - String mode = obj.getString("mode"); - + return ParsingUtilities.mapper.readValue(obj.toString(), MultiValuedCellSplitOperation.class); + } + + @JsonCreator + public static MultiValuedCellSplitOperation deserialize( + @JsonProperty("columnName") + String columnName, + @JsonProperty("keyColumnName") + String keyColumnName, + @JsonProperty("mode") + String mode, + @JsonProperty("separator") + String separator, + @JsonProperty("regex") + boolean regex, + @JsonProperty("fieldLengths") + int[] fieldLengths) { if ("separator".equals(mode)) { return new MultiValuedCellSplitOperation( - obj.getString("columnName"), - obj.getString("keyColumnName"), - obj.getString("separator"), - obj.getBoolean("regex") - ); - } else { // mode == "lengths" + columnName, + keyColumnName, + separator, + regex); + } else { return new MultiValuedCellSplitOperation( - obj.getString("columnName"), - obj.getString("keyColumnName"), - JSONUtilities.getIntArray(obj, "fieldLengths") - ); + columnName, + keyColumnName, + fieldLengths); } } From 8647e3d5866408305f57a38c91c3cac3484ad34d Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 13:38:53 +0100 Subject: [PATCH 090/164] Jackson deserialization for TextTransformOperation --- .../refine/commands/cell/MassEditCommand.java | 2 +- .../cell/TextTransformOperation.java | 28 +++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/main/src/com/google/refine/commands/cell/MassEditCommand.java b/main/src/com/google/refine/commands/cell/MassEditCommand.java index 4b5911a03..1b1558db2 100644 --- a/main/src/com/google/refine/commands/cell/MassEditCommand.java +++ b/main/src/com/google/refine/commands/cell/MassEditCommand.java @@ -60,7 +60,7 @@ public class MassEditCommand extends EngineDependentCommand { engineConfig, columnName, expression, - ParsingUtilities.mapper.readValue(ParsingUtilities.evaluateJsonStringToArray(editsString).toString(), MassEditOperation.new TypeReference>() {}) + ParsingUtilities.mapper.readValue(ParsingUtilities.evaluateJsonStringToArray(editsString).toString(), new TypeReference>() {}) ); } } diff --git a/main/src/com/google/refine/operations/cell/TextTransformOperation.java b/main/src/com/google/refine/operations/cell/TextTransformOperation.java index fa3a07c30..c1cc816b5 100644 --- a/main/src/com/google/refine/operations/cell/TextTransformOperation.java +++ b/main/src/com/google/refine/operations/cell/TextTransformOperation.java @@ -39,6 +39,9 @@ import java.util.Properties; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.expr.Evaluable; @@ -53,24 +56,20 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.operations.EngineDependentMassCellOperation; import com.google.refine.operations.OnError; +import com.google.refine.util.ParsingUtilities; public class TextTransformOperation extends EngineDependentMassCellOperation { + @JsonProperty("expression") final protected String _expression; + @JsonProperty("onError") final protected OnError _onError; + @JsonProperty("repeat") final protected boolean _repeat; + @JsonProperty("repeatCount") final protected int _repeatCount; static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - JSONObject engineConfig = obj.getJSONObject("engineConfig"); - - return new TextTransformOperation( - EngineConfig.reconstruct(engineConfig), - obj.getString("columnName"), - obj.getString("expression"), - stringToOnError(obj.getString("onError")), - obj.getBoolean("repeat"), - obj.getInt("repeatCount") - ); + return ParsingUtilities.mapper.readValue(obj.toString(), TextTransformOperation.class); } static public OnError stringToOnError(String s) { @@ -92,12 +91,19 @@ public class TextTransformOperation extends EngineDependentMassCellOperation { } } + @JsonCreator public TextTransformOperation( + @JsonProperty("engineConfig") EngineConfig engineConfig, + @JsonProperty("columnName") String columnName, - String expression, + @JsonProperty("expression") + String expression, + @JsonProperty("onError") OnError onError, + @JsonProperty("repeat") boolean repeat, + @JsonProperty("repeatCount") int repeatCount ) { super(engineConfig, columnName, true); From 6358a4aeb53bb852837d7d05cb3fe78048a288d0 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 13:54:45 +0100 Subject: [PATCH 091/164] Jackson deserialization for TransposeColumnsIntoRowsOperation --- .../TransposeColumnsIntoRowsOperation.java | 78 +++++++++++++++---- .../cell/SplitMultiValuedCellsTests.java | 2 - 2 files changed, 61 insertions(+), 19 deletions(-) diff --git a/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java b/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java index 41dc0774e..0f7c44690 100644 --- a/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java +++ b/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java @@ -38,6 +38,12 @@ import java.util.List; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; @@ -45,42 +51,80 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowColumnChange; -import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class TransposeColumnsIntoRowsOperation extends AbstractOperation { + @JsonProperty("startColumnName") final protected String _startColumnName; + @JsonProperty("columnCount") final protected int _columnCount; + @JsonProperty("ignoreBlankCells") final protected boolean _ignoreBlankCells; + @JsonProperty("fillDown") final protected boolean _fillDown; + @JsonProperty("combinedColumnName") + @JsonInclude(Include.NON_NULL) final protected String _combinedColumnName; + @JsonIgnore final protected boolean _prependColumnName; + @JsonProperty("separator") final protected String _separator; + @JsonProperty("keyColumnName") final protected String _keyColumnName; + @JsonProperty("valueColumnName") final protected String _valueColumnName; + + @JsonProperty("prependColumnName") + @JsonInclude(Include.NON_NULL) + public Boolean getPrependColumnName() { + return _combinedColumnName == null ? null : _prependColumnName; + } static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - String combinedColumnName = JSONUtilities.getString(obj, "combinedColumnName", null); + return ParsingUtilities.mapper.readValue(obj.toString(), TransposeColumnsIntoRowsOperation.class); + } + + @JsonCreator + static public TransposeColumnsIntoRowsOperation deserialize( + @JsonProperty("combinedColumnName") + String combinedColumnName, + @JsonProperty("startColumnName") + String startColumnName, + @JsonProperty("columnCount") + int columnCount, + @JsonProperty("ignoreBlankCells") + Boolean ignoreBlankCells, + @JsonProperty("fillDown") + Boolean fillDown, + @JsonProperty("prependColumnName") + boolean prependColumnName, + @JsonProperty("separator") + String separator, + @JsonProperty("keyColumnName") + String keyColumnName, + @JsonProperty("valueColumnName") + String valueColumnName) { + ignoreBlankCells = ignoreBlankCells == null ? true : ignoreBlankCells; + fillDown = fillDown == null ? false : fillDown; if (combinedColumnName != null) { return new TransposeColumnsIntoRowsOperation( - obj.getString("startColumnName"), - obj.getInt("columnCount"), - JSONUtilities.getBoolean(obj, "ignoreBlankCells", true), - JSONUtilities.getBoolean(obj, "fillDown", false), - combinedColumnName, - obj.getBoolean("prependColumnName"), - obj.getString("separator") - ); + startColumnName, + columnCount, + ignoreBlankCells, + fillDown, + combinedColumnName, + prependColumnName, + separator); } else { return new TransposeColumnsIntoRowsOperation( - obj.getString("startColumnName"), - obj.getInt("columnCount"), - JSONUtilities.getBoolean(obj, "ignoreBlankCells", true), - JSONUtilities.getBoolean(obj, "fillDown", false), - obj.getString("keyColumnName"), - obj.getString("valueColumnName") - ); + startColumnName, + columnCount, + ignoreBlankCells, + fillDown, + keyColumnName, + valueColumnName); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/SplitMultiValuedCellsTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/SplitMultiValuedCellsTests.java index 81788b9ac..da372dff0 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/SplitMultiValuedCellsTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/SplitMultiValuedCellsTests.java @@ -164,7 +164,5 @@ public class SplitMultiValuedCellsTests extends RefineTest { Assert.assertEquals(project.rows.get(3).getCellValue(keyCol), null); Assert.assertEquals(project.rows.get(3).getCellValue(valueCol), "four"); } - - } From 8f9004f7ee185f45dccd707406ce5dce2db84324 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 13:56:46 +0100 Subject: [PATCH 092/164] Jackson deserialization for TransposeRowsIntoColumnsOperation --- .../cell/TransposeRowsIntoColumnsOperation.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java b/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java index a5455397f..97f886074 100644 --- a/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java +++ b/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java @@ -38,6 +38,7 @@ import java.util.List; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.history.HistoryEntry; @@ -47,20 +48,21 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowColumnChange; +import com.google.refine.util.ParsingUtilities; public class TransposeRowsIntoColumnsOperation extends AbstractOperation { final protected String _columnName; final protected int _rowCount; static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return new TransposeRowsIntoColumnsOperation( - obj.getString("columnName"), - obj.getInt("rowCount") - ); + return ParsingUtilities.mapper.readValue(obj.toString(), TransposeRowsIntoColumnsOperation.class); } + @JsonCreator public TransposeRowsIntoColumnsOperation( + @JsonProperty("columnName") String columnName, + @JsonProperty("rowCount") int rowCount ) { _columnName = columnName; From 2ef955f24b27e19e5404668f60c1dbd9371e4dfd Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 14:07:02 +0100 Subject: [PATCH 093/164] Jackson deserialization for AbstractOperation --- .../history/ApplyOperationsCommand.java | 2 +- .../refine/model/AbstractOperation.java | 7 ++++ .../refine/operations/OperationRegistry.java | 34 +++++++++---------- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/main/src/com/google/refine/commands/history/ApplyOperationsCommand.java b/main/src/com/google/refine/commands/history/ApplyOperationsCommand.java index 6ea66a1f2..136109acf 100644 --- a/main/src/com/google/refine/commands/history/ApplyOperationsCommand.java +++ b/main/src/com/google/refine/commands/history/ApplyOperationsCommand.java @@ -78,7 +78,7 @@ public class ApplyOperationsCommand extends Command { } } - protected void reconstructOperation(Project project, JSONObject obj) { + protected void reconstructOperation(Project project, JSONObject obj) throws IOException { AbstractOperation operation = OperationRegistry.reconstruct(project, obj); if (operation != null) { try { diff --git a/main/src/com/google/refine/model/AbstractOperation.java b/main/src/com/google/refine/model/AbstractOperation.java index 414bbe453..16fd68741 100644 --- a/main/src/com/google/refine/model/AbstractOperation.java +++ b/main/src/com/google/refine/model/AbstractOperation.java @@ -36,6 +36,8 @@ package com.google.refine.model; import java.util.Properties; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver; import com.google.refine.history.HistoryEntry; import com.google.refine.operations.OperationRegistry; @@ -46,6 +48,11 @@ import com.google.refine.process.QuickHistoryEntryProcess; * An abstract operation can be applied to different but similar * projects. */ +@JsonTypeInfo( + use=JsonTypeInfo.Id.CUSTOM, + include=JsonTypeInfo.As.PROPERTY, + property="op") +@JsonTypeIdResolver(OperationResolver.class) abstract public class AbstractOperation { public Process createProcess(Project project, Properties options) throws Exception { return new QuickHistoryEntryProcess(project, getBriefDescription(null)) { diff --git a/main/src/com/google/refine/operations/OperationRegistry.java b/main/src/com/google/refine/operations/OperationRegistry.java index 604439f11..e947c510c 100644 --- a/main/src/com/google/refine/operations/OperationRegistry.java +++ b/main/src/com/google/refine/operations/OperationRegistry.java @@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations; +import java.io.IOException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.LinkedList; @@ -41,8 +42,12 @@ import java.util.Map; import org.json.JSONObject; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; + import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; +import com.google.refine.util.ParsingUtilities; import edu.mit.simile.butterfly.ButterflyModule; @@ -67,25 +72,18 @@ public abstract class OperationRegistry { classes.add(klass); } - static public AbstractOperation reconstruct(Project project, JSONObject obj) { - try { - String op = obj.getString("op"); - if (!op.contains("/")) { - op = "core/" + op; // backward compatible - } - - List> classes = s_opNameToClass.get(op); - if (classes != null && classes.size() > 0) { - Class klass = classes.get(classes.size() - 1); - - Method reconstruct = klass.getMethod("reconstruct", Project.class, JSONObject.class); - if (reconstruct != null) { - return (AbstractOperation) reconstruct.invoke(null, project, obj); - } - } - } catch (Exception e) { - e.printStackTrace(); + static public Class resolveOperationId(String op) { + if (!op.contains("/")) { + op = "core/" + op; // backward compatible + } + List> classes = s_opNameToClass.get(op); + if (classes != null && classes.size() > 0) { + return classes.get(classes.size() - 1); } return null; } + + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { + return ParsingUtilities.mapper.readValue(obj.toString(), AbstractOperation.class); + } } From ebcc7b51b5a141c2bd08ad195dbe9e51d432715d Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 14:18:03 +0100 Subject: [PATCH 094/164] Add OperationResolver --- .../refine/model/OperationResolver.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 main/src/com/google/refine/model/OperationResolver.java diff --git a/main/src/com/google/refine/model/OperationResolver.java b/main/src/com/google/refine/model/OperationResolver.java new file mode 100644 index 000000000..6a12b8db4 --- /dev/null +++ b/main/src/com/google/refine/model/OperationResolver.java @@ -0,0 +1,36 @@ +package com.google.refine.model; + +import java.io.IOException; + +import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; +import com.fasterxml.jackson.databind.DatabindContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase; +import com.fasterxml.jackson.databind.type.TypeFactory; + +import com.google.refine.operations.OperationRegistry; + +public class OperationResolver extends TypeIdResolverBase { + + protected TypeFactory factory = TypeFactory.defaultInstance(); + + @Override + public Id getMechanism() { + return Id.NAME; + } + + @Override + public String idFromValue(Object instance) { + return ((AbstractOperation)instance).getOperationId(); + } + + @Override + public String idFromValueAndType(Object instance, Class type) { + return OperationRegistry.s_opClassToName.get(type); + } + + @Override + public JavaType typeFromId(DatabindContext context, String id) throws IOException { + return factory.constructSimpleType(OperationRegistry.resolveOperationId(id), new JavaType[0]); + } +} From d012ea7f8d22ede640aef7af7d003fe4d9ed49f5 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 14:18:17 +0100 Subject: [PATCH 095/164] Remove reconstruct method on operations --- .../operations/EngineDependentMassCellOperation.java | 3 +++ .../refine/operations/cell/BlankDownOperation.java | 8 -------- .../refine/operations/cell/FillDownOperation.java | 8 -------- .../operations/cell/KeyValueColumnizeOperation.java | 8 -------- .../refine/operations/cell/MassEditOperation.java | 7 ------- .../operations/cell/MultiValuedCellJoinOperation.java | 7 ------- .../cell/MultiValuedCellSplitOperation.java | 6 ------ .../operations/cell/TextTransformOperation.java | 8 -------- .../cell/TransposeColumnsIntoRowsOperation.java | 7 ------- .../cell/TransposeRowsIntoColumnsOperation.java | 7 ------- .../column/ColumnAdditionByFetchingURLsOperation.java | 6 ------ .../operations/column/ColumnAdditionOperation.java | 9 --------- .../refine/operations/column/ColumnMoveOperation.java | 9 --------- .../operations/column/ColumnRemovalOperation.java | 9 --------- .../operations/column/ColumnRenameOperation.java | 9 --------- .../operations/column/ColumnReorderOperation.java | 7 ------- .../operations/column/ColumnSplitOperation.java | 8 -------- .../refine/operations/recon/ExtendDataOperation.java | 7 ------- .../recon/ReconClearSimilarCellsOperation.java | 9 --------- .../recon/ReconCopyAcrossColumnsOperation.java | 9 --------- .../recon/ReconDiscardJudgmentsOperation.java | 9 --------- .../recon/ReconJudgeSimilarCellsOperation.java | 11 +---------- .../operations/recon/ReconMarkNewTopicsOperation.java | 9 --------- .../recon/ReconMatchBestCandidatesOperation.java | 8 -------- .../recon/ReconMatchSpecificTopicOperation.java | 8 -------- .../refine/operations/recon/ReconOperation.java | 5 ----- .../recon/ReconUseValuesAsIdentifiersOperation.java | 8 -------- .../refine/operations/row/DenormalizeOperation.java | 6 ------ .../refine/operations/row/RowFlagOperation.java | 8 -------- .../refine/operations/row/RowRemovalOperation.java | 11 +---------- .../refine/operations/row/RowReorderOperation.java | 10 +--------- .../refine/operations/row/RowStarOperation.java | 11 +---------- .../tests/model/changes/DataExtensionChangeTest.java | 10 +++------- .../refine/tests/operations/cell/BlankDownTests.java | 5 ++--- .../refine/tests/operations/cell/FillDownTests.java | 5 +++-- .../operations/cell/JoinMultiValuedCellsTests.java | 4 ++-- .../tests/operations/cell/KeyValueColumnizeTests.java | 5 +++-- .../tests/operations/cell/MassOperationTests.java | 6 +----- .../operations/cell/SplitMultiValuedCellsTests.java | 6 +++--- .../refine/tests/operations/cell/TransposeTests.java | 8 ++------ .../ColumnAdditionByFetchingURLsOperationTests.java | 5 +++-- .../column/ColumnAdditionOperationTests.java | 8 ++------ .../operations/column/ColumnMoveOperationTests.java | 8 ++------ .../column/ColumnRemovalOperationTests.java | 8 ++------ .../operations/column/ColumnRenameOperationTests.java | 10 +++++----- .../operations/column/ColumnSplitOperationTests.java | 11 +++-------- .../operations/recon/ExtendDataOperationTests.java | 5 +++-- .../recon/ReconClearSimilarCellsOperationTests.java | 8 ++------ .../recon/ReconCopyAcrossColumnsOperationTests.java | 8 ++------ .../recon/ReconDiscardJudgmentsOperationTests.java | 8 ++------ .../recon/ReconJudgeSimilarCellsOperationTests.java | 6 ++---- .../operations/recon/ReconJudgeSimilarCellsTests.java | 6 +++--- .../recon/ReconMarkNewTopicsOperationTests.java | 8 ++------ .../recon/ReconMatchBestCandidatesOperationTests.java | 8 ++------ .../recon/ReconMatchSpecificTopicOperationTests.java | 8 ++------ .../tests/operations/recon/ReconOperationTests.java | 6 +++--- .../recon/ReconUseValuesAsIdsOperationTests.java | 6 +++--- .../operations/row/DenormalizeOperationTests.java | 3 +-- .../tests/operations/row/RowFlagOperationTests.java | 4 ++-- .../operations/row/RowRemovalOperationTests.java | 4 ++-- .../operations/row/RowReorderOperationTests.java | 3 ++- .../tests/operations/row/RowStarOperationTests.java | 5 +++-- 62 files changed, 79 insertions(+), 371 deletions(-) diff --git a/main/src/com/google/refine/operations/EngineDependentMassCellOperation.java b/main/src/com/google/refine/operations/EngineDependentMassCellOperation.java index 1ebbe8bec..daf02378e 100644 --- a/main/src/com/google/refine/operations/EngineDependentMassCellOperation.java +++ b/main/src/com/google/refine/operations/EngineDependentMassCellOperation.java @@ -36,6 +36,7 @@ package com.google.refine.operations; import java.util.ArrayList; import java.util.List; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.Engine; @@ -50,7 +51,9 @@ import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.MassCellChange; abstract public class EngineDependentMassCellOperation extends EngineDependentOperation { + @JsonIgnore final protected String _columnName; + @JsonIgnore final protected boolean _updateRowContextDependencies; protected EngineDependentMassCellOperation( diff --git a/main/src/com/google/refine/operations/cell/BlankDownOperation.java b/main/src/com/google/refine/operations/cell/BlankDownOperation.java index 4ed6c4fd6..f022f28af 100644 --- a/main/src/com/google/refine/operations/cell/BlankDownOperation.java +++ b/main/src/com/google/refine/operations/cell/BlankDownOperation.java @@ -35,8 +35,6 @@ package com.google.refine.operations.cell; import java.util.List; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -44,21 +42,15 @@ import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.expr.ExpressionUtils; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.util.ParsingUtilities; public class BlankDownOperation extends EngineDependentMassCellOperation { - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return ParsingUtilities.mapper.readValue(obj.toString(), BlankDownOperation.class); - } - @JsonCreator public BlankDownOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/cell/FillDownOperation.java b/main/src/com/google/refine/operations/cell/FillDownOperation.java index b672f9558..b3a47ca60 100644 --- a/main/src/com/google/refine/operations/cell/FillDownOperation.java +++ b/main/src/com/google/refine/operations/cell/FillDownOperation.java @@ -35,8 +35,6 @@ package com.google.refine.operations.cell; import java.util.List; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -45,21 +43,15 @@ import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.expr.ExpressionUtils; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.util.ParsingUtilities; public class FillDownOperation extends EngineDependentMassCellOperation { - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return ParsingUtilities.mapper.readValue(obj.toString(), FillDownOperation.class); - } - @JsonCreator public FillDownOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java b/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java index cfb9398f5..bc04f38d9 100644 --- a/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java +++ b/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java @@ -33,14 +33,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.cell; -import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -52,17 +49,12 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowColumnChange; -import com.google.refine.util.ParsingUtilities; public class KeyValueColumnizeOperation extends AbstractOperation { final protected String _keyColumnName; final protected String _valueColumnName; final protected String _noteColumnName; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), KeyValueColumnizeOperation.class); - } - @JsonCreator public KeyValueColumnizeOperation( @JsonProperty("keyColumnName") diff --git a/main/src/com/google/refine/operations/cell/MassEditOperation.java b/main/src/com/google/refine/operations/cell/MassEditOperation.java index 50f800834..fdd99d376 100644 --- a/main/src/com/google/refine/operations/cell/MassEditOperation.java +++ b/main/src/com/google/refine/operations/cell/MassEditOperation.java @@ -40,8 +40,6 @@ import java.util.List; import java.util.Map; import java.util.Properties; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -50,7 +48,6 @@ import com.google.refine.browsing.RowVisitor; import com.google.refine.expr.Evaluable; import com.google.refine.expr.ExpressionUtils; import com.google.refine.expr.MetaParser; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; @@ -106,10 +103,6 @@ public class MassEditOperation extends EngineDependentMassCellOperation { } } - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return ParsingUtilities.mapper.readValue(obj.toString(), MassEditOperation.class); - } - public MassEditOperation(EngineConfig engineConfig, String columnName, String expression, List edits) { super(engineConfig, columnName, true); _expression = expression; diff --git a/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java b/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java index 9f24bfb3d..88ef3aeff 100644 --- a/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java +++ b/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java @@ -36,8 +36,6 @@ package com.google.refine.operations.cell; import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -49,17 +47,12 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowChange; -import com.google.refine.util.ParsingUtilities; public class MultiValuedCellJoinOperation extends AbstractOperation { final protected String _columnName; final protected String _keyColumnName; final protected String _separator; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return ParsingUtilities.mapper.readValue(obj.toString(), MultiValuedCellJoinOperation.class); - } - @JsonCreator public MultiValuedCellJoinOperation( @JsonProperty("columnName") diff --git a/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java b/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java index d0b66d123..fbb3a9006 100644 --- a/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java +++ b/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java @@ -38,7 +38,6 @@ import java.util.List; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; -import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; @@ -52,7 +51,6 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowChange; -import com.google.refine.util.ParsingUtilities; public class MultiValuedCellSplitOperation extends AbstractOperation { final protected String _columnName; @@ -63,10 +61,6 @@ public class MultiValuedCellSplitOperation extends AbstractOperation { final protected int[] _fieldLengths; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return ParsingUtilities.mapper.readValue(obj.toString(), MultiValuedCellSplitOperation.class); - } - @JsonCreator public static MultiValuedCellSplitOperation deserialize( @JsonProperty("columnName") diff --git a/main/src/com/google/refine/operations/cell/TextTransformOperation.java b/main/src/com/google/refine/operations/cell/TextTransformOperation.java index c1cc816b5..bdedef2cc 100644 --- a/main/src/com/google/refine/operations/cell/TextTransformOperation.java +++ b/main/src/com/google/refine/operations/cell/TextTransformOperation.java @@ -37,8 +37,6 @@ import java.io.Serializable; import java.util.List; import java.util.Properties; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -48,7 +46,6 @@ import com.google.refine.expr.Evaluable; import com.google.refine.expr.ExpressionUtils; import com.google.refine.expr.MetaParser; import com.google.refine.expr.WrappedCell; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; @@ -56,7 +53,6 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.operations.EngineDependentMassCellOperation; import com.google.refine.operations.OnError; -import com.google.refine.util.ParsingUtilities; public class TextTransformOperation extends EngineDependentMassCellOperation { @JsonProperty("expression") @@ -68,10 +64,6 @@ public class TextTransformOperation extends EngineDependentMassCellOperation { @JsonProperty("repeatCount") final protected int _repeatCount; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return ParsingUtilities.mapper.readValue(obj.toString(), TextTransformOperation.class); - } - static public OnError stringToOnError(String s) { if ("set-to-blank".equalsIgnoreCase(s)) { return OnError.SetToBlank; diff --git a/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java b/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java index 0f7c44690..c9e416d76 100644 --- a/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java +++ b/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java @@ -36,8 +36,6 @@ package com.google.refine.operations.cell; import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -51,7 +49,6 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowColumnChange; -import com.google.refine.util.ParsingUtilities; public class TransposeColumnsIntoRowsOperation extends AbstractOperation { @JsonProperty("startColumnName") @@ -82,10 +79,6 @@ public class TransposeColumnsIntoRowsOperation extends AbstractOperation { return _combinedColumnName == null ? null : _prependColumnName; } - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return ParsingUtilities.mapper.readValue(obj.toString(), TransposeColumnsIntoRowsOperation.class); - } - @JsonCreator static public TransposeColumnsIntoRowsOperation deserialize( @JsonProperty("combinedColumnName") diff --git a/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java b/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java index 97f886074..bcfa612a1 100644 --- a/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java +++ b/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java @@ -36,8 +36,6 @@ package com.google.refine.operations.cell; import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -48,16 +46,11 @@ import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowColumnChange; -import com.google.refine.util.ParsingUtilities; public class TransposeRowsIntoColumnsOperation extends AbstractOperation { final protected String _columnName; final protected int _rowCount; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return ParsingUtilities.mapper.readValue(obj.toString(), TransposeRowsIntoColumnsOperation.class); - } - @JsonCreator public TransposeRowsIntoColumnsOperation( @JsonProperty("columnName") diff --git a/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java b/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java index daec11954..4e920f435 100644 --- a/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java @@ -46,7 +46,6 @@ import java.util.Properties; import java.util.concurrent.TimeUnit; import org.json.JSONException; -import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -65,7 +64,6 @@ import com.google.refine.expr.ExpressionUtils; import com.google.refine.expr.MetaParser; import com.google.refine.expr.WrappedCell; import com.google.refine.history.HistoryEntry; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; @@ -107,10 +105,6 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat final protected boolean _cacheResponses; final protected List _httpHeadersJson; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return ParsingUtilities.mapper.readValue(obj.toString(), ColumnAdditionByFetchingURLsOperation.class); - } - @JsonCreator public ColumnAdditionByFetchingURLsOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java b/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java index e32034361..6e58835e5 100644 --- a/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java @@ -33,14 +33,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.column; -import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Properties; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -54,7 +51,6 @@ import com.google.refine.expr.MetaParser; import com.google.refine.expr.WrappedCell; import com.google.refine.history.Change; import com.google.refine.history.HistoryEntry; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; @@ -63,7 +59,6 @@ import com.google.refine.model.changes.CellAtRow; import com.google.refine.model.changes.ColumnAdditionChange; import com.google.refine.operations.EngineDependentOperation; import com.google.refine.operations.OnError; -import com.google.refine.util.ParsingUtilities; public class ColumnAdditionOperation extends EngineDependentOperation { final protected String _baseColumnName; @@ -73,10 +68,6 @@ public class ColumnAdditionOperation extends EngineDependentOperation { final protected String _newColumnName; final protected int _columnInsertIndex; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), ColumnAdditionOperation.class); - } - @JsonCreator public ColumnAdditionOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/column/ColumnMoveOperation.java b/main/src/com/google/refine/operations/column/ColumnMoveOperation.java index ed764a731..fd0842f53 100644 --- a/main/src/com/google/refine/operations/column/ColumnMoveOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnMoveOperation.java @@ -33,10 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.column; -import java.io.IOException; - -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -45,16 +41,11 @@ import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.model.changes.ColumnMoveChange; -import com.google.refine.util.ParsingUtilities; public class ColumnMoveOperation extends AbstractOperation { final protected String _columnName; final protected int _index; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), ColumnMoveOperation.class); - } - @JsonCreator public ColumnMoveOperation( @JsonProperty("columnName") diff --git a/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java b/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java index 2d90a32ae..7449345bc 100644 --- a/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java @@ -33,10 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.column; -import java.io.IOException; - -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -46,15 +42,10 @@ import com.google.refine.model.AbstractOperation; import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.changes.ColumnRemovalChange; -import com.google.refine.util.ParsingUtilities; public class ColumnRemovalOperation extends AbstractOperation { final protected String _columnName; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), ColumnRemovalOperation.class); - } - @JsonCreator public ColumnRemovalOperation( @JsonProperty("columnName") diff --git a/main/src/com/google/refine/operations/column/ColumnRenameOperation.java b/main/src/com/google/refine/operations/column/ColumnRenameOperation.java index d76f928a7..6359d6324 100644 --- a/main/src/com/google/refine/operations/column/ColumnRenameOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnRenameOperation.java @@ -33,8 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.column; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.history.Change; @@ -47,13 +45,6 @@ public class ColumnRenameOperation extends AbstractOperation { final protected String _oldColumnName; final protected String _newColumnName; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return new ColumnRenameOperation( - obj.getString("oldColumnName"), - obj.getString("newColumnName") - ); - } - public ColumnRenameOperation( String oldColumnName, String newColumnName diff --git a/main/src/com/google/refine/operations/column/ColumnReorderOperation.java b/main/src/com/google/refine/operations/column/ColumnReorderOperation.java index 4202d2341..032a8f7b9 100644 --- a/main/src/com/google/refine/operations/column/ColumnReorderOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnReorderOperation.java @@ -35,8 +35,6 @@ package com.google.refine.operations.column; import java.util.List; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -44,13 +42,8 @@ import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.model.changes.ColumnReorderChange; -import com.google.refine.util.ParsingUtilities; public class ColumnReorderOperation extends AbstractOperation { - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return ParsingUtilities.mapper.readValue(obj.toString(), ColumnReorderOperation.class); - } - final protected List _columnNames; @JsonCreator diff --git a/main/src/com/google/refine/operations/column/ColumnSplitOperation.java b/main/src/com/google/refine/operations/column/ColumnSplitOperation.java index 1ac7388d1..6f55b7a47 100644 --- a/main/src/com/google/refine/operations/column/ColumnSplitOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnSplitOperation.java @@ -33,14 +33,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.column; -import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; -import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; @@ -55,13 +53,11 @@ import com.google.refine.expr.ExpressionUtils; import com.google.refine.history.Change; import com.google.refine.history.HistoryEntry; import com.google.refine.importers.ImporterUtilities; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.ColumnSplitChange; import com.google.refine.operations.EngineDependentOperation; -import com.google.refine.util.ParsingUtilities; public class ColumnSplitOperation extends EngineDependentOperation { final protected String _columnName; @@ -75,10 +71,6 @@ public class ColumnSplitOperation extends EngineDependentOperation { final protected int[] _fieldLengths; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), ColumnSplitOperation.class); - } - @JsonCreator public static ColumnSplitOperation deserialize( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/recon/ExtendDataOperation.java b/main/src/com/google/refine/operations/recon/ExtendDataOperation.java index e0aa039e4..adcd26861 100644 --- a/main/src/com/google/refine/operations/recon/ExtendDataOperation.java +++ b/main/src/com/google/refine/operations/recon/ExtendDataOperation.java @@ -42,7 +42,6 @@ import java.util.Properties; import java.util.Set; import org.json.JSONException; -import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -52,7 +51,6 @@ import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.HistoryEntry; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; @@ -68,7 +66,6 @@ import com.google.refine.model.recon.ReconciledDataExtensionJob.DataExtensionCon import com.google.refine.operations.EngineDependentOperation; import com.google.refine.process.LongRunningProcess; import com.google.refine.process.Process; -import com.google.refine.util.ParsingUtilities; public class ExtendDataOperation extends EngineDependentOperation { @JsonProperty("baseColumnName") @@ -85,10 +82,6 @@ public class ExtendDataOperation extends EngineDependentOperation { final protected int _columnInsertIndex; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return ParsingUtilities.mapper.readValue(obj.toString(), ExtendDataOperation.class); - } - @JsonCreator public ExtendDataOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java b/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java index c342878d8..673e5e49d 100644 --- a/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java @@ -33,18 +33,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.recon; -import java.io.IOException; import java.util.List; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; @@ -52,15 +48,10 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.util.ParsingUtilities; public class ReconClearSimilarCellsOperation extends EngineDependentMassCellOperation { final protected String _similarValue; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), ReconClearSimilarCellsOperation.class); - } - @JsonCreator public ReconClearSimilarCellsOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java b/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java index ddbcda50d..6b9f89aa9 100644 --- a/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java @@ -33,7 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.recon; -import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -42,7 +41,6 @@ import java.util.Map; import java.util.Set; import org.apache.commons.lang3.StringUtils; -import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -52,7 +50,6 @@ import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.HistoryEntry; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; @@ -62,8 +59,6 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.MassChange; import com.google.refine.operations.EngineDependentOperation; -import com.google.refine.util.JSONUtilities; -import com.google.refine.util.ParsingUtilities; public class ReconCopyAcrossColumnsOperation extends EngineDependentOperation { final protected String _fromColumnName; @@ -71,10 +66,6 @@ public class ReconCopyAcrossColumnsOperation extends EngineDependentOperation { final protected String[] _judgments; final protected boolean _applyToJudgedCells; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), ReconCopyAcrossColumnsOperation.class); - } - @JsonCreator public ReconCopyAcrossColumnsOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java b/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java index e58fa16f6..c5e538e2e 100644 --- a/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java @@ -33,20 +33,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.recon; -import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; @@ -56,15 +52,10 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.util.ParsingUtilities; public class ReconDiscardJudgmentsOperation extends EngineDependentMassCellOperation { final protected boolean _clearData; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), ReconDiscardJudgmentsOperation.class); - } - @JsonCreator public ReconDiscardJudgmentsOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java b/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java index 561fffcce..5068334b4 100644 --- a/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java @@ -33,13 +33,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.recon; - import java.io.IOException; -import java.util.HashMap; + import java.util.HashMap; import java.util.List; import java.util.Map; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -49,7 +46,6 @@ import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.expr.ExpressionUtils; import com.google.refine.history.Change; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; @@ -61,7 +57,6 @@ import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.model.recon.ReconConfig; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.util.ParsingUtilities; public class ReconJudgeSimilarCellsOperation extends EngineDependentMassCellOperation { final protected String _similarValue; @@ -69,10 +64,6 @@ public class ReconJudgeSimilarCellsOperation extends EngineDependentMassCellOper final protected ReconCandidate _match; final protected boolean _shareNewTopics; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), ReconJudgeSimilarCellsOperation.class); - } - @JsonCreator public ReconJudgeSimilarCellsOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java b/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java index 549f5cee2..ac0eb1989 100644 --- a/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java @@ -33,20 +33,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.recon; -import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; @@ -57,15 +53,10 @@ import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.model.recon.ReconConfig; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.util.ParsingUtilities; public class ReconMarkNewTopicsOperation extends EngineDependentMassCellOperation { final protected boolean _shareNewTopics; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), ReconMarkNewTopicsOperation.class); - } - @JsonCreator public ReconMarkNewTopicsOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java b/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java index 46aaf45d9..17dd06184 100644 --- a/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java @@ -37,15 +37,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; @@ -56,13 +53,8 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.util.ParsingUtilities; public class ReconMatchBestCandidatesOperation extends EngineDependentMassCellOperation { - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return ParsingUtilities.mapper.readValue(obj.toString(), ReconMatchBestCandidatesOperation.class); - } - @JsonCreator public ReconMatchBestCandidatesOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java b/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java index 709146811..918a71d4d 100644 --- a/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java @@ -37,8 +37,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; @@ -46,7 +44,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; @@ -57,7 +54,6 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.util.ParsingUtilities; public class ReconMatchSpecificTopicOperation extends EngineDependentMassCellOperation { @@ -91,10 +87,6 @@ public class ReconMatchSpecificTopicOperation extends EngineDependentMassCellOpe @JsonProperty("schemaSpace") final protected String schemaSpace; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return ParsingUtilities.mapper.readValue(obj.toString(), ReconMatchSpecificTopicOperation.class); - } - @JsonCreator public ReconMatchSpecificTopicOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/recon/ReconOperation.java b/main/src/com/google/refine/operations/recon/ReconOperation.java index 92bd12b12..b9218f145 100644 --- a/main/src/com/google/refine/operations/recon/ReconOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconOperation.java @@ -40,7 +40,6 @@ import java.util.List; import java.util.Map; import java.util.Properties; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -76,10 +75,6 @@ public class ReconOperation extends EngineDependentOperation { final protected String _columnName; final protected ReconConfig _reconConfig; - static public ReconOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), ReconOperation.class); - } - @JsonCreator public ReconOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java b/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java index b60744119..d6115decc 100644 --- a/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java @@ -1,11 +1,8 @@ package com.google.refine.operations.recon; -import java.io.IOException; import java.util.Collections; import java.util.List; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; @@ -25,7 +22,6 @@ import com.google.refine.model.changes.CellChange; import com.google.refine.model.changes.ReconChange; import com.google.refine.model.recon.StandardReconConfig; import com.google.refine.operations.EngineDependentMassCellOperation; -import com.google.refine.util.ParsingUtilities; public class ReconUseValuesAsIdentifiersOperation extends EngineDependentMassCellOperation { @@ -58,10 +54,6 @@ public class ReconUseValuesAsIdentifiersOperation extends EngineDependentMassCel this.reconConfig = new StandardReconConfig(service, identifierSpace, schemaSpace, null, null, true, Collections.emptyList()); } - static public ReconUseValuesAsIdentifiersOperation reconstruct(JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), ReconUseValuesAsIdentifiersOperation.class); - } - @Override public String getBriefDescription(Project project) { return "Use values as reconciliation identifiers in column " + _columnName; diff --git a/main/src/com/google/refine/operations/row/DenormalizeOperation.java b/main/src/com/google/refine/operations/row/DenormalizeOperation.java index da4b3a6d2..aaee43c51 100644 --- a/main/src/com/google/refine/operations/row/DenormalizeOperation.java +++ b/main/src/com/google/refine/operations/row/DenormalizeOperation.java @@ -36,8 +36,6 @@ package com.google.refine.operations.row; import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.google.refine.history.HistoryEntry; @@ -50,10 +48,6 @@ import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowChange; public class DenormalizeOperation extends AbstractOperation { - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return new DenormalizeOperation(); - } - @JsonCreator public DenormalizeOperation() { } diff --git a/main/src/com/google/refine/operations/row/RowFlagOperation.java b/main/src/com/google/refine/operations/row/RowFlagOperation.java index 5a998edda..ddf142ec4 100644 --- a/main/src/com/google/refine/operations/row/RowFlagOperation.java +++ b/main/src/com/google/refine/operations/row/RowFlagOperation.java @@ -36,8 +36,6 @@ package com.google.refine.operations.row; import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -47,21 +45,15 @@ import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; import com.google.refine.history.HistoryEntry; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassChange; import com.google.refine.model.changes.RowFlagChange; import com.google.refine.operations.EngineDependentOperation; -import com.google.refine.util.ParsingUtilities; public class RowFlagOperation extends EngineDependentOperation { final protected boolean _flagged; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return ParsingUtilities.mapper.readValue(obj.toString(), RowFlagOperation.class); - } - @JsonCreator public RowFlagOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/row/RowRemovalOperation.java b/main/src/com/google/refine/operations/row/RowRemovalOperation.java index ba2dd823f..bf536ce0d 100644 --- a/main/src/com/google/refine/operations/row/RowRemovalOperation.java +++ b/main/src/com/google/refine/operations/row/RowRemovalOperation.java @@ -33,12 +33,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.row; - import java.io.IOException; -import java.util.ArrayList; + import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -47,18 +44,12 @@ import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.HistoryEntry; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.RowRemovalChange; import com.google.refine.operations.EngineDependentOperation; -import com.google.refine.util.ParsingUtilities; public class RowRemovalOperation extends EngineDependentOperation { - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), RowRemovalOperation.class); - } - @JsonCreator public RowRemovalOperation( @JsonProperty("engineConfig") diff --git a/main/src/com/google/refine/operations/row/RowReorderOperation.java b/main/src/com/google/refine/operations/row/RowReorderOperation.java index 97c7e3ced..b90867846 100644 --- a/main/src/com/google/refine/operations/row/RowReorderOperation.java +++ b/main/src/com/google/refine/operations/row/RowReorderOperation.java @@ -33,12 +33,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.row; - import java.io.IOException; -import java.util.ArrayList; + import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -55,13 +52,8 @@ import com.google.refine.model.changes.RowReorderChange; import com.google.refine.sorting.SortingConfig; import com.google.refine.sorting.SortingRecordVisitor; import com.google.refine.sorting.SortingRowVisitor; -import com.google.refine.util.ParsingUtilities; public class RowReorderOperation extends AbstractOperation { - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), RowReorderOperation.class); - } - final protected Mode _mode; final protected SortingConfig _sorting; diff --git a/main/src/com/google/refine/operations/row/RowStarOperation.java b/main/src/com/google/refine/operations/row/RowStarOperation.java index ed88f6d31..1d6caf472 100644 --- a/main/src/com/google/refine/operations/row/RowStarOperation.java +++ b/main/src/com/google/refine/operations/row/RowStarOperation.java @@ -33,12 +33,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.row; - import java.io.IOException; -import java.util.ArrayList; + import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -48,21 +45,15 @@ import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; import com.google.refine.history.HistoryEntry; -import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassChange; import com.google.refine.model.changes.RowStarChange; import com.google.refine.operations.EngineDependentOperation; -import com.google.refine.util.ParsingUtilities; public class RowStarOperation extends EngineDependentOperation { final protected boolean _starred; - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), RowStarOperation.class); - } - @JsonCreator public RowStarOperation( @JsonProperty("engineConfig") diff --git a/main/tests/server/src/com/google/refine/tests/model/changes/DataExtensionChangeTest.java b/main/tests/server/src/com/google/refine/tests/model/changes/DataExtensionChangeTest.java index c3608622b..689b050c2 100644 --- a/main/tests/server/src/com/google/refine/tests/model/changes/DataExtensionChangeTest.java +++ b/main/tests/server/src/com/google/refine/tests/model/changes/DataExtensionChangeTest.java @@ -1,18 +1,11 @@ package com.google.refine.tests.model.changes; -import com.google.refine.model.ModelException; -import com.google.refine.model.Project; -import com.google.refine.model.changes.DataExtensionChange; -import com.google.refine.model.changes.MassChange; - import static org.junit.Assert.assertEquals; -import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.LineNumberReader; -import java.io.Reader; import org.slf4j.LoggerFactory; import org.testng.annotations.BeforeMethod; @@ -20,6 +13,9 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.refine.history.Change; +import com.google.refine.model.ModelException; +import com.google.refine.model.Project; +import com.google.refine.model.changes.DataExtensionChange; import com.google.refine.tests.RefineTest; import com.google.refine.util.Pool; diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/BlankDownTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/BlankDownTests.java index 1e7669b29..06e3d58a7 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/BlankDownTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/BlankDownTests.java @@ -24,7 +24,7 @@ import com.google.refine.operations.cell.FillDownOperation; import com.google.refine.process.Process; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; -import com.google.refine.util.Pool; +import com.google.refine.util.ParsingUtilities; public class BlankDownTests extends RefineTest { @@ -56,7 +56,7 @@ public class BlankDownTests extends RefineTest { + "\"description\":\"Blank down cells in column my column\"," + "\"engineConfig\":{\"mode\":\"record-based\",\"facets\":[]}," + "\"columnName\":\"my column\"}"; - AbstractOperation op = BlankDownOperation.reconstruct(project, new JSONObject(json)); + AbstractOperation op = ParsingUtilities.mapper.readValue(json, BlankDownOperation.class); TestUtils.isSerializedTo(op, json); } @@ -107,7 +107,6 @@ public class BlankDownTests extends RefineTest { "second"); Process process = op.createProcess(project, new Properties()); process.performImmediate(); - //project.saveToOutputStream(System.out, new Pool()); Assert.assertEquals("c", project.rows.get(0).cells.get(3).value); Assert.assertNull(project.rows.get(1).cells.get(3)); diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/FillDownTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/FillDownTests.java index eb15e693d..73d82f2e7 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/FillDownTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/FillDownTests.java @@ -20,9 +20,10 @@ import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.cell.FillDownOperation; +import com.google.refine.process.Process; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; -import com.google.refine.process.Process; +import com.google.refine.util.ParsingUtilities; public class FillDownTests extends RefineTest { @@ -54,7 +55,7 @@ public class FillDownTests extends RefineTest { + "\"description\":\"Fill down cells in column my key\"," + "\"engineConfig\":{\"mode\":\"record-based\",\"facets\":[]}," + "\"columnName\":\"my key\"}"; - TestUtils.isSerializedTo(FillDownOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, FillDownOperation.class), json); } @Test diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/JoinMultiValuedCellsTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/JoinMultiValuedCellsTests.java index c1a87aec7..9e84f3c37 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/JoinMultiValuedCellsTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/JoinMultiValuedCellsTests.java @@ -36,7 +36,6 @@ package com.google.refine.tests.operations.cell; import java.util.Properties; import org.json.JSONException; -import org.json.JSONObject; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.BeforeMethod; @@ -51,6 +50,7 @@ import com.google.refine.operations.cell.MultiValuedCellJoinOperation; import com.google.refine.process.Process; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class JoinMultiValuedCellsTests extends RefineTest { @@ -85,7 +85,7 @@ public class JoinMultiValuedCellsTests extends RefineTest { + "\"columnName\":\"value column\"," + "\"keyColumnName\":\"key column\"," + "\"separator\":\",\"}"; - TestUtils.isSerializedTo(MultiValuedCellJoinOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, MultiValuedCellJoinOperation.class), json); } diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java index 38567d48f..0ebeadb82 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java @@ -67,6 +67,7 @@ import com.google.refine.process.Process; import com.google.refine.tests.RefineServletStub; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class KeyValueColumnizeTests extends RefineTest { @@ -119,14 +120,14 @@ public class KeyValueColumnizeTests extends RefineTest { + "\"keyColumnName\":\"key column\"," + "\"valueColumnName\":\"value column\"," + "\"noteColumnName\":null}"; - TestUtils.isSerializedTo(KeyValueColumnizeOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, KeyValueColumnizeOperation.class), json); String jsonFull = "{\"op\":\"core/key-value-columnize\"," + "\"description\":\"Columnize by key column key column and value column value column with note column note column\"," + "\"keyColumnName\":\"key column\"," + "\"valueColumnName\":\"value column\"," + "\"noteColumnName\":\"note column\"}"; - TestUtils.isSerializedTo(KeyValueColumnizeOperation.reconstruct(project, new JSONObject(jsonFull)), jsonFull); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(jsonFull, KeyValueColumnizeOperation.class), jsonFull); } /** diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java index da41c8c02..01497bd5d 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java @@ -3,15 +3,12 @@ package com.google.refine.tests.operations.cell; import java.util.List; import org.json.JSONException; -import org.json.JSONObject; import org.testng.Assert; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import static org.mockito.Mockito.mock; import com.fasterxml.jackson.core.type.TypeReference; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.cell.MassEditOperation; import com.google.refine.operations.cell.MassEditOperation.Edit; @@ -31,13 +28,12 @@ public class MassOperationTests extends RefineTest { @Test public void serializeMassEditOperation() throws JSONException, Exception { - Project project = mock(Project.class); String json = "{\"op\":\"core/mass-edit\"," + "\"description\":\"Mass edit cells in column my column\"," + "\"engineConfig\":{\"mode\":\"record-based\",\"facets\":[]}," + "\"columnName\":\"my column\",\"expression\":\"value\"," + "\"edits\":[{\"fromBlank\":false,\"fromError\":false,\"from\":[\"String\"],\"to\":\"newString\"}]}"; - TestUtils.isSerializedTo(MassEditOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, MassEditOperation.class), json); } @Test diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/SplitMultiValuedCellsTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/SplitMultiValuedCellsTests.java index da372dff0..a74aebdb0 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/SplitMultiValuedCellsTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/SplitMultiValuedCellsTests.java @@ -37,7 +37,6 @@ package com.google.refine.tests.operations.cell; import java.util.Properties; import org.json.JSONException; -import org.json.JSONObject; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.BeforeMethod; @@ -51,6 +50,7 @@ import com.google.refine.operations.cell.MultiValuedCellSplitOperation; import com.google.refine.process.Process; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class SplitMultiValuedCellsTests extends RefineTest { @@ -80,7 +80,7 @@ public class SplitMultiValuedCellsTests extends RefineTest { + "\"mode\":\"separator\"," + "\"separator\":\":\"," + "\"regex\":false}"; - TestUtils.isSerializedTo(MultiValuedCellSplitOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, MultiValuedCellSplitOperation.class), json); } @Test @@ -91,7 +91,7 @@ public class SplitMultiValuedCellsTests extends RefineTest { + "\"keyColumnName\":\"Key\"," + "\"mode\":\"lengths\"," + "\"fieldLengths\":[1,1]}"; - TestUtils.isSerializedTo(MultiValuedCellSplitOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, MultiValuedCellSplitOperation.class), json); } /** diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/TransposeTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/TransposeTests.java index 3c08cb0b3..b58977510 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/TransposeTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/TransposeTests.java @@ -33,19 +33,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.tests.operations.cell; -import static org.mockito.Mockito.mock; - import org.json.JSONException; -import org.json.JSONObject; import org.slf4j.LoggerFactory; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.cell.TransposeRowsIntoColumnsOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class TransposeTests extends RefineTest { @@ -62,8 +59,7 @@ public class TransposeTests extends RefineTest { + "\"description\":\"Transpose every 3 cells in column start column into separate columns\"," + "\"columnName\":\"start column\"," + "\"rowCount\":3}"; - Project project = mock(Project.class); - TestUtils.isSerializedTo(TransposeRowsIntoColumnsOperation.reconstruct(project , new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, TransposeRowsIntoColumnsOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionByFetchingURLsOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionByFetchingURLsOperationTests.java index 4697cf37a..41101a5ff 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionByFetchingURLsOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionByFetchingURLsOperationTests.java @@ -63,6 +63,7 @@ import com.google.refine.process.Process; import com.google.refine.process.ProcessManager; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ColumnAdditionByFetchingURLsOperationTests extends RefineTest { @@ -125,12 +126,12 @@ public class ColumnAdditionByFetchingURLsOperationTests extends RefineTest { @Test public void serializeColumnAdditionByFetchingURLsOperation() throws JSONException, Exception { - TestUtils.isSerializedTo(ColumnAdditionByFetchingURLsOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ColumnAdditionByFetchingURLsOperation.class), json); } @Test public void serializeUrlFetchingProcess() throws Exception { - AbstractOperation op = ColumnAdditionByFetchingURLsOperation.reconstruct(project, new JSONObject(json)); + AbstractOperation op = ParsingUtilities.mapper.readValue(json, ColumnAdditionByFetchingURLsOperation.class); Process process = op.createProcess(project, new Properties()); TestUtils.isSerializedTo(process, String.format(processJson, process.hashCode())); } diff --git a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionOperationTests.java index d150adafb..8bb492edd 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnAdditionOperationTests.java @@ -1,17 +1,14 @@ package com.google.refine.tests.operations.column; -import static org.mockito.Mockito.mock; - import org.json.JSONException; -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.column.ColumnAdditionOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ColumnAdditionOperationTests extends RefineTest { @@ -28,7 +25,6 @@ public class ColumnAdditionOperationTests extends RefineTest { + " \"expression\":\"grel:value.parseJson()[\\\"employment-summary\\\"].join('###')\"," + " \"onError\":\"set-to-blank\"" + "}"; - Project project = mock(Project.class); - TestUtils.isSerializedTo(ColumnAdditionOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ColumnAdditionOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnMoveOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnMoveOperationTests.java index 61d7aef91..a0ef81029 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnMoveOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnMoveOperationTests.java @@ -1,17 +1,14 @@ package com.google.refine.tests.operations.column; -import static org.mockito.Mockito.mock; - import org.json.JSONException; -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.column.ColumnMoveOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ColumnMoveOperationTests extends RefineTest { @@ -26,7 +23,6 @@ public class ColumnMoveOperationTests extends RefineTest { + "\"description\":\"Move column my column to position 3\"," + "\"columnName\":\"my column\"," + "\"index\":3}"; - Project project = mock(Project.class); - TestUtils.isSerializedTo(ColumnMoveOperation.reconstruct(project , new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ColumnMoveOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnRemovalOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnRemovalOperationTests.java index 36a87e417..3caf1f463 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnRemovalOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnRemovalOperationTests.java @@ -1,17 +1,14 @@ package com.google.refine.tests.operations.column; -import static org.mockito.Mockito.mock; - import org.json.JSONException; -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.column.ColumnRemovalOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ColumnRemovalOperationTests extends RefineTest { @@ -26,7 +23,6 @@ public class ColumnRemovalOperationTests extends RefineTest { String json = "{\"op\":\"core/column-removal\"," + "\"description\":\"Remove column my column\"," + "\"columnName\":\"my column\"}"; - Project project = mock(Project.class); - TestUtils.isSerializedTo(ColumnRemovalOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ColumnRemovalOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnRenameOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnRenameOperationTests.java index 917d6fdbc..b75a8ebb5 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnRenameOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnRenameOperationTests.java @@ -1,13 +1,10 @@ package com.google.refine.tests.operations.column; -import static org.mockito.Mockito.mock; - import org.json.JSONException; import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.column.ColumnRenameOperation; import com.google.refine.tests.RefineTest; @@ -27,7 +24,10 @@ public class ColumnRenameOperationTests extends RefineTest { + "\"description\":\"Rename column old name to new name\"," + "\"oldColumnName\":\"old name\"," + "\"newColumnName\":\"new name\"}"; - Project project = mock(Project.class); - TestUtils.isSerializedTo(ColumnRenameOperation.reconstruct(project, new JSONObject(json)), json); + JSONObject obj = new JSONObject(json); + TestUtils.isSerializedTo(new ColumnRenameOperation( + obj.getString("oldColumnName"), + obj.getString("newColumnName") + ), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnSplitOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnSplitOperationTests.java index 57949edd9..1a44a8251 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/column/ColumnSplitOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/column/ColumnSplitOperationTests.java @@ -1,17 +1,14 @@ package com.google.refine.tests.operations.column; -import static org.mockito.Mockito.mock; - import org.json.JSONException; -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.column.ColumnSplitOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ColumnSplitOperationTests extends RefineTest { @BeforeSuite @@ -36,8 +33,7 @@ public class ColumnSplitOperationTests extends RefineTest { " \"regex\": false,\n" + " \"maxColumns\": 0\n" + " }"; - Project project = mock(Project.class); - TestUtils.isSerializedTo(ColumnSplitOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ColumnSplitOperation.class), json); } @Test @@ -55,7 +51,6 @@ public class ColumnSplitOperationTests extends RefineTest { " \"mode\": \"lengths\",\n" + " \"fieldLengths\": [1,1]\n" + " }"; - Project project = mock(Project.class); - TestUtils.isSerializedTo(ColumnSplitOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ColumnSplitOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java index 17cdb98ba..8038c94d2 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ExtendDataOperationTests.java @@ -69,6 +69,7 @@ import com.google.refine.process.Process; import com.google.refine.process.ProcessManager; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ExtendDataOperationTests extends RefineTest { @@ -165,12 +166,12 @@ public class ExtendDataOperationTests extends RefineTest { @Test public void serializeExtendDataOperation() throws JSONException, Exception { - TestUtils.isSerializedTo(ExtendDataOperation.reconstruct(project, new JSONObject(operationJson)), operationJson); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(operationJson, ExtendDataOperation.class), operationJson); } @Test public void serializeExtendDataProcess() throws JSONException, Exception { - Process p = ExtendDataOperation.reconstruct(project, new JSONObject(operationJson)) + Process p = ParsingUtilities.mapper.readValue(operationJson, ExtendDataOperation.class) .createProcess(project, new Properties()); TestUtils.isSerializedTo(p, String.format(processJson, p.hashCode())); } diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconClearSimilarCellsOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconClearSimilarCellsOperationTests.java index bddfb4fed..6ca86e8c2 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconClearSimilarCellsOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconClearSimilarCellsOperationTests.java @@ -1,15 +1,12 @@ package com.google.refine.tests.operations.recon; -import static org.mockito.Mockito.mock; - -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.recon.ReconClearSimilarCellsOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ReconClearSimilarCellsOperationTests extends RefineTest { @BeforeSuite @@ -24,7 +21,6 @@ public class ReconClearSimilarCellsOperationTests extends RefineTest { + "\"engineConfig\":{\"mode\":\"row-based\",\"facets\":[]}," + "\"columnName\":\"my column\"," + "\"similarValue\":\"some value\"}"; - Project project = mock(Project.class); - TestUtils.isSerializedTo(ReconClearSimilarCellsOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ReconClearSimilarCellsOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconCopyAcrossColumnsOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconCopyAcrossColumnsOperationTests.java index 23b38e248..8fe76e10d 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconCopyAcrossColumnsOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconCopyAcrossColumnsOperationTests.java @@ -1,15 +1,12 @@ package com.google.refine.tests.operations.recon; -import static org.mockito.Mockito.mock; - -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.recon.ReconCopyAcrossColumnsOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ReconCopyAcrossColumnsOperationTests extends RefineTest { @BeforeSuite @@ -26,7 +23,6 @@ public class ReconCopyAcrossColumnsOperationTests extends RefineTest { + "\"toColumnNames\":[\"first\",\"second\"]," + "\"judgments\":[\"matched\",\"new\"]," + "\"applyToJudgedCells\":true}"; - Project project = mock(Project.class); - TestUtils.isSerializedTo(ReconCopyAcrossColumnsOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ReconCopyAcrossColumnsOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconDiscardJudgmentsOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconDiscardJudgmentsOperationTests.java index ce44bb9cd..c778ae5c3 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconDiscardJudgmentsOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconDiscardJudgmentsOperationTests.java @@ -1,15 +1,12 @@ package com.google.refine.tests.operations.recon; -import static org.mockito.Mockito.mock; - -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.recon.ReconDiscardJudgmentsOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ReconDiscardJudgmentsOperationTests extends RefineTest { @BeforeSuite @@ -29,7 +26,6 @@ public class ReconDiscardJudgmentsOperationTests extends RefineTest { " \"columnName\": \"researcher\",\n" + " \"clearData\": true\n" + " }"; - Project project = mock(Project.class); - TestUtils.isSerializedTo(ReconDiscardJudgmentsOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ReconDiscardJudgmentsOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsOperationTests.java index 76cf1e39e..ee31342fd 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsOperationTests.java @@ -1,14 +1,12 @@ package com.google.refine.tests.operations.recon; -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import static org.mockito.Mockito.mock; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.recon.ReconJudgeSimilarCellsOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ReconJudgeSimilarCellsOperationTests extends RefineTest { @BeforeSuite @@ -26,6 +24,6 @@ public class ReconJudgeSimilarCellsOperationTests extends RefineTest { + "\"judgment\":\"matched\"," + "\"match\":{\"id\":\"Q7884717\",\"name\":\"Unicef Indonesia\",\"score\":71.42857142857143,\"types\":[\"Q43229\"]}," + "\"shareNewTopics\":false}"; - TestUtils.isSerializedTo(ReconJudgeSimilarCellsOperation.reconstruct(mock(Project.class), new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ReconJudgeSimilarCellsOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java index 8587fa417..4f5c8d263 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconJudgeSimilarCellsTests.java @@ -2,7 +2,6 @@ package com.google.refine.tests.operations.recon; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import static org.mockito.Mockito.mock; import java.io.IOException; import java.util.Collections; @@ -26,6 +25,7 @@ import com.google.refine.operations.recon.ReconJudgeSimilarCellsOperation; import com.google.refine.process.Process; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ReconJudgeSimilarCellsTests extends RefineTest { @@ -47,7 +47,7 @@ public class ReconJudgeSimilarCellsTests extends RefineTest { + "\"similarValue\":\"foo\"," + "\"judgment\":\"new\"," + "\"shareNewTopics\":true}"; - TestUtils.isSerializedTo(ReconJudgeSimilarCellsOperation.reconstruct(mock(Project.class), new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ReconJudgeSimilarCellsOperation.class), json); } @Test @@ -61,7 +61,7 @@ public class ReconJudgeSimilarCellsTests extends RefineTest { + "\"match\":{\"id\":\"Q42\",\"name\":\"Douglas Adams\",\"types\":[\"Q5\"],\"score\":85}," + "\"shareNewTopics\":false" + "}"; - TestUtils.isSerializedTo(ReconJudgeSimilarCellsOperation.reconstruct(mock(Project.class), new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ReconJudgeSimilarCellsOperation.class), json); } @Test diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconMarkNewTopicsOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconMarkNewTopicsOperationTests.java index a63dea505..655dbbbfe 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconMarkNewTopicsOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconMarkNewTopicsOperationTests.java @@ -1,15 +1,12 @@ package com.google.refine.tests.operations.recon; -import static org.mockito.Mockito.mock; - -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.recon.ReconMarkNewTopicsOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ReconMarkNewTopicsOperationTests extends RefineTest { @BeforeSuite @@ -26,7 +23,6 @@ public class ReconMarkNewTopicsOperationTests extends RefineTest { + "\"shareNewTopics\":true," + "\"description\":\"Mark to create new items for cells in column my column, one item for each group of similar cells\"" + "}"; - Project project = mock(Project.class); - TestUtils.isSerializedTo(ReconMarkNewTopicsOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ReconMarkNewTopicsOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconMatchBestCandidatesOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconMatchBestCandidatesOperationTests.java index 63274e487..9213238b5 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconMatchBestCandidatesOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconMatchBestCandidatesOperationTests.java @@ -1,15 +1,12 @@ package com.google.refine.tests.operations.recon; -import static org.mockito.Mockito.mock; - -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.recon.ReconMatchBestCandidatesOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ReconMatchBestCandidatesOperationTests extends RefineTest { @BeforeSuite @@ -28,7 +25,6 @@ public class ReconMatchBestCandidatesOperationTests extends RefineTest { + "]}," + "\"columnName\":\"organization_name\"" + "}"; - Project project = mock(Project.class); - TestUtils.isSerializedTo(ReconMatchBestCandidatesOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ReconMatchBestCandidatesOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconMatchSpecificTopicOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconMatchSpecificTopicOperationTests.java index 1e1c51386..145e5b8c7 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconMatchSpecificTopicOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconMatchSpecificTopicOperationTests.java @@ -1,15 +1,12 @@ package com.google.refine.tests.operations.recon; -import static org.mockito.Mockito.mock; - -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.recon.ReconMatchSpecificTopicOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ReconMatchSpecificTopicOperationTests extends RefineTest { @BeforeSuite @@ -37,7 +34,6 @@ public class ReconMatchSpecificTopicOperationTests extends RefineTest { " \"identifierSpace\": \"http://www.wikidata.org/entity/\",\n" + " \"schemaSpace\": \"http://www.wikidata.org/prop/direct/\"\n" + " }"; - Project project = mock(Project.class); - TestUtils.isSerializedTo(ReconMatchSpecificTopicOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ReconMatchSpecificTopicOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconOperationTests.java index 1fed8577f..e5206cd17 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconOperationTests.java @@ -5,7 +5,6 @@ import static org.mockito.Mockito.mock; import java.util.Properties; import org.json.JSONException; -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; @@ -16,6 +15,7 @@ import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.recon.ReconOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ReconOperationTests extends RefineTest { @@ -74,12 +74,12 @@ public class ReconOperationTests extends RefineTest { @Test public void serializeReconOperation() throws JSONException, Exception { - TestUtils.isSerializedTo(ReconOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ReconOperation.class), json); } @Test public void serializeReconProcess() throws JSONException, Exception { - ReconOperation op = ReconOperation.reconstruct(project, new JSONObject(json)); + ReconOperation op = ParsingUtilities.mapper.readValue(json, ReconOperation.class); com.google.refine.process.Process process = op.createProcess(project, new Properties()); TestUtils.isSerializedTo(process, String.format(processJson, process.hashCode())); } diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconUseValuesAsIdsOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconUseValuesAsIdsOperationTests.java index 3a6d94036..249c4e967 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconUseValuesAsIdsOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconUseValuesAsIdsOperationTests.java @@ -6,7 +6,6 @@ import static org.testng.Assert.assertNull; import java.util.Properties; import org.json.JSONException; -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; @@ -16,6 +15,7 @@ import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.recon.ReconUseValuesAsIdentifiersOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class ReconUseValuesAsIdsOperationTests extends RefineTest { @@ -36,7 +36,7 @@ public class ReconUseValuesAsIdsOperationTests extends RefineTest { @Test public void serializeReconUseValuesAsIdentifiersOperation() throws JSONException, Exception { - TestUtils.isSerializedTo(ReconUseValuesAsIdentifiersOperation.reconstruct(new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, ReconUseValuesAsIdentifiersOperation.class), json); } @Test @@ -45,7 +45,7 @@ public class ReconUseValuesAsIdsOperationTests extends RefineTest { + "Q343,hello\n" + ",world\n" + "Q31,test"); - ReconUseValuesAsIdentifiersOperation op = ReconUseValuesAsIdentifiersOperation.reconstruct(new JSONObject(json)); + ReconUseValuesAsIdentifiersOperation op = ParsingUtilities.mapper.readValue(json, ReconUseValuesAsIdentifiersOperation.class); op.createProcess(project, new Properties()).performImmediate(); assertEquals("Q343", project.rows.get(0).cells.get(0).recon.match.id); diff --git a/main/tests/server/src/com/google/refine/tests/operations/row/DenormalizeOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/row/DenormalizeOperationTests.java index d5a344fe2..7e8457a08 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/row/DenormalizeOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/row/DenormalizeOperationTests.java @@ -3,7 +3,6 @@ package com.google.refine.tests.operations.row; import static org.mockito.Mockito.mock; import org.json.JSONException; -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; @@ -26,6 +25,6 @@ public class DenormalizeOperationTests extends RefineTest { String json = "{" + "\"op\":\"core/denormalize\"," + "\"description\":\"Denormalize\"}"; - TestUtils.isSerializedTo(DenormalizeOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(new DenormalizeOperation(), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/row/RowFlagOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/row/RowFlagOperationTests.java index e7c625706..d8afecad1 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/row/RowFlagOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/row/RowFlagOperationTests.java @@ -3,7 +3,6 @@ package com.google.refine.tests.operations.row; import static org.mockito.Mockito.mock; import org.json.JSONException; -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; @@ -12,6 +11,7 @@ import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.row.RowFlagOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class RowFlagOperationTests extends RefineTest { @BeforeSuite @@ -27,6 +27,6 @@ public class RowFlagOperationTests extends RefineTest { + "\"description\":\"Flag rows\"," + "\"flagged\":true," + "\"engineConfig\":{\"mode\":\"row-based\",\"facets\":[]}}"; - TestUtils.isSerializedTo(RowFlagOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, RowFlagOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/row/RowRemovalOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/row/RowRemovalOperationTests.java index 4be80efd3..db168c626 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/row/RowRemovalOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/row/RowRemovalOperationTests.java @@ -5,7 +5,6 @@ import static org.mockito.Mockito.mock; import java.io.IOException; import org.json.JSONException; -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; @@ -14,6 +13,7 @@ import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.row.RowRemovalOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class RowRemovalOperationTests extends RefineTest { @BeforeSuite @@ -28,6 +28,6 @@ public class RowRemovalOperationTests extends RefineTest { + "\"op\":\"core/row-removal\"," + "\"description\":\"Remove rows\"," + "\"engineConfig\":{\"mode\":\"row-based\",\"facets\":[]}}"; - TestUtils.isSerializedTo(RowRemovalOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, RowRemovalOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/row/RowReorderOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/row/RowReorderOperationTests.java index 08b91927b..adb1160bd 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/row/RowReorderOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/row/RowReorderOperationTests.java @@ -23,6 +23,7 @@ import com.google.refine.process.Process; import com.google.refine.sorting.SortingConfig; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class RowReorderOperationTests extends RefineTest { @@ -85,7 +86,7 @@ public class RowReorderOperationTests extends RefineTest { " ]\n" + " }\n" + " }"; - TestUtils.isSerializedTo(RowReorderOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, RowReorderOperation.class), json); } } diff --git a/main/tests/server/src/com/google/refine/tests/operations/row/RowStarOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/row/RowStarOperationTests.java index 84e829f69..924c50ff4 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/row/RowStarOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/row/RowStarOperationTests.java @@ -3,14 +3,15 @@ package com.google.refine.tests.operations.row; import static org.mockito.Mockito.mock; import org.json.JSONException; -import org.json.JSONObject; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; + import com.google.refine.model.Project; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.row.RowStarOperation; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class RowStarOperationTests extends RefineTest { @BeforeSuite @@ -26,6 +27,6 @@ public class RowStarOperationTests extends RefineTest { + "\"description\":\"Star rows\"," + "\"starred\":true," + "\"engineConfig\":{\"mode\":\"row-based\",\"facets\":[]}}"; - TestUtils.isSerializedTo(RowStarOperation.reconstruct(project, new JSONObject(json)), json); + TestUtils.isSerializedTo(ParsingUtilities.mapper.readValue(json, RowStarOperation.class), json); } } From 59f322d6077acd6fd77cb8b0fe0f03e6d822836c Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 22 Oct 2018 14:25:19 +0100 Subject: [PATCH 096/164] Remove AbstractOperation.reconstruct --- .../refine/commands/history/ApplyOperationsCommand.java | 3 +-- main/src/com/google/refine/history/HistoryEntry.java | 3 +-- main/src/com/google/refine/model/AbstractOperation.java | 1 + main/src/com/google/refine/operations/OperationRegistry.java | 4 ---- .../refine/{model => operations}/OperationResolver.java | 4 ++-- 5 files changed, 5 insertions(+), 10 deletions(-) rename main/src/com/google/refine/{model => operations}/OperationResolver.java (92%) diff --git a/main/src/com/google/refine/commands/history/ApplyOperationsCommand.java b/main/src/com/google/refine/commands/history/ApplyOperationsCommand.java index 136109acf..8fbfeab44 100644 --- a/main/src/com/google/refine/commands/history/ApplyOperationsCommand.java +++ b/main/src/com/google/refine/commands/history/ApplyOperationsCommand.java @@ -47,7 +47,6 @@ import org.json.JSONObject; import com.google.refine.commands.Command; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; -import com.google.refine.operations.OperationRegistry; import com.google.refine.process.Process; import com.google.refine.util.ParsingUtilities; @@ -79,7 +78,7 @@ public class ApplyOperationsCommand extends Command { } protected void reconstructOperation(Project project, JSONObject obj) throws IOException { - AbstractOperation operation = OperationRegistry.reconstruct(project, obj); + AbstractOperation operation = ParsingUtilities.mapper.readValue(obj.toString(), AbstractOperation.class); if (operation != null) { try { Process process = operation.createProcess(project, new Properties()); diff --git a/main/src/com/google/refine/history/HistoryEntry.java b/main/src/com/google/refine/history/HistoryEntry.java index f2c7f793d..137bae283 100644 --- a/main/src/com/google/refine/history/HistoryEntry.java +++ b/main/src/com/google/refine/history/HistoryEntry.java @@ -49,7 +49,6 @@ import com.fasterxml.jackson.annotation.JsonView; import com.google.refine.ProjectManager; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; -import com.google.refine.operations.OperationRegistry; import com.google.refine.util.JsonViews; import com.google.refine.util.ParsingUtilities; @@ -159,7 +158,7 @@ public class HistoryEntry { AbstractOperation operation = null; if (obj.has(OPERATION) && !obj.isNull(OPERATION)) { - operation = OperationRegistry.reconstruct(project, obj.getJSONObject(OPERATION)); + operation = ParsingUtilities.mapper.readValue(obj.getJSONObject(OPERATION).toString(), AbstractOperation.class); } return new HistoryEntry( diff --git a/main/src/com/google/refine/model/AbstractOperation.java b/main/src/com/google/refine/model/AbstractOperation.java index 16fd68741..6ab8135c3 100644 --- a/main/src/com/google/refine/model/AbstractOperation.java +++ b/main/src/com/google/refine/model/AbstractOperation.java @@ -41,6 +41,7 @@ import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver; import com.google.refine.history.HistoryEntry; import com.google.refine.operations.OperationRegistry; +import com.google.refine.operations.OperationResolver; import com.google.refine.process.Process; import com.google.refine.process.QuickHistoryEntryProcess; diff --git a/main/src/com/google/refine/operations/OperationRegistry.java b/main/src/com/google/refine/operations/OperationRegistry.java index e947c510c..3a352917e 100644 --- a/main/src/com/google/refine/operations/OperationRegistry.java +++ b/main/src/com/google/refine/operations/OperationRegistry.java @@ -82,8 +82,4 @@ public abstract class OperationRegistry { } return null; } - - static public AbstractOperation reconstruct(Project project, JSONObject obj) throws IOException { - return ParsingUtilities.mapper.readValue(obj.toString(), AbstractOperation.class); - } } diff --git a/main/src/com/google/refine/model/OperationResolver.java b/main/src/com/google/refine/operations/OperationResolver.java similarity index 92% rename from main/src/com/google/refine/model/OperationResolver.java rename to main/src/com/google/refine/operations/OperationResolver.java index 6a12b8db4..5f8085e48 100644 --- a/main/src/com/google/refine/model/OperationResolver.java +++ b/main/src/com/google/refine/operations/OperationResolver.java @@ -1,4 +1,4 @@ -package com.google.refine.model; +package com.google.refine.operations; import java.io.IOException; @@ -8,7 +8,7 @@ import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase; import com.fasterxml.jackson.databind.type.TypeFactory; -import com.google.refine.operations.OperationRegistry; +import com.google.refine.model.AbstractOperation; public class OperationResolver extends TypeIdResolverBase { From 52426b98a3c29434999fe4c4f41b60fd47173364 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Tue, 23 Oct 2018 10:33:37 +0100 Subject: [PATCH 097/164] Jackson deserialization for CsvExporter --- .../google/refine/exporters/CsvExporter.java | 30 +++++++++++++------ .../tests/exporters/CsvExporterTests.java | 17 +++++++++++ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/main/src/com/google/refine/exporters/CsvExporter.java b/main/src/com/google/refine/exporters/CsvExporter.java index 55fa25aff..913d61d4f 100644 --- a/main/src/com/google/refine/exporters/CsvExporter.java +++ b/main/src/com/google/refine/exporters/CsvExporter.java @@ -43,9 +43,10 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.Engine; import com.google.refine.model.Project; -import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; import au.com.bytecode.opencsv.CSVWriter; @@ -62,26 +63,37 @@ public class CsvExporter implements WriterExporter{ public CsvExporter(char separator) { this.separator = separator; } + + private static class Configuration { + @JsonProperty("separator") + protected String separator = null; + @JsonProperty("lineSeparator") + protected String lineSeparator = CSVWriter.DEFAULT_LINE_END; + @JsonProperty("quoteAll") + protected boolean quoteAll = false; + } @Override public void export(Project project, Properties params, Engine engine, final Writer writer) throws IOException { String optionsString = (params == null) ? null : params.getProperty("options"); - JSONObject options = null; + Configuration options = new Configuration(); if (optionsString != null) { try { - options = ParsingUtilities.evaluateJsonStringToObject(optionsString); - } catch (JSONException e) { + options = ParsingUtilities.mapper.readValue(optionsString, Configuration.class); + if (options.separator == null) { + options.separator = Character.toString(separator); + } + } catch (IOException e) { // Ignore and keep options null. + e.printStackTrace(); } } - final String separator = options == null ? Character.toString(this.separator) : - JSONUtilities.getString(options, "separator", Character.toString(this.separator)); - final String lineSeparator = options == null ? CSVWriter.DEFAULT_LINE_END : - JSONUtilities.getString(options, "lineSeparator", CSVWriter.DEFAULT_LINE_END); - final boolean quoteAll = options == null ? false : JSONUtilities.getBoolean(options, "quoteAll", false); + final String separator = options.separator; + final String lineSeparator = options.lineSeparator; + final boolean quoteAll = options.quoteAll; final boolean printColumnHeader = (params != null && params.getProperty("printColumnHeader") != null) ? diff --git a/main/tests/server/src/com/google/refine/tests/exporters/CsvExporterTests.java b/main/tests/server/src/com/google/refine/tests/exporters/CsvExporterTests.java index 5c482a613..789823d1b 100644 --- a/main/tests/server/src/com/google/refine/tests/exporters/CsvExporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/exporters/CsvExporterTests.java @@ -125,6 +125,23 @@ public class CsvExporterTests extends RefineTest { verify(options,times(2)).getProperty("printColumnHeader"); } + + @Test + public void exportSimpleCsvCustomLineSeparator(){ + CreateGrid(2, 2); + when(options.getProperty("options")).thenReturn("{\"lineSeparator\":\"X\"}"); + + try { + SUT.export(project, options, engine, writer); + } catch (IOException e) { + Assert.fail(); + } + + Assert.assertEquals(writer.toString(), "column0,column1X" + + "row0cell0,row0cell1X" + + "row1cell0,row1cell1X"); + + } @Test public void exportCsvWithLineBreaks(){ From 2873035ee21168230a5dd35c4367f5656d3a9ecf Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 2 Nov 2018 14:05:33 +0000 Subject: [PATCH 098/164] Migrate TabularExporter to use JsonNode --- .../gdata/FusionTableSerializer.java | 5 +- .../gdata/SpreadsheetSerializer.java | 6 +- .../google/refine/exporters/CsvExporter.java | 11 +- .../CustomizableTabularExporterUtilities.java | 173 ++++++++++-------- .../refine/exporters/HtmlTableExporter.java | 4 +- .../google/refine/exporters/OdsExporter.java | 5 +- .../refine/exporters/TabularSerializer.java | 4 +- .../google/refine/exporters/XlsExporter.java | 5 +- .../exporters/sql/SqlCreateBuilder.java | 16 +- .../refine/exporters/sql/SqlExporter.java | 12 +- .../exporters/sql/SqlInsertBuilder.java | 24 ++- .../com/google/refine/util/JSONUtilities.java | 38 ++++ .../tests/exporters/sql/SqlExporterTests.java | 50 +++-- 13 files changed, 207 insertions(+), 146 deletions(-) diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableSerializer.java b/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableSerializer.java index 059fe66ab..230d836be 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableSerializer.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableSerializer.java @@ -4,13 +4,14 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; import com.google.api.client.http.AbstractInputStreamContent; import com.google.api.client.http.ByteArrayContent; import com.google.api.client.http.HttpResponseException; import com.google.api.services.fusiontables.Fusiontables; +import com.google.refine.exporters.CustomizableTabularExporterConfiguration; import com.google.refine.exporters.TabularSerializer; final class FusionTableSerializer implements TabularSerializer { @@ -31,7 +32,7 @@ final class FusionTableSerializer implements TabularSerializer { } @Override - public void startFile(JSONObject options) { + public void startFile(JsonNode options) { } @Override diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/SpreadsheetSerializer.java b/extensions/gdata/src/com/google/refine/extension/gdata/SpreadsheetSerializer.java index 145a92a2d..1aa6300e1 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/SpreadsheetSerializer.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/SpreadsheetSerializer.java @@ -6,10 +6,11 @@ import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.JsonNode; + import com.google.api.services.sheets.v4.Sheets; import com.google.api.services.sheets.v4.model.AppendCellsRequest; import com.google.api.services.sheets.v4.model.BatchUpdateSpreadsheetRequest; @@ -18,6 +19,7 @@ import com.google.api.services.sheets.v4.model.ExtendedValue; import com.google.api.services.sheets.v4.model.Request; import com.google.api.services.sheets.v4.model.RowData; +import com.google.refine.exporters.CustomizableTabularExporterConfiguration; import com.google.refine.exporters.TabularSerializer; final class SpreadsheetSerializer implements TabularSerializer { @@ -44,7 +46,7 @@ final class SpreadsheetSerializer implements TabularSerializer { } @Override - public void startFile(JSONObject options) { + public void startFile(JsonNode options) { } diff --git a/main/src/com/google/refine/exporters/CsvExporter.java b/main/src/com/google/refine/exporters/CsvExporter.java index 913d61d4f..a25276703 100644 --- a/main/src/com/google/refine/exporters/CsvExporter.java +++ b/main/src/com/google/refine/exporters/CsvExporter.java @@ -38,12 +38,11 @@ import java.io.Writer; import java.util.List; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; import com.google.refine.browsing.Engine; import com.google.refine.model.Project; @@ -82,14 +81,14 @@ public class CsvExporter implements WriterExporter{ if (optionsString != null) { try { options = ParsingUtilities.mapper.readValue(optionsString, Configuration.class); - if (options.separator == null) { - options.separator = Character.toString(separator); - } } catch (IOException e) { // Ignore and keep options null. e.printStackTrace(); } } + if (options.separator == null) { + options.separator = Character.toString(separator); + } final String separator = options.separator; final String lineSeparator = options.lineSeparator; @@ -105,7 +104,7 @@ public class CsvExporter implements WriterExporter{ TabularSerializer serializer = new TabularSerializer() { @Override - public void startFile(JSONObject options) { + public void startFile(JsonNode options) { } @Override diff --git a/main/src/com/google/refine/exporters/CustomizableTabularExporterUtilities.java b/main/src/com/google/refine/exporters/CustomizableTabularExporterUtilities.java index 00c203ad6..e395f8d86 100644 --- a/main/src/com/google/refine/exporters/CustomizableTabularExporterUtilities.java +++ b/main/src/com/google/refine/exporters/CustomizableTabularExporterUtilities.java @@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.exporters; +import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.time.OffsetDateTime; @@ -47,9 +48,12 @@ import java.util.TimeZone; import org.apache.commons.lang3.StringUtils; import org.apache.commons.validator.routines.UrlValidator; import org.json.JSONArray; -import org.json.JSONException; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.google.refine.ProjectManager; import com.google.refine.browsing.Engine; import com.google.refine.browsing.FilteredRows; @@ -65,6 +69,8 @@ import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; abstract public class CustomizableTabularExporterUtilities { + final static private String fullIso8601 = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + static public void exportRows( final Project project, final Engine engine, @@ -72,15 +78,15 @@ abstract public class CustomizableTabularExporterUtilities { final TabularSerializer serializer) { String optionsString = (params != null) ? params.getProperty("options") : null; - JSONObject optionsTemp = null; + JsonNode optionsTemp = null; if (optionsString != null) { try { - optionsTemp = ParsingUtilities.evaluateJsonStringToObject(optionsString); - } catch (JSONException e) { + optionsTemp = ParsingUtilities.mapper.readTree(optionsString); + } catch (IOException e) { // Ignore and keep options null. } } - final JSONObject options = optionsTemp; + final JsonNode options = optionsTemp; final boolean outputColumnHeaders = options == null ? true : JSONUtilities.getBoolean(options, "outputColumnHeaders", true); @@ -93,7 +99,7 @@ abstract public class CustomizableTabularExporterUtilities { final Map columnNameToFormatter = new HashMap(); - JSONArray columnOptionArray = options == null ? null : + List columnOptionArray = options == null ? null : JSONUtilities.getArray(options, "columns"); if (columnOptionArray == null) { List columns = project.columnModel.columns; @@ -105,16 +111,20 @@ abstract public class CustomizableTabularExporterUtilities { columnNameToFormatter.put(name, new CellFormatter()); } } else { - int count = columnOptionArray.length(); + int count = columnOptionArray.size(); columnNames = new ArrayList(count); for (int i = 0; i < count; i++) { - JSONObject columnOptions = JSONUtilities.getObjectElement(columnOptionArray, i); + JsonNode columnOptions = columnOptionArray.get(i); if (columnOptions != null) { String name = JSONUtilities.getString(columnOptions, "name", null); if (name != null) { columnNames.add(name); - columnNameToFormatter.put(name, new CellFormatter(columnOptions)); + try { + columnNameToFormatter.put(name, ParsingUtilities.mapper.treeToValue(columnOptions, ColumnOptions.class)); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } } } } @@ -186,7 +196,7 @@ abstract public class CustomizableTabularExporterUtilities { int rows; @Override - public void startFile(JSONObject options) { + public void startFile(JsonNode options) { } @Override @@ -201,30 +211,62 @@ abstract public class CustomizableTabularExporterUtilities { } private enum ReconOutputMode { + @JsonProperty("entity-name") ENTITY_NAME, + @JsonProperty("entity-id") ENTITY_ID, + @JsonProperty("cell-content") CELL_CONTENT } private enum DateFormatMode { + @JsonProperty("iso-8601") ISO_8601, + @JsonProperty("locale-short") SHORT_LOCALE, + @JsonProperty("locale-medium") MEDIUM_LOCALE, + @JsonProperty("locale-long") LONG_LOCALE, + @JsonProperty("locale-full") FULL_LOCALE, + @JsonProperty("custom") CUSTOM } - final static private String fullIso8601 = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + static private class ReconSettings { + @JsonProperty("output") + ReconOutputMode outputMode = ReconOutputMode.ENTITY_NAME; + @JsonProperty("blankUnmatchedCells") + boolean blankUnmatchedCells = false; + @JsonProperty("linkToEntityPages") + boolean linkToEntityPages = true; + } - static private class CellFormatter { - ReconOutputMode recon_outputMode = ReconOutputMode.ENTITY_NAME; - boolean recon_blankUnmatchedCells = false; - boolean recon_linkToEntityPages = true; + static private class DateSettings { + @JsonProperty("format") + DateFormatMode formatMode = DateFormatMode.ISO_8601; + @JsonProperty("custom") + String custom = null; + @JsonProperty("useLocalTimeZone") + boolean useLocalTimeZone = false; + @JsonProperty("omitTime") + boolean omitTime = false; + } + + static public class ColumnOptions extends CellFormatter { + @JsonProperty("name") + String columnName; + } + + static public class CellFormatter { + @JsonProperty("reconSettings") + ReconSettings recon = new ReconSettings(); + @JsonProperty("dateSettings") + DateSettings date = new DateSettings(); - DateFormatMode date_formatMode = DateFormatMode.ISO_8601; - String date_custom = null; - boolean date_useLocalTimeZone = false; - boolean date_omitTime = false; + //SQLExporter parameter to convert null cell value to empty string + @JsonProperty("nullValueToEmptyStr") + boolean includeNullFieldValue = false; DateFormat dateFormatter; String[] urlSchemes = {"http","https", "ftp"}; @@ -232,88 +274,65 @@ abstract public class CustomizableTabularExporterUtilities { Map identifierSpaceToUrl = null; - //SQLExporter parameter to convert null cell value to empty string - boolean includeNullFieldValue = false; - - CellFormatter() { - dateFormatter = new SimpleDateFormat(fullIso8601); + @JsonCreator + CellFormatter( + @JsonProperty("reconSettings") + ReconSettings reconSettings, + @JsonProperty("dateSettings") + DateSettings dateSettings, + @JsonProperty("nullValueToEmptyStr") + boolean includeNullFieldValue) { + if(reconSettings != null) { + recon = reconSettings; + } + if(dateSettings != null) { + date = dateSettings; + } + setup(); } - CellFormatter(JSONObject options) { - JSONObject reconSettings = JSONUtilities.getObject(options, "reconSettings"); - includeNullFieldValue = JSONUtilities.getBoolean(options, "nullValueToEmptyStr", false); - if (reconSettings != null) { - String reconOutputString = JSONUtilities.getString(reconSettings, "output", null); - if ("entity-name".equals(reconOutputString)) { - recon_outputMode = ReconOutputMode.ENTITY_NAME; - } else if ("entity-id".equals(reconOutputString)) { - recon_outputMode = ReconOutputMode.ENTITY_ID; - } else if ("cell-content".equals(reconOutputString)) { - recon_outputMode = ReconOutputMode.CELL_CONTENT; - } - - recon_blankUnmatchedCells = JSONUtilities.getBoolean(reconSettings, "blankUnmatchedCells", recon_blankUnmatchedCells); - recon_linkToEntityPages = JSONUtilities.getBoolean(reconSettings, "linkToEntityPages", recon_linkToEntityPages); - } - JSONObject dateSettings = JSONUtilities.getObject(options, "dateSettings"); - if (dateSettings != null) { - String dateFormatString = JSONUtilities.getString(dateSettings, "format", null); - if ("iso-8601".equals(dateFormatString)) { - date_formatMode = DateFormatMode.ISO_8601; - } else if ("locale-short".equals(dateFormatString)) { - date_formatMode = DateFormatMode.SHORT_LOCALE; - } else if ("locale-medium".equals(dateFormatString)) { - date_formatMode = DateFormatMode.MEDIUM_LOCALE; - } else if ("locale-long".equals(dateFormatString)) { - date_formatMode = DateFormatMode.LONG_LOCALE; - } else if ("locale-full".equals(dateFormatString)) { - date_formatMode = DateFormatMode.FULL_LOCALE; - } else if ("custom".equals(dateFormatString)) { - date_formatMode = DateFormatMode.CUSTOM; - } - - date_custom = JSONUtilities.getString(dateSettings, "custom", null); - date_useLocalTimeZone = JSONUtilities.getBoolean(dateSettings, "useLocalTimeZone", date_useLocalTimeZone); - date_omitTime = JSONUtilities.getBoolean(dateSettings, "omitTime", date_omitTime); - - if (date_formatMode == DateFormatMode.CUSTOM && - (date_custom == null || date_custom.isEmpty())) { - date_formatMode = DateFormatMode.ISO_8601; - } + CellFormatter() { + setup(); + } + + private void setup() { + if (date.formatMode == DateFormatMode.CUSTOM && + (date.custom == null || date.custom.isEmpty())) { + date.formatMode = DateFormatMode.ISO_8601; } - switch (date_formatMode) { + switch (date.formatMode) { case SHORT_LOCALE: - dateFormatter = date_omitTime ? + dateFormatter = date.omitTime ? SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT) : SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.SHORT); break; case MEDIUM_LOCALE: - dateFormatter = date_omitTime ? + dateFormatter = date.omitTime ? SimpleDateFormat.getDateInstance(SimpleDateFormat.MEDIUM) : SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.MEDIUM, SimpleDateFormat.MEDIUM); break; case LONG_LOCALE: - dateFormatter = date_omitTime ? + dateFormatter = date.omitTime ? SimpleDateFormat.getDateInstance(SimpleDateFormat.LONG) : SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.LONG, SimpleDateFormat.LONG); break; case FULL_LOCALE: - dateFormatter = date_omitTime ? + dateFormatter = date.omitTime ? SimpleDateFormat.getDateInstance(SimpleDateFormat.FULL) : SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.FULL, SimpleDateFormat.FULL); break; case CUSTOM: - dateFormatter = new SimpleDateFormat(date_custom); + dateFormatter = new SimpleDateFormat(date.custom); break; default: - dateFormatter = date_omitTime ? + dateFormatter = date.omitTime ? new SimpleDateFormat("yyyy-MM-dd") : new SimpleDateFormat(fullIso8601); } - if (!date_useLocalTimeZone) { + if (!date.useLocalTimeZone) { dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); } } @@ -326,13 +345,13 @@ abstract public class CustomizableTabularExporterUtilities { if (cell.recon != null) { Recon recon = cell.recon; if (recon.judgment == Recon.Judgment.Matched) { - if (recon_outputMode == ReconOutputMode.ENTITY_NAME) { + if (this.recon.outputMode == ReconOutputMode.ENTITY_NAME) { text = recon.match.name; - } else if (recon_outputMode == ReconOutputMode.ENTITY_ID) { + } else if (this.recon.outputMode == ReconOutputMode.ENTITY_ID) { text = recon.match.id; } // else: output cell content - if (recon_linkToEntityPages) { + if (this.recon.linkToEntityPages) { buildIdentifierSpaceToUrlMap(); String service = recon.service; @@ -341,7 +360,7 @@ abstract public class CustomizableTabularExporterUtilities { link = StringUtils.replace(viewUrl, "{{id}}", recon.match.id); } } - } else if (recon_blankUnmatchedCells) { + } else if (this.recon.blankUnmatchedCells) { return null; } } diff --git a/main/src/com/google/refine/exporters/HtmlTableExporter.java b/main/src/com/google/refine/exporters/HtmlTableExporter.java index 3cb6ee926..530a6e9d5 100644 --- a/main/src/com/google/refine/exporters/HtmlTableExporter.java +++ b/main/src/com/google/refine/exporters/HtmlTableExporter.java @@ -41,6 +41,8 @@ import java.util.Properties; import org.apache.commons.lang3.StringEscapeUtils; import org.json.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; + import com.google.refine.ProjectManager; import com.google.refine.browsing.Engine; import com.google.refine.model.Project; @@ -58,7 +60,7 @@ public class HtmlTableExporter implements WriterExporter { TabularSerializer serializer = new TabularSerializer() { @Override - public void startFile(JSONObject options) { + public void startFile(JsonNode options) { try { writer.write("\n"); writer.write("\n"); diff --git a/main/src/com/google/refine/exporters/OdsExporter.java b/main/src/com/google/refine/exporters/OdsExporter.java index ee4730cb7..e397d0ded 100644 --- a/main/src/com/google/refine/exporters/OdsExporter.java +++ b/main/src/com/google/refine/exporters/OdsExporter.java @@ -39,12 +39,13 @@ import java.time.OffsetDateTime; import java.util.List; import java.util.Properties; -import org.json.JSONObject; import org.odftoolkit.odfdom.doc.OdfSpreadsheetDocument; import org.odftoolkit.odfdom.doc.table.OdfTable; import org.odftoolkit.odfdom.doc.table.OdfTableCell; import org.odftoolkit.odfdom.doc.table.OdfTableRow; +import com.fasterxml.jackson.databind.JsonNode; + import com.google.refine.ProjectManager; import com.google.refine.browsing.Engine; import com.google.refine.model.Project; @@ -73,7 +74,7 @@ public class OdsExporter implements StreamExporter { //int rowCount = 0; @Override - public void startFile(JSONObject options) { + public void startFile(JsonNode options) { table = OdfTable.newTable(odfDoc); table.setTableName(ProjectManager.singleton.getProjectMetadata(project.id).getName()); } diff --git a/main/src/com/google/refine/exporters/TabularSerializer.java b/main/src/com/google/refine/exporters/TabularSerializer.java index 48f1c9cd3..09a7e8d73 100644 --- a/main/src/com/google/refine/exporters/TabularSerializer.java +++ b/main/src/com/google/refine/exporters/TabularSerializer.java @@ -2,7 +2,7 @@ package com.google.refine.exporters; import java.util.List; -import org.json.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; /** @@ -25,7 +25,7 @@ public interface TabularSerializer { } } - public void startFile(JSONObject options); + public void startFile(JsonNode options); public void endFile(); diff --git a/main/src/com/google/refine/exporters/XlsExporter.java b/main/src/com/google/refine/exporters/XlsExporter.java index 4269df0fa..3910f5cef 100644 --- a/main/src/com/google/refine/exporters/XlsExporter.java +++ b/main/src/com/google/refine/exporters/XlsExporter.java @@ -48,7 +48,8 @@ import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.WorkbookUtil; import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.json.JSONObject; + +import com.fasterxml.jackson.databind.JsonNode; import com.google.refine.ProjectManager; import com.google.refine.browsing.Engine; @@ -79,7 +80,7 @@ public class XlsExporter implements StreamExporter { CellStyle dateStyle; @Override - public void startFile(JSONObject options) { + public void startFile(JsonNode options) { s = wb.createSheet(); String sheetName = WorkbookUtil.createSafeSheetName( ProjectManager.singleton.getProjectMetadata(project.id).getName()); diff --git a/main/src/com/google/refine/exporters/sql/SqlCreateBuilder.java b/main/src/com/google/refine/exporters/sql/SqlCreateBuilder.java index 55a62b591..7f90b9549 100755 --- a/main/src/com/google/refine/exporters/sql/SqlCreateBuilder.java +++ b/main/src/com/google/refine/exporters/sql/SqlCreateBuilder.java @@ -29,13 +29,13 @@ package com.google.refine.exporters.sql; +import java.util.Collections; import java.util.List; -import org.json.JSONArray; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.JsonNode; import com.google.refine.util.JSONUtilities; public class SqlCreateBuilder { @@ -44,13 +44,13 @@ public class SqlCreateBuilder { private String table; private List columns; - private JSONObject options; + private JsonNode options; - public SqlCreateBuilder(String table, List columns, JSONObject options) { + public SqlCreateBuilder(String table, List columns, JsonNode sqlOptions) { this.table = table; this.columns = columns; - this.options = options; + this.options = sqlOptions; } @@ -60,15 +60,15 @@ public class SqlCreateBuilder { } StringBuffer createSB = new StringBuffer(); - JSONArray columnOptionArray = options == null ? null : JSONUtilities.getArray(options, "columns"); + List columnOptionArray = options == null ? Collections.emptyList() : JSONUtilities.getArray(options, "columns"); boolean trimColNames = options == null ? false : JSONUtilities.getBoolean(options, "trimColumnNames", false); - int count = columnOptionArray.length(); + int count = columnOptionArray.size(); for (int i = 0; i < count; i++) { - JSONObject columnOptions = JSONUtilities.getObjectElement(columnOptionArray, i); + JsonNode columnOptions = columnOptionArray.get(i); if (columnOptions != null) { String name = JSONUtilities.getString(columnOptions, "name", null); String type = JSONUtilities.getString(columnOptions, "type", SqlData.SQL_TYPE_VARCHAR); diff --git a/main/src/com/google/refine/exporters/sql/SqlExporter.java b/main/src/com/google/refine/exporters/sql/SqlExporter.java index 808cf45e7..dd00a2f00 100755 --- a/main/src/com/google/refine/exporters/sql/SqlExporter.java +++ b/main/src/com/google/refine/exporters/sql/SqlExporter.java @@ -39,6 +39,8 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.JsonNode; + import com.google.refine.ProjectManager; import com.google.refine.browsing.Engine; import com.google.refine.exporters.CustomizableTabularExporterUtilities; @@ -59,7 +61,7 @@ public class SqlExporter implements WriterExporter { private List columnNames = new ArrayList(); private List> sqlDataList = new ArrayList>(); - private JSONObject sqlOptions; + private JsonNode sqlOptions; @Override @@ -77,7 +79,7 @@ public class SqlExporter implements WriterExporter { TabularSerializer serializer = new TabularSerializer() { @Override - public void startFile(JSONObject options) { + public void startFile(JsonNode options) { sqlOptions = options; //logger.info("setting options::{}", sqlOptions); } @@ -97,10 +99,10 @@ public class SqlExporter implements WriterExporter { } String tableName = ProjectManager.singleton.getProjectMetadata(project.id).getName(); - Object tableNameManual = sqlOptions.get(JSON_TABLE_NAME); + String tableNameManual = JSONUtilities.getString(sqlOptions, JSON_TABLE_NAME, null); - if (tableNameManual != null && !tableNameManual.toString().isEmpty()) { - tableName = tableNameManual.toString(); + if (tableNameManual != null) { + tableName = tableNameManual; } SqlCreateBuilder createBuilder = new SqlCreateBuilder(tableName, columnNames, sqlOptions); diff --git a/main/src/com/google/refine/exporters/sql/SqlInsertBuilder.java b/main/src/com/google/refine/exporters/sql/SqlInsertBuilder.java index 2abedf0f5..8c49e2b01 100755 --- a/main/src/com/google/refine/exporters/sql/SqlInsertBuilder.java +++ b/main/src/com/google/refine/exporters/sql/SqlInsertBuilder.java @@ -36,11 +36,10 @@ import java.util.Map; import java.util.stream.Collectors; import org.apache.commons.lang3.math.NumberUtils; -import org.json.JSONArray; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.JsonNode; import com.google.refine.util.JSONUtilities; public class SqlInsertBuilder { @@ -53,7 +52,7 @@ public class SqlInsertBuilder { private List> sqlDataList; - private JSONObject options; + private JsonNode options; /** @@ -61,15 +60,15 @@ public class SqlInsertBuilder { * @param table * @param columns * @param rows - * @param options + * @param sqlOptions * @param sqlErrors */ - public SqlInsertBuilder(String table, List columns, List> rows, JSONObject options + public SqlInsertBuilder(String table, List columns, List> rows, JsonNode sqlOptions ) { this.table = table; this.columns = columns; this.sqlDataList = rows; - this.options = options; + this.options = sqlOptions; //logger.info("Column Size:{}", columns.size()); } @@ -83,12 +82,11 @@ public class SqlInsertBuilder { logger.debug("Insert SQL with columns: {}", columns); } - JSONArray colOptionArray = options == null ? null : JSONUtilities.getArray(options, "columns"); - Map colOptionsMap = new HashMap(); + List colOptionArray = options == null ? null : JSONUtilities.getArray(options, "columns"); + Map colOptionsMap = new HashMap<>(); if(colOptionArray != null) { - colOptionArray.forEach(c -> { - JSONObject json = (JSONObject)c; - colOptionsMap.put("" + json.get("name"), json); + colOptionArray.forEach(json -> { + colOptionsMap.put(JSONUtilities.getString(json, "name", null), json); }); } @@ -103,8 +101,8 @@ public class SqlInsertBuilder { //int fieldCount = 0; for(SqlData val : sqlRow) { - JSONObject jsonOb = colOptionsMap.get(val.getColumnName()); - String type = (String)jsonOb.get("type"); + JsonNode jsonOb = colOptionsMap.get(val.getColumnName()); + String type = JSONUtilities.getString(jsonOb, "type", null); String defaultValue = JSONUtilities.getString(jsonOb, "defaultValue", null); diff --git a/main/src/com/google/refine/util/JSONUtilities.java b/main/src/com/google/refine/util/JSONUtilities.java index ea94a17e8..5d2ef8711 100644 --- a/main/src/com/google/refine/util/JSONUtilities.java +++ b/main/src/com/google/refine/util/JSONUtilities.java @@ -47,8 +47,14 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeType; + +import com.google.common.collect.Lists; + public class JSONUtilities { + static public JSONObject getObject(JSONObject obj, String key) { try { return obj.getJSONObject(key); @@ -65,6 +71,14 @@ public class JSONUtilities { } } + static public String getString(JsonNode obj, String key, String def) { + if (obj.get(key) != null) { + return obj.get(key).textValue(); + } else { + return def; + } + } + static public int getInt(JSONObject obj, String key, int def) { try { return obj.getInt(key); @@ -73,6 +87,14 @@ public class JSONUtilities { } } + static public int getInt(JsonNode obj, String key, int def) { + if (obj.get(key) != null) { + return obj.get(key).asInt(def); + } else { + return def; + } + } + static public boolean getBoolean(JSONObject obj, String key, boolean def) { try { return obj.getBoolean(key); @@ -81,6 +103,14 @@ public class JSONUtilities { } } + static public boolean getBoolean(JsonNode obj, String key, boolean def) { + if (obj.get(key) != null) { + return obj.get(key).asBoolean(def); + } else { + return def; + } + } + static public double getDouble(JSONObject obj, String key, double def) { try { return obj.getDouble(key); @@ -125,6 +155,14 @@ public class JSONUtilities { } } + static public List getArray(JsonNode obj, String key) { + if (obj.has(key) && obj.get(key).getNodeType().equals(JsonNodeType.ARRAY)) { + return Lists.newArrayList(obj.get(key).elements()); + } else { + return null; + } + } + static public JSONArray arrayToJSONArray(String[] array) { return new JSONArray(Arrays.asList(array)); } diff --git a/main/tests/server/src/com/google/refine/tests/exporters/sql/SqlExporterTests.java b/main/tests/server/src/com/google/refine/tests/exporters/sql/SqlExporterTests.java index c6f8dcbfa..0b3073c20 100644 --- a/main/tests/server/src/com/google/refine/tests/exporters/sql/SqlExporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/exporters/sql/SqlExporterTests.java @@ -54,6 +54,9 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.ProjectManager; import com.google.refine.browsing.Engine; import com.google.refine.exporters.sql.SqlCreateBuilder; @@ -68,6 +71,8 @@ import com.google.refine.model.Row; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.ProjectManagerStub; import com.google.refine.tests.RefineTest; +import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class SqlExporterTests extends RefineTest { @@ -180,14 +185,10 @@ public class SqlExporterTests extends RefineTest { } String result = writer.toString(); - // logger.info("result = \n" + result); + Assert.assertNotNull(result); assertNotEquals(writer.toString(), SqlExporter.NO_OPTIONS_PRESENT_ERROR); - boolean checkResult = result.contains("CREATE TABLE " + tableName); - //logger.info("checkResult1 =" + checkResult); - checkResult = result.contains("INSERT INTO " + tableName); - // logger.info("checkResult2 =" + checkResult); - Assert.assertEquals(checkResult, true); + Assert.assertTrue(result.contains("INSERT INTO " + tableName)); } @@ -195,7 +196,7 @@ public class SqlExporterTests extends RefineTest { public void testExportSqlNoSchema(){ createGrid(2, 2); String tableName = "sql_table_test"; - JSONObject optionsJson = createOptionsFromProject(tableName, null,null); + ObjectNode optionsJson = (ObjectNode) createOptionsFromProject(tableName, null,null); optionsJson.put("includeStructure", false); when(options.getProperty("options")).thenReturn(optionsJson.toString()); // logger.info("Options = " + optionsJson.toString()); @@ -222,7 +223,7 @@ public class SqlExporterTests extends RefineTest { public void testExportSqlNoContent(){ createGrid(2, 2); String tableName = "sql_table_test"; - JSONObject optionsJson = createOptionsFromProject(tableName, null, null); + ObjectNode optionsJson = (ObjectNode) createOptionsFromProject(tableName, null, null); optionsJson.put("includeContent", false); when(options.getProperty("options")).thenReturn(optionsJson.toString()); //logger.info("Options = " + optionsJson.toString()); @@ -249,7 +250,7 @@ public class SqlExporterTests extends RefineTest { public void testExportSqlIncludeSchemaWithDropStmt(){ createGrid(2, 2); String tableName = "sql_table_test"; - JSONObject optionsJson = createOptionsFromProject(tableName, null, null); + ObjectNode optionsJson = (ObjectNode) createOptionsFromProject(tableName, null, null); optionsJson.put("includeStructure", true); optionsJson.put("includeDropStatement", true); @@ -289,7 +290,7 @@ public class SqlExporterTests extends RefineTest { String tableName = "sql_table_test"; String type = "CHAR"; String size = "2"; - JSONObject optionsJson = createOptionsFromProject(tableName, type, size); + JsonNode optionsJson = createOptionsFromProject(tableName, type, size); // logger.info("Options:: = " + optionsJson.toString()); List columns = project.columnModel.columns.stream().map(col -> col.getName()).collect(Collectors.toList()); @@ -307,7 +308,7 @@ public class SqlExporterTests extends RefineTest { int inNull = 8; createGridWithNullFields(3, 3, inNull); String tableName = "sql_table_test"; - JSONObject optionsJson = createOptionsFromProject(tableName, null, null); + ObjectNode optionsJson = (ObjectNode) createOptionsFromProject(tableName, null, null); optionsJson.put("includeStructure", true); optionsJson.put("includeDropStatement", true); optionsJson.put("convertNulltoEmptyString", true); @@ -338,7 +339,7 @@ public class SqlExporterTests extends RefineTest { int noOfRows = 3; createGrid(noOfRows, noOfCols); String tableName = "sql_table_test"; - JSONObject optionsJson = createOptionsFromProject(tableName, null, null, null, false); + ObjectNode optionsJson = createOptionsFromProject(tableName, null, null, null, false); optionsJson.put("includeStructure", true); optionsJson.put("includeDropStatement", true); optionsJson.put("convertNulltoEmptyString", true); @@ -497,18 +498,16 @@ public class SqlExporterTests extends RefineTest { return json; } - protected JSONObject createOptionsFromProject(String tableName, String type, String size) { - - JSONObject json = new JSONObject(); - JSONArray columns = new JSONArray(); - json.put("columns", columns); + protected JsonNode createOptionsFromProject(String tableName, String type, String size) { + ObjectNode json = ParsingUtilities.mapper.createObjectNode(); json.put("tableName", tableName); + ArrayNode columns = json.putArray("columns"); List cols = project.columnModel.columns; cols.forEach(c -> { //logger.info("Column Name = " + c.getName()); - JSONObject columnModel = new JSONObject(); + ObjectNode columnModel = ParsingUtilities.mapper.createObjectNode(); columnModel.put("name", c.getName()); if(type != null) { columnModel.put("type", type); @@ -529,26 +528,25 @@ public class SqlExporterTests extends RefineTest { columnModel.put("size", size); } - columns.put(columnModel); + columns.add(columnModel); }); - return json; + return json; } - protected JSONObject createOptionsFromProject(String tableName, String type, String size, String defaultValue, + protected ObjectNode createOptionsFromProject(String tableName, String type, String size, String defaultValue, boolean allowNull) { - JSONObject json = new JSONObject(); - JSONArray columns = new JSONArray(); - json.put("columns", columns); + ObjectNode json = ParsingUtilities.mapper.createObjectNode(); + ArrayNode columns = json.putArray("columns"); json.put("tableName", tableName); List cols = project.columnModel.columns; cols.forEach(c -> { //logger.info("Column Name = " + c.getName()); - JSONObject columnModel = new JSONObject(); + ObjectNode columnModel = ParsingUtilities.mapper.createObjectNode(); columnModel.put("name", c.getName()); if(type != null) { columnModel.put("type", type); @@ -572,7 +570,7 @@ public class SqlExporterTests extends RefineTest { columnModel.put("defaultValue", defaultValue); columnModel.put("allowNull", allowNull); - columns.put(columnModel); + columns.add(columnModel); }); From 5cf58d874b7492cf3df0cb87ab1862c51cb577ed Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 2 Nov 2018 15:06:54 +0000 Subject: [PATCH 099/164] Fix deserialization of MassEditOperation --- .../refine/operations/cell/MassEditOperation.java | 13 +++++++++++-- .../tests/operations/cell/MassOperationTests.java | 4 ++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/main/src/com/google/refine/operations/cell/MassEditOperation.java b/main/src/com/google/refine/operations/cell/MassEditOperation.java index fdd99d376..593912b42 100644 --- a/main/src/com/google/refine/operations/cell/MassEditOperation.java +++ b/main/src/com/google/refine/operations/cell/MassEditOperation.java @@ -77,7 +77,7 @@ public class MassEditOperation extends EngineDependentMassCellOperation { boolean fromError, Serializable to) { this.from = from; - this.fromBlank = fromBlank; + this.fromBlank = fromBlank || (from.size() == 1 && from.get(0).length() == 0); this.fromError = fromError; this.to = to; } @@ -103,7 +103,16 @@ public class MassEditOperation extends EngineDependentMassCellOperation { } } - public MassEditOperation(EngineConfig engineConfig, String columnName, String expression, List edits) { + @JsonCreator + public MassEditOperation( + @JsonProperty("engineConfig") + EngineConfig engineConfig, + @JsonProperty("columnName") + String columnName, + @JsonProperty("expression") + String expression, + @JsonProperty("edits") + List edits) { super(engineConfig, columnName, true); _expression = expression; _edits = edits; diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java index 01497bd5d..d604fedc3 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java @@ -93,7 +93,7 @@ public class MassOperationTests extends RefineTest { public void testReconstructEditDate() throws Exception { editsString = "[{\"from\":[\"2018-10-04T00:00:00Z\"],\"to\":\"newString\",\"type\":\"text\"}]"; - editList = ParsingUtilities.mapper.readValue(ParsingUtilities.evaluateJsonStringToArray(editsString).toString(), new TypeReference>() {}); + editList = ParsingUtilities.mapper.readValue(editsString, new TypeReference>() {}); Assert.assertEquals(editList.get(0).from.get(0), "2018-10-04T00:00:00Z"); Assert.assertEquals(editList.get(0).to,"newString" ); @@ -105,7 +105,7 @@ public class MassOperationTests extends RefineTest { public void testReconstructEditEmpty() throws Exception { editsString = "[{\"from\":[\"\"],\"to\":\"newString\",\"type\":\"text\"}]"; - editList = ParsingUtilities.mapper.readValue(ParsingUtilities.evaluateJsonStringToArray(editsString).toString(), new TypeReference>() {}); + editList = ParsingUtilities.mapper.readValue(editsString, new TypeReference>() {}); Assert.assertEquals(editList.get(0).from.size(), 1); Assert.assertEquals(editList.get(0).from.get(0), ""); From fc7da40055042fa88f9d0642edbbe09db56bf319 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sat, 3 Nov 2018 14:49:01 +0000 Subject: [PATCH 100/164] Jackson deserialization for PreferenceStore --- .../refine/commands/SetPreferenceCommand.java | 6 +- .../google/refine/io/FileProjectManager.java | 7 +- .../model/metadata/ProjectMetadata.java | 9 +-- .../refine/preference/PreferenceStore.java | 69 ++++++++++--------- .../com/google/refine/preference/TopList.java | 44 ++++-------- .../preference/PreferenceStoreTests.java | 12 ++-- .../refine/tests/preference/TopListTests.java | 10 ++- 7 files changed, 77 insertions(+), 80 deletions(-) diff --git a/main/src/com/google/refine/commands/SetPreferenceCommand.java b/main/src/com/google/refine/commands/SetPreferenceCommand.java index ac5d3cf74..877b8dcd7 100644 --- a/main/src/com/google/refine/commands/SetPreferenceCommand.java +++ b/main/src/com/google/refine/commands/SetPreferenceCommand.java @@ -42,9 +42,11 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONException; import org.json.JSONTokener; +import com.fasterxml.jackson.databind.JsonNode; import com.google.refine.ProjectManager; import com.google.refine.model.Project; import com.google.refine.preference.PreferenceStore; +import com.google.refine.util.ParsingUtilities; public class SetPreferenceCommand extends Command { @Override @@ -58,12 +60,12 @@ public class SetPreferenceCommand extends Command { String valueString = request.getParameter("value"); try { - Object o = valueString == null ? null : new JSONTokener(valueString).nextValue(); + JsonNode o = valueString == null ? null : ParsingUtilities.mapper.readTree(valueString); ps.put(prefName, PreferenceStore.loadObject(o)); respond(response, "{ \"code\" : \"ok\" }"); - } catch (JSONException e) { + } catch (IOException e) { respondException(response, e); } } diff --git a/main/src/com/google/refine/io/FileProjectManager.java b/main/src/com/google/refine/io/FileProjectManager.java index 2baa454fc..fc93e0ca6 100644 --- a/main/src/com/google/refine/io/FileProjectManager.java +++ b/main/src/com/google/refine/io/FileProjectManager.java @@ -67,6 +67,7 @@ import com.google.refine.model.metadata.DataPackageMetadata; import com.google.refine.model.metadata.IMetadata; import com.google.refine.model.metadata.MetadataFormat; import com.google.refine.model.metadata.ProjectMetadata; +import com.google.refine.preference.PreferenceStore; import com.google.refine.preference.TopList; import com.google.refine.util.ParsingUtilities; @@ -386,7 +387,7 @@ public class FileProjectManager extends ProjectManager { // load global preferences firstly if (obj.has("preferences") && !obj.isNull("preferences")) { - _preferenceStore.load(obj.getJSONObject("preferences")); + _preferenceStore = ParsingUtilities.mapper.readValue(obj.getJSONObject("preferences").toString(), PreferenceStore.class); } JSONArray a = obj.getJSONArray("projectIDs"); @@ -413,8 +414,8 @@ public class FileProjectManager extends ProjectManager { } if (obj.has("expressions") && !obj.isNull("expressions")) { // backward compatibility - ((TopList) _preferenceStore.get("scripting.expressions")) - .load(obj.getJSONArray("expressions")); + TopList newExpressions = ParsingUtilities.mapper.readValue(obj.getJSONArray("expressions").toString(), TopList.class); + this._preferenceStore.put("scripting.expressions", newExpressions); } found = true; diff --git a/main/src/com/google/refine/model/metadata/ProjectMetadata.java b/main/src/com/google/refine/model/metadata/ProjectMetadata.java index 0bf01d540..6ccd26fee 100644 --- a/main/src/com/google/refine/model/metadata/ProjectMetadata.java +++ b/main/src/com/google/refine/model/metadata/ProjectMetadata.java @@ -205,16 +205,17 @@ public class ProjectMetadata extends AbstractMetadata { if (obj.has("preferences") && !obj.isNull("preferences")) { try { - this._preferenceStore.load(obj.getJSONObject("preferences")); - } catch (JSONException e) { + this._preferenceStore = ParsingUtilities.mapper.readValue(obj.getJSONObject("preferences").toString(), PreferenceStore.class); + } catch (IOException e) { logger.error(ExceptionUtils.getStackTrace(e)); } } if (obj.has("expressions") && !obj.isNull("expressions")) { // backward compatibility try { - ((TopList) this._preferenceStore.get("scripting.expressions")).load(obj.getJSONArray("expressions")); - } catch (JSONException e) { + TopList newExpressions = ParsingUtilities.mapper.readValue(obj.getJSONArray("expressions").toString(), TopList.class); + this._preferenceStore.put("scripting.expressions", newExpressions); + } catch (IOException e) { logger.error(ExceptionUtils.getStackTrace(e)); } } diff --git a/main/src/com/google/refine/preference/PreferenceStore.java b/main/src/com/google/refine/preference/PreferenceStore.java index 25a27fba2..69b3bb3fd 100644 --- a/main/src/com/google/refine/preference/PreferenceStore.java +++ b/main/src/com/google/refine/preference/PreferenceStore.java @@ -34,7 +34,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.preference; import java.io.IOException; -import java.lang.reflect.Method; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -50,8 +49,9 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; - -import com.google.refine.RefineServlet; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.refine.util.ParsingUtilities; public class PreferenceStore { public static final String USER_METADATA_KEY = "userMetadata"; @@ -63,7 +63,6 @@ public class PreferenceStore { protected Map _prefs = new HashMap<>(); // Temporary wrapper while serialization has not been migrated yet. - @JsonProperty("entries") protected Map _prefsJackson = new HashMap<>(); public void put(String key, Object value) { @@ -119,39 +118,43 @@ public class PreferenceStore { return null; } - @SuppressWarnings("unchecked") - public void load(JSONObject obj) throws JSONException { - if (obj.has("entries") && !obj.isNull("entries")) { - JSONObject entries = obj.getJSONObject("entries"); - - Iterator i = entries.keys(); - while (i.hasNext()) { - String key = i.next(); - if (!entries.isNull(key)) { - Object o = entries.get(key), loaded = loadObject(o); - _prefs.put(key, loaded); - _prefsJackson.put(key, wrapJSONArray(loaded)); - } + @JsonProperty("entries") + public void setEntries(JsonNode entries) throws JSONException { + Iterator i = entries.fieldNames(); + while (i.hasNext()) { + String key = i.next(); + System.out.println(key); + if (entries.get(key) != null) { + JsonNode o = entries.get(key); + Object loaded = loadObject(o); + _prefs.put(key, loaded); + _prefsJackson.put(key, wrapJSONArray(loaded)); } - dirty = false; // internal puts don't count } + dirty = false; // internal puts don't count } - static public Object loadObject(Object o) { - if (o instanceof JSONObject) { - try { - JSONObject obj2 = (JSONObject) o; - String className = obj2.getString("class"); - Class klass = RefineServlet.getClass(className); - Method method = klass.getMethod("load", JSONObject.class); - - return method.invoke(null, obj2); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } else { - return o; + @JsonProperty("entries") + public Map getEntries() { + return _prefsJackson; + } + + static public Object loadObject(JsonNode o) { + System.out.println("loading"); + System.out.println(o.toString()); + try { + if (o instanceof ObjectNode) { + ObjectNode obj2 = (ObjectNode) o; + return ParsingUtilities.mapper.treeToValue(obj2, PreferenceValue.class); + } else if (o instanceof ArrayNode) { + return o; + } else { + // basic datatypes (int, double, boolean, string) + return ParsingUtilities.mapper.treeToValue(o, Object.class); + } + } catch (Exception e) { + e.printStackTrace(); + return null; } } } diff --git a/main/src/com/google/refine/preference/TopList.java b/main/src/com/google/refine/preference/TopList.java index 79b9802f3..f1bfaa860 100644 --- a/main/src/com/google/refine/preference/TopList.java +++ b/main/src/com/google/refine/preference/TopList.java @@ -38,24 +38,32 @@ import java.util.Iterator; import java.util.List; import org.apache.commons.collections.list.UnmodifiableList; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -public class TopList implements Iterable { +public class TopList implements Iterable, PreferenceValue { @JsonProperty("top") - final protected int _top; - final protected List _list = new ArrayList(); + protected int _top = 10; + protected List _list = new ArrayList(); public TopList(int top) { _top = top; } + @JsonCreator + public TopList( + @JsonProperty("top") + int top, + @JsonProperty("list") + List list) { + _top = top; + _list = list; + } + @SuppressWarnings("unchecked") @JsonProperty("list") public List getList() { @@ -75,30 +83,6 @@ public class TopList implements Iterable { _list.remove(element); } - @JsonProperty("class") - public String getClassName() { - return this.getClass().getName(); - } - - static public TopList load(JSONObject obj) throws JSONException { - int top = obj.has("top") && !obj.isNull("top") ? obj.getInt("top") : 10; - TopList tl = new TopList(top); - - if (obj.has("list") && !obj.isNull("list")) { - JSONArray a = obj.getJSONArray("list"); - - tl.load(a); - } - return tl; - } - - public void load(JSONArray a) throws JSONException { - int length = a.length(); - for (int i = 0; i < length && _list.size() < _top; i++) { - _list.add(a.getString(i)); - } - } - @Override @JsonIgnore public Iterator iterator() { diff --git a/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java b/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java index 9a5c1af18..0c58b7178 100644 --- a/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java +++ b/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java @@ -3,12 +3,15 @@ package com.google.refine.tests.preference; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; -import org.json.JSONObject; +import java.io.IOException; + import org.testng.annotations.Test; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; import com.google.refine.preference.PreferenceStore; -import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class PreferenceStoreTests { public static String json = "{" @@ -21,7 +24,7 @@ public class PreferenceStoreTests { + "}}"; @Test - public void serializePreferenceStore() { + public void serializePreferenceStore() throws JsonParseException, JsonMappingException, IOException { String jsonAfter = "{" + "\"entries\":{" @@ -32,8 +35,7 @@ public class PreferenceStoreTests { + " \"scripting.expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":100,\"list\":[]}," + " \"mypreference\":\"myvalue\"" + "}}"; - PreferenceStore prefStore = new PreferenceStore(); - prefStore.load(new JSONObject(json)); + PreferenceStore prefStore = ParsingUtilities.mapper.readValue(json, PreferenceStore.class); assertFalse(prefStore.isDirty()); prefStore.put("mypreference", "myvalue"); assertTrue(prefStore.isDirty()); diff --git a/main/tests/server/src/com/google/refine/tests/preference/TopListTests.java b/main/tests/server/src/com/google/refine/tests/preference/TopListTests.java index e9ed000d5..1339d1b23 100644 --- a/main/tests/server/src/com/google/refine/tests/preference/TopListTests.java +++ b/main/tests/server/src/com/google/refine/tests/preference/TopListTests.java @@ -1,14 +1,18 @@ package com.google.refine.tests.preference; -import org.json.JSONObject; +import java.io.IOException; + import org.testng.annotations.Test; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; import com.google.refine.preference.TopList; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class TopListTests { @Test - public void serializeTopList() { + public void serializeTopList() throws JsonParseException, JsonMappingException, IOException { String json = "{" + "\"class\":\"com.google.refine.preference.TopList\"," + "\"top\":100," @@ -21,7 +25,7 @@ public class TopListTests { + " \"grel:\\\"https://pub.orcid.org/\\\"+value+\\\"/employments\\\"\"" + "]}"; TestUtils.isSerializedTo( - TopList.load(new JSONObject(json)), + ParsingUtilities.mapper.readValue(json, TopList.class), json); } } From 9cab735dfcd18e587a6bdb34303d496bec812e2d Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sat, 3 Nov 2018 19:51:19 +0000 Subject: [PATCH 101/164] Add common interface for preference values --- .../refine/preference/PreferenceValue.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 main/src/com/google/refine/preference/PreferenceValue.java diff --git a/main/src/com/google/refine/preference/PreferenceValue.java b/main/src/com/google/refine/preference/PreferenceValue.java new file mode 100644 index 000000000..78d8e64f2 --- /dev/null +++ b/main/src/com/google/refine/preference/PreferenceValue.java @@ -0,0 +1,25 @@ +package com.google.refine.preference; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +/** + * Interface to be extended by all objects stored + * in the preferences. This ensures that their full class + * name is serialized with them. They should implement + * Jackson deserialization as usual. + * + * @author Antonin Delpeuch + */ + +@JsonTypeInfo( + use=JsonTypeInfo.Id.CLASS, + include=JsonTypeInfo.As.PROPERTY, + property="class") +public interface PreferenceValue { + + @JsonProperty("class") + public default String getClassName() { + return this.getClass().getName(); + } +} From e4e73d0b9201a80a0d31e258f2ea601340de1bfe Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 5 Nov 2018 16:35:51 +0000 Subject: [PATCH 102/164] Migrate importers to use Jackson classes --- .../src/com/google/refine/ProjectManager.java | 1 - .../refine/browsing/DecoratedValue.java | 1 - .../com/google/refine/browsing/Engine.java | 1 - .../google/refine/browsing/EngineConfig.java | 1 - .../refine/browsing/facets/FacetConfig.java | 1 - .../browsing/facets/FacetConfigResolver.java | 1 - .../refine/browsing/facets/ListFacet.java | 1 - .../browsing/facets/NominalFacetChoice.java | 1 - .../refine/browsing/facets/RangeFacet.java | 1 - .../browsing/facets/ScatterplotFacet.java | 1 - .../browsing/facets/TextSearchFacet.java | 1 - .../browsing/facets/TimeRangeFacet.java | 1 - .../refine/clustering/ClustererConfig.java | 1 - .../clustering/binning/BinningClusterer.java | 1 - .../refine/clustering/knn/kNNClusterer.java | 1 - .../com/google/refine/commands/Command.java | 1 - .../refine/commands/GetPreferenceCommand.java | 1 - .../refine/commands/HttpHeadersSupport.java | 1 - .../google/refine/commands/HttpUtilities.java | 1 - .../refine/commands/SetPreferenceCommand.java | 3 - .../commands/cell/EditOneCellCommand.java | 1 - .../refine/commands/cell/MassEditCommand.java | 1 - .../AddColumnByFetchingURLsCommand.java | 1 - .../column/GetColumnsInfoCommand.java | 1 - .../expr/GetExpressionHistoryCommand.java | 1 - .../GetExpressionLanguageInfoCommand.java | 1 - .../expr/GetStarredExpressionsCommand.java | 1 - .../expr/PreviewExpressionCommand.java | 1 - .../history/GetOperationsCommand.java | 1 - .../GetImportingConfigurationCommand.java | 1 - .../GetImportingJobStatusCommand.java | 1 - .../commands/lang/GetLanguagesCommand.java | 1 - .../project/CreateProjectCommand.java | 24 +-- .../commands/project/GetModelsCommand.java | 1 - .../recon/GuessTypesOfColumnCommand.java | 2 - .../recon/PreviewExtendDataCommand.java | 1 - .../recon/ReconClearOneCellCommand.java | 1 - .../ReconUseValuesAsIdentifiersCommand.java | 5 - .../refine/commands/row/GetRowsCommand.java | 1 - .../GetAllProjectMetadataCommand.java | 1 - .../workspace/GetAllProjectTagsCommand.java | 1 - .../google/refine/exporters/CsvExporter.java | 1 - .../refine/exporters/HtmlTableExporter.java | 2 - .../google/refine/exporters/OdsExporter.java | 1 - .../refine/exporters/TemplatingExporter.java | 1 - .../google/refine/exporters/XlsExporter.java | 1 - .../refine/exporters/sql/SqlExporter.java | 2 - .../com/google/refine/expr/MetaParser.java | 1 - .../refine/expr/functions/strings/Trim.java | 1 - main/src/com/google/refine/grel/Control.java | 1 - .../com/google/refine/history/History.java | 1 - .../google/refine/history/HistoryEntry.java | 1 - .../google/refine/history/HistoryProcess.java | 1 - .../refine/importers/ExcelImporter.java | 27 +-- .../refine/importers/FixedWidthImporter.java | 18 +- .../refine/importers/ImporterUtilities.java | 7 +- .../refine/importers/ImportingParserBase.java | 25 +-- .../google/refine/importers/JsonImporter.java | 51 +++--- .../refine/importers/LineBasedImporter.java | 10 +- .../google/refine/importers/MarcImporter.java | 8 +- .../google/refine/importers/OdsImporter.java | 27 +-- .../refine/importers/RdfTripleImporter.java | 4 +- .../importers/SeparatorBasedImporter.java | 27 +-- .../importers/TabularImportingParserBase.java | 13 +- .../refine/importers/WikitextImporter.java | 11 +- .../google/refine/importers/XmlImporter.java | 49 +++--- .../tree/TreeImportingParserBase.java | 24 +-- .../importing/DefaultImportingController.java | 37 ++-- .../google/refine/importing/ImportingJob.java | 40 ++--- .../refine/importing/ImportingManager.java | 1 - .../refine/importing/ImportingParser.java | 13 +- .../refine/importing/ImportingUtilities.java | 160 +++++++++--------- .../google/refine/io/FileProjectManager.java | 1 - .../refine/model/AbstractOperation.java | 1 - main/src/com/google/refine/model/Cell.java | 1 - main/src/com/google/refine/model/Column.java | 1 - .../com/google/refine/model/ColumnGroup.java | 1 - main/src/com/google/refine/model/Recon.java | 1 - .../google/refine/model/ReconCandidate.java | 1 - .../com/google/refine/model/ReconStats.java | 1 - .../com/google/refine/model/ReconType.java | 1 - .../com/google/refine/model/RecordModel.java | 1 - main/src/com/google/refine/model/Row.java | 1 - .../refine/model/changes/MassChange.java | 1 - .../model/metadata/ProjectMetadata.java | 6 +- .../refine/model/recon/ReconConfig.java | 1 - .../recon/ReconciledDataExtensionJob.java | 1 - .../model/recon/StandardReconConfig.java | 1 - .../EngineDependentMassCellOperation.java | 1 - .../operations/EngineDependentOperation.java | 1 - .../refine/operations/OperationRegistry.java | 9 - .../refine/operations/OperationResolver.java | 1 - .../operations/cell/BlankDownOperation.java | 1 - .../operations/cell/FillDownOperation.java | 1 - .../cell/KeyValueColumnizeOperation.java | 1 - .../operations/cell/MassEditOperation.java | 1 - .../cell/MultiValuedCellJoinOperation.java | 1 - .../cell/MultiValuedCellSplitOperation.java | 1 - .../cell/TextTransformOperation.java | 1 - .../TransposeColumnsIntoRowsOperation.java | 1 - .../TransposeRowsIntoColumnsOperation.java | 1 - ...ColumnAdditionByFetchingURLsOperation.java | 2 - .../column/ColumnAdditionOperation.java | 1 - .../column/ColumnMoveOperation.java | 1 - .../column/ColumnRemovalOperation.java | 1 - .../column/ColumnRenameOperation.java | 1 - .../column/ColumnReorderOperation.java | 1 - .../column/ColumnSplitOperation.java | 1 - .../operations/recon/ExtendDataOperation.java | 1 - .../ReconClearSimilarCellsOperation.java | 1 - .../ReconCopyAcrossColumnsOperation.java | 1 - .../recon/ReconDiscardJudgmentsOperation.java | 1 - .../ReconJudgeSimilarCellsOperation.java | 1 - .../recon/ReconMarkNewTopicsOperation.java | 1 - .../ReconMatchBestCandidatesOperation.java | 1 - .../ReconMatchSpecificTopicOperation.java | 1 - .../operations/recon/ReconOperation.java | 1 - .../ReconUseValuesAsIdentifiersOperation.java | 1 - .../operations/row/DenormalizeOperation.java | 1 - .../operations/row/RowFlagOperation.java | 1 - .../operations/row/RowRemovalOperation.java | 1 - .../operations/row/RowReorderOperation.java | 1 - .../operations/row/RowStarOperation.java | 1 - .../refine/process/LongRunningProcess.java | 1 - .../com/google/refine/process/Process.java | 1 - .../google/refine/process/ProcessManager.java | 1 - .../process/QuickHistoryEntryProcess.java | 1 - .../com/google/refine/sorting/Criterion.java | 9 +- .../google/refine/sorting/SortingConfig.java | 1 - .../refine/sorting/StringCriterion.java | 1 - .../com/google/refine/util/JSONUtilities.java | 136 ++++++++++++--- .../google/refine/util/ParsingUtilities.java | 27 +++ main/src/com/google/refine/util/Pool.java | 1 - .../refine/util/SerializationFilters.java | 1 - .../com/google/refine/tests/RefineTest.java | 42 ++++- .../refine/tests/browsing/EngineTests.java | 1 + .../browsing/facets/EngineConfigTests.java | 2 +- .../tests/browsing/facets/ListFacetTests.java | 1 - .../browsing/facets/RangeFacetTests.java | 1 - .../facets/ScatterplotFacetTests.java | 1 - .../browsing/facets/TextSearchFacetTests.java | 1 - .../browsing/facets/TimeRangeFacetTests.java | 1 - .../ExpressionNominalValueGrouperTests.java | 8 +- .../expr/ExpressionCommandTestBase.java | 1 - ...GetExpressionLanguageInfoCommandTests.java | 1 - .../expr/PreviewExpressionCommandTests.java | 6 +- .../ToggleStarredExpressionCommandTests.java | 3 +- .../project/ValidateOperationTests.java | 2 +- .../commands/row/GetRowsCommandTest.java | 14 +- .../util/CancelProcessesCommandTests.java | 2 +- .../tests/exporters/sql/SqlExporterTests.java | 1 - .../expr/functions/ContainsFunctionTests.java | 15 +- .../strings/ToFromConversionTests.java | 2 +- .../refine/tests/history/HistoryTests.java | 2 +- .../tests/importers/ExcelImporterTests.java | 22 ++- .../importers/FixedWidthImporterTests.java | 29 +--- .../refine/tests/importers/ImporterTest.java | 15 +- .../tests/importers/JsonImporterTests.java | 27 +-- .../tests/importers/TsvCsvImporterTests.java | 31 +--- .../tests/importers/XmlImporterTests.java | 27 +-- .../importing/ImportingUtilitiesTests.java | 20 +-- .../google/refine/tests/model/CacheTests.java | 1 - .../refine/tests/model/ColumnTests.java | 5 +- .../tests/model/changes/MassChangeTests.java | 2 +- .../cell/KeyValueColumnizeTests.java | 6 +- .../operations/cell/MassOperationTests.java | 1 - .../QuickHistoryEntryProcessTests.java | 3 +- .../PatternSyntaxExceptionParserTests.java | 6 +- .../google/refine/tests/util/TestUtils.java | 1 - 169 files changed, 572 insertions(+), 613 deletions(-) diff --git a/main/src/com/google/refine/ProjectManager.java b/main/src/com/google/refine/ProjectManager.java index 2e90d4624..3738209d0 100644 --- a/main/src/com/google/refine/ProjectManager.java +++ b/main/src/com/google/refine/ProjectManager.java @@ -56,7 +56,6 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.history.HistoryEntryManager; import com.google.refine.model.Project; import com.google.refine.model.metadata.IMetadata; diff --git a/main/src/com/google/refine/browsing/DecoratedValue.java b/main/src/com/google/refine/browsing/DecoratedValue.java index 67aa8a09d..909bf3d5b 100644 --- a/main/src/com/google/refine/browsing/DecoratedValue.java +++ b/main/src/com/google/refine/browsing/DecoratedValue.java @@ -37,7 +37,6 @@ import java.time.OffsetDateTime; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.util.StringUtils; /** diff --git a/main/src/com/google/refine/browsing/Engine.java b/main/src/com/google/refine/browsing/Engine.java index dd0249e3a..827555d6d 100644 --- a/main/src/com/google/refine/browsing/Engine.java +++ b/main/src/com/google/refine/browsing/Engine.java @@ -43,7 +43,6 @@ import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.facets.Facet; import com.google.refine.browsing.util.ConjunctiveFilteredRecords; import com.google.refine.browsing.util.ConjunctiveFilteredRows; diff --git a/main/src/com/google/refine/browsing/EngineConfig.java b/main/src/com/google/refine/browsing/EngineConfig.java index 3e9a4c4e4..0898fbd89 100644 --- a/main/src/com/google/refine/browsing/EngineConfig.java +++ b/main/src/com/google/refine/browsing/EngineConfig.java @@ -8,7 +8,6 @@ import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.facets.FacetConfig; import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/browsing/facets/FacetConfig.java b/main/src/com/google/refine/browsing/facets/FacetConfig.java index 07ffc9156..e745e2f7a 100644 --- a/main/src/com/google/refine/browsing/facets/FacetConfig.java +++ b/main/src/com/google/refine/browsing/facets/FacetConfig.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo; - import com.google.refine.model.Project; diff --git a/main/src/com/google/refine/browsing/facets/FacetConfigResolver.java b/main/src/com/google/refine/browsing/facets/FacetConfigResolver.java index 0cfac814c..e05fde24b 100644 --- a/main/src/com/google/refine/browsing/facets/FacetConfigResolver.java +++ b/main/src/com/google/refine/browsing/facets/FacetConfigResolver.java @@ -7,7 +7,6 @@ import com.fasterxml.jackson.databind.DatabindContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase; import com.fasterxml.jackson.databind.type.TypeFactory; - import com.google.refine.model.recon.ReconConfig; public class FacetConfigResolver extends TypeIdResolverBase { diff --git a/main/src/com/google/refine/browsing/facets/ListFacet.java b/main/src/com/google/refine/browsing/facets/ListFacet.java index f1f2ebff9..dc0d1eea0 100644 --- a/main/src/com/google/refine/browsing/facets/ListFacet.java +++ b/main/src/com/google/refine/browsing/facets/ListFacet.java @@ -42,7 +42,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.ProjectManager; import com.google.refine.browsing.DecoratedValue; import com.google.refine.browsing.FilteredRecords; diff --git a/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java b/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java index f29a6ae96..bec3dd180 100644 --- a/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java +++ b/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java @@ -34,7 +34,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.browsing.facets; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.DecoratedValue; /** diff --git a/main/src/com/google/refine/browsing/facets/RangeFacet.java b/main/src/com/google/refine/browsing/facets/RangeFacet.java index 4e978849a..f66bdcde6 100644 --- a/main/src/com/google/refine/browsing/facets/RangeFacet.java +++ b/main/src/com/google/refine/browsing/facets/RangeFacet.java @@ -38,7 +38,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RecordFilter; diff --git a/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java b/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java index f2f3d3243..1aa721ef0 100644 --- a/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java +++ b/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java @@ -51,7 +51,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RecordFilter; diff --git a/main/src/com/google/refine/browsing/facets/TextSearchFacet.java b/main/src/com/google/refine/browsing/facets/TextSearchFacet.java index 4a5ea6733..12e159565 100644 --- a/main/src/com/google/refine/browsing/facets/TextSearchFacet.java +++ b/main/src/com/google/refine/browsing/facets/TextSearchFacet.java @@ -38,7 +38,6 @@ import java.util.regex.Pattern; import org.json.JSONException; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RecordFilter; diff --git a/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java b/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java index 63ecfcc39..9d6898115 100644 --- a/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java +++ b/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java @@ -37,7 +37,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RecordFilter; diff --git a/main/src/com/google/refine/clustering/ClustererConfig.java b/main/src/com/google/refine/clustering/ClustererConfig.java index 5ac10369f..c63346036 100644 --- a/main/src/com/google/refine/clustering/ClustererConfig.java +++ b/main/src/com/google/refine/clustering/ClustererConfig.java @@ -3,7 +3,6 @@ package com.google.refine.clustering; import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.model.Project; /** diff --git a/main/src/com/google/refine/clustering/binning/BinningClusterer.java b/main/src/com/google/refine/clustering/binning/BinningClusterer.java index b09cd6dcd..f01c116b3 100644 --- a/main/src/com/google/refine/clustering/binning/BinningClusterer.java +++ b/main/src/com/google/refine/clustering/binning/BinningClusterer.java @@ -53,7 +53,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RowVisitor; diff --git a/main/src/com/google/refine/clustering/knn/kNNClusterer.java b/main/src/com/google/refine/clustering/knn/kNNClusterer.java index da0a502d8..13ed16434 100644 --- a/main/src/com/google/refine/clustering/knn/kNNClusterer.java +++ b/main/src/com/google/refine/clustering/knn/kNNClusterer.java @@ -50,7 +50,6 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RowVisitor; diff --git a/main/src/com/google/refine/commands/Command.java b/main/src/com/google/refine/commands/Command.java index f60dc15cb..a2af0c768 100644 --- a/main/src/com/google/refine/commands/Command.java +++ b/main/src/com/google/refine/commands/Command.java @@ -51,7 +51,6 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonGenerator; - import com.google.refine.ProjectManager; import com.google.refine.RefineServlet; import com.google.refine.browsing.Engine; diff --git a/main/src/com/google/refine/commands/GetPreferenceCommand.java b/main/src/com/google/refine/commands/GetPreferenceCommand.java index 2d133c041..8b87dd31e 100644 --- a/main/src/com/google/refine/commands/GetPreferenceCommand.java +++ b/main/src/com/google/refine/commands/GetPreferenceCommand.java @@ -40,7 +40,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.ProjectManager; import com.google.refine.preference.PreferenceStore; import com.google.refine.preference.TopList; diff --git a/main/src/com/google/refine/commands/HttpHeadersSupport.java b/main/src/com/google/refine/commands/HttpHeadersSupport.java index e7cd88b3e..73d850288 100644 --- a/main/src/com/google/refine/commands/HttpHeadersSupport.java +++ b/main/src/com/google/refine/commands/HttpHeadersSupport.java @@ -39,7 +39,6 @@ import java.util.Set; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.RefineServlet; abstract public class HttpHeadersSupport { diff --git a/main/src/com/google/refine/commands/HttpUtilities.java b/main/src/com/google/refine/commands/HttpUtilities.java index 09a8cdd27..6d7d9ddc5 100644 --- a/main/src/com/google/refine/commands/HttpUtilities.java +++ b/main/src/com/google/refine/commands/HttpUtilities.java @@ -17,7 +17,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.core.JsonGenerator; - import com.google.refine.RefineServlet; import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/commands/SetPreferenceCommand.java b/main/src/com/google/refine/commands/SetPreferenceCommand.java index 877b8dcd7..7dcbf07ba 100644 --- a/main/src/com/google/refine/commands/SetPreferenceCommand.java +++ b/main/src/com/google/refine/commands/SetPreferenceCommand.java @@ -39,9 +39,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONException; -import org.json.JSONTokener; - import com.fasterxml.jackson.databind.JsonNode; import com.google.refine.ProjectManager; import com.google.refine.model.Project; diff --git a/main/src/com/google/refine/commands/cell/EditOneCellCommand.java b/main/src/com/google/refine/commands/cell/EditOneCellCommand.java index 41c7ab0b3..e299000ce 100644 --- a/main/src/com/google/refine/commands/cell/EditOneCellCommand.java +++ b/main/src/com/google/refine/commands/cell/EditOneCellCommand.java @@ -43,7 +43,6 @@ import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.commands.Command; import com.google.refine.history.Change; import com.google.refine.history.HistoryEntry; diff --git a/main/src/com/google/refine/commands/cell/MassEditCommand.java b/main/src/com/google/refine/commands/cell/MassEditCommand.java index 1b1558db2..eecfb796a 100644 --- a/main/src/com/google/refine/commands/cell/MassEditCommand.java +++ b/main/src/com/google/refine/commands/cell/MassEditCommand.java @@ -38,7 +38,6 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.core.type.TypeReference; - import com.google.refine.browsing.EngineConfig; import com.google.refine.commands.EngineDependentCommand; import com.google.refine.model.AbstractOperation; diff --git a/main/src/com/google/refine/commands/column/AddColumnByFetchingURLsCommand.java b/main/src/com/google/refine/commands/column/AddColumnByFetchingURLsCommand.java index 13c7ea762..2d480b262 100644 --- a/main/src/com/google/refine/commands/column/AddColumnByFetchingURLsCommand.java +++ b/main/src/com/google/refine/commands/column/AddColumnByFetchingURLsCommand.java @@ -39,7 +39,6 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.ObjectMapper; - import com.google.refine.browsing.EngineConfig; import com.google.refine.commands.EngineDependentCommand; import com.google.refine.model.AbstractOperation; diff --git a/main/src/com/google/refine/commands/column/GetColumnsInfoCommand.java b/main/src/com/google/refine/commands/column/GetColumnsInfoCommand.java index e8683a124..378053a5c 100644 --- a/main/src/com/google/refine/commands/column/GetColumnsInfoCommand.java +++ b/main/src/com/google/refine/commands/column/GetColumnsInfoCommand.java @@ -40,7 +40,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.core.JsonGenerator; - import com.google.refine.browsing.util.ExpressionBasedRowEvaluable; import com.google.refine.browsing.util.NumericBinIndex; import com.google.refine.browsing.util.NumericBinRowIndex; diff --git a/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java b/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java index b4f229be9..75a88e406 100644 --- a/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java +++ b/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java @@ -45,7 +45,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.ProjectManager; import com.google.refine.commands.Command; import com.google.refine.preference.TopList; diff --git a/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java b/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java index a47f7b62b..3c4df3089 100644 --- a/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java +++ b/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java @@ -41,7 +41,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.commands.Command; import com.google.refine.grel.Control; import com.google.refine.grel.ControlFunctionRegistry; diff --git a/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java b/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java index 60635c399..245f69390 100644 --- a/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java +++ b/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java @@ -9,7 +9,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.ProjectManager; import com.google.refine.commands.Command; import com.google.refine.preference.TopList; diff --git a/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java b/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java index e59ad8b5b..135bf92b5 100644 --- a/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java +++ b/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java @@ -52,7 +52,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; - import com.google.refine.commands.Command; import com.google.refine.expr.EvalError; import com.google.refine.expr.Evaluable; diff --git a/main/src/com/google/refine/commands/history/GetOperationsCommand.java b/main/src/com/google/refine/commands/history/GetOperationsCommand.java index 9b3c88829..6b24fe4f0 100644 --- a/main/src/com/google/refine/commands/history/GetOperationsCommand.java +++ b/main/src/com/google/refine/commands/history/GetOperationsCommand.java @@ -44,7 +44,6 @@ import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.commands.Command; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; diff --git a/main/src/com/google/refine/commands/importing/GetImportingConfigurationCommand.java b/main/src/com/google/refine/commands/importing/GetImportingConfigurationCommand.java index 3dcc418fe..2899114d6 100644 --- a/main/src/com/google/refine/commands/importing/GetImportingConfigurationCommand.java +++ b/main/src/com/google/refine/commands/importing/GetImportingConfigurationCommand.java @@ -40,7 +40,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.commands.Command; import com.google.refine.importing.ImportingManager.ImportingConfiguration; diff --git a/main/src/com/google/refine/commands/importing/GetImportingJobStatusCommand.java b/main/src/com/google/refine/commands/importing/GetImportingJobStatusCommand.java index 4a06556b1..930b22032 100644 --- a/main/src/com/google/refine/commands/importing/GetImportingJobStatusCommand.java +++ b/main/src/com/google/refine/commands/importing/GetImportingJobStatusCommand.java @@ -43,7 +43,6 @@ import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.commands.Command; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingManager; diff --git a/main/src/com/google/refine/commands/lang/GetLanguagesCommand.java b/main/src/com/google/refine/commands/lang/GetLanguagesCommand.java index cd0ea55c9..560533162 100644 --- a/main/src/com/google/refine/commands/lang/GetLanguagesCommand.java +++ b/main/src/com/google/refine/commands/lang/GetLanguagesCommand.java @@ -48,7 +48,6 @@ import org.apache.commons.io.filefilter.WildcardFileFilter; import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.commands.Command; import edu.mit.simile.butterfly.ButterflyModule; diff --git a/main/src/com/google/refine/commands/project/CreateProjectCommand.java b/main/src/com/google/refine/commands/project/CreateProjectCommand.java index 0d5020fe1..ac34c5cc7 100644 --- a/main/src/com/google/refine/commands/project/CreateProjectCommand.java +++ b/main/src/com/google/refine/commands/project/CreateProjectCommand.java @@ -42,11 +42,11 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONArray; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.ProjectManager; import com.google.refine.commands.Command; import com.google.refine.commands.HttpUtilities; @@ -69,7 +69,7 @@ public class CreateProjectCommand extends Command { try { Properties parameters = ParsingUtilities.parseUrlParameters(request); ImportingJob job = ImportingManager.createJob(); - JSONObject config = job.getOrCreateDefaultConfig(); + ObjectNode config = job.getOrCreateDefaultConfig(); ImportingUtilities.loadDataAndPrepareJob( request, response, parameters, job, config); @@ -93,9 +93,9 @@ public class CreateProjectCommand extends Command { "\\t".equals(parameters.getProperty("separator"))) { format = "text/line-based/*sv"; } else { - JSONArray rankedFormats = JSONUtilities.getArray(config, "rankedFormats"); - if (rankedFormats != null && rankedFormats.length() > 0) { - format = rankedFormats.getString(0); + ArrayNode rankedFormats = JSONUtilities.getArray(config, "rankedFormats"); + if (rankedFormats != null && rankedFormats.size() > 0) { + format = rankedFormats.get(0).asText(); } } @@ -105,10 +105,10 @@ public class CreateProjectCommand extends Command { } } - JSONObject optionObj = null; - String optionsString = parameters.getProperty("options"); + ObjectNode optionObj = null; + String optionsString = parameters.getParameter("options"); if (optionsString != null && !optionsString.isEmpty()) { - optionObj = ParsingUtilities.evaluateJsonStringToObject(optionsString); + optionObj = ParsingUtilities.evaluateJsonStringToObjectNode(optionsString); } else { Format formatRecord = ImportingManager.formatToRecord.get(format); optionObj = formatRecord.parser.createParserUIInitializationData( @@ -133,7 +133,7 @@ public class CreateProjectCommand extends Command { } } - static private void adjustLegacyOptions(String format, Properties parameters, JSONObject optionObj) { + static private void adjustLegacyOptions(String format, Properties parameters, ObjectNode optionObj) { if (",".equals(parameters.getProperty("separator"))) { JSONUtilities.safePut(optionObj, "separator", ","); } else if ("\\t".equals(parameters.getProperty("separator"))) { @@ -150,7 +150,7 @@ public class CreateProjectCommand extends Command { } static private void adjustLegacyIntegerOption( - String format, Properties parameters, JSONObject optionObj, String legacyName, String newName) { + String format, Properties parameters, ObjectNode optionObj, String legacyName, String newName) { String s = parameters.getProperty(legacyName); if (s != null && !s.isEmpty()) { @@ -165,7 +165,7 @@ public class CreateProjectCommand extends Command { static private void adjustLegacyBooleanOption( String format, Properties parameters, - JSONObject optionObj, + ObjectNode optionObj, String legacyName, String newName, boolean invert) { diff --git a/main/src/com/google/refine/commands/project/GetModelsCommand.java b/main/src/com/google/refine/commands/project/GetModelsCommand.java index 876f5fa76..f42436823 100644 --- a/main/src/com/google/refine/commands/project/GetModelsCommand.java +++ b/main/src/com/google/refine/commands/project/GetModelsCommand.java @@ -44,7 +44,6 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONException; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.commands.Command; import com.google.refine.commands.HttpHeadersSupport; import com.google.refine.commands.HttpHeadersSupport.HttpHeaderInfo; diff --git a/main/src/com/google/refine/commands/recon/GuessTypesOfColumnCommand.java b/main/src/com/google/refine/commands/recon/GuessTypesOfColumnCommand.java index 9759a80ae..2600e36f3 100644 --- a/main/src/com/google/refine/commands/recon/GuessTypesOfColumnCommand.java +++ b/main/src/com/google/refine/commands/recon/GuessTypesOfColumnCommand.java @@ -36,7 +36,6 @@ package com.google.refine.commands.recon; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.StringWriter; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; @@ -59,7 +58,6 @@ import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.commands.Command; import com.google.refine.expr.ExpressionUtils; import com.google.refine.model.Column; diff --git a/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java b/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java index f42675fa0..a571aa4da 100644 --- a/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java +++ b/main/src/com/google/refine/commands/recon/PreviewExtendDataCommand.java @@ -48,7 +48,6 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONArray; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.commands.Command; import com.google.refine.model.Cell; import com.google.refine.model.Column; diff --git a/main/src/com/google/refine/commands/recon/ReconClearOneCellCommand.java b/main/src/com/google/refine/commands/recon/ReconClearOneCellCommand.java index 128c4dbad..6234f872e 100644 --- a/main/src/com/google/refine/commands/recon/ReconClearOneCellCommand.java +++ b/main/src/com/google/refine/commands/recon/ReconClearOneCellCommand.java @@ -40,7 +40,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.commands.Command; import com.google.refine.expr.ExpressionUtils; import com.google.refine.history.Change; diff --git a/main/src/com/google/refine/commands/recon/ReconUseValuesAsIdentifiersCommand.java b/main/src/com/google/refine/commands/recon/ReconUseValuesAsIdentifiersCommand.java index cece2bddb..6d13ed369 100644 --- a/main/src/com/google/refine/commands/recon/ReconUseValuesAsIdentifiersCommand.java +++ b/main/src/com/google/refine/commands/recon/ReconUseValuesAsIdentifiersCommand.java @@ -2,15 +2,10 @@ package com.google.refine.commands.recon; import javax.servlet.http.HttpServletRequest; -import org.json.JSONObject; - import com.google.refine.browsing.EngineConfig; import com.google.refine.commands.EngineDependentCommand; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; -import com.google.refine.model.ReconCandidate; -import com.google.refine.model.recon.StandardReconConfig; -import com.google.refine.operations.recon.ReconMatchSpecificTopicOperation; import com.google.refine.operations.recon.ReconUseValuesAsIdentifiersOperation; public class ReconUseValuesAsIdentifiersCommand extends EngineDependentCommand { diff --git a/main/src/com/google/refine/commands/row/GetRowsCommand.java b/main/src/com/google/refine/commands/row/GetRowsCommand.java index 9e11f9be7..b69042350 100644 --- a/main/src/com/google/refine/commands/row/GetRowsCommand.java +++ b/main/src/com/google/refine/commands/row/GetRowsCommand.java @@ -49,7 +49,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonUnwrapped; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.FilteredRecords; diff --git a/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java b/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java index 4968dffdd..034e42d4a 100644 --- a/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java +++ b/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java @@ -46,7 +46,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRawValue; - import com.google.refine.ProjectManager; import com.google.refine.commands.Command; import com.google.refine.model.metadata.ProjectMetadata; diff --git a/main/src/com/google/refine/commands/workspace/GetAllProjectTagsCommand.java b/main/src/com/google/refine/commands/workspace/GetAllProjectTagsCommand.java index 49330e8bf..10920810e 100644 --- a/main/src/com/google/refine/commands/workspace/GetAllProjectTagsCommand.java +++ b/main/src/com/google/refine/commands/workspace/GetAllProjectTagsCommand.java @@ -37,7 +37,6 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONException; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.ProjectManager; import com.google.refine.commands.Command; diff --git a/main/src/com/google/refine/exporters/CsvExporter.java b/main/src/com/google/refine/exporters/CsvExporter.java index a25276703..03724ecb8 100644 --- a/main/src/com/google/refine/exporters/CsvExporter.java +++ b/main/src/com/google/refine/exporters/CsvExporter.java @@ -43,7 +43,6 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; - import com.google.refine.browsing.Engine; import com.google.refine.model.Project; import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/exporters/HtmlTableExporter.java b/main/src/com/google/refine/exporters/HtmlTableExporter.java index 530a6e9d5..0f3f3ff0c 100644 --- a/main/src/com/google/refine/exporters/HtmlTableExporter.java +++ b/main/src/com/google/refine/exporters/HtmlTableExporter.java @@ -39,10 +39,8 @@ import java.util.List; import java.util.Properties; import org.apache.commons.lang3.StringEscapeUtils; -import org.json.JSONObject; import com.fasterxml.jackson.databind.JsonNode; - import com.google.refine.ProjectManager; import com.google.refine.browsing.Engine; import com.google.refine.model.Project; diff --git a/main/src/com/google/refine/exporters/OdsExporter.java b/main/src/com/google/refine/exporters/OdsExporter.java index e397d0ded..64ef9d19b 100644 --- a/main/src/com/google/refine/exporters/OdsExporter.java +++ b/main/src/com/google/refine/exporters/OdsExporter.java @@ -45,7 +45,6 @@ import org.odftoolkit.odfdom.doc.table.OdfTableCell; import org.odftoolkit.odfdom.doc.table.OdfTableRow; import com.fasterxml.jackson.databind.JsonNode; - import com.google.refine.ProjectManager; import com.google.refine.browsing.Engine; import com.google.refine.model.Project; diff --git a/main/src/com/google/refine/exporters/TemplatingExporter.java b/main/src/com/google/refine/exporters/TemplatingExporter.java index 05568fbf5..a18a62b57 100644 --- a/main/src/com/google/refine/exporters/TemplatingExporter.java +++ b/main/src/com/google/refine/exporters/TemplatingExporter.java @@ -41,7 +41,6 @@ import org.json.JSONException; import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.FilteredRecords; diff --git a/main/src/com/google/refine/exporters/XlsExporter.java b/main/src/com/google/refine/exporters/XlsExporter.java index 3910f5cef..79ffdaecd 100644 --- a/main/src/com/google/refine/exporters/XlsExporter.java +++ b/main/src/com/google/refine/exporters/XlsExporter.java @@ -50,7 +50,6 @@ import org.apache.poi.ss.util.WorkbookUtil; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import com.fasterxml.jackson.databind.JsonNode; - import com.google.refine.ProjectManager; import com.google.refine.browsing.Engine; import com.google.refine.model.Project; diff --git a/main/src/com/google/refine/exporters/sql/SqlExporter.java b/main/src/com/google/refine/exporters/sql/SqlExporter.java index dd00a2f00..1bc55fd35 100755 --- a/main/src/com/google/refine/exporters/sql/SqlExporter.java +++ b/main/src/com/google/refine/exporters/sql/SqlExporter.java @@ -35,12 +35,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.JsonNode; - import com.google.refine.ProjectManager; import com.google.refine.browsing.Engine; import com.google.refine.exporters.CustomizableTabularExporterUtilities; diff --git a/main/src/com/google/refine/expr/MetaParser.java b/main/src/com/google/refine/expr/MetaParser.java index 03ec48949..7473868ab 100644 --- a/main/src/com/google/refine/expr/MetaParser.java +++ b/main/src/com/google/refine/expr/MetaParser.java @@ -41,7 +41,6 @@ import java.util.Set; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.grel.Parser; import clojure.lang.IFn; diff --git a/main/src/com/google/refine/expr/functions/strings/Trim.java b/main/src/com/google/refine/expr/functions/strings/Trim.java index 68e6efd10..6d75a74ca 100644 --- a/main/src/com/google/refine/expr/functions/strings/Trim.java +++ b/main/src/com/google/refine/expr/functions/strings/Trim.java @@ -36,7 +36,6 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; import com.google.common.base.CharMatcher; - import com.google.refine.expr.EvalError; import com.google.refine.grel.Function; diff --git a/main/src/com/google/refine/grel/Control.java b/main/src/com/google/refine/grel/Control.java index 392017e23..5ff09b19a 100644 --- a/main/src/com/google/refine/grel/Control.java +++ b/main/src/com/google/refine/grel/Control.java @@ -38,7 +38,6 @@ import java.util.Properties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.expr.Evaluable; /** diff --git a/main/src/com/google/refine/history/History.java b/main/src/com/google/refine/history/History.java index e667e3503..bd0181c7e 100644 --- a/main/src/com/google/refine/history/History.java +++ b/main/src/com/google/refine/history/History.java @@ -47,7 +47,6 @@ import java.util.List; import java.util.Properties; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.ProjectManager; import com.google.refine.RefineServlet; import com.google.refine.model.Project; diff --git a/main/src/com/google/refine/history/HistoryEntry.java b/main/src/com/google/refine/history/HistoryEntry.java index 137bae283..108df9416 100644 --- a/main/src/com/google/refine/history/HistoryEntry.java +++ b/main/src/com/google/refine/history/HistoryEntry.java @@ -45,7 +45,6 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonView; - import com.google.refine.ProjectManager; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; diff --git a/main/src/com/google/refine/history/HistoryProcess.java b/main/src/com/google/refine/history/HistoryProcess.java index 80a5ccbba..903ac250d 100644 --- a/main/src/com/google/refine/history/HistoryProcess.java +++ b/main/src/com/google/refine/history/HistoryProcess.java @@ -35,7 +35,6 @@ package com.google.refine.history; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.model.Project; import com.google.refine.process.Process; import com.google.refine.process.ProcessManager; diff --git a/main/src/com/google/refine/importers/ExcelImporter.java b/main/src/com/google/refine/importers/ExcelImporter.java index 78d912084..efdd8b159 100644 --- a/main/src/com/google/refine/importers/ExcelImporter.java +++ b/main/src/com/google/refine/importers/ExcelImporter.java @@ -54,12 +54,12 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Cell; @@ -69,6 +69,7 @@ import com.google.refine.model.Recon.Judgment; import com.google.refine.model.ReconCandidate; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class ExcelImporter extends TabularImportingParserBase { static final Logger logger = LoggerFactory.getLogger(ExcelImporter.class); @@ -78,15 +79,15 @@ public class ExcelImporter extends TabularImportingParserBase { } @Override - public JSONObject createParserUIInitializationData( - ImportingJob job, List fileRecords, String format) { - JSONObject options = super.createParserUIInitializationData(job, fileRecords, format); + public ObjectNode createParserUIInitializationData( + ImportingJob job, List fileRecords, String format) { + ObjectNode options = super.createParserUIInitializationData(job, fileRecords, format); - JSONArray sheetRecords = new JSONArray(); + ArrayNode sheetRecords = ParsingUtilities.mapper.createArrayNode(); JSONUtilities.safePut(options, "sheetRecords", sheetRecords); try { for (int index = 0;index < fileRecords.size();index++) { - JSONObject fileRecord = fileRecords.get(index); + ObjectNode fileRecord = fileRecords.get(index); File file = ImportingUtilities.getFile(job, fileRecord); InputStream is = new FileInputStream(file); @@ -104,7 +105,7 @@ public class ExcelImporter extends TabularImportingParserBase { Sheet sheet = wb.getSheetAt(i); int rows = sheet.getLastRowNum() - sheet.getFirstRowNum() + 1; - JSONObject sheetRecord = new JSONObject(); + ObjectNode sheetRecord = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(sheetRecord, "name", file.getName() + "#" + sheet.getSheetName()); JSONUtilities.safePut(sheetRecord, "fileNameAndSheetIndex", file.getName() + "#" + i); JSONUtilities.safePut(sheetRecord, "rows", rows); @@ -138,7 +139,7 @@ public class ExcelImporter extends TabularImportingParserBase { String fileSource, InputStream inputStream, int limit, - JSONObject options, + ObjectNode options, List exceptions ) { Workbook wb = null; @@ -182,14 +183,14 @@ public class ExcelImporter extends TabularImportingParserBase { return; } - JSONArray sheets = JSONUtilities.getArray(options, "sheets"); + ArrayNode sheets = (ArrayNode) options.get("sheets"); - for(int i=0;i fileRecords, String format) { - JSONObject options = super.createParserUIInitializationData(job, fileRecords, format); - JSONArray columnWidths = new JSONArray(); + public ObjectNode createParserUIInitializationData( + ImportingJob job, List fileRecords, String format) { + ObjectNode options = super.createParserUIInitializationData(job, fileRecords, format); + ArrayNode columnWidths = ParsingUtilities.mapper.createArrayNode(); if (fileRecords.size() > 0) { - JSONObject firstFileRecord = fileRecords.get(0); + ObjectNode firstFileRecord = fileRecords.get(0); String encoding = ImportingUtilities.getEncoding(firstFileRecord); String location = JSONUtilities.getString(firstFileRecord, "location", null); if (location != null) { @@ -59,7 +59,7 @@ public class FixedWidthImporter extends TabularImportingParserBase { String fileSource, Reader reader, int limit, - JSONObject options, + ObjectNode options, List exceptions ) { final int[] columnWidths = JSONUtilities.getIntArray(options, "columnWidths"); diff --git a/main/src/com/google/refine/importers/ImporterUtilities.java b/main/src/com/google/refine/importers/ImporterUtilities.java index 7d543a3fb..d66ebb75e 100644 --- a/main/src/com/google/refine/importers/ImporterUtilities.java +++ b/main/src/com/google/refine/importers/ImporterUtilities.java @@ -43,8 +43,7 @@ import java.util.List; import java.util.Map; import java.util.Properties; -import org.json.JSONObject; - +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Column; @@ -197,9 +196,9 @@ public class ImporterUtilities { } static public MultiFileReadingProgress createMultiFileReadingProgress( - final ImportingJob job, List fileRecords) { + final ImportingJob job, List fileRecords) { long totalSize = 0; - for (JSONObject fileRecord : fileRecords) { + for (ObjectNode fileRecord : fileRecords) { File file = ImportingUtilities.getFile(job, fileRecord); totalSize += file.length(); } diff --git a/main/src/com/google/refine/importers/ImportingParserBase.java b/main/src/com/google/refine/importers/ImportingParserBase.java index bcb272d61..c37f02430 100644 --- a/main/src/com/google/refine/importers/ImportingParserBase.java +++ b/main/src/com/google/refine/importers/ImportingParserBase.java @@ -40,10 +40,10 @@ import java.io.Reader; import java.util.List; import org.json.JSONException; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importers.ImporterUtilities.MultiFileReadingProgress; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingParser; @@ -53,6 +53,7 @@ import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; abstract public class ImportingParserBase implements ImportingParser { final static Logger logger = LoggerFactory.getLogger("ImportingParserBase"); @@ -67,9 +68,9 @@ abstract public class ImportingParserBase implements ImportingParser { } @Override - public JSONObject createParserUIInitializationData(ImportingJob job, - List fileRecords, String format) { - JSONObject options = new JSONObject(); + public ObjectNode createParserUIInitializationData(ImportingJob job, + List fileRecords, String format) { + ObjectNode options = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(options, "includeFileSources", fileRecords.size() > 1); return options; @@ -77,10 +78,10 @@ abstract public class ImportingParserBase implements ImportingParser { @Override public void parse(Project project, ProjectMetadata metadata, - final ImportingJob job, List fileRecords, String format, - int limit, JSONObject options, List exceptions) { + final ImportingJob job, List fileRecords, String format, + int limit, ObjectNode options, List exceptions) { MultiFileReadingProgress progress = ImporterUtilities.createMultiFileReadingProgress(job, fileRecords); - for (JSONObject fileRecord : fileRecords) { + for (ObjectNode fileRecord : fileRecords) { if (job.canceled) { break; } @@ -101,9 +102,9 @@ abstract public class ImportingParserBase implements ImportingParser { Project project, ProjectMetadata metadata, ImportingJob job, - JSONObject fileRecord, + ObjectNode fileRecord, int limit, - JSONObject options, + ObjectNode options, List exceptions, final MultiFileReadingProgress progress ) throws IOException { @@ -142,13 +143,13 @@ abstract public class ImportingParserBase implements ImportingParser { String fileSource, Reader reader, int limit, - JSONObject options, + ObjectNode options, List exceptions ) { pushImportingOptions(metadata, fileSource, options); } - private void pushImportingOptions(ProjectMetadata metadata, String fileSource, JSONObject options) { + private void pushImportingOptions(ProjectMetadata metadata, String fileSource, ObjectNode options) { try { options.put("fileSource", fileSource); } catch (JSONException e) { @@ -165,7 +166,7 @@ abstract public class ImportingParserBase implements ImportingParser { String fileSource, InputStream inputStream, int limit, - JSONObject options, + ObjectNode options, List exceptions ) { pushImportingOptions(metadata, fileSource, options); diff --git a/main/src/com/google/refine/importers/JsonImporter.java b/main/src/com/google/refine/importers/JsonImporter.java index 4c7661549..25390755e 100644 --- a/main/src/com/google/refine/importers/JsonImporter.java +++ b/main/src/com/google/refine/importers/JsonImporter.java @@ -39,8 +39,6 @@ import java.io.InputStream; import java.io.Serializable; import java.util.List; -import org.json.JSONArray; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,7 +47,13 @@ import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonParser.NumberType; import com.fasterxml.jackson.core.JsonToken; - +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.BooleanNode; +import com.fasterxml.jackson.databind.node.DoubleNode; +import com.fasterxml.jackson.databind.node.LongNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; import com.google.refine.importers.tree.ImportColumnGroup; import com.google.refine.importers.tree.TreeImportingParserBase; import com.google.refine.importers.tree.TreeReader; @@ -59,6 +63,7 @@ import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Project; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class JsonImporter extends TreeImportingParserBase { static final Logger logger = LoggerFactory.getLogger(JsonImporter.class); @@ -76,18 +81,18 @@ public class JsonImporter extends TreeImportingParserBase { final static private int PREVIEW_PARSING_LIMIT = 1000; @Override - public JSONObject createParserUIInitializationData( - ImportingJob job, List fileRecords, String format) { - JSONObject options = super.createParserUIInitializationData(job, fileRecords, format); + public ObjectNode createParserUIInitializationData(ImportingJob job, + List fileRecords, String format) { + ObjectNode options = super.createParserUIInitializationData(job, fileRecords, format); if (fileRecords.size() > 0) { try { - JSONObject firstFileRecord = fileRecords.get(0); + ObjectNode firstFileRecord = fileRecords.get(0); File file = ImportingUtilities.getFile(job, firstFileRecord); JsonFactory factory = new JsonFactory(); JsonParser parser = factory.createJsonParser(file); PreviewParsingState state = new PreviewParsingState(); - Object rootValue = parseForPreview(parser, state); + JsonNode rootValue = parseForPreview(parser, state); if (rootValue != null) { JSONUtilities.safePut(options, "dom", rootValue); } @@ -99,7 +104,7 @@ public class JsonImporter extends TreeImportingParserBase { return options; } - final static private Object parseForPreview(JsonParser parser, PreviewParsingState state, JsonToken token) + final static private JsonNode parseForPreview(JsonParser parser, PreviewParsingState state, JsonToken token) throws JsonParseException, IOException { if (token != null) { switch (token) { @@ -108,15 +113,15 @@ public class JsonImporter extends TreeImportingParserBase { case START_OBJECT: return parseObjectForPreview(parser, state); case VALUE_STRING: - return parser.getText(); + return new TextNode(parser.getText()); case VALUE_NUMBER_INT: - return Long.valueOf(parser.getLongValue()); + return new LongNode(parser.getLongValue()); case VALUE_NUMBER_FLOAT: - return Double.valueOf(parser.getDoubleValue()); + return new DoubleNode(parser.getDoubleValue()); case VALUE_TRUE: - return Boolean.TRUE; + return BooleanNode.getTrue(); case VALUE_FALSE: - return Boolean.FALSE; + return BooleanNode.getFalse(); case VALUE_NULL: return null; case END_ARRAY: @@ -131,7 +136,7 @@ public class JsonImporter extends TreeImportingParserBase { return null; } - final static private Object parseForPreview(JsonParser parser, PreviewParsingState state) { + final static private JsonNode parseForPreview(JsonParser parser, PreviewParsingState state) { try { JsonToken token = parser.nextToken(); state.tokenCount++; @@ -141,8 +146,8 @@ public class JsonImporter extends TreeImportingParserBase { } } - final static private JSONObject parseObjectForPreview(JsonParser parser, PreviewParsingState state) { - JSONObject result = new JSONObject(); + final static private ObjectNode parseObjectForPreview(JsonParser parser, PreviewParsingState state) { + ObjectNode result = ParsingUtilities.mapper.createObjectNode(); loop:while (state.tokenCount < PREVIEW_PARSING_LIMIT) { try { JsonToken token = parser.nextToken(); @@ -154,7 +159,7 @@ public class JsonImporter extends TreeImportingParserBase { switch (token) { case FIELD_NAME: String fieldName = parser.getText(); - Object fieldValue = parseForPreview(parser, state); + JsonNode fieldValue = parseForPreview(parser, state); JSONUtilities.safePut(result, fieldName, fieldValue); break; case END_OBJECT: @@ -169,8 +174,8 @@ public class JsonImporter extends TreeImportingParserBase { return result; } - final static private JSONArray parseArrayForPreview(JsonParser parser, PreviewParsingState state) { - JSONArray result = new JSONArray(); + final static private ArrayNode parseArrayForPreview(JsonParser parser, PreviewParsingState state) { + ArrayNode result = ParsingUtilities.mapper.createArrayNode(); loop:while (state.tokenCount < PREVIEW_PARSING_LIMIT) { try { JsonToken token = parser.nextToken(); @@ -183,8 +188,8 @@ public class JsonImporter extends TreeImportingParserBase { case END_ARRAY: break loop; default: - Object element = parseForPreview(parser, state, token); - JSONUtilities.append(result, element); + JsonNode element = parseForPreview(parser, state, token); + result.add(element); } } catch (IOException e) { break; @@ -196,7 +201,7 @@ public class JsonImporter extends TreeImportingParserBase { @Override public void parseOneFile(Project project, ProjectMetadata metadata, ImportingJob job, String fileSource, InputStream is, - ImportColumnGroup rootColumnGroup, int limit, JSONObject options, List exceptions) { + ImportColumnGroup rootColumnGroup, int limit, ObjectNode options, List exceptions) { parseOneFile(project, metadata, job, fileSource, new JSONTreeReader(is), rootColumnGroup, limit, options, exceptions); diff --git a/main/src/com/google/refine/importers/LineBasedImporter.java b/main/src/com/google/refine/importers/LineBasedImporter.java index eb1ba6c08..f8829fed5 100644 --- a/main/src/com/google/refine/importers/LineBasedImporter.java +++ b/main/src/com/google/refine/importers/LineBasedImporter.java @@ -6,10 +6,10 @@ import java.io.Reader; import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Project; import com.google.refine.model.metadata.ProjectMetadata; @@ -23,9 +23,9 @@ public class LineBasedImporter extends TabularImportingParserBase { } @Override - public JSONObject createParserUIInitializationData( - ImportingJob job, List fileRecords, String format) { - JSONObject options = super.createParserUIInitializationData(job, fileRecords, format); + public ObjectNode createParserUIInitializationData( + ImportingJob job, List fileRecords, String format) { + ObjectNode options = super.createParserUIInitializationData(job, fileRecords, format); JSONUtilities.safePut(options, "linesPerRow", 1); JSONUtilities.safePut(options, "headerLines", 0); @@ -42,7 +42,7 @@ public class LineBasedImporter extends TabularImportingParserBase { String fileSource, Reader reader, int limit, - JSONObject options, + ObjectNode options, List exceptions ) { final int linesPerRow = JSONUtilities.getInt(options, "linesPerRow", 1); diff --git a/main/src/com/google/refine/importers/MarcImporter.java b/main/src/com/google/refine/importers/MarcImporter.java index 4c1c35717..acb52c5ce 100644 --- a/main/src/com/google/refine/importers/MarcImporter.java +++ b/main/src/com/google/refine/importers/MarcImporter.java @@ -40,12 +40,12 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import org.json.JSONObject; import org.marc4j.MarcPermissiveStreamReader; import org.marc4j.MarcWriter; import org.marc4j.MarcXmlWriter; import org.marc4j.marc.Record; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.util.JSONUtilities; @@ -57,9 +57,9 @@ public class MarcImporter extends XmlImporter { } @Override - public JSONObject createParserUIInitializationData(ImportingJob job, java.util.List fileRecords, String format) { + public ObjectNode createParserUIInitializationData(ImportingJob job, java.util.List fileRecords, String format) { if (fileRecords.size() > 0) { - JSONObject firstFileRecord = fileRecords.get(0); + ObjectNode firstFileRecord = fileRecords.get(0); File file = ImportingUtilities.getFile(job, firstFileRecord); File tempFile = new File(file.getAbsolutePath()+".xml"); @@ -97,7 +97,7 @@ public class MarcImporter extends XmlImporter { logger.error("Failed to create temporary XML file from MARC file", e); } } - JSONObject options = super.createParserUIInitializationData(job, fileRecords, format); + ObjectNode options = super.createParserUIInitializationData(job, fileRecords, format); return options; }; diff --git a/main/src/com/google/refine/importers/OdsImporter.java b/main/src/com/google/refine/importers/OdsImporter.java index a03f3ff66..74e13a2d3 100644 --- a/main/src/com/google/refine/importers/OdsImporter.java +++ b/main/src/com/google/refine/importers/OdsImporter.java @@ -45,9 +45,7 @@ import java.util.List; import java.util.Map; import org.apache.commons.lang3.exception.ExceptionUtils; -import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONObject; import org.odftoolkit.odfdom.doc.OdfDocument; import org.odftoolkit.odfdom.doc.table.OdfTable; import org.odftoolkit.odfdom.doc.table.OdfTableCell; @@ -55,6 +53,8 @@ import org.odftoolkit.odfdom.doc.table.OdfTableRow; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Cell; @@ -64,6 +64,7 @@ import com.google.refine.model.Recon.Judgment; import com.google.refine.model.ReconCandidate; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class OdsImporter extends TabularImportingParserBase { @@ -75,16 +76,16 @@ public class OdsImporter extends TabularImportingParserBase { @Override - public JSONObject createParserUIInitializationData( - ImportingJob job, List fileRecords, String format) { - JSONObject options = super.createParserUIInitializationData(job, fileRecords, format); + public ObjectNode createParserUIInitializationData( + ImportingJob job, List fileRecords, String format) { + ObjectNode options = super.createParserUIInitializationData(job, fileRecords, format); - JSONArray sheetRecords = new JSONArray(); + ArrayNode sheetRecords = ParsingUtilities.mapper.createArrayNode(); JSONUtilities.safePut(options, "sheetRecords", sheetRecords); OdfDocument odfDoc = null; try { for (int index = 0;index < fileRecords.size();index++) { - JSONObject fileRecord = fileRecords.get(index); + ObjectNode fileRecord = fileRecords.get(index); File file = ImportingUtilities.getFile(job, fileRecord); InputStream is = new FileInputStream(file); odfDoc = OdfDocument.loadDocument(is); @@ -95,7 +96,7 @@ public class OdsImporter extends TabularImportingParserBase { OdfTable sheet = tables.get(i); int rows = sheet.getRowCount(); - JSONObject sheetRecord = new JSONObject(); + ObjectNode sheetRecord = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(sheetRecord, "name", file.getName() + "#" + sheet.getTableName()); JSONUtilities.safePut(sheetRecord, "fileNameAndSheetIndex", file.getName() + "#" + i); JSONUtilities.safePut(sheetRecord, "rows", rows); @@ -129,7 +130,7 @@ public class OdsImporter extends TabularImportingParserBase { String fileSource, InputStream inputStream, int limit, - JSONObject options, + ObjectNode options, List exceptions ) { OdfDocument odfDoc; @@ -142,13 +143,13 @@ public class OdsImporter extends TabularImportingParserBase { List tables = odfDoc.getTableList(); - JSONArray sheets = JSONUtilities.getArray(options, "sheets"); - for(int i=0;i exceptions) { + InputStream input, int limit, ObjectNode options, List exceptions) { // create an empty model Model model = ModelFactory.createDefaultModel(); diff --git a/main/src/com/google/refine/importers/SeparatorBasedImporter.java b/main/src/com/google/refine/importers/SeparatorBasedImporter.java index 80920aaae..cd086e47f 100644 --- a/main/src/com/google/refine/importers/SeparatorBasedImporter.java +++ b/main/src/com/google/refine/importers/SeparatorBasedImporter.java @@ -50,8 +50,8 @@ import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringEscapeUtils; -import org.json.JSONObject; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Project; @@ -66,9 +66,9 @@ public class SeparatorBasedImporter extends TabularImportingParserBase { } @Override - public JSONObject createParserUIInitializationData(ImportingJob job, - List fileRecords, String format) { - JSONObject options = super.createParserUIInitializationData(job, fileRecords, format); + public ObjectNode createParserUIInitializationData(ImportingJob job, + List fileRecords, String format) { + ObjectNode options = super.createParserUIInitializationData(job, fileRecords, format); String separator = guessSeparator(job, fileRecords); JSONUtilities.safePut(options, "separator", separator != null ? separator : "\\t"); @@ -88,7 +88,7 @@ public class SeparatorBasedImporter extends TabularImportingParserBase { String fileSource, Reader reader, int limit, - JSONObject options, + ObjectNode options, List exceptions ) { String sep = JSONUtilities.getString(options, "separator", "\\t"); @@ -119,6 +119,7 @@ public class SeparatorBasedImporter extends TabularImportingParserBase { } } } + final List columnNames = retrievedColumnNames; Character quote = CSVParser.DEFAULT_QUOTE_CHARACTER; @@ -144,14 +145,14 @@ public class SeparatorBasedImporter extends TabularImportingParserBase { if (columnNames != null && !usedColumnNames) { usedColumnNames = true; return columnNames; - } else { - String line = lnReader.readLine(); - if (line == null) { - return null; } else { - return getCells(line, parser, lnReader); + String line = lnReader.readLine(); + if (line == null) { + return null; + } else { + return getCells(line, parser, lnReader); + } } - } } }; @@ -172,9 +173,9 @@ public class SeparatorBasedImporter extends TabularImportingParserBase { return cells; } - static public String guessSeparator(ImportingJob job, List fileRecords) { + static public String guessSeparator(ImportingJob job, List fileRecords) { for (int i = 0; i < 5 && i < fileRecords.size(); i++) { - JSONObject fileRecord = fileRecords.get(i); + ObjectNode fileRecord = fileRecords.get(i); String encoding = ImportingUtilities.getEncoding(fileRecord); String location = JSONUtilities.getString(fileRecord, "location", null); diff --git a/main/src/com/google/refine/importers/TabularImportingParserBase.java b/main/src/com/google/refine/importers/TabularImportingParserBase.java index efdcc0fe2..3018c67e5 100644 --- a/main/src/com/google/refine/importers/TabularImportingParserBase.java +++ b/main/src/com/google/refine/importers/TabularImportingParserBase.java @@ -39,8 +39,7 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; - +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.expr.ExpressionUtils; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Cell; @@ -56,9 +55,9 @@ abstract public class TabularImportingParserBase extends ImportingParserBase { } @Override - public JSONObject createParserUIInitializationData(ImportingJob job, - List fileRecords, String format) { - JSONObject options = super.createParserUIInitializationData(job, fileRecords, format); + public ObjectNode createParserUIInitializationData(ImportingJob job, + List fileRecords, String format) { + ObjectNode options = super.createParserUIInitializationData(job, fileRecords, format); JSONUtilities.safePut(options, "ignoreLines", -1); // number of blank lines at the beginning to ignore JSONUtilities.safePut(options, "headerLines", 1); // number of header lines @@ -85,7 +84,7 @@ abstract public class TabularImportingParserBase extends ImportingParserBase { TableDataReader reader, String fileSource, int limit, - JSONObject options, + ObjectNode options, List exceptions ) { int ignoreLines = JSONUtilities.getInt(options, "ignoreLines", -1); @@ -203,7 +202,7 @@ abstract public class TabularImportingParserBase extends ImportingParserBase { } public void parseOneFile(Project project, ProjectMetadata metadata, ImportingJob job, String fileSource, - Reader dataReader, int limit, JSONObject options, List exceptions) { + Reader dataReader, int limit, ObjectNode options, List exceptions) { super.parseOneFile(project, metadata, job, fileSource, dataReader, limit, options, exceptions); } } diff --git a/main/src/com/google/refine/importers/WikitextImporter.java b/main/src/com/google/refine/importers/WikitextImporter.java index 8bc509759..429492f38 100644 --- a/main/src/com/google/refine/importers/WikitextImporter.java +++ b/main/src/com/google/refine/importers/WikitextImporter.java @@ -9,7 +9,6 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.json.JSONObject; import org.sweble.wikitext.parser.ParserConfig; import org.sweble.wikitext.parser.WikitextEncodingValidator; import org.sweble.wikitext.parser.WikitextParser; @@ -51,8 +50,8 @@ import org.sweble.wikitext.parser.parser.PreprocessorToParserTransformer; import org.sweble.wikitext.parser.preprocessor.PreprocessedWikitext; import org.sweble.wikitext.parser.utils.SimpleParserConfig; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.io.CharStreams; - import com.google.refine.importing.ImportingJob; import com.google.refine.model.Cell; import com.google.refine.model.Column; @@ -77,9 +76,9 @@ public class WikitextImporter extends TabularImportingParserBase { } @Override - public JSONObject createParserUIInitializationData( - ImportingJob job, List fileRecords, String format) { - JSONObject options = super.createParserUIInitializationData(job, fileRecords, format); + public ObjectNode createParserUIInitializationData( + ImportingJob job, List fileRecords, String format) { + ObjectNode options = super.createParserUIInitializationData(job, fileRecords, format); JSONUtilities.safePut(options, "guessCellValueTypes", false); JSONUtilities.safePut(options, "blankSpanningCells", true); @@ -668,7 +667,7 @@ public class WikitextImporter extends TabularImportingParserBase { String fileSource, Reader reader, int limit, - JSONObject options, + ObjectNode options, List exceptions ) { // Set-up a simple wiki configuration diff --git a/main/src/com/google/refine/importers/XmlImporter.java b/main/src/com/google/refine/importers/XmlImporter.java index 7a3643091..0e67fbc89 100644 --- a/main/src/com/google/refine/importers/XmlImporter.java +++ b/main/src/com/google/refine/importers/XmlImporter.java @@ -46,11 +46,11 @@ import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; -import org.json.JSONArray; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importers.tree.ImportColumnGroup; import com.google.refine.importers.tree.TreeImportingParserBase; import com.google.refine.importers.tree.TreeReader; @@ -60,6 +60,7 @@ import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Project; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class XmlImporter extends TreeImportingParserBase { static final Logger logger = LoggerFactory.getLogger(XmlImporter.class); @@ -75,12 +76,12 @@ public class XmlImporter extends TreeImportingParserBase { final static private int PREVIEW_PARSING_LIMIT = 1000; @Override - public JSONObject createParserUIInitializationData( - ImportingJob job, List fileRecords, String format) { - JSONObject options = super.createParserUIInitializationData(job, fileRecords, format); + public ObjectNode createParserUIInitializationData( + ImportingJob job, List fileRecords, String format) { + ObjectNode options = super.createParserUIInitializationData(job, fileRecords, format); try { if (fileRecords.size() > 0) { - JSONObject firstFileRecord = fileRecords.get(0); + ObjectNode firstFileRecord = fileRecords.get(0); File file = ImportingUtilities.getFile(job, firstFileRecord); InputStream is = new FileInputStream(file); @@ -92,7 +93,7 @@ public class XmlImporter extends TreeImportingParserBase { int tokenType = parser.next(); state.tokenCount++; if (tokenType == XMLStreamConstants.START_ELEMENT) { - JSONObject rootElement = descendElement(parser, state); + ObjectNode rootElement = descendElement(parser, state); if (rootElement != null) { JSONUtilities.safePut(options, "dom", rootElement); break; @@ -114,8 +115,8 @@ public class XmlImporter extends TreeImportingParserBase { return options; } - final static private JSONObject descendElement(XMLStreamReader parser, PreviewParsingState state) { - JSONObject result = new JSONObject(); + final static private ObjectNode descendElement(XMLStreamReader parser, PreviewParsingState state) { + ObjectNode result = ParsingUtilities.mapper.createObjectNode(); { String name = parser.getLocalName(); JSONUtilities.safePut(result, "n", name); @@ -132,12 +133,11 @@ public class XmlImporter extends TreeImportingParserBase { int namespaceCount = parser.getNamespaceCount(); if (namespaceCount > 0) { - JSONArray namespaces = new JSONArray(); - JSONUtilities.safePut(result, "ns", namespaces); + ArrayNode namespaces = result.putArray("ns"); for (int i = 0; i < namespaceCount; i++) { - JSONObject namespace = new JSONObject(); - JSONUtilities.append(namespaces, namespace); + ObjectNode namespace = ParsingUtilities.mapper.createObjectNode(); + namespaces.add(namespace); JSONUtilities.safePut(namespace, "p", parser.getNamespacePrefix(i)); JSONUtilities.safePut(namespace, "uri", parser.getNamespaceURI(i)); } @@ -145,12 +145,11 @@ public class XmlImporter extends TreeImportingParserBase { int attributeCount = parser.getAttributeCount(); if (attributeCount > 0) { - JSONArray attributes = new JSONArray(); - JSONUtilities.safePut(result, "a", attributes); + ArrayNode attributes = result.putArray("a"); for (int i = 0; i < attributeCount; i++) { - JSONObject attribute = new JSONObject(); - JSONUtilities.append(attributes, attribute); + ObjectNode attribute = ParsingUtilities.mapper.createObjectNode(); + attributes.add(attribute); JSONUtilities.safePut(attribute, "n", parser.getAttributeLocalName(i)); JSONUtilities.safePut(attribute, "v", parser.getAttributeValue(i)); String prefix = parser.getAttributePrefix(i); @@ -160,7 +159,7 @@ public class XmlImporter extends TreeImportingParserBase { } } - JSONArray children = new JSONArray(); + ArrayNode children = ParsingUtilities.mapper.createArrayNode(); try { while (parser.hasNext() && state.tokenCount < PREVIEW_PARSING_LIMIT) { int tokenType = parser.next(); @@ -168,16 +167,16 @@ public class XmlImporter extends TreeImportingParserBase { if (tokenType == XMLStreamConstants.END_ELEMENT) { break; } else if (tokenType == XMLStreamConstants.START_ELEMENT) { - JSONObject childElement = descendElement(parser, state); + ObjectNode childElement = descendElement(parser, state); if (childElement != null) { - JSONUtilities.append(children, childElement); + children.add(childElement); } } else if (tokenType == XMLStreamConstants.CHARACTERS || tokenType == XMLStreamConstants.CDATA || tokenType == XMLStreamConstants.SPACE) { - JSONObject childElement = new JSONObject(); + ObjectNode childElement = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(childElement, "t", parser.getText()); - JSONUtilities.append(children, childElement); + children.add(childElement); } else { // ignore everything else } @@ -186,8 +185,8 @@ public class XmlImporter extends TreeImportingParserBase { logger.error("Error generating parser UI initialization data for XML file", e); } - if (children.length() > 0) { - JSONUtilities.safePut(result, "c", children); + if (children.size() > 0) { + result.put("c", children); } return result; } @@ -195,7 +194,7 @@ public class XmlImporter extends TreeImportingParserBase { @Override public void parseOneFile(Project project, ProjectMetadata metadata, ImportingJob job, String fileSource, InputStream inputStream, - ImportColumnGroup rootColumnGroup, int limit, JSONObject options, + ImportColumnGroup rootColumnGroup, int limit, ObjectNode options, List exceptions) { try { diff --git a/main/src/com/google/refine/importers/tree/TreeImportingParserBase.java b/main/src/com/google/refine/importers/tree/TreeImportingParserBase.java index 79b83a14a..27d207034 100644 --- a/main/src/com/google/refine/importers/tree/TreeImportingParserBase.java +++ b/main/src/com/google/refine/importers/tree/TreeImportingParserBase.java @@ -40,8 +40,8 @@ import java.io.Reader; import java.util.List; import org.apache.commons.lang3.NotImplementedException; -import org.json.JSONObject; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importers.ImporterUtilities; import com.google.refine.importers.ImporterUtilities.MultiFileReadingProgress; import com.google.refine.importers.ImportingParserBase; @@ -62,9 +62,9 @@ abstract public class TreeImportingParserBase extends ImportingParserBase { } @Override - public JSONObject createParserUIInitializationData(ImportingJob job, - List fileRecords, String format) { - JSONObject options = super.createParserUIInitializationData(job, fileRecords, format); + public ObjectNode createParserUIInitializationData(ImportingJob job, + List fileRecords, String format) { + ObjectNode options = super.createParserUIInitializationData(job, fileRecords, format); JSONUtilities.safePut(options, "trimStrings", false); JSONUtilities.safePut(options, "guessCellValueTypes", false); @@ -75,13 +75,13 @@ abstract public class TreeImportingParserBase extends ImportingParserBase { @Override public void parse(Project project, ProjectMetadata metadata, - ImportingJob job, List fileRecords, String format, - int limit, JSONObject options, List exceptions) { + ImportingJob job, List fileRecords, String format, + int limit, ObjectNode options, List exceptions) { MultiFileReadingProgress progress = ImporterUtilities.createMultiFileReadingProgress(job, fileRecords); ImportColumnGroup rootColumnGroup = new ImportColumnGroup(); - for (JSONObject fileRecord : fileRecords) { + for (ObjectNode fileRecord : fileRecords) { try { parseOneFile(project, metadata, job, fileRecord, rootColumnGroup, limit, options, exceptions, progress); } catch (IOException e) { @@ -102,10 +102,10 @@ abstract public class TreeImportingParserBase extends ImportingParserBase { Project project, ProjectMetadata metadata, ImportingJob job, - JSONObject fileRecord, + ObjectNode fileRecord, ImportColumnGroup rootColumnGroup, int limit, - JSONObject options, + ObjectNode options, List exceptions, final MultiFileReadingProgress progress ) throws IOException { @@ -151,7 +151,7 @@ abstract public class TreeImportingParserBase extends ImportingParserBase { Reader reader, ImportColumnGroup rootColumnGroup, int limit, - JSONObject options, + ObjectNode options, List exceptions ) { throw new NotImplementedException("project ID:" + project.id); @@ -171,7 +171,7 @@ abstract public class TreeImportingParserBase extends ImportingParserBase { InputStream inputStream, ImportColumnGroup rootColumnGroup, int limit, - JSONObject options, + ObjectNode options, List exceptions ) { // throw new NotImplementedException(); @@ -190,7 +190,7 @@ abstract public class TreeImportingParserBase extends ImportingParserBase { TreeReader treeParser, ImportColumnGroup rootColumnGroup, int limit, - JSONObject options, + ObjectNode options, List exceptions ) { String[] recordPath = JSONUtilities.getStringArray(options, "recordPath"); diff --git a/main/src/com/google/refine/importing/DefaultImportingController.java b/main/src/com/google/refine/importing/DefaultImportingController.java index 65fb583ad..96c063735 100644 --- a/main/src/com/google/refine/importing/DefaultImportingController.java +++ b/main/src/com/google/refine/importing/DefaultImportingController.java @@ -45,13 +45,12 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonGenerator; - +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.RefineServlet; import com.google.refine.commands.HttpUtilities; import com.google.refine.importing.ImportingManager.Format; @@ -112,8 +111,8 @@ public class DefaultImportingController implements ImportingController { job.updating = true; try { - JSONObject config = job.getOrCreateDefaultConfig(); - if (!("new".equals(config.getString("state")))) { + ObjectNode config = job.getOrCreateDefaultConfig(); + if (!("new".equals(JSONUtilities.getString(config, "state", null)))) { HttpUtilities.respond(response, "error", "Job already started; cannot load more data"); return; } @@ -140,13 +139,13 @@ public class DefaultImportingController implements ImportingController { job.updating = true; try { - JSONObject config = job.getOrCreateDefaultConfig(); - if (!("ready".equals(config.getString("state")))) { + ObjectNode config = job.getOrCreateDefaultConfig(); + if (!("ready".equals(JSONUtilities.getString(config, "state", null)))) { HttpUtilities.respond(response, "error", "Job not ready"); return; } - JSONArray fileSelectionArray = ParsingUtilities.evaluateJsonStringToArray( + ArrayNode fileSelectionArray = ParsingUtilities.evaluateJsonStringToArrayNode( request.getParameter("fileSelection")); ImportingUtilities.updateJobWithNewFileSelection(job, fileSelectionArray); @@ -172,14 +171,14 @@ public class DefaultImportingController implements ImportingController { job.updating = true; try { - JSONObject config = job.getOrCreateDefaultConfig(); - if (!("ready".equals(config.getString("state")))) { + ObjectNode config = job.getOrCreateDefaultConfig(); + if (!("ready".equals(JSONUtilities.getString(config, "state", null)))) { HttpUtilities.respond(response, "error", "Job not ready"); return; } String format = request.getParameter("format"); - JSONObject optionObj = ParsingUtilities.evaluateJsonStringToObject( + ObjectNode optionObj = ParsingUtilities.evaluateJsonStringToObjectNode( request.getParameter("options")); List exceptions = new LinkedList(); @@ -230,9 +229,9 @@ public class DefaultImportingController implements ImportingController { String format = request.getParameter("format"); Format formatRecord = ImportingManager.formatToRecord.get(format); if (formatRecord != null && formatRecord.parser != null) { - JSONObject options = formatRecord.parser.createParserUIInitializationData( + ObjectNode options = formatRecord.parser.createParserUIInitializationData( job, job.getSelectedFileRecords(), format); - JSONObject result = new JSONObject(); + ObjectNode result = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(result, "status", "ok"); JSONUtilities.safePut(result, "options", options); @@ -255,14 +254,14 @@ public class DefaultImportingController implements ImportingController { job.updating = true; job.touch(); try { - JSONObject config = job.getOrCreateDefaultConfig(); - if (!("ready".equals(config.getString("state")))) { + ObjectNode config = job.getOrCreateDefaultConfig(); + if (!("ready".equals(JSONUtilities.getString(config, "state", null)))) { HttpUtilities.respond(response, "error", "Job not ready"); return; } String format = request.getParameter("format"); - JSONObject optionObj = ParsingUtilities.evaluateJsonStringToObject( + ObjectNode optionObj = ParsingUtilities.evaluateJsonStringToObjectNode( request.getParameter("options")); List exceptions = new LinkedList(); @@ -317,13 +316,13 @@ public class DefaultImportingController implements ImportingController { } } - static public JSONArray convertErrorsToJsonArray(List exceptions) { - JSONArray a = new JSONArray(); + static public ArrayNode convertErrorsToJsonArray(List exceptions) { + ArrayNode a = ParsingUtilities.mapper.createArrayNode(); for (Exception e : exceptions) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); - JSONObject o = new JSONObject(); + ObjectNode o = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(o, "message", e.getLocalizedMessage()); JSONUtilities.safePut(o, "stack", sw.toString()); JSONUtilities.append(a, o); diff --git a/main/src/com/google/refine/importing/ImportingJob.java b/main/src/com/google/refine/importing/ImportingJob.java index a19af621a..1da792315 100644 --- a/main/src/com/google/refine/importing/ImportingJob.java +++ b/main/src/com/google/refine/importing/ImportingJob.java @@ -39,24 +39,24 @@ import java.util.ArrayList; import java.util.List; import org.apache.commons.io.FileUtils; -import org.json.JSONArray; -import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRawValue; - +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.ProjectManager; import com.google.refine.model.Project; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class ImportingJob { final public long id; final public File dir; // Temporary directory where the data about this job is stored - private JSONObject config; + private ObjectNode config; public Project project; public ProjectMetadata metadata; @@ -71,7 +71,7 @@ public class ImportingJob { this.id = id; this.dir = dir; - JSONObject cfg = new JSONObject(); + ObjectNode cfg = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(cfg, "state", "new"); JSONUtilities.safePut(cfg, "hasData", false); this.config = cfg; @@ -88,7 +88,7 @@ public class ImportingJob { } @JsonIgnore - public JSONObject getOrCreateDefaultConfig() { + public ObjectNode getOrCreateDefaultConfig() { return config; } @@ -114,9 +114,9 @@ public class ImportingJob { public void setProgress(int percent, String message) { synchronized (config) { - JSONObject progress = JSONUtilities.getObject(config, "progress"); + ObjectNode progress = JSONUtilities.getObject(config, "progress"); if (progress == null) { - progress = new JSONObject(); + progress = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(config, "progress", progress); } JSONUtilities.safePut(progress, "message", message); @@ -126,13 +126,13 @@ public class ImportingJob { } } - public void setFileSelection(JSONArray fileSelectionArray) { + public void setFileSelection(ArrayNode fileSelectionArray) { synchronized (config) { JSONUtilities.safePut(config, "fileSelection", fileSelectionArray); } } - public void setRankedFormats(JSONArray rankedFormats) { + public void setRankedFormats(ArrayNode rankedFormats) { synchronized (config) { JSONUtilities.safePut(config, "rankedFormats", rankedFormats); } @@ -140,7 +140,7 @@ public class ImportingJob { @JsonIgnore - public JSONObject getRetrievalRecord() { + public ObjectNode getRetrievalRecord() { synchronized(config) { return JSONUtilities.getObject(config,"retrievalRecord"); } @@ -149,25 +149,25 @@ public class ImportingJob { /** * TO check if the file record is a metadata file entry * @param fileRecordObject - * @return JSONObject + * @return ObjectNode */ - public boolean isMetadataFileRecord(JSONObject fileRecordObject) { + public boolean isMetadataFileRecord(ObjectNode fileRecordObject) { return fileRecordObject.has("metaDataFormat"); } @JsonIgnore - public List getSelectedFileRecords() { - List results = new ArrayList(); + public List getSelectedFileRecords() { + List results = new ArrayList(); - JSONObject retrievalRecord = JSONUtilities.getObject(config,"retrievalRecord"); + ObjectNode retrievalRecord = JSONUtilities.getObject(config,"retrievalRecord"); if (retrievalRecord != null) { - JSONArray fileRecordArray = JSONUtilities.getArray(retrievalRecord, "files"); + ArrayNode fileRecordArray = JSONUtilities.getArray(retrievalRecord, "files"); if (fileRecordArray != null) { - JSONArray fileSelectionArray = JSONUtilities.getArray(config,"fileSelection"); + ArrayNode fileSelectionArray = JSONUtilities.getArray(config,"fileSelection"); if (fileSelectionArray != null) { - for (int i = 0; i < fileSelectionArray.length(); i++) { + for (int i = 0; i < fileSelectionArray.size(); i++) { int index = JSONUtilities.getIntElement(fileSelectionArray, i, -1); - if (index >= 0 && index < fileRecordArray.length()) { + if (index >= 0 && index < fileRecordArray.size()) { results.add(JSONUtilities.getObjectElement(fileRecordArray, index)); } } diff --git a/main/src/com/google/refine/importing/ImportingManager.java b/main/src/com/google/refine/importing/ImportingManager.java index ec29caacd..02425cdc7 100644 --- a/main/src/com/google/refine/importing/ImportingManager.java +++ b/main/src/com/google/refine/importing/ImportingManager.java @@ -54,7 +54,6 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.RefineServlet; import edu.mit.simile.butterfly.ButterflyModule; diff --git a/main/src/com/google/refine/importing/ImportingParser.java b/main/src/com/google/refine/importing/ImportingParser.java index faafe4b3c..8d0b97295 100644 --- a/main/src/com/google/refine/importing/ImportingParser.java +++ b/main/src/com/google/refine/importing/ImportingParser.java @@ -35,8 +35,7 @@ package com.google.refine.importing; import java.util.List; -import org.json.JSONObject; - +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.model.Project; import com.google.refine.model.metadata.ProjectMetadata; @@ -49,11 +48,11 @@ public interface ImportingParser { * @param job * @param fileRecords * @param format - * @return JSONObject options + * @return ObjectNode options */ - public JSONObject createParserUIInitializationData( + public ObjectNode createParserUIInitializationData( ImportingJob job, - List fileRecords, + List fileRecords, String format ); @@ -77,10 +76,10 @@ public interface ImportingParser { Project project, ProjectMetadata metadata, ImportingJob job, - List fileRecords, + List fileRecords, String format, int limit, - JSONObject options, + ObjectNode options, List exceptions ); } diff --git a/main/src/com/google/refine/importing/ImportingUtilities.java b/main/src/com/google/refine/importing/ImportingUtilities.java index 375778019..067d1168b 100644 --- a/main/src/com/google/refine/importing/ImportingUtilities.java +++ b/main/src/com/google/refine/importing/ImportingUtilities.java @@ -83,11 +83,12 @@ import org.apache.http.util.EntityUtils; import org.apache.tools.bzip2.CBZip2InputStream; import org.apache.tools.tar.TarEntry; import org.apache.tools.tar.TarInputStream; -import org.json.JSONArray; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.ProjectManager; import com.google.refine.RefineServlet; import com.google.refine.importing.ImportingManager.Format; @@ -105,6 +106,7 @@ import com.google.refine.model.metadata.PackageExtension; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.preference.PreferenceStore; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; import io.frictionlessdata.datapackage.Package; import io.frictionlessdata.tableschema.Field; @@ -129,13 +131,13 @@ public class ImportingUtilities { HttpServletResponse response, Properties parameters, final ImportingJob job, - JSONObject config) throws IOException, ServletException { + ObjectNode config) throws IOException, ServletException { - JSONObject retrievalRecord = new JSONObject(); + ObjectNode retrievalRecord = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(config, "retrievalRecord", retrievalRecord); JSONUtilities.safePut(config, "state", "loading-raw-data"); - final JSONObject progress = new JSONObject(); + final ObjectNode progress = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(config, "progress", progress); try { ImportingUtilities.retrieveContentFromPostRequest( @@ -164,13 +166,13 @@ public class ImportingUtilities { return; } - JSONArray fileSelectionIndexes = new JSONArray(); + ArrayNode fileSelectionIndexes = ParsingUtilities.mapper.createArrayNode(); JSONUtilities.safePut(config, "fileSelection", fileSelectionIndexes); String bestFormat = ImportingUtilities.autoSelectFiles(job, retrievalRecord, fileSelectionIndexes); bestFormat = ImportingUtilities.guessBetterFormat(job, bestFormat); - JSONArray rankedFormats = new JSONArray(); + ArrayNode rankedFormats = ParsingUtilities.mapper.createArrayNode(); ImportingUtilities.rankFormats(job, bestFormat, rankedFormats); JSONUtilities.safePut(config, "rankedFormats", rankedFormats); @@ -179,13 +181,13 @@ public class ImportingUtilities { config.remove("progress"); } - static public void updateJobWithNewFileSelection(ImportingJob job, JSONArray fileSelectionArray) { + static public void updateJobWithNewFileSelection(ImportingJob job, ArrayNode fileSelectionArray) { job.setFileSelection(fileSelectionArray); String bestFormat = ImportingUtilities.getCommonFormatForSelectedFiles(job, fileSelectionArray); bestFormat = ImportingUtilities.guessBetterFormat(job, bestFormat); - JSONArray rankedFormats = new JSONArray(); + ArrayNode rankedFormats = ParsingUtilities.mapper.createArrayNode(); ImportingUtilities.rankFormats(job, bestFormat, rankedFormats); job.setRankedFormats(rankedFormats); } @@ -194,10 +196,10 @@ public class ImportingUtilities { HttpServletRequest request, Properties parameters, File rawDataDir, - JSONObject retrievalRecord, + ObjectNode retrievalRecord, final Progress progress ) throws Exception { - JSONArray fileRecords = new JSONArray(); + ArrayNode fileRecords = ParsingUtilities.mapper.createArrayNode(); JSONUtilities.safePut(retrievalRecord, "files", fileRecords); JSONUtilities.safePut(retrievalRecord, "downloadCount", 0); JSONUtilities.safePut(retrievalRecord, "archiveCount", 0); @@ -264,7 +266,7 @@ public class ImportingUtilities { File file = allocateFile(rawDataDir, "clipboard.txt"); - JSONObject fileRecord = new JSONObject(); + ObjectNode fileRecord = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(fileRecord, "origin", "clipboard"); JSONUtilities.safePut(fileRecord, "declaredEncoding", encoding); JSONUtilities.safePut(fileRecord, "declaredMimeType", (String) null); @@ -310,7 +312,7 @@ public class ImportingUtilities { File file = allocateFile(rawDataDir, fileName); - JSONObject fileRecord = new JSONObject(); + ObjectNode fileRecord = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(fileRecord, "origin", "upload"); JSONUtilities.safePut(fileRecord, "declaredEncoding", request.getCharacterEncoding()); JSONUtilities.safePut(fileRecord, "declaredMimeType", fileItem.getContentType()); @@ -344,19 +346,19 @@ public class ImportingUtilities { JSONUtilities.safePut(retrievalRecord, "clipboardCount", clipboardCount); } - private static void processDataPackage(JSONObject retrievalRecord, JSONArray fileRecords) { + private static void processDataPackage(ObjectNode retrievalRecord, ArrayNode fileRecords) { int dataPackageJSONFileIndex = getDataPackageJSONFile(fileRecords); if (dataPackageJSONFileIndex >= 0) { - JSONObject dataPackageJSONFile = (JSONObject) fileRecords.get(dataPackageJSONFileIndex); + ObjectNode dataPackageJSONFile = (ObjectNode) fileRecords.get(dataPackageJSONFileIndex); JSONUtilities.safePut(dataPackageJSONFile, "metaDataFormat", MetadataFormat.DATAPACKAGE_METADATA.name()); JSONUtilities.safePut(retrievalRecord, METADATA_FILE_KEY, dataPackageJSONFile); fileRecords.remove(dataPackageJSONFileIndex); } } - private static int getDataPackageJSONFile(JSONArray fileRecords) { - for (int i = 0; i < fileRecords.length(); i++) { - JSONObject file = fileRecords.getJSONObject(i); + private static int getDataPackageJSONFile(ArrayNode fileRecords) { + for (int i = 0; i < fileRecords.size(); i++) { + ObjectNode file = JSONUtilities.getObjectElement(fileRecords, i); if (file.has("archiveFileName") && file.has("fileName") && file.get("fileName").equals(DataPackageMetadata.DEFAULT_FILE_NAME)) { @@ -366,8 +368,8 @@ public class ImportingUtilities { return -1; } - private static void download(File rawDataDir, JSONObject retrievalRecord, final Progress progress, - JSONArray fileRecords, final SavingUpdate update, String urlString) + private static void download(File rawDataDir, ObjectNode retrievalRecord, final Progress progress, + ArrayNode fileRecords, final SavingUpdate update, String urlString) throws URISyntaxException, IOException, ClientProtocolException, Exception { download(rawDataDir, retrievalRecord, progress, fileRecords, update, urlString, null); } @@ -384,11 +386,11 @@ public class ImportingUtilities { * @throws ClientProtocolException * @throws Exception */ - private static void download(File rawDataDir, JSONObject retrievalRecord, final Progress progress, - JSONArray fileRecords, final SavingUpdate update, String urlString, String metaDataFormat) + private static void download(File rawDataDir, ObjectNode retrievalRecord, final Progress progress, + ArrayNode fileRecords, final SavingUpdate update, String urlString, String metaDataFormat) throws URISyntaxException, IOException, ClientProtocolException, Exception { URL url = new URL(urlString); - JSONObject fileRecord = new JSONObject(); + ObjectNode fileRecord = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(fileRecord, "origin", "download"); JSONUtilities.safePut(fileRecord, "url", urlString); @@ -482,7 +484,7 @@ public class ImportingUtilities { } private static boolean saveStream(InputStream stream, URL url, File rawDataDir, final Progress progress, - final SavingUpdate update, JSONObject fileRecord, JSONArray fileRecords, long length) + final SavingUpdate update, ObjectNode fileRecord, ArrayNode fileRecords, long length) throws IOException, Exception { String localname = url.getPath(); if (localname.isEmpty() || localname.endsWith("/")) { @@ -538,17 +540,17 @@ public class ImportingUtilities { return file; } - static public Reader getFileReader(ImportingJob job, JSONObject fileRecord, String commonEncoding) + static public Reader getFileReader(ImportingJob job, ObjectNode fileRecord, String commonEncoding) throws FileNotFoundException { return getFileReader(getFile(job, JSONUtilities.getString(fileRecord, "location", "")), fileRecord, commonEncoding); } - static public Reader getFileReader(File file, JSONObject fileRecord, String commonEncoding) throws FileNotFoundException { + static public Reader getFileReader(File file, ObjectNode fileRecord, String commonEncoding) throws FileNotFoundException { return getReaderFromStream(new FileInputStream(file), fileRecord, commonEncoding); } - static public Reader getReaderFromStream(InputStream inputStream, JSONObject fileRecord, String commonEncoding) { + static public Reader getReaderFromStream(InputStream inputStream, ObjectNode fileRecord, String commonEncoding) { String encoding = getEncoding(fileRecord); if (encoding == null) { encoding = commonEncoding; @@ -563,7 +565,7 @@ public class ImportingUtilities { return new InputStreamReader(inputStream); } - static public File getFile(ImportingJob job, JSONObject fileRecord) { + static public File getFile(ImportingJob job, ObjectNode fileRecord) { return getFile(job, JSONUtilities.getString(fileRecord, "location", "")); } @@ -571,7 +573,7 @@ public class ImportingUtilities { return new File(job.getRawDataDir(), location); } - static public String getFileSource(JSONObject fileRecord) { + static public String getFileSource(ObjectNode fileRecord) { return JSONUtilities.getString( fileRecord, "url", @@ -608,7 +610,7 @@ public class ImportingUtilities { } static public boolean postProcessRetrievedFile( - File rawDataDir, File file, JSONObject fileRecord, JSONArray fileRecords, final Progress progress) { + File rawDataDir, File file, ObjectNode fileRecord, ArrayNode fileRecords, final Progress progress) { String mimeType = JSONUtilities.getString(fileRecord, "declaredMimeType", null); String contentEncoding = JSONUtilities.getString(fileRecord, "declaredEncoding", null); @@ -654,7 +656,7 @@ public class ImportingUtilities { return false; } - static public void postProcessSingleRetrievedFile(File file, JSONObject fileRecord) { + static public void postProcessSingleRetrievedFile(File file, ObjectNode fileRecord) { if (!fileRecord.has("format")) { JSONUtilities.safePut(fileRecord, "format", ImportingManager.getFormat( @@ -693,8 +695,8 @@ public class ImportingUtilities { static public boolean explodeArchive( File rawDataDir, InputStream archiveIS, - JSONObject archiveFileRecord, - JSONArray fileRecords, + ObjectNode archiveFileRecord, + ArrayNode fileRecords, final Progress progress ) { if (archiveIS instanceof TarInputStream) { @@ -708,7 +710,7 @@ public class ImportingUtilities { progress.setProgress("Extracting " + fileName2, -1); - JSONObject fileRecord2 = new JSONObject(); + ObjectNode fileRecord2 = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(fileRecord2, "origin", JSONUtilities.getString(archiveFileRecord, "origin", null)); JSONUtilities.safePut(fileRecord2, "declaredEncoding", (String) null); JSONUtilities.safePut(fileRecord2, "declaredMimeType", (String) null); @@ -738,7 +740,7 @@ public class ImportingUtilities { progress.setProgress("Extracting " + fileName2, -1); - JSONObject fileRecord2 = new JSONObject(); + ObjectNode fileRecord2 = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(fileRecord2, "origin", JSONUtilities.getString(archiveFileRecord, "origin", null)); JSONUtilities.safePut(fileRecord2, "declaredEncoding", (String) null); JSONUtilities.safePut(fileRecord2, "declaredMimeType", (String) null); @@ -792,7 +794,7 @@ public class ImportingUtilities { static public File uncompressFile( File rawDataDir, InputStream uncompressedIS, - JSONObject fileRecord, + ObjectNode fileRecord, final Progress progress ) throws IOException { String fileName = JSONUtilities.getString(fileRecord, "location", "unknown"); @@ -823,10 +825,10 @@ public class ImportingUtilities { return NumberFormat.getIntegerInstance().format(bytes); } - static public String getEncoding(JSONObject fileRecord) { - String encoding = JSONUtilities.getString(fileRecord, "encoding", null); + static public String getEncoding(ObjectNode firstFileRecord) { + String encoding = JSONUtilities.getString(firstFileRecord, "encoding", null); if (encoding == null || encoding.isEmpty()) { - encoding = JSONUtilities.getString(fileRecord, "declaredEncoding", null); + encoding = JSONUtilities.getString(firstFileRecord, "declaredEncoding", null); } return encoding; } @@ -840,14 +842,14 @@ public class ImportingUtilities { * @param fileSelectionIndexes JSON array of selected file indices matching best format * @return best (highest frequency) format */ - static public String autoSelectFiles(ImportingJob job, JSONObject retrievalRecord, JSONArray fileSelectionIndexes) { + static public String autoSelectFiles(ImportingJob job, ObjectNode retrievalRecord, ArrayNode fileSelectionIndexes) { final Map formatToCount = new HashMap(); List formats = new ArrayList(); - JSONArray fileRecords = JSONUtilities.getArray(retrievalRecord, "files"); - int count = fileRecords.length(); + ArrayNode fileRecords = JSONUtilities.getArray(retrievalRecord, "files"); + int count = fileRecords.size(); for (int i = 0; i < count; i++) { - JSONObject fileRecord = JSONUtilities.getObjectElement(fileRecords, i); + ObjectNode fileRecord = JSONUtilities.getObjectElement(fileRecords, i); String format = JSONUtilities.getString(fileRecord, "format", null); if (format != null) { if (formatToCount.containsKey(format)) { @@ -875,7 +877,7 @@ public class ImportingUtilities { } else { // Otherwise, select files matching the best format for (int i = 0; i < count; i++) { - JSONObject fileRecord = JSONUtilities.getObjectElement(fileRecords, i); + ObjectNode fileRecord = JSONUtilities.getObjectElement(fileRecords, i); String format = JSONUtilities.getString(fileRecord, "format", null); if (format != null && format.equals(bestFormat)) { JSONUtilities.append(fileSelectionIndexes, i); @@ -884,7 +886,7 @@ public class ImportingUtilities { // If nothing matches the best format but we have some files, // then select them all - if (fileSelectionIndexes.length() == 0 && count > 0) { + if (fileSelectionIndexes.size() == 0 && count > 0) { for (int i = 0; i < count; i++) { JSONUtilities.append(fileSelectionIndexes, i); } @@ -893,18 +895,18 @@ public class ImportingUtilities { return bestFormat; } - static public String getCommonFormatForSelectedFiles(ImportingJob job, JSONArray fileSelectionIndexes) { - JSONObject retrievalRecord = job.getRetrievalRecord(); + static public String getCommonFormatForSelectedFiles(ImportingJob job, ArrayNode fileSelectionIndexes) { + ObjectNode retrievalRecord = job.getRetrievalRecord(); final Map formatToCount = new HashMap(); List formats = new ArrayList(); - JSONArray fileRecords = JSONUtilities.getArray(retrievalRecord, "files"); - int count = fileSelectionIndexes.length(); + ArrayNode fileRecords = JSONUtilities.getArray(retrievalRecord, "files"); + int count = fileSelectionIndexes.size(); for (int i = 0; i < count; i++) { int index = JSONUtilities.getIntElement(fileSelectionIndexes, i, -1); - if (index >= 0 && index < fileRecords.length()) { - JSONObject fileRecord = JSONUtilities.getObjectElement(fileRecords, index); + if (index >= 0 && index < fileRecords.size()) { + ObjectNode fileRecord = JSONUtilities.getObjectElement(fileRecords, index); String format = JSONUtilities.getString(fileRecord, "format", null); if (format != null) { if (formatToCount.containsKey(format)) { @@ -927,18 +929,18 @@ public class ImportingUtilities { } static String guessBetterFormat(ImportingJob job, String bestFormat) { - JSONObject retrievalRecord = job.getRetrievalRecord(); + ObjectNode retrievalRecord = job.getRetrievalRecord(); return retrievalRecord != null ? guessBetterFormat(job, retrievalRecord, bestFormat) : bestFormat; } - static String guessBetterFormat(ImportingJob job, JSONObject retrievalRecord, String bestFormat) { - JSONArray fileRecords = JSONUtilities.getArray(retrievalRecord, "files"); + static String guessBetterFormat(ImportingJob job, ObjectNode retrievalRecord, String bestFormat) { + ArrayNode fileRecords = JSONUtilities.getArray(retrievalRecord, "files"); return fileRecords != null ? guessBetterFormat(job, fileRecords, bestFormat) : bestFormat; } - static String guessBetterFormat(ImportingJob job, JSONArray fileRecords, String bestFormat) { - if (bestFormat != null && fileRecords != null && fileRecords.length() > 0) { - JSONObject firstFileRecord = JSONUtilities.getObjectElement(fileRecords, 0); + static String guessBetterFormat(ImportingJob job, ArrayNode fileRecords, String bestFormat) { + if (bestFormat != null && fileRecords != null && fileRecords.size() > 0) { + ObjectNode firstFileRecord = JSONUtilities.getObjectElement(fileRecords, 0); String encoding = getEncoding(firstFileRecord); String location = JSONUtilities.getString(firstFileRecord, "location", null); @@ -969,7 +971,7 @@ public class ImportingUtilities { return bestFormat; } - static void rankFormats(ImportingJob job, final String bestFormat, JSONArray rankedFormats) { + static void rankFormats(ImportingJob job, final String bestFormat, ArrayNode rankedFormats) { final Map formatToSegments = new HashMap(); boolean download = bestFormat == null ? true : @@ -1023,12 +1025,12 @@ public class ImportingUtilities { } for (String format : formats) { - JSONUtilities.append(rankedFormats, format); + rankedFormats.add(format); } } - static public void previewParse(ImportingJob job, String format, JSONObject optionObj, List exceptions) { + static public void previewParse(ImportingJob job, String format, ObjectNode optionObj, List exceptions) { Format record = ImportingManager.formatToRecord.get(format); if (record == null || record.parser == null) { // TODO: what to do? @@ -1054,7 +1056,7 @@ public class ImportingUtilities { static public long createProject( final ImportingJob job, final String format, - final JSONObject optionObj, + final ObjectNode optionObj, final List exceptions, boolean synchronous) { final Format record = ImportingManager.formatToRecord.get(format); @@ -1084,7 +1086,7 @@ public class ImportingUtilities { static private void createProjectSynchronously( final ImportingJob job, final String format, - final JSONObject optionObj, + final ObjectNode optionObj, final List exceptions, final Format record, final Project project @@ -1105,15 +1107,15 @@ public class ImportingUtilities { if (exceptions.size() == 0) { project.update(); // update all internal models, indexes, caches, etc. - boolean hasMetadataFileRecord = ((JSONObject)job.getRetrievalRecord()).has(METADATA_FILE_KEY); + boolean hasMetadataFileRecord = ((ObjectNode)job.getRetrievalRecord()).has(METADATA_FILE_KEY); if (hasMetadataFileRecord) { - JSONObject metadataFileRecord = (JSONObject) job.getRetrievalRecord().get(METADATA_FILE_KEY); + ObjectNode metadataFileRecord = (ObjectNode) job.getRetrievalRecord().get(METADATA_FILE_KEY); - String metadataFormat = (String)metadataFileRecord.get("metaDataFormat"); + String metadataFormat = JSONUtilities.getString(metadataFileRecord, "metaDataFormat", null); IMetadata metadata = MetadataFactory.buildMetadata(MetadataFormat.valueOf(metadataFormat)); - String relativePath = metadataFileRecord.getString("location"); + String relativePath = JSONUtilities.getString(metadataFileRecord, "location", null); File metadataFile = new File(job.getRawDataDir(), relativePath); metadata.loadFromFile(metadataFile); @@ -1159,10 +1161,10 @@ public class ImportingUtilities { } try { - JSONObject fieldsJSON = TypeInferrer.getInstance().infer(listCells, + ObjectNode fieldsJSON = JSONUtilities.jsonObjectToObjectNode(TypeInferrer.getInstance().infer(listCells, project.columnModel.getColumnNames().toArray(new String[0]), - 100); - populateColumnTypes(project.columnModel, fieldsJSON.getJSONArray(Schema.JSON_KEY_FIELDS)); + 100)); + populateColumnTypes(project.columnModel, JSONUtilities.getArray(fieldsJSON, Schema.JSON_KEY_FIELDS)); } catch (TypeInferringException e) { logger.error("infer column type exception.", ExceptionUtils.getStackTrace(e)); } @@ -1171,7 +1173,7 @@ public class ImportingUtilities { private static void populateDataPackageMetadata(Project project, ProjectMetadata pmd, DataPackageMetadata metadata) { // project metadata - JSONObject pkg = metadata.getPackage().getJson(); + ObjectNode pkg = JSONUtilities.jsonObjectToObjectNode(metadata.getPackage().getJson()); pmd.setName(getDataPackageProperty(pkg, Package.JSON_KEY_NAME)); pmd.setDescription(getDataPackageProperty(pkg, PackageExtension.JSON_KEY_DESCRIPTION)); @@ -1182,18 +1184,18 @@ public class ImportingUtilities { pmd.setVersion(getDataPackageProperty(pkg, PackageExtension.JSON_KEY_VERSION)); if (pkg.has(PackageExtension.JSON_KEY_KEYWORKS)) { - String[] tags = pkg.getJSONArray(PackageExtension.JSON_KEY_KEYWORKS).toList().toArray(new String[0]); + String[] tags = JSONUtilities.getStringArray(pkg, PackageExtension.JSON_KEY_KEYWORKS); pmd.appendTags(tags); } // column model - JSONObject schema = metadata.getPackage().getResources().get(0).getSchema(); + ObjectNode schema = JSONUtilities.jsonObjectToObjectNode(metadata.getPackage().getResources().get(0).getSchema()); if (schema != null) { - populateColumnTypes(project.columnModel, schema.getJSONArray(Schema.JSON_KEY_FIELDS)); + populateColumnTypes(project.columnModel, JSONUtilities.getArray(schema, Schema.JSON_KEY_FIELDS)); } } - private static String getDataPackageProperty(JSONObject pkg, String key) { + private static String getDataPackageProperty(ObjectNode pkg, String key) { return JSONUtilities.getString(pkg, key, StringUtils.EMPTY); } /** @@ -1201,12 +1203,12 @@ public class ImportingUtilities { * @param columnModel * @param fieldsJSON */ - private static void populateColumnTypes(ColumnModel columnModel, JSONArray fieldsJSON) { + private static void populateColumnTypes(ColumnModel columnModel, ArrayNode fieldsJSON) { int cellIndex = 0; - Iterator iter = fieldsJSON.iterator(); + Iterator iter = fieldsJSON.iterator(); while(iter.hasNext()){ - JSONObject fieldJsonObj = (JSONObject)iter.next(); - Field field = new Field(fieldJsonObj); + ObjectNode fieldJsonObj = (ObjectNode)iter.next(); + Field field = new Field(JSONUtilities.objectNodeToJsonNode(fieldJsonObj)); Column column = columnModel.getColumnByCellIndex(cellIndex); column.setType(field.getType()); @@ -1224,7 +1226,7 @@ public class ImportingUtilities { * @param optionObj * @return */ - static public ProjectMetadata createProjectMetadata(JSONObject optionObj) { + static public ProjectMetadata createProjectMetadata(ObjectNode optionObj) { ProjectMetadata pm = new ProjectMetadata(); PreferenceStore ps = ProjectManager.singleton.getPreferenceStore(); diff --git a/main/src/com/google/refine/io/FileProjectManager.java b/main/src/com/google/refine/io/FileProjectManager.java index fc93e0ca6..46875e02a 100644 --- a/main/src/com/google/refine/io/FileProjectManager.java +++ b/main/src/com/google/refine/io/FileProjectManager.java @@ -59,7 +59,6 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.ProjectManager; import com.google.refine.history.HistoryEntryManager; import com.google.refine.model.Project; diff --git a/main/src/com/google/refine/model/AbstractOperation.java b/main/src/com/google/refine/model/AbstractOperation.java index 6ab8135c3..cec470d81 100644 --- a/main/src/com/google/refine/model/AbstractOperation.java +++ b/main/src/com/google/refine/model/AbstractOperation.java @@ -38,7 +38,6 @@ import java.util.Properties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver; - import com.google.refine.history.HistoryEntry; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.OperationResolver; diff --git a/main/src/com/google/refine/model/Cell.java b/main/src/com/google/refine/model/Cell.java index 61394c809..d6767ff50 100644 --- a/main/src/com/google/refine/model/Cell.java +++ b/main/src/com/google/refine/model/Cell.java @@ -49,7 +49,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.InjectableValues; - import com.google.refine.expr.EvalError; import com.google.refine.expr.ExpressionUtils; import com.google.refine.expr.HasFields; diff --git a/main/src/com/google/refine/model/Column.java b/main/src/com/google/refine/model/Column.java index 29f0d52e0..f92d64598 100644 --- a/main/src/com/google/refine/model/Column.java +++ b/main/src/com/google/refine/model/Column.java @@ -46,7 +46,6 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; - import com.google.refine.InterProjectModel; import com.google.refine.model.recon.ReconConfig; import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/model/ColumnGroup.java b/main/src/com/google/refine/model/ColumnGroup.java index c6059d4e9..45e18b152 100644 --- a/main/src/com/google/refine/model/ColumnGroup.java +++ b/main/src/com/google/refine/model/ColumnGroup.java @@ -43,7 +43,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonView; - import com.google.refine.util.JsonViews; import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/model/Recon.java b/main/src/com/google/refine/model/Recon.java index caa1373e6..bf549e06b 100644 --- a/main/src/com/google/refine/model/Recon.java +++ b/main/src/com/google/refine/model/Recon.java @@ -46,7 +46,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonView; - import com.google.refine.expr.HasFields; import com.google.refine.util.JsonViews; import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/model/ReconCandidate.java b/main/src/com/google/refine/model/ReconCandidate.java index 6e2a1e3da..65d8c698a 100644 --- a/main/src/com/google/refine/model/ReconCandidate.java +++ b/main/src/com/google/refine/model/ReconCandidate.java @@ -41,7 +41,6 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; - import com.google.refine.expr.HasFields; import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/model/ReconStats.java b/main/src/com/google/refine/model/ReconStats.java index 89650c791..00bcbcd1a 100644 --- a/main/src/com/google/refine/model/ReconStats.java +++ b/main/src/com/google/refine/model/ReconStats.java @@ -38,7 +38,6 @@ import java.io.Writer; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.expr.ExpressionUtils; import com.google.refine.model.Recon.Judgment; import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/model/ReconType.java b/main/src/com/google/refine/model/ReconType.java index 65a6d34e9..2634bd6f0 100644 --- a/main/src/com/google/refine/model/ReconType.java +++ b/main/src/com/google/refine/model/ReconType.java @@ -37,7 +37,6 @@ import java.io.IOException; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/model/RecordModel.java b/main/src/com/google/refine/model/RecordModel.java index fe9ccae13..843922241 100644 --- a/main/src/com/google/refine/model/RecordModel.java +++ b/main/src/com/google/refine/model/RecordModel.java @@ -44,7 +44,6 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.expr.ExpressionUtils; public class RecordModel { diff --git a/main/src/com/google/refine/model/Row.java b/main/src/com/google/refine/model/Row.java index 3e161f3f7..9e0339174 100644 --- a/main/src/com/google/refine/model/Row.java +++ b/main/src/com/google/refine/model/Row.java @@ -43,7 +43,6 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.InjectableValues; - import com.google.refine.expr.CellTuple; import com.google.refine.expr.HasFields; import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/model/changes/MassChange.java b/main/src/com/google/refine/model/changes/MassChange.java index efb6feb81..1f9f9dab1 100644 --- a/main/src/com/google/refine/model/changes/MassChange.java +++ b/main/src/com/google/refine/model/changes/MassChange.java @@ -41,7 +41,6 @@ import java.util.List; import java.util.Properties; import com.google.common.collect.Lists; - import com.google.refine.history.Change; import com.google.refine.history.History; import com.google.refine.model.Project; diff --git a/main/src/com/google/refine/model/metadata/ProjectMetadata.java b/main/src/com/google/refine/model/metadata/ProjectMetadata.java index 6ccd26fee..23dc2f253 100644 --- a/main/src/com/google/refine/model/metadata/ProjectMetadata.java +++ b/main/src/com/google/refine/model/metadata/ProjectMetadata.java @@ -63,7 +63,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.annotation.JsonView; - +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.ProjectManager; import com.google.refine.preference.PreferenceStore; import com.google.refine.preference.TopList; @@ -362,8 +362,8 @@ public class ProjectMetadata extends AbstractMetadata { updateModified(); } - public void appendImportOptionMetadata(JSONObject obj) { - _importOptionMetadata.put(obj); + public void appendImportOptionMetadata(ObjectNode options) { + _importOptionMetadata.put(options); updateModified(); } diff --git a/main/src/com/google/refine/model/recon/ReconConfig.java b/main/src/com/google/refine/model/recon/ReconConfig.java index aa3459a89..bf2ebc063 100644 --- a/main/src/com/google/refine/model/recon/ReconConfig.java +++ b/main/src/com/google/refine/model/recon/ReconConfig.java @@ -46,7 +46,6 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver; - import com.google.refine.model.Cell; import com.google.refine.model.Project; import com.google.refine.model.Recon; diff --git a/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java b/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java index 13a630e5c..4f0196110 100644 --- a/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java +++ b/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java @@ -60,7 +60,6 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.databind.ObjectMapper; - import com.google.refine.expr.functions.ToDate; import com.google.refine.model.ReconCandidate; import com.google.refine.model.ReconType; diff --git a/main/src/com/google/refine/model/recon/StandardReconConfig.java b/main/src/com/google/refine/model/recon/StandardReconConfig.java index a8b568feb..78cda9334 100644 --- a/main/src/com/google/refine/model/recon/StandardReconConfig.java +++ b/main/src/com/google/refine/model/recon/StandardReconConfig.java @@ -60,7 +60,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; - import com.google.refine.expr.ExpressionUtils; import com.google.refine.model.Cell; import com.google.refine.model.Project; diff --git a/main/src/com/google/refine/operations/EngineDependentMassCellOperation.java b/main/src/com/google/refine/operations/EngineDependentMassCellOperation.java index daf02378e..c829e7ccd 100644 --- a/main/src/com/google/refine/operations/EngineDependentMassCellOperation.java +++ b/main/src/com/google/refine/operations/EngineDependentMassCellOperation.java @@ -38,7 +38,6 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; diff --git a/main/src/com/google/refine/operations/EngineDependentOperation.java b/main/src/com/google/refine/operations/EngineDependentOperation.java index 3cf969164..b5cbca25c 100644 --- a/main/src/com/google/refine/operations/EngineDependentOperation.java +++ b/main/src/com/google/refine/operations/EngineDependentOperation.java @@ -34,7 +34,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.model.AbstractOperation; diff --git a/main/src/com/google/refine/operations/OperationRegistry.java b/main/src/com/google/refine/operations/OperationRegistry.java index 3a352917e..d2f6393a6 100644 --- a/main/src/com/google/refine/operations/OperationRegistry.java +++ b/main/src/com/google/refine/operations/OperationRegistry.java @@ -33,21 +33,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations; -import java.io.IOException; -import java.lang.reflect.Method; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; -import org.json.JSONObject; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; - import com.google.refine.model.AbstractOperation; -import com.google.refine.model.Project; -import com.google.refine.util.ParsingUtilities; import edu.mit.simile.butterfly.ButterflyModule; diff --git a/main/src/com/google/refine/operations/OperationResolver.java b/main/src/com/google/refine/operations/OperationResolver.java index 5f8085e48..343e910b8 100644 --- a/main/src/com/google/refine/operations/OperationResolver.java +++ b/main/src/com/google/refine/operations/OperationResolver.java @@ -7,7 +7,6 @@ import com.fasterxml.jackson.databind.DatabindContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase; import com.fasterxml.jackson.databind.type.TypeFactory; - import com.google.refine.model.AbstractOperation; public class OperationResolver extends TypeIdResolverBase { diff --git a/main/src/com/google/refine/operations/cell/BlankDownOperation.java b/main/src/com/google/refine/operations/cell/BlankDownOperation.java index f022f28af..9d4a7d96b 100644 --- a/main/src/com/google/refine/operations/cell/BlankDownOperation.java +++ b/main/src/com/google/refine/operations/cell/BlankDownOperation.java @@ -37,7 +37,6 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; diff --git a/main/src/com/google/refine/operations/cell/FillDownOperation.java b/main/src/com/google/refine/operations/cell/FillDownOperation.java index b3a47ca60..1de411e10 100644 --- a/main/src/com/google/refine/operations/cell/FillDownOperation.java +++ b/main/src/com/google/refine/operations/cell/FillDownOperation.java @@ -37,7 +37,6 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.EngineConfig; diff --git a/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java b/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java index bc04f38d9..96987a5bc 100644 --- a/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java +++ b/main/src/com/google/refine/operations/cell/KeyValueColumnizeOperation.java @@ -40,7 +40,6 @@ import java.util.Map; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.expr.ExpressionUtils; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; diff --git a/main/src/com/google/refine/operations/cell/MassEditOperation.java b/main/src/com/google/refine/operations/cell/MassEditOperation.java index 593912b42..6d8a473e5 100644 --- a/main/src/com/google/refine/operations/cell/MassEditOperation.java +++ b/main/src/com/google/refine/operations/cell/MassEditOperation.java @@ -42,7 +42,6 @@ import java.util.Properties; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.expr.Evaluable; diff --git a/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java b/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java index 88ef3aeff..5bf16bc61 100644 --- a/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java +++ b/main/src/com/google/refine/operations/cell/MultiValuedCellJoinOperation.java @@ -38,7 +38,6 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.expr.ExpressionUtils; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; diff --git a/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java b/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java index fbb3a9006..658f5096d 100644 --- a/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java +++ b/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java @@ -43,7 +43,6 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; diff --git a/main/src/com/google/refine/operations/cell/TextTransformOperation.java b/main/src/com/google/refine/operations/cell/TextTransformOperation.java index bdedef2cc..1a043f2a7 100644 --- a/main/src/com/google/refine/operations/cell/TextTransformOperation.java +++ b/main/src/com/google/refine/operations/cell/TextTransformOperation.java @@ -39,7 +39,6 @@ import java.util.Properties; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.expr.Evaluable; diff --git a/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java b/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java index c9e416d76..0697dc9da 100644 --- a/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java +++ b/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java @@ -41,7 +41,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; diff --git a/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java b/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java index bcfa612a1..6feaa6197 100644 --- a/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java +++ b/main/src/com/google/refine/operations/cell/TransposeRowsIntoColumnsOperation.java @@ -38,7 +38,6 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; diff --git a/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java b/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java index 4e920f435..4251235e5 100644 --- a/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnAdditionByFetchingURLsOperation.java @@ -49,11 +49,9 @@ import org.json.JSONException; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; diff --git a/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java b/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java index 6e58835e5..377fa4ad8 100644 --- a/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnAdditionOperation.java @@ -40,7 +40,6 @@ import java.util.Properties; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; diff --git a/main/src/com/google/refine/operations/column/ColumnMoveOperation.java b/main/src/com/google/refine/operations/column/ColumnMoveOperation.java index fd0842f53..bc19ffc06 100644 --- a/main/src/com/google/refine/operations/column/ColumnMoveOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnMoveOperation.java @@ -35,7 +35,6 @@ package com.google.refine.operations.column; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.history.Change; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; diff --git a/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java b/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java index 7449345bc..0d38ebfd1 100644 --- a/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnRemovalOperation.java @@ -35,7 +35,6 @@ package com.google.refine.operations.column; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.history.Change; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; diff --git a/main/src/com/google/refine/operations/column/ColumnRenameOperation.java b/main/src/com/google/refine/operations/column/ColumnRenameOperation.java index 6359d6324..1b843fe6f 100644 --- a/main/src/com/google/refine/operations/column/ColumnRenameOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnRenameOperation.java @@ -34,7 +34,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.operations.column; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.history.Change; import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; diff --git a/main/src/com/google/refine/operations/column/ColumnReorderOperation.java b/main/src/com/google/refine/operations/column/ColumnReorderOperation.java index 032a8f7b9..d45787f87 100644 --- a/main/src/com/google/refine/operations/column/ColumnReorderOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnReorderOperation.java @@ -37,7 +37,6 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; diff --git a/main/src/com/google/refine/operations/column/ColumnSplitOperation.java b/main/src/com/google/refine/operations/column/ColumnSplitOperation.java index 6f55b7a47..77852088f 100644 --- a/main/src/com/google/refine/operations/column/ColumnSplitOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnSplitOperation.java @@ -44,7 +44,6 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; diff --git a/main/src/com/google/refine/operations/recon/ExtendDataOperation.java b/main/src/com/google/refine/operations/recon/ExtendDataOperation.java index adcd26861..670adda23 100644 --- a/main/src/com/google/refine/operations/recon/ExtendDataOperation.java +++ b/main/src/com/google/refine/operations/recon/ExtendDataOperation.java @@ -45,7 +45,6 @@ import org.json.JSONException; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; diff --git a/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java b/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java index 673e5e49d..3cccca2c2 100644 --- a/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconClearSimilarCellsOperation.java @@ -37,7 +37,6 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; diff --git a/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java b/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java index 6b9f89aa9..3fb901a64 100644 --- a/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java @@ -44,7 +44,6 @@ import org.apache.commons.lang3.StringUtils; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; diff --git a/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java b/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java index c5e538e2e..c9ba826dc 100644 --- a/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconDiscardJudgmentsOperation.java @@ -39,7 +39,6 @@ import java.util.Map; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; diff --git a/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java b/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java index 5068334b4..bfa016462 100644 --- a/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconJudgeSimilarCellsOperation.java @@ -41,7 +41,6 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.expr.ExpressionUtils; diff --git a/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java b/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java index ac0eb1989..b6d7b42c3 100644 --- a/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMarkNewTopicsOperation.java @@ -39,7 +39,6 @@ import java.util.Map; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; diff --git a/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java b/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java index 17dd06184..b5f782d10 100644 --- a/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMatchBestCandidatesOperation.java @@ -39,7 +39,6 @@ import java.util.Map; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; diff --git a/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java b/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java index 918a71d4d..83608fe92 100644 --- a/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconMatchSpecificTopicOperation.java @@ -40,7 +40,6 @@ import java.util.Map; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.history.Change; diff --git a/main/src/com/google/refine/operations/recon/ReconOperation.java b/main/src/com/google/refine/operations/recon/ReconOperation.java index b9218f145..fbc0a3f3c 100644 --- a/main/src/com/google/refine/operations/recon/ReconOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconOperation.java @@ -46,7 +46,6 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; diff --git a/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java b/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java index d6115decc..ef6f51e05 100644 --- a/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java @@ -6,7 +6,6 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.RowVisitor; import com.google.refine.expr.ExpressionUtils; diff --git a/main/src/com/google/refine/operations/row/DenormalizeOperation.java b/main/src/com/google/refine/operations/row/DenormalizeOperation.java index aaee43c51..c8888fc93 100644 --- a/main/src/com/google/refine/operations/row/DenormalizeOperation.java +++ b/main/src/com/google/refine/operations/row/DenormalizeOperation.java @@ -37,7 +37,6 @@ import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; - import com.google.refine.history.HistoryEntry; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Cell; diff --git a/main/src/com/google/refine/operations/row/RowFlagOperation.java b/main/src/com/google/refine/operations/row/RowFlagOperation.java index ddf142ec4..63501a273 100644 --- a/main/src/com/google/refine/operations/row/RowFlagOperation.java +++ b/main/src/com/google/refine/operations/row/RowFlagOperation.java @@ -38,7 +38,6 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; diff --git a/main/src/com/google/refine/operations/row/RowRemovalOperation.java b/main/src/com/google/refine/operations/row/RowRemovalOperation.java index bf536ce0d..f06d9e019 100644 --- a/main/src/com/google/refine/operations/row/RowRemovalOperation.java +++ b/main/src/com/google/refine/operations/row/RowRemovalOperation.java @@ -38,7 +38,6 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; diff --git a/main/src/com/google/refine/operations/row/RowReorderOperation.java b/main/src/com/google/refine/operations/row/RowReorderOperation.java index b90867846..ac5b23178 100644 --- a/main/src/com/google/refine/operations/row/RowReorderOperation.java +++ b/main/src/com/google/refine/operations/row/RowReorderOperation.java @@ -38,7 +38,6 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.RecordVisitor; diff --git a/main/src/com/google/refine/operations/row/RowStarOperation.java b/main/src/com/google/refine/operations/row/RowStarOperation.java index 1d6caf472..81e2f27f5 100644 --- a/main/src/com/google/refine/operations/row/RowStarOperation.java +++ b/main/src/com/google/refine/operations/row/RowStarOperation.java @@ -38,7 +38,6 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.FilteredRows; diff --git a/main/src/com/google/refine/process/LongRunningProcess.java b/main/src/com/google/refine/process/LongRunningProcess.java index b8e12c669..5d978676d 100644 --- a/main/src/com/google/refine/process/LongRunningProcess.java +++ b/main/src/com/google/refine/process/LongRunningProcess.java @@ -35,7 +35,6 @@ package com.google.refine.process; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.history.HistoryEntry; abstract public class LongRunningProcess extends Process { diff --git a/main/src/com/google/refine/process/Process.java b/main/src/com/google/refine/process/Process.java index 21af244fa..6633f68c6 100644 --- a/main/src/com/google/refine/process/Process.java +++ b/main/src/com/google/refine/process/Process.java @@ -35,7 +35,6 @@ package com.google.refine.process; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.history.HistoryEntry; public abstract class Process { diff --git a/main/src/com/google/refine/process/ProcessManager.java b/main/src/com/google/refine/process/ProcessManager.java index 3f5a48283..379de3364 100644 --- a/main/src/com/google/refine/process/ProcessManager.java +++ b/main/src/com/google/refine/process/ProcessManager.java @@ -42,7 +42,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.history.HistoryEntry; import com.google.refine.history.HistoryProcess; diff --git a/main/src/com/google/refine/process/QuickHistoryEntryProcess.java b/main/src/com/google/refine/process/QuickHistoryEntryProcess.java index 7f16f68e4..25f9cfa6a 100644 --- a/main/src/com/google/refine/process/QuickHistoryEntryProcess.java +++ b/main/src/com/google/refine/process/QuickHistoryEntryProcess.java @@ -34,7 +34,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.process; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.history.HistoryEntry; import com.google.refine.model.Project; diff --git a/main/src/com/google/refine/sorting/Criterion.java b/main/src/com/google/refine/sorting/Criterion.java index a9d01ac26..7e8a56fc8 100644 --- a/main/src/com/google/refine/sorting/Criterion.java +++ b/main/src/com/google/refine/sorting/Criterion.java @@ -33,23 +33,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.sorting; -import java.io.IOException; - -import org.json.JSONException; -import org.json.JSONObject; - import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; - +import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.google.refine.expr.ExpressionUtils; import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Record; import com.google.refine.model.Row; -import com.google.refine.util.ParsingUtilities; @JsonTypeInfo( use=JsonTypeInfo.Id.NAME, diff --git a/main/src/com/google/refine/sorting/SortingConfig.java b/main/src/com/google/refine/sorting/SortingConfig.java index a8e2e172b..cda207815 100644 --- a/main/src/com/google/refine/sorting/SortingConfig.java +++ b/main/src/com/google/refine/sorting/SortingConfig.java @@ -6,7 +6,6 @@ import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/sorting/StringCriterion.java b/main/src/com/google/refine/sorting/StringCriterion.java index 78234f767..9ad91a4f7 100644 --- a/main/src/com/google/refine/sorting/StringCriterion.java +++ b/main/src/com/google/refine/sorting/StringCriterion.java @@ -38,7 +38,6 @@ import java.text.Collator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.expr.ExpressionUtils; public class StringCriterion extends Criterion { diff --git a/main/src/com/google/refine/util/JSONUtilities.java b/main/src/com/google/refine/util/JSONUtilities.java index 5d2ef8711..9f8433087 100644 --- a/main/src/com/google/refine/util/JSONUtilities.java +++ b/main/src/com/google/refine/util/JSONUtilities.java @@ -39,17 +39,16 @@ import java.time.ZoneId; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; -import java.util.Collection; import java.util.List; -import java.util.Map; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeType; - +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.Lists; @@ -63,6 +62,14 @@ public class JSONUtilities { } } + static public ObjectNode getObject(ObjectNode obj, String key) { + JsonNode node = obj.get(key); + if(node != null && node instanceof ObjectNode) { + return (ObjectNode)node; + } + return null; + } + static public String getString(JSONObject obj, String key, String def) { try { return obj.getString(key); @@ -72,7 +79,7 @@ public class JSONUtilities { } static public String getString(JsonNode obj, String key, String def) { - if (obj.get(key) != null) { + if (obj.has(key)) { return obj.get(key).textValue(); } else { return def; @@ -88,7 +95,7 @@ public class JSONUtilities { } static public int getInt(JsonNode obj, String key, int def) { - if (obj.get(key) != null) { + if (obj.has(key)) { return obj.get(key).asInt(def); } else { return def; @@ -104,7 +111,7 @@ public class JSONUtilities { } static public boolean getBoolean(JsonNode obj, String key, boolean def) { - if (obj.get(key) != null) { + if (obj.has(key)) { return obj.get(key).asBoolean(def); } else { return def; @@ -155,6 +162,14 @@ public class JSONUtilities { } } + static public ArrayNode getArray(ObjectNode obj, String key) { + JsonNode v = obj.get(key); + if( obj.has(key) && obj.get(key) instanceof ArrayNode) { + return (ArrayNode) obj.get(key); + } + return null; + } + static public List getArray(JsonNode obj, String key) { if (obj.has(key) && obj.get(key).getNodeType().equals(JsonNodeType.ARRAY)) { return Lists.newArrayList(obj.get(key).elements()); @@ -182,6 +197,20 @@ public class JSONUtilities { } } + static public int[] getIntArray(ObjectNode obj, String key) { + ArrayNode a = getArray(obj, key); + if (a == null) { + return new int[0]; + } + int[] r = new int[a.size()]; + int i = 0; + for(JsonNode n : a) { + r[i] = n.asInt(); + i++; + } + return r; + } + static public String[] getStringArray(JSONObject obj, String key) { try { JSONArray a = obj.getJSONArray(key); @@ -197,6 +226,20 @@ public class JSONUtilities { } } + static public String[] getStringArray(ObjectNode obj, String key) { + ArrayNode a = getArray(obj, key); + if (a == null) { + return new String[0]; + } + String[] r = new String[a.size()]; + + for (int i = 0; i < r.length; i++) { + r[i] = a.get(i).asText(); + } + + return r; + } + static public void getStringList(JSONObject obj, String key, List list) { try { JSONArray a = obj.getJSONArray(key); @@ -235,6 +278,14 @@ public class JSONUtilities { } } + static public ObjectNode getObjectElement(ArrayNode a, int i) { + JsonNode n = a.get(i); + if (n != null && n instanceof ObjectNode) { + return (ObjectNode) n; + } + return null; + } + static public int getIntElement(JSONArray a, int i, int def) { try { return a.getInt(i); @@ -243,13 +294,28 @@ public class JSONUtilities { } } - static public void append(JSONArray a, JSONObject element) { + static public int getIntElement(ArrayNode a, int i, int def) { + if (a.get(i) != null) { + return a.get(i).asInt(def); + } + return def; + } + + static public void append(JSONArray sheetRecords, JSONObject sheetRecord) { try { - a.put(a.length(), element); + sheetRecords.put(sheetRecords.length(), sheetRecord); } catch (JSONException e) { } } + static public void append(ArrayNode sheetRecords, ObjectNode sheetRecord) { + sheetRecords.add(sheetRecord); + } + + static public void append(ArrayNode array, int v) { + array.add(v); + } + static public void append(JSONArray a, Object element) { try { a.put(a.length(), element); @@ -292,9 +358,13 @@ public class JSONUtilities { } } - static public void safePut(JSONObject obj, String key, int value) { + static public void append(ArrayNode a, String element) { + a.add(element); + } + + static public void safePut(ObjectNode options, String key, JsonNode rootElement) { try { - obj.put(key, value); + options.put(key, rootElement); } catch (JSONException e) { // Ignore: the JSONObject is just too happy about throwing exceptions. } @@ -309,6 +379,15 @@ public class JSONUtilities { } } + static public void safeInc(ObjectNode obj, String key) { + int currentValue = getInt(obj, key, 0); + safePut(obj, key, currentValue + 1); + } + + static public void safePut(ObjectNode obj, String key, long value) { + obj.put(key, value); + } + static public void safePut(JSONObject obj, String key, long value) { try { obj.put(key, value); @@ -317,6 +396,10 @@ public class JSONUtilities { } } + static public void safePut(ObjectNode obj, String key, double value) { + obj.put(key, value); + } + static public void safePut(JSONObject obj, String key, double value) { try { obj.put(key, value); @@ -325,6 +408,10 @@ public class JSONUtilities { } } + static public void safePut(ObjectNode obj, String key, boolean value) { + obj.put(key, value); + } + static public void safePut(JSONObject obj, String key, boolean value) { try { obj.put(key, value); @@ -333,6 +420,10 @@ public class JSONUtilities { } } + static public void safePut(ObjectNode obj, String key, String value) { + obj.put(key, value); + } + static public void safePut(JSONObject obj, String key, String value) { try { obj.put(key, value); @@ -341,22 +432,6 @@ public class JSONUtilities { } } - static public void safePut(JSONObject obj, String key, Collection value) { - try { - obj.put(key, value); - } catch (JSONException e) { - // Ignore: the JSONObject is just too happy about throwing exceptions. - } - } - - static public void safePut(JSONObject obj, String key, Map value) { - try { - obj.put(key, value); - } catch (JSONException e) { - // Ignore: the JSONObject is just too happy about throwing exceptions. - } - } - static public void safePut(JSONObject obj, String key, Object value) { try { obj.put(key, value); @@ -393,4 +468,13 @@ public class JSONUtilities { destArray.put(srcArray.get(i)); } } + + // temporary method used during migratino + static public ObjectNode jsonObjectToObjectNode(JSONObject obj) { + return ParsingUtilities.evaluateJsonStringToObjectNode(obj.toString()); + } + + public static JSONObject objectNodeToJsonNode(ObjectNode fieldJsonObj) { + return new JSONObject(fieldJsonObj.toString()); + } } diff --git a/main/src/com/google/refine/util/ParsingUtilities.java b/main/src/com/google/refine/util/ParsingUtilities.java index f4426a989..9717c880b 100644 --- a/main/src/com/google/refine/util/ParsingUtilities.java +++ b/main/src/com/google/refine/util/ParsingUtilities.java @@ -62,9 +62,12 @@ import org.json.JSONTokener; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; @@ -269,4 +272,28 @@ public class ParsingUtilities { cal.setTimeInMillis(offsetDateTime.toInstant().toEpochMilli()); return cal; } + + public static ObjectNode evaluateJsonStringToObjectNode(String optionsString) { + try { + JsonNode tree = mapper.readTree(optionsString); + if(tree instanceof ObjectNode) { + return (ObjectNode)tree; + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + public static ArrayNode evaluateJsonStringToArrayNode(String parameter) { + try { + JsonNode tree = mapper.readTree(parameter); + if(tree instanceof ArrayNode) { + return (ArrayNode)tree; + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } } diff --git a/main/src/com/google/refine/util/Pool.java b/main/src/com/google/refine/util/Pool.java index d91ca0f9a..ab12395fa 100644 --- a/main/src/com/google/refine/util/Pool.java +++ b/main/src/com/google/refine/util/Pool.java @@ -46,7 +46,6 @@ import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.refine.RefineServlet; import com.google.refine.model.Recon; import com.google.refine.model.ReconCandidate; diff --git a/main/src/com/google/refine/util/SerializationFilters.java b/main/src/com/google/refine/util/SerializationFilters.java index 4c937c25f..37902617d 100644 --- a/main/src/com/google/refine/util/SerializationFilters.java +++ b/main/src/com/google/refine/util/SerializationFilters.java @@ -11,7 +11,6 @@ import com.fasterxml.jackson.databind.ser.PropertyFilter; import com.fasterxml.jackson.databind.ser.PropertyWriter; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; import com.fasterxml.jackson.databind.ser.std.StdSerializer; - import com.google.refine.model.Recon; import com.google.refine.model.Recon.Judgment; diff --git a/main/tests/server/src/com/google/refine/tests/RefineTest.java b/main/tests/server/src/com/google/refine/tests/RefineTest.java index 26d21eae6..a4429c74b 100644 --- a/main/tests/server/src/com/google/refine/tests/RefineTest.java +++ b/main/tests/server/src/com/google/refine/tests/RefineTest.java @@ -54,6 +54,11 @@ import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.BooleanNode; +import com.fasterxml.jackson.databind.node.IntNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; import com.google.refine.ProjectManager; import com.google.refine.RefineServlet; import com.google.refine.importers.SeparatorBasedImporter; @@ -165,7 +170,7 @@ public class RefineTest { ProjectMetadata metadata = new ProjectMetadata(); metadata.setName(projectName); - JSONObject options = mock(JSONObject.class); + ObjectNode options = mock(ObjectNode.class); prepareImportOptions(options, ",", -1, 0, 0, 1, false, false); ImportingJob job = ImportingManager.createJob(); @@ -193,7 +198,7 @@ public class RefineTest { * @param guessValueType * @param ignoreQuotes */ - private void prepareImportOptions(JSONObject options, + private void prepareImportOptions(ObjectNode options, String sep, int limit, int skip, int ignoreLines, int headerLines, boolean guessValueType, boolean ignoreQuotes) { @@ -281,26 +286,51 @@ public class RefineTest { when(JSONUtilities.getBoolean(options, name, def)).thenReturn(def); } + static public void whenGetBooleanOption(String name, ObjectNode options, Boolean def){ + when(options.has(name)).thenReturn(true); + when(options.get(name)).thenReturn(def ? BooleanNode.TRUE : BooleanNode.FALSE); + } + static public void whenGetIntegerOption(String name, JSONObject options, int def){ when(options.has(name)).thenReturn(true); when(JSONUtilities.getInt(options, name, def)).thenReturn(def); } + static public void whenGetIntegerOption(String name, ObjectNode options, int def){ + when(options.has(name)).thenReturn(true); + when(options.get(name)).thenReturn(new IntNode(def)); + } + static public void whenGetStringOption(String name, JSONObject options, String def){ when(options.has(name)).thenReturn(true); when(JSONUtilities.getString(options, name, def)).thenReturn(def); } + static public void whenGetStringOption(String name, ObjectNode options, String def){ + when(options.has(name)).thenReturn(true); + when(options.get(name)).thenReturn(new TextNode(def)); + } + static public void whenGetObjectOption(String name, JSONObject options, JSONObject def){ when(options.has(name)).thenReturn(true); when(JSONUtilities.getObject(options, name)).thenReturn(def); } + static public void whenGetObjectOption(String name, ObjectNode options, ObjectNode def){ + when(options.has(name)).thenReturn(true); + when(options.get(name)).thenReturn(def); + } + static public void whenGetArrayOption(String name, JSONObject options, JSONArray def){ when(options.has(name)).thenReturn(true); when(JSONUtilities.getArray(options, name)).thenReturn(def); } + static public void whenGetArrayOption(String name, ObjectNode options, ArrayNode def){ + when(options.has(name)).thenReturn(true); + when(options.get(name)).thenReturn(def); + } + static public void verifyGetOption(String name, JSONObject options){ verify(options, times(1)).has(name); try { @@ -311,13 +341,9 @@ public class RefineTest { } // Works for both int, String, and JSON arrays - static public void verifyGetArrayOption(String name, JSONObject options){ + static public void verifyGetArrayOption(String name, ObjectNode options){ verify(options, times(1)).has(name); - try { - verify(options, times(1)).getJSONArray(name); - } catch (JSONException e) { - Assert.fail("JSONException",e); - } + verify(options, times(1)).get(name); } protected ButterflyModule getCoreModule() { diff --git a/main/tests/server/src/com/google/refine/tests/browsing/EngineTests.java b/main/tests/server/src/com/google/refine/tests/browsing/EngineTests.java index e6d875452..4ed43f040 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/EngineTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/EngineTests.java @@ -1,6 +1,7 @@ package com.google.refine.tests.browsing; import static org.mockito.Mockito.mock; + import org.testng.annotations.Test; import com.google.refine.browsing.Engine; diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/EngineConfigTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/EngineConfigTests.java index d63cd2f76..51847b3ef 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/EngineConfigTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/EngineConfigTests.java @@ -4,8 +4,8 @@ import org.json.JSONObject; import org.testng.Assert; import org.testng.annotations.Test; -import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.Engine.Mode; +import com.google.refine.browsing.EngineConfig; import com.google.refine.tests.util.TestUtils; public class EngineConfigTests { diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java index 200134d6f..a9994954f 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java @@ -6,7 +6,6 @@ import org.testng.annotations.Test; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.facets.Facet; import com.google.refine.browsing.facets.ListFacet.ListFacetConfig; diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/RangeFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/RangeFacetTests.java index 21374439d..ecfd51b26 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/RangeFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/RangeFacetTests.java @@ -6,7 +6,6 @@ import org.testng.annotations.Test; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.facets.RangeFacet; import com.google.refine.browsing.facets.RangeFacet.RangeFacetConfig; diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/ScatterplotFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/ScatterplotFacetTests.java index 29e7e9112..1aceb9392 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/ScatterplotFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/ScatterplotFacetTests.java @@ -6,7 +6,6 @@ import org.testng.annotations.Test; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.facets.ScatterplotFacet; import com.google.refine.browsing.facets.ScatterplotFacet.ScatterplotFacetConfig; diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java index 5d8903bc8..5d9b14baf 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java @@ -44,7 +44,6 @@ import org.testng.annotations.Test; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; - import com.google.refine.browsing.RowFilter; import com.google.refine.browsing.facets.TextSearchFacet; import com.google.refine.browsing.facets.TextSearchFacet.TextSearchFacetConfig; diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java index a0741a03c..4c77b4684 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java @@ -7,7 +7,6 @@ import org.testng.annotations.Test; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.facets.TimeRangeFacet; import com.google.refine.browsing.facets.TimeRangeFacet.TimeRangeFacetConfig; diff --git a/main/tests/server/src/com/google/refine/tests/browsing/util/ExpressionNominalValueGrouperTests.java b/main/tests/server/src/com/google/refine/tests/browsing/util/ExpressionNominalValueGrouperTests.java index 6b482856e..c0bbf169d 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/util/ExpressionNominalValueGrouperTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/util/ExpressionNominalValueGrouperTests.java @@ -30,24 +30,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.tests.browsing.util; -import com.google.refine.expr.MetaParser; -import org.testng.annotations.AfterMethod; -import org.testng.Assert; - import java.io.IOException; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; import java.util.Properties; - import org.json.JSONException; import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.refine.browsing.util.ExpressionNominalValueGrouper; import com.google.refine.expr.Evaluable; +import com.google.refine.expr.MetaParser; import com.google.refine.model.Cell; import com.google.refine.model.ModelException; import com.google.refine.model.Project; diff --git a/main/tests/server/src/com/google/refine/tests/commands/expr/ExpressionCommandTestBase.java b/main/tests/server/src/com/google/refine/tests/commands/expr/ExpressionCommandTestBase.java index f2ffb2244..34c55c990 100644 --- a/main/tests/server/src/com/google/refine/tests/commands/expr/ExpressionCommandTestBase.java +++ b/main/tests/server/src/com/google/refine/tests/commands/expr/ExpressionCommandTestBase.java @@ -16,7 +16,6 @@ import org.testng.annotations.BeforeMethod; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; - import com.google.refine.commands.Command; import com.google.refine.io.FileProjectManager; import com.google.refine.tests.util.TestUtils; diff --git a/main/tests/server/src/com/google/refine/tests/commands/expr/GetExpressionLanguageInfoCommandTests.java b/main/tests/server/src/com/google/refine/tests/commands/expr/GetExpressionLanguageInfoCommandTests.java index b80159be2..ef895d8d6 100644 --- a/main/tests/server/src/com/google/refine/tests/commands/expr/GetExpressionLanguageInfoCommandTests.java +++ b/main/tests/server/src/com/google/refine/tests/commands/expr/GetExpressionLanguageInfoCommandTests.java @@ -8,7 +8,6 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.fasterxml.jackson.databind.JsonNode; - import com.google.refine.commands.expr.GetExpressionLanguageInfoCommand; import com.google.refine.tests.util.TestUtils; import com.google.refine.util.ParsingUtilities; diff --git a/main/tests/server/src/com/google/refine/tests/commands/expr/PreviewExpressionCommandTests.java b/main/tests/server/src/com/google/refine/tests/commands/expr/PreviewExpressionCommandTests.java index 268107b51..ab4ee0390 100644 --- a/main/tests/server/src/com/google/refine/tests/commands/expr/PreviewExpressionCommandTests.java +++ b/main/tests/server/src/com/google/refine/tests/commands/expr/PreviewExpressionCommandTests.java @@ -1,12 +1,12 @@ package com.google.refine.tests.commands.expr; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/main/tests/server/src/com/google/refine/tests/commands/expr/ToggleStarredExpressionCommandTests.java b/main/tests/server/src/com/google/refine/tests/commands/expr/ToggleStarredExpressionCommandTests.java index 019fa43ba..91a6d296e 100644 --- a/main/tests/server/src/com/google/refine/tests/commands/expr/ToggleStarredExpressionCommandTests.java +++ b/main/tests/server/src/com/google/refine/tests/commands/expr/ToggleStarredExpressionCommandTests.java @@ -1,8 +1,9 @@ package com.google.refine.tests.commands.expr; -import java.io.IOException; import static org.mockito.Mockito.when; +import java.io.IOException; + import javax.servlet.ServletException; import org.testng.annotations.BeforeMethod; diff --git a/main/tests/server/src/com/google/refine/tests/commands/project/ValidateOperationTests.java b/main/tests/server/src/com/google/refine/tests/commands/project/ValidateOperationTests.java index 528a43e60..8582d657c 100644 --- a/main/tests/server/src/com/google/refine/tests/commands/project/ValidateOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/commands/project/ValidateOperationTests.java @@ -28,10 +28,10 @@ import org.testng.Assert; import com.google.refine.ProjectManager; import com.google.refine.importers.SeparatorBasedImporter; import com.google.refine.model.Column; -import com.google.refine.model.metadata.validator.ValidateOperation; import com.google.refine.model.metadata.DataPackageMetadata; import com.google.refine.model.metadata.MetadataFactory; import com.google.refine.model.metadata.MetadataFormat; +import com.google.refine.model.metadata.validator.ValidateOperation; import com.google.refine.tests.importers.TsvCsvImporterTests; import com.google.refine.util.ParsingUtilities; diff --git a/main/tests/server/src/com/google/refine/tests/commands/row/GetRowsCommandTest.java b/main/tests/server/src/com/google/refine/tests/commands/row/GetRowsCommandTest.java index d35315c7d..52e5e06d6 100644 --- a/main/tests/server/src/com/google/refine/tests/commands/row/GetRowsCommandTest.java +++ b/main/tests/server/src/com/google/refine/tests/commands/row/GetRowsCommandTest.java @@ -1,5 +1,12 @@ package com.google.refine.tests.commands.row; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -13,13 +20,6 @@ import com.google.refine.model.Project; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; - public class GetRowsCommandTest extends RefineTest { HttpServletRequest request = null; diff --git a/main/tests/server/src/com/google/refine/tests/commands/util/CancelProcessesCommandTests.java b/main/tests/server/src/com/google/refine/tests/commands/util/CancelProcessesCommandTests.java index a1ed70c2a..45d5356ab 100644 --- a/main/tests/server/src/com/google/refine/tests/commands/util/CancelProcessesCommandTests.java +++ b/main/tests/server/src/com/google/refine/tests/commands/util/CancelProcessesCommandTests.java @@ -33,7 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.tests.commands.util; -import static org.mockito.Matchers.anyLong; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; diff --git a/main/tests/server/src/com/google/refine/tests/exporters/sql/SqlExporterTests.java b/main/tests/server/src/com/google/refine/tests/exporters/sql/SqlExporterTests.java index 0b3073c20..9243596be 100644 --- a/main/tests/server/src/com/google/refine/tests/exporters/sql/SqlExporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/exporters/sql/SqlExporterTests.java @@ -71,7 +71,6 @@ import com.google.refine.model.Row; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.ProjectManagerStub; import com.google.refine.tests.RefineTest; -import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; diff --git a/main/tests/server/src/com/google/refine/tests/expr/functions/ContainsFunctionTests.java b/main/tests/server/src/com/google/refine/tests/expr/functions/ContainsFunctionTests.java index 735c82dfb..7f5c5ac3c 100644 --- a/main/tests/server/src/com/google/refine/tests/expr/functions/ContainsFunctionTests.java +++ b/main/tests/server/src/com/google/refine/tests/expr/functions/ContainsFunctionTests.java @@ -1,11 +1,9 @@ package com.google.refine.tests.expr.functions; -import com.google.refine.RefineServlet; -import com.google.refine.grel.ControlFunctionRegistry; -import com.google.refine.grel.Function; -import com.google.refine.tests.RefineServletStub; -import com.google.refine.tests.RefineTest; +import java.util.Properties; +import java.util.regex.Pattern; + import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.AfterMethod; @@ -13,8 +11,11 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import java.util.Properties; -import java.util.regex.Pattern; +import com.google.refine.RefineServlet; +import com.google.refine.grel.ControlFunctionRegistry; +import com.google.refine.grel.Function; +import com.google.refine.tests.RefineServletStub; +import com.google.refine.tests.RefineTest; /** * Test cases for find function. diff --git a/main/tests/server/src/com/google/refine/tests/expr/functions/strings/ToFromConversionTests.java b/main/tests/server/src/com/google/refine/tests/expr/functions/strings/ToFromConversionTests.java index 7d64488fd..cb7f467c4 100644 --- a/main/tests/server/src/com/google/refine/tests/expr/functions/strings/ToFromConversionTests.java +++ b/main/tests/server/src/com/google/refine/tests/expr/functions/strings/ToFromConversionTests.java @@ -44,8 +44,8 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.refine.expr.EvalError; -import com.google.refine.expr.util.CalendarParserException; import com.google.refine.expr.util.CalendarParser; +import com.google.refine.expr.util.CalendarParserException; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/history/HistoryTests.java b/main/tests/server/src/com/google/refine/tests/history/HistoryTests.java index 759fa8273..81641b3fa 100644 --- a/main/tests/server/src/com/google/refine/tests/history/HistoryTests.java +++ b/main/tests/server/src/com/google/refine/tests/history/HistoryTests.java @@ -47,6 +47,7 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.refine.ProjectManager; +import com.google.refine.history.Change; import com.google.refine.history.History; import com.google.refine.history.HistoryEntry; import com.google.refine.history.HistoryEntryManager; @@ -54,7 +55,6 @@ import com.google.refine.model.Project; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; -import com.google.refine.history.Change; public class HistoryTests extends RefineTest { diff --git a/main/tests/server/src/com/google/refine/tests/importers/ExcelImporterTests.java b/main/tests/server/src/com/google/refine/tests/importers/ExcelImporterTests.java index efc36c8d9..86732e1d0 100644 --- a/main/tests/server/src/com/google/refine/tests/importers/ExcelImporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/importers/ExcelImporterTests.java @@ -53,9 +53,7 @@ import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONObject; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.AfterMethod; @@ -63,8 +61,9 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import com.fasterxml.jackson.databind.node.ArrayNode; import com.google.refine.importers.ExcelImporter; -import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class ExcelImporterTests extends ImporterTest { @@ -101,11 +100,10 @@ public class ExcelImporterTests extends ImporterTest { //---------------------read tests------------------------ @Test - public void readXls() throws FileNotFoundException, JSONException{ + public void readXls() throws FileNotFoundException, IOException{ - JSONArray sheets = new JSONArray(); - JSONUtilities.append(sheets, - new JSONObject("{name: \"file-source#Test Sheet 0\", fileNameAndSheetIndex: \"file-source#0\", rows: 31, selected: true}")); + ArrayNode sheets = ParsingUtilities.mapper.createArrayNode(); + sheets.add(ParsingUtilities.mapper.readTree("{name: \"file-source#Test Sheet 0\", fileNameAndSheetIndex: \"file-source#0\", rows: 31, selected: true}")); whenGetArrayOption("sheets", options, sheets); whenGetIntegerOption("ignoreLines", options, 0); @@ -134,11 +132,11 @@ public class ExcelImporterTests extends ImporterTest { Assert.assertNull((String)project.rows.get(1).getCellValue(5)); try { - verify(options, times(1)).getInt("ignoreLines"); - verify(options, times(1)).getInt("headerLines"); - verify(options, times(1)).getInt("skipDataLines"); - verify(options, times(1)).getInt("limit"); - verify(options, times(1)).getBoolean("storeBlankCellsAsNulls"); + verify(options, times(1)).get("ignoreLines"); + verify(options, times(1)).get("headerLines"); + verify(options, times(1)).get("skipDataLines"); + verify(options, times(1)).get("limit"); + verify(options, times(1)).get("storeBlankCellsAsNulls"); } catch (JSONException e) { Assert.fail("JSON exception",e); } diff --git a/main/tests/server/src/com/google/refine/tests/importers/FixedWidthImporterTests.java b/main/tests/server/src/com/google/refine/tests/importers/FixedWidthImporterTests.java index 2fbd05ab2..0a1633f4e 100644 --- a/main/tests/server/src/com/google/refine/tests/importers/FixedWidthImporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/importers/FixedWidthImporterTests.java @@ -1,13 +1,8 @@ package com.google.refine.tests.importers; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - import java.io.StringReader; -import org.json.JSONArray; -import org.json.JSONException; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.AfterMethod; @@ -15,8 +10,10 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import com.fasterxml.jackson.databind.node.ArrayNode; import com.google.refine.importers.FixedWidthImporter; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class FixedWidthImporterTests extends ImporterTest { @Override @@ -50,16 +47,16 @@ public class FixedWidthImporterTests extends ImporterTest { public void readFixedWidth(){ StringReader reader = new StringReader(SAMPLE_ROW + "\nTooShort"); - JSONArray columnWidths = new JSONArray(); + ArrayNode columnWidths = ParsingUtilities.mapper.createArrayNode(); JSONUtilities.append(columnWidths, 6); JSONUtilities.append(columnWidths, 9); JSONUtilities.append(columnWidths, 5); whenGetArrayOption("columnWidths", options, columnWidths); - JSONArray columnNames = new JSONArray(); - JSONUtilities.append(columnNames, "Col 1"); - JSONUtilities.append(columnNames, "Col 2"); - JSONUtilities.append(columnNames, "Col 3"); + ArrayNode columnNames = ParsingUtilities.mapper.createArrayNode(); + columnNames.add("Col 1"); + columnNames.add("Col 2"); + columnNames.add("Col 3"); whenGetArrayOption("columnNames", options, columnNames); whenGetIntegerOption("ignoreLines", options, 0); @@ -83,17 +80,5 @@ public class FixedWidthImporterTests extends ImporterTest { Assert.assertEquals((String)project.rows.get(2).getCellValue(0), "TooSho"); Assert.assertEquals((String)project.rows.get(2).getCellValue(1), "rt"); Assert.assertNull(project.rows.get(2).getCellValue(2)); - - verifyGetArrayOption("columnNames", options); - try { - verify(options, times(1)).getJSONArray("columnWidths"); - verify(options, times(1)).getInt("ignoreLines"); - verify(options, times(1)).getInt("headerLines"); - verify(options, times(1)).getInt("skipDataLines"); - verify(options, times(1)).getInt("limit"); - verify(options, times(1)).getBoolean("storeBlankCellsAsNulls"); - } catch (JSONException e) { - Assert.fail("JSON exception",e); - } } } diff --git a/main/tests/server/src/com/google/refine/tests/importers/ImporterTest.java b/main/tests/server/src/com/google/refine/tests/importers/ImporterTest.java index 46161e043..58704b353 100644 --- a/main/tests/server/src/com/google/refine/tests/importers/ImporterTest.java +++ b/main/tests/server/src/com/google/refine/tests/importers/ImporterTest.java @@ -9,9 +9,9 @@ import java.io.Reader; import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; import org.mockito.Mockito; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.RefineServlet; import com.google.refine.importers.ImportingParserBase; import com.google.refine.importers.tree.ImportColumnGroup; @@ -23,6 +23,7 @@ import com.google.refine.model.Project; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.RefineServletStub; import com.google.refine.tests.RefineTest; +import com.google.refine.util.ParsingUtilities; abstract public class ImporterTest extends RefineTest { //mock dependencies @@ -31,7 +32,7 @@ abstract public class ImporterTest extends RefineTest { protected ImportingJob job; protected RefineServlet servlet; - protected JSONObject options; + protected ObjectNode options; public void setUp(){ //FIXME - should we try and use mock(Project.class); - seems unnecessary complexity @@ -42,9 +43,9 @@ abstract public class ImporterTest extends RefineTest { metadata = new ProjectMetadata(); ImportingJob spiedJob = ImportingManager.createJob(); job = Mockito.spy(spiedJob); - when(job.getRetrievalRecord()).thenReturn(new JSONObject()); + when(job.getRetrievalRecord()).thenReturn(ParsingUtilities.mapper.createObjectNode()); - options = Mockito.mock(JSONObject.class); + options = Mockito.mock(ObjectNode.class); } public void tearDown(){ @@ -102,12 +103,12 @@ abstract public class ImporterTest extends RefineTest { project.columnModel.update(); } - protected void parseOneFile(TreeImportingParserBase parser, InputStream inputStream, JSONObject options) { + protected void parseOneFile(TreeImportingParserBase parser, InputStream inputStream, ObjectNode options) { parseOneInputStreamAsReader(parser, inputStream, options); } protected void parseOneInputStream( - TreeImportingParserBase parser, InputStream inputStream, JSONObject options) { + TreeImportingParserBase parser, InputStream inputStream, ObjectNode options) { ImportColumnGroup rootColumnGroup = new ImportColumnGroup(); List exceptions = new ArrayList(); @@ -126,7 +127,7 @@ abstract public class ImporterTest extends RefineTest { } protected void parseOneInputStreamAsReader( - TreeImportingParserBase parser, InputStream inputStream, JSONObject options) { + TreeImportingParserBase parser, InputStream inputStream, ObjectNode options) { ImportColumnGroup rootColumnGroup = new ImportColumnGroup(); List exceptions = new ArrayList(); diff --git a/main/tests/server/src/com/google/refine/tests/importers/JsonImporterTests.java b/main/tests/server/src/com/google/refine/tests/importers/JsonImporterTests.java index 3f6ba1973..b893d3834 100644 --- a/main/tests/server/src/com/google/refine/tests/importers/JsonImporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/importers/JsonImporterTests.java @@ -39,8 +39,6 @@ import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.LinkedList; -import org.json.JSONArray; -import org.json.JSONObject; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.AfterMethod; @@ -48,6 +46,8 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importers.JsonImporter; import com.google.refine.importers.JsonImporter.JSONTreeReader; import com.google.refine.importers.tree.TreeImportingParserBase; @@ -55,6 +55,7 @@ import com.google.refine.importers.tree.TreeReader.Token; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Row; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class JsonImporterTests extends ImporterTest { @Override @@ -166,12 +167,12 @@ public class JsonImporterTests extends ImporterTest { public void testElementWithMqlReadOutput(){ String mqlOutput = "{\"code\":\"/api/status/ok\",\"result\":[{\"armed_force\":{\"id\":\"/en/wehrmacht\"},\"id\":\"/en/afrika_korps\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/m/0chtrwn\"},\"id\":\"/en/sacred_band_of_thebes\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/en/british_army\"},\"id\":\"/en/british_16_air_assault_brigade\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/en/british_army\"},\"id\":\"/en/pathfinder_platoon\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/m/0ch7qgz\"},\"id\":\"/en/sacred_band\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/en/polish_navy\"},\"id\":\"/en/3rd_ship_flotilla\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/m/0chtrwn\"},\"id\":\"/m/0c0kxn9\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/m/0chtrwn\"},\"id\":\"/m/0c0kxq9\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/m/0chtrwn\"},\"id\":\"/m/0c0kxqh\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/m/0chtrwn\"},\"id\":\"/m/0c0kxqp\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/m/0chtrwn\"},\"id\":\"/m/0c0kxqw\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/m/0chtrwn\"},\"id\":\"/m/0c1wxl3\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/m/0chtrwn\"},\"id\":\"/m/0c1wxlp\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/m/0chtrwn\"},\"id\":\"/m/0ck96kz\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/m/0chtrwn\"},\"id\":\"/m/0cm3j23\",\"type\":\"/military/military_unit\"},{\"armed_force\":{\"id\":\"/m/0chtrwn\"},\"id\":\"/m/0cw8hb4\",\"type\":\"/military/military_unit\"}],\"status\":\"200 OK\",\"transaction_id\":\"cache;cache01.p01.sjc1:8101;2010-10-04T15:04:33Z;0007\"}"; - JSONObject options = SUT.createParserUIInitializationData( - job, new LinkedList(), "text/json"); - JSONArray path = new JSONArray(); - JSONUtilities.append(path, JsonImporter.ANONYMOUS); - JSONUtilities.append(path, "result"); - JSONUtilities.append(path, JsonImporter.ANONYMOUS); + ObjectNode options = SUT.createParserUIInitializationData( + job, new LinkedList<>(), "text/json"); + ArrayNode path = ParsingUtilities.mapper.createArrayNode(); + path.add(JsonImporter.ANONYMOUS); + path.add("result"); + path.add(JsonImporter.ANONYMOUS); JSONUtilities.safePut(options, "recordPath", path); RunTest(mqlOutput, options); @@ -404,11 +405,11 @@ public class JsonImporterTests extends ImporterTest { return sb.toString(); } - private static JSONObject getOptions(ImportingJob job, TreeImportingParserBase parser, String pathSelector) { - JSONObject options = parser.createParserUIInitializationData( - job, new LinkedList(), "text/json"); + private static ObjectNode getOptions(ImportingJob job, TreeImportingParserBase parser, String pathSelector) { + ObjectNode options = parser.createParserUIInitializationData( + job, new LinkedList<>(), "text/json"); - JSONArray path = new JSONArray(); + ArrayNode path = ParsingUtilities.mapper.createArrayNode(); JSONUtilities.append(path, JsonImporter.ANONYMOUS); JSONUtilities.append(path, pathSelector); @@ -507,7 +508,7 @@ public class JsonImporterTests extends ImporterTest { RunTest(testString, getOptions(job, SUT, "institutes")); } - private void RunTest(String testString, JSONObject options) { + private void RunTest(String testString, ObjectNode options) { try { inputStream = new ByteArrayInputStream( testString.getBytes( "UTF-8" ) ); } catch (UnsupportedEncodingException e1) { diff --git a/main/tests/server/src/com/google/refine/tests/importers/TsvCsvImporterTests.java b/main/tests/server/src/com/google/refine/tests/importers/TsvCsvImporterTests.java index 21d29db68..8481a98d6 100644 --- a/main/tests/server/src/com/google/refine/tests/importers/TsvCsvImporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/importers/TsvCsvImporterTests.java @@ -33,13 +33,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.tests.importers; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - import java.io.StringReader; -import org.json.JSONArray; -import org.json.JSONException; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.AfterMethod; @@ -49,6 +44,7 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import com.google.refine.importers.SeparatorBasedImporter; +import com.google.refine.util.ParsingUtilities; public class TsvCsvImporterTests extends ImporterTest { @@ -522,7 +518,7 @@ public class TsvCsvImporterTests extends ImporterTest { String input = "data1" + inputSeparator + "data2" + inputSeparator + "data3\n"; try { - prepareOptions(sep, -1, 0, 0, 1, false, false,"\"","[col1,col2,col3]"); + prepareOptions(sep, -1, 0, 0, 1, false, false,"\"","[\"col1\",\"col2\",\"col3\"]"); parseOneFile(SUT, new StringReader(input)); } catch (Exception e) { Assert.fail("Exception during file parse",e); @@ -554,8 +550,6 @@ public class TsvCsvImporterTests extends ImporterTest { Assert.assertEquals((String)project.rows.get(0).cells.get(0).value, "NDB_No"); Assert.assertEquals((String)project.rows.get(0).cells.get(1).value, "Shrt_Desc"); Assert.assertEquals((String)project.rows.get(0).cells.get(2).value, "Water"); - - verifyOptions(); } @Test @@ -577,8 +571,6 @@ public class TsvCsvImporterTests extends ImporterTest { Assert.assertEquals((String)project.rows.get(0).cells.get(1).value, "data2"); Assert.assertEquals((String)project.rows.get(0).cells.get(2).value, "data3"); Assert.assertEquals((String)project.rows.get(0).cells.get(3).value, "data4"); - - verifyOptions(); } //--helpers-- @@ -618,23 +610,6 @@ public class TsvCsvImporterTests extends ImporterTest { whenGetBooleanOption("guessCellValueTypes", options, guessValueType); whenGetBooleanOption("processQuotes", options, !ignoreQuotes); whenGetBooleanOption("storeBlankCellsAsNulls", options, true); - whenGetArrayOption("columnNames", options, new JSONArray(columnNames)); + whenGetArrayOption("columnNames", options, ParsingUtilities.evaluateJsonStringToArrayNode(columnNames)); } - - private void verifyOptions() { - try { - verify(options, times(1)).getString("separator"); - verify(options, times(1)).getInt("limit"); - verify(options, times(1)).getInt("skipDataLines"); - verify(options, times(1)).getInt("ignoreLines"); - verify(options, times(1)).getInt("headerLines"); - verify(options, times(1)).getBoolean("guessCellValueTypes"); - verify(options, times(1)).getBoolean("processQuotes"); - verify(options, times(1)).getBoolean("storeBlankCellsAsNulls"); - verify(options, times(1)).getJSONArray("columnNames"); - } catch (JSONException e) { - Assert.fail("JSON exception",e); - } - - } } diff --git a/main/tests/server/src/com/google/refine/tests/importers/XmlImporterTests.java b/main/tests/server/src/com/google/refine/tests/importers/XmlImporterTests.java index 6ca5f195d..40d35d882 100644 --- a/main/tests/server/src/com/google/refine/tests/importers/XmlImporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/importers/XmlImporterTests.java @@ -39,8 +39,6 @@ import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.LinkedList; -import org.json.JSONArray; -import org.json.JSONObject; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.AfterMethod; @@ -48,11 +46,14 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importers.XmlImporter; import com.google.refine.importers.tree.TreeImportingParserBase; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Row; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class XmlImporterTests extends ImporterTest { @@ -223,11 +224,11 @@ public class XmlImporterTests extends ImporterTest { return sb.toString(); } - public static JSONObject getOptions(ImportingJob job, TreeImportingParserBase parser) { - JSONObject options = parser.createParserUIInitializationData( - job, new LinkedList(), "text/json"); + public static ObjectNode getOptions(ImportingJob job, TreeImportingParserBase parser) { + ObjectNode options = parser.createParserUIInitializationData( + job, new LinkedList<>(), "text/json"); - JSONArray path = new JSONArray(); + ArrayNode path = ParsingUtilities.mapper.createArrayNode(); JSONUtilities.append(path, "library"); JSONUtilities.append(path, "book"); @@ -235,11 +236,11 @@ public class XmlImporterTests extends ImporterTest { return options; } - public static JSONObject getNestedOptions(ImportingJob job, TreeImportingParserBase parser) { - JSONObject options = parser.createParserUIInitializationData( - job, new LinkedList(), "text/json"); + public static ObjectNode getNestedOptions(ImportingJob job, TreeImportingParserBase parser) { + ObjectNode options = parser.createParserUIInitializationData( + job, new LinkedList<>(), "text/json"); - JSONArray path = new JSONArray(); + ArrayNode path = ParsingUtilities.mapper.createArrayNode(); JSONUtilities.append(path, "nest"); JSONUtilities.append(path, "nest2"); JSONUtilities.append(path, "library"); @@ -336,7 +337,7 @@ public class XmlImporterTests extends ImporterTest { RunTest(testString, getOptions(job, SUT)); } - private void RunTest(String testString, JSONObject options) { + private void RunTest(String testString, ObjectNode objectNode) { try { inputStream = new ByteArrayInputStream(testString.getBytes( "UTF-8" )); } catch (UnsupportedEncodingException e1) { @@ -344,7 +345,7 @@ public class XmlImporterTests extends ImporterTest { } try { - parseOneFile(SUT, inputStream, options); + parseOneFile(SUT, inputStream, objectNode); } catch (Exception e) { e.printStackTrace(); Assert.fail(); @@ -352,7 +353,7 @@ public class XmlImporterTests extends ImporterTest { } @Override - protected void parseOneFile(TreeImportingParserBase parser, InputStream inputStream, JSONObject options) { + protected void parseOneFile(TreeImportingParserBase parser, InputStream inputStream, ObjectNode options) { parseOneInputStream(parser, inputStream, options); } } diff --git a/main/tests/server/src/com/google/refine/tests/importing/ImportingUtilitiesTests.java b/main/tests/server/src/com/google/refine/tests/importing/ImportingUtilitiesTests.java index 7bcf306bc..0edd996d8 100644 --- a/main/tests/server/src/com/google/refine/tests/importing/ImportingUtilitiesTests.java +++ b/main/tests/server/src/com/google/refine/tests/importing/ImportingUtilitiesTests.java @@ -4,12 +4,12 @@ package com.google.refine.tests.importing; import java.io.InputStream; import java.util.LinkedList; -import org.json.JSONArray; -import org.json.JSONObject; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importers.XmlImporter; import com.google.refine.importers.tree.TreeImportingParserBase; import com.google.refine.importing.ImportingJob; @@ -18,6 +18,7 @@ import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.importers.ImporterTest; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class ImportingUtilitiesTests extends ImporterTest { @@ -30,7 +31,7 @@ public class ImportingUtilitiesTests extends ImporterTest { @Test public void createProjectMetadataTest() throws Exception { - JSONObject optionObj = new JSONObject( + ObjectNode optionObj = ParsingUtilities.evaluateJsonStringToObjectNode( "{\"projectName\":\"acme\",\"projectTags\":[],\"created\":\"2017-12-18T13:28:40.659\",\"modified\":\"2017-12-20T09:28:06.654\",\"creator\":\"\",\"contributors\":\"\",\"subject\":\"\",\"description\":\"\",\"rowCount\":50,\"customMetadata\":{}}"); ProjectMetadata pm = ImportingUtilities.createProjectMetadata(optionObj); Assert.assertEquals(pm.getName(), "acme"); @@ -60,14 +61,13 @@ public class ImportingUtilitiesTests extends ImporterTest { Assert.assertTrue(project.columnModel.getColumnByName("result - person - sexe").getType().equals("boolean")); } - private JSONObject getNestedOptions(ImportingJob job, TreeImportingParserBase parser) { - JSONObject options = parser.createParserUIInitializationData( - job, new LinkedList(), "text/json"); + private ObjectNode getNestedOptions(ImportingJob job, TreeImportingParserBase parser) { + ObjectNode options = parser.createParserUIInitializationData( + job, new LinkedList<>(), "text/json"); - JSONArray path = new JSONArray(); - JSONUtilities.append(path, "results"); - JSONUtilities.append(path, "result"); -// JSONUtilities.append(path, "object"); + ArrayNode path = ParsingUtilities.mapper.createArrayNode(); + path.add("results"); + path.add("result"); JSONUtilities.safePut(options, "recordPath", path); return options; diff --git a/main/tests/server/src/com/google/refine/tests/model/CacheTests.java b/main/tests/server/src/com/google/refine/tests/model/CacheTests.java index 4cf52dc52..cccacf68f 100644 --- a/main/tests/server/src/com/google/refine/tests/model/CacheTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/CacheTests.java @@ -53,7 +53,6 @@ import com.google.refine.model.Cell; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.operations.EngineDependentOperation; import com.google.refine.operations.row.RowRemovalOperation; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/model/ColumnTests.java b/main/tests/server/src/com/google/refine/tests/model/ColumnTests.java index 162483a24..1a5c95d6a 100644 --- a/main/tests/server/src/com/google/refine/tests/model/ColumnTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/ColumnTests.java @@ -1,5 +1,8 @@ package com.google.refine.tests.model; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import org.testng.annotations.Test; import com.google.refine.model.Column; @@ -8,8 +11,6 @@ import com.google.refine.model.recon.StandardReconConfig; import com.google.refine.tests.util.TestUtils; import edu.mit.simile.butterfly.ButterflyModule; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class ColumnTests { @Test diff --git a/main/tests/server/src/com/google/refine/tests/model/changes/MassChangeTests.java b/main/tests/server/src/com/google/refine/tests/model/changes/MassChangeTests.java index b0b631340..1bb8a6137 100644 --- a/main/tests/server/src/com/google/refine/tests/model/changes/MassChangeTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/changes/MassChangeTests.java @@ -12,12 +12,12 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import com.google.refine.history.Change; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.changes.CellAtRow; import com.google.refine.model.changes.ColumnAdditionChange; import com.google.refine.model.changes.MassChange; -import com.google.refine.history.Change; import com.google.refine.tests.RefineTest; public class MassChangeTests extends RefineTest { diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java index 0ebeadb82..a80bca841 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java @@ -43,7 +43,6 @@ import java.util.List; import java.util.Properties; import org.json.JSONException; -import org.json.JSONObject; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.AfterMethod; @@ -51,6 +50,7 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.ProjectManager; import com.google.refine.RefineServlet; import com.google.refine.importers.SeparatorBasedImporter; @@ -75,7 +75,7 @@ public class KeyValueColumnizeTests extends RefineTest { private RefineServlet servlet; private Project project; private ProjectMetadata pm; - private JSONObject options; + private ObjectNode options; private ImportingJob job; private SeparatorBasedImporter importer; @@ -95,7 +95,7 @@ public class KeyValueColumnizeTests extends RefineTest { pm = new ProjectMetadata(); pm.setName("KeyValueColumnize test"); ProjectManager.singleton.registerProject(project, pm); - options = mock(JSONObject.class); + options = mock(ObjectNode.class); OperationRegistry.registerOperation(getCoreModule(), "key-value-columnize", KeyValueColumnizeOperation.class); ImportingManager.initialize(servlet); diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java index d604fedc3..629e1eafb 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/MassOperationTests.java @@ -8,7 +8,6 @@ import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; import com.fasterxml.jackson.core.type.TypeReference; - import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.cell.MassEditOperation; import com.google.refine.operations.cell.MassEditOperation.Edit; diff --git a/main/tests/server/src/com/google/refine/tests/process/QuickHistoryEntryProcessTests.java b/main/tests/server/src/com/google/refine/tests/process/QuickHistoryEntryProcessTests.java index 538eb3b01..238c35298 100644 --- a/main/tests/server/src/com/google/refine/tests/process/QuickHistoryEntryProcessTests.java +++ b/main/tests/server/src/com/google/refine/tests/process/QuickHistoryEntryProcessTests.java @@ -1,13 +1,14 @@ package com.google.refine.tests.process; import static org.mockito.Mockito.mock; + import org.testng.annotations.Test; import com.google.refine.history.HistoryEntry; import com.google.refine.model.Project; +import com.google.refine.process.Process; import com.google.refine.process.QuickHistoryEntryProcess; import com.google.refine.tests.util.TestUtils; -import com.google.refine.process.Process; public class QuickHistoryEntryProcessTests { public static class QuickHistoryEntryProcessStub extends QuickHistoryEntryProcess { diff --git a/main/tests/server/src/com/google/refine/tests/util/PatternSyntaxExceptionParserTests.java b/main/tests/server/src/com/google/refine/tests/util/PatternSyntaxExceptionParserTests.java index f42dcabc0..b87e32e40 100644 --- a/main/tests/server/src/com/google/refine/tests/util/PatternSyntaxExceptionParserTests.java +++ b/main/tests/server/src/com/google/refine/tests/util/PatternSyntaxExceptionParserTests.java @@ -33,14 +33,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.tests.util; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - import com.google.refine.tests.RefineTest; import com.google.refine.util.PatternSyntaxExceptionParser; diff --git a/main/tests/server/src/com/google/refine/tests/util/TestUtils.java b/main/tests/server/src/com/google/refine/tests/util/TestUtils.java index f35f20184..64bc6bd8d 100644 --- a/main/tests/server/src/com/google/refine/tests/util/TestUtils.java +++ b/main/tests/server/src/com/google/refine/tests/util/TestUtils.java @@ -17,7 +17,6 @@ import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.SerializationFeature; - import com.google.refine.util.ParsingUtilities; From 1eaadc30b72d0655ad3d93a00e3fcdbd7ea45b4e Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 5 Nov 2018 16:43:20 +0000 Subject: [PATCH 103/164] Migrate database extension importers to Jackson --- .../extension/database/DatabaseImportController.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java b/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java index 1fce41bc7..1f6c56c73 100644 --- a/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java +++ b/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java @@ -45,7 +45,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.core.JsonGenerator; - +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.ProjectManager; import com.google.refine.RefineServlet; import com.google.refine.commands.HttpUtilities; @@ -192,7 +192,7 @@ public class DatabaseImportController implements ImportingController { job.updating = true; try { - JSONObject optionObj = ParsingUtilities.evaluateJsonStringToObject( + ObjectNode optionObj = ParsingUtilities.evaluateJsonStringToObjectNode( request.getParameter("options")); List exceptions = new LinkedList(); @@ -265,7 +265,7 @@ public class DatabaseImportController implements ImportingController { ProjectMetadata metadata, final ImportingJob job, int limit, - JSONObject options, + ObjectNode options, List exceptions) throws DatabaseServiceException{ @@ -323,7 +323,7 @@ public class DatabaseImportController implements ImportingController { job.updating = true; try { - final JSONObject optionObj = ParsingUtilities.evaluateJsonStringToObject( + final ObjectNode optionObj = ParsingUtilities.evaluateJsonStringToObjectNode( request.getParameter("options")); final List exceptions = new LinkedList(); @@ -394,7 +394,7 @@ public class DatabaseImportController implements ImportingController { ProjectMetadata metadata, final ImportingJob job, int limit, - JSONObject options, + ObjectNode options, List exceptions) throws DatabaseServiceException{ From 5b153dcfba83010c4ae79f9ce0785fb09ac2929b Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 5 Nov 2018 16:47:18 +0000 Subject: [PATCH 104/164] Migrate gdata extension importers to Jackson --- .../refine/extension/gdata/DeAuthorizeCommand.java | 1 - .../refine/extension/gdata/FusionTableImporter.java | 8 +++----- .../refine/extension/gdata/FusionTableSerializer.java | 3 --- .../com/google/refine/extension/gdata/GDataImporter.java | 9 ++++----- .../refine/extension/gdata/GDataImportingController.java | 7 +++---- .../refine/extension/gdata/GoogleAPIExtension.java | 1 - .../refine/extension/gdata/SpreadsheetSerializer.java | 3 --- .../com/google/refine/extension/gdata/UploadCommand.java | 4 +--- 8 files changed, 11 insertions(+), 25 deletions(-) diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/DeAuthorizeCommand.java b/extensions/gdata/src/com/google/refine/extension/gdata/DeAuthorizeCommand.java index 7a1dd1ead..9ea0a706b 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/DeAuthorizeCommand.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/DeAuthorizeCommand.java @@ -40,7 +40,6 @@ import com.google.api.client.http.HttpRequestFactory; import com.google.api.client.http.HttpResponse; import com.google.api.client.http.HttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; - import com.google.refine.commands.Command; public class DeAuthorizeCommand extends Command { diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableImporter.java b/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableImporter.java index c56f9d27e..2d6fd8633 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableImporter.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableImporter.java @@ -32,13 +32,11 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.json.JSONObject; - +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.api.services.fusiontables.Fusiontables; import com.google.api.services.fusiontables.model.Column; import com.google.api.services.fusiontables.model.Sqlresponse; import com.google.api.services.fusiontables.model.Table; - import com.google.refine.importers.TabularImportingParserBase; import com.google.refine.importers.TabularImportingParserBase.TableDataReader; import com.google.refine.importing.ImportingJob; @@ -60,7 +58,7 @@ public class FusionTableImporter { ProjectMetadata metadata, final ImportingJob job, int limit, - JSONObject options, + ObjectNode options, List exceptions) { Fusiontables service = FusionTableHandler.getFusionTablesService(token); @@ -206,7 +204,7 @@ public class FusionTableImporter { ProjectMetadata metadata, final ImportingJob job, int limit, - JSONObject options, + ObjectNode options, List exceptions) { String docUrlString = JSONUtilities.getString(options, "docUrl", null); diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableSerializer.java b/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableSerializer.java index 230d836be..86e6cef90 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableSerializer.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableSerializer.java @@ -5,13 +5,10 @@ import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.databind.JsonNode; - import com.google.api.client.http.AbstractInputStreamContent; import com.google.api.client.http.ByteArrayContent; import com.google.api.client.http.HttpResponseException; import com.google.api.services.fusiontables.Fusiontables; - -import com.google.refine.exporters.CustomizableTabularExporterConfiguration; import com.google.refine.exporters.TabularSerializer; final class FusionTableSerializer implements TabularSerializer { diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/GDataImporter.java b/extensions/gdata/src/com/google/refine/extension/gdata/GDataImporter.java index 05598e737..714c66167 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/GDataImporter.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/GDataImporter.java @@ -6,15 +6,14 @@ import java.net.URL; import java.util.List; import org.apache.commons.lang3.exception.ExceptionUtils; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.api.services.sheets.v4.Sheets; import com.google.api.services.sheets.v4.model.Sheet; import com.google.api.services.sheets.v4.model.Spreadsheet; import com.google.api.services.sheets.v4.model.ValueRange; - import com.google.refine.importers.TabularImportingParserBase; import com.google.refine.importers.TabularImportingParserBase.TableDataReader; import com.google.refine.importing.ImportingJob; @@ -31,7 +30,7 @@ public class GDataImporter { ProjectMetadata metadata, final ImportingJob job, int limit, - JSONObject options, + ObjectNode options, List exceptions) throws IOException { String docType = JSONUtilities.getString(options, "docType", null); @@ -64,7 +63,7 @@ public class GDataImporter { ProjectMetadata metadata, final ImportingJob job, int limit, - JSONObject options, + ObjectNode options, List exceptions) { String docUrlString = JSONUtilities.getString(options, "docUrl", null); @@ -100,7 +99,7 @@ public class GDataImporter { URL docURL, int worksheetIndex, int limit, - JSONObject options, + ObjectNode options, List exceptions) { try { diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java b/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java index 8b243bbe6..8a35d4612 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java @@ -18,7 +18,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.core.JsonGenerator; - +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.api.services.drive.Drive; import com.google.api.services.drive.model.File; import com.google.api.services.drive.model.FileList; @@ -29,7 +29,6 @@ import com.google.api.services.fusiontables.model.TableList; import com.google.api.services.sheets.v4.Sheets; import com.google.api.services.sheets.v4.model.Sheet; import com.google.api.services.sheets.v4.model.Spreadsheet; - import com.google.refine.ProjectManager; import com.google.refine.RefineServlet; import com.google.refine.commands.HttpUtilities; @@ -237,7 +236,7 @@ public class GDataImportingController implements ImportingController { job.updating = true; try { - JSONObject optionObj = ParsingUtilities.evaluateJsonStringToObject( + ObjectNode optionObj = ParsingUtilities.evaluateJsonStringToObjectNode( request.getParameter("options")); List exceptions = new LinkedList(); @@ -301,7 +300,7 @@ public class GDataImportingController implements ImportingController { job.updating = true; try { - final JSONObject optionObj = ParsingUtilities.evaluateJsonStringToObject( + final ObjectNode optionObj = ParsingUtilities.evaluateJsonStringToObjectNode( request.getParameter("options")); final List exceptions = new LinkedList(); diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/GoogleAPIExtension.java b/extensions/gdata/src/com/google/refine/extension/gdata/GoogleAPIExtension.java index dd68b505a..dc9d707e2 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/GoogleAPIExtension.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/GoogleAPIExtension.java @@ -25,7 +25,6 @@ import com.google.api.services.drive.DriveScopes; import com.google.api.services.fusiontables.FusiontablesScopes; import com.google.api.services.sheets.v4.Sheets; import com.google.api.services.sheets.v4.SheetsScopes; - import com.google.refine.ProjectManager; import com.google.refine.preference.PreferenceStore; import com.google.refine.util.ParsingUtilities; diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/SpreadsheetSerializer.java b/extensions/gdata/src/com/google/refine/extension/gdata/SpreadsheetSerializer.java index 1aa6300e1..769793dcd 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/SpreadsheetSerializer.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/SpreadsheetSerializer.java @@ -10,7 +10,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.JsonNode; - import com.google.api.services.sheets.v4.Sheets; import com.google.api.services.sheets.v4.model.AppendCellsRequest; import com.google.api.services.sheets.v4.model.BatchUpdateSpreadsheetRequest; @@ -18,8 +17,6 @@ import com.google.api.services.sheets.v4.model.BatchUpdateSpreadsheetResponse; import com.google.api.services.sheets.v4.model.ExtendedValue; import com.google.api.services.sheets.v4.model.Request; import com.google.api.services.sheets.v4.model.RowData; - -import com.google.refine.exporters.CustomizableTabularExporterConfiguration; import com.google.refine.exporters.TabularSerializer; final class SpreadsheetSerializer implements TabularSerializer { diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/UploadCommand.java b/extensions/gdata/src/com/google/refine/extension/gdata/UploadCommand.java index f1879065a..e2272fecd 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/UploadCommand.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/UploadCommand.java @@ -14,19 +14,17 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.commons.codec.binary.Base64; import com.fasterxml.jackson.core.JsonGenerator; - import com.google.api.client.http.FileContent; import com.google.api.services.drive.Drive; import com.google.api.services.drive.model.File; import com.google.api.services.drive.model.File.ContentHints; import com.google.api.services.drive.model.File.ContentHints.Thumbnail; - import com.google.refine.ProjectManager; import com.google.refine.browsing.Engine; import com.google.refine.commands.Command; From ff57ff172e8651f8b1849307f9a7191a4fdc6be3 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 5 Nov 2018 17:03:06 +0000 Subject: [PATCH 105/164] Migrate pc-axis extension importers to Jackson --- .../src/com/google/refine/pcaxis/PCAxisImporter.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/extensions/pc-axis/src/com/google/refine/pcaxis/PCAxisImporter.java b/extensions/pc-axis/src/com/google/refine/pcaxis/PCAxisImporter.java index 8a41c27f9..504f53d59 100644 --- a/extensions/pc-axis/src/com/google/refine/pcaxis/PCAxisImporter.java +++ b/extensions/pc-axis/src/com/google/refine/pcaxis/PCAxisImporter.java @@ -37,15 +37,16 @@ import java.io.LineNumberReader; import java.io.Reader; import java.util.List; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importers.TabularImportingParserBase; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Project; import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; public class PCAxisImporter extends TabularImportingParserBase { static final Logger logger = LoggerFactory.getLogger(PCAxisImporter.class); @@ -55,9 +56,9 @@ public class PCAxisImporter extends TabularImportingParserBase { } @Override - public JSONObject createParserUIInitializationData( - ImportingJob job, List fileRecords, String format) { - JSONObject options = new JSONObject(); + public ObjectNode createParserUIInitializationData( + ImportingJob job, List fileRecords, String format) { + ObjectNode options = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(options, "includeFileSources", fileRecords.size() > 1); JSONUtilities.safePut(options, "skipDataLines", 0); JSONUtilities.safePut(options, "limit", -1); @@ -72,7 +73,7 @@ public class PCAxisImporter extends TabularImportingParserBase { String fileSource, Reader reader, int limit, - JSONObject options, + ObjectNode options, List exceptions ) { LineNumberReader lnReader = new LineNumberReader(reader); From cb2bbbf80189cbc8b5b6594e137180c81581b6f2 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 5 Nov 2018 17:03:28 +0000 Subject: [PATCH 106/164] Cleanup --- main/src/com/google/refine/preference/PreferenceStore.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/main/src/com/google/refine/preference/PreferenceStore.java b/main/src/com/google/refine/preference/PreferenceStore.java index 69b3bb3fd..82e61a152 100644 --- a/main/src/com/google/refine/preference/PreferenceStore.java +++ b/main/src/com/google/refine/preference/PreferenceStore.java @@ -123,7 +123,6 @@ public class PreferenceStore { Iterator i = entries.fieldNames(); while (i.hasNext()) { String key = i.next(); - System.out.println(key); if (entries.get(key) != null) { JsonNode o = entries.get(key); Object loaded = loadObject(o); @@ -140,8 +139,6 @@ public class PreferenceStore { } static public Object loadObject(JsonNode o) { - System.out.println("loading"); - System.out.println(o.toString()); try { if (o instanceof ObjectNode) { ObjectNode obj2 = (ObjectNode) o; From bca832ed0353ad717a6c170a4fbf5603f1eda3ab Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 5 Nov 2018 17:03:46 +0000 Subject: [PATCH 107/164] Enable legacy JSON parsing for compatibility with tests --- main/src/com/google/refine/util/ParsingUtilities.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/main/src/com/google/refine/util/ParsingUtilities.java b/main/src/com/google/refine/util/ParsingUtilities.java index 9717c880b..cb1ede0f4 100644 --- a/main/src/com/google/refine/util/ParsingUtilities.java +++ b/main/src/com/google/refine/util/ParsingUtilities.java @@ -59,6 +59,7 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; +import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.DeserializationFeature; @@ -86,6 +87,7 @@ public class ParsingUtilities { mapper.registerModule(module); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); } public static final FilterProvider defaultFilters = new SimpleFilterProvider() From ebfa59119033164bd01e55700bc9f78bc0d05803 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 5 Nov 2018 17:14:25 +0000 Subject: [PATCH 108/164] Fix WikibaseSchemaTest --- .../org/openrefine/wikidata/schema/WikibaseSchemaTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/extensions/wikidata/tests/src/org/openrefine/wikidata/schema/WikibaseSchemaTest.java b/extensions/wikidata/tests/src/org/openrefine/wikidata/schema/WikibaseSchemaTest.java index 42ba06c8d..065136cb7 100644 --- a/extensions/wikidata/tests/src/org/openrefine/wikidata/schema/WikibaseSchemaTest.java +++ b/extensions/wikidata/tests/src/org/openrefine/wikidata/schema/WikibaseSchemaTest.java @@ -49,8 +49,6 @@ import org.wikidata.wdtk.datamodel.interfaces.StatementRank; import org.wikidata.wdtk.datamodel.interfaces.StringValue; import org.wikidata.wdtk.datamodel.interfaces.TimeValue; -import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; - import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.model.Project; @@ -100,7 +98,7 @@ public class WikibaseSchemaTest extends RefineTest { throws JSONException, IOException { JSONObject serialized = TestingData.jsonFromFile("schema/history_of_medicine.json"); WikibaseSchema parsed = WikibaseSchema.reconstruct(serialized); - TestUtils.isSerializedTo(parsed, TestingData.jsonFromFile("data/schema/history_of_medicine_normalized.json").toString()); + TestUtils.isSerializedTo(parsed, TestingData.jsonFromFile("schema/history_of_medicine_normalized.json").toString()); } @Test From ccb1ac84c11232aab21bc4eb0c6049dc4837aa50 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Thu, 15 Nov 2018 16:55:26 +0000 Subject: [PATCH 109/164] Migrate GREL AST to Jackson --- .../refine/grel/ast/FieldAccessorExpr.java | 29 +++++++++++++------ .../google/refine/grel/ast/LiteralExpr.java | 5 ++-- .../tests/grel/ast/LiteralExprTest.java | 21 ++++++++++++++ 3 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 main/tests/server/src/com/google/refine/tests/grel/ast/LiteralExprTest.java diff --git a/main/src/com/google/refine/grel/ast/FieldAccessorExpr.java b/main/src/com/google/refine/grel/ast/FieldAccessorExpr.java index 9677106ea..73f45c7c1 100644 --- a/main/src/com/google/refine/grel/ast/FieldAccessorExpr.java +++ b/main/src/com/google/refine/grel/ast/FieldAccessorExpr.java @@ -35,9 +35,9 @@ package com.google.refine.grel.ast; import java.util.Properties; -import org.json.JSONException; -import org.json.JSONObject; - +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.Lists; import com.google.refine.expr.Evaluable; import com.google.refine.expr.ExpressionUtils; import com.google.refine.expr.HasFields; @@ -65,12 +65,23 @@ public class FieldAccessorExpr implements Evaluable { return null; } else if (o instanceof HasFields) { return ((HasFields) o).getField(_fieldName, bindings); - } else if (o instanceof JSONObject) { - try { - return ((JSONObject) o).get(_fieldName); - } catch (JSONException e) { - return null; - } + } else if (o instanceof ObjectNode) { + JsonNode value = ((ObjectNode) o).get(_fieldName); + if (value.isArray()) { + return Lists.newArrayList(value.elements()); + } else if (value.isBigDecimal() || value.isDouble() || value.isFloat()) { + return value.asDouble(); + } else if (value.isBigInteger() || value.isInt()) { + return value.asLong(); + } else if (value.isBinary() || value.isTextual()) { + return value.asText(); + } else if (value.isBoolean()) { + return value.asBoolean(); + } else if (value.isNull()) { + return null; + } else { + return null; + } } else { return null; } diff --git a/main/src/com/google/refine/grel/ast/LiteralExpr.java b/main/src/com/google/refine/grel/ast/LiteralExpr.java index 8c04ade8f..d6ac35748 100644 --- a/main/src/com/google/refine/grel/ast/LiteralExpr.java +++ b/main/src/com/google/refine/grel/ast/LiteralExpr.java @@ -35,8 +35,7 @@ package com.google.refine.grel.ast; import java.util.Properties; -import org.json.JSONObject; - +import com.fasterxml.jackson.databind.node.TextNode; import com.google.refine.expr.Evaluable; /** @@ -56,6 +55,6 @@ public class LiteralExpr implements Evaluable { @Override public String toString() { - return _value instanceof String ? JSONObject.quote((String) _value) : _value.toString(); + return _value instanceof String ? new TextNode((String) _value).toString() : _value.toString(); } } diff --git a/main/tests/server/src/com/google/refine/tests/grel/ast/LiteralExprTest.java b/main/tests/server/src/com/google/refine/tests/grel/ast/LiteralExprTest.java new file mode 100644 index 000000000..789ce9ee9 --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/grel/ast/LiteralExprTest.java @@ -0,0 +1,21 @@ +package com.google.refine.tests.grel.ast; + +import static org.testng.Assert.assertEquals; + +import org.testng.annotations.Test; + +import com.google.refine.grel.ast.LiteralExpr; + +public class LiteralExprTest { + @Test + public void intLiteralToString() { + LiteralExpr expr = new LiteralExpr(42); + assertEquals("42", expr.toString()); + } + + @Test + public void stringLiteralToString() { + LiteralExpr expr = new LiteralExpr("string with \"\\backslash\""); + assertEquals("\"string with \\\"\\\\backslash\\\"\"", expr.toString()); + } +} From 4a067cb110a9693668364055d423bd9cb1d0413f Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Thu, 15 Nov 2018 17:39:11 +0000 Subject: [PATCH 110/164] Migrate FileProjectManager to Jackson --- .../google/refine/io/FileProjectManager.java | 102 ++++++++---------- 1 file changed, 44 insertions(+), 58 deletions(-) diff --git a/main/src/com/google/refine/io/FileProjectManager.java b/main/src/com/google/refine/io/FileProjectManager.java index 46875e02a..d342229b7 100644 --- a/main/src/com/google/refine/io/FileProjectManager.java +++ b/main/src/com/google/refine/io/FileProjectManager.java @@ -36,12 +36,12 @@ package com.google.refine.io; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.HashMap; +import java.util.List; import java.util.Map.Entry; import java.util.Set; import java.util.zip.GZIPInputStream; @@ -50,10 +50,7 @@ import java.util.zip.GZIPOutputStream; import org.apache.tools.tar.TarEntry; import org.apache.tools.tar.TarInputStream; import org.apache.tools.tar.TarOutputStream; -import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONTokener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -377,60 +374,11 @@ public class FileProjectManager extends ProjectManager { boolean found = false; - if (file.exists() || file.canRead()) { - FileReader reader = null; - try { - reader = new FileReader(file); - JSONTokener tokener = new JSONTokener(reader); - JSONObject obj = (JSONObject) tokener.nextValue(); - - // load global preferences firstly - if (obj.has("preferences") && !obj.isNull("preferences")) { - _preferenceStore = ParsingUtilities.mapper.readValue(obj.getJSONObject("preferences").toString(), PreferenceStore.class); - } - - JSONArray a = obj.getJSONArray("projectIDs"); - int count = a.length(); - for (int i = 0; i < count; i++) { - long id = a.getLong(i); - - File projectDir = getProjectDir(id); - ProjectMetadata metadata = ProjectMetadataUtilities.load(projectDir); - - mergeEmptyUserMetadata(metadata); - - _projectsMetadata.put(id, metadata); - - if (metadata != null && metadata.getTags() != null) { - for (String tag : metadata.getTags()) { - if (_projectsTags.containsKey(tag)) { - _projectsTags.put(tag, _projectsTags.get(tag) + 1); - } else { - _projectsTags.put(tag, 1); - } - } - } - } - - if (obj.has("expressions") && !obj.isNull("expressions")) { // backward compatibility - TopList newExpressions = ParsingUtilities.mapper.readValue(obj.getJSONArray("expressions").toString(), TopList.class); - this._preferenceStore.put("scripting.expressions", newExpressions); - } - - found = true; - } catch (JSONException e) { - logger.warn("Error reading file", e); - } catch (IOException e) { - logger.warn("Error reading file", e); - } finally { - try { - if (reader != null) { - reader.close(); - } - } catch (IOException e) { - logger.warn("Exception closing file",e); - } - } + try { + ParsingUtilities.mapper.readerForUpdating(this).readValue(file); + found = true; + } catch(IOException e) { + logger.warn(e.toString()); } return found; @@ -490,4 +438,42 @@ public class FileProjectManager extends ProjectManager { public Set getProjectIds() { return _projectsMetadata.keySet(); } + + @JsonProperty("projectIDs") + protected void loadProjects(List projectIDs) { + for (Long id : projectIDs) { + + File projectDir = getProjectDir(id); + ProjectMetadata metadata = ProjectMetadataUtilities.load(projectDir); + + mergeEmptyUserMetadata(metadata); + + _projectsMetadata.put(id, metadata); + + if (metadata != null && metadata.getTags() != null) { + for (String tag : metadata.getTags()) { + if (_projectsTags.containsKey(tag)) { + _projectsTags.put(tag, _projectsTags.get(tag) + 1); + } else { + _projectsTags.put(tag, 1); + } + } + } + } + } + + @JsonProperty("preferences") + protected void setPreferences(PreferenceStore preferences) { + if(preferences != null) { + _preferenceStore = preferences; + } + } + + // backwards compatibility + @JsonProperty("expressions") + protected void setExpressions(TopList newExpressions) { + if (newExpressions != null) { + _preferenceStore.put("scripting.expressions", newExpressions); + } + } } \ No newline at end of file From 62190d36c029a50a10d46f0a8186e547f9cf12fd Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 16 Nov 2018 10:50:06 +0000 Subject: [PATCH 111/164] Start to migrate ProjectMetadata to Jackson --- .../model/metadata/AbstractMetadata.java | 9 +- .../refine/model/metadata/IMetadata.java | 1 - .../model/metadata/ProjectMetadata.java | 161 ++++++------------ 3 files changed, 56 insertions(+), 115 deletions(-) diff --git a/main/src/com/google/refine/model/metadata/AbstractMetadata.java b/main/src/com/google/refine/model/metadata/AbstractMetadata.java index 5433cdbd0..aab2f94ec 100644 --- a/main/src/com/google/refine/model/metadata/AbstractMetadata.java +++ b/main/src/com/google/refine/model/metadata/AbstractMetadata.java @@ -1,6 +1,7 @@ package com.google.refine.model.metadata; import java.io.File; +import java.io.IOException; import java.time.LocalDateTime; import org.apache.commons.beanutils.PropertyUtils; @@ -8,6 +9,7 @@ import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.refine.util.ParsingUtilities; public abstract class AbstractMetadata implements IMetadata { @JsonIgnore @@ -26,9 +28,10 @@ public abstract class AbstractMetadata implements IMetadata { public void setFormatName(MetadataFormat formatName) { this.formatName = formatName; } - - @Override - public abstract void loadFromJSON(JSONObject obj); + + public void loadFromJSON(String obj) throws IOException { + ParsingUtilities.mapper.readerForUpdating(this).readValue(obj); + } @Override public abstract void loadFromFile(File metadataFile); diff --git a/main/src/com/google/refine/model/metadata/IMetadata.java b/main/src/com/google/refine/model/metadata/IMetadata.java index 8f5f863fd..dc2e36006 100644 --- a/main/src/com/google/refine/model/metadata/IMetadata.java +++ b/main/src/com/google/refine/model/metadata/IMetadata.java @@ -11,7 +11,6 @@ import org.json.JSONObject; * Interface to import/export metadata */ public interface IMetadata { - public void loadFromJSON(JSONObject obj); public void loadFromFile(File metadataFile); diff --git a/main/src/com/google/refine/model/metadata/ProjectMetadata.java b/main/src/com/google/refine/model/metadata/ProjectMetadata.java index 23dc2f253..21770e1af 100644 --- a/main/src/com/google/refine/model/metadata/ProjectMetadata.java +++ b/main/src/com/google/refine/model/metadata/ProjectMetadata.java @@ -48,6 +48,7 @@ import java.util.Map; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.json.JSONArray; @@ -57,12 +58,15 @@ import org.json.JSONTokener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.annotation.JsonView; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.ProjectManager; import com.google.refine.preference.PreferenceStore; @@ -77,7 +81,7 @@ public class ProjectMetadata extends AbstractMetadata { final public static String OLD_FILE_NAME = "metadata.old.json"; @JsonProperty("created") - private final LocalDateTime _created; + private LocalDateTime _created; @JsonProperty("name") private String _name = ""; @JsonProperty("password") @@ -93,7 +97,8 @@ public class ProjectMetadata extends AbstractMetadata { @JsonProperty("rowCount") private int _rowCount; // user metadata - private JSONArray _userMetadata = new JSONArray(); + @JsonIgnore + private ArrayNode _userMetadata = ParsingUtilities.mapper.createArrayNode(); // _tags maps to keywords of the data package metadata @JsonProperty("tags") @@ -108,9 +113,10 @@ public class ProjectMetadata extends AbstractMetadata { private String _description = ""; // free form of comment // import options is an array for 1-n data sources - private JSONArray _importOptionMetadata = new JSONArray(); + @JsonIgnore + private ArrayNode _importOptionMetadata = ParsingUtilities.mapper.createArrayNode(); - @JsonUnwrapped + @JsonProperty("customMetadata") private Map _customMetadata = new HashMap(); @JsonProperty("preferences") @JsonView(JsonViews.SaveMode.class) @@ -128,24 +134,40 @@ public class ProjectMetadata extends AbstractMetadata { @JsonProperty("version") private String version = ""; - @JsonProperty("userMetadata") - @JsonRawValue + @JsonProperty(PreferenceStore.USER_METADATA_KEY) @JsonInclude(Include.NON_NULL) - public String getJsonUserMetadata() { - if (_userMetadata.length() > 0) { - return _userMetadata.toString(); + public ArrayNode getJsonUserMetadata() { + if (_userMetadata.size() > 0) { + return _userMetadata; + } + return null; + } + + @JsonProperty(PreferenceStore.USER_METADATA_KEY) + protected void setUserMetadataJson(ArrayNode json) { + _userMetadata = json; + } + + @JsonProperty("importOptionMetadata") + @JsonInclude(Include.NON_NULL) + public ArrayNode getJsonImportOptionMetadata() { + if (_importOptionMetadata.size() > 0) { + return _importOptionMetadata; } return null; } @JsonProperty("importOptionMetadata") - @JsonRawValue - @JsonInclude(Include.NON_NULL) - public String getJsonImportOptionMetadata() { - if (_importOptionMetadata.length() > 0) { - return _importOptionMetadata.toString(); - } - return null; + public void setImportOptionMetadataJson(ArrayNode options) { + _importOptionMetadata = options; + // this field should always be present so we can update the last updated time here + this.written = LocalDateTime.now(); + } + + // backwards compatibility + @JsonProperty("expressions") + protected void setExpressions(TopList expressions) { + this._preferenceStore.put("scripting.expressions", expressions); } private final static Logger logger = LoggerFactory.getLogger("project_metadata"); @@ -180,91 +202,6 @@ public class ProjectMetadata extends AbstractMetadata { return null; } - public void loadFromJSON(JSONObject obj) { - extractModifiedLocalTime(obj); - - this._name = JSONUtilities.getString(obj, "name", ""); - this._password = JSONUtilities.getString(obj, "password", ""); - - this._encoding = JSONUtilities.getString(obj, "encoding", ""); - this._encodingConfidence = JSONUtilities.getInt(obj, "encodingConfidence", 0); - - this._creator = JSONUtilities.getString(obj, "creator", ""); - this._contributors = JSONUtilities.getString(obj, "contributors", ""); - this._subject = JSONUtilities.getString(obj, "subject", ""); - this._description = JSONUtilities.getString(obj, "description", ""); - this._rowCount = JSONUtilities.getInt(obj, "rowCount", 0); - - this.title = JSONUtilities.getString(obj, "title", ""); - this.homepage = JSONUtilities.getString(obj, "homepage", ""); - this.image = JSONUtilities.getString(obj, "image", ""); - this.license = JSONUtilities.getString(obj, "license", ""); - this.version = JSONUtilities.getString(obj, "version", ""); - - this._tags = JSONUtilities.getStringArray(obj, "tags"); - - if (obj.has("preferences") && !obj.isNull("preferences")) { - try { - this._preferenceStore = ParsingUtilities.mapper.readValue(obj.getJSONObject("preferences").toString(), PreferenceStore.class); - } catch (IOException e) { - logger.error(ExceptionUtils.getStackTrace(e)); - } - } - - if (obj.has("expressions") && !obj.isNull("expressions")) { // backward compatibility - try { - TopList newExpressions = ParsingUtilities.mapper.readValue(obj.getJSONArray("expressions").toString(), TopList.class); - this._preferenceStore.put("scripting.expressions", newExpressions); - } catch (IOException e) { - logger.error(ExceptionUtils.getStackTrace(e)); - } - } - - if (obj.has("customMetadata") && !obj.isNull("customMetadata")) { - try { - JSONObject obj2 = obj.getJSONObject("customMetadata"); - - Iterator keys = obj2.keys(); - while (keys.hasNext()) { - String key = keys.next(); - Object value = obj2.get(key); - if (value != null && value instanceof Serializable) { - this._customMetadata.put(key, (Serializable) value); - } - } - } catch (JSONException e) { - logger.error(ExceptionUtils.getStackTrace(e)); - } - } - - if (obj.has("importOptionMetadata") && !obj.isNull("importOptionMetadata")) { - try { - JSONArray jsonArray = obj.getJSONArray("importOptionMetadata"); - this._importOptionMetadata = jsonArray; - } catch (JSONException e) { - logger.error(ExceptionUtils.getStackTrace(e)); - } - } - - if (obj.has(PreferenceStore.USER_METADATA_KEY) && !obj.isNull(PreferenceStore.USER_METADATA_KEY)) { - try { - JSONArray jsonArray = obj.getJSONArray(PreferenceStore.USER_METADATA_KEY); - this._userMetadata = jsonArray; - } catch (JSONException e) { - logger.error(ExceptionUtils.getStackTrace(e)); - } - } - - this.written = LocalDateTime.now(); // Mark it as not needing writing until modified - - } - - private void extractModifiedLocalTime(JSONObject obj) { - String modified = JSONUtilities.getString(obj, "modified", LocalDateTime.now().toString()); - - this._modified = ParsingUtilities.stringToLocalDate(modified); - } - static protected void preparePreferenceStore(PreferenceStore ps) { ProjectManager.preparePreferenceStore(ps); // Any project specific preferences? @@ -353,17 +290,19 @@ public class ProjectMetadata extends AbstractMetadata { updateModified(); } - public JSONArray getImportOptionMetadata() { + @JsonIgnore + public ArrayNode getImportOptionMetadata() { return _importOptionMetadata; } - public void setImportOptionMetadata(JSONArray jsonArray) { + @JsonIgnore + public void setImportOptionMetadata(ArrayNode jsonArray) { _importOptionMetadata = jsonArray; updateModified(); } public void appendImportOptionMetadata(ObjectNode options) { - _importOptionMetadata.put(options); + _importOptionMetadata.add(options); updateModified(); } @@ -477,20 +416,20 @@ public class ProjectMetadata extends AbstractMetadata { updateModified(); } - public JSONArray getUserMetadata() { + public ArrayNode getUserMetadata() { return _userMetadata; } - public void setUserMetadata(JSONArray userMetadata) { + public void setUserMetadata(ArrayNode userMetadata) { this._userMetadata = userMetadata; } private void updateUserMetadata(String metaName, String valueString) { - for (int i = 0; i < _userMetadata.length(); i++) { + for (int i = 0; i < _userMetadata.size(); i++) { try { - JSONObject obj = _userMetadata.getJSONObject(i); - if (obj.getString("name").equals(metaName)) { - obj.put("value", valueString); + JsonNode obj = _userMetadata.get(i); + if (obj.get("name").asText("").equals(metaName)) { + ((ObjectNode) obj).put("value", valueString); } } catch (JSONException e) { logger.error(ExceptionUtils.getStackTrace(e)); @@ -530,7 +469,7 @@ public class ProjectMetadata extends AbstractMetadata { JSONTokener tokener = new JSONTokener(reader); JSONObject obj = (JSONObject) tokener.nextValue(); - this.loadFromJSON(obj); + this.loadFromJSON(IOUtils.toString(inputStream)); } catch (IOException e) { logger.error(ExceptionUtils.getStackTrace(e)); } From ac444b8b5069f983a403427f203af953df8364c7 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 16 Nov 2018 10:52:57 +0000 Subject: [PATCH 112/164] Add project metadata serialization test --- main/tests/data/example_project_metadata.json | 1 + .../refine/tests/io/ProjectMetadataTests.java | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 main/tests/data/example_project_metadata.json create mode 100644 main/tests/server/src/com/google/refine/tests/io/ProjectMetadataTests.java diff --git a/main/tests/data/example_project_metadata.json b/main/tests/data/example_project_metadata.json new file mode 100644 index 000000000..016955776 --- /dev/null +++ b/main/tests/data/example_project_metadata.json @@ -0,0 +1 @@ +{"_customMetadata":{},"created":"2018-10-12T10:24:28Z","tags":[],"importOptionMetadata":[{"guessCellValueTypes":false,"projectTags":[""],"ignoreLines":-1,"processQuotes":true,"fileSource":"query.tsv","encoding":"","separator":"\\t","storeBlankCellsAsNulls":true,"storeBlankRows":true,"skipDataLines":0,"includeFileSources":false,"headerLines":1,"limit":-1,"quoteCharacter":"\"","projectName":"CPVs"}],"creator":"","contributors":"","subject":"","rowCount":289,"preferenceStore":{"entries":{"scripting.starred-expressions":{"top":2147483647,"list":[],"class":"com.google.refine.preference.TopList"},"scripting.expressions":{"top":100,"list":[],"class":"com.google.refine.preference.TopList"}}},"modified":"2018-10-12T10:51:41Z","description":"","name":"CPVs","dirty":false,"title":"","homepage":"","image":"","license":"","version":""} diff --git a/main/tests/server/src/com/google/refine/tests/io/ProjectMetadataTests.java b/main/tests/server/src/com/google/refine/tests/io/ProjectMetadataTests.java new file mode 100644 index 000000000..e25e8aeaf --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/io/ProjectMetadataTests.java @@ -0,0 +1,22 @@ +package com.google.refine.tests.io; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; +import org.testng.annotations.Test; + +import com.google.refine.model.metadata.ProjectMetadata; +import com.google.refine.tests.util.TestUtils; + +public class ProjectMetadataTests { + @Test + public void serializeProjectMetadata() throws IOException { + ProjectMetadata metadata = new ProjectMetadata(); + InputStream f = ProjectMetadataTests.class.getClassLoader().getResourceAsStream("example_project_metadata.json"); + String json = IOUtils.toString(f); + f = ProjectMetadataTests.class.getClassLoader().getResourceAsStream("example_project_metadata.json"); + metadata.loadFromStream(f); + TestUtils.isSerializedTo(metadata, json); + } +} From 5a4a79028f06da321bee2029669ff1c04927e73e Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sat, 17 Nov 2018 20:42:34 +0000 Subject: [PATCH 113/164] Revert "data package metadata (#1398)" This reverts commit c4b0ff6bea1278032855c56bb8c6393619c42acd. --- .../database/DatabaseImportController.java | 2 +- .../DatabaseImportControllerTest.java | 2 +- .../cmd/SavedConnectionCommandTest.java | 2 +- .../extension/gdata/FusionTableImporter.java | 3 +- .../refine/extension/gdata/GDataImporter.java | 2 +- .../gdata/GDataImportingController.java | 2 +- .../google/refine/pcaxis/PCAxisImporter.java | 2 +- .../datapackage-java-1.0-SNAPSHOT-sources.jar | Bin 63773 -> 0 bytes .../tableschema-java-1.0-SNAPSHOT-sources.jar | Bin 41751 -> 0 bytes .../datapackage-java-1.0-SNAPSHOT.jar | Bin 68785 -> 0 bytes .../tableschema-java-1.0-SNAPSHOT.jar | Bin 53102 -> 0 bytes .../schemas/TableSchemaValidator.json | 213 - .../schemas/datapackage-template.json | 16 - .../src/com/google/refine/ProjectManager.java | 56 +- .../com/google/refine/ProjectMetadata.java | 319 + .../clustering/binning/FingerprintKeyer.java | 2 +- .../com/google/refine/commands/Command.java | 17 +- .../refine/commands/SetPreferenceCommand.java | 4 +- .../expr/GetExpressionHistoryCommand.java | 1 - .../commands/expr/LogExpressionCommand.java | 3 - .../project/DeleteProjectCommand.java | 2 +- .../commands/project/GetMetadataCommand.java | 48 - .../project/ImportProjectCommand.java | 2 +- .../project/PackageProjectCommand.java | 83 - .../project/RenameProjectCommand.java | 4 +- .../project/SetProjectMetadataCommand.java | 5 +- .../project/SetProjectTagsCommand.java | 2 +- .../project/ValidateSchemaCommand.java | 42 - .../refine/commands/row/GetRowsCommand.java | 6 +- .../GetAllProjectMetadataCommand.java | 2 +- .../expr/functions/strings/Reinterpret.java | 2 +- .../refine/grel/controls/IsNumeric.java | 2 +- .../refine/importers/ExcelImporter.java | 6 +- .../refine/importers/FixedWidthImporter.java | 4 +- .../refine/importers/ImportingParserBase.java | 2 +- .../google/refine/importers/JsonImporter.java | 5 +- .../refine/importers/LineBasedImporter.java | 2 +- .../google/refine/importers/OdsImporter.java | 6 +- .../refine/importers/RdfTripleImporter.java | 3 +- .../importers/SeparatorBasedImporter.java | 2 +- .../importers/TabularImportingParserBase.java | 2 +- .../refine/importers/WikitextImporter.java | 6 +- .../google/refine/importers/XmlImporter.java | 4 +- .../tree/TreeImportingParserBase.java | 6 +- .../google/refine/importing/ImportingJob.java | 11 +- .../refine/importing/ImportingParser.java | 3 +- .../refine/importing/ImportingUtilities.java | 398 +- .../google/refine/importing/UrlRewriter.java | 37 +- .../google/refine/io/FileProjectManager.java | 30 +- .../refine/io/ProjectMetadataUtilities.java | 26 +- .../google/refine/io/ProjectUtilities.java | 76 +- main/src/com/google/refine/model/Column.java | 33 +- main/src/com/google/refine/model/Project.java | 18 +- .../model/changes/ColumnAdditionChange.java | 15 - .../model/changes/ColumnMoveChange.java | 12 - .../model/changes/ColumnRemovalChange.java | 6 +- .../model/changes/ColumnReorderChange.java | 5 - .../model/changes/ColumnSplitChange.java | 17 +- .../model/metadata/AbstractMetadata.java | 59 - .../model/metadata/DataPackageMetadata.java | 106 - .../metadata/DataPackageUrlRewriter.java | 44 - .../refine/model/metadata/IMetadata.java | 29 - .../model/metadata/MetadataFactory.java | 82 - .../refine/model/metadata/MetadataFormat.java | 24 - .../model/metadata/PackageExtension.java | 88 - .../model/metadata/ProjectMetadata.java | 483 - .../model/metadata/SchemaExtension.java | 64 - .../metadata/validator/ValidateOperation.java | 21 - .../metadata/validator/ValidatorConfig.java | 6 - .../validator/ValidatorExceptions.java | 6 - .../validator/ValidatorInspector.java | 102 - .../metadata/validator/ValidatorRegistry.java | 41 - .../metadata/validator/ValidatorSpec.java | 28 - .../validator/checks/AbstractValidator.java | 122 - .../validator/checks/BlankHeader.java | 11 - .../metadata/validator/checks/BlankRow.java | 12 - .../validator/checks/DuplicateHeader.java | 11 - .../validator/checks/DuplicateRow.java | 12 - .../checks/EnumerableConstraint.java | 28 - .../validator/checks/ExtraHeader.java | 11 - .../metadata/validator/checks/ExtraValue.java | 12 - .../validator/checks/MaximumConstraint.java | 39 - .../checks/MaximumLengthConstraint.java | 26 - .../validator/checks/MinimumConstraint.java | 39 - .../checks/MinimumLengthConstraint.java | 35 - .../validator/checks/MissingHeader.java | 12 - .../validator/checks/MissingValue.java | 12 - .../validator/checks/NonMatchingHeader.java | 12 - .../validator/checks/PatternConstraint.java | 30 - .../validator/checks/RequiredConstraint.java | 26 - .../validator/checks/TypeorFormatError.java | 49 - .../validator/checks/UniqueConstraint.java | 12 - .../metadata/validator/checks/Validator.java | 36 - .../recon/ReconciledDataExtensionJob.java | 2 +- .../model/recon/StandardReconConfig.java | 2 +- .../ReconCopyAcrossColumnsOperation.java | 1 - .../refine/preference/PreferenceStore.java | 3 - main/src/com/google/refine/util/JSObject.java | 4 +- .../google/refine/util/ParsingUtilities.java | 2 +- main/src/validator-resource-bundle.properties | 13 - main/tests/data/datapackage-sample.json | 44 - main/tests/data/gdp.csv | 11543 ----- .../refine/tests/ProjectManagerStub.java | 5 +- .../refine/tests/ProjectManagerTests.java | 73 +- .../com/google/refine/tests/RefineTest.java | 2 +- .../browsing/facets/TextSearchFacetTests.java | 4 +- .../SetProjectMetadataCommandTests.java | 11 +- .../project/ValidateOperationTests.java | 269 - .../tests/exporters/CsvExporterTests.java | 38 +- .../tests/exporters/HtmlExporterTests.java | 2 +- .../exporters/TemplatingExporterTests.java | 2 +- .../tests/exporters/XlsExporterTests.java | 2 +- .../tests/exporters/sql/SqlExporterTests.java | 2 +- .../refine/tests/history/HistoryTests.java | 2 +- .../refine/tests/importers/ImporterTest.java | 4 +- .../tests/importers/JsonImporterTests.java | 9 + .../tests/importers/TsvCsvImporterTests.java | 6 +- .../importing/ImportingUtilitiesTests.java | 27 +- .../tests/io/FileProjectManagerTests.java | 2 +- .../cell/KeyValueColumnizeTests.java | 2 +- .../tests/process/HistoryProcessTests.java | 2 +- .../webapp/modules/core/MOD-INF/controller.js | 14 +- .../jsoneditor/img/jsoneditor-icons.png | Bin 5287 -> 0 bytes .../jsoneditor/img/jsoneditor-icons.svg | 899 - .../core/externals/jsoneditor/jsoneditor.css | 1065 - .../core/externals/jsoneditor/jsoneditor.js | 38359 ---------------- .../modules/core/langs/translation-en.json | 1 - .../file-selection-panel.js | 4 +- .../import-from-data-package-form.html | 7 - .../default-importing-sources/sources.js | 32 - .../scripts/index/edit-metadata-dialog.js | 19 +- .../core/scripts/index/open-project-ui.js | 72 +- .../project/edit-general-metadata-dialog.html | 12 - .../project/edit-general-metadata-dialog.js | 606 - .../modules/core/scripts/project/exporters.js | 34 - .../views/data-table/data-table-view.js | 14 +- .../core/styles/index/open-project-ui.less | 8 +- server/lib-local/native/windows/jdatapath.dll | Bin start.sh | 0 stop.sh | 0 140 files changed, 705 insertions(+), 55830 deletions(-) delete mode 100644 main/lib-local-src/datapackage-java-1.0-SNAPSHOT-sources.jar delete mode 100644 main/lib-local-src/tableschema-java-1.0-SNAPSHOT-sources.jar delete mode 100644 main/lib-local/datapackage-java-1.0-SNAPSHOT.jar delete mode 100644 main/lib-local/tableschema-java-1.0-SNAPSHOT.jar delete mode 100644 main/resources/schemas/TableSchemaValidator.json delete mode 100644 main/resources/schemas/datapackage-template.json create mode 100644 main/src/com/google/refine/ProjectMetadata.java delete mode 100644 main/src/com/google/refine/commands/project/GetMetadataCommand.java delete mode 100644 main/src/com/google/refine/commands/project/PackageProjectCommand.java delete mode 100644 main/src/com/google/refine/commands/project/ValidateSchemaCommand.java delete mode 100644 main/src/com/google/refine/model/metadata/AbstractMetadata.java delete mode 100644 main/src/com/google/refine/model/metadata/DataPackageMetadata.java delete mode 100644 main/src/com/google/refine/model/metadata/DataPackageUrlRewriter.java delete mode 100644 main/src/com/google/refine/model/metadata/IMetadata.java delete mode 100644 main/src/com/google/refine/model/metadata/MetadataFactory.java delete mode 100644 main/src/com/google/refine/model/metadata/MetadataFormat.java delete mode 100644 main/src/com/google/refine/model/metadata/PackageExtension.java delete mode 100644 main/src/com/google/refine/model/metadata/ProjectMetadata.java delete mode 100644 main/src/com/google/refine/model/metadata/SchemaExtension.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/ValidateOperation.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/ValidatorConfig.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/ValidatorExceptions.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/ValidatorInspector.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/ValidatorRegistry.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/ValidatorSpec.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/AbstractValidator.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/BlankHeader.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/BlankRow.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/DuplicateHeader.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/DuplicateRow.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/EnumerableConstraint.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/ExtraHeader.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/ExtraValue.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/MaximumConstraint.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/MaximumLengthConstraint.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/MinimumConstraint.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/MinimumLengthConstraint.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/MissingHeader.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/MissingValue.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/NonMatchingHeader.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/PatternConstraint.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/RequiredConstraint.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/TypeorFormatError.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/UniqueConstraint.java delete mode 100644 main/src/com/google/refine/model/metadata/validator/checks/Validator.java delete mode 100644 main/src/validator-resource-bundle.properties delete mode 100644 main/tests/data/datapackage-sample.json delete mode 100644 main/tests/data/gdp.csv delete mode 100644 main/tests/server/src/com/google/refine/tests/commands/project/ValidateOperationTests.java delete mode 100644 main/webapp/modules/core/externals/jsoneditor/img/jsoneditor-icons.png delete mode 100644 main/webapp/modules/core/externals/jsoneditor/img/jsoneditor-icons.svg delete mode 100644 main/webapp/modules/core/externals/jsoneditor/jsoneditor.css delete mode 100644 main/webapp/modules/core/externals/jsoneditor/jsoneditor.js delete mode 100644 main/webapp/modules/core/scripts/index/default-importing-sources/import-from-data-package-form.html delete mode 100644 main/webapp/modules/core/scripts/project/edit-general-metadata-dialog.html delete mode 100644 main/webapp/modules/core/scripts/project/edit-general-metadata-dialog.js mode change 100644 => 100755 server/lib-local/native/windows/jdatapath.dll mode change 100755 => 100644 start.sh mode change 100755 => 100644 stop.sh diff --git a/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java b/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java index 1f6c56c73..c44b358c2 100644 --- a/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java +++ b/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java @@ -47,6 +47,7 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.commands.HttpUtilities; import com.google.refine.extension.database.model.DatabaseColumn; @@ -56,7 +57,6 @@ import com.google.refine.importing.ImportingController; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingManager; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; diff --git a/extensions/database/tests/src/com/google/refine/extension/database/DatabaseImportControllerTest.java b/extensions/database/tests/src/com/google/refine/extension/database/DatabaseImportControllerTest.java index 25b1f920d..b1ee56bfa 100644 --- a/extensions/database/tests/src/com/google/refine/extension/database/DatabaseImportControllerTest.java +++ b/extensions/database/tests/src/com/google/refine/extension/database/DatabaseImportControllerTest.java @@ -25,6 +25,7 @@ import org.testng.annotations.Parameters; import org.testng.annotations.Test; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.extension.database.mysql.MySQLDatabaseService; import com.google.refine.extension.database.stub.RefineDbServletStub; @@ -32,7 +33,6 @@ import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingManager; import com.google.refine.io.FileProjectManager; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; diff --git a/extensions/database/tests/src/com/google/refine/extension/database/cmd/SavedConnectionCommandTest.java b/extensions/database/tests/src/com/google/refine/extension/database/cmd/SavedConnectionCommandTest.java index 31aa5ed53..12ee019f3 100644 --- a/extensions/database/tests/src/com/google/refine/extension/database/cmd/SavedConnectionCommandTest.java +++ b/extensions/database/tests/src/com/google/refine/extension/database/cmd/SavedConnectionCommandTest.java @@ -25,6 +25,7 @@ import org.testng.annotations.Parameters; import org.testng.annotations.Test; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.extension.database.DBExtensionTestUtils; import com.google.refine.extension.database.DBExtensionTests; @@ -35,7 +36,6 @@ import com.google.refine.extension.database.stub.RefineDbServletStub; import com.google.refine.importing.ImportingManager; import com.google.refine.io.FileProjectManager; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; public class SavedConnectionCommandTest extends DBExtensionTests{ diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableImporter.java b/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableImporter.java index 2d6fd8633..998e567fb 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableImporter.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableImporter.java @@ -37,11 +37,12 @@ import com.google.api.services.fusiontables.Fusiontables; import com.google.api.services.fusiontables.model.Column; import com.google.api.services.fusiontables.model.Sqlresponse; import com.google.api.services.fusiontables.model.Table; + +import com.google.refine.ProjectMetadata; import com.google.refine.importers.TabularImportingParserBase; import com.google.refine.importers.TabularImportingParserBase.TableDataReader; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; /** diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/GDataImporter.java b/extensions/gdata/src/com/google/refine/extension/gdata/GDataImporter.java index 714c66167..7238bbd17 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/GDataImporter.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/GDataImporter.java @@ -14,11 +14,11 @@ import com.google.api.services.sheets.v4.Sheets; import com.google.api.services.sheets.v4.model.Sheet; import com.google.api.services.sheets.v4.model.Spreadsheet; import com.google.api.services.sheets.v4.model.ValueRange; +import com.google.refine.ProjectMetadata; import com.google.refine.importers.TabularImportingParserBase; import com.google.refine.importers.TabularImportingParserBase.TableDataReader; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; public class GDataImporter { diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java b/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java index 8a35d4612..1a54b5ef4 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java @@ -30,6 +30,7 @@ import com.google.api.services.sheets.v4.Sheets; import com.google.api.services.sheets.v4.model.Sheet; import com.google.api.services.sheets.v4.model.Spreadsheet; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.commands.HttpUtilities; import com.google.refine.importing.DefaultImportingController; @@ -37,7 +38,6 @@ import com.google.refine.importing.ImportingController; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingManager; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; diff --git a/extensions/pc-axis/src/com/google/refine/pcaxis/PCAxisImporter.java b/extensions/pc-axis/src/com/google/refine/pcaxis/PCAxisImporter.java index 504f53d59..1b6203b44 100644 --- a/extensions/pc-axis/src/com/google/refine/pcaxis/PCAxisImporter.java +++ b/extensions/pc-axis/src/com/google/refine/pcaxis/PCAxisImporter.java @@ -41,10 +41,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.refine.ProjectMetadata; import com.google.refine.importers.TabularImportingParserBase; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; diff --git a/main/lib-local-src/datapackage-java-1.0-SNAPSHOT-sources.jar b/main/lib-local-src/datapackage-java-1.0-SNAPSHOT-sources.jar deleted file mode 100644 index 0e5959abf6fa1cb96b0ccd65021a1b4ce5a4e47e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63773 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%0D1gQ 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 qnrl)HtOdHvSP)rucKLJRdJn{|t?*9S1sro1Y diff --git a/main/lib-local-src/tableschema-java-1.0-SNAPSHOT-sources.jar b/main/lib-local-src/tableschema-java-1.0-SNAPSHOT-sources.jar deleted file mode 100644 index d9ddf411ebb67aec64e40e88e41c15e95a67da8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41751 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 diff --git a/main/lib-local/tableschema-java-1.0-SNAPSHOT.jar b/main/lib-local/tableschema-java-1.0-SNAPSHOT.jar deleted file mode 100644 index 4cc32a03f0badb8687064f2418aca417870c9223..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53102 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 z%0D4IutI;x4=5VlAJCNk1)BcPnCdov3rzn9;N*V+d}n@behCKq_sDmK{MYBM0@nWp zGSENA-@TKEt>>EmG4M9j?^2b&OZLZCDfcj$)vw`&feOICCC2<&kY8S<_d|q-8p6NJ z1n}C{Z_iz2R01J>-r)MXRKU5%gH%%wQvJO4d!PE(An=r~(%x0j0Kfs-uU^7_rqA$% z1NMP`YJrM(HxtBwUTL*$Eq{x_14{5-kqFTem=Orz6`?x~)6XZv6Ak{K38b{Gl(fz4 z^aU)+VR|hYk*@t8o7W@u;pH9G8 z;(gP<0~RLvXJ7?gBYktAFxX7n#s(Cb<$B+M0Qj02fR`Enm}MoPUx0sA^M4HtSw3?j8J@L3amqgdKNtq?11te0twKMChrcFOt^W>q7_<8)Z-%ER-+v;# z_d)j$j4a%Rym!Tf02Wi|C*3c_?B)MYjAFmKRuIs(vHb^1&;ap2Su;Fe3;ZX_{~azK zw3UFyLcgb+7yM6@|1&Z=C?jax?|Vi=;eTd)IM@q#iph%$p7=9vcduqLZfb?)?_3K>ecc(dj<(&bP1=P2}J&UvN z-?RL#aDCwE02KXU8SbRSKc8*S0l&XTf1nrrOTj-V6R2GNo@w{Pzh=7E>Vm?9O49G) zH~jxK{GSBspe&#g^LrK#py=`Uk>T%O`QN+_P-XW$zH#8c#{Wy5H)u&frPB9IUO|7) z^n0`V-!B7HcYF^X9{l&<4_ei)#rTs78MGjv^4*_Y8J<-k54ip$<^{z86~f-*RD?dj z`E6XdGxB$SbwE)-<*)ZBkYNu{fXN?-VL?GaMX2{6Ee}EdV03=De+>!*s`cCXe0g#y(|-9w#5{~79c3O zg9=6NkpkoYjPwWD2xz82g$DOf(TRTz^}Fl<6bkgh{XNup(mm9luHWCo{CUUf?&#vz z2L*6@J5v5&>*?n~#{Cu$=()$k9gy2wh>AZY{_BH{{|yLSv_8m<;J*WWu*LNApyMaQ zUmtb+ _projectsMetadata; protected Map _projectsTags;// TagName, number of projects having that tag protected PreferenceStore _preferenceStore; @@ -103,8 +101,8 @@ public abstract class ProjectManager { transient protected Map _projects; static public ProjectManager singleton; - - protected ProjectManager() { + + protected ProjectManager(){ _projectsMetadata = new HashMap(); _preferenceStore = new PreferenceStore(); _projects = new HashMap(); @@ -195,7 +193,7 @@ public abstract class ProjectManager { } catch (Exception e) { e.printStackTrace(); } - } + }//FIXME what should be the behaviour if metadata is null? i.e. not found Project project = getProject(id); if (project != null && metadata != null && metadata.getModified().isAfter(project.getLastSave())) { @@ -204,7 +202,8 @@ public abstract class ProjectManager { } catch (Exception e) { e.printStackTrace(); } - } + }//FIXME what should be the behaviour if project is null? i.e. not found or loaded. + //FIXME what should happen if the metadata is found, but not the project? or vice versa? } } @@ -215,7 +214,7 @@ public abstract class ProjectManager { * @param projectId * @throws Exception */ - public abstract void saveMetadata(IMetadata metadata, long projectId) throws Exception; + public abstract void saveMetadata(ProjectMetadata metadata, long projectId) throws Exception; /** * Save project to the data store @@ -268,23 +267,23 @@ public abstract class ProjectManager { Project project = _projects.get(id); // don't call getProject() as that will load the project. if (project != null) { - LocalDateTime projectLastSaveTime = project.getLastSave(); boolean hasUnsavedChanges = - !metadata.getModified().isBefore(projectLastSaveTime); + metadata.getModified().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() >= project.getLastSave().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); // We use >= instead of just > to avoid the case where a newly created project // has the same modified and last save times, resulting in the project not getting // saved at all. if (hasUnsavedChanges) { - long msecsOverdue = ChronoUnit.MILLIS.between(projectLastSaveTime, startTimeOfSave); - + long msecsOverdue = startTimeOfSave.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - project.getLastSave().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + records.add(new SaveRecord(project, msecsOverdue)); + } else if (!project.getProcessManager().hasPending() - && ChronoUnit.MILLIS.between(projectLastSaveTime, startTimeOfSave) > PROJECT_FLUSH_DELAY) { + && startTimeOfSave.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - project.getLastSave().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() > PROJECT_FLUSH_DELAY) { /* - * It's been a while since the project was last saved and it hasn't been - * modified. We can safely remove it from the cache to save some memory. + * It's been a while since the project was last saved and it hasn't been + * modified. We can safely remove it from the cache to save some memory. */ _projects.remove(id).dispose(); } @@ -310,10 +309,13 @@ public abstract class ProjectManager { "Saving all modified projects ..." : "Saving some modified projects ..." ); - - for (int i = 0;i < records.size() && - (allModified || (ChronoUnit.MILLIS.between(startTimeOfSave, LocalDateTime.now()) < QUICK_SAVE_MAX_TIME)); + + for (int i = 0; + i < records.size() && + (allModified || (LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - + startTimeOfSave.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() < QUICK_SAVE_MAX_TIME)); i++) { + try { saveProject(records.get(i).project); } catch (Exception e) { @@ -352,14 +354,14 @@ public abstract class ProjectManager { /** * Gets the project metadata from memory - * Requires that the metadata has already been loaded from the data store. + * Requires that the metadata has already been loaded from the data store * @param id * @return */ public ProjectMetadata getProjectMetadata(long id) { return _projectsMetadata.get(id); } - + /** * Gets the project metadata from memory * Requires that the metadata has already been loaded from the data store @@ -369,7 +371,7 @@ public abstract class ProjectManager { public ProjectMetadata getProjectMetadata(String name) { for (ProjectMetadata pm : _projectsMetadata.values()) { if (pm.getName().equals(name)) { - return pm; + return pm; } } return null; @@ -421,7 +423,7 @@ public abstract class ProjectManager { userMetadataPreference = new JSONArray(userMeta); } catch (JSONException e1) { logger.warn("wrong definition of userMetadata format. Please use form [{\"name\": \"client name\", \"display\":true}, {\"name\": \"progress\", \"display\":false}]"); - logger.error(ExceptionUtils.getStackTrace(e1)); + logger.error(ExceptionUtils.getFullStackTrace(e1)); } for (int index = 0; index < userMetadataPreference.length(); index++) { @@ -466,7 +468,7 @@ public abstract class ProjectManager { JSONObject projectMetaJsonObj = jsonObjArray.getJSONObject(index); projectMetaJsonObj.put("display", false); } catch (JSONException e) { - logger.error(ExceptionUtils.getStackTrace(e)); + logger.error(ExceptionUtils.getFullStackTrace(e)); } } } @@ -486,7 +488,7 @@ public abstract class ProjectManager { /** * Gets all the project tags currently held in memory - * + * * @return */ @JsonIgnore @@ -494,7 +496,6 @@ public abstract class ProjectManager { return _projectsTags; } - /** * Gets the required project from the data store * If project does not already exist in memory, it is loaded from the data store @@ -603,9 +604,8 @@ public abstract class ProjectManager { * * @param ps */ - public static void preparePreferenceStore(PreferenceStore ps) { + static protected void preparePreferenceStore(PreferenceStore ps) { ps.put("scripting.expressions", new TopList(s_expressionHistoryMax)); ps.put("scripting.starred-expressions", new TopList(Integer.MAX_VALUE)); } - } diff --git a/main/src/com/google/refine/ProjectMetadata.java b/main/src/com/google/refine/ProjectMetadata.java new file mode 100644 index 000000000..b5817f708 --- /dev/null +++ b/main/src/com/google/refine/ProjectMetadata.java @@ -0,0 +1,319 @@ +/* + +Copyright 2010, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +package com.google.refine; + +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.lang.exception.ExceptionUtils; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.refine.preference.PreferenceStore; +import com.google.refine.util.ParsingUtilities; + +public class ProjectMetadata { + public final static String DEFAULT_FILE_NAME = "metadata.json"; + public final static String TEMP_FILE_NAME = "metadata.temp.json"; + public final static String OLD_FILE_NAME = "metadata.old.json"; + + private final LocalDateTime _created; + private LocalDateTime _modified; + private LocalDateTime written = null; + private String _name = ""; + private String _password = ""; + + private String _encoding = ""; + private int _encodingConfidence; + + private String[] _tags = new String[0]; + + private String _creator = ""; + private String _contributors = ""; + private String _subject = ""; // Several refine projects may be linked + private String _description = ""; // free form of comment + private int _rowCount; // at the creation. Essential for cleaning old projects too heavy + + // import options is an array for 1-n data sources + private JSONArray _importOptionMetadata = new JSONArray(); + + // user metadata + private JSONArray _userMetadata = new JSONArray(); + + private Map _customMetadata = new HashMap(); + private PreferenceStore _preferenceStore = new PreferenceStore(); + + private final static Logger logger = LoggerFactory.getLogger("project_metadata"); + + protected ProjectMetadata(LocalDateTime date) { + _created = date; + preparePreferenceStore(_preferenceStore); + } + + public ProjectMetadata() { + this(LocalDateTime.now()); + _modified = _created; + } + + public ProjectMetadata(LocalDateTime created, LocalDateTime modified, String name) { + this(created); + _modified = modified; + _name = name; + } + + private boolean isSaveMode(Properties options) { + return "save".equals(options.getProperty("mode")); + } + + public boolean isDirty() { + return written == null || _modified.isAfter(written); + } + + static protected void preparePreferenceStore(PreferenceStore ps) { + ProjectManager.preparePreferenceStore(ps); + // Any project specific preferences? + } + + public LocalDateTime getCreated() { + return _created; + } + + public void setName(String name) { + this._name = name; + updateModified(); + } + + public String getName() { + return _name; + } + + public void setEncoding(String encoding) { + this._encoding = encoding; + updateModified(); + } + + public String getEncoding() { + return _encoding; + } + + public void setEncodingConfidence(int confidence) { + this._encodingConfidence = confidence; + updateModified(); + } + + public void setEncodingConfidence(String confidence) { + if (confidence != null) { + this.setEncodingConfidence(Integer.parseInt(confidence)); + } + } + + public int getEncodingConfidence() { + return _encodingConfidence; + } + + public void setTags(String[] tags) { + if (tags != null) { + List tmpTags = new ArrayList(tags.length); + for (String tag : tags) { + if (tag != null) { + String trimmedTag = tag.trim(); + + if (!trimmedTag.isEmpty()) { + tmpTags.add(trimmedTag); + } + } + } + this._tags = tmpTags.toArray(new String[tmpTags.size()]); + } else { + this._tags = tags; + } + + updateModified(); + } + + public String[] getTags() { + if (_tags == null) this._tags = new String[0]; + return _tags; + } + + public void setPassword(String password) { + this._password = password; + updateModified(); + } + + public String getPassword() { + return _password; + } + + public LocalDateTime getModified() { + return _modified; + } + + public void updateModified() { + _modified = LocalDateTime.now(); + } + + public PreferenceStore getPreferenceStore() { + return _preferenceStore; + } + + public Serializable getCustomMetadata(String key) { + return _customMetadata.get(key); + } + + public void setCustomMetadata(String key, Serializable value) { + if (value == null) { + _customMetadata.remove(key); + } else { + _customMetadata.put(key, value); + } + updateModified(); + } + + public JSONArray getImportOptionMetadata() { + return _importOptionMetadata; + } + + public void setImportOptionMetadata(JSONArray jsonArray) { + _importOptionMetadata = jsonArray; + updateModified(); + } + + public void appendImportOptionMetadata(ObjectNode options) { + _importOptionMetadata.put(options); + updateModified(); + } + + public String getCreator() { + return _creator; + } + + public void setCreator(String creator) { + this._creator = creator; + updateModified(); + } + + public String getContributors() { + return _contributors; + } + + public void setContributors(String contributors) { + this._contributors = contributors; + updateModified(); + } + + public String getSubject() { + return _subject; + } + + public void setSubject(String subject) { + this._subject = subject; + updateModified(); + } + + public String getDescription() { + return _description; + } + + public void setDescription(String description) { + this._description = description; + updateModified(); + } + + public int getRowCount() { + return _rowCount; + } + + public void setRowCount(int rowCount) { + this._rowCount = rowCount; + updateModified(); + } + + public JSONArray getUserMetadata() { + return _userMetadata; + } + + public void setUserMetadata(JSONArray userMetadata) { + this._userMetadata = userMetadata; + } + + private void updateUserMetadata(String metaName, String valueString) { + for (int i = 0; i < _userMetadata.length(); i++) { + try { + JSONObject obj = _userMetadata.getJSONObject(i); + if (obj.getString("name").equals(metaName)) { + obj.put("value", valueString); + } + } catch (JSONException e) { + logger.error(ExceptionUtils.getFullStackTrace(e)); + } + } + } + + public void setAnyField(String metaName, String valueString) { + Class metaClass = this.getClass(); + try { + Field metaField = metaClass.getDeclaredField("_" + metaName); + if (metaName.equals("tags")) { + metaField.set(this, valueString.split(",")); + } else { + metaField.set(this, valueString); + } + } catch (NoSuchFieldException e) { + updateUserMetadata(metaName, valueString); + } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) { + logger.error(ExceptionUtils.getFullStackTrace(e)); + } + } + + public static ProjectMetadata loadFromStream(InputStream f) throws IOException { + return ParsingUtilities.mapper.readValue(f, ProjectMetadata.class); + } + +} diff --git a/main/src/com/google/refine/clustering/binning/FingerprintKeyer.java b/main/src/com/google/refine/clustering/binning/FingerprintKeyer.java index 0d9a07bc1..5d8885996 100644 --- a/main/src/com/google/refine/clustering/binning/FingerprintKeyer.java +++ b/main/src/com/google/refine/clustering/binning/FingerprintKeyer.java @@ -37,7 +37,7 @@ import java.util.Iterator; import java.util.TreeSet; import java.util.regex.Pattern; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang.StringUtils; public class FingerprintKeyer extends Keyer { diff --git a/main/src/com/google/refine/commands/Command.java b/main/src/com/google/refine/commands/Command.java index a2af0c768..1edecbc5a 100644 --- a/main/src/com/google/refine/commands/Command.java +++ b/main/src/com/google/refine/commands/Command.java @@ -52,12 +52,12 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonGenerator; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.browsing.Engine; import com.google.refine.browsing.EngineConfig; import com.google.refine.history.HistoryEntry; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.process.Process; import com.google.refine.util.ParsingUtilities; @@ -196,7 +196,7 @@ public abstract class Command { * @return * @throws ServletException */ - protected ProjectMetadata getMetadata(HttpServletRequest request) throws ServletException { + protected ProjectMetadata getProjectMetadata(HttpServletRequest request) throws ServletException { if (request == null) { throw new IllegalArgumentException("parameter 'request' should not be null"); } @@ -320,20 +320,7 @@ public abstract class Command { w.flush(); w.close(); } - - static protected void respondJSONObject( - HttpServletResponse response, JSONObject o) - throws IOException, JSONException { - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - response.setHeader("Cache-Control", "no-cache"); - Writer w = response.getWriter(); - w.append(o.toString()); - w.flush(); - w.close(); - } - static protected void respondException(HttpServletResponse response, Exception e) throws IOException, ServletException { diff --git a/main/src/com/google/refine/commands/SetPreferenceCommand.java b/main/src/com/google/refine/commands/SetPreferenceCommand.java index 7dcbf07ba..43857e11f 100644 --- a/main/src/com/google/refine/commands/SetPreferenceCommand.java +++ b/main/src/com/google/refine/commands/SetPreferenceCommand.java @@ -51,7 +51,9 @@ public class SetPreferenceCommand extends Command { throws ServletException, IOException { Project project = request.getParameter("project") != null ? getProject(request) : null; - PreferenceStore ps = ProjectManager.singleton.getPreferenceStore(); + PreferenceStore ps = project != null ? + project.getMetadata().getPreferenceStore() : + ProjectManager.singleton.getPreferenceStore(); String prefName = request.getParameter("name"); String valueString = request.getParameter("value"); diff --git a/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java b/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java index 75a88e406..19aac3772 100644 --- a/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java +++ b/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java @@ -83,7 +83,6 @@ public class GetExpressionHistoryCommand extends Command { throws ServletException, IOException { try { - List expressions = toExpressionList(ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")); Set starredExpressions = new HashSet(((TopList)ProjectManager.singleton.getPreferenceStore().get("scripting.starred-expressions")).getList()); ExpressionsList expressionsList = new ExpressionsList(expressions.stream() diff --git a/main/src/com/google/refine/commands/expr/LogExpressionCommand.java b/main/src/com/google/refine/commands/expr/LogExpressionCommand.java index b5bc0bde1..818da044a 100644 --- a/main/src/com/google/refine/commands/expr/LogExpressionCommand.java +++ b/main/src/com/google/refine/commands/expr/LogExpressionCommand.java @@ -52,9 +52,6 @@ public class LogExpressionCommand extends Command { try { String expression = request.getParameter("expression"); - ((TopList) ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")) - .add(expression); - ((TopList) ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")) .add(expression); diff --git a/main/src/com/google/refine/commands/project/DeleteProjectCommand.java b/main/src/com/google/refine/commands/project/DeleteProjectCommand.java index 57b61207d..9d146a01e 100644 --- a/main/src/com/google/refine/commands/project/DeleteProjectCommand.java +++ b/main/src/com/google/refine/commands/project/DeleteProjectCommand.java @@ -41,8 +41,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.commands.Command; -import com.google.refine.model.metadata.ProjectMetadata; public class DeleteProjectCommand extends Command { diff --git a/main/src/com/google/refine/commands/project/GetMetadataCommand.java b/main/src/com/google/refine/commands/project/GetMetadataCommand.java deleted file mode 100644 index a448505e3..000000000 --- a/main/src/com/google/refine/commands/project/GetMetadataCommand.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.google.refine.commands.project; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.everit.json.schema.ValidationException; -import org.json.JSONException; - -import com.google.refine.commands.Command; -import com.google.refine.model.Project; -import com.google.refine.model.metadata.IMetadata; -import com.google.refine.model.metadata.MetadataFactory; -import com.google.refine.model.metadata.MetadataFormat; - -public class GetMetadataCommand extends Command { - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - try { - Project project; - MetadataFormat metadataFormat; - try { - project = getProject(request); - metadataFormat = MetadataFormat.valueOf(request.getParameter("metadataFormat")); - } catch (ServletException e) { - respond(response, "error", e.getLocalizedMessage()); - return; - } - - // for now, only the data package metadata is supported. - if (metadataFormat != MetadataFormat.DATAPACKAGE_METADATA) { - respond(response, "error", "metadata format is not supported"); - return; - } - - IMetadata metadata = MetadataFactory.buildDataPackageMetadata(project); - respondJSON(response, metadata); - } catch (JSONException e) { - respondException(response, e); - } catch (ValidationException e) { - respondException(response, e); - } - } -} diff --git a/main/src/com/google/refine/commands/project/ImportProjectCommand.java b/main/src/com/google/refine/commands/project/ImportProjectCommand.java index 8972261e9..740b72c9b 100644 --- a/main/src/com/google/refine/commands/project/ImportProjectCommand.java +++ b/main/src/com/google/refine/commands/project/ImportProjectCommand.java @@ -51,9 +51,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.commands.Command; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.ParsingUtilities; public class ImportProjectCommand extends Command { diff --git a/main/src/com/google/refine/commands/project/PackageProjectCommand.java b/main/src/com/google/refine/commands/project/PackageProjectCommand.java deleted file mode 100644 index c73af8935..000000000 --- a/main/src/com/google/refine/commands/project/PackageProjectCommand.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.google.refine.commands.project; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.util.zip.GZIPOutputStream; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.io.IOUtils; -import org.apache.tools.tar.TarOutputStream; - -import com.google.refine.ProjectManager; -import com.google.refine.browsing.Engine; -import com.google.refine.commands.Command; -import com.google.refine.exporters.CsvExporter; -import com.google.refine.model.Project; -import com.google.refine.model.metadata.DataPackageMetadata; -import com.google.refine.model.metadata.PackageExtension; - -public class PackageProjectCommand extends Command { - @Override - public void doPost(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - ProjectManager.singleton.setBusy(true); - - try { - // get the metadata - String metadata = request.getParameter("metadata"); - InputStream in = IOUtils.toInputStream(metadata, "UTF-8"); - - Project project = getProject(request); - Engine engine = getEngine(request, project); - - // ensure project get saved - DataPackageMetadata dpm = new DataPackageMetadata(); - dpm.loadFromStream(in); - ProjectManager.singleton.ensureProjectSaved(project.id); - - // export project - CsvExporter exporter = new CsvExporter(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Writer outputStreamWriter = new OutputStreamWriter(baos); - exporter.export(project, null, engine, outputStreamWriter); - - OutputStream os = response.getOutputStream(); - try { - PackageExtension.saveZip(dpm.getPackage(), baos, os); - response.setHeader("Content-Type", "application/x-gzip"); - } finally { - outputStreamWriter.close(); - os.close(); - } - } catch (Exception e) { - respondException(response, e); - } finally { - ProjectManager.singleton.setBusy(false); - } - } - - protected void gzipTarToOutputStream(Project project, OutputStream os) throws IOException { - GZIPOutputStream gos = new GZIPOutputStream(os); - try { - tarToOutputStream(project, gos); - } finally { - gos.close(); - } - } - - protected void tarToOutputStream(Project project, OutputStream os) throws IOException { - TarOutputStream tos = new TarOutputStream(os); - try { - ProjectManager.singleton.exportProject(project.id, tos); - } finally { - tos.close(); - } - } -} diff --git a/main/src/com/google/refine/commands/project/RenameProjectCommand.java b/main/src/com/google/refine/commands/project/RenameProjectCommand.java index 18eea1872..b8023df4a 100644 --- a/main/src/com/google/refine/commands/project/RenameProjectCommand.java +++ b/main/src/com/google/refine/commands/project/RenameProjectCommand.java @@ -39,8 +39,8 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import com.google.refine.ProjectMetadata; import com.google.refine.commands.Command; -import com.google.refine.model.metadata.ProjectMetadata; public class RenameProjectCommand extends Command { @Override @@ -49,7 +49,7 @@ public class RenameProjectCommand extends Command { try { String name = request.getParameter("name"); - ProjectMetadata pm = getMetadata(request); + ProjectMetadata pm = getProjectMetadata(request); pm.setName(name); diff --git a/main/src/com/google/refine/commands/project/SetProjectMetadataCommand.java b/main/src/com/google/refine/commands/project/SetProjectMetadataCommand.java index 016716ff7..28399a733 100644 --- a/main/src/com/google/refine/commands/project/SetProjectMetadataCommand.java +++ b/main/src/com/google/refine/commands/project/SetProjectMetadataCommand.java @@ -9,14 +9,15 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONException; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.commands.Command; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; public class SetProjectMetadataCommand extends Command { @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + Project project = request.getParameter("project") != null ? getProject(request) : null; String metaName = request.getParameter("name"); String valueString = request.getParameter("value"); @@ -32,7 +33,7 @@ public class SetProjectMetadataCommand extends Command { response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "application/json"); - meta.setAnyStringField(metaName, valueString); + meta.setAnyField(metaName, valueString); ProjectManager.singleton.saveMetadata(meta, project.id); respond(response, "{ \"code\" : \"ok\" }"); diff --git a/main/src/com/google/refine/commands/project/SetProjectTagsCommand.java b/main/src/com/google/refine/commands/project/SetProjectTagsCommand.java index ce86139b5..2bffa2a9f 100644 --- a/main/src/com/google/refine/commands/project/SetProjectTagsCommand.java +++ b/main/src/com/google/refine/commands/project/SetProjectTagsCommand.java @@ -37,9 +37,9 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONException; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.commands.Command; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; public class SetProjectTagsCommand extends Command { @Override diff --git a/main/src/com/google/refine/commands/project/ValidateSchemaCommand.java b/main/src/com/google/refine/commands/project/ValidateSchemaCommand.java deleted file mode 100644 index cfe5c6e3f..000000000 --- a/main/src/com/google/refine/commands/project/ValidateSchemaCommand.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.google.refine.commands.project; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.json.JSONException; -import org.json.JSONObject; - -import com.google.refine.ProjectManager; -import com.google.refine.commands.Command; -import com.google.refine.model.Project; -import com.google.refine.model.metadata.validator.ValidateOperation; -import com.google.refine.util.ParsingUtilities; - -public class ValidateSchemaCommand extends Command { - - @Override - public void doPost(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - ProjectManager.singleton.setBusy(true); - try { - Project project = getProject(request); - JSONObject optionObj = ParsingUtilities.evaluateJsonStringToObject( - request.getParameter("options")); - - new ValidateOperation(project, optionObj).startProcess(); - - respond(response, "{ \"code\" : \"ok\" }"); - } catch (JSONException e) { - respondException(response, e); - } catch (ServletException e) { - respond(response, "error", e.getLocalizedMessage()); - return; - } finally { - ProjectManager.singleton.setBusy(false); - } - } -} diff --git a/main/src/com/google/refine/commands/row/GetRowsCommand.java b/main/src/com/google/refine/commands/row/GetRowsCommand.java index b69042350..238c28823 100644 --- a/main/src/com/google/refine/commands/row/GetRowsCommand.java +++ b/main/src/com/google/refine/commands/row/GetRowsCommand.java @@ -226,9 +226,9 @@ public class GetRowsCommand extends Command { } // metadata refresh for row mode and record mode - if (project.getMetadata() != null) { - project.getMetadata().setRowCount(project.rows.size()); - } + if (project.getMetadata() != null) { + project.getMetadata().setRowCount(project.rows.size()); + } } catch (Exception e) { respondException(response, e); } diff --git a/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java b/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java index 034e42d4a..3388df788 100644 --- a/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java +++ b/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java @@ -47,8 +47,8 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRawValue; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.commands.Command; -import com.google.refine.model.metadata.ProjectMetadata; public class GetAllProjectMetadataCommand extends Command { public static class AllProjectMetadata { diff --git a/main/src/com/google/refine/expr/functions/strings/Reinterpret.java b/main/src/com/google/refine/expr/functions/strings/Reinterpret.java index cc7057862..9d7904bd0 100644 --- a/main/src/com/google/refine/expr/functions/strings/Reinterpret.java +++ b/main/src/com/google/refine/expr/functions/strings/Reinterpret.java @@ -37,11 +37,11 @@ import java.io.UnsupportedEncodingException; import java.util.Properties; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; public class Reinterpret implements Function { diff --git a/main/src/com/google/refine/grel/controls/IsNumeric.java b/main/src/com/google/refine/grel/controls/IsNumeric.java index b56f08185..c8bc88a60 100644 --- a/main/src/com/google/refine/grel/controls/IsNumeric.java +++ b/main/src/com/google/refine/grel/controls/IsNumeric.java @@ -33,7 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.grel.controls; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang.StringUtils; public class IsNumeric extends IsTest { @Override diff --git a/main/src/com/google/refine/importers/ExcelImporter.java b/main/src/com/google/refine/importers/ExcelImporter.java index efdd8b159..8bce9bcad 100644 --- a/main/src/com/google/refine/importers/ExcelImporter.java +++ b/main/src/com/google/refine/importers/ExcelImporter.java @@ -44,7 +44,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.poi.POIXMLDocument; import org.apache.poi.POIXMLException; import org.apache.poi.common.usermodel.Hyperlink; @@ -60,6 +60,7 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.refine.ProjectMetadata; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Cell; @@ -67,7 +68,6 @@ import com.google.refine.model.Project; import com.google.refine.model.Recon; import com.google.refine.model.Recon.Judgment; import com.google.refine.model.ReconCandidate; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; @@ -192,7 +192,7 @@ public class ExcelImporter extends TabularImportingParserBase { // value is fileName#sheetIndex fileNameAndSheetIndex = sheetObj.get("fileNameAndSheetIndex").asText().split("#"); } catch (JSONException e) { - logger.error(ExceptionUtils.getStackTrace(e)); + logger.error(ExceptionUtils.getFullStackTrace(e)); } if (!fileNameAndSheetIndex[0].equals(fileSource)) diff --git a/main/src/com/google/refine/importers/FixedWidthImporter.java b/main/src/com/google/refine/importers/FixedWidthImporter.java index 4c4d9dd49..b8773907d 100644 --- a/main/src/com/google/refine/importers/FixedWidthImporter.java +++ b/main/src/com/google/refine/importers/FixedWidthImporter.java @@ -16,7 +16,9 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; + +import com.google.refine.ProjectMetadata; + import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/importers/ImportingParserBase.java b/main/src/com/google/refine/importers/ImportingParserBase.java index c37f02430..fe0061f96 100644 --- a/main/src/com/google/refine/importers/ImportingParserBase.java +++ b/main/src/com/google/refine/importers/ImportingParserBase.java @@ -44,6 +44,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.refine.ProjectMetadata; import com.google.refine.importers.ImporterUtilities.MultiFileReadingProgress; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingParser; @@ -51,7 +52,6 @@ import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Column; import com.google.refine.model.ModelException; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/importers/JsonImporter.java b/main/src/com/google/refine/importers/JsonImporter.java index 25390755e..0a7cf39dd 100644 --- a/main/src/com/google/refine/importers/JsonImporter.java +++ b/main/src/com/google/refine/importers/JsonImporter.java @@ -47,6 +47,7 @@ import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonParser.NumberType; import com.fasterxml.jackson.core.JsonToken; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.BooleanNode; @@ -54,6 +55,8 @@ import com.fasterxml.jackson.databind.node.DoubleNode; import com.fasterxml.jackson.databind.node.LongNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; + +import com.google.refine.ProjectMetadata; import com.google.refine.importers.tree.ImportColumnGroup; import com.google.refine.importers.tree.TreeImportingParserBase; import com.google.refine.importers.tree.TreeReader; @@ -61,7 +64,7 @@ import com.google.refine.importers.tree.TreeReaderException; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; + import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/importers/LineBasedImporter.java b/main/src/com/google/refine/importers/LineBasedImporter.java index f8829fed5..34ba172a4 100644 --- a/main/src/com/google/refine/importers/LineBasedImporter.java +++ b/main/src/com/google/refine/importers/LineBasedImporter.java @@ -12,7 +12,7 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; +import com.google.refine.ProjectMetadata; import com.google.refine.util.JSONUtilities; public class LineBasedImporter extends TabularImportingParserBase { diff --git a/main/src/com/google/refine/importers/OdsImporter.java b/main/src/com/google/refine/importers/OdsImporter.java index 74e13a2d3..48dbb6c34 100644 --- a/main/src/com/google/refine/importers/OdsImporter.java +++ b/main/src/com/google/refine/importers/OdsImporter.java @@ -44,7 +44,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.commons.lang.exception.ExceptionUtils; import org.json.JSONException; import org.odftoolkit.odfdom.doc.OdfDocument; import org.odftoolkit.odfdom.doc.table.OdfTable; @@ -55,6 +55,7 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.refine.ProjectMetadata; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Cell; @@ -62,7 +63,6 @@ import com.google.refine.model.Project; import com.google.refine.model.Recon; import com.google.refine.model.Recon.Judgment; import com.google.refine.model.ReconCandidate; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; @@ -151,7 +151,7 @@ public class OdsImporter extends TabularImportingParserBase { // value is fileName#sheetIndex fileNameAndSheetIndex = sheetObj.get("fileNameAndSheetIndex").asText().split("#"); } catch (JSONException e) { - logger.error(ExceptionUtils.getStackTrace(e)); + logger.error(ExceptionUtils.getFullStackTrace(e)); } if (!fileNameAndSheetIndex[0].equals(fileSource)) diff --git a/main/src/com/google/refine/importers/RdfTripleImporter.java b/main/src/com/google/refine/importers/RdfTripleImporter.java index b31e3da9a..4eb36b472 100644 --- a/main/src/com/google/refine/importers/RdfTripleImporter.java +++ b/main/src/com/google/refine/importers/RdfTripleImporter.java @@ -46,6 +46,7 @@ import org.apache.jena.rdf.model.Statement; import org.apache.jena.rdf.model.StmtIterator; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.refine.ProjectMetadata; import com.google.refine.expr.ExpressionUtils; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Cell; @@ -53,7 +54,7 @@ import com.google.refine.model.Column; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; -import com.google.refine.model.metadata.ProjectMetadata; + public class RdfTripleImporter extends ImportingParserBase { private Mode mode; diff --git a/main/src/com/google/refine/importers/SeparatorBasedImporter.java b/main/src/com/google/refine/importers/SeparatorBasedImporter.java index cd086e47f..243fc69b2 100644 --- a/main/src/com/google/refine/importers/SeparatorBasedImporter.java +++ b/main/src/com/google/refine/importers/SeparatorBasedImporter.java @@ -52,10 +52,10 @@ import java.util.Map; import org.apache.commons.lang3.StringEscapeUtils; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.refine.ProjectMetadata; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; import au.com.bytecode.opencsv.CSVParser; diff --git a/main/src/com/google/refine/importers/TabularImportingParserBase.java b/main/src/com/google/refine/importers/TabularImportingParserBase.java index 3018c67e5..b36827030 100644 --- a/main/src/com/google/refine/importers/TabularImportingParserBase.java +++ b/main/src/com/google/refine/importers/TabularImportingParserBase.java @@ -40,13 +40,13 @@ import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.refine.ProjectMetadata; import com.google.refine.expr.ExpressionUtils; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; abstract public class TabularImportingParserBase extends ImportingParserBase { diff --git a/main/src/com/google/refine/importers/WikitextImporter.java b/main/src/com/google/refine/importers/WikitextImporter.java index 429492f38..67761a8b4 100644 --- a/main/src/com/google/refine/importers/WikitextImporter.java +++ b/main/src/com/google/refine/importers/WikitextImporter.java @@ -52,20 +52,22 @@ import org.sweble.wikitext.parser.utils.SimpleParserConfig; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.io.CharStreams; +import xtc.parser.ParseException; + +import com.google.refine.ProjectMetadata; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Recon; import com.google.refine.model.ReconStats; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.model.recon.ReconJob; import com.google.refine.model.recon.StandardReconConfig; + import com.google.refine.model.recon.StandardReconConfig.ColumnDetail; import com.google.refine.util.JSONUtilities; import de.fau.cs.osr.ptk.common.AstVisitor; -import xtc.parser.ParseException; public class WikitextImporter extends TabularImportingParserBase { diff --git a/main/src/com/google/refine/importers/XmlImporter.java b/main/src/com/google/refine/importers/XmlImporter.java index 0e67fbc89..74d7fa58d 100644 --- a/main/src/com/google/refine/importers/XmlImporter.java +++ b/main/src/com/google/refine/importers/XmlImporter.java @@ -51,6 +51,8 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.refine.ProjectMetadata; + import com.google.refine.importers.tree.ImportColumnGroup; import com.google.refine.importers.tree.TreeImportingParserBase; import com.google.refine.importers.tree.TreeReader; @@ -58,7 +60,7 @@ import com.google.refine.importers.tree.TreeReaderException; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; + import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; diff --git a/main/src/com/google/refine/importers/tree/TreeImportingParserBase.java b/main/src/com/google/refine/importers/tree/TreeImportingParserBase.java index 27d207034..eaf255f00 100644 --- a/main/src/com/google/refine/importers/tree/TreeImportingParserBase.java +++ b/main/src/com/google/refine/importers/tree/TreeImportingParserBase.java @@ -39,16 +39,16 @@ import java.io.InputStream; import java.io.Reader; import java.util.List; -import org.apache.commons.lang3.NotImplementedException; +import org.apache.commons.lang.NotImplementedException; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.refine.ProjectMetadata; import com.google.refine.importers.ImporterUtilities; import com.google.refine.importers.ImporterUtilities.MultiFileReadingProgress; import com.google.refine.importers.ImportingParserBase; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; /** @@ -154,7 +154,7 @@ abstract public class TreeImportingParserBase extends ImportingParserBase { ObjectNode options, List exceptions ) { - throw new NotImplementedException("project ID:" + project.id); + throw new NotImplementedException(); } /** diff --git a/main/src/com/google/refine/importing/ImportingJob.java b/main/src/com/google/refine/importing/ImportingJob.java index 1da792315..9bd76ec6f 100644 --- a/main/src/com/google/refine/importing/ImportingJob.java +++ b/main/src/com/google/refine/importing/ImportingJob.java @@ -46,8 +46,8 @@ import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; @@ -146,15 +146,6 @@ public class ImportingJob { } } - /** - * TO check if the file record is a metadata file entry - * @param fileRecordObject - * @return ObjectNode - */ - public boolean isMetadataFileRecord(ObjectNode fileRecordObject) { - return fileRecordObject.has("metaDataFormat"); - } - @JsonIgnore public List getSelectedFileRecords() { List results = new ArrayList(); diff --git a/main/src/com/google/refine/importing/ImportingParser.java b/main/src/com/google/refine/importing/ImportingParser.java index 8d0b97295..ae4277601 100644 --- a/main/src/com/google/refine/importing/ImportingParser.java +++ b/main/src/com/google/refine/importing/ImportingParser.java @@ -37,7 +37,8 @@ import java.util.List; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; + +import com.google.refine.ProjectMetadata; public interface ImportingParser { /** diff --git a/main/src/com/google/refine/importing/ImportingUtilities.java b/main/src/com/google/refine/importing/ImportingUtilities.java index 067d1168b..f73b6936e 100644 --- a/main/src/com/google/refine/importing/ImportingUtilities.java +++ b/main/src/com/google/refine/importing/ImportingUtilities.java @@ -42,7 +42,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.UnsupportedEncodingException; -import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import java.text.NumberFormat; @@ -50,11 +49,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.stream.Collectors; import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -68,14 +65,10 @@ import org.apache.commons.fileupload.ProgressListener; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.fileupload.util.Streams; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DecompressingHttpClient; import org.apache.http.impl.client.DefaultHttpClient; @@ -86,41 +79,20 @@ import org.apache.tools.tar.TarInputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.importing.ImportingManager.Format; import com.google.refine.importing.UrlRewriter.Result; -import com.google.refine.model.Cell; -import com.google.refine.model.Column; -import com.google.refine.model.ColumnModel; import com.google.refine.model.Project; -import com.google.refine.model.Row; -import com.google.refine.model.metadata.DataPackageMetadata; -import com.google.refine.model.metadata.IMetadata; -import com.google.refine.model.metadata.MetadataFactory; -import com.google.refine.model.metadata.MetadataFormat; -import com.google.refine.model.metadata.PackageExtension; -import com.google.refine.model.metadata.ProjectMetadata; -import com.google.refine.preference.PreferenceStore; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; -import io.frictionlessdata.datapackage.Package; -import io.frictionlessdata.tableschema.Field; -import io.frictionlessdata.tableschema.Schema; -import io.frictionlessdata.tableschema.TypeInferrer; -import io.frictionlessdata.tableschema.exceptions.TypeInferringException; - public class ImportingUtilities { final static protected Logger logger = LoggerFactory.getLogger("importing-utilities"); - private final static String METADATA_FILE_KEY = "metadataFile"; - - private static final int INFER_ROW_LIMIT = 100; - static public interface Progress { public void setProgress(String message, int percent); public boolean isCanceled(); @@ -201,11 +173,11 @@ public class ImportingUtilities { ) throws Exception { ArrayNode fileRecords = ParsingUtilities.mapper.createArrayNode(); JSONUtilities.safePut(retrievalRecord, "files", fileRecords); - JSONUtilities.safePut(retrievalRecord, "downloadCount", 0); - JSONUtilities.safePut(retrievalRecord, "archiveCount", 0); int clipboardCount = 0; int uploadCount = 0; + int downloadCount = 0; + int archiveCount = 0; // This tracks the total progress, which involves uploading data from the client // as well as downloading data from URLs. @@ -249,7 +221,7 @@ public class ImportingUtilities { List tempFiles = (List)upload.parseRequest(request); progress.setProgress("Uploading data ...", -1); - for (FileItem fileItem : tempFiles) { + parts: for (FileItem fileItem : tempFiles) { if (progress.isCanceled()) { break; } @@ -284,27 +256,107 @@ public class ImportingUtilities { } else if (name.equals("download")) { String urlString = Streams.asString(stream); - download(rawDataDir, retrievalRecord, progress, fileRecords, update, urlString); - processDataPackage(retrievalRecord, fileRecords); - } else if (name.equals("data-package")) { - String urlString = Streams.asString(stream); - List results = null; + URL url = new URL(urlString); + + ObjectNode fileRecord = ParsingUtilities.mapper.createObjectNode(); + JSONUtilities.safePut(fileRecord, "origin", "download"); + JSONUtilities.safePut(fileRecord, "url", urlString); for (UrlRewriter rewriter : ImportingManager.urlRewriters) { - results = rewriter.rewrite(urlString); - if (results != null) { - for (Result result : results) { - download(rawDataDir, retrievalRecord, progress, fileRecords, - update, result.rewrittenUrl, result.metaDataFormat); + Result result = rewriter.rewrite(urlString); + if (result != null) { + urlString = result.rewrittenUrl; + url = new URL(urlString); + + JSONUtilities.safePut(fileRecord, "url", urlString); + JSONUtilities.safePut(fileRecord, "format", result.format); + if (!result.download) { + downloadCount++; + JSONUtilities.append(fileRecords, fileRecord); + continue parts; } } } + + if ("http".equals(url.getProtocol()) || "https".equals(url.getProtocol())) { + DefaultHttpClient client = new DefaultHttpClient(); + DecompressingHttpClient httpclient = + new DecompressingHttpClient(client); + HttpGet httpGet = new HttpGet(url.toURI()); + httpGet.setHeader("User-Agent", RefineServlet.getUserAgent()); + if ("https".equals(url.getProtocol())) { + // HTTPS only - no sending password in the clear over HTTP + String userinfo = url.getUserInfo(); + if (userinfo != null) { + int s = userinfo.indexOf(':'); + if (s > 0) { + String user = userinfo.substring(0, s); + String pw = userinfo.substring(s + 1, userinfo.length()); + client.getCredentialsProvider().setCredentials( + new AuthScope(url.getHost(), 443), + new UsernamePasswordCredentials(user, pw)); + } + } + } + + HttpResponse response = httpclient.execute(httpGet); + + try { + response.getStatusLine(); + HttpEntity entity = response.getEntity(); + if (entity == null) { + throw new Exception("No content found in " + url.toString()); + } + InputStream stream2 = entity.getContent(); + String encoding = null; + if (entity.getContentEncoding() != null) { + encoding = entity.getContentEncoding().getValue(); + } + JSONUtilities.safePut(fileRecord, "declaredEncoding", encoding); + String contentType = null; + if (entity.getContentType() != null) { + contentType = entity.getContentType().getValue(); + } + JSONUtilities.safePut(fileRecord, "declaredMimeType", contentType); + if (saveStream(stream2, url, rawDataDir, progress, update, + fileRecord, fileRecords, + entity.getContentLength())) { + archiveCount++; + } + downloadCount++; + EntityUtils.consume(entity); + } finally { + httpGet.releaseConnection(); + } + } else { + // Fallback handling for non HTTP connections (only FTP?) + URLConnection urlConnection = url.openConnection(); + urlConnection.setConnectTimeout(5000); + urlConnection.connect(); + InputStream stream2 = urlConnection.getInputStream(); + JSONUtilities.safePut(fileRecord, "declaredEncoding", + urlConnection.getContentEncoding()); + JSONUtilities.safePut(fileRecord, "declaredMimeType", + urlConnection.getContentType()); + try { + if (saveStream(stream2, url, rawDataDir, progress, + update, fileRecord, fileRecords, + urlConnection.getContentLength())) { + archiveCount++; + } + downloadCount++; + } finally { + stream2.close(); + } + } } else { String value = Streams.asString(stream); parameters.put(name, value); // TODO: We really want to store this on the request so it's available for everyone // request.getParameterMap().put(name, value); + } + } else { // is file content String fileName = fileItem.getName(); if (fileName.length() > 0) { @@ -325,11 +377,9 @@ public class ImportingUtilities { JSONUtilities.safePut(fileRecord, "size", saveStreamToFile(stream, file, null)); if (postProcessRetrievedFile(rawDataDir, file, fileRecord, fileRecords, progress)) { - JSONUtilities.safeInc(retrievalRecord, "archiveCount"); + archiveCount++; } - processDataPackage(retrievalRecord, fileRecords); - uploadCount++; } } @@ -343,144 +393,9 @@ public class ImportingUtilities { } JSONUtilities.safePut(retrievalRecord, "uploadCount", uploadCount); + JSONUtilities.safePut(retrievalRecord, "downloadCount", downloadCount); JSONUtilities.safePut(retrievalRecord, "clipboardCount", clipboardCount); - } - - private static void processDataPackage(ObjectNode retrievalRecord, ArrayNode fileRecords) { - int dataPackageJSONFileIndex = getDataPackageJSONFile(fileRecords); - if (dataPackageJSONFileIndex >= 0) { - ObjectNode dataPackageJSONFile = (ObjectNode) fileRecords.get(dataPackageJSONFileIndex); - JSONUtilities.safePut(dataPackageJSONFile, "metaDataFormat", MetadataFormat.DATAPACKAGE_METADATA.name()); - JSONUtilities.safePut(retrievalRecord, METADATA_FILE_KEY, dataPackageJSONFile); - fileRecords.remove(dataPackageJSONFileIndex); - } - } - - private static int getDataPackageJSONFile(ArrayNode fileRecords) { - for (int i = 0; i < fileRecords.size(); i++) { - ObjectNode file = JSONUtilities.getObjectElement(fileRecords, i); - if (file.has("archiveFileName") && - file.has("fileName") && - file.get("fileName").equals(DataPackageMetadata.DEFAULT_FILE_NAME)) { - return i; - } - } - return -1; - } - - private static void download(File rawDataDir, ObjectNode retrievalRecord, final Progress progress, - ArrayNode fileRecords, final SavingUpdate update, String urlString) - throws URISyntaxException, IOException, ClientProtocolException, Exception { - download(rawDataDir, retrievalRecord, progress, fileRecords, update, urlString, null); - } - - /** - * @param rawDataDir - * @param retrievalRecord - * @param progress - * @param fileRecords - * @param update - * @param urlString - * @throws URISyntaxException - * @throws IOException - * @throws ClientProtocolException - * @throws Exception - */ - private static void download(File rawDataDir, ObjectNode retrievalRecord, final Progress progress, - ArrayNode fileRecords, final SavingUpdate update, String urlString, String metaDataFormat) - throws URISyntaxException, IOException, ClientProtocolException, Exception { - URL url = new URL(urlString); - ObjectNode fileRecord = ParsingUtilities.mapper.createObjectNode(); - JSONUtilities.safePut(fileRecord, "origin", "download"); - JSONUtilities.safePut(fileRecord, "url", urlString); - - if ("http".equals(url.getProtocol()) || "https".equals(url.getProtocol())) { - DefaultHttpClient client = new DefaultHttpClient(); - DecompressingHttpClient httpclient = - new DecompressingHttpClient(client); - HttpGet httpGet = new HttpGet(url.toURI()); - httpGet.setHeader("User-Agent", RefineServlet.getUserAgent()); - if ("https".equals(url.getProtocol())) { - // HTTPS only - no sending password in the clear over HTTP - String userinfo = url.getUserInfo(); - if (userinfo != null) { - int s = userinfo.indexOf(':'); - if (s > 0) { - String user = userinfo.substring(0, s); - String pw = userinfo.substring(s + 1, userinfo.length()); - client.getCredentialsProvider().setCredentials( - new AuthScope(url.getHost(), 443), - new UsernamePasswordCredentials(user, pw)); - } - } - } - - HttpResponse response = httpclient.execute(httpGet); - - try { - int code = response.getStatusLine().getStatusCode(); - if (code != HttpStatus.SC_OK) { - throw new Exception("HTTP response code: " + code + - " when accessing URL: "+ url.toString()); - } - - HttpEntity entity = response.getEntity(); - if (entity == null) { - throw new Exception("No content found in " + url.toString()); - } - InputStream stream2 = entity.getContent(); - String encoding = null; - if (entity.getContentEncoding() != null) { - encoding = entity.getContentEncoding().getValue(); - } - JSONUtilities.safePut(fileRecord, "declaredEncoding", encoding); - String contentType = null; - if (entity.getContentType() != null) { - contentType = entity.getContentType().getValue(); - } - JSONUtilities.safePut(fileRecord, "declaredMimeType", contentType); - - if (saveStream(stream2, url, rawDataDir, progress, update, - fileRecord, fileRecords, - entity.getContentLength())) { - JSONUtilities.safeInc(retrievalRecord, "archiveCount"); - } - - if (metaDataFormat != null) { - JSONUtilities.safePut(fileRecord, "metaDataFormat", metaDataFormat); - JSONUtilities.safePut(retrievalRecord, METADATA_FILE_KEY, fileRecord); - fileRecords.remove(0); - } - - JSONUtilities.safeInc(retrievalRecord, "downloadCount"); - EntityUtils.consume(entity); - } finally { - httpGet.releaseConnection(); - } - } else { - // Fallback handling for non HTTP connections (only FTP?) - URLConnection urlConnection = url.openConnection(); - urlConnection.setConnectTimeout(5000); - urlConnection.connect(); - InputStream stream2 = urlConnection.getInputStream(); - JSONUtilities.safePut(fileRecord, "declaredEncoding", - urlConnection.getContentEncoding()); - JSONUtilities.safePut(fileRecord, "declaredMimeType", - urlConnection.getContentType()); - try { - if (saveStream(stream2, url, rawDataDir, progress, - update, fileRecord, fileRecords, - urlConnection.getContentLength())) { - JSONUtilities.safeInc(retrievalRecord, "archiveCount"); - } - if (metaDataFormat != null) - JSONUtilities.safePut(fileRecord, "metaDataFormat", metaDataFormat); - - JSONUtilities.safeInc(retrievalRecord, "downloadCount"); - } finally { - stream2.close(); - } - } + JSONUtilities.safePut(retrievalRecord, "archiveCount", archiveCount); } private static boolean saveStream(InputStream stream, URL url, File rawDataDir, final Progress progress, @@ -1107,30 +1022,8 @@ public class ImportingUtilities { if (exceptions.size() == 0) { project.update(); // update all internal models, indexes, caches, etc. - boolean hasMetadataFileRecord = ((ObjectNode)job.getRetrievalRecord()).has(METADATA_FILE_KEY); - - if (hasMetadataFileRecord) { - ObjectNode metadataFileRecord = (ObjectNode) job.getRetrievalRecord().get(METADATA_FILE_KEY); - - String metadataFormat = JSONUtilities.getString(metadataFileRecord, "metaDataFormat", null); - IMetadata metadata = MetadataFactory.buildMetadata(MetadataFormat.valueOf(metadataFormat)); - - String relativePath = JSONUtilities.getString(metadataFileRecord, "location", null); - File metadataFile = new File(job.getRawDataDir(), relativePath); - metadata.loadFromFile(metadataFile); - - // process the data package metadata - if (MetadataFormat.valueOf(metadataFormat) == MetadataFormat.DATAPACKAGE_METADATA) { - populateDataPackageMetadata(project, pm, (DataPackageMetadata) metadata); - } - logger.info(metadataFileRecord.get("metaDataFormat") + " metadata is set for project " + project.id); - } - ProjectManager.singleton.registerProject(project, pm); - // infer the column type - inferColumnType(project); - job.setProjectID(project.id); job.setState("created-project"); } else { @@ -1141,101 +1034,10 @@ public class ImportingUtilities { } } - public static void inferColumnType(final Project project) { - if (project.columnModel.columns.get(0).getType().isEmpty()) { - List listCells = new ArrayList(INFER_ROW_LIMIT); - List rows = project.rows - .stream() - .limit(INFER_ROW_LIMIT) - .map(Row::dup) - .collect(Collectors.toList()); - // convert the null object to prevent the NPE - for (Row row : rows) { - for (int i = 0; i < row.cells.size(); i++) { - Cell cell = row.cells.get(i); - if (cell == null) { - row.cells.set(i, new Cell(StringUtils.EMPTY, null)); - } - } - listCells.add(row.cells.toArray()); - } - - try { - ObjectNode fieldsJSON = JSONUtilities.jsonObjectToObjectNode(TypeInferrer.getInstance().infer(listCells, - project.columnModel.getColumnNames().toArray(new String[0]), - 100)); - populateColumnTypes(project.columnModel, JSONUtilities.getArray(fieldsJSON, Schema.JSON_KEY_FIELDS)); - } catch (TypeInferringException e) { - logger.error("infer column type exception.", ExceptionUtils.getStackTrace(e)); - } - } - } - - private static void populateDataPackageMetadata(Project project, ProjectMetadata pmd, DataPackageMetadata metadata) { - // project metadata - ObjectNode pkg = JSONUtilities.jsonObjectToObjectNode(metadata.getPackage().getJson()); - - pmd.setName(getDataPackageProperty(pkg, Package.JSON_KEY_NAME)); - pmd.setDescription(getDataPackageProperty(pkg, PackageExtension.JSON_KEY_DESCRIPTION)); - pmd.setTitle(getDataPackageProperty(pkg, PackageExtension.JSON_KEY_TITLE)); - pmd.setHomepage(getDataPackageProperty(pkg, PackageExtension.JSON_KEY_HOMEPAGE)); - pmd.setImage(getDataPackageProperty(pkg, PackageExtension.JSON_KEY_IMAGE)); - pmd.setLicense(getDataPackageProperty(pkg, PackageExtension.JSON_KEY_LICENSE)); - pmd.setVersion(getDataPackageProperty(pkg, PackageExtension.JSON_KEY_VERSION)); - - if (pkg.has(PackageExtension.JSON_KEY_KEYWORKS)) { - String[] tags = JSONUtilities.getStringArray(pkg, PackageExtension.JSON_KEY_KEYWORKS); - pmd.appendTags(tags); - } - - // column model - ObjectNode schema = JSONUtilities.jsonObjectToObjectNode(metadata.getPackage().getResources().get(0).getSchema()); - if (schema != null) { - populateColumnTypes(project.columnModel, JSONUtilities.getArray(schema, Schema.JSON_KEY_FIELDS)); - } - } - - private static String getDataPackageProperty(ObjectNode pkg, String key) { - return JSONUtilities.getString(pkg, key, StringUtils.EMPTY); - } - /** - * Populate the column model - * @param columnModel - * @param fieldsJSON - */ - private static void populateColumnTypes(ColumnModel columnModel, ArrayNode fieldsJSON) { - int cellIndex = 0; - Iterator iter = fieldsJSON.iterator(); - while(iter.hasNext()){ - ObjectNode fieldJsonObj = (ObjectNode)iter.next(); - Field field = new Field(JSONUtilities.objectNodeToJsonNode(fieldJsonObj)); - - Column column = columnModel.getColumnByCellIndex(cellIndex); - column.setType(field.getType()); - column.setFormat(field.getFormat()); - column.setDescription(field.getDescription()); - column.setTitle(field.getTitle()); - column.setConstraints(field.getConstraints()); - - cellIndex++; - } - } - - /** - * Create project metadata. pull the "USER_NAME" from the PreferenceStore as the creator - * @param optionObj - * @return - */ static public ProjectMetadata createProjectMetadata(ObjectNode optionObj) { ProjectMetadata pm = new ProjectMetadata(); - PreferenceStore ps = ProjectManager.singleton.getPreferenceStore(); - pm.setName(JSONUtilities.getString(optionObj, "projectName", "Untitled")); pm.setTags(JSONUtilities.getStringArray(optionObj, "projectTags")); - pm.setTitle(JSONUtilities.getString(optionObj, "title", "")); - pm.setHomepage(JSONUtilities.getString(optionObj, "homepage", "")); - pm.setImage(JSONUtilities.getString(optionObj, "image", "")); - pm.setLicense(JSONUtilities.getString(optionObj, "license", "")); String encoding = JSONUtilities.getString(optionObj, "encoding", "UTF-8"); if ("".equals(encoding)) { @@ -1243,12 +1045,6 @@ public class ImportingUtilities { encoding = "UTF-8"; } pm.setEncoding(encoding); - - if (ps.get(PreferenceStore.USER_NAME) != null) { - String creator = (String) ps.get(PreferenceStore.USER_NAME); - pm.setCreator(creator); - } - return pm; } } diff --git a/main/src/com/google/refine/importing/UrlRewriter.java b/main/src/com/google/refine/importing/UrlRewriter.java index 7563fe1cc..4e6015488 100644 --- a/main/src/com/google/refine/importing/UrlRewriter.java +++ b/main/src/com/google/refine/importing/UrlRewriter.java @@ -33,47 +33,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.importing; -import java.io.IOException; -import java.net.MalformedURLException; -import java.util.List; - -import com.google.refine.model.metadata.DataPackageUrlRewriter; - -/** - * Given a URL rewrittenUrl, the interface will rewrite it into different URLS based on the rewrittenUrl - * The result will be stored in the Result and can be used for download, parsing etc. - * Typical use is to parse the data package json file. - * @see DataPackageUrlRewriter - */ public interface UrlRewriter { static public class Result { public String rewrittenUrl; public String format; public boolean download; - public String metaDataFormat; - - public Result(String rewrittenUrl, String format, boolean download) { - this.rewrittenUrl = rewrittenUrl; - this.format = format; - this.download = download; - } - - public Result(String rewrittenUrl, String format, boolean download, String metaDataFormat) { - this.rewrittenUrl = rewrittenUrl; - this.format = format; - this.download = download; - this.metaDataFormat = metaDataFormat; - } } - /** - * Parse the url and output the Result - * @param url - * @return - * @throws MalformedURLException - * @throws IOException - */ - public List rewrite(String url) throws MalformedURLException, IOException; - - public boolean filter(String url); + public Result rewrite(String url); } diff --git a/main/src/com/google/refine/io/FileProjectManager.java b/main/src/com/google/refine/io/FileProjectManager.java index d342229b7..71240ff60 100644 --- a/main/src/com/google/refine/io/FileProjectManager.java +++ b/main/src/com/google/refine/io/FileProjectManager.java @@ -57,12 +57,9 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.history.HistoryEntryManager; import com.google.refine.model.Project; -import com.google.refine.model.metadata.DataPackageMetadata; -import com.google.refine.model.metadata.IMetadata; -import com.google.refine.model.metadata.MetadataFormat; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.preference.PreferenceStore; import com.google.refine.preference.TopList; import com.google.refine.util.ParsingUtilities; @@ -127,6 +124,7 @@ public class FileProjectManager extends ProjectManager { if (metadata == null) { metadata = ProjectMetadataUtilities.recover(getProjectDir(projectID), projectID); } + if (metadata != null) { _projectsMetadata.put(projectID, metadata); if (_projectsTags == null) { @@ -161,7 +159,7 @@ public class FileProjectManager extends ProjectManager { untar(destDir, inputStream); } } - + protected void untar(File destDir, InputStream inputStream) throws IOException { TarInputStream tin = new TarInputStream(inputStream); TarEntry tarEntry = null; @@ -237,21 +235,9 @@ public class FileProjectManager extends ProjectManager { } @Override - public void saveMetadata(IMetadata metadata, long projectId) throws Exception { + public void saveMetadata(ProjectMetadata metadata, long projectId) throws Exception { File projectDir = getProjectDir(projectId); - - if (metadata.getFormatName() == MetadataFormat.PROJECT_METADATA) { - Project project = ProjectManager.singleton.getProject(projectId); - ((ProjectMetadata)metadata).setRowCount(project.rows.size()); - ProjectMetadataUtilities.save(metadata, projectDir); - } else if (metadata.getFormatName() == MetadataFormat.DATAPACKAGE_METADATA) { - DataPackageMetadata dp = (DataPackageMetadata)metadata; - FileWriter writer = new FileWriter(new File(projectDir, DataPackageMetadata.DEFAULT_FILE_NAME)); - ParsingUtilities.defaultWriter.writeValue(writer, dp); - writer.close(); - } - - logger.info("metadata saved in " + metadata.getFormatName()); + ProjectMetadataUtilities.save(metadata, projectDir); } @Override @@ -331,6 +317,8 @@ public class FileProjectManager extends ProjectManager { return saveWasNeeded; } + + @Override public void deleteProject(long projectID) { synchronized (this) { @@ -372,6 +360,8 @@ public class FileProjectManager extends ProjectManager { protected boolean loadFromFile(File file) { logger.info("Loading workspace: {}", file.getAbsolutePath()); + _projectsMetadata.clear(); + boolean found = false; try { @@ -476,4 +466,4 @@ public class FileProjectManager extends ProjectManager { _preferenceStore.put("scripting.expressions", newExpressions); } } -} \ No newline at end of file +} diff --git a/main/src/com/google/refine/io/ProjectMetadataUtilities.java b/main/src/com/google/refine/io/ProjectMetadataUtilities.java index e41fa500d..05da2edaf 100644 --- a/main/src/com/google/refine/io/ProjectMetadataUtilities.java +++ b/main/src/com/google/refine/io/ProjectMetadataUtilities.java @@ -35,6 +35,7 @@ package com.google.refine.io; import java.io.File; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; @@ -46,23 +47,26 @@ import java.util.List; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONTokener; +import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.refine.ProjectMetadata; import com.google.refine.model.Project; -import com.google.refine.model.metadata.IMetadata; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.ParsingUtilities; + public class ProjectMetadataUtilities { final static Logger logger = LoggerFactory.getLogger("project_metadata_utilities"); - - public static void save(IMetadata projectMeta, File projectDir) throws JSONException, IOException { - File tempFile = new File(projectDir, ProjectMetadata.TEMP_FILE_NAME); + + public static void save(ProjectMetadata projectMeta, File projectDir) throws JSONException, IOException { + File tempFile = new File(projectDir, "metadata.temp.json"); saveToFile(projectMeta, tempFile); - File file = new File(projectDir, ProjectMetadata.DEFAULT_FILE_NAME); - File oldFile = new File(projectDir, ProjectMetadata.OLD_FILE_NAME); + File file = new File(projectDir, "metadata.json"); + File oldFile = new File(projectDir, "metadata.old.json"); if (oldFile.exists()) { oldFile.delete(); @@ -75,7 +79,7 @@ public class ProjectMetadataUtilities { tempFile.renameTo(file); } - protected static void saveToFile(IMetadata projectMeta, File metadataFile) throws JSONException, IOException { + protected static void saveToFile(ProjectMetadata projectMeta, File metadataFile) throws JSONException, IOException { Writer writer = new OutputStreamWriter(new FileOutputStream(metadataFile)); try { ParsingUtilities.defaultWriter.writeValue(writer, projectMeta); @@ -157,8 +161,8 @@ public class ProjectMetadataUtilities { } static protected ProjectMetadata loadFromFile(File metadataFile) throws Exception { - ProjectMetadata projectMetaData = new ProjectMetadata(); - projectMetaData.loadFromFile(metadataFile); - return projectMetaData; + FileReader reader = new FileReader(metadataFile); + return ProjectMetadata.loadFromStream(reader); + } } diff --git a/main/src/com/google/refine/io/ProjectUtilities.java b/main/src/com/google/refine/io/ProjectUtilities.java index edc2d5efc..4088cfeb9 100644 --- a/main/src/com/google/refine/io/ProjectUtilities.java +++ b/main/src/com/google/refine/io/ProjectUtilities.java @@ -36,8 +36,6 @@ package com.google.refine.io; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; @@ -47,9 +45,6 @@ import org.slf4j.LoggerFactory; import com.google.refine.ProjectManager; import com.google.refine.model.Project; -import com.google.refine.model.metadata.DataPackageMetadata; -import com.google.refine.model.metadata.IMetadata; -import com.google.refine.model.metadata.MetadataFormat; import com.google.refine.util.Pool; @@ -115,63 +110,38 @@ public class ProjectUtilities { out.close(); } } - - static public Project loadDataFile(File dir, String dataFile, long id) { + + static public Project load(File dir, long id) { try { - File file = new File(dir, dataFile); + File file = new File(dir, "data.zip"); if (file.exists()) { return loadFromFile(file, id); } } catch (Exception e) { e.printStackTrace(); } - + + try { + File file = new File(dir, "data.temp.zip"); + if (file.exists()) { + return loadFromFile(file, id); + } + } catch (Exception e) { + e.printStackTrace(); + } + + try { + File file = new File(dir, "data.old.zip"); + if (file.exists()) { + return loadFromFile(file, id); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; } - - static public Project load(File dir, long id) { - Project project =null; - - if ((project = loadDataFile(dir, "data.zip", id)) == null) { - if ((project = loadDataFile(dir, "data.temp.zip", id)) == null) { - project = loadDataFile(dir, "data.old.zip", id); - } - } - return project; - } - - - /** - * scan the folder for json files and read them as metadata - * @param dir - * @param project - */ - public static Map retriveMetadata(File dir) { - // load the metadatas from data folder. - Map metadataMap = new HashMap(); - - File[] jsons = dir.listFiles( - (folder, file) -> { - return file.toLowerCase().endsWith(".json"); - } - ); - - for (File file : jsons) { - // already loaded - if (file.getName().startsWith("metadata.")) - continue; - - DataPackageMetadata metadata = new DataPackageMetadata(); - // load itself - metadata.loadFromFile(file); - - metadataMap.put(MetadataFormat.DATAPACKAGE_METADATA, metadata); - } - - return metadataMap; - - } - + static protected Project loadFromFile( File file, long id diff --git a/main/src/com/google/refine/model/Column.java b/main/src/com/google/refine/model/Column.java index f92d64598..e32c80207 100644 --- a/main/src/com/google/refine/model/Column.java +++ b/main/src/com/google/refine/model/Column.java @@ -39,6 +39,13 @@ import java.lang.reflect.Method; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; @@ -50,11 +57,6 @@ import com.google.refine.InterProjectModel; import com.google.refine.model.recon.ReconConfig; import com.google.refine.util.ParsingUtilities; -import io.frictionlessdata.tableschema.Field; -import io.frictionlessdata.tableschema.TypeInferrer; -import io.frictionlessdata.tableschema.exceptions.ConstraintsException; -import io.frictionlessdata.tableschema.exceptions.InvalidCastException; - public class Column { final private int _cellIndex; final private String _originalName; @@ -64,7 +66,7 @@ public class Column { // from data package metadata Field.java: private String type = ""; - private String format = Field.FIELD_FORMAT_DEFAULT; + private String format = ""; private String title = ""; private String description = ""; private Map constraints = Collections.emptyMap(); @@ -237,23 +239,4 @@ public class Column { public String toString() { return _name; } - - public Any castValue(String value) - throws InvalidCastException, ConstraintsException { - if (this.type.isEmpty()) { - throw new InvalidCastException(); - } else { - try { - // Using reflection to invoke appropriate type casting method from the - // TypeInferrer class - String castMethodName = "cast" + (this.type.substring(0, 1).toUpperCase() + this.type.substring(1)); - Method method = TypeInferrer.class.getMethod(castMethodName, String.class, String.class, Map.class); - Object castValue = method.invoke(TypeInferrer.getInstance(), this.format, value, null); - - return (Any) castValue; - } catch (Exception e) { - throw new InvalidCastException(); - } - } - } } diff --git a/main/src/com/google/refine/model/Project.java b/main/src/com/google/refine/model/Project.java index fee610280..f07532d86 100644 --- a/main/src/com/google/refine/model/Project.java +++ b/main/src/com/google/refine/model/Project.java @@ -51,9 +51,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.history.History; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.process.ProcessManager; import com.google.refine.util.ParsingUtilities; import com.google.refine.util.Pool; @@ -73,13 +73,14 @@ public class Project { transient private LocalDateTime _lastSave = LocalDateTime.now(); final static Logger logger = LoggerFactory.getLogger("project"); - + static public long generateID() { return System.currentTimeMillis() + Math.round(Math.random() * 1000000000000L); } public Project() { - this(generateID()); + id = generateID(); + history = new History(this); } protected Project(long id) { @@ -116,6 +117,10 @@ public class Project { this._lastSave = LocalDateTime.now(); } + public ProjectMetadata getMetadata() { + return ProjectManager.singleton.getProjectMetadata(id); + } + public void saveToOutputStream(OutputStream out, Pool pool) throws IOException { for (OverlayModel overlayModel : overlayModels.values()) { try { @@ -240,14 +245,11 @@ public class Project { columnModel.update(); recordModel.update(this); } - + + //wrapper of processManager variable to allow unit testing //TODO make the processManager variable private, and force all calls through this method public ProcessManager getProcessManager() { return this.processManager; } - - public ProjectMetadata getMetadata() { - return ProjectManager.singleton.getProjectMetadata(id); - } } diff --git a/main/src/com/google/refine/model/changes/ColumnAdditionChange.java b/main/src/com/google/refine/model/changes/ColumnAdditionChange.java index 752ba9f51..f3a6afcee 100644 --- a/main/src/com/google/refine/model/changes/ColumnAdditionChange.java +++ b/main/src/com/google/refine/model/changes/ColumnAdditionChange.java @@ -62,21 +62,6 @@ public class ColumnAdditionChange extends ColumnChange { newCells.toArray(_newCells); } - - public String getColumnName() { - return _columnName; - } - - - public int getColumnIndex() { - return _columnIndex; - } - - - public int getNewCellIndex() { - return _newCellIndex; - } - @Override public void apply(Project project) { synchronized (project) { diff --git a/main/src/com/google/refine/model/changes/ColumnMoveChange.java b/main/src/com/google/refine/model/changes/ColumnMoveChange.java index 817e3eb36..de394c8a5 100644 --- a/main/src/com/google/refine/model/changes/ColumnMoveChange.java +++ b/main/src/com/google/refine/model/changes/ColumnMoveChange.java @@ -58,18 +58,6 @@ public class ColumnMoveChange extends ColumnChange { _newColumnIndex = index; } - public int getOldColumnIndex() { - return _oldColumnIndex; - } - - public String getColumnName() { - return _columnName; - } - - public int getNewColumnIndex() { - return _newColumnIndex; - } - @Override public void apply(Project project) { synchronized (project) { diff --git a/main/src/com/google/refine/model/changes/ColumnRemovalChange.java b/main/src/com/google/refine/model/changes/ColumnRemovalChange.java index c7ecc1f92..70a2b0636 100644 --- a/main/src/com/google/refine/model/changes/ColumnRemovalChange.java +++ b/main/src/com/google/refine/model/changes/ColumnRemovalChange.java @@ -54,15 +54,11 @@ public class ColumnRemovalChange extends ColumnChange { protected Column _oldColumn; protected CellAtRow[] _oldCells; protected List _oldColumnGroups; - + public ColumnRemovalChange(int index) { _oldColumnIndex = index; } - public int getOldColumnIndex() { - return _oldColumnIndex; - } - @Override public void apply(Project project) { synchronized (project) { diff --git a/main/src/com/google/refine/model/changes/ColumnReorderChange.java b/main/src/com/google/refine/model/changes/ColumnReorderChange.java index e29d01ade..bdf714998 100644 --- a/main/src/com/google/refine/model/changes/ColumnReorderChange.java +++ b/main/src/com/google/refine/model/changes/ColumnReorderChange.java @@ -57,11 +57,6 @@ public class ColumnReorderChange extends ColumnChange { _columnNames = columnNames; } - - public List getColumnNames() { - return _columnNames; - } - @Override public void apply(Project project) { synchronized (project) { diff --git a/main/src/com/google/refine/model/changes/ColumnSplitChange.java b/main/src/com/google/refine/model/changes/ColumnSplitChange.java index adf50cc64..bb49a4c4a 100644 --- a/main/src/com/google/refine/model/changes/ColumnSplitChange.java +++ b/main/src/com/google/refine/model/changes/ColumnSplitChange.java @@ -54,7 +54,7 @@ import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.util.Pool; -public class ColumnSplitChange extends ColumnChange { +public class ColumnSplitChange implements Change { final protected String _columnName; final protected List _columnNames; @@ -118,21 +118,6 @@ public class ColumnSplitChange extends ColumnChange { _newRows = newRows; } - - public List getColumnNames() { - return _columnNames; - } - - - public boolean isRemoveOriginalColumn() { - return _removeOriginalColumn; - } - - - public int getColumnIndex() { - return _columnIndex; - } - @Override public void apply(Project project) { synchronized (project) { diff --git a/main/src/com/google/refine/model/metadata/AbstractMetadata.java b/main/src/com/google/refine/model/metadata/AbstractMetadata.java deleted file mode 100644 index aab2f94ec..000000000 --- a/main/src/com/google/refine/model/metadata/AbstractMetadata.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.google.refine.model.metadata; - -import java.io.File; -import java.io.IOException; -import java.time.LocalDateTime; - -import org.apache.commons.beanutils.PropertyUtils; -import org.json.JSONObject; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.refine.util.ParsingUtilities; - -public abstract class AbstractMetadata implements IMetadata { - @JsonIgnore - private MetadataFormat formatName = MetadataFormat.UNKNOWN; - - @JsonIgnore - protected LocalDateTime written = null; - @JsonProperty("modified") - protected LocalDateTime _modified; - - public MetadataFormat getFormatName() { - return formatName; - } - - - public void setFormatName(MetadataFormat formatName) { - this.formatName = formatName; - } - - public void loadFromJSON(String obj) throws IOException { - ParsingUtilities.mapper.readerForUpdating(this).readValue(obj); - } - - @Override - public abstract void loadFromFile(File metadataFile); - - @Override - public boolean isDirty() { - return written == null || _modified.isAfter(written); - } - - @Override - public LocalDateTime getModified() { - return _modified; - } - - @Override - public void updateModified() { - _modified = LocalDateTime.now(); - } - - protected static boolean propertyExists(Object bean, String property) { - return PropertyUtils.isReadable(bean, property) && - PropertyUtils.isWriteable(bean, property); - } - -} diff --git a/main/src/com/google/refine/model/metadata/DataPackageMetadata.java b/main/src/com/google/refine/model/metadata/DataPackageMetadata.java deleted file mode 100644 index b314d6e74..000000000 --- a/main/src/com/google/refine/model/metadata/DataPackageMetadata.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.google.refine.model.metadata; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.exception.ExceptionUtils; -import org.everit.json.schema.ValidationException; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.annotation.JsonRawValue; -import com.fasterxml.jackson.annotation.JsonValue; - -import io.frictionlessdata.datapackage.Package; -import io.frictionlessdata.datapackage.Resource; -import io.frictionlessdata.datapackage.exceptions.DataPackageException; - - -public class DataPackageMetadata extends AbstractMetadata { - private final static Logger logger = LoggerFactory.getLogger(DataPackageMetadata.class); - - public static final String DEFAULT_FILE_NAME = "datapackage.json"; - - private Package _pkg; - - @JsonValue - @JsonRawValue - public String getJson() { - return _pkg.getJson().toString(); - } - - public DataPackageMetadata() { - setFormatName(MetadataFormat.DATAPACKAGE_METADATA); - - _pkg = PackageExtension.buildPackageFromTemplate(); - } - - @Override - public void loadFromJSON(JSONObject obj) { - try { - _pkg = new Package(obj); - } catch (ValidationException | DataPackageException | IOException e) { - logger.error("Load from JSONObject failed" + obj.toString(4), - ExceptionUtils.getStackTrace(e)); - } - - logger.info("Data Package metadata loaded"); - } - - @Override - public void loadFromFile(File metadataFile) { - String jsonString = null; - try { - jsonString = FileUtils.readFileToString(metadataFile); - } catch (IOException e) { - logger.error("Load data package failed when reading from file: " + metadataFile.getAbsolutePath(), - ExceptionUtils.getStackTrace(e)); - } - - loadFromJSON(new JSONObject(jsonString)); - } - - @Override - public void loadFromStream(InputStream inputStream) { - try { - this._pkg = new Package(IOUtils.toString(inputStream)); - } catch (ValidationException e) { - logger.error("validation failed", ExceptionUtils.getStackTrace(e)); - } catch (DataPackageException e) { - logger.error("Data package excpetion when loading from stream", ExceptionUtils.getStackTrace(e)); - } catch (IOException e) { - logger.error("IO exception when loading from stream", ExceptionUtils.getStackTrace(e)); - } - } - - public List getResourcePaths() { - List listResources = new ArrayList(); - - for (Resource resource : _pkg.getResources()) { - listResources.add((String) resource.getPath()); - } - - return listResources; - } - - public Package getPackage() { - return _pkg; - } - - @Override - public List validate() { - try { - _pkg.validate(); - } catch (ValidationException | IOException | DataPackageException e) { - logger.error("validate json failed", ExceptionUtils.getStackTrace(e)); - } - - return _pkg.getErrors(); - } -} diff --git a/main/src/com/google/refine/model/metadata/DataPackageUrlRewriter.java b/main/src/com/google/refine/model/metadata/DataPackageUrlRewriter.java deleted file mode 100644 index 7944dfcf1..000000000 --- a/main/src/com/google/refine/model/metadata/DataPackageUrlRewriter.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.google.refine.model.metadata; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; - -import com.google.refine.importing.UrlRewriter; - - -public class DataPackageUrlRewriter implements UrlRewriter { - @Override - public List rewrite(String url) throws MalformedURLException, IOException { - List listResult = new ArrayList(); - - if (!filter(url)) - return listResult; - - listResult.add(new Result(url, "json", true, MetadataFormat.DATAPACKAGE_METADATA.name())); - - DataPackageMetadata meta = new DataPackageMetadata(); - meta.loadFromStream(new URL(url).openStream()); - // Import the data files. - for (String path : meta.getResourcePaths()) { - String fileURL = getBaseURL(url) + "/" + path; - listResult.add(new Result(fileURL, - "", // leave to guesser. "text/line-based/*sv" - true)); - } - - return listResult; - } - - @Override - public boolean filter(String url) { - return url.endsWith(DataPackageMetadata.DEFAULT_FILE_NAME); - } - - private String getBaseURL(String url) { - return url.replaceFirst(DataPackageMetadata.DEFAULT_FILE_NAME, ""); - } - -} diff --git a/main/src/com/google/refine/model/metadata/IMetadata.java b/main/src/com/google/refine/model/metadata/IMetadata.java deleted file mode 100644 index dc2e36006..000000000 --- a/main/src/com/google/refine/model/metadata/IMetadata.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.google.refine.model.metadata; - -import java.io.File; -import java.io.InputStream; -import java.time.LocalDateTime; -import java.util.List; - -import org.json.JSONObject; - -/** - * Interface to import/export metadata - */ -public interface IMetadata { - - public void loadFromFile(File metadataFile); - - public void loadFromStream(InputStream inputStream); - - public MetadataFormat getFormatName(); - public void setFormatName(MetadataFormat format); - - public LocalDateTime getModified(); - - public void updateModified(); - - public boolean isDirty(); - - public List validate(); -} diff --git a/main/src/com/google/refine/model/metadata/MetadataFactory.java b/main/src/com/google/refine/model/metadata/MetadataFactory.java deleted file mode 100644 index d23599659..000000000 --- a/main/src/com/google/refine/model/metadata/MetadataFactory.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.google.refine.model.metadata; - -import java.io.IOException; - -import org.apache.commons.lang3.exception.ExceptionUtils; -import org.everit.json.schema.ValidationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.refine.model.Project; -import com.google.refine.util.JSONUtilities; -import com.google.refine.util.ParsingUtilities; - -import io.frictionlessdata.datapackage.Package; -import io.frictionlessdata.datapackage.Resource; -import io.frictionlessdata.datapackage.exceptions.DataPackageException; - -public class MetadataFactory { - private final static Logger logger = LoggerFactory.getLogger(MetadataFactory.class); - - /** - * Build metadata based on the format - * @param format - * @return - */ - public static IMetadata buildMetadata(MetadataFormat format) { - IMetadata metadata = null; - if (format == MetadataFormat.PROJECT_METADATA) { - metadata = new ProjectMetadata(); - } else if (format == MetadataFormat.DATAPACKAGE_METADATA) { - metadata = new DataPackageMetadata(); - } - - return metadata; - } - - /** - * build an empty Data Package Metadata - * @return - */ - public static DataPackageMetadata buildDataPackageMetadata() { - return (DataPackageMetadata) buildMetadata(MetadataFormat.DATAPACKAGE_METADATA); - } - - /** - * Build an empty data package metadata, then populate the fields from the Project Metadata - * @param project - * @return - */ - public static DataPackageMetadata buildDataPackageMetadata(Project project) { - DataPackageMetadata dpm = buildDataPackageMetadata(); - ProjectMetadata pmd = project.getMetadata(); - Package pkg = dpm.getPackage(); - Resource resource = SchemaExtension.createResource(project.getMetadata().getName(), - project.columnModel); - try { - pkg.addResource(resource); - - putValue(pkg, Package.JSON_KEY_NAME, pmd.getName()); - putValue(pkg, PackageExtension.JSON_KEY_LAST_UPDATED, ParsingUtilities.localDateToString(pmd.getModified())); - putValue(pkg, PackageExtension.JSON_KEY_DESCRIPTION, pmd.getDescription()); - putValue(pkg, PackageExtension.JSON_KEY_TITLE, pmd.getTitle()); - putValue(pkg, PackageExtension.JSON_KEY_HOMEPAGE, pmd.getHomepage()); - putValue(pkg, PackageExtension.JSON_KEY_IMAGE, pmd.getImage()); - putValue(pkg, PackageExtension.JSON_KEY_LICENSE, pmd.getLicense()); - - pkg.removeProperty(PackageExtension.JSON_KEY_KEYWORKS); - pkg.addProperty(PackageExtension.JSON_KEY_KEYWORKS, JSONUtilities.arrayToJSONArray(pmd.getTags())); - } catch (ValidationException | IOException | DataPackageException e) { - logger.error(ExceptionUtils.getStackTrace(e)); - } - - return dpm; - } - - private static void putValue(Package pkg, String key, String value) throws DataPackageException { - if(pkg.getJson().has(key)) { - pkg.removeProperty(key); - } - pkg.addProperty(key, value); - } -} diff --git a/main/src/com/google/refine/model/metadata/MetadataFormat.java b/main/src/com/google/refine/model/metadata/MetadataFormat.java deleted file mode 100644 index 526d67c95..000000000 --- a/main/src/com/google/refine/model/metadata/MetadataFormat.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.google.refine.model.metadata; - - -/** - * A list of supported metadata format - * - */ -public enum MetadataFormat { - UNKNOWN("UNKNOWN"), - PROJECT_METADATA("PROJECT_METADATA"), - DATAPACKAGE_METADATA("DATAPACKAGE_METADATA"), - CSVW_METADATA("CSVW_METADATA"); - - private final String format; - - private MetadataFormat(final String format) { - this.format = format; - } - - @Override - public String toString() { - return format; - } -} diff --git a/main/src/com/google/refine/model/metadata/PackageExtension.java b/main/src/com/google/refine/model/metadata/PackageExtension.java deleted file mode 100644 index 4a63913be..000000000 --- a/main/src/com/google/refine/model/metadata/PackageExtension.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.google.refine.model.metadata; - -import java.io.ByteArrayOutputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.exception.ExceptionUtils; -import org.everit.json.schema.ValidationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import io.frictionlessdata.datapackage.Package; -import io.frictionlessdata.datapackage.exceptions.DataPackageException; - -/** - * This class contains some methods which is not included in the official "Data Package" repo for now. - * Some methods can be removed after the official library provide the corresponding function. - */ -public class PackageExtension { - private final static Logger logger = LoggerFactory.getLogger(PackageExtension.class); - - private static final int JSON_INDENT_FACTOR = 4; - - public static final String JSON_KEY_LAST_UPDATED = "last_updated"; - public static final String JSON_KEY_DESCRIPTION = "description"; - public static final String JSON_KEY_KEYWORKS = "keywords"; - public static final String JSON_KEY_TITLE = "title"; - public static final String JSON_KEY_HOMEPAGE = "homepage"; - public static final String JSON_KEY_IMAGE = "image"; - public static final String JSON_KEY_LICENSE = "license"; - public static final String JSON_KEY_VERSION = "version"; - - public static String DATAPACKAGE_TEMPLATE_FILE = "schemas/datapackage-template.json"; - - /** - * Do the package since the final spec for the compression/bundle are not settled yet. - * https://github.com/frictionlessdata/datapackage-js/issues/93 - * - * @param pkg Package - * @param dataByteArrayOutputStream ByteArrayOutputStream - * @param destOs OutputStream - * @throws IOException - * @throws FileNotFoundException - * @see Package#saveZip(String outputFilePath) - */ - public static void saveZip(Package pkg, final ByteArrayOutputStream dataByteArrayOutputStream, final OutputStream destOs) throws FileNotFoundException, IOException { - try(ZipOutputStream zos = new ZipOutputStream(destOs)){ - // json file - ZipEntry entry = new ZipEntry(DataPackageMetadata.DEFAULT_FILE_NAME); - zos.putNextEntry(entry); - zos.write(pkg.getJson().toString(JSON_INDENT_FACTOR).getBytes()); - zos.closeEntry(); - // default data file to data.csv or given path(can only handle one file because files cannot be restored) - String path = (String) pkg.getResources().get(0).getPath(); - entry = new ZipEntry(StringUtils.isBlank(path) ? "data.csv" : path); - zos.putNextEntry(entry); - zos.write(dataByteArrayOutputStream.toByteArray()); - zos.closeEntry(); - } - } - - /** - * To build a Package object from a template file contains empty metadata - * - * @param templateFile - */ - public static Package buildPackageFromTemplate() { - try { - ClassLoader classLoader = PackageExtension.class.getClassLoader(); - InputStream inputStream = classLoader.getResourceAsStream(DATAPACKAGE_TEMPLATE_FILE); - return new Package(IOUtils.toString(inputStream), false); - } catch (ValidationException e) { - logger.error("validation failed", ExceptionUtils.getStackTrace(e)); - } catch (DataPackageException e) { - logger.error("DataPackage Exception", ExceptionUtils.getStackTrace(e)); - } catch (IOException e) { - logger.error("IOException when build package from template", ExceptionUtils.getStackTrace(e)); - } - - return null; - } -} diff --git a/main/src/com/google/refine/model/metadata/ProjectMetadata.java b/main/src/com/google/refine/model/metadata/ProjectMetadata.java deleted file mode 100644 index 21770e1af..000000000 --- a/main/src/com/google/refine/model/metadata/ProjectMetadata.java +++ /dev/null @@ -1,483 +0,0 @@ -/* - -Copyright 2010, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -package com.google.refine.model.metadata; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Serializable; -import java.lang.reflect.InvocationTargetException; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.commons.beanutils.BeanUtils; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.exception.ExceptionUtils; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONTokener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonRawValue; -import com.fasterxml.jackson.annotation.JsonUnwrapped; -import com.fasterxml.jackson.annotation.JsonView; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.refine.ProjectManager; -import com.google.refine.preference.PreferenceStore; -import com.google.refine.preference.TopList; -import com.google.refine.util.JSONUtilities; -import com.google.refine.util.JsonViews; -import com.google.refine.util.ParsingUtilities; - -public class ProjectMetadata extends AbstractMetadata { - final public static String DEFAULT_FILE_NAME = "metadata.json"; - final public static String TEMP_FILE_NAME = "metadata.temp.json"; - final public static String OLD_FILE_NAME = "metadata.old.json"; - - @JsonProperty("created") - private LocalDateTime _created; - @JsonProperty("name") - private String _name = ""; - @JsonProperty("password") - @JsonView(JsonViews.SaveMode.class) - private String _password = ""; - - @JsonProperty("encoding") - @JsonView(JsonViews.SaveMode.class) - private String _encoding = ""; - @JsonProperty("encodingConfidence") - @JsonView(JsonViews.SaveMode.class) - private int _encodingConfidence; - @JsonProperty("rowCount") - private int _rowCount; - // user metadata - @JsonIgnore - private ArrayNode _userMetadata = ParsingUtilities.mapper.createArrayNode(); - - // _tags maps to keywords of the data package metadata - @JsonProperty("tags") - private String[] _tags = new String[0]; - @JsonProperty("creator") - private String _creator = ""; - @JsonProperty("contributors") - private String _contributors = ""; - @JsonProperty("subject") - private String _subject = ""; // Several refine projects may be linked - @JsonProperty("description") - private String _description = ""; // free form of comment - - // import options is an array for 1-n data sources - @JsonIgnore - private ArrayNode _importOptionMetadata = ParsingUtilities.mapper.createArrayNode(); - - @JsonProperty("customMetadata") - private Map _customMetadata = new HashMap(); - @JsonProperty("preferences") - @JsonView(JsonViews.SaveMode.class) - private PreferenceStore _preferenceStore = new PreferenceStore(); - - // below 5 fields are from data package metadata: - @JsonProperty("title") - private String title = ""; - @JsonProperty("homepage") - private String homepage; - @JsonProperty("image") - private String image = ""; - @JsonProperty("license") - private String license = ""; - @JsonProperty("version") - private String version = ""; - - @JsonProperty(PreferenceStore.USER_METADATA_KEY) - @JsonInclude(Include.NON_NULL) - public ArrayNode getJsonUserMetadata() { - if (_userMetadata.size() > 0) { - return _userMetadata; - } - return null; - } - - @JsonProperty(PreferenceStore.USER_METADATA_KEY) - protected void setUserMetadataJson(ArrayNode json) { - _userMetadata = json; - } - - @JsonProperty("importOptionMetadata") - @JsonInclude(Include.NON_NULL) - public ArrayNode getJsonImportOptionMetadata() { - if (_importOptionMetadata.size() > 0) { - return _importOptionMetadata; - } - return null; - } - - @JsonProperty("importOptionMetadata") - public void setImportOptionMetadataJson(ArrayNode options) { - _importOptionMetadata = options; - // this field should always be present so we can update the last updated time here - this.written = LocalDateTime.now(); - } - - // backwards compatibility - @JsonProperty("expressions") - protected void setExpressions(TopList expressions) { - this._preferenceStore.put("scripting.expressions", expressions); - } - - private final static Logger logger = LoggerFactory.getLogger("project_metadata"); - - protected ProjectMetadata(LocalDateTime date) { - setFormatName(MetadataFormat.PROJECT_METADATA); - _created = date; - preparePreferenceStore(_preferenceStore); - } - - public ProjectMetadata() { - this(LocalDateTime.now()); - _modified = _created; - } - - public ProjectMetadata(LocalDateTime created, LocalDateTime modified, String name) { - this(created); - _modified = modified; - _name = name; - } - - public void setRowCount(int rowCount) { - this._rowCount = rowCount; - updateModified(); - } - - @JsonProperty("saveModeWritten") - @JsonView(JsonViews.SaveMode.class) - @JsonInclude(Include.NON_NULL) - public String setSaveModeWritten() { - written = LocalDateTime.now(); - return null; - } - - static protected void preparePreferenceStore(PreferenceStore ps) { - ProjectManager.preparePreferenceStore(ps); - // Any project specific preferences? - } - - public LocalDateTime getCreated() { - return _created; - } - - public void setEncodingConfidence(int confidence) { - this._encodingConfidence = confidence; - updateModified(); - } - - public void setEncodingConfidence(String confidence) { - if (confidence != null) { - this.setEncodingConfidence(Integer.parseInt(confidence)); - } - } - - public int getEncodingConfidence() { - return _encodingConfidence; - } - - public void setTags(String[] tags) { - if (tags != null) { - List tmpTags = new ArrayList(tags.length); - for (String tag : tags) { - if (tag != null) { - String trimmedTag = tag.trim(); - - if (!trimmedTag.isEmpty()) { - tmpTags.add(trimmedTag); - } - } - } - this._tags = tmpTags.toArray(new String[tmpTags.size()]); - } else { - this._tags = tags; - } - - updateModified(); - } - - public void appendTags(String[] tags) { - String[] mergedTags = (String[])ArrayUtils.addAll(this._tags, tags); - setTags(mergedTags); - } - - public String[] getTags() { - if (_tags == null) this._tags = new String[0]; - return _tags; - } - - public void setPassword(String password) { - this._password = password; - updateModified(); - } - - public String getPassword() { - return _password; - } - - public LocalDateTime getModified() { - return _modified; - } - - public void updateModified() { - _modified = LocalDateTime.now(); - } - - public PreferenceStore getPreferenceStore() { - return _preferenceStore; - } - - public Serializable getCustomMetadata(String key) { - return _customMetadata.get(key); - } - - public void setCustomMetadata(String key, Serializable value) { - if (value == null) { - _customMetadata.remove(key); - } else { - _customMetadata.put(key, value); - } - updateModified(); - } - - @JsonIgnore - public ArrayNode getImportOptionMetadata() { - return _importOptionMetadata; - } - - @JsonIgnore - public void setImportOptionMetadata(ArrayNode jsonArray) { - _importOptionMetadata = jsonArray; - updateModified(); - } - - public void appendImportOptionMetadata(ObjectNode options) { - _importOptionMetadata.add(options); - updateModified(); - } - - public String getEncoding() { - return _encoding; - } - - public void setName(String name) { - this._name = name; - updateModified(); - } - - public String getName() { - return _name; - } - - public void setEncoding(String encoding) { - this._encoding = encoding; - updateModified(); - } - - public String getCreator() { - return _creator; - } - - public void setCreator(String creator) { - this._creator = creator; - updateModified(); - } - - - public String getContributors() { - return _contributors; - } - - public void setContributors(String contributors) { - this._contributors = contributors; - updateModified(); - } - - - public String getSubject() { - return _subject; - } - - public void setSubject(String subject) { - this._subject = subject; - updateModified(); - } - - public String getDescription() { - return _description; - } - - public void setDescription(String description) { - this._description = description; - updateModified(); - } - - - public String getTitle() { - return title; - } - - - public void setTitle(String title) { - this.title = title; - updateModified(); - } - - - public String getHomepage() { - return homepage; - } - - - public void setHomepage(String homepage) { - this.homepage = homepage; - updateModified(); - } - - - public String getImage() { - return image; - } - - - public void setImage(String image) { - this.image = image; - updateModified(); - } - - - public String getLicense() { - return license; - } - - - public void setLicense(String license) { - this.license = license; - updateModified(); - } - - public String getVersion() { - return version; - } - - - public void setVersion(String version) { - this.version = version; - updateModified(); - } - - public ArrayNode getUserMetadata() { - return _userMetadata; - } - - public void setUserMetadata(ArrayNode userMetadata) { - this._userMetadata = userMetadata; - } - - private void updateUserMetadata(String metaName, String valueString) { - for (int i = 0; i < _userMetadata.size(); i++) { - try { - JsonNode obj = _userMetadata.get(i); - if (obj.get("name").asText("").equals(metaName)) { - ((ObjectNode) obj).put("value", valueString); - } - } catch (JSONException e) { - logger.error(ExceptionUtils.getStackTrace(e)); - } - } - } - - public void setAnyStringField(String metaName, String valueString) { - if (propertyExists(this, metaName)) { - try { - if (metaName.equals("tags")) { - BeanUtils.setProperty(this, metaName, valueString.split(",")); - } else - BeanUtils.setProperty(this, metaName, valueString); - } catch (IllegalAccessException | InvocationTargetException ite) { - logger.error(ExceptionUtils.getStackTrace(ite)); - } - } else { - updateUserMetadata(metaName, valueString); - } - } - - @Override - public void loadFromFile(File metadataFile) { - InputStream targetStream = null; - try { - targetStream = FileUtils.openInputStream(metadataFile); - } catch (IOException e) { - logger.error(ExceptionUtils.getStackTrace(e)); - } - loadFromStream(targetStream); - } - - @Override - public void loadFromStream(InputStream inputStream) { - try (InputStreamReader reader = new InputStreamReader(inputStream)) { - JSONTokener tokener = new JSONTokener(reader); - JSONObject obj = (JSONObject) tokener.nextValue(); - - this.loadFromJSON(IOUtils.toString(inputStream)); - } catch (IOException e) { - logger.error(ExceptionUtils.getStackTrace(e)); - } - } - - @Override - public List validate() { - return null; - } - -} diff --git a/main/src/com/google/refine/model/metadata/SchemaExtension.java b/main/src/com/google/refine/model/metadata/SchemaExtension.java deleted file mode 100644 index fabe7bec8..000000000 --- a/main/src/com/google/refine/model/metadata/SchemaExtension.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.google.refine.model.metadata; - -import com.google.refine.model.Column; -import com.google.refine.model.ColumnModel; - -import io.frictionlessdata.datapackage.Resource; -import io.frictionlessdata.tableschema.Field; -import io.frictionlessdata.tableschema.Schema; - -/** - * This class contains some methods which is not included in the official "table schema" repo for now. - * Some methods can be removed after the official library provide the corresponding function. - */ -public class SchemaExtension { - private static final String DEFAULT_RESOURCE_PATH = "data/"; - private static final String DEFAULT_RESOURCE_SUFFIX = ".csv"; - - /** - * insert the field to schema at specified position - * @param schema - * @param field - * @param position - */ - public static void insertField(Schema schema, Field field, int position) { - schema.getFields().add(position, field); - } - - /** - * Remove the filed from the schema at specified position - * @param schema - * @param index - * @return - */ - public static Field removeField(Schema schema, int index) { - return schema.getFields().remove(index); - } - - /** - * Create a resource by name, get the schema information from the ColumnModel - * @param resourceName - * @param columnModel - * @return - * @see ColumnModel - */ - public static Resource createResource(String resourceName, ColumnModel columnModel) { - // populate the data package schema from the openrefine column model - Schema schema = new Schema(); - for (Column column : columnModel.columns) { - schema.addField(new Field(column.getName(), - column.getType(), - column.getFormat(), - column.getTitle(), - column.getDescription(), - column.getConstraints())); - } - - Resource resource = new Resource(resourceName, - DEFAULT_RESOURCE_PATH + resourceName + DEFAULT_RESOURCE_SUFFIX, - schema.getJson()); - - return resource; - } - -} diff --git a/main/src/com/google/refine/model/metadata/validator/ValidateOperation.java b/main/src/com/google/refine/model/metadata/validator/ValidateOperation.java deleted file mode 100644 index 10d0f3a86..000000000 --- a/main/src/com/google/refine/model/metadata/validator/ValidateOperation.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.google.refine.model.metadata.validator; - -import org.json.JSONObject; - -import com.google.refine.model.AbstractOperation; -import com.google.refine.model.Project; - -public class ValidateOperation extends AbstractOperation { - private Project project; - private JSONObject options; - - public ValidateOperation(Project project, JSONObject options) { - this.project = project; - this.options = options; - } - - public JSONObject startProcess() { - return ValidatorInspector.inspect(project, options); - } - -} diff --git a/main/src/com/google/refine/model/metadata/validator/ValidatorConfig.java b/main/src/com/google/refine/model/metadata/validator/ValidatorConfig.java deleted file mode 100644 index 4057761fb..000000000 --- a/main/src/com/google/refine/model/metadata/validator/ValidatorConfig.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.google.refine.model.metadata.validator; - - -public class ValidatorConfig { - -} diff --git a/main/src/com/google/refine/model/metadata/validator/ValidatorExceptions.java b/main/src/com/google/refine/model/metadata/validator/ValidatorExceptions.java deleted file mode 100644 index e023c689a..000000000 --- a/main/src/com/google/refine/model/metadata/validator/ValidatorExceptions.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.google.refine.model.metadata.validator; - - -public class ValidatorExceptions { - -} diff --git a/main/src/com/google/refine/model/metadata/validator/ValidatorInspector.java b/main/src/com/google/refine/model/metadata/validator/ValidatorInspector.java deleted file mode 100644 index 829001867..000000000 --- a/main/src/com/google/refine/model/metadata/validator/ValidatorInspector.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.google.refine.model.metadata.validator; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.commons.lang3.exception.ExceptionUtils; -import org.json.JSONArray; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.refine.model.Column; -import com.google.refine.model.Project; -import com.google.refine.model.metadata.validator.checks.TypeorFormatError; -import com.google.refine.model.metadata.validator.checks.Validator; -import com.google.refine.util.JSONUtilities; - -public class ValidatorInspector { - private final static Logger logger = LoggerFactory.getLogger(ValidatorInspector.class); - - /** - * Return a report contains the validate result - * @param project - * @param options - * @return - */ - public static JSONObject inspect(Project project, JSONObject options) { - List columnNames; - String COLUMN_NAMES_KEY = "columnNames"; - Map> columnToCheckersMap = new HashMap>(); - JSONArray validateReport = new JSONArray(); - - logger.info("starting inspect with options:" + options.toString()); - columnNames = JSONUtilities.toStringList(options.getJSONArray(COLUMN_NAMES_KEY)); - - // build the check items - List validatorList = null; - for(String columnName : columnNames) { - validatorList = compileChecks(project, columnName, options); - if (validatorList.size() >= 0) - columnToCheckersMap.put(columnName, validatorList); - } - logger.info("=========================================================="); - logger.info("Inspector finished the checks compile. will do following check:"); - for (Entry> entry : columnToCheckersMap.entrySet()) { - logger.info("Column Name: " + entry.getKey()); - for (Validator v : entry.getValue()) { - logger.info("\t Validator: " + v.getClass().getSimpleName()); - } - } - logger.info("=========================================================="); - - // do the inspect in another loop: - for(String columnName : columnNames) { - List validators = columnToCheckersMap.get(columnName); - if (validators != null) { - for (Validator validator : validators) { - JSONArray result = validator.validate(); - if (result != null && result.length() > 0) - JSONUtilities.concatArray(validateReport, result); - } - } - } - logger.info("Inspector finished the validation."); - - return new JSONObject().put("validation-reports", (Object)validateReport); - } - - private static List compileChecks(Project project, String columnName, JSONObject options) { - Map constraintHandlersMap = ValidatorRegistry.getInstance().getConstraintHandlersMap(); - - Column column = project.columnModel.getColumnByName(columnName); - List validatorList = new ArrayList(); - - int columnIndex = project.columnModel.getColumnIndexByName(columnName); - - validatorList.add(new TypeorFormatError(project, columnIndex, options)); - - - if (column.getConstraints() != null) { - for (Entry entry : column.getConstraints().entrySet()) { - Class clazz = constraintHandlersMap.get(entry.getKey()); - try { - Constructor c = clazz.getConstructor(Project.class, int.class, JSONObject.class); - validatorList.add(c.newInstance(project, columnIndex, options)); - } catch (InstantiationException | IllegalAccessException | IllegalArgumentException - | InvocationTargetException | NoSuchMethodException | SecurityException e) { - logger.error("failed to do compileChecks:" + ExceptionUtils.getStackTrace(e)); - } - } - } - - return validatorList; - } - - -} diff --git a/main/src/com/google/refine/model/metadata/validator/ValidatorRegistry.java b/main/src/com/google/refine/model/metadata/validator/ValidatorRegistry.java deleted file mode 100644 index d4e7e6234..000000000 --- a/main/src/com/google/refine/model/metadata/validator/ValidatorRegistry.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.google.refine.model.metadata.validator; - -import java.util.HashMap; -import java.util.Map; - -import com.google.refine.model.metadata.validator.checks.EnumerableConstraint; -import com.google.refine.model.metadata.validator.checks.MaximumConstraint; -import com.google.refine.model.metadata.validator.checks.MaximumLengthConstraint; -import com.google.refine.model.metadata.validator.checks.MinimumConstraint; -import com.google.refine.model.metadata.validator.checks.MinimumLengthConstraint; -import com.google.refine.model.metadata.validator.checks.PatternConstraint; -import com.google.refine.model.metadata.validator.checks.RequiredConstraint; - -import io.frictionlessdata.tableschema.Field; - -public class ValidatorRegistry { - private static ValidatorRegistry instance = null; - private Map constraintHandlersMap = null; - - private ValidatorRegistry() { - constraintHandlersMap = new HashMap(); - constraintHandlersMap.put(Field.CONSTRAINT_KEY_ENUM,EnumerableConstraint.class); - constraintHandlersMap.put(Field.CONSTRAINT_KEY_MAXIMUM, MaximumConstraint.class); - constraintHandlersMap.put(Field.CONSTRAINT_KEY_MAX_LENGTH, MaximumLengthConstraint.class); - constraintHandlersMap.put(Field.CONSTRAINT_KEY_MINIMUM, MinimumConstraint.class); - constraintHandlersMap.put(Field.CONSTRAINT_KEY_MIN_LENGTH, MinimumLengthConstraint.class); - constraintHandlersMap.put(Field.CONSTRAINT_KEY_PATTERN, PatternConstraint.class); - constraintHandlersMap.put(Field.CONSTRAINT_KEY_REQUIRED, RequiredConstraint.class); - } - - public static ValidatorRegistry getInstance() { - if (instance == null) - instance = new ValidatorRegistry(); - - return instance; - } - - public Map getConstraintHandlersMap() { - return constraintHandlersMap; - } -} diff --git a/main/src/com/google/refine/model/metadata/validator/ValidatorSpec.java b/main/src/com/google/refine/model/metadata/validator/ValidatorSpec.java deleted file mode 100644 index 94df475dd..000000000 --- a/main/src/com/google/refine/model/metadata/validator/ValidatorSpec.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.google.refine.model.metadata.validator; - -import java.util.Locale; -import java.util.ResourceBundle; - -public class ValidatorSpec { - private static String VALIDATOR_RESOURCE_BUNDLE = "validator-resource-bundle"; - - private static ValidatorSpec instance = null; - private ResourceBundle bundle; - - private ValidatorSpec() { - Locale locale = new Locale("en", "US"); - bundle = ResourceBundle.getBundle(VALIDATOR_RESOURCE_BUNDLE, locale); - } - - public static ValidatorSpec getInstance() { - if (instance == null) - instance = new ValidatorSpec(); - - return instance; - } - - public String getMessage(String code) { - return bundle.getString(code); - } - -} diff --git a/main/src/com/google/refine/model/metadata/validator/checks/AbstractValidator.java b/main/src/com/google/refine/model/metadata/validator/checks/AbstractValidator.java deleted file mode 100644 index d93958969..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/AbstractValidator.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.lang3.text.StrSubstitutor; -import org.json.JSONArray; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.refine.model.Cell; -import com.google.refine.model.Column; -import com.google.refine.model.Project; -import com.google.refine.model.Row; -import com.google.refine.model.metadata.validator.ValidatorSpec; - -public abstract class AbstractValidator implements Validator { - protected final Logger logger = LoggerFactory.getLogger(this.getClass()); - - protected Project project; - protected int cellIndex; - protected JSONObject options; - protected Column column; - protected String code; - - protected JSONArray jsonErros = null; - - protected Map lookup = new HashMap(6); - - /** - * Constructor - * @param project - * @param cellIndex - * @param options - */ - public AbstractValidator(Project project, int cellIndex, JSONObject options) { - this.project = project; - this.cellIndex = cellIndex; - this.options = options; - this.column = project.columnModel.getColumnByCellIndex(cellIndex); - } - - @Override - public JSONArray validate() { - for (int rowIndex = 0;rowIndex < project.rows.size();rowIndex++) { - Row row = project.rows.get(rowIndex); - Cell cell = row.getCell(cellIndex); - if (filter(cell)) - continue; - - boolean checkResult = checkCell(cell); - if (!checkResult) { - addError(formatErrorMessage(cell, rowIndex + 1)); - } - } - return jsonErros; - } - - @Override - public JSONObject formatErrorMessage(Cell cell, int rowIndex) { - String message = null; - message = ValidatorSpec.getInstance().getMessage(code); - String formattedMessage = format(message, cell.value.toString(), rowIndex, cellIndex, code); - JSONObject json = new JSONObject(); - json.put("code", code); - json.put("message", formattedMessage); - json.put("row-number", rowIndex); - json.put("column-number", cellIndex); - - return json; - } - - /** - * MessageFormat.format cannot take the named parameters. - * @param message - * @param value - * @param rowIndex - * @param cellIndex - * @param code - * @return - */ - private String format(String message, String value, int rowIndex, int cellIndex, String code) { - lookup.put("value", value); - lookup.put("row_number", Integer.toString(rowIndex)); - lookup.put("column_number", Integer.toString(cellIndex)); - lookup.put("constraint", code); - customizedFormat(); - - return new StrSubstitutor(lookup).replace(message); - } - - /* - * Empty body since default there is no customized Format - * @see com.google.refine.model.metadata.validator.checks.Validator#customizedFormat() - */ - @Override - public void customizedFormat() { - } - - /** - * will skip the cell if return true - */ - @Override - public boolean filter(Cell cell) { - return cell == null || cell.value == null; - } - - @Override - public boolean checkCell(Cell cell) { - return false; - } - - @Override - public void addError(JSONObject result) { - if (jsonErros == null) - jsonErros = new JSONArray(); - - jsonErros.put(result); - } - -} diff --git a/main/src/com/google/refine/model/metadata/validator/checks/BlankHeader.java b/main/src/com/google/refine/model/metadata/validator/checks/BlankHeader.java deleted file mode 100644 index 7598ceef0..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/BlankHeader.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Project; - -public class BlankHeader extends AbstractValidator { - public BlankHeader(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/BlankRow.java b/main/src/com/google/refine/model/metadata/validator/checks/BlankRow.java deleted file mode 100644 index aeb5d2897..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/BlankRow.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Project; - -public class BlankRow extends AbstractValidator { - - public BlankRow(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/DuplicateHeader.java b/main/src/com/google/refine/model/metadata/validator/checks/DuplicateHeader.java deleted file mode 100644 index 61b21533a..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/DuplicateHeader.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Project; - -public class DuplicateHeader extends AbstractValidator { - public DuplicateHeader(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/DuplicateRow.java b/main/src/com/google/refine/model/metadata/validator/checks/DuplicateRow.java deleted file mode 100644 index 07d31b2fd..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/DuplicateRow.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Project; - -public class DuplicateRow extends AbstractValidator { - - public DuplicateRow(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/EnumerableConstraint.java b/main/src/com/google/refine/model/metadata/validator/checks/EnumerableConstraint.java deleted file mode 100644 index 29bb266a4..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/EnumerableConstraint.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import java.util.List; - -import org.json.JSONObject; - -import com.google.refine.model.Cell; -import com.google.refine.model.Project; - -import io.frictionlessdata.tableschema.Field; - -public class EnumerableConstraint extends AbstractValidator { - private List enumList; - - @SuppressWarnings("unchecked") - public EnumerableConstraint(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - this.code = "enumerable-constraint"; - - enumList = (List) column.getConstraints().get(Field.CONSTRAINT_KEY_ENUM); - } - - @Override - public boolean checkCell(Cell cell) { - // XXX: deal with recon - return enumList.contains(cell.value); - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/ExtraHeader.java b/main/src/com/google/refine/model/metadata/validator/checks/ExtraHeader.java deleted file mode 100644 index d52f2b21a..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/ExtraHeader.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Project; - -public class ExtraHeader extends AbstractValidator { - public ExtraHeader(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/ExtraValue.java b/main/src/com/google/refine/model/metadata/validator/checks/ExtraValue.java deleted file mode 100644 index 213e9d46f..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/ExtraValue.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Project; - -public class ExtraValue extends AbstractValidator { - - public ExtraValue(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/MaximumConstraint.java b/main/src/com/google/refine/model/metadata/validator/checks/MaximumConstraint.java deleted file mode 100644 index d937c5c81..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/MaximumConstraint.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Cell; -import com.google.refine.model.Project; - -import io.frictionlessdata.tableschema.Field; -import io.frictionlessdata.tableschema.exceptions.ConstraintsException; -import io.frictionlessdata.tableschema.exceptions.InvalidCastException; - -@SuppressWarnings("rawtypes") -public class MaximumConstraint extends AbstractValidator { - private String threshold; - - public MaximumConstraint(Project project, int cellIndex, JSONObject options) throws InvalidCastException, ConstraintsException { - super(project, cellIndex, options); - this.code = "maximum-constraint"; - threshold = (String)column.getConstraints() - .get(Field.CONSTRAINT_KEY_MAXIMUM); - } - - @SuppressWarnings("unchecked") - @Override - public boolean checkCell(Cell cell) { - boolean valid = true; - - try { - Comparable value = column.castValue(cell.value.toString()); - // return this - threshold - if (value.compareTo(column.castValue(threshold)) > 0) - valid = false; - } catch (InvalidCastException | ConstraintsException e) { - valid = false; - } - - return valid; - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/MaximumLengthConstraint.java b/main/src/com/google/refine/model/metadata/validator/checks/MaximumLengthConstraint.java deleted file mode 100644 index fddcc2b78..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/MaximumLengthConstraint.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Cell; -import com.google.refine.model.Project; - -import io.frictionlessdata.tableschema.Field; - -public class MaximumLengthConstraint extends AbstractValidator { - private int maxLength; - - public MaximumLengthConstraint(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - this.code = "maximum-length-constraint"; - - maxLength = (int) column.getConstraints() - .get(Field.CONSTRAINT_KEY_MAX_LENGTH); - } - - @Override - public boolean checkCell(Cell cell) { - return cell.value.toString().length() <= maxLength; - } - -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/MinimumConstraint.java b/main/src/com/google/refine/model/metadata/validator/checks/MinimumConstraint.java deleted file mode 100644 index 2ac90db56..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/MinimumConstraint.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Cell; -import com.google.refine.model.Project; - -import io.frictionlessdata.tableschema.Field; -import io.frictionlessdata.tableschema.exceptions.ConstraintsException; -import io.frictionlessdata.tableschema.exceptions.InvalidCastException; - -@SuppressWarnings("rawtypes") -public class MinimumConstraint extends AbstractValidator { -private String threshold; - - public MinimumConstraint(Project project, int cellIndex, JSONObject options) throws InvalidCastException, ConstraintsException { - super(project, cellIndex, options); - this.code = "minimum-constraint"; - threshold = (String)column.getConstraints() - .get(Field.CONSTRAINT_KEY_MINIMUM); - } - - @SuppressWarnings("unchecked") - @Override - public boolean checkCell(Cell cell) { - boolean valid = true; - - try { - Comparable value = column.castValue(cell.value.toString()); - // return this - threshold - if (value.compareTo(column.castValue(threshold)) < 0) - valid = false; - } catch (InvalidCastException | ConstraintsException e) { - valid = false; - } - - return valid; - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/MinimumLengthConstraint.java b/main/src/com/google/refine/model/metadata/validator/checks/MinimumLengthConstraint.java deleted file mode 100644 index 4b42e98f6..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/MinimumLengthConstraint.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Cell; -import com.google.refine.model.Project; - -import io.frictionlessdata.tableschema.Field; - -public class MinimumLengthConstraint extends AbstractValidator { - private int minLength; - - public MinimumLengthConstraint(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - this.code = "minimum-length-constrain"; - - minLength = (int)column.getConstraints() - .get(Field.CONSTRAINT_KEY_MIN_LENGTH); - } - - @Override - public boolean filter(Cell cell) { - return true; - } - - @Override - public boolean checkCell(Cell cell) { - if (cell == null || cell.value == null) - return false; - - return cell.value.toString().length() >= minLength; - } - - -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/MissingHeader.java b/main/src/com/google/refine/model/metadata/validator/checks/MissingHeader.java deleted file mode 100644 index 1c4f53797..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/MissingHeader.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Project; - -public class MissingHeader extends AbstractValidator { - - public MissingHeader(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/MissingValue.java b/main/src/com/google/refine/model/metadata/validator/checks/MissingValue.java deleted file mode 100644 index b3a1d31cc..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/MissingValue.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Project; - -public class MissingValue extends AbstractValidator { - - public MissingValue(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/NonMatchingHeader.java b/main/src/com/google/refine/model/metadata/validator/checks/NonMatchingHeader.java deleted file mode 100644 index 355c238fc..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/NonMatchingHeader.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Project; - -public class NonMatchingHeader extends AbstractValidator { - - public NonMatchingHeader(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/PatternConstraint.java b/main/src/com/google/refine/model/metadata/validator/checks/PatternConstraint.java deleted file mode 100644 index f03a3a2b6..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/PatternConstraint.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.json.JSONObject; - -import com.google.refine.model.Cell; -import com.google.refine.model.Project; - -import io.frictionlessdata.tableschema.Field; - -public class PatternConstraint extends AbstractValidator { - private String regexPattern; - - public PatternConstraint(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - this.code = "pattern-constraint"; - - this.regexPattern = (String)column.getConstraints().get(Field.CONSTRAINT_KEY_PATTERN); - } - - @Override - public boolean checkCell(Cell cell) { - Pattern pattern = Pattern.compile(regexPattern); - Matcher matcher = pattern.matcher((String)cell.value); - - return matcher.matches(); - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/RequiredConstraint.java b/main/src/com/google/refine/model/metadata/validator/checks/RequiredConstraint.java deleted file mode 100644 index 4934434d1..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/RequiredConstraint.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.apache.commons.lang3.StringUtils; -import org.json.JSONObject; - -import com.google.refine.model.Cell; -import com.google.refine.model.Project; - -public class RequiredConstraint extends AbstractValidator { - - public RequiredConstraint(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - this.code = "required-constraint"; - } - - @Override - public boolean filter(Cell cell) { - // always check - return false; - } - - @Override - public boolean checkCell(Cell cell) { - return StringUtils.isNotBlank(cell.value.toString()); - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/TypeorFormatError.java b/main/src/com/google/refine/model/metadata/validator/checks/TypeorFormatError.java deleted file mode 100644 index c6d9d26ac..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/TypeorFormatError.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Cell; -import com.google.refine.model.Project; - -import io.frictionlessdata.tableschema.exceptions.ConstraintsException; -import io.frictionlessdata.tableschema.exceptions.InvalidCastException; - -public class TypeorFormatError extends AbstractValidator { - private String type; - private String format; - - public TypeorFormatError(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - this.code = "type-or-format-error"; - - this.type = column.getType(); - this.format = column.getFormat(); - } - - @Override - public boolean checkCell(Cell cell) { - boolean valid = true; - - try { - column.castValue(cell.value.toString()); - } catch (InvalidCastException | ConstraintsException e) { - // patch for issue: https://github.com/frictionlessdata/tableschema-java/issues/21 - if ("number".equals(type)) { - try { - column.castValue(cell.value.toString() + ".0"); - } catch (InvalidCastException | ConstraintsException e1) { - valid = false; - } - } else - valid = false; - } - - return valid; - } - - @Override - public void customizedFormat() { - lookup.put("field_type", type); - lookup.put("field_format", format); - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/UniqueConstraint.java b/main/src/com/google/refine/model/metadata/validator/checks/UniqueConstraint.java deleted file mode 100644 index cfc9d344c..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/UniqueConstraint.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONObject; - -import com.google.refine.model.Project; - -public class UniqueConstraint extends AbstractValidator { - public UniqueConstraint(Project project, int cellIndex, JSONObject options) { - super(project, cellIndex, options); - this.code = "unique-constraint"; - } -} \ No newline at end of file diff --git a/main/src/com/google/refine/model/metadata/validator/checks/Validator.java b/main/src/com/google/refine/model/metadata/validator/checks/Validator.java deleted file mode 100644 index 5ea740d22..000000000 --- a/main/src/com/google/refine/model/metadata/validator/checks/Validator.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.google.refine.model.metadata.validator.checks; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.google.refine.model.Cell; - -public interface Validator { - /** - * Given the options and cell index, apply the validate operation. - * @return - */ - public JSONArray validate(); - - /** - * Skip if cell is incomplete - * @return - */ - public boolean filter(Cell cell); - - /** - * check the cell against the table schema - * @param cell - * @return false if fails the validation / check. Otherwise return true - */ - public boolean checkCell(Cell cell); - - /** - * Add error into the report for return - */ - public void addError(JSONObject result); - - public JSONObject formatErrorMessage(Cell cell, int rowIndex); - - public void customizedFormat(); -} diff --git a/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java b/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java index 4f0196110..db9620974 100644 --- a/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java +++ b/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java @@ -256,7 +256,7 @@ public class ReconciledDataExtensionJob { String str = val.getString("str"); storeCell(rows, rowindex, colindex, str); } else if (val.has("float")) { - float v = val.getBigDecimal("float").floatValue(); + float v = Float.parseFloat(val.getString("float")); storeCell(rows, rowindex, colindex, v); } else if (val.has("int")) { int v = Integer.parseInt(val.getString("int")); diff --git a/main/src/com/google/refine/model/recon/StandardReconConfig.java b/main/src/com/google/refine/model/recon/StandardReconConfig.java index 78cda9334..7a7fa453e 100644 --- a/main/src/com/google/refine/model/recon/StandardReconConfig.java +++ b/main/src/com/google/refine/model/recon/StandardReconConfig.java @@ -47,7 +47,7 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang.StringUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; diff --git a/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java b/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java index 3fb901a64..f7d3bda32 100644 --- a/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java @@ -41,7 +41,6 @@ import java.util.Map; import java.util.Set; import org.apache.commons.lang3.StringUtils; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.refine.browsing.Engine; diff --git a/main/src/com/google/refine/preference/PreferenceStore.java b/main/src/com/google/refine/preference/PreferenceStore.java index 82e61a152..735a34be2 100644 --- a/main/src/com/google/refine/preference/PreferenceStore.java +++ b/main/src/com/google/refine/preference/PreferenceStore.java @@ -56,9 +56,6 @@ import com.google.refine.util.ParsingUtilities; public class PreferenceStore { public static final String USER_METADATA_KEY = "userMetadata"; - // use to populate "creator" filed in metadata. https://github.com/OpenRefine/OpenRefine/issues/1393 - public static final String USER_NAME = "username"; - private boolean dirty = false; protected Map _prefs = new HashMap<>(); diff --git a/main/src/com/google/refine/util/JSObject.java b/main/src/com/google/refine/util/JSObject.java index 18d22fef1..06bb8bd56 100644 --- a/main/src/com/google/refine/util/JSObject.java +++ b/main/src/com/google/refine/util/JSObject.java @@ -39,7 +39,7 @@ import java.util.Enumeration; import java.util.Iterator; import java.util.Properties; -import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.lang.StringEscapeUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -157,7 +157,7 @@ public class JSObject extends Properties { writeJSONObject(writer, (JSONObject) o); } else { - writer.print("\"" + StringEscapeUtils.escapeEcmaScript(o.toString()) + "\""); + writer.print("\"" + StringEscapeUtils.escapeJavaScript(o.toString()) + "\""); } } } diff --git a/main/src/com/google/refine/util/ParsingUtilities.java b/main/src/com/google/refine/util/ParsingUtilities.java index cb1ede0f4..a73f8279c 100644 --- a/main/src/com/google/refine/util/ParsingUtilities.java +++ b/main/src/com/google/refine/util/ParsingUtilities.java @@ -59,9 +59,9 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; -import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/main/src/validator-resource-bundle.properties b/main/src/validator-resource-bundle.properties deleted file mode 100644 index ca059b67d..000000000 --- a/main/src/validator-resource-bundle.properties +++ /dev/null @@ -1,13 +0,0 @@ -schema-error=Table Schema error: ${error_message} -non-matching-header=Header in column ${column_number} doesn't match field name ${field_name} in the schema -extra-header=There is an extra header in column ${column_number} -missing-header=There is a missing header in column ${column_number} -type-or-format-error=The value ${value} in row ${row_number} and column ${column_number} is not type ${field_type} and format ${field_format} -required-constraint=Column ${column_number} is a required field, but row ${row_number} has no value -pattern-constraint=The value ${value} in row ${row_number} and column ${column_number} does not conform to the pattern constraint of ${constraint} -unique-constraint=Rows ${row_numbers} has unique constraint violation in column ${column_number} -enumerable-constraint=The value ${value} in row ${row_number} and column ${column_number} does not conform to the given enumeration: ${constraint} -minimum-constraint=The value ${value} in row ${row_number} and column ${column_number} does not conform to the minimum constraint of ${constraint} -maximum-constraint=The value ${value} in row ${row_number} and column ${column_number} does not conform to the maximum constraint of ${constraint} -minimum-length-constraint=The value ${value} in row ${row_number} and column ${column_number} does not conform to the minimum length constraint of ${constraint} -maximum-length-constraint=The value ${value} in row ${row_number} and column ${column_number} does not conform to the maximum length constraint of ${constraint} diff --git a/main/tests/data/datapackage-sample.json b/main/tests/data/datapackage-sample.json deleted file mode 100644 index 6ed88f3e7..000000000 --- a/main/tests/data/datapackage-sample.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "image": "http://assets.okfn.org/p/opendatahandbook/img/data-wrench.png", - "license": "PDDL-1.0", - "last_updated": "2011-09-21", - "keywords": [ - "GDP", - "World", - "Gross Domestic Product", - "Time series" - ], - "sources": [{ - "web": "http://data.worldbank.org/indicator/NY.GDP.MKTP.CD", - "name": "World Bank and OECD", - "title": "World Bank and OECD" - }], - "name": "gdp", - "description": "Country, regional and world GDP in current US Dollars ($). Regional means collections of countries e.g. Europe & Central Asia. Data is sourced from the World Bank and turned into a standard normalized CSV.", - "resources": [{ - "schema": {"fields": [ - { - "name": "Country Name", - "type": "string" - }, - { - "name": "Country Code", - "type": "string", - "foreignkey": "iso-3-geo-codes/id" - }, - { - "name": "Year", - "type": "year" - }, - { - "name": "Value", - "description": "GDP in current USD", - "type": "number" - } - ]}, - "path": "data/gdp.csv", - "name": "gdp" - }], - "title": "Country, Regional and World GDP (Gross Domestic Product)", - "version": "2011" -} \ No newline at end of file diff --git a/main/tests/data/gdp.csv b/main/tests/data/gdp.csv deleted file mode 100644 index da7de60ba..000000000 --- a/main/tests/data/gdp.csv +++ /dev/null @@ -1,11543 +0,0 @@ -Country Name,Country Code,Year,Value -Arab World,ARB,1968,25760683041.0826 -Arab World,ARB,1969,28434203615.4795 -Arab World,ARB,1970,31385499664.0635 -Arab World,ARB,1971,36426909888.3884 -Arab World,ARB,1972,43316056615.451 -Arab World,ARB,1973,55018394945.576 -Arab World,ARB,1974,105145803084.364 -Arab World,ARB,1975,116337021938.327 -Arab World,ARB,1976,144846175400.471 -Arab World,ARB,1977,167308327683.573 -Arab World,ARB,1978,183555544342.167 -Arab World,ARB,1979,248646206366.973 -Arab World,ARB,1980,338177454717.499 -Arab World,ARB,1981,348592795413.075 -Arab World,ARB,1982,324328753765.261 -Arab World,ARB,1983,303962539723.043 -Arab World,ARB,1984,307940771858.505 -Arab World,ARB,1985,303893618415.505 -Arab World,ARB,1986,289029150639.407 -Arab World,ARB,1987,312681678329.895 -Arab World,ARB,1988,307503035642.479 -Arab World,ARB,1989,322325140494.687 -Arab World,ARB,1990,446877161735.167 -Arab World,ARB,1991,439779177858.364 -Arab World,ARB,1992,471163515480.256 -Arab World,ARB,1993,476513630630.268 -Arab World,ARB,1994,487526906280.526 -Arab World,ARB,1995,523759898288.293 -Arab World,ARB,1996,578231297763.478 -Arab World,ARB,1997,613279452474.103 -Arab World,ARB,1998,591525594021.399 -Arab World,ARB,1999,643889670873.196 -Arab World,ARB,2000,735025140336.255 -Arab World,ARB,2001,723282816382.445 -Arab World,ARB,2002,729051715403.984 -Arab World,ARB,2003,823110541431.167 -Arab World,ARB,2004,963862340520.581 -Arab World,ARB,2005,1184661549595.13 -Arab World,ARB,2006,1404113530800.68 -Arab World,ARB,2007,1637573196970.62 -Arab World,ARB,2008,2077706582271.06 -Arab World,ARB,2009,1795472295052.32 -Arab World,ARB,2010,2109224213446 -Arab World,ARB,2011,2501942770389.97 -Arab World,ARB,2012,2740536188974.17 -Arab World,ARB,2013,2838294388723.79 -Arab World,ARB,2014,2904404570076.29 -Arab World,ARB,2015,2561129553776.39 -Arab World,ARB,2016,2500931669252.23 -Caribbean small states,CSS,1960,1922640775.37204 -Caribbean small states,CSS,1961,2080830143.04221 -Caribbean small states,CSS,1962,2195684581.07261 -Caribbean small states,CSS,1963,2331959438.21902 -Caribbean small states,CSS,1964,2519261152.97369 -Caribbean small states,CSS,1965,2712715412.87482 -Caribbean small states,CSS,1966,2942141442.47693 -Caribbean small states,CSS,1967,3158211274.70685 -Caribbean small states,CSS,1968,3140469906.3566 -Caribbean small states,CSS,1969,3417668655.56627 -Caribbean small states,CSS,1970,3760199658.87297 -Caribbean small states,CSS,1971,4088013918.53147 -Caribbean small states,CSS,1972,4732543297.55318 -Caribbean small states,CSS,1973,5169932102.82734 -Caribbean small states,CSS,1974,6720764011.57956 -Caribbean small states,CSS,1975,7864013356.29591 -Caribbean small states,CSS,1976,8070017845.29298 -Caribbean small states,CSS,1977,9382602731.01335 -Caribbean small states,CSS,1978,9571657513.65075 -Caribbean small states,CSS,1979,10966585159.6649 -Caribbean small states,CSS,1980,13453485464.7329 -Caribbean small states,CSS,1981,14842851376.6236 -Caribbean small states,CSS,1982,16495461075.5827 -Caribbean small states,CSS,1983,16712010846.6962 -Caribbean small states,CSS,1984,15923806275.1117 -Caribbean small states,CSS,1985,15742679785.309 -Caribbean small states,CSS,1986,14358714160.1057 -Caribbean small states,CSS,1987,15429015788.2553 -Caribbean small states,CSS,1988,16357329644.5497 -Caribbean small states,CSS,1989,16756727132.51 -Caribbean small states,CSS,1990,17873417057.5917 -Caribbean small states,CSS,1991,17682124581.2842 -Caribbean small states,CSS,1992,17403218746.3421 -Caribbean small states,CSS,1993,18271706185.3177 -Caribbean small states,CSS,1994,19289595454.1442 -Caribbean small states,CSS,1995,21134882108.6249 -Caribbean small states,CSS,1996,23041766083.4574 -Caribbean small states,CSS,1997,25732062006.8942 -Caribbean small states,CSS,1998,28249810016.98 -Caribbean small states,CSS,1999,30022260633.4195 -Caribbean small states,CSS,2000,32252030400.7358 -Caribbean small states,CSS,2001,33172149746.0103 -Caribbean small states,CSS,2002,34944596086.0711 -Caribbean small states,CSS,2003,37495408032.2944 -Caribbean small states,CSS,2004,41173138191.6472 -Caribbean small states,CSS,2005,46649069646.0953 -Caribbean small states,CSS,2006,52393433350.716 -Caribbean small states,CSS,2007,58257681979.3301 -Caribbean small states,CSS,2008,66480563576.5929 -Caribbean small states,CSS,2009,55930530970.8562 -Caribbean small states,CSS,2010,60772694299.858 -Caribbean small states,CSS,2011,65739442150.8813 -Caribbean small states,CSS,2012,67860562821.0636 -Caribbean small states,CSS,2013,68729777391.3784 -Caribbean small states,CSS,2014,68744227741.6518 -Caribbean small states,CSS,2015,66799701061.8327 -Caribbean small states,CSS,2016,63540193020.0893 -Central Europe and the Baltics,CEB,1990,256113714527.618 -Central Europe and the Baltics,CEB,1991,242631767248.709 -Central Europe and the Baltics,CEB,1992,259823093659.716 -Central Europe and the Baltics,CEB,1993,273915105741.891 -Central Europe and the Baltics,CEB,1994,310702556423.306 -Central Europe and the Baltics,CEB,1995,386114777052.74 -Central Europe and the Baltics,CEB,1996,412629652592.241 -Central Europe and the Baltics,CEB,1997,408895193163.935 -Central Europe and the Baltics,CEB,1998,447448444539.62 -Central Europe and the Baltics,CEB,1999,433914932035.509 -Central Europe and the Baltics,CEB,2000,427550058634.753 -Central Europe and the Baltics,CEB,2001,468161745109.393 -Central Europe and the Baltics,CEB,2002,527146030956.314 -Central Europe and the Baltics,CEB,2003,634284039973.081 -Central Europe and the Baltics,CEB,2004,762451562237.799 -Central Europe and the Baltics,CEB,2005,885747879466.35 -Central Europe and the Baltics,CEB,2006,1001942855597.53 -Central Europe and the Baltics,CEB,2007,1260957147846.53 -Central Europe and the Baltics,CEB,2008,1523196377519.86 -Central Europe and the Baltics,CEB,2009,1279854250277.72 -Central Europe and the Baltics,CEB,2010,1312750149554.56 -Central Europe and the Baltics,CEB,2011,1446220607413.34 -Central Europe and the Baltics,CEB,2012,1350778814230.21 -Central Europe and the Baltics,CEB,2013,1421351670726.71 -Central Europe and the Baltics,CEB,2014,1461972726743.52 -Central Europe and the Baltics,CEB,2015,1281539342884.75 -Central Europe and the Baltics,CEB,2016,1303382786630.62 -Early-demographic dividend,EAR,1960,152222021503.101 -Early-demographic dividend,EAR,1961,153174173789.089 -Early-demographic dividend,EAR,1962,158795369827.794 -Early-demographic dividend,EAR,1963,167975897835.712 -Early-demographic dividend,EAR,1964,192426156455.164 -Early-demographic dividend,EAR,1965,209993963772.447 -Early-demographic dividend,EAR,1966,207316686431.051 -Early-demographic dividend,EAR,1967,217587076275.313 -Early-demographic dividend,EAR,1968,235705718659.736 -Early-demographic dividend,EAR,1969,263417168820.022 -Early-demographic dividend,EAR,1970,278414463364.508 -Early-demographic dividend,EAR,1971,300750846441.857 -Early-demographic dividend,EAR,1972,330264782812.664 -Early-demographic dividend,EAR,1973,422538233529.836 -Early-demographic dividend,EAR,1974,592504417822.073 -Early-demographic dividend,EAR,1975,636292930399.372 -Early-demographic dividend,EAR,1976,694401920707.909 -Early-demographic dividend,EAR,1977,777069860599.993 -Early-demographic dividend,EAR,1978,860276042756.762 -Early-demographic dividend,EAR,1979,1045208440796.38 -Early-demographic dividend,EAR,1980,1289757085834.86 -Early-demographic dividend,EAR,1981,1441144663708.07 -Early-demographic dividend,EAR,1982,1371908131842.89 -Early-demographic dividend,EAR,1983,1385300584420.83 -Early-demographic dividend,EAR,1984,1365815981597.72 -Early-demographic dividend,EAR,1985,1397858695204.75 -Early-demographic dividend,EAR,1986,1418211765048.27 -Early-demographic dividend,EAR,1987,1429315977542.63 -Early-demographic dividend,EAR,1988,1535871536563.05 -Early-demographic dividend,EAR,1989,1568562659306.28 -Early-demographic dividend,EAR,1990,1806505172134.77 -Early-demographic dividend,EAR,1991,1912921517302.44 -Early-demographic dividend,EAR,1992,2098149661879.33 -Early-demographic dividend,EAR,1993,2302453002964.44 -Early-demographic dividend,EAR,1994,2408912031539.9 -Early-demographic dividend,EAR,1995,2468961701917.03 -Early-demographic dividend,EAR,1996,2694453298131.29 -Early-demographic dividend,EAR,1997,2878903970242.92 -Early-demographic dividend,EAR,1998,2839864195429.24 -Early-demographic dividend,EAR,1999,3010697292749.06 -Early-demographic dividend,EAR,2000,3265108230891.93 -Early-demographic dividend,EAR,2001,3224441922892.92 -Early-demographic dividend,EAR,2002,3131166808367.24 -Early-demographic dividend,EAR,2003,3500675725433.46 -Early-demographic dividend,EAR,2004,4066546525118.83 -Early-demographic dividend,EAR,2005,4742611342049.54 -Early-demographic dividend,EAR,2006,5428145324754.82 -Early-demographic dividend,EAR,2007,6446032068048.83 -Early-demographic dividend,EAR,2008,7272012608284.4 -Early-demographic dividend,EAR,2009,6990930969841.42 -Early-demographic dividend,EAR,2010,8490184886018.92 -Early-demographic dividend,EAR,2011,9567687630587.59 -Early-demographic dividend,EAR,2012,9956217405201.38 -Early-demographic dividend,EAR,2013,10199668619019.7 -Early-demographic dividend,EAR,2014,10514807961576.6 -Early-demographic dividend,EAR,2015,10225383730055.9 -Early-demographic dividend,EAR,2016,10378321855929.9 -East Asia & Pacific,EAS,1960,153406062445.133 -East Asia & Pacific,EAS,1961,153851906489.076 -East Asia & Pacific,EAS,1962,157422860957.598 -East Asia & Pacific,EAS,1963,175666653928.707 -East Asia & Pacific,EAS,1964,201828758065.12 -East Asia & Pacific,EAS,1965,224795305298.806 -East Asia & Pacific,EAS,1966,251316895422.914 -East Asia & Pacific,EAS,1967,272311886780.484 -East Asia & Pacific,EAS,1968,300037540836.51 -East Asia & Pacific,EAS,1969,345620520780.581 -East Asia & Pacific,EAS,1970,406892268832.737 -East Asia & Pacific,EAS,1971,451555305929.632 -East Asia & Pacific,EAS,1972,560418537433.307 -East Asia & Pacific,EAS,1973,738629607846.873 -East Asia & Pacific,EAS,1974,850486001086.155 -East Asia & Pacific,EAS,1975,931183199853.372 -East Asia & Pacific,EAS,1976,1023624295308.86 -East Asia & Pacific,EAS,1977,1220099418673.47 -East Asia & Pacific,EAS,1978,1539413405469.08 -East Asia & Pacific,EAS,1979,1671803883927.95 -East Asia & Pacific,EAS,1980,1806920411252.29 -East Asia & Pacific,EAS,1981,1994776943312.9 -East Asia & Pacific,EAS,1982,1953473277429.83 -East Asia & Pacific,EAS,1983,2073066401462.35 -East Asia & Pacific,EAS,1984,2223992929693.57 -East Asia & Pacific,EAS,1985,2358172144946.55 -East Asia & Pacific,EAS,1986,3076109459284.79 -East Asia & Pacific,EAS,1987,3598365917263.22 -East Asia & Pacific,EAS,1988,4330848600314.32 -East Asia & Pacific,EAS,1989,4529251580451.43 -East Asia & Pacific,EAS,1990,4740125610961.6 -East Asia & Pacific,EAS,1991,5337495034346.36 -East Asia & Pacific,EAS,1992,5827466927803.02 -East Asia & Pacific,EAS,1993,6542241886332.86 -East Asia & Pacific,EAS,1994,7302165972072.7 -East Asia & Pacific,EAS,1995,8297217618291.42 -East Asia & Pacific,EAS,1996,7993854682092.77 -East Asia & Pacific,EAS,1997,7649008381580.38 -East Asia & Pacific,EAS,1998,6857782846050.01 -East Asia & Pacific,EAS,1999,7656256420658.01 -East Asia & Pacific,EAS,2000,8283672555565.95 -East Asia & Pacific,EAS,2001,7705159083109.51 -East Asia & Pacific,EAS,2002,7827298972846.93 -East Asia & Pacific,EAS,2003,8605351856004.54 -East Asia & Pacific,EAS,2004,9651082222195.5 -East Asia & Pacific,EAS,2005,10292825485348.7 -East Asia & Pacific,EAS,2006,10913330711044.6 -East Asia & Pacific,EAS,2007,12205786067031.7 -East Asia & Pacific,EAS,2008,14097329803496.3 -East Asia & Pacific,EAS,2009,14526049741278.9 -East Asia & Pacific,EAS,2010,16934259897815.9 -East Asia & Pacific,EAS,2011,19633645544446.8 -East Asia & Pacific,EAS,2012,21013112141456.7 -East Asia & Pacific,EAS,2013,21256469783768.7 -East Asia & Pacific,EAS,2014,21894085979174.9 -East Asia & Pacific,EAS,2015,21765291253881.4 -East Asia & Pacific,EAS,2016,22477425046152.2 -East Asia & Pacific (excluding high income),EAP,1960,80259949708.256 -East Asia & Pacific (excluding high income),EAP,1961,70454320784.1637 -East Asia & Pacific (excluding high income),EAP,1962,64561374187.0283 -East Asia & Pacific (excluding high income),EAP,1963,69911007473.5442 -East Asia & Pacific (excluding high income),EAP,1964,81054694801.5609 -East Asia & Pacific (excluding high income),EAP,1965,94592399250.3341 -East Asia & Pacific (excluding high income),EAP,1966,103552673128.584 -East Asia & Pacific (excluding high income),EAP,1967,100339273081.733 -East Asia & Pacific (excluding high income),EAP,1968,101275421779.252 -East Asia & Pacific (excluding high income),EAP,1969,113721619713.104 -East Asia & Pacific (excluding high income),EAP,1970,126769627751.232 -East Asia & Pacific (excluding high income),EAP,1971,136328570880.601 -East Asia & Pacific (excluding high income),EAP,1972,154659093609.397 -East Asia & Pacific (excluding high income),EAP,1973,194723705741.74 -East Asia & Pacific (excluding high income),EAP,1974,219684982687.941 -East Asia & Pacific (excluding high income),EAP,1975,246972833579.966 -East Asia & Pacific (excluding high income),EAP,1976,250679070877.618 -East Asia & Pacific (excluding high income),EAP,1977,289679258049.107 -East Asia & Pacific (excluding high income),EAP,1978,280440164773.063 -East Asia & Pacific (excluding high income),EAP,1979,324841171790.876 -East Asia & Pacific (excluding high income),EAP,1980,374815806190.863 -East Asia & Pacific (excluding high income),EAP,1981,399965066634.494 -East Asia & Pacific (excluding high income),EAP,1982,419766288759.248 -East Asia & Pacific (excluding high income),EAP,1983,440469714741.303 -East Asia & Pacific (excluding high income),EAP,1984,478158198678.127 -East Asia & Pacific (excluding high income),EAP,1985,524014062044.045 -East Asia & Pacific (excluding high income),EAP,1986,522534774843.578 -East Asia & Pacific (excluding high income),EAP,1987,516086961052.224 -East Asia & Pacific (excluding high income),EAP,1988,572406468163.312 -East Asia & Pacific (excluding high income),EAP,1989,618643709376.269 -East Asia & Pacific (excluding high income),EAP,1990,663045725610.49 -East Asia & Pacific (excluding high income),EAP,1991,719584447233.343 -East Asia & Pacific (excluding high income),EAP,1992,806358557827.083 -East Asia & Pacific (excluding high income),EAP,1993,885238781446.321 -East Asia & Pacific (excluding high income),EAP,1994,1064868940113.18 -East Asia & Pacific (excluding high income),EAP,1995,1314307625271.26 -East Asia & Pacific (excluding high income),EAP,1996,1509620351019.71 -East Asia & Pacific (excluding high income),EAP,1997,1563661684670.21 -East Asia & Pacific (excluding high income),EAP,1998,1433164072949.29 -East Asia & Pacific (excluding high income),EAP,1999,1576476091414.92 -East Asia & Pacific (excluding high income),EAP,2000,1737704956830.78 -East Asia & Pacific (excluding high income),EAP,2001,1848846696904.54 -East Asia & Pacific (excluding high income),EAP,2002,2046255878039.6 -East Asia & Pacific (excluding high income),EAP,2003,2315970352098 -East Asia & Pacific (excluding high income),EAP,2004,2685679579693.63 -East Asia & Pacific (excluding high income),EAP,2005,3105942817285.98 -East Asia & Pacific (excluding high income),EAP,2006,3737485223150.79 -East Asia & Pacific (excluding high income),EAP,2007,4727397727396.91 -East Asia & Pacific (excluding high income),EAP,2008,5984384402421.37 -East Asia & Pacific (excluding high income),EAP,2009,6493261436292.97 -East Asia & Pacific (excluding high income),EAP,2010,7875013124582.93 -East Asia & Pacific (excluding high income),EAP,2011,9625870808891.42 -East Asia & Pacific (excluding high income),EAP,2012,10738363479428.9 -East Asia & Pacific (excluding high income),EAP,2013,11854913554643.5 -East Asia & Pacific (excluding high income),EAP,2014,12748307082155.9 -East Asia & Pacific (excluding high income),EAP,2015,13267645915189.5 -East Asia & Pacific (excluding high income),EAP,2016,13511178026303.6 -East Asia & Pacific (IDA & IBRD countries),TEA,1960,80087763368.4641 -East Asia & Pacific (IDA & IBRD countries),TEA,1961,70303171030.6136 -East Asia & Pacific (IDA & IBRD countries),TEA,1962,64422866914.6763 -East Asia & Pacific (IDA & IBRD countries),TEA,1963,69761023321.6503 -East Asia & Pacific (IDA & IBRD countries),TEA,1964,80880803448.8805 -East Asia & Pacific (IDA & IBRD countries),TEA,1965,94389464672.6492 -East Asia & Pacific (IDA & IBRD countries),TEA,1966,103330515554.021 -East Asia & Pacific (IDA & IBRD countries),TEA,1967,100124009401.253 -East Asia & Pacific (IDA & IBRD countries),TEA,1968,101058149724.505 -East Asia & Pacific (IDA & IBRD countries),TEA,1969,113477646105.785 -East Asia & Pacific (IDA & IBRD countries),TEA,1970,126497661493.109 -East Asia & Pacific (IDA & IBRD countries),TEA,1971,136036097265.624 -East Asia & Pacific (IDA & IBRD countries),TEA,1972,154327294457.505 -East Asia & Pacific (IDA & IBRD countries),TEA,1973,194305953646.402 -East Asia & Pacific (IDA & IBRD countries),TEA,1974,219213679712.873 -East Asia & Pacific (IDA & IBRD countries),TEA,1975,246442988390.718 -East Asia & Pacific (IDA & IBRD countries),TEA,1976,250141274481.86 -East Asia & Pacific (IDA & IBRD countries),TEA,1977,289057792282.702 -East Asia & Pacific (IDA & IBRD countries),TEA,1978,279838520171.011 -East Asia & Pacific (IDA & IBRD countries),TEA,1979,324144271125.13 -East Asia & Pacific (IDA & IBRD countries),TEA,1980,374011692034.316 -East Asia & Pacific (IDA & IBRD countries),TEA,1981,399106998306.283 -East Asia & Pacific (IDA & IBRD countries),TEA,1982,418865739717.139 -East Asia & Pacific (IDA & IBRD countries),TEA,1983,439524749434.869 -East Asia & Pacific (IDA & IBRD countries),TEA,1984,477132378074.312 -East Asia & Pacific (IDA & IBRD countries),TEA,1985,522889864188.566 -East Asia & Pacific (IDA & IBRD countries),TEA,1986,521413750588.998 -East Asia & Pacific (IDA & IBRD countries),TEA,1987,514979769667.717 -East Asia & Pacific (IDA & IBRD countries),TEA,1988,571178451263.419 -East Asia & Pacific (IDA & IBRD countries),TEA,1989,617316497032.628 -East Asia & Pacific (IDA & IBRD countries),TEA,1990,661623255038.025 -East Asia & Pacific (IDA & IBRD countries),TEA,1991,718040680851.845 -East Asia & Pacific (IDA & IBRD countries),TEA,1992,804628629897.439 -East Asia & Pacific (IDA & IBRD countries),TEA,1993,883339627183.539 -East Asia & Pacific (IDA & IBRD countries),TEA,1994,1062584414819.77 -East Asia & Pacific (IDA & IBRD countries),TEA,1995,1311487964653.74 -East Asia & Pacific (IDA & IBRD countries),TEA,1996,1506381674647.97 -East Asia & Pacific (IDA & IBRD countries),TEA,1997,1560307070281.15 -East Asia & Pacific (IDA & IBRD countries),TEA,1998,1430089422679.27 -East Asia & Pacific (IDA & IBRD countries),TEA,1999,1573093985533.5 -East Asia & Pacific (IDA & IBRD countries),TEA,2000,1733976957283.78 -East Asia & Pacific (IDA & IBRD countries),TEA,2001,1844880258516.11 -East Asia & Pacific (IDA & IBRD countries),TEA,2002,2041865926249.22 -East Asia & Pacific (IDA & IBRD countries),TEA,2003,2311056516099.72 -East Asia & Pacific (IDA & IBRD countries),TEA,2004,2680080452885.16 -East Asia & Pacific (IDA & IBRD countries),TEA,2005,3099556641923.49 -East Asia & Pacific (IDA & IBRD countries),TEA,2006,3729909801279.21 -East Asia & Pacific (IDA & IBRD countries),TEA,2007,4717923246206.8 -East Asia & Pacific (IDA & IBRD countries),TEA,2008,5972485978440.58 -East Asia & Pacific (IDA & IBRD countries),TEA,2009,6480284114182.45 -East Asia & Pacific (IDA & IBRD countries),TEA,2010,7859520533899.79 -East Asia & Pacific (IDA & IBRD countries),TEA,2011,9607063801205.78 -East Asia & Pacific (IDA & IBRD countries),TEA,2012,10717379224740.4 -East Asia & Pacific (IDA & IBRD countries),TEA,2013,11831819367549.7 -East Asia & Pacific (IDA & IBRD countries),TEA,2014,12723521658445.1 -East Asia & Pacific (IDA & IBRD countries),TEA,2015,13241873807583.3 -East Asia & Pacific (IDA & IBRD countries),TEA,2016,13484932862978.8 -Euro area,EMU,1960,245389523535.21 -Euro area,EMU,1961,270108736771.728 -Euro area,EMU,1962,299749528685.376 -Euro area,EMU,1963,336271770003.717 -Euro area,EMU,1964,374010191933.27 -Euro area,EMU,1965,408119028178.097 -Euro area,EMU,1966,445040235612.184 -Euro area,EMU,1967,483441345246.615 -Euro area,EMU,1968,518263505475.995 -Euro area,EMU,1969,572532268216.495 -Euro area,EMU,1970,641460637395.971 -Euro area,EMU,1971,727045243334.751 -Euro area,EMU,1972,878371965947.911 -Euro area,EMU,1973,1140215331077.93 -Euro area,EMU,1974,1292913189870.35 -Euro area,EMU,1975,1499292682301.1 -Euro area,EMU,1976,1564518129278.76 -Euro area,EMU,1977,1779460900157.27 -Euro area,EMU,1978,2179044584488.07 -Euro area,EMU,1979,2639765077757.45 -Euro area,EMU,1980,2956735717812.24 -Euro area,EMU,1981,2569819070205.93 -Euro area,EMU,1982,2487970498872.87 -Euro area,EMU,1983,2427189312535.1 -Euro area,EMU,1984,2328259732922.51 -Euro area,EMU,1985,2392054029846.51 -Euro area,EMU,1986,3357238823395.49 -Euro area,EMU,1987,4152743228203.74 -Euro area,EMU,1988,4567318804504.65 -Euro area,EMU,1989,4665607905988.66 -Euro area,EMU,1990,5871693989817.08 -Euro area,EMU,1991,6104530124284.34 -Euro area,EMU,1992,6734901870233.99 -Euro area,EMU,1993,6168663044953.83 -Euro area,EMU,1994,6515506760178.52 -Euro area,EMU,1995,7520106864481.86 -Euro area,EMU,1996,7611726452029.66 -Euro area,EMU,1997,6959484673611.01 -Euro area,EMU,1998,7151028055866.01 -Euro area,EMU,1999,7119223020204.08 -Euro area,EMU,2000,6486948965622.98 -Euro area,EMU,2001,6593233923750.33 -Euro area,EMU,2002,7173603214645.71 -Euro area,EMU,2003,8850599071571.01 -Euro area,EMU,2004,10151814034876.7 -Euro area,EMU,2005,10535328496601.9 -Euro area,EMU,2006,11184406192078.3 -Euro area,EMU,2007,12877397931377.4 -Euro area,EMU,2008,14115366559756.8 -Euro area,EMU,2009,12905452856781.1 -Euro area,EMU,2010,12642935603562.1 -Euro area,EMU,2011,13622723195115.4 -Euro area,EMU,2012,12637588983379.4 -Euro area,EMU,2013,13187495064380.7 -Euro area,EMU,2014,13457720442907.5 -Euro area,EMU,2015,11616144612366.3 -Euro area,EMU,2016,11885664082849.1 -Europe & Central Asia,ECS,1960,432763685324.509 -Europe & Central Asia,ECS,1961,460668876592.491 -Europe & Central Asia,ECS,1962,503638735647.907 -Europe & Central Asia,ECS,1963,555368983066.662 -Europe & Central Asia,ECS,1964,615028489294.961 -Europe & Central Asia,ECS,1965,669257339022.057 -Europe & Central Asia,ECS,1966,727080705610.445 -Europe & Central Asia,ECS,1967,782273534888.326 -Europe & Central Asia,ECS,1968,815868539007.526 -Europe & Central Asia,ECS,1969,895741081122.038 -Europe & Central Asia,ECS,1970,1007609884842.09 -Europe & Central Asia,ECS,1971,1136379130354.99 -Europe & Central Asia,ECS,1972,1361730567491.87 -Europe & Central Asia,ECS,1973,1729501999343.51 -Europe & Central Asia,ECS,1974,1954079227218.94 -Europe & Central Asia,ECS,1975,2282879504237.62 -Europe & Central Asia,ECS,1976,2372796286718.28 -Europe & Central Asia,ECS,1977,2689034117521.4 -Europe & Central Asia,ECS,1978,3282122941201.44 -Europe & Central Asia,ECS,1979,4015364706047.03 -Europe & Central Asia,ECS,1980,4548343163223.59 -Europe & Central Asia,ECS,1981,4048271618267.42 -Europe & Central Asia,ECS,1982,3900963906539.6 -Europe & Central Asia,ECS,1983,3784300665660.48 -Europe & Central Asia,ECS,1984,3637246299961.42 -Europe & Central Asia,ECS,1985,3764269446867.66 -Europe & Central Asia,ECS,1986,5137673243594.37 -Europe & Central Asia,ECS,1987,6348859470242.99 -Europe & Central Asia,ECS,1988,7067497880251.27 -Europe & Central Asia,ECS,1989,7224451847727.19 -Europe & Central Asia,ECS,1990,8837798957217.56 -Europe & Central Asia,ECS,1991,9118254483722.14 -Europe & Central Asia,ECS,1992,9780068883431.27 -Europe & Central Asia,ECS,1993,8987910993879.63 -Europe & Central Asia,ECS,1994,9400417935058.64 -Europe & Central Asia,ECS,1995,10827903895370.2 -Europe & Central Asia,ECS,1996,11055076580949 -Europe & Central Asia,ECS,1997,10489769869606.2 -Europe & Central Asia,ECS,1998,10749669669893.6 -Europe & Central Asia,ECS,1999,10628573427395.1 -Europe & Central Asia,ECS,2000,10011304103592.3 -Europe & Central Asia,ECS,2001,10112904613806.8 -Europe & Central Asia,ECS,2002,11061551679319.4 -Europe & Central Asia,ECS,2003,13475936343306.8 -Europe & Central Asia,ECS,2004,15710079754567.4 -Europe & Central Asia,ECS,2005,16731221185836.3 -Europe & Central Asia,ECS,2006,18108863489937 -Europe & Central Asia,ECS,2007,21160525702403.2 -Europe & Central Asia,ECS,2008,23218568155419.7 -Europe & Central Asia,ECS,2009,20419024790312.5 -Europe & Central Asia,ECS,2010,20905471026131.4 -Europe & Central Asia,ECS,2011,23146206945497.4 -Europe & Central Asia,ECS,2012,22278308473166.2 -Europe & Central Asia,ECS,2013,23253753489878.5 -Europe & Central Asia,ECS,2014,23602629398500.7 -Europe & Central Asia,ECS,2015,20278407939904.2 -Europe & Central Asia,ECS,2016,20162858489508.1 -Europe & Central Asia (excluding high income),ECA,1989,903702469910.52 -Europe & Central Asia (excluding high income),ECA,1990,960438672723.367 -Europe & Central Asia (excluding high income),ECA,1991,926765119090.884 -Europe & Central Asia (excluding high income),ECA,1992,853278424758.789 -Europe & Central Asia (excluding high income),ECA,1993,838260559328.055 -Europe & Central Asia (excluding high income),ECA,1994,727687093069.718 -Europe & Central Asia (excluding high income),ECA,1995,776931366529.155 -Europe & Central Asia (excluding high income),ECA,1996,787851671889.667 -Europe & Central Asia (excluding high income),ECA,1997,820131784781.875 -Europe & Central Asia (excluding high income),ECA,1998,771871770861.159 -Europe & Central Asia (excluding high income),ECA,1999,650450056519.407 -Europe & Central Asia (excluding high income),ECA,2000,720049109208.474 -Europe & Central Asia (excluding high income),ECA,2001,717065633312.417 -Europe & Central Asia (excluding high income),ECA,2002,820427017878.696 -Europe & Central Asia (excluding high income),ECA,2003,1037515255499.23 -Europe & Central Asia (excluding high income),ECA,2004,1367586660092.33 -Europe & Central Asia (excluding high income),ECA,2005,1726468996323.24 -Europe & Central Asia (excluding high income),ECA,2006,2114341890534.89 -Europe & Central Asia (excluding high income),ECA,2007,2727633767388.62 -Europe & Central Asia (excluding high income),ECA,2008,3372528990767.71 -Europe & Central Asia (excluding high income),ECA,2009,2655132038891.56 -Europe & Central Asia (excluding high income),ECA,2010,3156252483058.18 -Europe & Central Asia (excluding high income),ECA,2011,3871963192958.71 -Europe & Central Asia (excluding high income),ECA,2012,4070879223563.86 -Europe & Central Asia (excluding high income),ECA,2013,4302720557394.26 -Europe & Central Asia (excluding high income),ECA,2014,4078799138447.73 -Europe & Central Asia (excluding high income),ECA,2015,3120102822297.1 -Europe & Central Asia (excluding high income),ECA,2016,2979118476324.24 -Europe & Central Asia (IDA & IBRD countries),TEC,1989,960328174371.057 -Europe & Central Asia (IDA & IBRD countries),TEC,1990,1020619449300.74 -Europe & Central Asia (IDA & IBRD countries),TEC,1991,1007801660268.39 -Europe & Central Asia (IDA & IBRD countries),TEC,1992,944312695547.955 -Europe & Central Asia (IDA & IBRD countries),TEC,1993,931235788654.179 -Europe & Central Asia (IDA & IBRD countries),TEC,1994,837243545767.996 -Europe & Central Asia (IDA & IBRD countries),TEC,1995,918930607816.217 -Europe & Central Asia (IDA & IBRD countries),TEC,1996,947704910874.353 -Europe & Central Asia (IDA & IBRD countries),TEC,1997,979132756086.026 -Europe & Central Asia (IDA & IBRD countries),TEC,1998,946228594056.486 -Europe & Central Asia (IDA & IBRD countries),TEC,1999,820213773405.425 -Europe & Central Asia (IDA & IBRD countries),TEC,2000,891934707791.111 -Europe & Central Asia (IDA & IBRD countries),TEC,2001,907586896655.439 -Europe & Central Asia (IDA & IBRD countries),TEC,2002,1019107655133.6 -Europe & Central Asia (IDA & IBRD countries),TEC,2003,1255033897823.74 -Europe & Central Asia (IDA & IBRD countries),TEC,2004,1622688912935.72 -Europe & Central Asia (IDA & IBRD countries),TEC,2005,2032603631916.98 -Europe & Central Asia (IDA & IBRD countries),TEC,2006,2459168320833.04 -Europe & Central Asia (IDA & IBRD countries),TEC,2007,3156883414983.23 -Europe & Central Asia (IDA & IBRD countries),TEC,2008,3906344780241.39 -Europe & Central Asia (IDA & IBRD countries),TEC,2009,3094928199271.03 -Europe & Central Asia (IDA & IBRD countries),TEC,2010,3635573611967.41 -Europe & Central Asia (IDA & IBRD countries),TEC,2011,4400783138334.08 -Europe & Central Asia (IDA & IBRD countries),TEC,2012,4571223504946.21 -Europe & Central Asia (IDA & IBRD countries),TEC,2013,4826935346702.26 -Europe & Central Asia (IDA & IBRD countries),TEC,2014,4623950916968.12 -Europe & Central Asia (IDA & IBRD countries),TEC,2015,3597439604363.69 -Europe & Central Asia (IDA & IBRD countries),TEC,2016,3448627156740.36 -European Union,EUU,1960,358939666615.47 -European Union,EUU,1961,390789544218.134 -European Union,EUU,1962,426908194104.211 -European Union,EUU,1963,470297095519.743 -European Union,EUU,1964,521197684985.034 -European Union,EUU,1965,567590518505.608 -European Union,EUU,1966,615283909698.108 -European Union,EUU,1967,661166979382.423 -European Union,EUU,1968,687213740362.304 -European Union,EUU,1969,754796434973.419 -European Union,EUU,1970,855234352054.266 -European Union,EUU,1971,967419657510.242 -European Union,EUU,1972,1158320102742.09 -European Union,EUU,1973,1470725772176.78 -European Union,EUU,1974,1652902769120.73 -European Union,EUU,1975,1926973312297.35 -European Union,EUU,1976,1995730917312.52 -European Union,EUU,1977,2260041856810.23 -European Union,EUU,1978,2769687171486.68 -European Union,EUU,1979,3382589603382.52 -European Union,EUU,1980,3860946303423.78 -European Union,EUU,1981,3416278760871.41 -European Union,EUU,1982,3287910701007.99 -European Union,EUU,1983,3186966976981.42 -European Union,EUU,1984,3059979571007.95 -European Union,EUU,1985,3162521224924.48 -European Union,EUU,1986,4336668252551.86 -European Union,EUU,1987,5365914989685.94 -European Union,EUU,1988,5985449350585.64 -European Union,EUU,1989,6111509859371.48 -European Union,EUU,1990,7578533627539.12 -European Union,EUU,1991,7865147971074.68 -European Union,EUU,1992,8570482000033.34 -European Union,EUU,1993,7814819013689.57 -European Union,EUU,1994,8298433649328.58 -European Union,EUU,1995,9610497311406.19 -European Union,EUU,1996,9824668960664.23 -European Union,EUU,1997,9273364401458.35 -European Union,EUU,1998,9589846268503.63 -European Union,EUU,1999,9576780993379.78 -European Union,EUU,2000,8899281080301.74 -European Union,EUU,2001,9000712583377.4 -European Union,EUU,2002,9811088515429.67 -European Union,EUU,2003,11945762088043.2 -European Union,EUU,2004,13795554923350 -European Union,EUU,2005,14426590936518.2 -European Union,EUU,2006,15388732742870.8 -European Union,EUU,2007,17781304404686.5 -European Union,EUU,2008,19117797795887.7 -European Union,EUU,2009,17080879375428 -European Union,EUU,2010,16977855795546.3 -European Union,EUU,2011,18340538607136.1 -European Union,EUU,2012,17271715977529.1 -European Union,EUU,2013,18002706275463.5 -European Union,EUU,2014,18588239232261 -European Union,EUU,2015,16334844026788 -European Union,EUU,2016,16397979816576.1 -Fragile and conflict affected situations,FCS,2000,212661618000.573 -Fragile and conflict affected situations,FCS,2001,196781933108.681 -Fragile and conflict affected situations,FCS,2002,190816468796.57 -Fragile and conflict affected situations,FCS,2003,217472506931.578 -Fragile and conflict affected situations,FCS,2004,247331719330.617 -Fragile and conflict affected situations,FCS,2005,300124282952.738 -Fragile and conflict affected situations,FCS,2006,351606441448.304 -Fragile and conflict affected situations,FCS,2007,435172555818.384 -Fragile and conflict affected situations,FCS,2008,561422238512.442 -Fragile and conflict affected situations,FCS,2009,523959040574.02 -Fragile and conflict affected situations,FCS,2010,624219448362.822 -Fragile and conflict affected situations,FCS,2011,676660621845.22 -Fragile and conflict affected situations,FCS,2012,730528738068.19 -Fragile and conflict affected situations,FCS,2013,781048126926.108 -Fragile and conflict affected situations,FCS,2014,821766296573.443 -Fragile and conflict affected situations,FCS,2015,750921360242.507 -Fragile and conflict affected situations,FCS,2016,736492620797.34 -Heavily indebted poor countries (HIPC),HPC,1960,17566642115.4168 -Heavily indebted poor countries (HIPC),HPC,1961,18033526303.1068 -Heavily indebted poor countries (HIPC),HPC,1962,19660722938.5933 -Heavily indebted poor countries (HIPC),HPC,1963,23797854828.0912 -Heavily indebted poor countries (HIPC),HPC,1964,21181173056.3962 -Heavily indebted poor countries (HIPC),HPC,1965,24791433536.9807 -Heavily indebted poor countries (HIPC),HPC,1966,27037002542.0683 -Heavily indebted poor countries (HIPC),HPC,1967,26469517421.1298 -Heavily indebted poor countries (HIPC),HPC,1968,27687706183.1679 -Heavily indebted poor countries (HIPC),HPC,1969,30902141055.3267 -Heavily indebted poor countries (HIPC),HPC,1970,32389167090.0469 -Heavily indebted poor countries (HIPC),HPC,1971,34920433870.4235 -Heavily indebted poor countries (HIPC),HPC,1972,37813701276.9785 -Heavily indebted poor countries (HIPC),HPC,1973,45584823246.267 -Heavily indebted poor countries (HIPC),HPC,1974,56142116082.6774 -Heavily indebted poor countries (HIPC),HPC,1975,63535307034.3364 -Heavily indebted poor countries (HIPC),HPC,1976,67559791246.943 -Heavily indebted poor countries (HIPC),HPC,1977,79909125894.0715 -Heavily indebted poor countries (HIPC),HPC,1978,90789385371.85 -Heavily indebted poor countries (HIPC),HPC,1979,101664820366.851 -Heavily indebted poor countries (HIPC),HPC,1980,106677929490.771 -Heavily indebted poor countries (HIPC),HPC,1981,106633807023.73 -Heavily indebted poor countries (HIPC),HPC,1982,106403185666.529 -Heavily indebted poor countries (HIPC),HPC,1983,100261185483.72 -Heavily indebted poor countries (HIPC),HPC,1984,100078815923.674 -Heavily indebted poor countries (HIPC),HPC,1985,104994491996.922 -Heavily indebted poor countries (HIPC),HPC,1986,120358284739.616 -Heavily indebted poor countries (HIPC),HPC,1987,132550820434.308 -Heavily indebted poor countries (HIPC),HPC,1988,132065171231.102 -Heavily indebted poor countries (HIPC),HPC,1989,127152957339.515 -Heavily indebted poor countries (HIPC),HPC,1990,129590021510.749 -Heavily indebted poor countries (HIPC),HPC,1991,133299444700.789 -Heavily indebted poor countries (HIPC),HPC,1992,121796046071.449 -Heavily indebted poor countries (HIPC),HPC,1993,123961926712.477 -Heavily indebted poor countries (HIPC),HPC,1994,110357996127.295 -Heavily indebted poor countries (HIPC),HPC,1995,126157292697.297 -Heavily indebted poor countries (HIPC),HPC,1996,132123113216.448 -Heavily indebted poor countries (HIPC),HPC,1997,138643799979.895 -Heavily indebted poor countries (HIPC),HPC,1998,142823908564.672 -Heavily indebted poor countries (HIPC),HPC,1999,143030868524.954 -Heavily indebted poor countries (HIPC),HPC,2000,155061199539.282 -Heavily indebted poor countries (HIPC),HPC,2001,147407334553.846 -Heavily indebted poor countries (HIPC),HPC,2002,160216529979.782 -Heavily indebted poor countries (HIPC),HPC,2003,182328184670.128 -Heavily indebted poor countries (HIPC),HPC,2004,209456626079.117 -Heavily indebted poor countries (HIPC),HPC,2005,242142895089.303 -Heavily indebted poor countries (HIPC),HPC,2006,289296463304.802 -Heavily indebted poor countries (HIPC),HPC,2007,344296287547.737 -Heavily indebted poor countries (HIPC),HPC,2008,414897655686.46 -Heavily indebted poor countries (HIPC),HPC,2009,421736724661.502 -Heavily indebted poor countries (HIPC),HPC,2010,463157748195.383 -Heavily indebted poor countries (HIPC),HPC,2011,518080704387.585 -Heavily indebted poor countries (HIPC),HPC,2012,558428816750.537 -Heavily indebted poor countries (HIPC),HPC,2013,604887195078.331 -Heavily indebted poor countries (HIPC),HPC,2014,643085647289.931 -Heavily indebted poor countries (HIPC),HPC,2015,635445735588.403 -Heavily indebted poor countries (HIPC),HPC,2016,641483025657.911 -High income,HIC,1960,1060243880168.7 -High income,HIC,1961,1121981243040.71 -High income,HIC,1962,1211776607405.32 -High income,HIC,1963,1304603063142.08 -High income,HIC,1964,1424584016309.32 -High income,HIC,1965,1546689929989.83 -High income,HIC,1966,1696346036809.99 -High income,HIC,1967,1819327353188.27 -High income,HIC,1968,1971265014235.61 -High income,HIC,1969,2163798867287.21 -High income,HIC,1970,2379635398065.42 -High income,HIC,1971,2640680118163.63 -High income,HIC,1972,3063716011733.77 -High income,HIC,1973,3706329864579 -High income,HIC,1974,4181857989922.81 -High income,HIC,1975,4663456510499.43 -High income,HIC,1976,5079507752415.01 -High income,HIC,1977,5751828019898.84 -High income,HIC,1978,6888147385510.59 -High income,HIC,1979,7965334539289.59 -High income,HIC,1980,8898498285406.06 -High income,HIC,1981,9036558177457.95 -High income,HIC,1982,8949612375739.48 -High income,HIC,1983,9239819279588.91 -High income,HIC,1984,9637983479337.74 -High income,HIC,1985,10132406784514.8 -High income,HIC,1986,12297564072616.7 -High income,HIC,1987,14242430872936.9 -High income,HIC,1988,16042589882344.5 -High income,HIC,1989,16805389434609.4 -High income,HIC,1990,18896462178031 -High income,HIC,1991,19983111824868.1 -High income,HIC,1992,21499618272513.5 -High income,HIC,1993,21696143760634 -High income,HIC,1994,23254026236811.5 -High income,HIC,1995,25821731647568.2 -High income,HIC,1996,26052438147494.1 -High income,HIC,1997,25624851684656.3 -High income,HIC,1998,25710064575645.4 -High income,HIC,1999,27011881987743.9 -High income,HIC,2000,27571498060078.4 -High income,HIC,2001,27308139048338.7 -High income,HIC,2002,28461009762104.4 -High income,HIC,2003,31909785738810.1 -High income,HIC,2004,35519515046236.5 -High income,HIC,2005,37558565439921.7 -High income,HIC,2006,39635947402724.5 -High income,HIC,2007,43320749778521.8 -High income,HIC,2008,46007526813566.5 -High income,HIC,2009,43117491018121.2 -High income,HIC,2010,45187761310741.6 -High income,HIC,2011,48762979397332.6 -High income,HIC,2012,48790077028762.4 -High income,HIC,2013,49316266632359.8 -High income,HIC,2014,50308250490810.1 -High income,HIC,2015,47409525372420.8 -High income,HIC,2016,48407640157423.4 -IBRD only,IBD,1960,294792529250.207 -IBRD only,IBD,1961,281626215408.776 -IBRD only,IBD,1962,293934441536.983 -IBRD only,IBD,1963,313396206080.027 -IBRD only,IBD,1964,354919270653.881 -IBRD only,IBD,1965,389878012188.969 -IBRD only,IBD,1966,402017322061.603 -IBRD only,IBD,1967,413014336037.993 -IBRD only,IBD,1968,436571843248.962 -IBRD only,IBD,1969,488040628514.822 -IBRD only,IBD,1970,529362750187.336 -IBRD only,IBD,1971,578582492654.098 -IBRD only,IBD,1972,651149122217.479 -IBRD only,IBD,1973,837821911282.808 -IBRD only,IBD,1974,1057251132019.3 -IBRD only,IBD,1975,1142724094139.65 -IBRD only,IBD,1976,1246289423374.27 -IBRD only,IBD,1977,1413532715597.07 -IBRD only,IBD,1978,1524704140806.03 -IBRD only,IBD,1979,1825690390932.99 -IBRD only,IBD,1980,2139762149345.92 -IBRD only,IBD,1981,2321258403803.81 -IBRD only,IBD,1982,2302549053326.87 -IBRD only,IBD,1983,2272103495406.6 -IBRD only,IBD,1984,2313687727936.92 -IBRD only,IBD,1985,2439461778036.01 -IBRD only,IBD,1986,2553168739556.33 -IBRD only,IBD,1987,2616094413959.71 -IBRD only,IBD,1988,2844737806054.1 -IBRD only,IBD,1989,3045326136048.95 -IBRD only,IBD,1990,3443776644827.72 -IBRD only,IBD,1991,3711451063868.31 -IBRD only,IBD,1992,3696285768627.5 -IBRD only,IBD,1993,3965845725257.7 -IBRD only,IBD,1994,4343949156182.07 -IBRD only,IBD,1995,4877267746552.34 -IBRD only,IBD,1996,5322354990131.63 -IBRD only,IBD,1997,5633308770924 -IBRD only,IBD,1998,5473749235787.22 -IBRD only,IBD,1999,5316743211058.67 -IBRD only,IBD,2000,5778989842384.42 -IBRD only,IBD,2001,5856302815575.35 -IBRD only,IBD,2002,5947536549262.23 -IBRD only,IBD,2003,6716225139151.19 -IBRD only,IBD,2004,7990347950856.02 -IBRD only,IBD,2005,9549735974950.61 -IBRD only,IBD,2006,11321411711668.7 -IBRD only,IBD,2007,14088931626236.9 -IBRD only,IBD,2008,16926584187094.4 -IBRD only,IBD,2009,16425341705202.5 -IBRD only,IBD,2010,19954364488950.4 -IBRD only,IBD,2011,23607619466961.8 -IBRD only,IBD,2012,25002131466488.6 -IBRD only,IBD,2013,26486061975152.6 -IBRD only,IBD,2014,27385523724212.7 -IBRD only,IBD,2015,25878328332858.1 -IBRD only,IBD,2016,25924292415039.1 -IDA & IBRD total,IBT,1960,332410539293.112 -IDA & IBRD total,IBT,1961,321985771144.331 -IDA & IBRD total,IBT,1962,337685120265.7 -IDA & IBRD total,IBT,1963,362761033613.715 -IDA & IBRD total,IBT,1964,402977587836.774 -IDA & IBRD total,IBT,1965,444428542057.831 -IDA & IBRD total,IBT,1966,461258734546.45 -IDA & IBRD total,IBT,1967,472865842237.292 -IDA & IBRD total,IBT,1968,499660160465.74 -IDA & IBRD total,IBT,1969,559287041398.569 -IDA & IBRD total,IBT,1970,612186629071.988 -IDA & IBRD total,IBT,1971,661686153516.207 -IDA & IBRD total,IBT,1972,737610959339.937 -IDA & IBRD total,IBT,1973,936838994091.702 -IDA & IBRD total,IBT,1974,1191684644882.95 -IDA & IBRD total,IBT,1975,1303667274673.25 -IDA & IBRD total,IBT,1976,1413816096264.77 -IDA & IBRD total,IBT,1977,1596341785085 -IDA & IBRD total,IBT,1978,1730854109299.48 -IDA & IBRD total,IBT,1979,2065313058061.8 -IDA & IBRD total,IBT,1980,2422283170989.76 -IDA & IBRD total,IBT,1981,2610827592142.73 -IDA & IBRD total,IBT,1982,2582656721626.52 -IDA & IBRD total,IBT,1983,2522667584587.84 -IDA & IBRD total,IBT,1984,2556908680047.68 -IDA & IBRD total,IBT,1985,2691625504690.32 -IDA & IBRD total,IBT,1986,2813180853749.35 -IDA & IBRD total,IBT,1987,2897841130486.82 -IDA & IBRD total,IBT,1988,3135683945829.85 -IDA & IBRD total,IBT,1989,3336319692781.06 -IDA & IBRD total,IBT,1990,3753855345937.29 -IDA & IBRD total,IBT,1991,4028757715172.53 -IDA & IBRD total,IBT,1992,4004458417669.02 -IDA & IBRD total,IBT,1993,4264177499395.29 -IDA & IBRD total,IBT,1994,4630909142217.15 -IDA & IBRD total,IBT,1995,5209713498214.82 -IDA & IBRD total,IBT,1996,5688958786196.36 -IDA & IBRD total,IBT,1997,6012285279839.32 -IDA & IBRD total,IBT,1998,5850703459189.88 -IDA & IBRD total,IBT,1999,5702543484501.18 -IDA & IBRD total,IBT,2000,6204623716453.03 -IDA & IBRD total,IBT,2001,6271139335707.81 -IDA & IBRD total,IBT,2002,6392053928474.98 -IDA & IBRD total,IBT,2003,7219473737910.63 -IDA & IBRD total,IBT,2004,8575492654333.95 -IDA & IBRD total,IBT,2005,10227019071857.2 -IDA & IBRD total,IBT,2006,12135265896478.6 -IDA & IBRD total,IBT,2007,15039672145151.6 -IDA & IBRD total,IBT,2008,18069265699993 -IDA & IBRD total,IBT,2009,17550676210066 -IDA & IBRD total,IBT,2010,21396210578999.2 -IDA & IBRD total,IBT,2011,25246476428292.6 -IDA & IBRD total,IBT,2012,26768123725809.4 -IDA & IBRD total,IBT,2013,28404378612941.1 -IDA & IBRD total,IBT,2014,29459720089842 -IDA & IBRD total,IBT,2015,27894376853304.5 -IDA & IBRD total,IBT,2016,27911770057428.9 -IDA blend,IDB,1960,12528091853.1585 -IDA blend,IDB,1961,13388928377.9155 -IDA blend,IDB,1962,14310570026.0649 -IDA blend,IDB,1963,15136261036.8151 -IDA blend,IDB,1964,16547083675.0911 -IDA blend,IDB,1965,18008427704.7256 -IDA blend,IDB,1966,19548468193.7723 -IDA blend,IDB,1967,19670828004.2858 -IDA blend,IDB,1968,20910846571.8878 -IDA blend,IDB,1969,23861812085.1294 -IDA blend,IDB,1970,32843393663.0869 -IDA blend,IDB,1971,30365264329.5773 -IDA blend,IDB,1972,33936248295.21 -IDA blend,IDB,1973,36073763303.9852 -IDA blend,IDB,1974,52387318527.9086 -IDA blend,IDB,1975,60251909395.5155 -IDA blend,IDB,1976,73264439498.9809 -IDA blend,IDB,1977,76793603162.5652 -IDA blend,IDB,1978,83188559519.2582 -IDA blend,IDB,1979,102363089138.532 -IDA blend,IDB,1980,131669829698.641 -IDA blend,IDB,1981,135610723887.684 -IDA blend,IDB,1982,127708517011.63 -IDA blend,IDB,1983,106285802122.516 -IDA blend,IDB,1984,99724892442.8074 -IDA blend,IDB,1985,99654429284.9044 -IDA blend,IDB,1986,96843172567.8211 -IDA blend,IDB,1987,107048715951.938 -IDA blend,IDB,1988,114678605164.99 -IDA blend,IDB,1989,117241208130.828 -IDA blend,IDB,1990,124515366242.566 -IDA blend,IDB,1991,128087577902.076 -IDA blend,IDB,1992,129464158157.523 -IDA blend,IDB,1993,117459126359.094 -IDA blend,IDB,1994,117901745281.71 -IDA blend,IDB,1995,139685272955.961 -IDA blend,IDB,1996,155752080707.91 -IDA blend,IDB,1997,157340845858.204 -IDA blend,IDB,1998,150468042836.428 -IDA blend,IDB,1999,157062060341.58 -IDA blend,IDB,2000,174891573406.934 -IDA blend,IDB,2001,168921966719.703 -IDA blend,IDB,2002,183712405328.485 -IDA blend,IDB,2003,209404819444.115 -IDA blend,IDB,2004,252474835319.475 -IDA blend,IDB,2005,297634375913.672 -IDA blend,IDB,2006,373661921221.27 -IDA blend,IDB,2007,427256953306.27 -IDA blend,IDB,2008,508512182149.602 -IDA blend,IDB,2009,473469947548.861 -IDA blend,IDB,2010,699996618179.802 -IDA blend,IDB,2011,802831759834.01 -IDA blend,IDB,2012,883071662424.879 -IDA blend,IDB,2013,960383402110.485 -IDA blend,IDB,2014,1043383926479.73 -IDA blend,IDB,2015,976614588892.231 -IDA blend,IDB,2016,914220211373.289 -IDA only,IDX,1960,26900729558.6756 -IDA only,IDX,1961,28202127747.3091 -IDA only,IDX,1962,30578919823.2805 -IDA only,IDX,1963,35608750994.9935 -IDA only,IDX,1964,32782637428.41 -IDA only,IDX,1965,38049648216.3678 -IDA only,IDX,1966,41260252648.3372 -IDA only,IDX,1967,41803467079.1778 -IDA only,IDX,1968,43857842843.3742 -IDA only,IDX,1969,49232891560.4311 -IDA only,IDX,1970,51155937980.7403 -IDA only,IDX,1971,54433112942.909 -IDA only,IDX,1972,53913727572.5046 -IDA only,IDX,1973,65130587108.3052 -IDA only,IDX,1974,84317852974.6352 -IDA only,IDX,1975,103845586044.62 -IDA only,IDX,1976,95540888530.4483 -IDA only,IDX,1977,108030645862.408 -IDA only,IDX,1978,125870174760.378 -IDA only,IDX,1979,139556026001.644 -IDA only,IDX,1980,151420555888.676 -IDA only,IDX,1981,154577110449.62 -IDA only,IDX,1982,153716825855.11 -IDA only,IDX,1983,147442512236.276 -IDA only,IDX,1984,147495091462.227 -IDA only,IDX,1985,157306474735.099 -IDA only,IDX,1986,168977242488.592 -IDA only,IDX,1987,180063158863.859 -IDA only,IDX,1988,181385498558.729 -IDA only,IDX,1989,179072082631.41 -IDA only,IDX,1990,188126607992.926 -IDA only,IDX,1991,191081249885.044 -IDA only,IDX,1992,179808280295.291 -IDA only,IDX,1993,181679334834.709 -IDA only,IDX,1994,167877722801.344 -IDA only,IDX,1995,191639298395.647 -IDA only,IDX,1996,209648120648.985 -IDA only,IDX,1997,220284365616.801 -IDA only,IDX,1998,226082116332.62 -IDA only,IDX,1999,228981957026.655 -IDA only,IDX,2000,251151822827.442 -IDA only,IDX,2001,246099126238.948 -IDA only,IDX,2002,261187520893.639 -IDA only,IDX,2003,294249141169.591 -IDA only,IDX,2004,332732438424.107 -IDA only,IDX,2005,379223704355.932 -IDA only,IDX,2006,439386921175.794 -IDA only,IDX,2007,521840470219.516 -IDA only,IDX,2008,632814903358.774 -IDA only,IDX,2009,653724047017.456 -IDA only,IDX,2010,739442152602.564 -IDA only,IDX,2011,829706713781.067 -IDA only,IDX,2012,875853724368.38 -IDA only,IDX,2013,952302996802.463 -IDA only,IDX,2014,1028027058553.17 -IDA only,IDX,2015,1040940192004.62 -IDA only,IDX,2016,1077908367748.55 -IDA total,IDA,1960,38748692260.3948 -IDA total,IDA,1961,40905486343.7645 -IDA total,IDA,1962,44123855995.0844 -IDA total,IDA,1963,49688700780.7972 -IDA total,IDA,1964,48638830926.4057 -IDA total,IDA,1965,55127127619.5494 -IDA total,IDA,1966,59801429749.3153 -IDA total,IDA,1967,60439331470.9625 -IDA total,IDA,1968,63710108686.0779 -IDA total,IDA,1969,71945084444.5374 -IDA total,IDA,1970,83611704212.3582 -IDA total,IDA,1971,83933783702.5892 -IDA total,IDA,1972,87371340568.4539 -IDA total,IDA,1973,100144499811.812 -IDA total,IDA,1974,135889407708.479 -IDA total,IDA,1975,162649110156.035 -IDA total,IDA,1976,169321323255.879 -IDA total,IDA,1977,184780649645.364 -IDA total,IDA,1978,208345111898.598 -IDA total,IDA,1979,242195946786.616 -IDA total,IDA,1980,285548847107.09 -IDA total,IDA,1981,292801265885.592 -IDA total,IDA,1982,283456512539.266 -IDA total,IDA,1983,254398227877.098 -IDA total,IDA,1984,247369742089.672 -IDA total,IDA,1985,256654502726.648 -IDA total,IDA,1986,264781775186.289 -IDA total,IDA,1987,286234708513.801 -IDA total,IDA,1988,295577043063.381 -IDA total,IDA,1989,295978940818.795 -IDA total,IDA,1990,312339707016.851 -IDA total,IDA,1991,318967140383.491 -IDA total,IDA,1992,309553959926.279 -IDA total,IDA,1993,298741566135.181 -IDA total,IDA,1994,285802386263.917 -IDA total,IDA,1995,331562738922.137 -IDA total,IDA,1996,365804847537.744 -IDA total,IDA,1997,377740987931.319 -IDA total,IDA,1998,376129203724.069 -IDA total,IDA,1999,385846241612.534 -IDA total,IDA,2000,425955016165.44 -IDA total,IDA,2001,414877779648.671 -IDA total,IDA,2002,444822239206.007 -IDA total,IDA,2003,503607352753.133 -IDA total,IDA,2004,585417780901.716 -IDA total,IDA,2005,677263856840.947 -IDA total,IDA,2006,814002488452.235 -IDA total,IDA,2007,949952688725.4 -IDA total,IDA,2008,1141761566655.15 -IDA total,IDA,2009,1125176003190.5 -IDA total,IDA,2010,1444980672769.83 -IDA total,IDA,2011,1639584122424.2 -IDA total,IDA,2012,1768118438213.61 -IDA total,IDA,2013,1922693336373.33 -IDA total,IDA,2014,2082520619431.07 -IDA total,IDA,2015,2025758505542.6 -IDA total,IDA,2016,1996430776919.24 -Late-demographic dividend,LTE,1960,170979834687.82 -Late-demographic dividend,LTE,1961,157897071090.677 -Late-demographic dividend,LTE,1962,165672797274.762 -Late-demographic dividend,LTE,1963,179542413759.862 -Late-demographic dividend,LTE,1964,198102076676.436 -Late-demographic dividend,LTE,1965,220983844815.084 -Late-demographic dividend,LTE,1966,245370863668.602 -Late-demographic dividend,LTE,1967,247715535734.439 -Late-demographic dividend,LTE,1968,253063859646.871 -Late-demographic dividend,LTE,1969,282834192565.336 -Late-demographic dividend,LTE,1970,321365344911.656 -Late-demographic dividend,LTE,1971,357842300708.806 -Late-demographic dividend,LTE,1972,410662881425.586 -Late-demographic dividend,LTE,1973,521687954591.208 -Late-demographic dividend,LTE,1974,614358488944.055 -Late-demographic dividend,LTE,1975,675062859870.315 -Late-demographic dividend,LTE,1976,736553700531.906 -Late-demographic dividend,LTE,1977,854920620708.272 -Late-demographic dividend,LTE,1978,890798665710.268 -Late-demographic dividend,LTE,1979,1064378208589.85 -Late-demographic dividend,LTE,1980,1206585272167.42 -Late-demographic dividend,LTE,1981,1279073780899.5 -Late-demographic dividend,LTE,1982,1308692614317.31 -Late-demographic dividend,LTE,1983,1210824718313.28 -Late-demographic dividend,LTE,1984,1274947279487.52 -Late-demographic dividend,LTE,1985,1362593298859.71 -Late-demographic dividend,LTE,1986,1449305917334.82 -Late-demographic dividend,LTE,1987,1527784692119.54 -Late-demographic dividend,LTE,1988,1682824251759.88 -Late-demographic dividend,LTE,1989,1907361656034.27 -Late-demographic dividend,LTE,1990,2027228504115.95 -Late-demographic dividend,LTE,1991,2230277776370.29 -Late-demographic dividend,LTE,1992,2079905732735.5 -Late-demographic dividend,LTE,1993,2155921522368 -Late-demographic dividend,LTE,1994,2468839439179.73 -Late-demographic dividend,LTE,1995,3032807636908.79 -Late-demographic dividend,LTE,1996,3325672519645.58 -Late-demographic dividend,LTE,1997,3480271526233.09 -Late-demographic dividend,LTE,1998,3351316496248.07 -Late-demographic dividend,LTE,1999,3096106154774.71 -Late-demographic dividend,LTE,2000,3403220871015.89 -Late-demographic dividend,LTE,2001,3517771351799.08 -Late-demographic dividend,LTE,2002,3726423996249.01 -Late-demographic dividend,LTE,2003,4249229634687.67 -Late-demographic dividend,LTE,2004,5107491089896.68 -Late-demographic dividend,LTE,2005,6161761848491.52 -Late-demographic dividend,LTE,2006,7436786145930.92 -Late-demographic dividend,LTE,2007,9366206761782.71 -Late-demographic dividend,LTE,2008,11644623639987.3 -Late-demographic dividend,LTE,2009,11256631749196.5 -Late-demographic dividend,LTE,2010,13512634949047.9 -Late-demographic dividend,LTE,2011,16461624017478 -Late-demographic dividend,LTE,2012,17588592847258.8 -Late-demographic dividend,LTE,2013,18943439059235.6 -Late-demographic dividend,LTE,2014,19696765765637.5 -Late-demographic dividend,LTE,2015,18442948166730.4 -Late-demographic dividend,LTE,2016,18428970585288.9 -Latin America & Caribbean,LCN,1960,81335701189.6428 -Latin America & Caribbean,LCN,1961,86401548189.3568 -Latin America & Caribbean,LCN,1962,99481669694.8621 -Latin America & Caribbean,LCN,1963,100098935911.675 -Latin America & Caribbean,LCN,1964,111187567574.716 -Latin America & Caribbean,LCN,1965,119770844951.528 -Latin America & Caribbean,LCN,1966,131441042298.551 -Latin America & Caribbean,LCN,1967,134656950399.366 -Latin America & Caribbean,LCN,1968,145003712535.205 -Latin America & Caribbean,LCN,1969,162478343090.837 -Latin America & Caribbean,LCN,1970,176599027868.457 -Latin America & Caribbean,LCN,1971,197516005457.39 -Latin America & Caribbean,LCN,1972,222012459414.042 -Latin America & Caribbean,LCN,1973,290635423997.013 -Latin America & Caribbean,LCN,1974,377414609202.896 -Latin America & Caribbean,LCN,1975,395907967425.139 -Latin America & Caribbean,LCN,1976,440234859237.179 -Latin America & Caribbean,LCN,1977,484661330903.231 -Latin America & Caribbean,LCN,1978,549446058073.142 -Latin America & Caribbean,LCN,1979,653954905333.575 -Latin America & Caribbean,LCN,1980,775694200782.059 -Latin America & Caribbean,LCN,1981,893319180188.671 -Latin America & Caribbean,LCN,1982,835598635135.828 -Latin America & Caribbean,LCN,1983,742131362504.011 -Latin America & Caribbean,LCN,1984,732119681478.353 -Latin America & Caribbean,LCN,1985,753457210178.004 -Latin America & Caribbean,LCN,1986,766884114945.657 -Latin America & Caribbean,LCN,1987,807221928641.526 -Latin America & Caribbean,LCN,1988,921057504142.402 -Latin America & Caribbean,LCN,1989,1006663109065.92 -Latin America & Caribbean,LCN,1990,1170492068804.72 -Latin America & Caribbean,LCN,1991,1440178343364.67 -Latin America & Caribbean,LCN,1992,1358408884243.74 -Latin America & Caribbean,LCN,1993,1564958746610.74 -Latin America & Caribbean,LCN,1994,1797150601266.59 -Latin America & Caribbean,LCN,1995,1916099987242.12 -Latin America & Caribbean,LCN,1996,2060739339318.38 -Latin America & Caribbean,LCN,1997,2255377930705.67 -Latin America & Caribbean,LCN,1998,2271734532596.57 -Latin America & Caribbean,LCN,1999,2050793762812.47 -Latin America & Caribbean,LCN,2000,2262087168956.71 -Latin America & Caribbean,LCN,2001,2204812692751.2 -Latin America & Caribbean,LCN,2002,1976793288246.23 -Latin America & Caribbean,LCN,2003,2035297413712.73 -Latin America & Caribbean,LCN,2004,2350652052445.82 -Latin America & Caribbean,LCN,2005,2845502363895.91 -Latin America & Caribbean,LCN,2006,3337221449300.33 -Latin America & Caribbean,LCN,2007,3936233657945.05 -Latin America & Caribbean,LCN,2008,4575918476342.71 -Latin America & Caribbean,LCN,2009,4302206310681.48 -Latin America & Caribbean,LCN,2010,5334359905744.97 -Latin America & Caribbean,LCN,2011,6063818698406.67 -Latin America & Caribbean,LCN,2012,6118412885788.98 -Latin America & Caribbean,LCN,2013,6270431817071.43 -Latin America & Caribbean,LCN,2014,6389407132290.57 -Latin America & Caribbean,LCN,2015,5456024297600.86 -Latin America & Caribbean,LCN,2016,5294928047201.73 -Latin America & Caribbean (excluding high income),LAC,1960,73395468426.688 -Latin America & Caribbean (excluding high income),LAC,1961,77129609859.8088 -Latin America & Caribbean (excluding high income),LAC,1962,88911888348.821 -Latin America & Caribbean (excluding high income),LAC,1963,89097573498.6413 -Latin America & Caribbean (excluding high income),LAC,1964,99074812474.4309 -Latin America & Caribbean (excluding high income),LAC,1965,107304593077.581 -Latin America & Caribbean (excluding high income),LAC,1966,117616850185.479 -Latin America & Caribbean (excluding high income),LAC,1967,120609010516.58 -Latin America & Caribbean (excluding high income),LAC,1968,130256250949.786 -Latin America & Caribbean (excluding high income),LAC,1969,145346421052.827 -Latin America & Caribbean (excluding high income),LAC,1970,157880701506.35 -Latin America & Caribbean (excluding high income),LAC,1971,175505487290.549 -Latin America & Caribbean (excluding high income),LAC,1972,198599650385.719 -Latin America & Caribbean (excluding high income),LAC,1973,259117670925.781 -Latin America & Caribbean (excluding high income),LAC,1974,344587170087.191 -Latin America & Caribbean (excluding high income),LAC,1975,371280813794.006 -Latin America & Caribbean (excluding high income),LAC,1976,411643476107.596 -Latin America & Caribbean (excluding high income),LAC,1977,450102375279.173 -Latin America & Caribbean (excluding high income),LAC,1978,509915128707.522 -Latin America & Caribbean (excluding high income),LAC,1979,602811483644.084 -Latin America & Caribbean (excluding high income),LAC,1980,710116907993.984 -Latin America & Caribbean (excluding high income),LAC,1981,818425766809.108 -Latin America & Caribbean (excluding high income),LAC,1982,769759179392.8 -Latin America & Caribbean (excluding high income),LAC,1983,685169082243.003 -Latin America & Caribbean (excluding high income),LAC,1984,673764033131.398 -Latin America & Caribbean (excluding high income),LAC,1985,695943952938.005 -Latin America & Caribbean (excluding high income),LAC,1986,707488075055.622 -Latin America & Caribbean (excluding high income),LAC,1987,740352753238.472 -Latin America & Caribbean (excluding high income),LAC,1988,846851503909.44 -Latin America & Caribbean (excluding high income),LAC,1989,925567803838.453 -Latin America & Caribbean (excluding high income),LAC,1990,1081353158707.23 -Latin America & Caribbean (excluding high income),LAC,1991,1341594021709.41 -Latin America & Caribbean (excluding high income),LAC,1992,1247729796135 -Latin America & Caribbean (excluding high income),LAC,1993,1446291182393.37 -Latin America & Caribbean (excluding high income),LAC,1994,1663902703398.57 -Latin America & Caribbean (excluding high income),LAC,1995,1760538940825.78 -Latin America & Caribbean (excluding high income),LAC,1996,1895254878110.68 -Latin America & Caribbean (excluding high income),LAC,1997,2074269012884.32 -Latin America & Caribbean (excluding high income),LAC,1998,2085413655025.19 -Latin America & Caribbean (excluding high income),LAC,1999,1867635348455.59 -Latin America & Caribbean (excluding high income),LAC,2000,2070772006620.39 -Latin America & Caribbean (excluding high income),LAC,2001,2013631181344.99 -Latin America & Caribbean (excluding high income),LAC,2002,1791362291806.72 -Latin America & Caribbean (excluding high income),LAC,2003,1839436251262.6 -Latin America & Caribbean (excluding high income),LAC,2004,2121459944550.01 -Latin America & Caribbean (excluding high income),LAC,2005,2579728858022.5 -Latin America & Caribbean (excluding high income),LAC,2006,3029641277365.53 -Latin America & Caribbean (excluding high income),LAC,2007,3598012077005.43 -Latin America & Caribbean (excluding high income),LAC,2008,4213388169678.88 -Latin America & Caribbean (excluding high income),LAC,2009,3953038143139.52 -Latin America & Caribbean (excluding high income),LAC,2010,4923451838328.67 -Latin America & Caribbean (excluding high income),LAC,2011,5604881793369.78 -Latin America & Caribbean (excluding high income),LAC,2012,5639788774858.59 -Latin America & Caribbean (excluding high income),LAC,2013,5771253261929.29 -Latin America & Caribbean (excluding high income),LAC,2014,5905860152291 -Latin America & Caribbean (excluding high income),LAC,2015,5012025091739.32 -Latin America & Caribbean (excluding high income),LAC,2016,4851312777942.51 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1960,76482111077.6185 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1961,81138563371.9225 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1962,93494266400.9791 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1963,93815979997.1996 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1964,104219981388.786 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1965,112129154406.885 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1966,123024977802.299 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1967,125678109114.536 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1968,135122479528.732 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1969,151315870034.114 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1970,164325954209.404 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1971,183241160615.466 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1972,205656941379.028 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1973,271328852988.129 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1974,355626000642.165 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1975,371930862648.18 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1976,414445379589.903 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1977,457226562193.466 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1978,516657430530.222 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1979,616982642629.746 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1980,735862731970.81 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1981,851087909516.137 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1982,791710474105.973 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1983,696442194165.987 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1984,682241174471.374 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1985,703159186334.514 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1986,713216307476.36 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1987,750018929385.015 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1988,858688357375.556 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1989,941803363255.407 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1990,1100843309813.08 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1991,1372317945905.81 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1992,1290654691364.3 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1993,1493678182537.17 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1994,1715751583151.98 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1995,1829060058160.92 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1996,1975504627485.21 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1997,2164600526781.61 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1998,2173777212537.54 -Latin America & the Caribbean (IDA & IBRD countries),TLA,1999,1946393638777.13 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2000,2150291053438.54 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2001,2083909607913.16 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2002,1851416583657.79 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2003,1903845944839.22 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2004,2210850350066.21 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2005,2694953121481.19 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2006,3171420273729.5 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2007,3760043430335.24 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2008,4392555500737.54 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2009,4116124679683.7 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2010,5141956791475.98 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2011,5863434327505.38 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2012,5912679156108.39 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2013,6058441110940.89 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2014,6171728371691.76 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2015,5247223786180.95 -Latin America & the Caribbean (IDA & IBRD countries),TLA,2016,5091478259237.56 -Least developed countries: UN classification,LDC,1985,121227419694.536 -Least developed countries: UN classification,LDC,1986,131938238081.808 -Least developed countries: UN classification,LDC,1987,143578647017.282 -Least developed countries: UN classification,LDC,1988,147074754062.361 -Least developed countries: UN classification,LDC,1989,152628715228.138 -Least developed countries: UN classification,LDC,1990,157170715256.827 -Least developed countries: UN classification,LDC,1991,160976404765.403 -Least developed countries: UN classification,LDC,1992,141665506654.277 -Least developed countries: UN classification,LDC,1993,143654148545.13 -Least developed countries: UN classification,LDC,1994,134056722134.952 -Least developed countries: UN classification,LDC,1995,152708087751.642 -Least developed countries: UN classification,LDC,1996,168685657996.561 -Least developed countries: UN classification,LDC,1997,178534049893.884 -Least developed countries: UN classification,LDC,1998,179530418610.067 -Least developed countries: UN classification,LDC,1999,181622928394.098 -Least developed countries: UN classification,LDC,2000,206064992890.969 -Least developed countries: UN classification,LDC,2001,196139081536.109 -Least developed countries: UN classification,LDC,2002,211734892493.178 -Least developed countries: UN classification,LDC,2003,239687925539.993 -Least developed countries: UN classification,LDC,2004,275300002656.28 -Least developed countries: UN classification,LDC,2005,322233431675.558 -Least developed countries: UN classification,LDC,2006,377006716127.018 -Least developed countries: UN classification,LDC,2007,458953974129.743 -Least developed countries: UN classification,LDC,2008,570703787280.472 -Least developed countries: UN classification,LDC,2009,583900864058.256 -Least developed countries: UN classification,LDC,2010,659839922368.982 -Least developed countries: UN classification,LDC,2011,750266890616.884 -Least developed countries: UN classification,LDC,2012,796749375366.047 -Least developed countries: UN classification,LDC,2013,863502921391.032 -Least developed countries: UN classification,LDC,2014,936514097645.983 -Least developed countries: UN classification,LDC,2015,928999138028.508 -Least developed countries: UN classification,LDC,2016,940285148246.681 -Low & middle income,LMY,1960,322880916332.716 -Low & middle income,LMY,1961,311231715583.693 -Low & middle income,LMY,1962,325417665734.193 -Low & middle income,LMY,1963,350156888666 -Low & middle income,LMY,1964,389096758803.45 -Low & middle income,LMY,1965,430331569299.832 -Low & middle income,LMY,1966,445816749394.908 -Low & middle income,LMY,1967,457649154436.817 -Low & middle income,LMY,1968,484077925262.186 -Low & middle income,LMY,1969,541207794796.467 -Low & middle income,LMY,1970,592564334146.401 -Low & middle income,LMY,1971,639515242844.186 -Low & middle income,LMY,1972,714843001925.87 -Low & middle income,LMY,1973,903871947953.725 -Low & middle income,LMY,1974,1155364728140.96 -Low & middle income,LMY,1975,1278200898264.97 -Low & middle income,LMY,1976,1383584014217.24 -Low & middle income,LMY,1977,1557251333561.92 -Low & middle income,LMY,1978,1689674986849.66 -Low & middle income,LMY,1979,2008497065323.04 -Low & middle income,LMY,1980,2344256743828.1 -Low & middle income,LMY,1981,2520680956567.89 -Low & middle income,LMY,1982,2506206543210.46 -Low & middle income,LMY,1983,2460475457385.26 -Low & middle income,LMY,1984,2497490161411.77 -Low & middle income,LMY,1985,2631158758229.95 -Low & middle income,LMY,1986,2752146346147.57 -Low & middle income,LMY,1987,2830361348685.47 -Low & middle income,LMY,1988,3061048683744.94 -Low & middle income,LMY,1989,3252693889005.75 -Low & middle income,LMY,1990,3658538915672.86 -Low & middle income,LMY,1991,3901223943739.81 -Low & middle income,LMY,1992,3855226625179.94 -Low & middle income,LMY,1993,4108081847781.04 -Low & middle income,LMY,1994,4454438133064.89 -Low & middle income,LMY,1995,4983280097683.29 -Low & middle income,LMY,1996,5432096474657.18 -Low & middle income,LMY,1997,5746597952135 -Low & middle income,LMY,1998,5570045115899.25 -Low & middle income,LMY,1999,5438376046486.8 -Low & middle income,LMY,2000,5939720920632.49 -Low & middle income,LMY,2001,5994991423437.34 -Low & middle income,LMY,2002,6113967979982.54 -Low & middle income,LMY,2003,6911432587348.75 -Low & middle income,LMY,2004,8199024522261.18 -Low & middle income,LMY,2005,9771338254565.71 -Low & middle income,LMY,2006,11610585486988 -Low & middle income,LMY,2007,14403262097266.8 -Low & middle income,LMY,2008,17304070901099.9 -Low & middle income,LMY,2009,16904208788743.9 -Low & middle income,LMY,2010,20662142675904.1 -Low & middle income,LMY,2011,24424596002573.7 -Low & middle income,LMY,2012,25968368047735.1 -Low & middle income,LMY,2013,27567318674507.7 -Low & middle income,LMY,2014,28624869169602 -Low & middle income,LMY,2015,27167365722548.3 -Low & middle income,LMY,2016,27190673692762.9 -Low income,LIC,1980,80209493052.731 -Low income,LIC,1981,77218047173.3983 -Low income,LIC,1982,80698662025.246 -Low income,LIC,1983,75225831144.4383 -Low income,LIC,1984,69082552304.0881 -Low income,LIC,1985,71599175719.0479 -Low income,LIC,1986,81243884335.6357 -Low income,LIC,1987,84768074082.989 -Low income,LIC,1988,91473322897.3124 -Low income,LIC,1989,90496828327.9022 -Low income,LIC,1990,96263982212.309 -Low income,LIC,1991,98290478926.7244 -Low income,LIC,1992,86879256494.9218 -Low income,LIC,1993,86545417718.2698 -Low income,LIC,1994,73004355880.147 -Low income,LIC,1995,84186096134.2208 -Low income,LIC,1996,93849664244.7633 -Low income,LIC,1997,97016681510.3045 -Low income,LIC,1998,98076470573.4088 -Low income,LIC,1999,98178378552.344 -Low income,LIC,2000,113334918600.364 -Low income,LIC,2001,102344707240.841 -Low income,LIC,2002,110542725688.212 -Low income,LIC,2003,121412373512.426 -Low income,LIC,2004,138406056360.832 -Low income,LIC,2005,159876776422.899 -Low income,LIC,2006,177405351695.882 -Low income,LIC,2007,211564340820.323 -Low income,LIC,2008,254864815001.772 -Low income,LIC,2009,271114296708.762 -Low income,LIC,2010,289973428214.635 -Low income,LIC,2011,327276455418.728 -Low income,LIC,2012,352304788203.414 -Low income,LIC,2013,379841277359.31 -Low income,LIC,2014,409946364477.957 -Low income,LIC,2015,401557904349.121 -Low income,LIC,2016,405500691890.706 -Lower middle income,LMC,1965,137461884746.768 -Lower middle income,LMC,1966,124653071069.42 -Lower middle income,LMC,1967,132904891803.828 -Lower middle income,LMC,1968,142418186233.418 -Lower middle income,LMC,1969,158951711186.14 -Lower middle income,LMC,1970,174828599744.636 -Lower middle income,LMC,1971,181895531247.864 -Lower middle income,LMC,1972,193226951288.583 -Lower middle income,LMC,1973,230257570746.104 -Lower middle income,LMC,1974,295746915764.238 -Lower middle income,LMC,1975,328315078089.788 -Lower middle income,LMC,1976,355970733034.943 -Lower middle income,LMC,1977,407693469545.836 -Lower middle income,LMC,1978,456337424996.254 -Lower middle income,LMC,1979,519598733097.624 -Lower middle income,LMC,1980,645574198150.025 -Lower middle income,LMC,1981,681873952068.244 -Lower middle income,LMC,1982,688236725783.1 -Lower middle income,LMC,1983,672506305328.491 -Lower middle income,LMC,1984,669999684572.239 -Lower middle income,LMC,1985,705033625730.709 -Lower middle income,LMC,1986,734922204323.85 -Lower middle income,LMC,1987,807849540707.224 -Lower middle income,LMC,1988,841860056894.847 -Lower middle income,LMC,1989,854143629643.268 -Lower middle income,LMC,1990,914031845671.275 -Lower middle income,LMC,1991,879585053610.512 -Lower middle income,LMC,1992,917120105052.312 -Lower middle income,LMC,1993,928250234223.785 -Lower middle income,LMC,1994,1008393895038.79 -Lower middle income,LMC,1995,1132835750025.1 -Lower middle income,LMC,1996,1244059564531.71 -Lower middle income,LMC,1997,1285159992957.23 -Lower middle income,LMC,1998,1162403879271.33 -Lower middle income,LMC,1999,1260946586435.45 -Lower middle income,LMC,2000,1334823902218.48 -Lower middle income,LMC,2001,1347552601226.17 -Lower middle income,LMC,2002,1447377162059.63 -Lower middle income,LMC,2003,1659139779548.2 -Lower middle income,LMC,2004,1897336556896.53 -Lower middle income,LMC,2005,2185062024100.34 -Lower middle income,LMC,2006,2598144857845.71 -Lower middle income,LMC,2007,3198643502815.83 -Lower middle income,LMC,2008,3597614231170.5 -Lower middle income,LMC,2009,3686218059205.86 -Lower middle income,LMC,2010,4659868433805.74 -Lower middle income,LMC,2011,5271066216374.76 -Lower middle income,LMC,2012,5526562820088.11 -Lower middle income,LMC,2013,5765503690093.18 -Lower middle income,LMC,2014,6067382503069.23 -Lower middle income,LMC,2015,6034684295981.41 -Lower middle income,LMC,2016,6252243979358.16 -Middle East & North Africa,MEA,1968,32544887124.715 -Middle East & North Africa,MEA,1969,36324978697.3221 -Middle East & North Africa,MEA,1970,40541253687.1512 -Middle East & North Africa,MEA,1971,46837776480.6965 -Middle East & North Africa,MEA,1972,57004801533.1691 -Middle East & North Africa,MEA,1973,76859486837.6555 -Middle East & North Africa,MEA,1974,140509090225.561 -Middle East & North Africa,MEA,1975,153634644912.125 -Middle East & North Africa,MEA,1976,191078602015.36 -Middle East & North Africa,MEA,1977,221864632728.163 -Middle East & North Africa,MEA,1978,235765780535.398 -Middle East & North Africa,MEA,1979,308143991726.14 -Middle East & North Africa,MEA,1980,399635706600.82 -Middle East & North Africa,MEA,1981,413100094747.124 -Middle East & North Africa,MEA,1982,410711932256.055 -Middle East & North Africa,MEA,1983,416988855437.435 -Middle East & North Africa,MEA,1984,422997945987.704 -Middle East & North Africa,MEA,1985,429106552157.991 -Middle East & North Africa,MEA,1986,438374928771.13 -Middle East & North Africa,MEA,1987,405957775183.96 -Middle East & North Africa,MEA,1988,402886867149.289 -Middle East & North Africa,MEA,1989,415650066556.61 -Middle East & North Africa,MEA,1990,544628789841.346 -Middle East & North Africa,MEA,1991,545480411372.983 -Middle East & North Africa,MEA,1992,593377600004.871 -Middle East & North Africa,MEA,1993,597234481572.268 -Middle East & North Africa,MEA,1994,621835421140.165 -Middle East & North Africa,MEA,1995,708396338042.244 -Middle East & North Africa,MEA,1996,802232077700.633 -Middle East & North Africa,MEA,1997,832583629107.313 -Middle East & North Africa,MEA,1998,809335180977.759 -Middle East & North Africa,MEA,1999,866997519336.959 -Middle East & North Africa,MEA,2000,967123025893.847 -Middle East & North Africa,MEA,2001,970705165852.075 -Middle East & North Africa,MEA,2002,966886322034.273 -Middle East & North Africa,MEA,2003,1089026969409.72 -Middle East & North Africa,MEA,2004,1264692501508.67 -Middle East & North Africa,MEA,2005,1523735247225.23 -Middle East & North Africa,MEA,2006,1783624049835.17 -Middle East & North Africa,MEA,2007,2111520707885.6 -Middle East & North Africa,MEA,2008,2639163398129.61 -Middle East & North Africa,MEA,2009,2353140017976.63 -Middle East & North Africa,MEA,2010,2747991985923.82 -Middle East & North Africa,MEA,2011,3291238768813.27 -Middle East & North Africa,MEA,2012,3517290042987.4 -Middle East & North Africa,MEA,2013,3569108760902.47 -Middle East & North Africa,MEA,2014,3552155105906.59 -Middle East & North Africa,MEA,2015,3153183676492.12 -Middle East & North Africa,MEA,2016,3111499137793.74 -Middle East & North Africa (excluding high income),MNA,1993,291596156344.835 -Middle East & North Africa (excluding high income),MNA,1994,299033433705.304 -Middle East & North Africa (excluding high income),MNA,1995,341005087325.937 -Middle East & North Africa (excluding high income),MNA,1996,395419455083.866 -Middle East & North Africa (excluding high income),MNA,1997,406142008337.3 -Middle East & North Africa (excluding high income),MNA,1998,412226941363.17 -Middle East & North Africa (excluding high income),MNA,1999,435964657109.841 -Middle East & North Africa (excluding high income),MNA,2000,451745270165.348 -Middle East & North Africa (excluding high income),MNA,2001,467443771526.278 -Middle East & North Africa (excluding high income),MNA,2002,453763567498.89 -Middle East & North Africa (excluding high income),MNA,2003,511876924084.121 -Middle East & North Africa (excluding high income),MNA,2004,586243634956.355 -Middle East & North Africa (excluding high income),MNA,2005,691427125900.788 -Middle East & North Africa (excluding high income),MNA,2006,803273276926.291 -Middle East & North Africa (excluding high income),MNA,2007,989862700047.422 -Middle East & North Africa (excluding high income),MNA,2008,1225666634970.85 -Middle East & North Africa (excluding high income),MNA,2009,1179785595912.43 -Middle East & North Africa (excluding high income),MNA,2010,1362935523406.7 -Middle East & North Africa (excluding high income),MNA,2011,1577443963809.85 -Middle East & North Africa (excluding high income),MNA,2012,1668157593637.49 -Middle East & North Africa (excluding high income),MNA,2013,1637016759700.7 -Middle East & North Africa (excluding high income),MNA,2014,1579293076205.83 -Middle East & North Africa (excluding high income),MNA,2015,1445527236068.07 -Middle East & North Africa (IDA & IBRD countries),TMN,1993,288793981432.888 -Middle East & North Africa (IDA & IBRD countries),TMN,1994,296159788194.109 -Middle East & North Africa (IDA & IBRD countries),TMN,1995,337684846816.424 -Middle East & North Africa (IDA & IBRD countries),TMN,1996,391994294829.679 -Middle East & North Africa (IDA & IBRD countries),TMN,1997,402348143945.757 -Middle East & North Africa (IDA & IBRD countries),TMN,1998,408106910445.414 -Middle East & North Africa (IDA & IBRD countries),TMN,1999,431640382177.662 -Middle East & North Africa (IDA & IBRD countries),TMN,2000,447384545921.062 -Middle East & North Africa (IDA & IBRD countries),TMN,2001,463423567528.959 -Middle East & North Africa (IDA & IBRD countries),TMN,2002,450214949083.257 -Middle East & North Africa (IDA & IBRD countries),TMN,2003,507920055467.194 -Middle East & North Africa (IDA & IBRD countries),TMN,2004,581942286783.674 -Middle East & North Africa (IDA & IBRD countries),TMN,2005,686628893957.615 -Middle East & North Africa (IDA & IBRD countries),TMN,2006,798404019734.187 -Middle East & North Africa (IDA & IBRD countries),TMN,2007,984408659212.038 -Middle East & North Africa (IDA & IBRD countries),TMN,2008,1219063793136.09 -Middle East & North Africa (IDA & IBRD countries),TMN,2009,1172546853378.41 -Middle East & North Africa (IDA & IBRD countries),TMN,2010,1354032869496.32 -Middle East & North Africa (IDA & IBRD countries),TMN,2011,1566983828956.61 -Middle East & North Africa (IDA & IBRD countries),TMN,2012,1656868816266.87 -Middle East & North Africa (IDA & IBRD countries),TMN,2013,1624432436239.87 -Middle East & North Africa (IDA & IBRD countries),TMN,2014,1566425106492.08 -Middle East & North Africa (IDA & IBRD countries),TMN,2015,1432641907767.45 -Middle income,MIC,1960,310379641287.339 -Middle income,MIC,1961,298629856589.636 -Middle income,MIC,1962,311470336452.733 -Middle income,MIC,1963,332436061824.552 -Middle income,MIC,1964,375258292135.611 -Middle income,MIC,1965,413664176294.508 -Middle income,MIC,1966,427456737432.456 -Middle income,MIC,1967,440150321992.544 -Middle income,MIC,1968,465920438850.911 -Middle income,MIC,1969,520867515611.093 -Middle income,MIC,1970,571296418063.845 -Middle income,MIC,1971,616131606095.362 -Middle income,MIC,1972,688973366920.011 -Middle income,MIC,1973,872977889163.73 -Middle income,MIC,1974,1118745885064.35 -Middle income,MIC,1975,1236174910742.05 -Middle income,MIC,1976,1341860828067.38 -Middle income,MIC,1977,1509117019025.73 -Middle income,MIC,1978,1634224303394.68 -Middle income,MIC,1979,1947681001919.87 -Middle income,MIC,1980,2280187292914.43 -Middle income,MIC,1981,2459499139801.4 -Middle income,MIC,1982,2441787641412.67 -Middle income,MIC,1983,2400889964155.46 -Middle income,MIC,1984,2443660614880.83 -Middle income,MIC,1985,2575525887782.12 -Middle income,MIC,1986,2688214490798.85 -Middle income,MIC,1987,2763479253508.59 -Middle income,MIC,1988,2988896953383.47 -Middle income,MIC,1989,3182426401658.11 -Middle income,MIC,1990,3583954413081.7 -Middle income,MIC,1991,3825385475042.01 -Middle income,MIC,1992,3789343789199.26 -Middle income,MIC,1993,4043243535797.25 -Middle income,MIC,1994,4402360060455.03 -Middle income,MIC,1995,4922821848492.25 -Middle income,MIC,1996,5363658537833.46 -Middle income,MIC,1997,5674926531226.03 -Middle income,MIC,1998,5499432482324.87 -Middle income,MIC,1999,5365881260373.12 -Middle income,MIC,2000,5851457342169 -Middle income,MIC,2001,5917641548115.5 -Middle income,MIC,2002,6032742784414.22 -Middle income,MIC,2003,6827061176773.63 -Middle income,MIC,2004,8104396652437.36 -Middle income,MIC,2005,9658919014552.3 -Middle income,MIC,2006,11484611685884.1 -Middle income,MIC,2007,14252023316865.7 -Middle income,MIC,2008,17120054313779.3 -Middle income,MIC,2009,16697282511085.5 -Middle income,MIC,2010,20431462486141.4 -Middle income,MIC,2011,24158308272825.3 -Middle income,MIC,2012,25671457284263.6 -Middle income,MIC,2013,27244416912947.4 -Middle income,MIC,2014,28271814853457.7 -Middle income,MIC,2015,26814503372731.8 -Middle income,MIC,2016,26835804840473.3 -North America,NAC,1960,584477920198.99 -North America,NAC,1961,604157219440.397 -North America,NAC,1962,647173002027.413 -North America,NAC,1963,683353535761.531 -North America,NAC,1964,734790505460.858 -North America,NAC,1965,797723909391.131 -North America,NAC,1966,875492805408.936 -North America,NAC,1967,926623934246.798 -North America,NAC,1968,1013409031841.72 -North America,NAC,1969,1097952410241.71 -North America,NAC,1970,1163966395224.42 -North America,NAC,1971,1267253061477.52 -North America,NAC,1972,1395767220992.02 -North America,NAC,1973,1560140359214.08 -North America,NAC,1974,1709546297648.26 -North America,NAC,1975,1863102029787.65 -North America,NAC,1976,2084548864401.62 -North America,NAC,1977,2298010156934.65 -North America,NAC,1978,2575679667449.81 -North America,NAC,1979,2875732302185.42 -North America,NAC,1980,3136972126345.01 -North America,NAC,1981,3517909963656.99 -North America,NAC,1982,3659283025119.14 -North America,NAC,1983,3979574111781.89 -North America,NAC,1984,4397051258071.62 -North America,NAC,1985,4712529999482.75 -North America,NAC,1986,4968766427343.98 -North America,NAC,1987,5302830242049.45 -North America,NAC,1988,5761398451214.26 -North America,NAC,1989,6224250243275.25 -North America,NAC,1990,6575110950908.47 -North America,NAC,1991,6786006083611.19 -North America,NAC,1992,7133366589284.92 -North America,NAC,1993,7457709121892.44 -North America,NAC,1994,7888761439501.61 -North America,NAC,1995,8270122373385.4 -North America,NAC,1996,8731442777972.13 -North America,NAC,1997,9264273191726.28 -North America,NAC,1998,9724112027406.81 -North America,NAC,1999,10340031087640.9 -North America,NAC,2000,11030552667252.6 -North America,NAC,2001,11361884260892.6 -North America,NAC,2002,11739401906646.5 -North America,NAC,2003,12407237511367.9 -North America,NAC,2004,13302608706074.6 -North America,NAC,2005,14267952115864.7 -North America,NAC,2006,15176717496461.2 -North America,NAC,2007,15948507238205.8 -North America,NAC,2008,16273823136997.2 -North America,NAC,2009,15795698382986.4 -North America,NAC,2010,16583580836811.1 -North America,NAC,2011,17312124677047.8 -North America,NAC,2012,17985081294447.6 -North America,NAC,2013,18539718715830.2 -North America,NAC,2014,19191755961783.7 -North America,NAC,2015,19595346721974.5 -North America,NAC,2016,20104904753734.8 -OECD members,OED,1960,1071148468561.41 -OECD members,OED,1961,1125832842998.51 -OECD members,OED,1962,1215841389136.37 -OECD members,OED,1963,1310283723048.87 -OECD members,OED,1964,1431887112561.98 -OECD members,OED,1965,1554546204085.41 -OECD members,OED,1966,1706871950732.13 -OECD members,OED,1967,1831600828348.03 -OECD members,OED,1968,1985484758150.99 -OECD members,OED,1969,2179226855795.61 -OECD members,OED,1970,2390390686111.07 -OECD members,OED,1971,2646317574763.35 -OECD members,OED,1972,3070546015009.47 -OECD members,OED,1973,3709185177074.73 -OECD members,OED,1974,4158280828971.97 -OECD members,OED,1975,4658825077597.2 -OECD members,OED,1976,5049009543873.49 -OECD members,OED,1977,5693077367140.28 -OECD members,OED,1978,6835772209740.3 -OECD members,OED,1979,7896142494077.98 -OECD members,OED,1980,8764338498877.9 -OECD members,OED,1981,8922436064860.69 -OECD members,OED,1982,8786255124380.75 -OECD members,OED,1983,9077887021838.69 -OECD members,OED,1984,9494477176460.86 -OECD members,OED,1985,10015967458690.2 -OECD members,OED,1986,12140888703533 -OECD members,OED,1987,14052574571754.2 -OECD members,OED,1988,15854831419998 -OECD members,OED,1989,16610824977450.6 -OECD members,OED,1990,18717131834846.2 -OECD members,OED,1991,19798533698156.4 -OECD members,OED,1992,21286212823936.3 -OECD members,OED,1993,21602686285516.6 -OECD members,OED,1994,23066746233125.3 -OECD members,OED,1995,25409558844503.5 -OECD members,OED,1996,25631695317896.3 -OECD members,OED,1997,25240277081015.1 -OECD members,OED,1998,25498833540302.8 -OECD members,OED,1999,26798774923570.7 -OECD members,OED,2000,27363992604547.7 -OECD members,OED,2001,27110458919332 -OECD members,OED,2002,28288512785831.6 -OECD members,OED,2003,31695202048895.5 -OECD members,OED,2004,35282198913762.3 -OECD members,OED,2005,37292067332552.4 -OECD members,OED,2006,39314471295987.4 -OECD members,OED,2007,42976830154645.7 -OECD members,OED,2008,45489387299735.7 -OECD members,OED,2009,42557636517549.5 -OECD members,OED,2010,44588338330918.9 -OECD members,OED,2011,47907103635329.9 -OECD members,OED,2012,47806877198116 -OECD members,OED,2013,48377472404230.7 -OECD members,OED,2014,49318789250850.1 -OECD members,OED,2015,46489946919891.2 -OECD members,OED,2016,47394052796780.3 -Other small states,OSS,1970,3120000513.63038 -Other small states,OSS,1971,3703668497.25236 -Other small states,OSS,1972,4485075013.76688 -Other small states,OSS,1973,6495784978.63854 -Other small states,OSS,1974,11967802921.9622 -Other small states,OSS,1975,13355843219.8957 -Other small states,OSS,1976,16602401120.5883 -Other small states,OSS,1977,18699272186.2965 -Other small states,OSS,1978,20631386856.0129 -Other small states,OSS,1979,26785098967.4081 -Other small states,OSS,1980,37183269997.956 -Other small states,OSS,1981,37385918037.1978 -Other small states,OSS,1982,35362618281.9374 -Other small states,OSS,1983,33399704521.5294 -Other small states,OSS,1984,33642964084.1968 -Other small states,OSS,1985,31964598499.4935 -Other small states,OSS,1986,32342044549.6327 -Other small states,OSS,1987,38389402844.2948 -Other small states,OSS,1988,43139712814.829 -Other small states,OSS,1989,45177490212.0309 -Other small states,OSS,1990,54042037641.2318 -Other small states,OSS,1991,55656865129.0129 -Other small states,OSS,1992,60712295552.4811 -Other small states,OSS,1993,57746555835.7855 -Other small states,OSS,1994,60482828187.5356 -Other small states,OSS,1995,69298946725.52 -Other small states,OSS,1996,73172701870.202 -Other small states,OSS,1997,76266859217.9987 -Other small states,OSS,1998,74735365660.7398 -Other small states,OSS,1999,80433140076.8188 -Other small states,OSS,2000,91230480401.4556 -Other small states,OSS,2001,90672611826.8333 -Other small states,OSS,2002,97772578664.9743 -Other small states,OSS,2003,121118378940.561 -Other small states,OSS,2004,150081419957.446 -Other small states,OSS,2005,182102127175.268 -Other small states,OSS,2006,214036484985.338 -Other small states,OSS,2007,261998871872.612 -Other small states,OSS,2008,320442487440.3 -Other small states,OSS,2009,275173743167.462 -Other small states,OSS,2010,320128712509.16 -Other small states,OSS,2011,396019011152.095 -Other small states,OSS,2012,413403874820.602 -Other small states,OSS,2013,431086487370.448 -Other small states,OSS,2014,444405144277.814 -Other small states,OSS,2015,368813590036.302 -Other small states,OSS,2016,358773092768.133 -Pacific island small states,PSS,1975,1119628254.45097 -Pacific island small states,PSS,1976,1122701696.34762 -Pacific island small states,PSS,1977,1171337344.9078 -Pacific island small states,PSS,1978,1358461165.8138 -Pacific island small states,PSS,1979,1664350939.8496 -Pacific island small states,PSS,1980,1904926911.85166 -Pacific island small states,PSS,1981,1963994945.57172 -Pacific island small states,PSS,1982,1918437387.41573 -Pacific island small states,PSS,1983,1837236806.42751 -Pacific island small states,PSS,1984,2014185046.11569 -Pacific island small states,PSS,1985,1906817279.10052 -Pacific island small states,PSS,1986,2070080622.74654 -Pacific island small states,PSS,1987,2033588088.5576 -Pacific island small states,PSS,1988,2130602489.94617 -Pacific island small states,PSS,1989,2224856985.74429 -Pacific island small states,PSS,1990,2396519647.95393 -Pacific island small states,PSS,1991,2548876044.46992 -Pacific island small states,PSS,1992,2794580111.5317 -Pacific island small states,PSS,1993,2946262871.07794 -Pacific island small states,PSS,1994,3395405058.97482 -Pacific island small states,PSS,1995,3668259744.87741 -Pacific island small states,PSS,1996,3939096312.4053 -Pacific island small states,PSS,1997,3935301807.10212 -Pacific island small states,PSS,1998,3383564007.07114 -Pacific island small states,PSS,1999,3685133762.02162 -Pacific island small states,PSS,2000,3448662181.8232 -Pacific island small states,PSS,2001,3375672793.3588 -Pacific island small states,PSS,2002,3547120140.79495 -Pacific island small states,PSS,2003,4158737438.11844 -Pacific island small states,PSS,2004,4803309271.01673 -Pacific island small states,PSS,2005,5273003192.09283 -Pacific island small states,PSS,2006,5542891987.75737 -Pacific island small states,PSS,2007,6079623933.05137 -Pacific island small states,PSS,2008,6554131285.08651 -Pacific island small states,PSS,2009,5775975880.54319 -Pacific island small states,PSS,2010,6402407316.26645 -Pacific island small states,PSS,2011,7588040251.82748 -Pacific island small states,PSS,2012,8109258573.53231 -Pacific island small states,PSS,2013,8375325157.08132 -Pacific island small states,PSS,2014,8780810605.05193 -Pacific island small states,PSS,2015,8577127156.94718 -Pacific island small states,PSS,2016,8888374720.40864 -Post-demographic dividend,PST,1960,1044656471320.34 -Post-demographic dividend,PST,1961,1104232973387.34 -Post-demographic dividend,PST,1962,1192909023772.47 -Post-demographic dividend,PST,1963,1284222177741.77 -Post-demographic dividend,PST,1964,1401673751394.55 -Post-demographic dividend,PST,1965,1522536171657.24 -Post-demographic dividend,PST,1966,1669615615246.75 -Post-demographic dividend,PST,1967,1791607216531.48 -Post-demographic dividend,PST,1968,1941588054277.74 -Post-demographic dividend,PST,1969,2129810291257.2 -Post-demographic dividend,PST,1970,2340888132430.83 -Post-demographic dividend,PST,1971,2595435794745.15 -Post-demographic dividend,PST,1972,3010533039073.01 -Post-demographic dividend,PST,1973,3633402675461.9 -Post-demographic dividend,PST,1974,4057572289102.56 -Post-demographic dividend,PST,1975,4546348912848.59 -Post-demographic dividend,PST,1976,4932972042226.7 -Post-demographic dividend,PST,1977,5576027961708.64 -Post-demographic dividend,PST,1978,6699303304490.5 -Post-demographic dividend,PST,1979,7701902775121.56 -Post-demographic dividend,PST,1980,8528744893965.75 -Post-demographic dividend,PST,1981,8627548222470.53 -Post-demographic dividend,PST,1982,8585856196665.95 -Post-demographic dividend,PST,1983,8907329214532.46 -Post-demographic dividend,PST,1984,9311124585501.98 -Post-demographic dividend,PST,1985,9820475618013.04 -Post-demographic dividend,PST,1986,11992583228317.2 -Post-demographic dividend,PST,1987,13892518055017.9 -Post-demographic dividend,PST,1988,15649138703182.9 -Post-demographic dividend,PST,1989,16363490315438.2 -Post-demographic dividend,PST,1990,18373377012979.3 -Post-demographic dividend,PST,1991,19370853403893.8 -Post-demographic dividend,PST,1992,20787746843384.1 -Post-demographic dividend,PST,1993,20957060229668.8 -Post-demographic dividend,PST,1994,22429029383135.7 -Post-demographic dividend,PST,1995,24852064655451.6 -Post-demographic dividend,PST,1996,24982304258549.2 -Post-demographic dividend,PST,1997,24511726798084.9 -Post-demographic dividend,PST,1998,24615173781504.8 -Post-demographic dividend,PST,1999,25841010690140.8 -Post-demographic dividend,PST,2000,26282689637675.3 -Post-demographic dividend,PST,2001,26041902978856 -Post-demographic dividend,PST,2002,27158954468171.9 -Post-demographic dividend,PST,2003,30469203654916.5 -Post-demographic dividend,PST,2004,33857110810844.5 -Post-demographic dividend,PST,2005,35634331213681.7 -Post-demographic dividend,PST,2006,37477971990381.3 -Post-demographic dividend,PST,2007,40875024376117.4 -Post-demographic dividend,PST,2008,43181906552198.2 -Post-demographic dividend,PST,2009,40654677510668 -Post-demographic dividend,PST,2010,42396023961852.1 -Post-demographic dividend,PST,2011,45507579610296.7 -Post-demographic dividend,PST,2012,45431195222279.9 -Post-demographic dividend,PST,2013,45820016966895.3 -Post-demographic dividend,PST,2014,46685151869819.2 -Post-demographic dividend,PST,2015,44081796060319.5 -Post-demographic dividend,PST,2016,45072138207006.3 -Pre-demographic dividend,PRE,1960,10444792557.8843 -Pre-demographic dividend,PRE,1961,10792191176.9913 -Pre-demographic dividend,PRE,1962,11794111161.167 -Pre-demographic dividend,PRE,1963,13764637075.142 -Pre-demographic dividend,PRE,1964,12795571686.9276 -Pre-demographic dividend,PRE,1965,14432973775.8933 -Pre-demographic dividend,PRE,1966,15869568127.6857 -Pre-demographic dividend,PRE,1967,14966394983.6694 -Pre-demographic dividend,PRE,1968,15779012377.2635 -Pre-demographic dividend,PRE,1969,17940990058.5991 -Pre-demographic dividend,PRE,1970,21951712164.311 -Pre-demographic dividend,PRE,1971,21460771419.442 -Pre-demographic dividend,PRE,1972,24863758794.081 -Pre-demographic dividend,PRE,1973,30483369632.1883 -Pre-demographic dividend,PRE,1974,43595337802.2346 -Pre-demographic dividend,PRE,1975,49542343893.6683 -Pre-demographic dividend,PRE,1976,58304074038.3621 -Pre-demographic dividend,PRE,1977,64654895975.3614 -Pre-demographic dividend,PRE,1978,71877526055.5515 -Pre-demographic dividend,PRE,1979,90876577931.6188 -Pre-demographic dividend,PRE,1980,111128692579.225 -Pre-demographic dividend,PRE,1981,99890611243.0475 -Pre-demographic dividend,PRE,1982,96485338012.3114 -Pre-demographic dividend,PRE,1983,82315486748.1406 -Pre-demographic dividend,PRE,1984,81200162508.3063 -Pre-demographic dividend,PRE,1985,84292961016.2471 -Pre-demographic dividend,PRE,1986,86854873100.4704 -Pre-demographic dividend,PRE,1987,99081060277.1037 -Pre-demographic dividend,PRE,1988,101944868961.831 -Pre-demographic dividend,PRE,1989,104019371613.989 -Pre-demographic dividend,PRE,1990,167507910377.201 -Pre-demographic dividend,PRE,1991,166990503688.432 -Pre-demographic dividend,PRE,1992,152419870394.426 -Pre-demographic dividend,PRE,1993,138508748991.463 -Pre-demographic dividend,PRE,1994,126874724056.413 -Pre-demographic dividend,PRE,1995,155361079241.209 -Pre-demographic dividend,PRE,1996,173224107614.69 -Pre-demographic dividend,PRE,1997,180765049998.456 -Pre-demographic dividend,PRE,1998,178797997119.74 -Pre-demographic dividend,PRE,1999,181481700462.617 -Pre-demographic dividend,PRE,2000,211754710795.63 -Pre-demographic dividend,PRE,2001,200696505653.475 -Pre-demographic dividend,PRE,2002,237011718871.519 -Pre-demographic dividend,PRE,2003,274020284824.498 -Pre-demographic dividend,PRE,2004,332024783749.247 -Pre-demographic dividend,PRE,2005,411421770397.822 -Pre-demographic dividend,PRE,2006,513693910493.325 -Pre-demographic dividend,PRE,2007,628900837818.886 -Pre-demographic dividend,PRE,2008,802590453555.333 -Pre-demographic dividend,PRE,2009,730577224083.185 -Pre-demographic dividend,PRE,2010,1005125615291.85 -Pre-demographic dividend,PRE,2011,1162386942622.43 -Pre-demographic dividend,PRE,2012,1277869591512.9 -Pre-demographic dividend,PRE,2013,1396458716370.55 -Pre-demographic dividend,PRE,2014,1491939195061.18 -Pre-demographic dividend,PRE,2015,1296897941977.73 -Pre-demographic dividend,PRE,2016,1194739930946.8 -Small states,SST,1970,7836787195.57926 -Small states,SST,1971,8818144097.10709 -Small states,SST,1972,10407377358.8588 -Small states,SST,1973,12964753902.4681 -Small states,SST,1974,20152451259.247 -Small states,SST,1975,22936619953.578 -Small states,SST,1976,26214423633.4757 -Small states,SST,1977,29771720454.8057 -Small states,SST,1978,31993368148.3596 -Small states,SST,1979,39722899441.6698 -Small states,SST,1980,52643379201.5761 -Small states,SST,1981,54400876326.3316 -Small states,SST,1982,54173365558.0276 -Small states,SST,1983,52414910869.8285 -Small states,SST,1984,51973393619.5984 -Small states,SST,1985,50036733663.1376 -Small states,SST,1986,49068591555.2924 -Small states,SST,1987,56063766853.2931 -Small states,SST,1988,61791930551.2311 -Small states,SST,1989,64304587894.9821 -Small states,SST,1990,74325169013.8579 -Small states,SST,1991,75856511772.4776 -Small states,SST,1992,80746249830.122 -Small states,SST,1993,78946659813.3949 -Small states,SST,1994,83179982124.9322 -Small states,SST,1995,94034486010.0192 -Small states,SST,1996,100096683467.444 -Small states,SST,1997,105904285406.659 -Small states,SST,1998,106388698435.668 -Small states,SST,1999,114155580862.484 -Small states,SST,2000,126923095471.91 -Small states,SST,2001,127212731119.311 -Small states,SST,2002,136256691925.274 -Small states,SST,2003,162766467544.72 -Small states,SST,2004,196053942193.91 -Small states,SST,2005,234022949884.059 -Small states,SST,2006,271974858948.518 -Small states,SST,2007,326343861812.675 -Small states,SST,2008,393489345339.146 -Small states,SST,2009,336886290580.524 -Small states,SST,2010,387290741084.775 -Small states,SST,2011,469287734302.83 -Small states,SST,2012,489309844392.053 -Small states,SST,2013,508115793399.22 -Small states,SST,2014,521843492853.73 -Small states,SST,2015,444166579289.296 -Small states,SST,2016,431168068762.38 -South Asia,SAS,1960,46535882350.9266 -South Asia,SAS,1961,49639265058.4063 -South Asia,SAS,1962,52969959484.3953 -South Asia,SAS,1963,59564124015.8815 -South Asia,SAS,1964,68207240598.8702 -South Asia,SAS,1965,73302133554.3812 -South Asia,SAS,1966,61638106880.2155 -South Asia,SAS,1967,67859668328.6678 -South Asia,SAS,1968,71227636451.2209 -South Asia,SAS,1969,78199356804.4547 -South Asia,SAS,1970,84723556606.6577 -South Asia,SAS,1971,90042201735.933 -South Asia,SAS,1972,90429767479.7852 -South Asia,SAS,1973,103394104064.568 -South Asia,SAS,1974,125253027719.481 -South Asia,SAS,1975,134416247893.554 -South Asia,SAS,1976,131167736496.854 -South Asia,SAS,1977,151656859741.32 -South Asia,SAS,1978,172583702484.323 -South Asia,SAS,1979,193318644211.014 -South Asia,SAS,1980,233086150890.581 -South Asia,SAS,1981,247106727885.511 -South Asia,SAS,1982,255647758195.845 -South Asia,SAS,1983,270545959911.574 -South Asia,SAS,1984,269355371616.79 -South Asia,SAS,1985,292874261371.477 -South Asia,SAS,1986,310147312219.788 -South Asia,SAS,1987,344338564248.576 -South Asia,SAS,1988,370046274630.143 -South Asia,SAS,1989,373481452094.992 -South Asia,SAS,1990,402050004575.507 -South Asia,SAS,1991,357724016273.124 -South Asia,SAS,1992,379830007893.096 -South Asia,SAS,1993,376239667456.956 -South Asia,SAS,1994,426649315426.754 -South Asia,SAS,1995,474034412841.889 -South Asia,SAS,1996,518624561848.025 -South Asia,SAS,1997,544005563622.908 -South Asia,SAS,1998,551628275406.445 -South Asia,SAS,1999,590948715637.038 -South Asia,SAS,2000,614756473709.585 -South Asia,SAS,2001,630828017006.122 -South Asia,SAS,2002,663250167513.155 -South Asia,SAS,2003,774457944529.068 -South Asia,SAS,2004,897902015362.288 -South Asia,SAS,2005,1028596382537.81 -South Asia,SAS,2006,1176153232856.56 -South Asia,SAS,2007,1488571172561.54 -South Asia,SAS,2008,1515479924054.14 -South Asia,SAS,2009,1665393025481.3 -South Asia,SAS,2010,2041877081506.8 -South Asia,SAS,2011,2271681618877.26 -South Asia,SAS,2012,2297541689398.13 -South Asia,SAS,2013,2356159930348.29 -South Asia,SAS,2014,2577102437097.39 -South Asia,SAS,2015,2705001263802.98 -South Asia,SAS,2016,2896360597068.83 -South Asia (IDA & IBRD),TSA,1960,46535882350.9266 -South Asia (IDA & IBRD),TSA,1961,49639265058.4063 -South Asia (IDA & IBRD),TSA,1962,52969959484.3953 -South Asia (IDA & IBRD),TSA,1963,59564124015.8815 -South Asia (IDA & IBRD),TSA,1964,68207240598.8702 -South Asia (IDA & IBRD),TSA,1965,73302133554.3812 -South Asia (IDA & IBRD),TSA,1966,61638106880.2155 -South Asia (IDA & IBRD),TSA,1967,67859668328.6678 -South Asia (IDA & IBRD),TSA,1968,71227636451.2209 -South Asia (IDA & IBRD),TSA,1969,78199356804.4547 -South Asia (IDA & IBRD),TSA,1970,84723556606.6577 -South Asia (IDA & IBRD),TSA,1971,90042201735.933 -South Asia (IDA & IBRD),TSA,1972,90429767479.7852 -South Asia (IDA & IBRD),TSA,1973,103394104064.568 -South Asia (IDA & IBRD),TSA,1974,125253027719.481 -South Asia (IDA & IBRD),TSA,1975,134416247893.554 -South Asia (IDA & IBRD),TSA,1976,131167736496.854 -South Asia (IDA & IBRD),TSA,1977,151656859741.32 -South Asia (IDA & IBRD),TSA,1978,172583702484.323 -South Asia (IDA & IBRD),TSA,1979,193318644211.014 -South Asia (IDA & IBRD),TSA,1980,233086150890.581 -South Asia (IDA & IBRD),TSA,1981,247106727885.511 -South Asia (IDA & IBRD),TSA,1982,255647758195.845 -South Asia (IDA & IBRD),TSA,1983,270545959911.574 -South Asia (IDA & IBRD),TSA,1984,269355371616.79 -South Asia (IDA & IBRD),TSA,1985,292874261371.477 -South Asia (IDA & IBRD),TSA,1986,310147312219.788 -South Asia (IDA & IBRD),TSA,1987,344338564248.576 -South Asia (IDA & IBRD),TSA,1988,370046274630.143 -South Asia (IDA & IBRD),TSA,1989,373481452094.992 -South Asia (IDA & IBRD),TSA,1990,402050004575.507 -South Asia (IDA & IBRD),TSA,1991,357724016273.124 -South Asia (IDA & IBRD),TSA,1992,379830007893.096 -South Asia (IDA & IBRD),TSA,1993,376239667456.956 -South Asia (IDA & IBRD),TSA,1994,426649315426.754 -South Asia (IDA & IBRD),TSA,1995,474034412841.889 -South Asia (IDA & IBRD),TSA,1996,518624561848.025 -South Asia (IDA & IBRD),TSA,1997,544005563622.908 -South Asia (IDA & IBRD),TSA,1998,551628275406.445 -South Asia (IDA & IBRD),TSA,1999,590948715637.038 -South Asia (IDA & IBRD),TSA,2000,614756473709.585 -South Asia (IDA & IBRD),TSA,2001,630828017006.122 -South Asia (IDA & IBRD),TSA,2002,663250167513.155 -South Asia (IDA & IBRD),TSA,2003,774457944529.068 -South Asia (IDA & IBRD),TSA,2004,897902015362.288 -South Asia (IDA & IBRD),TSA,2005,1028596382537.81 -South Asia (IDA & IBRD),TSA,2006,1176153232856.56 -South Asia (IDA & IBRD),TSA,2007,1488571172561.54 -South Asia (IDA & IBRD),TSA,2008,1515479924054.14 -South Asia (IDA & IBRD),TSA,2009,1665393025481.3 -South Asia (IDA & IBRD),TSA,2010,2041877081506.8 -South Asia (IDA & IBRD),TSA,2011,2271681618877.26 -South Asia (IDA & IBRD),TSA,2012,2297541689398.13 -South Asia (IDA & IBRD),TSA,2013,2356159930348.29 -South Asia (IDA & IBRD),TSA,2014,2577102437097.39 -South Asia (IDA & IBRD),TSA,2015,2705001263802.98 -South Asia (IDA & IBRD),TSA,2016,2896360597068.83 -Sub-Saharan Africa,SSF,1960,30385873317.6191 -Sub-Saharan Africa,SSF,1961,31561069598.0721 -Sub-Saharan Africa,SSF,1962,34208896061.892 -Sub-Saharan Africa,SSF,1963,39225741664.7524 -Sub-Saharan Africa,SSF,1964,38271070687.048 -Sub-Saharan Africa,SSF,1965,42640958019.1558 -Sub-Saharan Africa,SSF,1966,46032013187.6583 -Sub-Saharan Africa,SSF,1967,45494160112.4203 -Sub-Saharan Africa,SSF,1968,48659688079.8348 -Sub-Saharan Africa,SSF,1969,55788782510.7981 -Sub-Saharan Africa,SSF,1970,65641311288.6349 -Sub-Saharan Africa,SSF,1971,66787674494.6591 -Sub-Saharan Africa,SSF,1972,75244560743.9655 -Sub-Saharan Africa,SSF,1973,96178659252.9924 -Sub-Saharan Africa,SSF,1974,126049492057.768 -Sub-Saharan Africa,SSF,1975,138623192435.063 -Sub-Saharan Africa,SSF,1976,150523567593.48 -Sub-Saharan Africa,SSF,1977,165924142356.056 -Sub-Saharan Africa,SSF,1978,183362414567.183 -Sub-Saharan Africa,SSF,1979,220720718807.57 -Sub-Saharan Africa,SSF,1980,277168620649.298 -Sub-Saharan Africa,SSF,1981,279597299140.561 -Sub-Saharan Africa,SSF,1982,261201722615.81 -Sub-Saharan Africa,SSF,1983,243178158509.023 -Sub-Saharan Africa,SSF,1984,231534327753.875 -Sub-Saharan Africa,SSF,1985,215767871591.388 -Sub-Saharan Africa,SSF,1986,239127684060.416 -Sub-Saharan Africa,SSF,1987,281787606420.109 -Sub-Saharan Africa,SSF,1988,296425266186.195 -Sub-Saharan Africa,SSF,1989,310125765635.045 -Sub-Saharan Africa,SSF,1990,310601465373.488 -Sub-Saharan Africa,SSF,1991,320112647218.571 -Sub-Saharan Africa,SSF,1992,314832065746.688 -Sub-Saharan Africa,SSF,1993,298956393687.87 -Sub-Saharan Africa,SSF,1994,291679005862.221 -Sub-Saharan Africa,SSF,1995,337515727715.285 -Sub-Saharan Africa,SSF,1996,349098748885.709 -Sub-Saharan Africa,SSF,1997,361099250055.323 -Sub-Saharan Africa,SSF,1998,340612558536.667 -Sub-Saharan Africa,SSF,1999,343239312535.324 -Sub-Saharan Africa,SSF,2000,367992054429.688 -Sub-Saharan Africa,SSF,2001,342553779838.8 -Sub-Saharan Africa,SSF,2002,367108332547.638 -Sub-Saharan Africa,SSF,2003,468992752558.158 -Sub-Saharan Africa,SSF,2004,583209894804.24 -Sub-Saharan Africa,SSF,2005,685920335014.857 -Sub-Saharan Africa,SSF,2006,801445697569.974 -Sub-Saharan Africa,SSF,2007,932416460747.498 -Sub-Saharan Africa,SSF,2008,1064752013079.22 -Sub-Saharan Africa,SSF,2009,1022260711828.75 -Sub-Saharan Africa,SSF,2010,1361111020590.47 -Sub-Saharan Africa,SSF,2011,1532598528787.88 -Sub-Saharan Africa,SSF,2012,1607918609335.78 -Sub-Saharan Africa,SSF,2013,1692968078930.83 -Sub-Saharan Africa,SSF,2014,1775063779086.99 -Sub-Saharan Africa,SSF,2015,1601114502934 -Sub-Saharan Africa,SSF,2016,1498001165832.29 -Sub-Saharan Africa (excluding high income),SSA,1960,30375251120.8982 -Sub-Saharan Africa (excluding high income),SSA,1961,31551059162.9924 -Sub-Saharan Africa (excluding high income),SSA,1962,34197956223.5719 -Sub-Saharan Africa (excluding high income),SSA,1963,39213859646.9823 -Sub-Saharan Africa (excluding high income),SSA,1964,38257387425.3277 -Sub-Saharan Africa (excluding high income),SSA,1965,42627500884.5051 -Sub-Saharan Africa (excluding high income),SSA,1966,46017949100.4039 -Sub-Saharan Africa (excluding high income),SSA,1967,45479820393.276 -Sub-Saharan Africa (excluding high income),SSA,1968,48646316919.2904 -Sub-Saharan Africa (excluding high income),SSA,1969,55775718701.4028 -Sub-Saharan Africa (excluding high income),SSA,1970,65627001306.2372 -Sub-Saharan Africa (excluding high income),SSA,1971,66769437518.4287 -Sub-Saharan Africa (excluding high income),SSA,1972,75217262850.8043 -Sub-Saharan Africa (excluding high income),SSA,1973,96146370804.013 -Sub-Saharan Africa (excluding high income),SSA,1974,126013152393.226 -Sub-Saharan Africa (excluding high income),SSA,1975,138582808945.702 -Sub-Saharan Africa (excluding high income),SSA,1976,150482725715.529 -Sub-Saharan Africa (excluding high income),SSA,1977,165867501154.588 -Sub-Saharan Africa (excluding high income),SSA,1978,183283589349.244 -Sub-Saharan Africa (excluding high income),SSA,1979,220598169194.501 -Sub-Saharan Africa (excluding high income),SSA,1980,277028916343.799 -Sub-Saharan Africa (excluding high income),SSA,1981,279449423286.245 -Sub-Saharan Africa (excluding high income),SSA,1982,261060121194.45 -Sub-Saharan Africa (excluding high income),SSA,1983,243036605981.087 -Sub-Saharan Africa (excluding high income),SSA,1984,231387005071.033 -Sub-Saharan Africa (excluding high income),SSA,1985,215600490241.505 -Sub-Saharan Africa (excluding high income),SSA,1986,238920584205.91 -Sub-Saharan Africa (excluding high income),SSA,1987,281539069227.019 -Sub-Saharan Africa (excluding high income),SSA,1988,296141433311.271 -Sub-Saharan Africa (excluding high income),SSA,1989,309820789988.06 -Sub-Saharan Africa (excluding high income),SSA,1990,310231626268.599 -Sub-Saharan Africa (excluding high income),SSA,1991,319737091702.347 -Sub-Saharan Africa (excluding high income),SSA,1992,314396072361.021 -Sub-Saharan Africa (excluding high income),SSA,1993,298479274571.218 -Sub-Saharan Africa (excluding high income),SSA,1994,291189045365.333 -Sub-Saharan Africa (excluding high income),SSA,1995,337004319808.346 -Sub-Saharan Africa (excluding high income),SSA,1996,348592745999.649 -Sub-Saharan Africa (excluding high income),SSA,1997,360532574706.808 -Sub-Saharan Africa (excluding high income),SSA,1998,339999446598.117 -Sub-Saharan Africa (excluding high income),SSA,1999,342611389093.949 -Sub-Saharan Africa (excluding high income),SSA,2000,367372728727.684 -Sub-Saharan Africa (excluding high income),SSA,2001,341926581367.121 -Sub-Saharan Africa (excluding high income),SSA,2002,366405040525.772 -Sub-Saharan Africa (excluding high income),SSA,2003,468282596074.19 -Sub-Saharan Africa (excluding high income),SSA,2004,582365642433.327 -Sub-Saharan Africa (excluding high income),SSA,2005,684996503798.667 -Sub-Saharan Africa (excluding high income),SSA,2006,800424661847.349 -Sub-Saharan Africa (excluding high income),SSA,2007,931379876723.897 -Sub-Saharan Africa (excluding high income),SSA,2008,1063784722921.19 -Sub-Saharan Africa (excluding high income),SSA,2009,1021413301121.37 -Sub-Saharan Africa (excluding high income),SSA,2010,1360141211429.22 -Sub-Saharan Africa (excluding high income),SSA,2011,1531532869537.52 -Sub-Saharan Africa (excluding high income),SSA,2012,1606784475519.59 -Sub-Saharan Africa (excluding high income),SSA,2013,1691556590025.3 -Sub-Saharan Africa (excluding high income),SSA,2014,1773640768624.54 -Sub-Saharan Africa (excluding high income),SSA,2015,1599676432988.51 -Sub-Saharan Africa (excluding high income),SSA,2016,1496573096431.15 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1960,30385873317.619 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1961,31561069598.0721 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1962,34208896061.8919 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1963,39225741664.7524 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1964,38271070687.0479 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1965,42640958019.1557 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1966,46032013187.6583 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1967,45494160112.4203 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1968,48659688079.8347 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1969,55788782510.798 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1970,65641311288.6349 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1971,66787674494.659 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1972,75244560743.9654 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1973,96178659252.9923 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1974,126049492057.768 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1975,138623192435.063 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1976,150523567593.48 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1977,165924142356.056 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1978,183362414567.182 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1979,220720718807.57 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1980,277168620649.297 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1981,279597299140.561 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1982,261201722615.809 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1983,243178158509.023 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1984,231534327753.875 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1985,215767871591.388 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1986,239127684060.416 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1987,281787606420.109 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1988,296425266186.195 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1989,310125765635.045 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1990,310601465373.488 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1991,320112647218.571 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1992,314832065746.688 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1993,298956393687.87 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1994,291679005862.221 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1995,337515727715.285 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1996,349098748885.709 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1997,361099250055.323 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1998,340612558536.667 -Sub-Saharan Africa (IDA & IBRD countries),TSS,1999,343239312535.324 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2000,367992054429.687 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2001,342553779838.8 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2002,367108332547.638 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2003,468992752558.158 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2004,583209894804.24 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2005,685920335014.857 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2006,801445697569.974 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2007,932416460747.498 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2008,1064752013079.22 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2009,1022260711828.75 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2010,1361111020590.47 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2011,1532598528787.88 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2012,1607918609335.78 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2013,1692968078930.83 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2014,1775063779086.99 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2015,1601114502934 -Sub-Saharan Africa (IDA & IBRD countries),TSS,2016,1498001165832.29 -Upper middle income,UMC,1960,217198647348.494 -Upper middle income,UMC,1961,198163003670.2 -Upper middle income,UMC,1962,208389042802.748 -Upper middle income,UMC,1963,218098552786.484 -Upper middle income,UMC,1964,246119837319.701 -Upper middle income,UMC,1965,274662862506.164 -Upper middle income,UMC,1966,301790005708.953 -Upper middle income,UMC,1967,306050686739.129 -Upper middle income,UMC,1968,322082966685.997 -Upper middle income,UMC,1969,360349217563.025 -Upper middle income,UMC,1970,394712327560.652 -Upper middle income,UMC,1971,432720300458.596 -Upper middle income,UMC,1972,494632159315.49 -Upper middle income,UMC,1973,642140455074.472 -Upper middle income,UMC,1974,822217878924.844 -Upper middle income,UMC,1975,906913549605.54 -Upper middle income,UMC,1976,984885444867.622 -Upper middle income,UMC,1977,1099899948045.69 -Upper middle income,UMC,1978,1175443653695.94 -Upper middle income,UMC,1979,1426467211025.1 -Upper middle income,UMC,1980,1630719856470.39 -Upper middle income,UMC,1981,1773950086597.61 -Upper middle income,UMC,1982,1749446371405.03 -Upper middle income,UMC,1983,1724517465799.49 -Upper middle income,UMC,1984,1770310443963.72 -Upper middle income,UMC,1985,1867008281184.46 -Upper middle income,UMC,1986,1949731563473.3 -Upper middle income,UMC,1987,1947828103084.37 -Upper middle income,UMC,1988,2143335758799.66 -Upper middle income,UMC,1989,2330524136589.05 -Upper middle income,UMC,1990,2668016557510.31 -Upper middle income,UMC,1991,2945883449408.78 -Upper middle income,UMC,1992,2871295456915.82 -Upper middle income,UMC,1993,3115112542376.69 -Upper middle income,UMC,1994,3394104181360.42 -Upper middle income,UMC,1995,3790108844101.48 -Upper middle income,UMC,1996,4119760606241.92 -Upper middle income,UMC,1997,4389848846126.91 -Upper middle income,UMC,1998,4336871558815.34 -Upper middle income,UMC,1999,4105143075774.15 -Upper middle income,UMC,2000,4516745939516.19 -Upper middle income,UMC,2001,4570215302631.64 -Upper middle income,UMC,2002,4585099461562.07 -Upper middle income,UMC,2003,5167508901821.26 -Upper middle income,UMC,2004,6206949763569.09 -Upper middle income,UMC,2005,7473673674144.63 -Upper middle income,UMC,2006,8886248909977.84 -Upper middle income,UMC,2007,11053091998253.6 -Upper middle income,UMC,2008,13518836281583.6 -Upper middle income,UMC,2009,13009912111056.7 -Upper middle income,UMC,2010,15772171277711.6 -Upper middle income,UMC,2011,18884745299009.3 -Upper middle income,UMC,2012,20141382977240.6 -Upper middle income,UMC,2013,21474040434046.4 -Upper middle income,UMC,2014,22200346875601.1 -Upper middle income,UMC,2015,20773804256767.4 -Upper middle income,UMC,2016,20570823016722.9 -World,WLD,1960,1366594741088.4 -World,WLD,1961,1421709987131.86 -World,WLD,1962,1526879874910.38 -World,WLD,1963,1643678995959.36 -World,WLD,1964,1800740602720.3 -World,WLD,1965,1961944483712.14 -World,WLD,1966,2128619422408.42 -World,WLD,1967,2264793675472.3 -World,WLD,1968,2443345941026.71 -World,WLD,1969,2690870797695.49 -World,WLD,1970,2956885263956.69 -World,WLD,1971,3265917075455.06 -World,WLD,1972,3766131377379.81 -World,WLD,1973,4589203445245.55 -World,WLD,1974,5292853388124.73 -World,WLD,1975,5893742092987.04 -World,WLD,1976,6412245309406.65 -World,WLD,1977,7252968306810.71 -World,WLD,1978,8537753756958.14 -World,WLD,1979,9919046089674.77 -World,WLD,1980,11166003844627.3 -World,WLD,1981,11457611762565.2 -World,WLD,1982,11355656421230.4 -World,WLD,1983,11616289845852.5 -World,WLD,1984,12058393957798 -World,WLD,1985,12681690895939.6 -World,WLD,1986,15014218229942.7 -World,WLD,1987,17083141772090.1 -World,WLD,1988,19129417553328 -World,WLD,1989,20080076891104.8 -World,WLD,1990,22579759701252.1 -World,WLD,1991,23909829105950.2 -World,WLD,1992,25389800980490.1 -World,WLD,1993,25834735037805.8 -World,WLD,1994,27740746941786.4 -World,WLD,1995,30840585358429 -World,WLD,1996,31518975357605.6 -World,WLD,1997,31403319223627.4 -World,WLD,1998,31314851252776.4 -World,WLD,1999,32486113872865.7 -World,WLD,2000,33543172517758.5 -World,WLD,2001,33335981983184.4 -World,WLD,2002,34612407886315.4 -World,WLD,2003,38867460911728.5 -World,WLD,2004,43770744134898.4 -World,WLD,2005,47385623695571.6 -World,WLD,2006,51306757202160.1 -World,WLD,2007,57793330584397.1 -World,WLD,2008,63386360623929.9 -World,WLD,2009,60086989444835.8 -World,WLD,2010,65906150734910.9 -World,WLD,2011,73241717918435.6 -World,WLD,2012,74802287628562.6 -World,WLD,2013,76924649557249.8 -World,WLD,2014,78972470867720.3 -World,WLD,2015,74606412596560.3 -World,WLD,2016,75641577475364.6 -Afghanistan,AFG,1960,537777811.111111 -Afghanistan,AFG,1961,548888895.555556 -Afghanistan,AFG,1962,546666677.777778 -Afghanistan,AFG,1963,751111191.111111 -Afghanistan,AFG,1964,800000044.444444 -Afghanistan,AFG,1965,1006666637.77778 -Afghanistan,AFG,1966,1399999966.66667 -Afghanistan,AFG,1967,1673333417.77778 -Afghanistan,AFG,1968,1373333366.66667 -Afghanistan,AFG,1969,1408888922.22222 -Afghanistan,AFG,1970,1748886595.55556 -Afghanistan,AFG,1971,1831108971.11111 -Afghanistan,AFG,1972,1595555475.55556 -Afghanistan,AFG,1973,1733333264.44444 -Afghanistan,AFG,1974,2155555497.77778 -Afghanistan,AFG,1975,2366666615.55556 -Afghanistan,AFG,1976,2555555566.66667 -Afghanistan,AFG,1977,2953333417.77778 -Afghanistan,AFG,1978,3300000108.88889 -Afghanistan,AFG,1979,3697940409.61098 -Afghanistan,AFG,1980,3641723321.99546 -Afghanistan,AFG,1981,3478787909.09091 -Afghanistan,AFG,2001,2461665937.89386 -Afghanistan,AFG,2002,4128820723.04713 -Afghanistan,AFG,2003,4583644246.48061 -Afghanistan,AFG,2004,5285465685.86423 -Afghanistan,AFG,2005,6275073571.54659 -Afghanistan,AFG,2006,7057598406.61553 -Afghanistan,AFG,2007,9843842455.48323 -Afghanistan,AFG,2008,10190529882.4878 -Afghanistan,AFG,2009,12486943505.7381 -Afghanistan,AFG,2010,15936800636.2487 -Afghanistan,AFG,2011,17930239399.8149 -Afghanistan,AFG,2012,20536542736.7297 -Afghanistan,AFG,2013,20046334303.9661 -Afghanistan,AFG,2014,20050189881.6659 -Afghanistan,AFG,2015,19702986340.5494 -Afghanistan,AFG,2016,19469022207.6357 -Albania,ALB,1984,1924242453.00793 -Albania,ALB,1985,1965384586.2409 -Albania,ALB,1986,2173750012.5 -Albania,ALB,1987,2156624900 -Albania,ALB,1988,2126000000 -Albania,ALB,1989,2335124987.5 -Albania,ALB,1990,2101624962.5 -Albania,ALB,1991,1139166645.83333 -Albania,ALB,1992,709452583.880319 -Albania,ALB,1993,1228071037.84446 -Albania,ALB,1994,1985673798.10258 -Albania,ALB,1995,2424499009.14264 -Albania,ALB,1996,3314898291.75235 -Albania,ALB,1997,2359903108.38446 -Albania,ALB,1998,2707123772.16195 -Albania,ALB,1999,3414760915.27878 -Albania,ALB,2000,3632043907.97733 -Albania,ALB,2001,4060758804.12084 -Albania,ALB,2002,4435078647.74817 -Albania,ALB,2003,5746945912.58082 -Albania,ALB,2004,7314865175.6199 -Albania,ALB,2005,8158548716.68554 -Albania,ALB,2006,8992642348.7871 -Albania,ALB,2007,10701011896.7708 -Albania,ALB,2008,12881352687.7773 -Albania,ALB,2009,12044212903.8168 -Albania,ALB,2010,11926953258.916 -Albania,ALB,2011,12890867538.5302 -Albania,ALB,2012,12319784787.2987 -Albania,ALB,2013,12781029643.5936 -Albania,ALB,2014,13219857459.1009 -Albania,ALB,2015,11390365293.8057 -Albania,ALB,2016,11926892452.8499 -Algeria,DZA,1960,2723648551.75208 -Algeria,DZA,1961,2434776645.73628 -Algeria,DZA,1962,2001468867.73344 -Algeria,DZA,1963,2703014867.32834 -Algeria,DZA,1964,2909351792.58659 -Algeria,DZA,1965,3136258896.9233 -Algeria,DZA,1966,3039834558.74906 -Algeria,DZA,1967,3370843065.76735 -Algeria,DZA,1968,3852115816.97758 -Algeria,DZA,1969,4257218772.15369 -Algeria,DZA,1970,4863487492.65763 -Algeria,DZA,1971,5077222366.97472 -Algeria,DZA,1972,6761786386.54713 -Algeria,DZA,1973,8715105930.49101 -Algeria,DZA,1974,13209713643.3219 -Algeria,DZA,1975,15557934268.4965 -Algeria,DZA,1976,17728347374.994 -Algeria,DZA,1977,20971901273.271 -Algeria,DZA,1978,26364491313.4471 -Algeria,DZA,1979,33243422157.6311 -Algeria,DZA,1980,42345277342.0195 -Algeria,DZA,1981,44348672667.8715 -Algeria,DZA,1982,45207088715.6483 -Algeria,DZA,1983,48801369800.3675 -Algeria,DZA,1984,53698278905.9678 -Algeria,DZA,1985,57937868670.1937 -Algeria,DZA,1986,63696301892.8116 -Algeria,DZA,1987,66742267773.1959 -Algeria,DZA,1988,59089067187.3943 -Algeria,DZA,1989,55631489801.5508 -Algeria,DZA,1990,62045099642.7774 -Algeria,DZA,1991,45715367087.1001 -Algeria,DZA,1992,48003298223.1178 -Algeria,DZA,1993,49946455210.966 -Algeria,DZA,1994,42542571305.5136 -Algeria,DZA,1995,41764052457.8814 -Algeria,DZA,1996,46941496779.8499 -Algeria,DZA,1997,48177862501.9495 -Algeria,DZA,1998,48187747528.899 -Algeria,DZA,1999,48640574566.6476 -Algeria,DZA,2000,54790245600.5846 -Algeria,DZA,2001,54744714396.1666 -Algeria,DZA,2002,56760288973.6703 -Algeria,DZA,2003,67863829880.4832 -Algeria,DZA,2004,85324998813.604 -Algeria,DZA,2005,103198228458.588 -Algeria,DZA,2006,117027304746.54 -Algeria,DZA,2007,134977087734.008 -Algeria,DZA,2008,171000691877.714 -Algeria,DZA,2009,137211039898.193 -Algeria,DZA,2010,161207268655.392 -Algeria,DZA,2011,200013051408.116 -Algeria,DZA,2012,209047389309.482 -Algeria,DZA,2013,209783503258.224 -Algeria,DZA,2014,213983107815.932 -Algeria,DZA,2015,164779467703.299 -Algeria,DZA,2016,156079606663.188 -American Samoa,ASM,2002,514000000 -American Samoa,ASM,2003,527000000 -American Samoa,ASM,2004,512000000 -American Samoa,ASM,2005,503000000 -American Samoa,ASM,2006,496000000 -American Samoa,ASM,2007,520000000 -American Samoa,ASM,2008,563000000 -American Samoa,ASM,2009,678000000 -American Samoa,ASM,2010,576000000 -American Samoa,ASM,2011,574000000 -American Samoa,ASM,2012,644000000 -American Samoa,ASM,2013,639000000 -American Samoa,ASM,2014,638000000 -American Samoa,ASM,2015,641000000 -Andorra,AND,1970,78619206.0850963 -Andorra,AND,1971,89409820.3592814 -Andorra,AND,1972,113408231.944085 -Andorra,AND,1973,150820102.798401 -Andorra,AND,1974,186558696.279204 -Andorra,AND,1975,220127246.376812 -Andorra,AND,1976,227281024.620741 -Andorra,AND,1977,254020153.340635 -Andorra,AND,1978,308008897.569444 -Andorra,AND,1979,411578334.159643 -Andorra,AND,1980,446416105.825017 -Andorra,AND,1981,388958731.302938 -Andorra,AND,1982,375895956.383462 -Andorra,AND,1983,327861832.946636 -Andorra,AND,1984,330070689.298282 -Andorra,AND,1985,346737964.774951 -Andorra,AND,1986,482000594.03588 -Andorra,AND,1987,611316399.407088 -Andorra,AND,1988,721425939.15155 -Andorra,AND,1989,795449332.396346 -Andorra,AND,1990,1029048481.88051 -Andorra,AND,1991,1106928582.86629 -Andorra,AND,1992,1210013651.87713 -Andorra,AND,1993,1007025755.00065 -Andorra,AND,1994,1017549124.33238 -Andorra,AND,1995,1178738991.19295 -Andorra,AND,1996,1223945356.62682 -Andorra,AND,1997,1180597272.72727 -Andorra,AND,1998,1211932397.81713 -Andorra,AND,1999,1239876305.13531 -Andorra,AND,2000,1401695227.56587 -Andorra,AND,2001,1484017897.09172 -Andorra,AND,2002,1717485413.13759 -Andorra,AND,2003,2373927765.23702 -Andorra,AND,2004,2916786689.84356 -Andorra,AND,2005,3248215396.09501 -Andorra,AND,2006,3536632793.87781 -Andorra,AND,2007,4010990966.32904 -Andorra,AND,2008,4001201113.22689 -Andorra,AND,2009,3650083356.48791 -Andorra,AND,2010,3346516556.29139 -Andorra,AND,2011,3427022518.76564 -Andorra,AND,2012,3146151869.45908 -Andorra,AND,2013,3248924588.42273 -Angola,AGO,1985,6684491978.60963 -Angola,AGO,1986,6684491978.60963 -Angola,AGO,1987,6684491978.60963 -Angola,AGO,1988,6684491978.60963 -Angola,AGO,1989,10026737967.9144 -Angola,AGO,1990,10026737967.9144 -Angola,AGO,1991,12118610904.2251 -Angola,AGO,1992,5684291718.77106 -Angola,AGO,1993,5278182970.79618 -Angola,AGO,1994,4059352153.05368 -Angola,AGO,1995,5039552482.42778 -Angola,AGO,1996,7526446605.51712 -Angola,AGO,1997,7648377412.83277 -Angola,AGO,1998,6445041824.66621 -Angola,AGO,1999,6152922942.98032 -Angola,AGO,2000,9129594818.60749 -Angola,AGO,2001,8936063723.20121 -Angola,AGO,2002,12497346669.6684 -Angola,AGO,2003,14188949190.618 -Angola,AGO,2004,19640848728.8937 -Angola,AGO,2005,28233712830.9035 -Angola,AGO,2006,41789478661.3096 -Angola,AGO,2007,60448921272.2326 -Angola,AGO,2008,84178032716.0971 -Angola,AGO,2009,75492384801.3695 -Angola,AGO,2010,82470913120.7314 -Angola,AGO,2011,104115923082.737 -Angola,AGO,2012,115398371427.673 -Angola,AGO,2013,124912063308.202 -Angola,AGO,2014,126776874216.703 -Angola,AGO,2015,102962245246.708 -Angola,AGO,2016,89633156470.3104 -Antigua and Barbuda,ATG,1977,77496740.7407407 -Antigua and Barbuda,ATG,1978,87879333.3333333 -Antigua and Barbuda,ATG,1979,109079962.962963 -Antigua and Barbuda,ATG,1980,131431037.037037 -Antigua and Barbuda,ATG,1981,147841740.740741 -Antigua and Barbuda,ATG,1982,164369296.296296 -Antigua and Barbuda,ATG,1983,182144111.111111 -Antigua and Barbuda,ATG,1984,208372851.851852 -Antigua and Barbuda,ATG,1985,240923925.925926 -Antigua and Barbuda,ATG,1986,290440148.148148 -Antigua and Barbuda,ATG,1987,337174851.851852 -Antigua and Barbuda,ATG,1988,398637740.740741 -Antigua and Barbuda,ATG,1989,438794777.777778 -Antigua and Barbuda,ATG,1990,459469074.074074 -Antigua and Barbuda,ATG,1991,481706333.333333 -Antigua and Barbuda,ATG,1992,499281148.148148 -Antigua and Barbuda,ATG,1993,535172777.777778 -Antigua and Barbuda,ATG,1994,589429592.592593 -Antigua and Barbuda,ATG,1995,577280740.740741 -Antigua and Barbuda,ATG,1996,633730629.62963 -Antigua and Barbuda,ATG,1997,680617111.111111 -Antigua and Barbuda,ATG,1998,727860592.592593 -Antigua and Barbuda,ATG,1999,766198925.925926 -Antigua and Barbuda,ATG,2000,825405518.518518 -Antigua and Barbuda,ATG,2001,795976518.518518 -Antigua and Barbuda,ATG,2002,809754481.481482 -Antigua and Barbuda,ATG,2003,850218592.592592 -Antigua and Barbuda,ATG,2004,913710370.37037 -Antigua and Barbuda,ATG,2005,1014979666.66667 -Antigua and Barbuda,ATG,2006,1149025481.48148 -Antigua and Barbuda,ATG,2007,1302388925.92593 -Antigua and Barbuda,ATG,2008,1359733555.55556 -Antigua and Barbuda,ATG,2009,1217719666.66667 -Antigua and Barbuda,ATG,2010,1147942222.22222 -Antigua and Barbuda,ATG,2011,1141865444.44444 -Antigua and Barbuda,ATG,2012,1216045777.77778 -Antigua and Barbuda,ATG,2013,1195885111.11111 -Antigua and Barbuda,ATG,2014,1274330333.33333 -Antigua and Barbuda,ATG,2015,1355645888.88889 -Antigua and Barbuda,ATG,2016,1449160185.18519 -Argentina,ARG,1962,24450604877.6081 -Argentina,ARG,1963,18272123664.4715 -Argentina,ARG,1964,25605249381.7597 -Argentina,ARG,1965,28344705966.6389 -Argentina,ARG,1966,28630474727.9023 -Argentina,ARG,1967,24256667553.2569 -Argentina,ARG,1968,26436857247.4982 -Argentina,ARG,1969,31256284543.6155 -Argentina,ARG,1970,31584210365.5447 -Argentina,ARG,1971,33293199095.4881 -Argentina,ARG,1972,34733000536.2862 -Argentina,ARG,1973,52544000116.9037 -Argentina,ARG,1974,72436777342.4554 -Argentina,ARG,1975,52438647921.9226 -Argentina,ARG,1976,51169499890.7722 -Argentina,ARG,1977,56781000100.9448 -Argentina,ARG,1978,58082870156.2634 -Argentina,ARG,1979,69252328953.3789 -Argentina,ARG,1980,76961923741.9478 -Argentina,ARG,1981,78676842366.4213 -Argentina,ARG,1982,84307486836.724 -Argentina,ARG,1983,103979106777.911 -Argentina,ARG,1984,79092001998.032 -Argentina,ARG,1985,88416668900.2596 -Argentina,ARG,1986,110934442762.694 -Argentina,ARG,1987,111106191358.197 -Argentina,ARG,1988,126206817196.091 -Argentina,ARG,1989,76636898036.4712 -Argentina,ARG,1990,141352368714.691 -Argentina,ARG,1991,189719984268.485 -Argentina,ARG,1992,228788617201.696 -Argentina,ARG,1993,236741715015.015 -Argentina,ARG,1994,257440000000 -Argentina,ARG,1995,258031750000 -Argentina,ARG,1996,272149750000 -Argentina,ARG,1997,292859000000 -Argentina,ARG,1998,298948250000 -Argentina,ARG,1999,283523000000 -Argentina,ARG,2000,284203750000 -Argentina,ARG,2001,268696750000 -Argentina,ARG,2002,97724004251.8602 -Argentina,ARG,2003,127586973492.177 -Argentina,ARG,2004,164657930452.787 -Argentina,ARG,2005,198737095012.282 -Argentina,ARG,2006,232557260817.308 -Argentina,ARG,2007,287530508430.568 -Argentina,ARG,2008,361558037110.419 -Argentina,ARG,2009,332976484577.619 -Argentina,ARG,2010,423627422092.49 -Argentina,ARG,2011,530163281574.658 -Argentina,ARG,2012,545982375701.128 -Argentina,ARG,2013,552025140252.246 -Argentina,ARG,2014,526319673731.638 -Argentina,ARG,2015,584711485367.267 -Argentina,ARG,2016,545866164478.053 -Armenia,ARM,1990,2256838858.42714 -Armenia,ARM,1991,2068526521.90299 -Armenia,ARM,1992,1272577521.7683 -Armenia,ARM,1993,1201313196.45626 -Armenia,ARM,1994,1315158670.47971 -Armenia,ARM,1995,1468317350.02343 -Armenia,ARM,1996,1596968913.19202 -Armenia,ARM,1997,1639492424.38103 -Armenia,ARM,1998,1893726437.35976 -Armenia,ARM,1999,1845482181.48539 -Armenia,ARM,2000,1911563665.39006 -Armenia,ARM,2001,2118467913.37873 -Armenia,ARM,2002,2376335048.39976 -Armenia,ARM,2003,2807061008.69084 -Armenia,ARM,2004,3576615240.41616 -Armenia,ARM,2005,4900469515.07252 -Armenia,ARM,2006,6384451606.1421 -Armenia,ARM,2007,9206301700.39619 -Armenia,ARM,2008,11662040713.8753 -Armenia,ARM,2009,8647936747.98704 -Armenia,ARM,2010,9260284937.79782 -Armenia,ARM,2011,10142111334.4961 -Armenia,ARM,2012,10619320048.5857 -Armenia,ARM,2013,11121465767.4067 -Armenia,ARM,2014,11609512939.7543 -Armenia,ARM,2015,10529182498.3475 -Armenia,ARM,2016,10547331235.1895 -Aruba,ABW,1994,1330167597.76536 -Aruba,ABW,1995,1320670391.06145 -Aruba,ABW,1996,1379888268.15642 -Aruba,ABW,1997,1531843575.41899 -Aruba,ABW,1998,1665363128.49162 -Aruba,ABW,1999,1722798882.68156 -Aruba,ABW,2000,1873452513.96648 -Aruba,ABW,2001,1920262569.8324 -Aruba,ABW,2002,1941094972.06704 -Aruba,ABW,2003,2021301675.97765 -Aruba,ABW,2004,2228279329.60894 -Aruba,ABW,2005,2331005586.59218 -Aruba,ABW,2006,2421474860.3352 -Aruba,ABW,2007,2623726256.98324 -Aruba,ABW,2008,2791960893.85475 -Aruba,ABW,2009,2498932960.89385 -Aruba,ABW,2010,2467703910.61453 -Aruba,ABW,2011,2584463687.15084 -Australia,AUS,1960,18593347519.3191 -Australia,AUS,1961,19666256019.7111 -Australia,AUS,1962,19911524246.8362 -Australia,AUS,1963,21527606674.8796 -Australia,AUS,1964,23787658192.4068 -Australia,AUS,1965,25962593795.4978 -Australia,AUS,1966,27288610146.713 -Australia,AUS,1967,30421099787.2102 -Australia,AUS,1968,32687870982.1929 -Australia,AUS,1969,36659200358.3828 -Australia,AUS,1970,41304737372.6061 -Australia,AUS,1971,45183111210.6619 -Australia,AUS,1972,52003504672.8972 -Australia,AUS,1973,63782190903.2671 -Australia,AUS,1974,88906411201.1791 -Australia,AUS,1975,97226546497.3372 -Australia,AUS,1976,104974158578.092 -Australia,AUS,1977,110266116081.67 -Australia,AUS,1978,118400631626.438 -Australia,AUS,1979,134793820288.538 -Australia,AUS,1980,149887465181.059 -Australia,AUS,1981,176804829908.278 -Australia,AUS,1982,193954540439.148 -Australia,AUS,1983,177176415535.798 -Australia,AUS,1984,193503894222.061 -Australia,AUS,1985,180470967247.066 -Australia,AUS,1986,182281757134.863 -Australia,AUS,1987,189375992588.671 -Australia,AUS,1988,236135768335.274 -Australia,AUS,1989,299941372852.374 -Australia,AUS,1990,311425933051.174 -Australia,AUS,1991,326068597441.331 -Australia,AUS,1992,325692532492.502 -Australia,AUS,1993,312372821810.006 -Australia,AUS,1994,323216879972.328 -Australia,AUS,1995,368391743391.743 -Australia,AUS,1996,401819423368.74 -Australia,AUS,1997,436097980904.68 -Australia,AUS,1998,399778878111.646 -Australia,AUS,1999,389146509587.668 -Australia,AUS,2000,415446209885.072 -Australia,AUS,2001,378899860470.108 -Australia,AUS,2002,394635830891.586 -Australia,AUS,2003,466853232382.062 -Australia,AUS,2004,613329776639.636 -Australia,AUS,2005,693764095624.718 -Australia,AUS,2006,747572626534.891 -Australia,AUS,2007,853764622752.61 -Australia,AUS,2008,1055334825425.25 -Australia,AUS,2009,927168310999.853 -Australia,AUS,2010,1142876772659.21 -Australia,AUS,2011,1390557034407.97 -Australia,AUS,2012,1538194473087.23 -Australia,AUS,2013,1567178619062.28 -Australia,AUS,2014,1459597906912.7 -Australia,AUS,2015,1345383143356.35 -Australia,AUS,2016,1204616439828.41 -Austria,AUT,1960,6592693841.18495 -Austria,AUT,1961,7311749633.36229 -Austria,AUT,1962,7756110210.11966 -Austria,AUT,1963,8374175257.73075 -Austria,AUT,1964,9169983885.71185 -Austria,AUT,1965,9994070615.85997 -Austria,AUT,1966,10887682273.1014 -Austria,AUT,1967,11579431668.9165 -Austria,AUT,1968,12440625312.8685 -Austria,AUT,1969,13582798556.2404 -Austria,AUT,1970,15335972267.7957 -Austria,AUT,1971,17815464919.0439 -Austria,AUT,1972,22006470861.3608 -Austria,AUT,1973,29444365310.2818 -Austria,AUT,1974,35104529078.3274 -Austria,AUT,1975,39962704274.3146 -Austria,AUT,1976,42856485617.8569 -Austria,AUT,1977,51421585629.8393 -Austria,AUT,1978,61902774945.5131 -Austria,AUT,1979,73759181883.685 -Austria,AUT,1980,81861232822.8037 -Austria,AUT,1981,70863106877.484 -Austria,AUT,1982,71103585383.5605 -Austria,AUT,1983,71947277233.032 -Austria,AUT,1984,67821568599.1335 -Austria,AUT,1985,69219621907.4222 -Austria,AUT,1986,98797587381.7035 -Austria,AUT,1987,123869321397.475 -Austria,AUT,1988,133018182770.534 -Austria,AUT,1989,132785154342.174 -Austria,AUT,1990,166062376739.683 -Austria,AUT,1991,173375508073.07 -Austria,AUT,1992,194608183696.469 -Austria,AUT,1993,189921096652.076 -Austria,AUT,1994,203044926876.28 -Austria,AUT,1995,240457622492.152 -Austria,AUT,1996,236720496490.772 -Austria,AUT,1997,212323463750.141 -Austria,AUT,1998,217683626056.025 -Austria,AUT,1999,216725261027.062 -Austria,AUT,2000,196421706283.398 -Austria,AUT,2001,196953628635.347 -Austria,AUT,2002,212970685111.989 -Austria,AUT,2003,260721478555.305 -Austria,AUT,2004,299857238639.185 -Austria,AUT,2005,314648986444.472 -Austria,AUT,2006,334309371471.584 -Austria,AUT,2007,386458951546.674 -Austria,AUT,2008,427611527757.434 -Austria,AUT,2009,397594276187.83 -Austria,AUT,2010,390211866490.257 -Austria,AUT,2011,429037361514.409 -Austria,AUT,2012,407451583084.239 -Austria,AUT,2013,428248420485.175 -Austria,AUT,2014,438376178526.317 -Austria,AUT,2015,376967406147.987 -Austria,AUT,2016,386427793787.215 -Azerbaijan,AZE,1990,8858006035.91566 -Azerbaijan,AZE,1991,8792365810.5094 -Azerbaijan,AZE,1992,4991350457.5425 -Azerbaijan,AZE,1993,3973027396.65195 -Azerbaijan,AZE,1994,3313739673.54738 -Azerbaijan,AZE,1995,3052467522.36104 -Azerbaijan,AZE,1996,3176749593.11788 -Azerbaijan,AZE,1997,3962710163.11167 -Azerbaijan,AZE,1998,4446396217.63265 -Azerbaijan,AZE,1999,4581222442.45783 -Azerbaijan,AZE,2000,5272617196.04517 -Azerbaijan,AZE,2001,5707720390.8515 -Azerbaijan,AZE,2002,6235795103.88809 -Azerbaijan,AZE,2003,7276013031.96905 -Azerbaijan,AZE,2004,8680472168.51531 -Azerbaijan,AZE,2005,13245716099.0057 -Azerbaijan,AZE,2006,20983019923.8863 -Azerbaijan,AZE,2007,33050343782.7759 -Azerbaijan,AZE,2008,48852482960.0779 -Azerbaijan,AZE,2009,44291490420.5026 -Azerbaijan,AZE,2010,52902703376.1056 -Azerbaijan,AZE,2011,65951627200.2026 -Azerbaijan,AZE,2012,69684317718.9409 -Azerbaijan,AZE,2013,74164435946.4627 -Azerbaijan,AZE,2014,75244166772.9185 -Azerbaijan,AZE,2015,53074370486.0433 -Azerbaijan,AZE,2016,37847715736.0406 -"Bahamas, The",BHS,1960,169803921.568627 -"Bahamas, The",BHS,1961,190098039.215686 -"Bahamas, The",BHS,1962,212254901.960784 -"Bahamas, The",BHS,1963,237745098.039216 -"Bahamas, The",BHS,1964,266666666.666667 -"Bahamas, The",BHS,1965,300392156.862745 -"Bahamas, The",BHS,1966,340000000 -"Bahamas, The",BHS,1967,390196078.431373 -"Bahamas, The",BHS,1968,444901960.784314 -"Bahamas, The",BHS,1969,528137254.901961 -"Bahamas, The",BHS,1970,538423153.692615 -"Bahamas, The",BHS,1971,573400000 -"Bahamas, The",BHS,1972,590900000 -"Bahamas, The",BHS,1973,670900000 -"Bahamas, The",BHS,1974,632400000 -"Bahamas, The",BHS,1975,596200000 -"Bahamas, The",BHS,1976,642100000 -"Bahamas, The",BHS,1977,713000000 -"Bahamas, The",BHS,1978,832400000 -"Bahamas, The",BHS,1979,1139800100 -"Bahamas, The",BHS,1980,1335300000 -"Bahamas, The",BHS,1981,1426500000 -"Bahamas, The",BHS,1982,1578300000 -"Bahamas, The",BHS,1983,1732800000 -"Bahamas, The",BHS,1984,2041100000 -"Bahamas, The",BHS,1985,2320699900 -"Bahamas, The",BHS,1986,2472500000 -"Bahamas, The",BHS,1987,2713999900 -"Bahamas, The",BHS,1988,2817900000 -"Bahamas, The",BHS,1989,3062000000 -"Bahamas, The",BHS,1990,3166000000 -"Bahamas, The",BHS,1991,3111160000 -"Bahamas, The",BHS,1992,3109000000 -"Bahamas, The",BHS,1993,3092000000 -"Bahamas, The",BHS,1994,3259000000 -"Bahamas, The",BHS,1995,3429000000 -"Bahamas, The",BHS,1996,3609000000 -"Bahamas, The",BHS,1997,4961119000 -"Bahamas, The",BHS,1998,5353524000 -"Bahamas, The",BHS,1999,6019972000 -"Bahamas, The",BHS,2000,6327552000 -"Bahamas, The",BHS,2001,6516651000 -"Bahamas, The",BHS,2002,6957996000 -"Bahamas, The",BHS,2003,6949317000 -"Bahamas, The",BHS,2004,7094413000 -"Bahamas, The",BHS,2005,7706222000 -"Bahamas, The",BHS,2006,7965588000 -"Bahamas, The",BHS,2007,8318996000 -"Bahamas, The",BHS,2008,8247000000 -"Bahamas, The",BHS,2009,7820000000 -"Bahamas, The",BHS,2010,7910000000 -"Bahamas, The",BHS,2011,7890000000 -"Bahamas, The",BHS,2012,8399000000 -"Bahamas, The",BHS,2013,8522000000 -"Bahamas, The",BHS,2014,8618000000 -"Bahamas, The",BHS,2015,8854000000 -"Bahamas, The",BHS,2016,9047000000 -Bahrain,BHR,1980,3072698328.46909 -Bahrain,BHR,1981,3467819148.93617 -Bahrain,BHR,1982,3645744680.85106 -Bahrain,BHR,1983,3735106382.97872 -Bahrain,BHR,1984,3905585106.38298 -Bahrain,BHR,1985,3651861702.12766 -Bahrain,BHR,1986,3052393617.02128 -Bahrain,BHR,1987,3392021010.6383 -Bahrain,BHR,1988,3702393617.02128 -Bahrain,BHR,1989,3863563829.78723 -Bahrain,BHR,1990,4229787234.04255 -Bahrain,BHR,1991,4616223404.25532 -Bahrain,BHR,1992,4751063829.78723 -Bahrain,BHR,1993,5200265957.44681 -Bahrain,BHR,1994,5567553457.44681 -Bahrain,BHR,1995,5849467819.14894 -Bahrain,BHR,1996,6101861436.17021 -Bahrain,BHR,1997,6349202393.61702 -Bahrain,BHR,1998,6183776595.74468 -Bahrain,BHR,1999,6621010372.34043 -Bahrain,BHR,2000,9062906914.89362 -Bahrain,BHR,2001,8976207712.76596 -Bahrain,BHR,2002,9632155053.19149 -Bahrain,BHR,2003,11074822074.4681 -Bahrain,BHR,2004,13150166755.3191 -Bahrain,BHR,2005,15968726861.7021 -Bahrain,BHR,2006,18505053191.4894 -Bahrain,BHR,2007,21730000000 -Bahrain,BHR,2008,25710877659.5745 -Bahrain,BHR,2009,22938218085.1064 -Bahrain,BHR,2010,25713271276.5957 -Bahrain,BHR,2011,29157446808.5106 -Bahrain,BHR,2012,30749308510.6383 -Bahrain,BHR,2013,32898670212.766 -Bahrain,BHR,2014,33387712765.9575 -Bahrain,BHR,2015,31125851063.8298 -Bahrain,BHR,2016,31858510638.2979 -Bangladesh,BGD,1960,4274893913.46432 -Bangladesh,BGD,1961,4817580183.56657 -Bangladesh,BGD,1962,5081413339.74945 -Bangladesh,BGD,1963,5319458351.12372 -Bangladesh,BGD,1964,5386054619.31076 -Bangladesh,BGD,1965,5906636556.95802 -Bangladesh,BGD,1966,6439687598.27648 -Bangladesh,BGD,1967,7253575399.26882 -Bangladesh,BGD,1968,7483685473.4584 -Bangladesh,BGD,1969,8471006100.89247 -Bangladesh,BGD,1970,8992721809.32801 -Bangladesh,BGD,1971,8751842839.73302 -Bangladesh,BGD,1972,6288245866.66667 -Bangladesh,BGD,1973,8086725729.3407 -Bangladesh,BGD,1974,12512460519.7088 -Bangladesh,BGD,1975,19448348073.4565 -Bangladesh,BGD,1976,10117113333.3333 -Bangladesh,BGD,1977,9651149301.8746 -Bangladesh,BGD,1978,13281767142.8571 -Bangladesh,BGD,1979,15565480321.9448 -Bangladesh,BGD,1980,18138049095.6072 -Bangladesh,BGD,1981,20249694002.448 -Bangladesh,BGD,1982,18525399201.5968 -Bangladesh,BGD,1983,17609048821.5488 -Bangladesh,BGD,1984,18920840000 -Bangladesh,BGD,1985,22278423076.9231 -Bangladesh,BGD,1986,21774033333.3333 -Bangladesh,BGD,1987,24298032258.0645 -Bangladesh,BGD,1988,26579005760.315 -Bangladesh,BGD,1989,28781714763.7823 -Bangladesh,BGD,1990,31598341233.5793 -Bangladesh,BGD,1991,30957483290.541 -Bangladesh,BGD,1992,31708873954.9405 -Bangladesh,BGD,1993,33166520084.8295 -Bangladesh,BGD,1994,33768662171.2233 -Bangladesh,BGD,1995,37939748051.3878 -Bangladesh,BGD,1996,46438482370.3942 -Bangladesh,BGD,1997,48244308274.8086 -Bangladesh,BGD,1998,49984559471.3656 -Bangladesh,BGD,1999,51270569883.5275 -Bangladesh,BGD,2000,53369787318.6245 -Bangladesh,BGD,2001,53991289844.3291 -Bangladesh,BGD,2002,54724081490.5102 -Bangladesh,BGD,2003,60158929188.2556 -Bangladesh,BGD,2004,65108544250.0425 -Bangladesh,BGD,2005,69442943089.4309 -Bangladesh,BGD,2006,71819083683.7403 -Bangladesh,BGD,2007,79611888213.148 -Bangladesh,BGD,2008,91631278239.3237 -Bangladesh,BGD,2009,102477791472.39 -Bangladesh,BGD,2010,115279077465.226 -Bangladesh,BGD,2011,128637938711.386 -Bangladesh,BGD,2012,133355749482.478 -Bangladesh,BGD,2013,149990451022.29 -Bangladesh,BGD,2014,172885454931.453 -Bangladesh,BGD,2015,195078561219.325 -Bangladesh,BGD,2016,221415280325.518 -Barbados,BRB,1980,1012264035.93834 -Barbados,BRB,1981,1114104641.92324 -Barbados,BRB,1982,1164059789.75045 -Barbados,BRB,1983,1235775210.81961 -Barbados,BRB,1984,1347033586.80082 -Barbados,BRB,1985,1409740726.1551 -Barbados,BRB,1986,1547790025.47984 -Barbados,BRB,1987,1704440882.93392 -Barbados,BRB,1988,1812891396.47311 -Barbados,BRB,1989,2006394477.47387 -Barbados,BRB,1990,2012302519.52124 -Barbados,BRB,1991,2020744653.61842 -Barbados,BRB,1992,1957168343.54374 -Barbados,BRB,1993,2063267995.73752 -Barbados,BRB,1994,2151285060.49141 -Barbados,BRB,1995,2261996995.18515 -Barbados,BRB,1996,2411846465.43502 -Barbados,BRB,1997,2549260575.07039 -Barbados,BRB,1998,2874413287.26735 -Barbados,BRB,1999,3012021852.2502 -Barbados,BRB,2000,3121619807.97687 -Barbados,BRB,2001,3116632412.98352 -Barbados,BRB,2002,3169612598.33334 -Barbados,BRB,2003,3274856571.16604 -Barbados,BRB,2004,3514370691.25563 -Barbados,BRB,2005,3897467233.85757 -Barbados,BRB,2006,4303275572.40197 -Barbados,BRB,2007,4546115388.40716 -Barbados,BRB,2008,4595264650 -Barbados,BRB,2009,4601250000 -Barbados,BRB,2010,4446800000 -Barbados,BRB,2011,4358900000 -Barbados,BRB,2012,4332150000 -Barbados,BRB,2013,4371200000 -Barbados,BRB,2014,4352700000 -Barbados,BRB,2015,4421800000 -Barbados,BRB,2016,4587550000 -Belarus,BLR,1990,21650000000 -Belarus,BLR,1991,17420000000 -Belarus,BLR,1992,17120370370.3704 -Belarus,BLR,1993,16286280991.7355 -Belarus,BLR,1994,14932192010.7419 -Belarus,BLR,1995,13972630803.5817 -Belarus,BLR,1996,14756861538.4615 -Belarus,BLR,1997,14128412417.193 -Belarus,BLR,1998,15222014828.3039 -Belarus,BLR,1999,12138485328.6267 -Belarus,BLR,2000,12736856827.9847 -Belarus,BLR,2001,12354820143.8849 -Belarus,BLR,2002,14594925392.9691 -Belarus,BLR,2003,17825436034.5366 -Belarus,BLR,2004,23141587717.7633 -Belarus,BLR,2005,30210091836.8294 -Belarus,BLR,2006,36961821893.6976 -Belarus,BLR,2007,45275747860.6442 -Belarus,BLR,2008,60752177438.8895 -Belarus,BLR,2009,49208656976.0389 -Belarus,BLR,2010,57231904542.8755 -Belarus,BLR,2011,61762341356.8996 -Belarus,BLR,2012,65685903833.0838 -Belarus,BLR,2013,75527537703.1836 -Belarus,BLR,2014,78813049849.6078 -Belarus,BLR,2015,56454775870.958 -Belarus,BLR,2016,47433442293.1858 -Belgium,BEL,1960,11658722590.99 -Belgium,BEL,1961,12400145221.595 -Belgium,BEL,1962,13264015675.3193 -Belgium,BEL,1963,14260017387.0492 -Belgium,BEL,1964,15960106680.6732 -Belgium,BEL,1965,17371457607.9374 -Belgium,BEL,1966,18651883472.4808 -Belgium,BEL,1967,19992040788.4593 -Belgium,BEL,1968,21376353113.475 -Belgium,BEL,1969,23710735894.7022 -Belgium,BEL,1970,26849173618.3945 -Belgium,BEL,1971,29981318394.8688 -Belgium,BEL,1972,37408626615.3423 -Belgium,BEL,1973,47999408507.5554 -Belgium,BEL,1974,56333063690.9693 -Belgium,BEL,1975,66029811341.45 -Belgium,BEL,1976,71494607105.5381 -Belgium,BEL,1977,83283407090.6021 -Belgium,BEL,1978,101788571282.183 -Belgium,BEL,1979,116938177352.779 -Belgium,BEL,1980,127508322941.095 -Belgium,BEL,1981,105290713602.781 -Belgium,BEL,1982,92588982518.0999 -Belgium,BEL,1983,87650998816.568 -Belgium,BEL,1984,83795759983.2449 -Belgium,BEL,1985,86730120728.3103 -Belgium,BEL,1986,120661334386.852 -Belgium,BEL,1987,150194219665.046 -Belgium,BEL,1988,163168007789.358 -Belgium,BEL,1989,165100250614.251 -Belgium,BEL,1990,206431036697.248 -Belgium,BEL,1991,211638016538.689 -Belgium,BEL,1992,236038607528.231 -Belgium,BEL,1993,225924893540.112 -Belgium,BEL,1994,246195171328.671 -Belgium,BEL,1995,289567597153.804 -Belgium,BEL,1996,281357654723.127 -Belgium,BEL,1997,254813937753.721 -Belgium,BEL,1998,260602356079.129 -Belgium,BEL,1999,260202429149.798 -Belgium,BEL,2000,237904919845.218 -Belgium,BEL,2001,237841610738.255 -Belgium,BEL,2002,258860342555.995 -Belgium,BEL,2003,319003386004.515 -Belgium,BEL,2004,370885274397.815 -Belgium,BEL,2005,387365999253.824 -Belgium,BEL,2006,409813072387.404 -Belgium,BEL,2007,471821790309.335 -Belgium,BEL,2008,518626043650.212 -Belgium,BEL,2009,484552653514.865 -Belgium,BEL,2010,483548693409.337 -Belgium,BEL,2011,527008036846.811 -Belgium,BEL,2012,497884088082.651 -Belgium,BEL,2013,520117140495.059 -Belgium,BEL,2014,531750903174.686 -Belgium,BEL,2015,454991318727.907 -Belgium,BEL,2016,466365727353.85 -Belize,BLZ,1960,28071888.5622288 -Belize,BLZ,1961,29964370.7125857 -Belize,BLZ,1962,31856922.8615428 -Belize,BLZ,1963,33749405.0118998 -Belize,BLZ,1964,36193826.1234775 -Belize,BLZ,1965,40069930.0699301 -Belize,BLZ,1966,44405594.4055944 -Belize,BLZ,1967,47379310.3448276 -Belize,BLZ,1968,44910179.6407186 -Belize,BLZ,1969,47305389.2215569 -Belize,BLZ,1970,53233532.9341317 -Belize,BLZ,1971,59207317.0731707 -Belize,BLZ,1972,66062500 -Belize,BLZ,1973,78343558.2822086 -Belize,BLZ,1974,103216374.269006 -Belize,BLZ,1975,118066298.342541 -Belize,BLZ,1976,96905829.5964126 -Belize,BLZ,1977,117650000 -Belize,BLZ,1978,136300000 -Belize,BLZ,1979,151800000 -Belize,BLZ,1980,194750000 -Belize,BLZ,1981,192900000 -Belize,BLZ,1982,179250000 -Belize,BLZ,1983,189000000 -Belize,BLZ,1984,210900000 -Belize,BLZ,1985,209150000 -Belize,BLZ,1986,227850000 -Belize,BLZ,1987,276550000 -Belize,BLZ,1988,314900000 -Belize,BLZ,1989,363150000 -Belize,BLZ,1990,413050000 -Belize,BLZ,1991,444720750 -Belize,BLZ,1992,518239100 -Belize,BLZ,1993,559858250 -Belize,BLZ,1994,580863700 -Belize,BLZ,1995,620140400 -Belize,BLZ,1996,641383800 -Belize,BLZ,1997,654314350 -Belize,BLZ,1998,688992450 -Belize,BLZ,1999,732732350 -Belize,BLZ,2000,832072450 -Belize,BLZ,2001,871860600 -Belize,BLZ,2002,932551850 -Belize,BLZ,2003,990374050 -Belize,BLZ,2004,1057845500 -Belize,BLZ,2005,1114222550 -Belize,BLZ,2006,1217467600 -Belize,BLZ,2007,1290573400 -Belize,BLZ,2008,1368625150 -Belize,BLZ,2009,1336957250 -Belize,BLZ,2010,1397113450 -Belize,BLZ,2011,1486712300 -Belize,BLZ,2012,1573618750 -Belize,BLZ,2013,1613705850 -Belize,BLZ,2014,1706497950 -Belize,BLZ,2015,1742545900 -Belize,BLZ,2016,1765256400 -Benin,BEN,1960,226195579.35701 -Benin,BEN,1961,235668222.429984 -Benin,BEN,1962,236434906.75427 -Benin,BEN,1963,253927646.475909 -Benin,BEN,1964,269818988.259263 -Benin,BEN,1965,289908720.648622 -Benin,BEN,1966,302925280.773564 -Benin,BEN,1967,306222000.407316 -Benin,BEN,1968,326323097.355964 -Benin,BEN,1969,330748211.459737 -Benin,BEN,1970,333627758.154666 -Benin,BEN,1971,335072975.215766 -Benin,BEN,1972,410331900.950531 -Benin,BEN,1973,504376035.716401 -Benin,BEN,1974,554654786.965107 -Benin,BEN,1975,676870140.341529 -Benin,BEN,1976,698408244.385343 -Benin,BEN,1977,750049739.152238 -Benin,BEN,1978,928843304.783965 -Benin,BEN,1979,1186231265.18417 -Benin,BEN,1980,1405251547.23882 -Benin,BEN,1981,1291119965.11262 -Benin,BEN,1982,1267778489.03079 -Benin,BEN,1983,1095348302.91865 -Benin,BEN,1984,1051133927.00009 -Benin,BEN,1985,1045712703.02696 -Benin,BEN,1986,1336102040.71025 -Benin,BEN,1987,1562412030.34838 -Benin,BEN,1988,1620246187.15171 -Benin,BEN,1989,1502294411.46202 -Benin,BEN,1990,1959965243.76269 -Benin,BEN,1991,1986437859.90346 -Benin,BEN,1992,1695315305.70308 -Benin,BEN,1993,2274557914.07481 -Benin,BEN,1994,1598075932.35432 -Benin,BEN,1995,2169627250.93379 -Benin,BEN,1996,2361116587.86079 -Benin,BEN,1997,2268301537.65128 -Benin,BEN,1998,2455092582.30927 -Benin,BEN,1999,2689787917.50711 -Benin,BEN,2000,2569186642.86999 -Benin,BEN,2001,2680213931.46472 -Benin,BEN,2002,3054571081.6912 -Benin,BEN,2003,3905366187.87017 -Benin,BEN,2004,4521424807.22519 -Benin,BEN,2005,4803702821.08055 -Benin,BEN,2006,5142380779.44103 -Benin,BEN,2007,5969535131.58016 -Benin,BEN,2008,7132787396.66547 -Benin,BEN,2009,7097198711.61023 -Benin,BEN,2010,6970240895.49888 -Benin,BEN,2011,7814081155.64988 -Benin,BEN,2012,8152554487.31321 -Benin,BEN,2013,9156748441.42175 -Benin,BEN,2014,9707432015.61441 -Benin,BEN,2015,8290986804.45245 -Benin,BEN,2016,8583031398.21675 -Bermuda,BMU,1960,84466654.0801544 -Bermuda,BMU,1961,89249986.7007156 -Bermuda,BMU,1962,94149985.9705588 -Bermuda,BMU,1963,96366652.3069165 -Bermuda,BMU,1964,107566650.637987 -Bermuda,BMU,1965,114339048.962736 -Bermuda,BMU,1966,134173373.782802 -Bermuda,BMU,1967,155102984.621576 -Bermuda,BMU,1968,150000000 -Bermuda,BMU,1969,164900000 -Bermuda,BMU,1970,186300000 -Bermuda,BMU,1971,211100000 -Bermuda,BMU,1972,235400000 -Bermuda,BMU,1973,269500000 -Bermuda,BMU,1974,312600000 -Bermuda,BMU,1975,345000000 -Bermuda,BMU,1976,386300000 -Bermuda,BMU,1977,447000000 -Bermuda,BMU,1978,475800000 -Bermuda,BMU,1979,517200000 -Bermuda,BMU,1980,613299968 -Bermuda,BMU,1981,739100032 -Bermuda,BMU,1982,785500032 -Bermuda,BMU,1983,889400000 -Bermuda,BMU,1984,985699968 -Bermuda,BMU,1985,1039500032 -Bermuda,BMU,1986,1173500032 -Bermuda,BMU,1987,1296499968 -Bermuda,BMU,1988,1415100032 -Bermuda,BMU,1989,1501500032 -Bermuda,BMU,1990,1592400000 -Bermuda,BMU,1991,1634899968 -Bermuda,BMU,1992,1679900032 -Bermuda,BMU,1993,1820359936 -Bermuda,BMU,1994,1867160064 -Bermuda,BMU,1995,2030749952 -Bermuda,BMU,1996,2695390000 -Bermuda,BMU,1997,2932827000 -Bermuda,BMU,1998,3130748000 -Bermuda,BMU,1999,3324433000 -Bermuda,BMU,2000,3480219000 -Bermuda,BMU,2001,3680483000 -Bermuda,BMU,2002,3937228000 -Bermuda,BMU,2003,4186525000 -Bermuda,BMU,2004,4484703000 -Bermuda,BMU,2005,4868136000 -Bermuda,BMU,2006,5414299000 -Bermuda,BMU,2007,5895048000 -Bermuda,BMU,2008,6109928000 -Bermuda,BMU,2009,5806378000 -Bermuda,BMU,2010,5744414000 -Bermuda,BMU,2011,5550771000 -Bermuda,BMU,2012,5537537000 -Bermuda,BMU,2013,5573710000 -Bhutan,BTN,1980,135653295.165394 -Bhutan,BTN,1981,146391639.722864 -Bhutan,BTN,1982,148934334.038055 -Bhutan,BTN,1983,165585940.594059 -Bhutan,BTN,1984,169264991.197183 -Bhutan,BTN,1985,172217502.021019 -Bhutan,BTN,1986,201375725.614592 -Bhutan,BTN,1987,253182453.703704 -Bhutan,BTN,1988,283855833.333333 -Bhutan,BTN,1989,275949889.09427 -Bhutan,BTN,1990,299787275.842376 -Bhutan,BTN,1991,250045839.929639 -Bhutan,BTN,1992,250794359.567901 -Bhutan,BTN,1993,235239570.350935 -Bhutan,BTN,1994,270801565.189672 -Bhutan,BTN,1995,303053462.843047 -Bhutan,BTN,1996,316420860.852385 -Bhutan,BTN,1997,365964500.137703 -Bhutan,BTN,1998,376955087.251575 -Bhutan,BTN,1999,419035810.496981 -Bhutan,BTN,2000,439158233.199822 -Bhutan,BTN,2001,476360697.181606 -Bhutan,BTN,2002,537050133.717342 -Bhutan,BTN,2003,622026107.771576 -Bhutan,BTN,2004,702682018.976169 -Bhutan,BTN,2005,818869145.124717 -Bhutan,BTN,2006,897731524.929922 -Bhutan,BTN,2007,1196091805.02316 -Bhutan,BTN,2008,1258332337.28382 -Bhutan,BTN,2009,1264758197.96593 -Bhutan,BTN,2010,1585472534.10547 -Bhutan,BTN,2011,1820207625.80217 -Bhutan,BTN,2012,1823692109.61652 -Bhutan,BTN,2013,1798333725.83954 -Bhutan,BTN,2014,1958819914.95916 -Bhutan,BTN,2015,2057947621.19283 -Bhutan,BTN,2016,2236933237.89015 -Bolivia,BOL,1960,563110051.920733 -Bolivia,BOL,1961,612518906.826491 -Bolivia,BOL,1962,669722541.277818 -Bolivia,BOL,1963,721142957.311474 -Bolivia,BOL,1964,812543072.505384 -Bolivia,BOL,1965,908874537.037037 -Bolivia,BOL,1966,994044553.872054 -Bolivia,BOL,1967,1084059814.81481 -Bolivia,BOL,1968,908874537.037037 -Bolivia,BOL,1969,964615698.653199 -Bolivia,BOL,1970,1017171717.17172 -Bolivia,BOL,1971,1095454545.45455 -Bolivia,BOL,1972,1257615644.97932 -Bolivia,BOL,1973,1263018490.75462 -Bolivia,BOL,1974,2100249875.06247 -Bolivia,BOL,1975,2404697651.17441 -Bolivia,BOL,1976,2732083958.02099 -Bolivia,BOL,1977,3227436281.85907 -Bolivia,BOL,1978,3758220889.55522 -Bolivia,BOL,1979,4421343606.18135 -Bolivia,BOL,1980,4537487842.57749 -Bolivia,BOL,1981,5891606676.18271 -Bolivia,BOL,1982,5594118400.16731 -Bolivia,BOL,1983,5422656261.71049 -Bolivia,BOL,1984,6169481549.37482 -Bolivia,BOL,1985,5377277406.71638 -Bolivia,BOL,1986,3959379487.6064 -Bolivia,BOL,1987,4347956298.51327 -Bolivia,BOL,1988,4597615562.66594 -Bolivia,BOL,1989,4715978868.21613 -Bolivia,BOL,1990,4867582620.20708 -Bolivia,BOL,1991,5343274311.56789 -Bolivia,BOL,1992,5643893347.00679 -Bolivia,BOL,1993,5734676560.92471 -Bolivia,BOL,1994,5981244886.917 -Bolivia,BOL,1995,6715220507.05164 -Bolivia,BOL,1996,7396966657.47054 -Bolivia,BOL,1997,7925673448.41368 -Bolivia,BOL,1998,8497545598.08352 -Bolivia,BOL,1999,8285075872.27307 -Bolivia,BOL,2000,8397912509.09679 -Bolivia,BOL,2001,8141537937.61068 -Bolivia,BOL,2002,7905485216.17852 -Bolivia,BOL,2003,8082364868.39357 -Bolivia,BOL,2004,8773451738.91129 -Bolivia,BOL,2005,9549077869.10651 -Bolivia,BOL,2006,11451869164.7112 -Bolivia,BOL,2007,13120159975.5451 -Bolivia,BOL,2008,16674324634.2373 -Bolivia,BOL,2009,17339992165.2422 -Bolivia,BOL,2010,19649631308.1648 -Bolivia,BOL,2011,23963033443.8518 -Bolivia,BOL,2012,27084497539.7974 -Bolivia,BOL,2013,30659338929.0883 -Bolivia,BOL,2014,32996187988.4226 -Bolivia,BOL,2015,33000198263.3864 -Bolivia,BOL,2016,33806395513.7482 -Bosnia and Herzegovina,BIH,1994,1255802469.1358 -Bosnia and Herzegovina,BIH,1995,1866572953.73666 -Bosnia and Herzegovina,BIH,1996,2786045321.63743 -Bosnia and Herzegovina,BIH,1997,3671816504.23851 -Bosnia and Herzegovina,BIH,1998,4116699437.4041 -Bosnia and Herzegovina,BIH,1999,4685729738.56209 -Bosnia and Herzegovina,BIH,2000,5505984455.95855 -Bosnia and Herzegovina,BIH,2001,5748990666.17862 -Bosnia and Herzegovina,BIH,2002,6651226179.01829 -Bosnia and Herzegovina,BIH,2003,8370020196.19158 -Bosnia and Herzegovina,BIH,2004,10022840634.9206 -Bosnia and Herzegovina,BIH,2005,11225138297.1959 -Bosnia and Herzegovina,BIH,2006,12866524918.2221 -Bosnia and Herzegovina,BIH,2007,15776422673.198 -Bosnia and Herzegovina,BIH,2008,19101454463.7507 -Bosnia and Herzegovina,BIH,2009,17600630726.6141 -Bosnia and Herzegovina,BIH,2010,17164279813.0968 -Bosnia and Herzegovina,BIH,2011,18629346790.8167 -Bosnia and Herzegovina,BIH,2012,17207367625.8048 -Bosnia and Herzegovina,BIH,2013,18154290272.2151 -Bosnia and Herzegovina,BIH,2014,18521475376.4754 -Bosnia and Herzegovina,BIH,2015,16173806634.5336 -Bosnia and Herzegovina,BIH,2016,16559695718.568 -Botswana,BWA,1960,30412308.9864012 -Botswana,BWA,1961,32902336.644746 -Botswana,BWA,1962,35643207.6265246 -Botswana,BWA,1963,38091150.566196 -Botswana,BWA,1964,41613969.0506064 -Botswana,BWA,1965,45790869.7473126 -Botswana,BWA,1966,51464435.1464435 -Botswana,BWA,1967,58646443.5146444 -Botswana,BWA,1968,66248256.6248257 -Botswana,BWA,1969,77356914.0788191 -Botswana,BWA,1970,96245114.4611949 -Botswana,BWA,1971,126957494.407159 -Botswana,BWA,1972,165258093.875959 -Botswana,BWA,1973,244129088.027662 -Botswana,BWA,1974,306033848.417954 -Botswana,BWA,1975,355172413.793103 -Botswana,BWA,1976,372010119.595216 -Botswana,BWA,1977,451603325.415677 -Botswana,BWA,1978,590376720.598889 -Botswana,BWA,1979,819877300.613497 -Botswana,BWA,1980,1060923829.13021 -Botswana,BWA,1981,1073861599.13948 -Botswana,BWA,1982,1014907254.54016 -Botswana,BWA,1983,1172258182.14969 -Botswana,BWA,1984,1240796364.75662 -Botswana,BWA,1985,1114764007.14811 -Botswana,BWA,1986,1392634771.9653 -Botswana,BWA,1987,1965274882.36345 -Botswana,BWA,1988,2644536804.11244 -Botswana,BWA,1989,3083800684.89751 -Botswana,BWA,1990,3790567051.86778 -Botswana,BWA,1991,3942792837.35655 -Botswana,BWA,1992,4146513722.33019 -Botswana,BWA,1993,4160086253.1468 -Botswana,BWA,1994,4259330999.03151 -Botswana,BWA,1995,4730611067.02258 -Botswana,BWA,1996,4847752842.78924 -Botswana,BWA,1997,5020214747.45261 -Botswana,BWA,1998,4790458837.17078 -Botswana,BWA,1999,5484257417.17844 -Botswana,BWA,2000,5788329609.15755 -Botswana,BWA,2001,5489608299.66445 -Botswana,BWA,2002,5438857106.73536 -Botswana,BWA,2003,7511582173.37724 -Botswana,BWA,2004,8957467706.5354 -Botswana,BWA,2005,9931134940.51346 -Botswana,BWA,2006,10126940513.3125 -Botswana,BWA,2007,10939053367.1521 -Botswana,BWA,2008,10945070441.9283 -Botswana,BWA,2009,10267133177.7334 -Botswana,BWA,2010,12786654365.8738 -Botswana,BWA,2011,15682926890.0326 -Botswana,BWA,2012,14686278713.5189 -Botswana,BWA,2013,14915780533.086 -Botswana,BWA,2014,16259445049.7698 -Botswana,BWA,2015,14430608463.4399 -Botswana,BWA,2016,15274861068.209 -Brazil,BRA,1960,15165569912.5199 -Brazil,BRA,1961,15236854859.469 -Brazil,BRA,1962,19926293839.0163 -Brazil,BRA,1963,23021477292.2093 -Brazil,BRA,1964,21211892259.9904 -Brazil,BRA,1965,21790035117.19 -Brazil,BRA,1966,27062716577.9111 -Brazil,BRA,1967,30591834053.9653 -Brazil,BRA,1968,33875881876.3672 -Brazil,BRA,1969,37458898243.8609 -Brazil,BRA,1970,42327600098.2412 -Brazil,BRA,1971,49204456700.4516 -Brazil,BRA,1972,58539008786.3684 -Brazil,BRA,1973,79279057730.829 -Brazil,BRA,1974,105136007528.76 -Brazil,BRA,1975,123709376567.89 -Brazil,BRA,1976,152678020452.829 -Brazil,BRA,1977,176171284311.761 -Brazil,BRA,1978,200800891870.164 -Brazil,BRA,1979,224969488835.181 -Brazil,BRA,1980,235024598983.261 -Brazil,BRA,1981,263561088977.129 -Brazil,BRA,1982,281682304161.041 -Brazil,BRA,1983,203304515490.795 -Brazil,BRA,1984,209023912696.839 -Brazil,BRA,1985,222942790435.299 -Brazil,BRA,1986,268137224729.722 -Brazil,BRA,1987,294084112392.66 -Brazil,BRA,1988,330397381998.489 -Brazil,BRA,1989,425595310000 -Brazil,BRA,1990,461951782000 -Brazil,BRA,1991,602860000000 -Brazil,BRA,1992,400599250000 -Brazil,BRA,1993,437798577639.752 -Brazil,BRA,1994,558111997497.263 -Brazil,BRA,1995,785643456467.255 -Brazil,BRA,1996,850425828275.793 -Brazil,BRA,1997,883199443413.729 -Brazil,BRA,1998,863723395088.324 -Brazil,BRA,1999,599388879704.634 -Brazil,BRA,2000,655421153320.579 -Brazil,BRA,2001,559372502338.237 -Brazil,BRA,2002,507962741819.919 -Brazil,BRA,2003,558320116997.075 -Brazil,BRA,2004,669316239316.239 -Brazil,BRA,2005,891629970423.924 -Brazil,BRA,2006,1107640325472.35 -Brazil,BRA,2007,1397084381901.29 -Brazil,BRA,2008,1695824517395.57 -Brazil,BRA,2009,1667019605881.76 -Brazil,BRA,2010,2208871646202.82 -Brazil,BRA,2011,2616201578192.25 -Brazil,BRA,2012,2465188674415.03 -Brazil,BRA,2013,2472806919901.67 -Brazil,BRA,2014,2455993200170 -Brazil,BRA,2015,1803652649613.75 -Brazil,BRA,2016,1796186586414.45 -Brunei Darussalam,BRN,1965,114040245.655299 -Brunei Darussalam,BRN,1966,132758395.400497 -Brunei Darussalam,BRN,1967,139030445.576898 -Brunei Darussalam,BRN,1968,160819286.554292 -Brunei Darussalam,BRN,1969,161211289.690318 -Brunei Darussalam,BRN,1970,179080099.307461 -Brunei Darussalam,BRN,1971,197523179.241883 -Brunei Darussalam,BRN,1972,270818555.823521 -Brunei Darussalam,BRN,1973,433092003.579273 -Brunei Darussalam,BRN,1974,1073577085.64159 -Brunei Darussalam,BRN,1975,1168304305.65513 -Brunei Darussalam,BRN,1976,1423061356.64562 -Brunei Darussalam,BRN,1977,1732721160.94122 -Brunei Darussalam,BRN,1978,1941600703.60598 -Brunei Darussalam,BRN,1979,2803780005.51826 -Brunei Darussalam,BRN,1980,4928824957.9675 -Brunei Darussalam,BRN,1981,4366213849.57637 -Brunei Darussalam,BRN,1982,4264252336.4486 -Brunei Darussalam,BRN,1983,3844723142.45149 -Brunei Darussalam,BRN,1984,3782523088.4628 -Brunei Darussalam,BRN,1985,3523612563.06532 -Brunei Darussalam,BRN,1986,2358592817.12134 -Brunei Darussalam,BRN,1987,2754463437.79677 -Brunei Darussalam,BRN,1988,2690717551.18267 -Brunei Darussalam,BRN,1989,2985467979.28524 -Brunei Darussalam,BRN,1990,3520551724.13793 -Brunei Darussalam,BRN,1991,3701667052.55846 -Brunei Darussalam,BRN,1992,4183548189.07305 -Brunei Darussalam,BRN,1993,4105706151.75145 -Brunei Darussalam,BRN,1994,4087337959.93191 -Brunei Darussalam,BRN,1995,4734020036.68689 -Brunei Darussalam,BRN,1996,5115602836.87943 -Brunei Darussalam,BRN,1997,5197332974.13793 -Brunei Darussalam,BRN,1998,4051147227.53346 -Brunei Darussalam,BRN,1999,4600000000 -Brunei Darussalam,BRN,2000,6001153306.2645 -Brunei Darussalam,BRN,2001,5601090584.36122 -Brunei Darussalam,BRN,2002,5843329107.56171 -Brunei Darussalam,BRN,2003,6557333084.60567 -Brunei Darussalam,BRN,2004,7872333215.00414 -Brunei Darussalam,BRN,2005,9531402847.87311 -Brunei Darussalam,BRN,2006,11470703002.0769 -Brunei Darussalam,BRN,2007,12247694247.2298 -Brunei Darussalam,BRN,2008,14393099068.5859 -Brunei Darussalam,BRN,2009,10732366286.2643 -Brunei Darussalam,BRN,2010,13707370737.0737 -Brunei Darussalam,BRN,2011,18525319977.7407 -Brunei Darussalam,BRN,2012,19048495518.5659 -Brunei Darussalam,BRN,2013,18093829923.2737 -Brunei Darussalam,BRN,2014,17123125493.2912 -Brunei Darussalam,BRN,2015,12930394937.8137 -Brunei Darussalam,BRN,2016,11400266877.3769 -Bulgaria,BGR,1980,19839230769.2308 -Bulgaria,BGR,1981,19870000000 -Bulgaria,BGR,1982,19342000000 -Bulgaria,BGR,1983,16563666666.6667 -Bulgaria,BGR,1984,17594944444.4444 -Bulgaria,BGR,1985,17155421052.6316 -Bulgaria,BGR,1986,20249294117.6471 -Bulgaria,BGR,1987,28101000000 -Bulgaria,BGR,1988,22555941176.4706 -Bulgaria,BGR,1989,21988444444.4444 -Bulgaria,BGR,1990,20632090909.0909 -Bulgaria,BGR,1991,10943548387.0968 -Bulgaria,BGR,1992,10350515463.9175 -Bulgaria,BGR,1993,10829710144.9275 -Bulgaria,BGR,1994,9697416974.16974 -Bulgaria,BGR,1995,13063422619.0476 -Bulgaria,BGR,1996,10109404159.6402 -Bulgaria,BGR,1997,11195630536.8928 -Bulgaria,BGR,1998,14630974778.4594 -Bulgaria,BGR,1999,13495062850.302 -Bulgaria,BGR,2000,13148099185.2305 -Bulgaria,BGR,2001,14135393875.5893 -Bulgaria,BGR,2002,16360346653.8276 -Bulgaria,BGR,2003,21074775206.3254 -Bulgaria,BGR,2004,26094622563.6468 -Bulgaria,BGR,2005,29821662537.3229 -Bulgaria,BGR,2006,34304448149.8108 -Bulgaria,BGR,2007,44765733379.986 -Bulgaria,BGR,2008,54666642734.2757 -Bulgaria,BGR,2009,51783454183.5501 -Bulgaria,BGR,2010,50610031135.7791 -Bulgaria,BGR,2011,57418391041.5926 -Bulgaria,BGR,2012,53903028252.2996 -Bulgaria,BGR,2013,55758744571.1183 -Bulgaria,BGR,2014,56732006512.0065 -Bulgaria,BGR,2015,50199117547.0415 -Bulgaria,BGR,2016,52395164027.1493 -Burkina Faso,BFA,1960,330442817.168859 -Burkina Faso,BFA,1961,350247237.11684 -Burkina Faso,BFA,1962,379567178.256898 -Burkina Faso,BFA,1963,394040749.12567 -Burkina Faso,BFA,1964,410321785.631059 -Burkina Faso,BFA,1965,422916848.424208 -Burkina Faso,BFA,1966,433889831.584706 -Burkina Faso,BFA,1967,450753993.176448 -Burkina Faso,BFA,1968,460442864.205949 -Burkina Faso,BFA,1969,478298781.545658 -Burkina Faso,BFA,1970,458404330.125096 -Burkina Faso,BFA,1971,482411278.982439 -Burkina Faso,BFA,1972,578595583.975723 -Burkina Faso,BFA,1973,674773821.151416 -Burkina Faso,BFA,1974,751133642.647461 -Burkina Faso,BFA,1975,939972703.463021 -Burkina Faso,BFA,1976,976547572.215824 -Burkina Faso,BFA,1977,1131225278.77773 -Burkina Faso,BFA,1978,1475584037.28156 -Burkina Faso,BFA,1979,1748480982.18517 -Burkina Faso,BFA,1980,1928720390.28869 -Burkina Faso,BFA,1981,1775842679.94056 -Burkina Faso,BFA,1982,1754450379.2077 -Burkina Faso,BFA,1983,1600278756.43589 -Burkina Faso,BFA,1984,1459880352.6483 -Burkina Faso,BFA,1985,1552493413.98989 -Burkina Faso,BFA,1986,2036303381.20142 -Burkina Faso,BFA,1987,2369835438.62393 -Burkina Faso,BFA,1988,2616040645.87263 -Burkina Faso,BFA,1989,2615588545.68629 -Burkina Faso,BFA,1990,3101301780.95067 -Burkina Faso,BFA,1991,3135045684.1006 -Burkina Faso,BFA,1992,2240264711.54816 -Burkina Faso,BFA,1993,2332018010.55341 -Burkina Faso,BFA,1994,1895290964.80829 -Burkina Faso,BFA,1995,2379518099.2266 -Burkina Faso,BFA,1996,2586550747.09844 -Burkina Faso,BFA,1997,2447669403.89018 -Burkina Faso,BFA,1998,2804902723.73145 -Burkina Faso,BFA,1999,2993753187.09677 -Burkina Faso,BFA,2000,2628920056.10098 -Burkina Faso,BFA,2001,2812845513.57125 -Burkina Faso,BFA,2002,3205592289.79773 -Burkina Faso,BFA,2003,4205691222.11396 -Burkina Faso,BFA,2004,4838551099.70985 -Burkina Faso,BFA,2005,5462709498.45119 -Burkina Faso,BFA,2006,5844669845.53733 -Burkina Faso,BFA,2007,6771277870.96412 -Burkina Faso,BFA,2008,8369637065.40255 -Burkina Faso,BFA,2009,8369175126.25316 -Burkina Faso,BFA,2010,8979966766.07232 -Burkina Faso,BFA,2011,10724061338.5874 -Burkina Faso,BFA,2012,11166061507.8024 -Burkina Faso,BFA,2013,11934606509.5944 -Burkina Faso,BFA,2014,12400688571.1396 -Burkina Faso,BFA,2015,11148759324.507 -Burkina Faso,BFA,2016,12115155931.5461 -Burundi,BDI,1960,195999990 -Burundi,BDI,1961,202999992 -Burundi,BDI,1962,213500006 -Burundi,BDI,1963,232749998 -Burundi,BDI,1964,260750008 -Burundi,BDI,1965,158994962.962963 -Burundi,BDI,1966,165444571.428571 -Burundi,BDI,1967,178297142.857143 -Burundi,BDI,1968,183200000 -Burundi,BDI,1969,190205714.285714 -Burundi,BDI,1970,242732571.428571 -Burundi,BDI,1971,252842285.714286 -Burundi,BDI,1972,246804571.428571 -Burundi,BDI,1973,304339839.552146 -Burundi,BDI,1974,345263492.063492 -Burundi,BDI,1975,420986666.666667 -Burundi,BDI,1976,448412753.623188 -Burundi,BDI,1977,547535555.555556 -Burundi,BDI,1978,610225555.555556 -Burundi,BDI,1979,782496666.666667 -Burundi,BDI,1980,919726666.666667 -Burundi,BDI,1981,969046666.666667 -Burundi,BDI,1982,1013222222.22222 -Burundi,BDI,1983,1082926304.46477 -Burundi,BDI,1984,987143931.166987 -Burundi,BDI,1985,1149979285.77347 -Burundi,BDI,1986,1201725497.06578 -Burundi,BDI,1987,1131466494.01101 -Burundi,BDI,1988,1082403219.48787 -Burundi,BDI,1989,1113924130.41149 -Burundi,BDI,1990,1132101252.51817 -Burundi,BDI,1991,1167398478.3459 -Burundi,BDI,1992,1083037670.60484 -Burundi,BDI,1993,938632612.026359 -Burundi,BDI,1994,925030590.153683 -Burundi,BDI,1995,1000428393.88528 -Burundi,BDI,1996,869033856.317093 -Burundi,BDI,1997,972896267.915425 -Burundi,BDI,1998,893770806.077641 -Burundi,BDI,1999,808077223.365746 -Burundi,BDI,2000,870486065.883137 -Burundi,BDI,2001,876794723.068586 -Burundi,BDI,2002,825394490.159111 -Burundi,BDI,2003,784654423.620476 -Burundi,BDI,2004,915257323.3961 -Burundi,BDI,2005,1117257279.46188 -Burundi,BDI,2006,1273180597.02711 -Burundi,BDI,2007,1356078278.18821 -Burundi,BDI,2008,1611634331.64869 -Burundi,BDI,2009,1739781488.7457 -Burundi,BDI,2010,2026864469.36388 -Burundi,BDI,2011,2355652125.85184 -Burundi,BDI,2012,2472384906.99794 -Burundi,BDI,2013,2714505634.52629 -Burundi,BDI,2014,3093647226.8107 -Burundi,BDI,2015,3097324739.8493 -Burundi,BDI,2016,3007029030.39976 -Cabo Verde,CPV,1980,142246875.536716 -Cabo Verde,CPV,1981,139468114.599741 -Cabo Verde,CPV,1982,140630758.594899 -Cabo Verde,CPV,1983,138476239.366792 -Cabo Verde,CPV,1984,132019065.033419 -Cabo Verde,CPV,1985,137728155.212661 -Cabo Verde,CPV,1986,190651207.999511 -Cabo Verde,CPV,1987,235253171.841062 -Cabo Verde,CPV,1988,264308140.285149 -Cabo Verde,CPV,1989,267448513.108168 -Cabo Verde,CPV,1990,306891107.262039 -Cabo Verde,CPV,1991,319827058.592875 -Cabo Verde,CPV,1992,357160985.327413 -Cabo Verde,CPV,1993,490417389.682569 -Cabo Verde,CPV,1994,406580652.330537 -Cabo Verde,CPV,1995,487148993.533109 -Cabo Verde,CPV,1996,501979069.274683 -Cabo Verde,CPV,1997,490608657.924976 -Cabo Verde,CPV,1998,521910560.524868 -Cabo Verde,CPV,1999,592416703.058878 -Cabo Verde,CPV,2000,539227277.626411 -Cabo Verde,CPV,2001,563024383.296626 -Cabo Verde,CPV,2002,620974660.230303 -Cabo Verde,CPV,2003,813963830.179217 -Cabo Verde,CPV,2004,924318490.7598 -Cabo Verde,CPV,2005,971977088.156914 -Cabo Verde,CPV,2006,1107891063.43863 -Cabo Verde,CPV,2007,1513934037.24782 -Cabo Verde,CPV,2008,1789333748.6799 -Cabo Verde,CPV,2009,1711817181.52969 -Cabo Verde,CPV,2010,1664310769.55229 -Cabo Verde,CPV,2011,1864824080.69256 -Cabo Verde,CPV,2012,1751888561.72747 -Cabo Verde,CPV,2013,1850951315.45564 -Cabo Verde,CPV,2014,1858121723.24993 -Cabo Verde,CPV,2015,1574288667.69981 -Cabo Verde,CPV,2016,1617467435.77007 -Cambodia,KHM,1960,637142865.714286 -Cambodia,KHM,1961,642857134.285714 -Cambodia,KHM,1962,660000008.571429 -Cambodia,KHM,1963,728571437.142857 -Cambodia,KHM,1964,782857128.571429 -Cambodia,KHM,1965,868571428.571429 -Cambodia,KHM,1966,914285714.285714 -Cambodia,KHM,1967,962857134.285714 -Cambodia,KHM,1968,1065714248.57143 -Cambodia,KHM,1969,978873232.394366 -Cambodia,KHM,1970,718401157.724163 -Cambodia,KHM,1971,969911421.394181 -Cambodia,KHM,1972,505549441.375077 -Cambodia,KHM,1973,702899155.982033 -Cambodia,KHM,1974,588443893.689773 -Cambodia,KHM,1993,2533727592.02872 -Cambodia,KHM,1994,2791435272.25765 -Cambodia,KHM,1995,3441205692.90388 -Cambodia,KHM,1996,3506695719.5716 -Cambodia,KHM,1997,3443413388.70675 -Cambodia,KHM,1998,3120425502.56968 -Cambodia,KHM,1999,3517242477.23368 -Cambodia,KHM,2000,3654031716.27649 -Cambodia,KHM,2001,3984000517.01899 -Cambodia,KHM,2002,4284028482.54971 -Cambodia,KHM,2003,4658246918.26014 -Cambodia,KHM,2004,5337833248.02828 -Cambodia,KHM,2005,6293046161.82646 -Cambodia,KHM,2006,7274595706.66355 -Cambodia,KHM,2007,8639235842.17756 -Cambodia,KHM,2008,10351914093.1626 -Cambodia,KHM,2009,10401851850.6062 -Cambodia,KHM,2010,11242275198.9706 -Cambodia,KHM,2011,12829541141.0175 -Cambodia,KHM,2012,14038383450.1945 -Cambodia,KHM,2013,15449630418.5461 -Cambodia,KHM,2014,16777820332.6952 -Cambodia,KHM,2015,18049954289.4301 -Cambodia,KHM,2016,20016747754.0153 -Cameroon,CMR,1960,618740988.011405 -Cameroon,CMR,1961,657597382.759152 -Cameroon,CMR,1962,699373701.217138 -Cameroon,CMR,1963,723624365.288138 -Cameroon,CMR,1964,782384527.813649 -Cameroon,CMR,1965,814139855.756458 -Cameroon,CMR,1966,853268771.097081 -Cameroon,CMR,1967,934079050.346173 -Cameroon,CMR,1968,1053077155.17925 -Cameroon,CMR,1969,1152418514.82616 -Cameroon,CMR,1970,1160002260.94729 -Cameroon,CMR,1971,1233991075.11626 -Cameroon,CMR,1972,1430951331.85034 -Cameroon,CMR,1973,1758727395.18703 -Cameroon,CMR,1974,2255496995.49378 -Cameroon,CMR,1975,2752771043.88609 -Cameroon,CMR,1976,3076592431.27204 -Cameroon,CMR,1977,3366368664.59706 -Cameroon,CMR,1978,4409920643.6422 -Cameroon,CMR,1979,5811444660.65752 -Cameroon,CMR,1980,6740756568.91566 -Cameroon,CMR,1981,7636345827.34308 -Cameroon,CMR,1982,7322914570.15588 -Cameroon,CMR,1983,7381854746.91629 -Cameroon,CMR,1984,7801858825.18416 -Cameroon,CMR,1985,8148223603.58399 -Cameroon,CMR,1986,10621158532.5193 -Cameroon,CMR,1987,12302471429.4318 -Cameroon,CMR,1988,12493286761.7341 -Cameroon,CMR,1989,11140055364.1502 -Cameroon,CMR,1990,11151578050.7356 -Cameroon,CMR,1991,12434370004.9586 -Cameroon,CMR,1992,11396310990.2197 -Cameroon,CMR,1993,13532137227.585 -Cameroon,CMR,1994,9220470913.32766 -Cameroon,CMR,1995,8733231184.34755 -Cameroon,CMR,1996,9732328115.73674 -Cameroon,CMR,1997,9840553235.89425 -Cameroon,CMR,1998,9629649416.89037 -Cameroon,CMR,1999,10486451144.4061 -Cameroon,CMR,2000,9287367235.25769 -Cameroon,CMR,2001,9633109349.64535 -Cameroon,CMR,2002,10879778384.1965 -Cameroon,CMR,2003,13621738837.1961 -Cameroon,CMR,2004,15775357014.6254 -Cameroon,CMR,2005,16587858856.6778 -Cameroon,CMR,2006,17953066721.0949 -Cameroon,CMR,2007,20431780377.8605 -Cameroon,CMR,2008,23322254113.5623 -Cameroon,CMR,2009,23381142146.6485 -Cameroon,CMR,2010,23622483983.7101 -Cameroon,CMR,2011,26587311527.5711 -Cameroon,CMR,2012,26472056037.7696 -Cameroon,CMR,2013,29567504655.4935 -Cameroon,CMR,2014,32050817632.9602 -Cameroon,CMR,2015,28415950981.4447 -Cameroon,CMR,2016,24204448566.6105 -Canada,CAN,1960,41093453544.9096 -Canada,CAN,1961,40767969453.696 -Canada,CAN,1962,41978852041.4426 -Canada,CAN,1963,44657169109.224 -Canada,CAN,1964,48882938810.2204 -Canada,CAN,1965,53909570342.169 -Canada,CAN,1966,60358632035.1532 -Canada,CAN,1967,64768831262.1761 -Canada,CAN,1968,70759031841.7237 -Canada,CAN,1969,77887510241.7083 -Canada,CAN,1970,87896095224.4234 -Canada,CAN,1971,99271961477.5203 -Canada,CAN,1972,113082820992.019 -Canada,CAN,1973,131321859214.079 -Canada,CAN,1974,160408697648.262 -Canada,CAN,1975,173834029787.652 -Canada,CAN,1976,206575564401.623 -Canada,CAN,1977,211612156934.65 -Canada,CAN,1978,218632867449.812 -Canada,CAN,1979,243072102185.419 -Canada,CAN,1980,273853826377.01 -Canada,CAN,1981,306214863624.99 -Canada,CAN,1982,313506525087.136 -Canada,CAN,1983,340547711781.889 -Canada,CAN,1984,355372558103.621 -Canada,CAN,1985,364756499450.751 -Canada,CAN,1986,377437927311.983 -Canada,CAN,1987,431316742081.448 -Canada,CAN,1988,507354351182.254 -Canada,CAN,1989,565055743243.243 -Canada,CAN,1990,593929550908.468 -Canada,CAN,1991,610328183643.188 -Canada,CAN,1992,592387689252.916 -Canada,CAN,1993,577170761956.438 -Canada,CAN,1994,578139279437.61 -Canada,CAN,1995,604031623433.401 -Canada,CAN,1996,628546387972.131 -Canada,CAN,1997,652825364726.275 -Canada,CAN,1998,631813279406.808 -Canada,CAN,1999,676082654640.91 -Canada,CAN,2000,742293448252.643 -Canada,CAN,2001,736379777892.562 -Canada,CAN,2002,757950678646.53 -Canada,CAN,2003,892380986367.854 -Canada,CAN,2004,1023196003074.56 -Canada,CAN,2005,1169357979864.66 -Canada,CAN,2006,1315415197461.21 -Canada,CAN,2007,1464977190205.75 -Canada,CAN,2008,1549131208997.19 -Canada,CAN,2009,1371153004986.44 -Canada,CAN,2010,1613464422811.13 -Canada,CAN,2011,1788647906047.76 -Canada,CAN,2012,1824288757447.57 -Canada,CAN,2013,1842628005830.18 -Canada,CAN,2014,1792883225804.38 -Canada,CAN,2015,1552807652015.37 -Canada,CAN,2016,1529760492201.35 -Cayman Islands,CYM,1996,1012444074.07495 -Cayman Islands,CYM,2006,3207032512.94205 -Central African Republic,CAF,1960,112155598.949571 -Central African Republic,CAF,1961,123134584.467673 -Central African Republic,CAF,1962,124482748.937917 -Central African Republic,CAF,1963,129379097.888958 -Central African Republic,CAF,1964,142025069.461676 -Central African Republic,CAF,1965,150574816.300764 -Central African Republic,CAF,1966,157930041.875883 -Central African Republic,CAF,1967,163820538.867947 -Central African Republic,CAF,1968,191767436.956884 -Central African Republic,CAF,1969,188039191.323608 -Central African Republic,CAF,1970,189106554.521277 -Central African Republic,CAF,1971,201450768.367553 -Central African Republic,CAF,1972,230317908.038643 -Central African Republic,CAF,1973,271183061.359635 -Central African Republic,CAF,1974,281398668.160613 -Central African Republic,CAF,1975,378660016.265936 -Central African Republic,CAF,1976,451152449.984411 -Central African Republic,CAF,1977,507298120.68315 -Central African Republic,CAF,1978,610578523.761178 -Central African Republic,CAF,1979,700764892.704831 -Central African Republic,CAF,1980,797048028.773247 -Central African Republic,CAF,1981,694803502.722356 -Central African Republic,CAF,1982,748312283.726758 -Central African Republic,CAF,1983,658679394.907969 -Central African Republic,CAF,1984,637820620.670195 -Central African Republic,CAF,1985,864849765.059665 -Central African Republic,CAF,1986,1122265026.38274 -Central African Republic,CAF,1987,1200991825.95398 -Central African Republic,CAF,1988,1264899368.20165 -Central African Republic,CAF,1989,1233930277.04922 -Central African Republic,CAF,1990,1440711395.67069 -Central African Republic,CAF,1991,1377375030.52921 -Central African Republic,CAF,1992,1411917558.45855 -Central African Republic,CAF,1993,1278781166.72188 -Central African Republic,CAF,1994,851174350.649409 -Central African Republic,CAF,1995,1115389731.79119 -Central African Republic,CAF,1996,1007791186.20106 -Central African Republic,CAF,1997,937741468.029676 -Central African Republic,CAF,1998,967338348.658314 -Central African Republic,CAF,1999,999477510.686632 -Central African Republic,CAF,2000,914500299.097034 -Central African Republic,CAF,2001,931833302.752857 -Central African Republic,CAF,2002,991387870.12463 -Central African Republic,CAF,2003,1139754799.16304 -Central African Republic,CAF,2004,1270080250.65268 -Central African Republic,CAF,2005,1350301057.06866 -Central African Republic,CAF,2006,1460562038.37097 -Central African Republic,CAF,2007,1698125617.92304 -Central African Republic,CAF,2008,1985239276.62611 -Central African Republic,CAF,2009,1981728140.77833 -Central African Republic,CAF,2010,1986014845.63184 -Central African Republic,CAF,2011,2212699746.81377 -Central African Republic,CAF,2012,2184183758.31567 -Central African Republic,CAF,2013,1518565219.01061 -Central African Republic,CAF,2014,1702898939.55483 -Central African Republic,CAF,2015,1583776759.97697 -Central African Republic,CAF,2016,1756124677.19671 -Chad,TCD,1960,313582727.638108 -Chad,TCD,1961,333975336.626596 -Chad,TCD,1962,357635713.876856 -Chad,TCD,1963,371767002.656036 -Chad,TCD,1964,392247517.601949 -Chad,TCD,1965,416926302.963497 -Chad,TCD,1966,432794922.459759 -Chad,TCD,1967,449826322.995107 -Chad,TCD,1968,453980096.654412 -Chad,TCD,1969,471635620.924368 -Chad,TCD,1970,469266736.605101 -Chad,TCD,1971,501866730.722503 -Chad,TCD,1972,585427545.723598 -Chad,TCD,1973,647199482.827982 -Chad,TCD,1974,652532796.06664 -Chad,TCD,1975,864602103.303074 -Chad,TCD,1976,866044961.048354 -Chad,TCD,1977,935360466.351488 -Chad,TCD,1978,1113920122.61232 -Chad,TCD,1979,1004316495.11176 -Chad,TCD,1980,1033002401.82543 -Chad,TCD,1981,876937559.724954 -Chad,TCD,1982,834369860.427317 -Chad,TCD,1983,832415805.956265 -Chad,TCD,1984,919103735.322906 -Chad,TCD,1985,1033069709.99506 -Chad,TCD,1986,1067828247.23579 -Chad,TCD,1987,1163426850.65024 -Chad,TCD,1988,1482597298.88729 -Chad,TCD,1989,1433686309.83641 -Chad,TCD,1990,1738605558.05436 -Chad,TCD,1991,1877138041.64308 -Chad,TCD,1992,1881847676.80752 -Chad,TCD,1993,1463251055.40068 -Chad,TCD,1994,1179837954.72193 -Chad,TCD,1995,1445919969.89272 -Chad,TCD,1996,1607345450.04578 -Chad,TCD,1997,1544689502.82472 -Chad,TCD,1998,1744794457.276 -Chad,TCD,1999,1534673583.2487 -Chad,TCD,2000,1385058161.76746 -Chad,TCD,2001,1709347793.32873 -Chad,TCD,2002,1987622279.11463 -Chad,TCD,2003,2736666515.8294 -Chad,TCD,2004,4414929219.99649 -Chad,TCD,2005,6646663561.2656 -Chad,TCD,2006,7422102655.98832 -Chad,TCD,2007,8638711442.7705 -Chad,TCD,2008,10351932604.4154 -Chad,TCD,2009,9253484108.49701 -Chad,TCD,2010,10657705536.4978 -Chad,TCD,2011,12156380425.0825 -Chad,TCD,2012,12368071038.7362 -Chad,TCD,2013,12949854262.8127 -Chad,TCD,2014,13922223233.5184 -Chad,TCD,2015,10888798113.7866 -Chad,TCD,2016,9600761473.78738 -Channel Islands,CHI,1998,5945677376.61477 -Channel Islands,CHI,1999,6262740656.85164 -Channel Islands,CHI,2000,6439703434.71024 -Channel Islands,CHI,2001,6232906290.4851 -Channel Islands,CHI,2002,6663669064.7482 -Channel Islands,CHI,2003,7332244897.95918 -Channel Islands,CHI,2004,8553643354.08275 -Channel Islands,CHI,2005,8827272727.27273 -Channel Islands,CHI,2006,9676172953.08188 -Channel Islands,CHI,2007,11514605842.3369 -Chile,CHL,1960,4109993820.85867 -Chile,CHL,1961,4609700367.43769 -Chile,CHL,1962,5416266783.44725 -Chile,CHL,1963,5668205957.19525 -Chile,CHL,1964,5982343871.07657 -Chile,CHL,1965,6026583778.99913 -Chile,CHL,1966,7072636623.49356 -Chile,CHL,1967,7013192291.50469 -Chile,CHL,1968,7167084577.79975 -Chile,CHL,1969,8377098357.87508 -Chile,CHL,1970,9126311883.24115 -Chile,CHL,1971,10884112885.7799 -Chile,CHL,1972,11853818445.9512 -Chile,CHL,1973,16836261234.4254 -Chile,CHL,1974,16210404218.7163 -Chile,CHL,1975,7622217357.00739 -Chile,CHL,1976,10341925245.9606 -Chile,CHL,1977,13962893421.8332 -Chile,CHL,1978,15989933709.6354 -Chile,CHL,1979,21803696986.4362 -Chile,CHL,1980,29036709873.0313 -Chile,CHL,1981,34509878043.8003 -Chile,CHL,1982,25325893204.9564 -Chile,CHL,1983,20355959236.7512 -Chile,CHL,1984,19622527479.8718 -Chile,CHL,1985,17702885393.2705 -Chile,CHL,1986,18891048818.9936 -Chile,CHL,1987,22255407684.5828 -Chile,CHL,1988,26040229792.9356 -Chile,CHL,1989,29885685143.0648 -Chile,CHL,1990,33113887817.8869 -Chile,CHL,1991,37834793730.368 -Chile,CHL,1992,45964327558.9522 -Chile,CHL,1993,49297773130.1452 -Chile,CHL,1994,57008425295.862 -Chile,CHL,1995,73447063319.1781 -Chile,CHL,1996,78039572221.6062 -Chile,CHL,1997,84952360922.4958 -Chile,CHL,1998,81577430181.4606 -Chile,CHL,1999,75173794497.0496 -Chile,CHL,2000,77860932151.9303 -Chile,CHL,2001,70980110277.4532 -Chile,CHL,2002,69737148847.9119 -Chile,CHL,2003,75643733356.097 -Chile,CHL,2004,99210528495.6404 -Chile,CHL,2005,122964812046.14 -Chile,CHL,2006,154788024805.866 -Chile,CHL,2007,173605979255.357 -Chile,CHL,2008,179638483957.885 -Chile,CHL,2009,172389500030.292 -Chile,CHL,2010,218537565496.634 -Chile,CHL,2011,252251992029.518 -Chile,CHL,2012,267122318194.715 -Chile,CHL,2013,278384345259.391 -Chile,CHL,2014,260990291671.248 -Chile,CHL,2015,242517910999.453 -Chile,CHL,2016,247027899421.318 -China,CHN,1960,59716467625.3148 -China,CHN,1961,50056868957.6732 -China,CHN,1962,47209359005.6056 -China,CHN,1963,50706799902.5103 -China,CHN,1964,59708343488.5043 -China,CHN,1965,70436266146.7219 -China,CHN,1966,76720285969.6157 -China,CHN,1967,72881631326.6715 -China,CHN,1968,70846535055.6503 -China,CHN,1969,79705906247.4612 -China,CHN,1970,92602973434.0726 -China,CHN,1971,99800958648.1436 -China,CHN,1972,113687586299.051 -China,CHN,1973,138544284708.957 -China,CHN,1974,144182133387.722 -China,CHN,1975,163431551779.761 -China,CHN,1976,153940455341.506 -China,CHN,1977,174938098826.569 -China,CHN,1978,149540650406.504 -China,CHN,1979,178282608695.652 -China,CHN,1980,191150000000 -China,CHN,1981,195865079365.079 -China,CHN,1982,205091603053.435 -China,CHN,1983,230685823754.789 -China,CHN,1984,259946428571.429 -China,CHN,1985,309486394557.823 -China,CHN,1986,300759420289.855 -China,CHN,1987,272973094170.404 -China,CHN,1988,312353909465.021 -China,CHN,1989,347767206477.733 -China,CHN,1990,360858508604.206 -China,CHN,1991,383372822299.652 -China,CHN,1992,426915227629.513 -China,CHN,1993,444730903968.185 -China,CHN,1994,564325246266.838 -China,CHN,1995,734548001963.907 -China,CHN,1996,863746361646.34 -China,CHN,1997,961603416246.472 -China,CHN,1998,1029043011921.59 -China,CHN,1999,1093997559885.48 -China,CHN,2000,1211346395438.73 -China,CHN,2001,1339395440432.04 -China,CHN,2002,1470549716080.71 -China,CHN,2003,1660287543796.06 -China,CHN,2004,1955347477285.91 -China,CHN,2005,2285965854313.36 -China,CHN,2006,2752132089196.58 -China,CHN,2007,3552182714426.55 -China,CHN,2008,4598205419718.8 -China,CHN,2009,5109954035775.98 -China,CHN,2010,6100620356557.32 -China,CHN,2011,7572554360442.62 -China,CHN,2012,8560546868811.69 -China,CHN,2013,9607224248684.59 -China,CHN,2014,10482371325324.7 -China,CHN,2015,11064664793255.7 -China,CHN,2016,11199145157649.2 -Colombia,COL,1960,4040948153.73022 -Colombia,COL,1961,4552914000 -Colombia,COL,1962,4968603735.58222 -Colombia,COL,1963,4838841455.55556 -Colombia,COL,1964,5992169466.66667 -Colombia,COL,1965,5790247619.04762 -Colombia,COL,1966,5452762962.96296 -Colombia,COL,1967,5727195020.23203 -Colombia,COL,1968,5918455409.8099 -Colombia,COL,1969,6405427873.70755 -Colombia,COL,1970,7198360460.19887 -Colombia,COL,1971,7820380970.53674 -Colombia,COL,1972,8671358732.68486 -Colombia,COL,1973,10315760000.3394 -Colombia,COL,1974,12370029583.6419 -Colombia,COL,1975,13098633901.8673 -Colombia,COL,1976,15341403660.4698 -Colombia,COL,1977,19470960619.1297 -Colombia,COL,1978,23263511958.0509 -Colombia,COL,1979,27940411250.2732 -Colombia,COL,1980,33400735644.0481 -Colombia,COL,1981,36388366869.0309 -Colombia,COL,1982,38968039721.748 -Colombia,COL,1983,38729822781.5997 -Colombia,COL,1984,38253120737.9671 -Colombia,COL,1985,34894411351.983 -Colombia,COL,1986,34942489683.9712 -Colombia,COL,1987,36373307085.0887 -Colombia,COL,1988,39212550050.4223 -Colombia,COL,1989,39540080200.3938 -Colombia,COL,1990,40274204595.2296 -Colombia,COL,1991,41239551378.2482 -Colombia,COL,1992,49279585355.0948 -Colombia,COL,1993,55802538219.0264 -Colombia,COL,1994,81703500846.0364 -Colombia,COL,1995,92507279383.0387 -Colombia,COL,1996,97160109277.8087 -Colombia,COL,1997,106659508271.255 -Colombia,COL,1998,98443739941.1664 -Colombia,COL,1999,86186158684.7685 -Colombia,COL,2000,99886577330.7271 -Colombia,COL,2001,98203546156.3102 -Colombia,COL,2002,97933391976.083 -Colombia,COL,2003,94684584162.773 -Colombia,COL,2004,117074863821.85 -Colombia,COL,2005,146566264837.014 -Colombia,COL,2006,162590146096.414 -Colombia,COL,2007,207416494642.379 -Colombia,COL,2008,243982437870.84 -Colombia,COL,2009,233821670544.258 -Colombia,COL,2010,287018184637.529 -Colombia,COL,2011,335415156702.186 -Colombia,COL,2012,369659700375.52 -Colombia,COL,2013,380191881860.372 -Colombia,COL,2014,378195716714.266 -Colombia,COL,2015,291519591532.951 -Colombia,COL,2016,282462548889.26 -Comoros,COM,1980,123505640.914474 -Comoros,COM,1981,114271897.268272 -Comoros,COM,1982,107089552.302395 -Comoros,COM,1983,111519676.021905 -Comoros,COM,1984,107489822.704044 -Comoros,COM,1985,114490697.57503 -Comoros,COM,1986,162487763.894624 -Comoros,COM,1987,196433684.042405 -Comoros,COM,1988,207476554.806734 -Comoros,COM,1989,198733185.875107 -Comoros,COM,1990,250030760.754786 -Comoros,COM,1991,246823428.906664 -Comoros,COM,1992,266191040.373328 -Comoros,COM,1993,263568114.445462 -Comoros,COM,1994,185761822.560488 -Comoros,COM,1995,231896229.562629 -Comoros,COM,1996,230495751.446593 -Comoros,COM,1997,212099634.697751 -Comoros,COM,1998,215394066.068976 -Comoros,COM,1999,222580453.753844 -Comoros,COM,2000,203846427.738737 -Comoros,COM,2001,220093812.206791 -Comoros,COM,2002,246737679.472106 -Comoros,COM,2003,317562269.371106 -Comoros,COM,2004,368143118.68996 -Comoros,COM,2005,380372892.606774 -Comoros,COM,2006,406111873.539847 -Comoros,COM,2007,462453582.873627 -Comoros,COM,2008,523134896.968654 -Comoros,COM,2009,524157261.014644 -Comoros,COM,2010,530493353.218937 -Comoros,COM,2011,586281766.75997 -Comoros,COM,2012,570865941.229395 -Comoros,COM,2013,618663921.86116 -Comoros,COM,2014,647720707.076427 -Comoros,COM,2015,565689764.63263 -Comoros,COM,2016,616654490.471188 -"Congo, Dem. Rep.",COD,1960,3359404132.31797 -"Congo, Dem. Rep.",COD,1961,3086746936.39789 -"Congo, Dem. Rep.",COD,1962,3779841409.55267 -"Congo, Dem. Rep.",COD,1963,6213185773.92265 -"Congo, Dem. Rep.",COD,1964,2881545277.14307 -"Congo, Dem. Rep.",COD,1965,4043901724.13762 -"Congo, Dem. Rep.",COD,1966,4532660145.32842 -"Congo, Dem. Rep.",COD,1967,3384063359.82333 -"Congo, Dem. Rep.",COD,1968,3909780525.37375 -"Congo, Dem. Rep.",COD,1969,5032434970.84174 -"Congo, Dem. Rep.",COD,1970,4877684933.12505 -"Congo, Dem. Rep.",COD,1971,5594770351.56981 -"Congo, Dem. Rep.",COD,1972,6173712809.28569 -"Congo, Dem. Rep.",COD,1973,7870239463.58461 -"Congo, Dem. Rep.",COD,1974,9596960174.34365 -"Congo, Dem. Rep.",COD,1975,10237343153.4311 -"Congo, Dem. Rep.",COD,1976,9648583220.47256 -"Congo, Dem. Rep.",COD,1977,12344424775.9239 -"Congo, Dem. Rep.",COD,1978,15372607995.4061 -"Congo, Dem. Rep.",COD,1979,15068422242.0571 -"Congo, Dem. Rep.",COD,1980,14394927492.9647 -"Congo, Dem. Rep.",COD,1981,12537821039.8252 -"Congo, Dem. Rep.",COD,1982,13651667370.5466 -"Congo, Dem. Rep.",COD,1983,11006712649.2175 -"Congo, Dem. Rep.",COD,1984,7857729192.85629 -"Congo, Dem. Rep.",COD,1985,7195042615.84176 -"Congo, Dem. Rep.",COD,1986,8095367168.16178 -"Congo, Dem. Rep.",COD,1987,7661625472.51189 -"Congo, Dem. Rep.",COD,1988,8861299976.68858 -"Congo, Dem. Rep.",COD,1989,9021862775.25443 -"Congo, Dem. Rep.",COD,1990,9349764580.35198 -"Congo, Dem. Rep.",COD,1991,9087965281.52807 -"Congo, Dem. Rep.",COD,1992,8206227134.00857 -"Congo, Dem. Rep.",COD,1993,10707792340.0276 -"Congo, Dem. Rep.",COD,1994,5820383305.54668 -"Congo, Dem. Rep.",COD,1995,5643439262.21735 -"Congo, Dem. Rep.",COD,1996,5771454939.62404 -"Congo, Dem. Rep.",COD,1997,6090840548.18784 -"Congo, Dem. Rep.",COD,1998,6215591269.89747 -"Congo, Dem. Rep.",COD,1999,4711259427.27273 -"Congo, Dem. Rep.",COD,2000,19088046305.7971 -"Congo, Dem. Rep.",COD,2001,7438189100.33333 -"Congo, Dem. Rep.",COD,2002,8728038525.14034 -"Congo, Dem. Rep.",COD,2003,8937567059.87754 -"Congo, Dem. Rep.",COD,2004,10297483481.223 -"Congo, Dem. Rep.",COD,2005,11964484667.9102 -"Congo, Dem. Rep.",COD,2006,14296507096.4135 -"Congo, Dem. Rep.",COD,2007,16364029327.3457 -"Congo, Dem. Rep.",COD,2008,19206060270.2521 -"Congo, Dem. Rep.",COD,2009,18262773820.8055 -"Congo, Dem. Rep.",COD,2010,20523285374.187 -"Congo, Dem. Rep.",COD,2011,23849009737.6669 -"Congo, Dem. Rep.",COD,2012,27463220380.0054 -"Congo, Dem. Rep.",COD,2013,30014813755.772 -"Congo, Dem. Rep.",COD,2014,34028119332.6087 -"Congo, Dem. Rep.",COD,2015,36188521106.9294 -"Congo, Dem. Rep.",COD,2016,34998638634.1 -"Congo, Rep.",COG,1960,131731862.568997 -"Congo, Rep.",COG,1961,151675739.160627 -"Congo, Rep.",COG,1962,166521239.863281 -"Congo, Rep.",COG,1963,172233430.871502 -"Congo, Rep.",COG,1964,185693724.845331 -"Congo, Rep.",COG,1965,198318063.860835 -"Congo, Rep.",COG,1966,220613582.369827 -"Congo, Rep.",COG,1967,237397428.336429 -"Congo, Rep.",COG,1968,251247458.012189 -"Congo, Rep.",COG,1969,265040036.059116 -"Congo, Rep.",COG,1970,274960699.85855 -"Congo, Rep.",COG,1971,322128019.323561 -"Congo, Rep.",COG,1972,410669262.897929 -"Congo, Rep.",COG,1973,541973362.480998 -"Congo, Rep.",COG,1974,585364635.354748 -"Congo, Rep.",COG,1975,767102679.018622 -"Congo, Rep.",COG,1976,754549600.548182 -"Congo, Rep.",COG,1977,765224030.636552 -"Congo, Rep.",COG,1978,878771771.29105 -"Congo, Rep.",COG,1979,1198749665.95066 -"Congo, Rep.",COG,1980,1705796849.54655 -"Congo, Rep.",COG,1981,1993512325.92286 -"Congo, Rep.",COG,1982,2160640566.5396 -"Congo, Rep.",COG,1983,2097274289.61512 -"Congo, Rep.",COG,1984,2193581366.40722 -"Congo, Rep.",COG,1985,2160872541.41887 -"Congo, Rep.",COG,1986,1849268214.68184 -"Congo, Rep.",COG,1987,2297753649.2798 -"Congo, Rep.",COG,1988,2212536313.33492 -"Congo, Rep.",COG,1989,2389593021.94866 -"Congo, Rep.",COG,1990,2798746050.58236 -"Congo, Rep.",COG,1991,2724853507.63856 -"Congo, Rep.",COG,1992,2933222705.80382 -"Congo, Rep.",COG,1993,1918970177.74925 -"Congo, Rep.",COG,1994,1769365438.87155 -"Congo, Rep.",COG,1995,2116003868.17928 -"Congo, Rep.",COG,1996,2540697537.71673 -"Congo, Rep.",COG,1997,2322719101.29807 -"Congo, Rep.",COG,1998,1949481380.64044 -"Congo, Rep.",COG,1999,2353909441.71514 -"Congo, Rep.",COG,2000,3219910666.03357 -"Congo, Rep.",COG,2001,2794259783.08097 -"Congo, Rep.",COG,2002,3019993738.77492 -"Congo, Rep.",COG,2003,3495868808.0512 -"Congo, Rep.",COG,2004,4648628921.36969 -"Congo, Rep.",COG,2005,6087003176.11624 -"Congo, Rep.",COG,2006,7731261310.93322 -"Congo, Rep.",COG,2007,8394688284.06224 -"Congo, Rep.",COG,2008,11859014004.0772 -"Congo, Rep.",COG,2009,9593536531.23778 -"Congo, Rep.",COG,2010,12007880590.4575 -"Congo, Rep.",COG,2011,14425607224.168 -"Congo, Rep.",COG,2012,13677930123.5919 -"Congo, Rep.",COG,2013,14085852120.4761 -"Congo, Rep.",COG,2014,14177437627.2969 -"Congo, Rep.",COG,2015,8553154505.83693 -"Congo, Rep.",COG,2016,7833509443.39395 -Costa Rica,CRI,1960,507513829.994855 -Costa Rica,CRI,1961,490325181.614275 -Costa Rica,CRI,1962,479180824.348506 -Costa Rica,CRI,1963,511902136.809973 -Costa Rica,CRI,1964,542578367.242598 -Costa Rica,CRI,1965,592981162.264151 -Costa Rica,CRI,1966,647305630.188679 -Costa Rica,CRI,1967,699456618.867925 -Costa Rica,CRI,1968,773841494.339623 -Costa Rica,CRI,1969,853630203.773585 -Costa Rica,CRI,1970,984830158.490566 -Costa Rica,CRI,1971,1077152902.29104 -Costa Rica,CRI,1972,1238251695.55388 -Costa Rica,CRI,1973,1528916185.23199 -Costa Rica,CRI,1974,1666544754.09836 -Costa Rica,CRI,1975,1960863465.5776 -Costa Rica,CRI,1976,2412555425.90432 -Costa Rica,CRI,1977,3072427012.83547 -Costa Rica,CRI,1978,3523208809.80163 -Costa Rica,CRI,1979,4035519323.22054 -Costa Rica,CRI,1980,4831447001.16686 -Costa Rica,CRI,1981,2623807074.2948 -Costa Rica,CRI,1982,2606621255.01581 -Costa Rica,CRI,1983,3976453966.73983 -Costa Rica,CRI,1984,4593908718.76172 -Costa Rica,CRI,1985,4796628461.38614 -Costa Rica,CRI,1986,5477895474.91039 -Costa Rica,CRI,1987,5841132961.60586 -Costa Rica,CRI,1988,6063759370.62937 -Costa Rica,CRI,1989,6866402028.10997 -Costa Rica,CRI,1990,7403457319.20472 -Costa Rica,CRI,1991,7168999428.24471 -Costa Rica,CRI,1992,8528593084.48749 -Costa Rica,CRI,1993,9537297507.16915 -Costa Rica,CRI,1994,10432619390.3609 -Costa Rica,CRI,1995,11513472693.8707 -Costa Rica,CRI,1996,11618286553.3677 -Costa Rica,CRI,1997,12552071367.1539 -Costa Rica,CRI,1998,13617405420.1174 -Costa Rica,CRI,1999,14195623424.811 -Costa Rica,CRI,2000,14949514585.1585 -Costa Rica,CRI,2001,15913363335.0564 -Costa Rica,CRI,2002,16504795453.2822 -Costa Rica,CRI,2003,17195867540.353 -Costa Rica,CRI,2004,18529767934.4743 -Costa Rica,CRI,2005,19952156474.8454 -Costa Rica,CRI,2006,22600431878.0024 -Costa Rica,CRI,2007,26743874286.8514 -Costa Rica,CRI,2008,30612932802.8991 -Costa Rica,CRI,2009,30562361123.0307 -Costa Rica,CRI,2010,37268635287.0856 -Costa Rica,CRI,2011,42262697840.385 -Costa Rica,CRI,2012,46473128285.5589 -Costa Rica,CRI,2013,49745088111.6953 -Costa Rica,CRI,2014,50656002895.8763 -Costa Rica,CRI,2015,54840103850.265 -Costa Rica,CRI,2016,57435507212.256 -Cote d'Ivoire,CIV,1960,546203561.571989 -Cote d'Ivoire,CIV,1961,618245639.221382 -Cote d'Ivoire,CIV,1962,645284344.684118 -Cote d'Ivoire,CIV,1963,761047045.830402 -Cote d'Ivoire,CIV,1964,921063266.445521 -Cote d'Ivoire,CIV,1965,919771356.426097 -Cote d'Ivoire,CIV,1966,1024103034.29198 -Cote d'Ivoire,CIV,1967,1082922892.15202 -Cote d'Ivoire,CIV,1968,1281281245.67032 -Cote d'Ivoire,CIV,1969,1361360157.26999 -Cote d'Ivoire,CIV,1970,1455482990.24143 -Cote d'Ivoire,CIV,1971,1584128262.08933 -Cote d'Ivoire,CIV,1972,1849400599.77558 -Cote d'Ivoire,CIV,1973,2508421234.8557 -Cote d'Ivoire,CIV,1974,3070151901.06383 -Cote d'Ivoire,CIV,1975,3893839190.26806 -Cote d'Ivoire,CIV,1976,4662053707.7763 -Cote d'Ivoire,CIV,1977,6265067857.86534 -Cote d'Ivoire,CIV,1978,7900524897.8644 -Cote d'Ivoire,CIV,1979,9142935857.94766 -Cote d'Ivoire,CIV,1980,10175615441.8127 -Cote d'Ivoire,CIV,1981,8432588483.85263 -Cote d'Ivoire,CIV,1982,7567109766.61129 -Cote d'Ivoire,CIV,1983,6838185418.53642 -Cote d'Ivoire,CIV,1984,6841638714.5454 -Cote d'Ivoire,CIV,1985,6977650069.33578 -Cote d'Ivoire,CIV,1986,9158302205.36237 -Cote d'Ivoire,CIV,1987,10087653189.3287 -Cote d'Ivoire,CIV,1988,10255170459.986 -Cote d'Ivoire,CIV,1989,9757410614.0812 -Cote d'Ivoire,CIV,1990,10795850106.9547 -Cote d'Ivoire,CIV,1991,10492628915.4927 -Cote d'Ivoire,CIV,1992,11152971316.074 -Cote d'Ivoire,CIV,1993,11045759468.9412 -Cote d'Ivoire,CIV,1994,8313557450.25213 -Cote d'Ivoire,CIV,1995,11000146839.497 -Cote d'Ivoire,CIV,1996,12139234938.7863 -Cote d'Ivoire,CIV,1997,11722142706.1278 -Cote d'Ivoire,CIV,1998,12612033728.8572 -Cote d'Ivoire,CIV,1999,12376639822.9265 -Cote d'Ivoire,CIV,2000,10717022462.6859 -Cote d'Ivoire,CIV,2001,11192560827.2962 -Cote d'Ivoire,CIV,2002,12346919216.1359 -Cote d'Ivoire,CIV,2003,15306602560.2533 -Cote d'Ivoire,CIV,2004,16554441846.5192 -Cote d'Ivoire,CIV,2005,17084928927.4555 -Cote d'Ivoire,CIV,2006,17800887796.4987 -Cote d'Ivoire,CIV,2007,20343635319.6174 -Cote d'Ivoire,CIV,2008,24224903099.6283 -Cote d'Ivoire,CIV,2009,24277493862.0625 -Cote d'Ivoire,CIV,2010,24884505034.5564 -Cote d'Ivoire,CIV,2011,25381616734.0693 -Cote d'Ivoire,CIV,2012,27040562587.1771 -Cote d'Ivoire,CIV,2013,31273049200.243 -Cote d'Ivoire,CIV,2014,35372603446.2605 -Cote d'Ivoire,CIV,2015,32828516580.3451 -Cote d'Ivoire,CIV,2016,36164644633.0972 -Croatia,HRV,1995,22387561845.2244 -Croatia,HRV,1996,23678012697.3612 -Croatia,HRV,1997,23822087053.2091 -Croatia,HRV,1998,25432144406.2043 -Croatia,HRV,1999,23386945596.6928 -Croatia,HRV,2000,21774273832.1031 -Croatia,HRV,2001,23289671102.3197 -Croatia,HRV,2002,26878499206.0165 -Croatia,HRV,2003,34658113497.39 -Croatia,HRV,2004,41574530815.5047 -Croatia,HRV,2005,45416076680.8707 -Croatia,HRV,2006,50453577898.4886 -Croatia,HRV,2007,60093155532.7678 -Croatia,HRV,2008,70481451814.3118 -Croatia,HRV,2009,62703095750.5257 -Croatia,HRV,2010,59665427464.5326 -Croatia,HRV,2011,62236751773.0497 -Croatia,HRV,2012,56485301967.4205 -Croatia,HRV,2013,57769872074.883 -Croatia,HRV,2014,57080369367.8021 -Croatia,HRV,2015,48676334689.3545 -Croatia,HRV,2016,50425333970.0264 -Cuba,CUB,1970,5693005200 -Cuba,CUB,1971,6914658400 -Cuba,CUB,1972,8135150891.92025 -Cuba,CUB,1973,9987709650.18094 -Cuba,CUB,1974,11405957317.0732 -Cuba,CUB,1975,13027415243.9024 -Cuba,CUB,1976,13789579902.5579 -Cuba,CUB,1977,14206158674.6988 -Cuba,CUB,1978,17844705324.6753 -Cuba,CUB,1979,19584443287.6712 -Cuba,CUB,1980,19912889861.1111 -Cuba,CUB,1981,20150254096.3855 -Cuba,CUB,1982,20953510235.2941 -Cuba,CUB,1983,22204940512.2235 -Cuba,CUB,1984,24039383608.4235 -Cuba,CUB,1985,22920490774.102 -Cuba,CUB,1986,24226574634.0293 -Cuba,CUB,1987,25213935012.0819 -Cuba,CUB,1988,27458999472.2955 -Cuba,CUB,1989,27023468665.8977 -Cuba,CUB,1990,28645436569.1489 -Cuba,CUB,1991,24316556025.6585 -Cuba,CUB,1992,22085858243.2432 -Cuba,CUB,1993,22367254864.8649 -Cuba,CUB,1994,28448326756.7568 -Cuba,CUB,1995,30429803651.2192 -Cuba,CUB,1996,25017300000 -Cuba,CUB,1997,25366200000 -Cuba,CUB,1998,25736331247.1786 -Cuba,CUB,1999,28364615241.6894 -Cuba,CUB,2000,30565400000 -Cuba,CUB,2001,31682400000 -Cuba,CUB,2002,33590500000 -Cuba,CUB,2003,35901200000 -Cuba,CUB,2004,38203000000 -Cuba,CUB,2005,42643836074.8 -Cuba,CUB,2006,52742800000 -Cuba,CUB,2007,58603900000 -Cuba,CUB,2008,60806300000 -Cuba,CUB,2009,62080000000 -Cuba,CUB,2010,64328000000 -Cuba,CUB,2011,68990000000 -Cuba,CUB,2012,73141000000 -Cuba,CUB,2013,77148000000 -Cuba,CUB,2014,80656100000 -Cuba,CUB,2015,87132800000 -Cyprus,CYP,1975,489914760.682807 -Cyprus,CYP,1976,576090073.715036 -Cyprus,CYP,1977,734887973.975806 -Cyprus,CYP,1978,964026512.197839 -Cyprus,CYP,1979,1288715209.58084 -Cyprus,CYP,1980,2154311276.94859 -Cyprus,CYP,1981,2087496373.77964 -Cyprus,CYP,1982,2159242416.76942 -Cyprus,CYP,1983,2160364071.19021 -Cyprus,CYP,1984,2278248953.14058 -Cyprus,CYP,1985,2430411900.19194 -Cyprus,CYP,1986,3090734463.27684 -Cyprus,CYP,1987,3704813885.50548 -Cyprus,CYP,1988,4278792597.23965 -Cyprus,CYP,1989,4563482603.5503 -Cyprus,CYP,1990,5591130217.66965 -Cyprus,CYP,1991,5770197348.48485 -Cyprus,CYP,1992,6912150456.32334 -Cyprus,CYP,1993,6590291048.29211 -Cyprus,CYP,1994,7425703928.57143 -Cyprus,CYP,1995,9826778783.9586 -Cyprus,CYP,1996,9899623588.45671 -Cyprus,CYP,1997,9594298745.72406 -Cyprus,CYP,1998,10353506787.3303 -Cyprus,CYP,1999,10614455231.931 -Cyprus,CYP,2000,10183317624.8822 -Cyprus,CYP,2001,10567304189.4353 -Cyprus,CYP,2002,11618269230.7692 -Cyprus,CYP,2003,14576896942.2424 -Cyprus,CYP,2004,17422375000 -Cyprus,CYP,2005,18703146374.829 -Cyprus,CYP,2006,20403713461.2972 -Cyprus,CYP,2007,24077470572.1325 -Cyprus,CYP,2008,27839460963.8201 -Cyprus,CYP,2009,25942622950.8197 -Cyprus,CYP,2010,25562251655.6291 -Cyprus,CYP,2011,27427161523.4918 -Cyprus,CYP,2012,25012206090.1966 -Cyprus,CYP,2013,24054965480.616 -Cyprus,CYP,2014,23308212816.7706 -Cyprus,CYP,2015,19559942331.1523 -Cyprus,CYP,2016,19801664168.2788 -Czech Republic,CZE,1990,40315847383.7197 -Czech Republic,CZE,1991,29557058174.1697 -Czech Republic,CZE,1992,34451993226.0347 -Czech Republic,CZE,1993,40452245779.1651 -Czech Republic,CZE,1994,47364869195.7617 -Czech Republic,CZE,1995,59537113790.5049 -Czech Republic,CZE,1996,66775046785.4354 -Czech Republic,CZE,1997,61621364981.4187 -Czech Republic,CZE,1998,66372594575.1707 -Czech Republic,CZE,1999,64719461254.5271 -Czech Republic,CZE,2000,61474265134.5364 -Czech Republic,CZE,2001,67375623427.4642 -Czech Republic,CZE,2002,81696651658.8981 -Czech Republic,CZE,2003,99300329682.0164 -Czech Republic,CZE,2004,118976023159.713 -Czech Republic,CZE,2005,135990215966.674 -Czech Republic,CZE,2006,155213006071.979 -Czech Republic,CZE,2007,188818155388.125 -Czech Republic,CZE,2008,235204812643.146 -Czech Republic,CZE,2009,205729790694.015 -Czech Republic,CZE,2010,207016402026.364 -Czech Republic,CZE,2011,227948349666.354 -Czech Republic,CZE,2012,207376427020.815 -Czech Republic,CZE,2013,209402444996.104 -Czech Republic,CZE,2014,207818330723.835 -Czech Republic,CZE,2015,185156359571.116 -Czech Republic,CZE,2016,192924593987.295 -Denmark,DNK,1960,6248946880.2777 -Denmark,DNK,1961,6933842098.84548 -Denmark,DNK,1962,7812968114.40012 -Denmark,DNK,1963,8316692385.77386 -Denmark,DNK,1964,9506678762.77765 -Denmark,DNK,1965,10678897387.0006 -Denmark,DNK,1966,11721248101.0874 -Denmark,DNK,1967,12788479692.1939 -Denmark,DNK,1968,13196541952 -Denmark,DNK,1969,15009384584.5333 -Denmark,DNK,1970,17075466666.6667 -Denmark,DNK,1971,19085681968.1403 -Denmark,DNK,1972,23232411897.6012 -Denmark,DNK,1973,30730638895.7765 -Denmark,DNK,1974,34160363582.6675 -Denmark,DNK,1975,40474400473.3563 -Denmark,DNK,1976,44575847808.1059 -Denmark,DNK,1977,49784281716.4179 -Denmark,DNK,1978,60362854966.8154 -Denmark,DNK,1979,70366280174.8717 -Denmark,DNK,1980,71127592753.5975 -Denmark,DNK,1981,61877755004.6326 -Denmark,DNK,1982,60412846238.7787 -Denmark,DNK,1983,60644833242.2089 -Denmark,DNK,1984,59105208272.9853 -Denmark,DNK,1985,62658544411.3095 -Denmark,DNK,1986,88078729452.4781 -Denmark,DNK,1987,109414353171.645 -Denmark,DNK,1988,115552848547.872 -Denmark,DNK,1989,112409236409.401 -Denmark,DNK,1990,138247261092.977 -Denmark,DNK,1991,139224732275.463 -Denmark,DNK,1992,152915624326.966 -Denmark,DNK,1993,143195607581.857 -Denmark,DNK,1994,156162311731.598 -Denmark,DNK,1995,185006961302.299 -Denmark,DNK,1996,187632400365.599 -Denmark,DNK,1997,173537588008.176 -Denmark,DNK,1998,176992000955.11 -Denmark,DNK,1999,177965224620.854 -Denmark,DNK,2000,164158800460.219 -Denmark,DNK,2001,164791416350.267 -Denmark,DNK,2002,178635160297.415 -Denmark,DNK,2003,218095997085.477 -Denmark,DNK,2004,251373036671.062 -Denmark,DNK,2005,264467308109.19 -Denmark,DNK,2006,282884912894.33 -Denmark,DNK,2007,319423370134.284 -Denmark,DNK,2008,353361056079.716 -Denmark,DNK,2009,321241396034.248 -Denmark,DNK,2010,321995350346.501 -Denmark,DNK,2011,344003209695.606 -Denmark,DNK,2012,327148899962.146 -Denmark,DNK,2013,343584385594.132 -Denmark,DNK,2014,352296969840.949 -Denmark,DNK,2015,301307828843.613 -Denmark,DNK,2016,306142937248.09 -Djibouti,DJI,1985,340989527.967995 -Djibouti,DJI,1987,373371738.286415 -Djibouti,DJI,1988,395794538.630775 -Djibouti,DJI,1989,409220087.102818 -Djibouti,DJI,1990,452328087.282876 -Djibouti,DJI,1991,462421998.525779 -Djibouti,DJI,1992,478058304.871118 -Djibouti,DJI,1993,466048469.22986 -Djibouti,DJI,1994,491689220.744875 -Djibouti,DJI,1995,497723960.589913 -Djibouti,DJI,1996,494004647.73437 -Djibouti,DJI,1997,502675542.001227 -Djibouti,DJI,1998,514267869.300758 -Djibouti,DJI,1999,536080148.097299 -Djibouti,DJI,2000,551230861.856505 -Djibouti,DJI,2001,572417440.820162 -Djibouti,DJI,2002,591122039.601398 -Djibouti,DJI,2003,622044665.515049 -Djibouti,DJI,2004,666072101.777505 -Djibouti,DJI,2005,708633194.726566 -Djibouti,DJI,2006,768873684.032838 -Djibouti,DJI,2007,847918929.107984 -Djibouti,DJI,2008,999105339.267729 -Djibouti,DJI,2009,1049110684.72493 -Djibouti,DJI,2010,1128611700.3618 -Djibouti,DJI,2011,1239144501.77525 -Djibouti,DJI,2012,1353632941.5207 -Djibouti,DJI,2013,1455000000 -Djibouti,DJI,2014,1588000000 -Djibouti,DJI,2015,1727000000 -Dominica,DMA,1977,36370370.3703704 -Dominica,DMA,1978,45170370.3703704 -Dominica,DMA,1979,44296296.2962963 -Dominica,DMA,1980,59100000 -Dominica,DMA,1981,66218518.5185185 -Dominica,DMA,1982,72051851.8518518 -Dominica,DMA,1983,79925925.9259259 -Dominica,DMA,1984,89848148.1481481 -Dominica,DMA,1985,98585185.1851852 -Dominica,DMA,1986,112074074.074074 -Dominica,DMA,1987,126348148.148148 -Dominica,DMA,1988,143766666.666667 -Dominica,DMA,1989,153374074.074074 -Dominica,DMA,1990,166322222.222222 -Dominica,DMA,1991,180437037.037037 -Dominica,DMA,1992,191759259.259259 -Dominica,DMA,1993,200418518.518519 -Dominica,DMA,1994,215459259.259259 -Dominica,DMA,1995,224037037.037037 -Dominica,DMA,1996,236444444.444444 -Dominica,DMA,1997,245781481.481481 -Dominica,DMA,1998,258440740.740741 -Dominica,DMA,1999,267740740.740741 -Dominica,DMA,2000,335845814.814815 -Dominica,DMA,2001,343119370.37037 -Dominica,DMA,2002,337695740.740741 -Dominica,DMA,2003,350091222.222222 -Dominica,DMA,2004,374771481.481481 -Dominica,DMA,2005,370370370.37037 -Dominica,DMA,2006,390370370.37037 -Dominica,DMA,2007,421375851.851852 -Dominica,DMA,2008,458190185.185185 -Dominica,DMA,2009,489074333.333333 -Dominica,DMA,2010,493824407.407407 -Dominica,DMA,2011,500988407.407407 -Dominica,DMA,2012,485905592.592593 -Dominica,DMA,2013,508447148.148148 -Dominica,DMA,2014,528178703.703704 -Dominica,DMA,2015,517218962.962963 -Dominica,DMA,2016,525424630 -Dominican Republic,DOM,1960,672399700 -Dominican Republic,DOM,1961,654100200 -Dominican Republic,DOM,1962,824100000 -Dominican Republic,DOM,1963,940799900 -Dominican Republic,DOM,1964,1025599900 -Dominican Republic,DOM,1965,888100000 -Dominican Republic,DOM,1966,983900000 -Dominican Republic,DOM,1967,1034800000 -Dominican Republic,DOM,1968,1079100000 -Dominican Republic,DOM,1969,1230500000 -Dominican Republic,DOM,1970,1485400100 -Dominican Republic,DOM,1971,1666400000 -Dominican Republic,DOM,1972,1987300000 -Dominican Republic,DOM,1973,2344699900 -Dominican Republic,DOM,1974,2925600000 -Dominican Republic,DOM,1975,3599300100 -Dominican Republic,DOM,1976,3951399900 -Dominican Republic,DOM,1977,4587100200 -Dominican Republic,DOM,1978,4774400000 -Dominican Republic,DOM,1979,5498800100 -Dominican Republic,DOM,1980,6631000100 -Dominican Republic,DOM,1981,7266999800 -Dominican Republic,DOM,1982,7964000300 -Dominican Republic,DOM,1983,8622000100 -Dominican Republic,DOM,1984,10330399700 -Dominican Republic,DOM,1985,5044592912.6775 -Dominican Republic,DOM,1986,6122197810.14358 -Dominican Republic,DOM,1987,5826987203.49563 -Dominican Republic,DOM,1988,5374315190.18405 -Dominican Republic,DOM,1989,6686592728.70663 -Dominican Republic,DOM,1990,7073674721.12418 -Dominican Republic,DOM,1991,9724402004.34906 -Dominican Republic,DOM,1992,11277676879.9612 -Dominican Republic,DOM,1993,12976408000 -Dominican Republic,DOM,1994,14511134920.6349 -Dominican Republic,DOM,1995,16358496124.031 -Dominican Republic,DOM,1996,18131813000.6281 -Dominican Republic,DOM,1997,19593869595.0191 -Dominican Republic,DOM,1998,21171523985.0642 -Dominican Republic,DOM,1999,21709726722.118 -Dominican Republic,DOM,2000,23996063503.0497 -Dominican Republic,DOM,2001,24892521236.9553 -Dominican Republic,DOM,2002,26571620978.7885 -Dominican Republic,DOM,2003,21277165885.6865 -Dominican Republic,DOM,2004,22039232609.9553 -Dominican Republic,DOM,2005,34004033803.9438 -Dominican Republic,DOM,2006,35952845582.5029 -Dominican Republic,DOM,2007,44169678153.1566 -Dominican Republic,DOM,2008,48288967303.4896 -Dominican Republic,DOM,2009,48376555305.6902 -Dominican Republic,DOM,2010,53954579003.5277 -Dominican Republic,DOM,2011,57746684847.0898 -Dominican Republic,DOM,2012,60613645121.3529 -Dominican Republic,DOM,2013,61965942056.6828 -Dominican Republic,DOM,2014,65231032303.2418 -Dominican Republic,DOM,2015,68102618092.1031 -Dominican Republic,DOM,2016,71583553488.0804 -Ecuador,ECU,1960,1010325138.03016 -Ecuador,ECU,1961,979108806.848646 -Ecuador,ECU,1962,958598195.033967 -Ecuador,ECU,1963,1038389642.31418 -Ecuador,ECU,1964,1156150890.06133 -Ecuador,ECU,1965,2387048255.45173 -Ecuador,ECU,1966,2429309513.80854 -Ecuador,ECU,1967,2553596091.82258 -Ecuador,ECU,1968,2582180794.1855 -Ecuador,ECU,1969,3112166848.3004 -Ecuador,ECU,1970,2862504169.99893 -Ecuador,ECU,1971,2754220263.02528 -Ecuador,ECU,1972,3185987234.84089 -Ecuador,ECU,1973,3891755551.94138 -Ecuador,ECU,1974,6599259420.99605 -Ecuador,ECU,1975,7731677256.80982 -Ecuador,ECU,1976,9091924304.83477 -Ecuador,ECU,1977,11026346589.5011 -Ecuador,ECU,1978,11922502170.6405 -Ecuador,ECU,1979,14175166007.5774 -Ecuador,ECU,1980,17881514682.8784 -Ecuador,ECU,1981,21810767209.3695 -Ecuador,ECU,1982,19929853574.6095 -Ecuador,ECU,1983,17152483214.3536 -Ecuador,ECU,1984,16912515183.2783 -Ecuador,ECU,1985,17149094589.9827 -Ecuador,ECU,1986,15314143988.0621 -Ecuador,ECU,1987,13945431882.2271 -Ecuador,ECU,1988,13051886552.3377 -Ecuador,ECU,1989,13890828707.6493 -Ecuador,ECU,1990,15239278100.3502 -Ecuador,ECU,1991,16988535267.6338 -Ecuador,ECU,1992,18094238119.0595 -Ecuador,ECU,1993,18938717358.6793 -Ecuador,ECU,1994,22708673336.6683 -Ecuador,ECU,1995,24432884442.2211 -Ecuador,ECU,1996,25226393196.5983 -Ecuador,ECU,1997,28162053026.5133 -Ecuador,ECU,1998,27981896948.4742 -Ecuador,ECU,1999,19645272636.3182 -Ecuador,ECU,2000,18327764882.4412 -Ecuador,ECU,2001,24468324000 -Ecuador,ECU,2002,28548945000 -Ecuador,ECU,2003,32432859000 -Ecuador,ECU,2004,36591661000 -Ecuador,ECU,2005,41507085000 -Ecuador,ECU,2006,46802044000 -Ecuador,ECU,2007,51007777000 -Ecuador,ECU,2008,61762635000 -Ecuador,ECU,2009,62519686000 -Ecuador,ECU,2010,69555367000 -Ecuador,ECU,2011,79276664000 -Ecuador,ECU,2012,87924544000 -Ecuador,ECU,2013,95129659000 -Ecuador,ECU,2014,102292260000 -Ecuador,ECU,2015,100176808000 -Ecuador,ECU,2016,97802211000 -"Egypt, Arab Rep.",EGY,1965,5111621013.54303 -"Egypt, Arab Rep.",EGY,1966,5339520612.99374 -"Egypt, Arab Rep.",EGY,1967,5579168509.50907 -"Egypt, Arab Rep.",EGY,1968,6109112149.53271 -"Egypt, Arab Rep.",EGY,1969,6861743341.40436 -"Egypt, Arab Rep.",EGY,1970,7682491836.22206 -"Egypt, Arab Rep.",EGY,1971,8266003570.51773 -"Egypt, Arab Rep.",EGY,1972,8763960703.20579 -"Egypt, Arab Rep.",EGY,1973,9616725366.34664 -"Egypt, Arab Rep.",EGY,1974,9015166839.80885 -"Egypt, Arab Rep.",EGY,1975,11437965585.2696 -"Egypt, Arab Rep.",EGY,1976,13360476861.9662 -"Egypt, Arab Rep.",EGY,1977,14636028766.883 -"Egypt, Arab Rep.",EGY,1978,14849909490.6004 -"Egypt, Arab Rep.",EGY,1979,18150000571.4286 -"Egypt, Arab Rep.",EGY,1980,22912500555.5556 -"Egypt, Arab Rep.",EGY,1981,23405404729.7297 -"Egypt, Arab Rep.",EGY,1982,25592365394.0887 -"Egypt, Arab Rep.",EGY,1983,28137369499.4179 -"Egypt, Arab Rep.",EGY,1984,30642873038.0563 -"Egypt, Arab Rep.",EGY,1985,34689560464.8728 -"Egypt, Arab Rep.",EGY,1986,35880262675.3976 -"Egypt, Arab Rep.",EGY,1987,40507934171.249 -"Egypt, Arab Rep.",EGY,1988,35044634014.7643 -"Egypt, Arab Rep.",EGY,1989,39648442534.0768 -"Egypt, Arab Rep.",EGY,1990,43130416913.4141 -"Egypt, Arab Rep.",EGY,1991,36970555898.9698 -"Egypt, Arab Rep.",EGY,1992,41855986519.4235 -"Egypt, Arab Rep.",EGY,1993,46578631452.581 -"Egypt, Arab Rep.",EGY,1994,51897983392.6453 -"Egypt, Arab Rep.",EGY,1995,60159245060.4542 -"Egypt, Arab Rep.",EGY,1996,67629716981.1321 -"Egypt, Arab Rep.",EGY,1997,78436578171.0914 -"Egypt, Arab Rep.",EGY,1998,84828807556.0803 -"Egypt, Arab Rep.",EGY,1999,90710704806.8416 -"Egypt, Arab Rep.",EGY,2000,99838543960.0763 -"Egypt, Arab Rep.",EGY,2001,97632008709.853 -"Egypt, Arab Rep.",EGY,2002,87850683978.6691 -"Egypt, Arab Rep.",EGY,2003,82924503942.6381 -"Egypt, Arab Rep.",EGY,2004,78845185293.4964 -"Egypt, Arab Rep.",EGY,2005,89685725230.2517 -"Egypt, Arab Rep.",EGY,2006,107484034870.974 -"Egypt, Arab Rep.",EGY,2007,130478960092.499 -"Egypt, Arab Rep.",EGY,2008,162818181818.182 -"Egypt, Arab Rep.",EGY,2009,188982374700.805 -"Egypt, Arab Rep.",EGY,2010,218888324504.753 -"Egypt, Arab Rep.",EGY,2011,236001858960.015 -"Egypt, Arab Rep.",EGY,2012,279372758361.832 -"Egypt, Arab Rep.",EGY,2013,288586231501.877 -"Egypt, Arab Rep.",EGY,2014,305529656458.438 -"Egypt, Arab Rep.",EGY,2015,332698041030.807 -"Egypt, Arab Rep.",EGY,2016,336296921758.782 -El Salvador,SLV,1965,877720000 -El Salvador,SLV,1966,929520000 -El Salvador,SLV,1967,976200000 -El Salvador,SLV,1968,1009760100 -El Salvador,SLV,1969,1049400000 -El Salvador,SLV,1970,1132920000 -El Salvador,SLV,1971,1186120000 -El Salvador,SLV,1972,1263720000 -El Salvador,SLV,1973,1442320000 -El Salvador,SLV,1974,1665880000 -El Salvador,SLV,1975,1884120100 -El Salvador,SLV,1976,2328280100 -El Salvador,SLV,1977,2941640100 -El Salvador,SLV,1978,3127960000 -El Salvador,SLV,1979,3463639900 -El Salvador,SLV,1980,3573959900 -El Salvador,SLV,1981,3437200200 -El Salvador,SLV,1982,3399189100 -El Salvador,SLV,1983,3506347800 -El Salvador,SLV,1984,3661683400 -El Salvador,SLV,1985,3800368600 -El Salvador,SLV,1986,3771663200 -El Salvador,SLV,1987,3958045800 -El Salvador,SLV,1988,4189880000 -El Salvador,SLV,1989,4372215300 -El Salvador,SLV,1990,4800900000 -El Salvador,SLV,1991,5311000000 -El Salvador,SLV,1992,5954700000 -El Salvador,SLV,1993,6938000000 -El Salvador,SLV,1994,8085600000 -El Salvador,SLV,1995,9500500000 -El Salvador,SLV,1996,10315500000 -El Salvador,SLV,1997,11134700000 -El Salvador,SLV,1998,12008400000 -El Salvador,SLV,1999,12464700000 -El Salvador,SLV,2000,13134100000 -El Salvador,SLV,2001,13812700000 -El Salvador,SLV,2002,14306700000 -El Salvador,SLV,2003,15046700000 -El Salvador,SLV,2004,15798300000 -El Salvador,SLV,2005,17093800000 -El Salvador,SLV,2006,18550700000 -El Salvador,SLV,2007,20104900000 -El Salvador,SLV,2008,21430950000 -El Salvador,SLV,2009,20661030000 -El Salvador,SLV,2010,21418330000 -El Salvador,SLV,2011,23139040000 -El Salvador,SLV,2012,23813600000 -El Salvador,SLV,2013,24350930000 -El Salvador,SLV,2014,25054230000 -El Salvador,SLV,2015,26052340000 -El Salvador,SLV,2016,26797470000 -Equatorial Guinea,GNQ,1962,9122751.45318345 -Equatorial Guinea,GNQ,1963,10840095.1283649 -Equatorial Guinea,GNQ,1964,12712471.3960211 -Equatorial Guinea,GNQ,1965,64748333.3333333 -Equatorial Guinea,GNQ,1966,69110000 -Equatorial Guinea,GNQ,1967,72317446.9327193 -Equatorial Guinea,GNQ,1968,67514285.7142857 -Equatorial Guinea,GNQ,1969,67225714.2857143 -Equatorial Guinea,GNQ,1970,66331428.5714286 -Equatorial Guinea,GNQ,1971,64946954.756798 -Equatorial Guinea,GNQ,1972,65429198.238708 -Equatorial Guinea,GNQ,1973,81203226.9138345 -Equatorial Guinea,GNQ,1974,94159862.7073691 -Equatorial Guinea,GNQ,1975,104295643.388437 -Equatorial Guinea,GNQ,1976,103653049.93797 -Equatorial Guinea,GNQ,1977,103987520.075827 -Equatorial Guinea,GNQ,1980,50642880.7737503 -Equatorial Guinea,GNQ,1981,36731422.8456914 -Equatorial Guinea,GNQ,1982,44294647.733479 -Equatorial Guinea,GNQ,1983,44442456.94764 -Equatorial Guinea,GNQ,1984,50320914.4065688 -Equatorial Guinea,GNQ,1985,62118564.8495425 -Equatorial Guinea,GNQ,1986,76407396.7552964 -Equatorial Guinea,GNQ,1987,93345847.7270323 -Equatorial Guinea,GNQ,1988,100534663.294927 -Equatorial Guinea,GNQ,1989,88265974.5843603 -Equatorial Guinea,GNQ,1990,112119406.548331 -Equatorial Guinea,GNQ,1991,110906032.075075 -Equatorial Guinea,GNQ,1992,134707184.355541 -Equatorial Guinea,GNQ,1993,136047896.155778 -Equatorial Guinea,GNQ,1994,100807001.813926 -Equatorial Guinea,GNQ,1995,141853368.256815 -Equatorial Guinea,GNQ,1996,232463036.435759 -Equatorial Guinea,GNQ,1997,442337849.474377 -Equatorial Guinea,GNQ,1998,370687618.717326 -Equatorial Guinea,GNQ,1999,621117885.668503 -Equatorial Guinea,GNQ,2000,1045998496.43872 -Equatorial Guinea,GNQ,2001,1461139022.02954 -Equatorial Guinea,GNQ,2002,1806742742.27311 -Equatorial Guinea,GNQ,2003,2484745935.09329 -Equatorial Guinea,GNQ,2004,4410764338.66733 -Equatorial Guinea,GNQ,2005,8217369092.65224 -Equatorial Guinea,GNQ,2006,10086528698.8604 -Equatorial Guinea,GNQ,2007,13071718758.7373 -Equatorial Guinea,GNQ,2008,19749893536.3204 -Equatorial Guinea,GNQ,2009,15027795173.2187 -Equatorial Guinea,GNQ,2010,16298542027.9965 -Equatorial Guinea,GNQ,2011,21329395900.871 -Equatorial Guinea,GNQ,2012,22389627294.4179 -Equatorial Guinea,GNQ,2013,21942597765.3631 -Equatorial Guinea,GNQ,2014,21461989483.1265 -Equatorial Guinea,GNQ,2015,12162117377.3923 -Equatorial Guinea,GNQ,2016,10178967206.0184 -Eritrea,ERI,1992,477101651.648376 -Eritrea,ERI,1993,467872714.755603 -Eritrea,ERI,1994,531688311.688312 -Eritrea,ERI,1995,578015625 -Eritrea,ERI,1996,693535954.190067 -Eritrea,ERI,1997,686490090.140141 -Eritrea,ERI,1998,745526154.93283 -Eritrea,ERI,1999,688921325.712043 -Eritrea,ERI,2000,706370815.584416 -Eritrea,ERI,2001,752368495.512622 -Eritrea,ERI,2002,729321366.651861 -Eritrea,ERI,2003,870247703.182758 -Eritrea,ERI,2004,1109054005.43971 -Eritrea,ERI,2005,1098425900.74116 -Eritrea,ERI,2006,1211161879.6748 -Eritrea,ERI,2007,1317974491.05691 -Eritrea,ERI,2008,1380188800 -Eritrea,ERI,2009,1856695551.21951 -Eritrea,ERI,2010,2117039512.19512 -Eritrea,ERI,2011,2607739837.39837 -Estonia,EST,1995,4373665145.55468 -Estonia,EST,1996,4746109767.1999 -Estonia,EST,1997,5066240419.29666 -Estonia,EST,1998,5617109244.63233 -Estonia,EST,1999,5726897998.29642 -Estonia,EST,2000,5685774808.80862 -Estonia,EST,2001,6245069734.13302 -Estonia,EST,2002,7322069511.16134 -Estonia,EST,2003,9833870709.12376 -Estonia,EST,2004,12059201242.236 -Estonia,EST,2005,14006088297.4754 -Estonia,EST,2006,16963625015.6818 -Estonia,EST,2007,22237061730.0849 -Estonia,EST,2008,24194039255.8957 -Estonia,EST,2009,19652492636.8436 -Estonia,EST,2010,19490936349.1753 -Estonia,EST,2011,23170239900.7654 -Estonia,EST,2012,23043864510.0543 -Estonia,EST,2013,25081185830.6876 -Estonia,EST,2014,26213940386.7883 -Estonia,EST,2015,22460470490.0133 -Estonia,EST,2016,23136741984.155 -Ethiopia,ETH,1981,7324903188.4058 -Ethiopia,ETH,1982,7707678019.32367 -Ethiopia,ETH,1983,8567890821.25604 -Ethiopia,ETH,1984,8096302367.14976 -Ethiopia,ETH,1985,9480840483.09179 -Ethiopia,ETH,1986,9848600869.56522 -Ethiopia,ETH,1987,10527338647.343 -Ethiopia,ETH,1988,10908935748.7923 -Ethiopia,ETH,1989,11476584879.2271 -Ethiopia,ETH,1990,12175166763.285 -Ethiopia,ETH,1991,13463868357.4879 -Ethiopia,ETH,1992,10492993077.6093 -Ethiopia,ETH,1993,8830712713.90781 -Ethiopia,ETH,1994,6927950564.55657 -Ethiopia,ETH,1995,7663984567.90123 -Ethiopia,ETH,1996,8547939730.62374 -Ethiopia,ETH,1997,8589211390.49612 -Ethiopia,ETH,1998,7818224905.55071 -Ethiopia,ETH,1999,7700833482.00615 -Ethiopia,ETH,2000,8242392103.68061 -Ethiopia,ETH,2001,8231326016.47494 -Ethiopia,ETH,2002,7850809498.16803 -Ethiopia,ETH,2003,8623691300.04079 -Ethiopia,ETH,2004,10131187261.4421 -Ethiopia,ETH,2005,12401139453.9738 -Ethiopia,ETH,2006,15280861834.6024 -Ethiopia,ETH,2007,19707616772.7996 -Ethiopia,ETH,2008,27066912635.2228 -Ethiopia,ETH,2009,32437389116.038 -Ethiopia,ETH,2010,29933790334.3418 -Ethiopia,ETH,2011,31952763089.33 -Ethiopia,ETH,2012,43310721414.0829 -Ethiopia,ETH,2013,47648211133.2183 -Ethiopia,ETH,2014,55612228233.5179 -Ethiopia,ETH,2015,64464423674.6569 -Ethiopia,ETH,2016,72374252815.3782 -Faroe Islands,FRO,1998,1105688872.97039 -Faroe Islands,FRO,1999,1125684470.05533 -Faroe Islands,FRO,2000,1062339943.83343 -Faroe Islands,FRO,2001,1154899793.33878 -Faroe Islands,FRO,2002,1268445919.41429 -Faroe Islands,FRO,2003,1486861878.95624 -Faroe Islands,FRO,2004,1683997930.26322 -Faroe Islands,FRO,2005,1730891409.07567 -Faroe Islands,FRO,2006,1970142377.91507 -Faroe Islands,FRO,2007,2278229533.05096 -Faroe Islands,FRO,2008,2413237402.14803 -Faroe Islands,FRO,2009,2257097731.55019 -Faroe Islands,FRO,2010,2301178416.00619 -Faroe Islands,FRO,2011,2468748767.9772 -Faroe Islands,FRO,2012,2356505419.09755 -Faroe Islands,FRO,2013,2613458942.48139 -Fiji,FJI,1960,112328422.113084 -Fiji,FJI,1961,116987784.913739 -Fiji,FJI,1962,122906434.957814 -Fiji,FJI,1963,129454728.623599 -Fiji,FJI,1964,140032741.468329 -Fiji,FJI,1965,147084750.031482 -Fiji,FJI,1966,150603925.515853 -Fiji,FJI,1967,162625885.863484 -Fiji,FJI,1968,166952937.135005 -Fiji,FJI,1969,182182067.703568 -Fiji,FJI,1970,219878482.173564 -Fiji,FJI,1971,247749327.721267 -Fiji,FJI,1972,316650508.967523 -Fiji,FJI,1973,425963359.355326 -Fiji,FJI,1974,558589870.903674 -Fiji,FJI,1975,684268280.812751 -Fiji,FJI,1976,694552411.718837 -Fiji,FJI,1977,719533137.126662 -Fiji,FJI,1978,829239489.844119 -Fiji,FJI,1979,1019743927.24662 -Fiji,FJI,1980,1202567359.4132 -Fiji,FJI,1981,1235899836.18067 -Fiji,FJI,1982,1194015444.01544 -Fiji,FJI,1983,1123107276.30285 -Fiji,FJI,1984,1177997413.63384 -Fiji,FJI,1985,1141210124.82663 -Fiji,FJI,1986,1290228616.82408 -Fiji,FJI,1987,1177908191.97685 -Fiji,FJI,1988,1109976927.91722 -Fiji,FJI,1989,1182686577.22645 -Fiji,FJI,1990,1337024782.22702 -Fiji,FJI,1991,1383843860.1247 -Fiji,FJI,1992,1531803060.54558 -Fiji,FJI,1993,1635426125.30808 -Fiji,FJI,1994,1825285158.11762 -Fiji,FJI,1995,1970347720.96992 -Fiji,FJI,1996,2129266728.42585 -Fiji,FJI,1997,2093994597.21549 -Fiji,FJI,1998,1656784779.545 -Fiji,FJI,1999,1942170999.18765 -Fiji,FJI,2000,1684109743.49338 -Fiji,FJI,2001,1660102345.60309 -Fiji,FJI,2002,1842691481.09196 -Fiji,FJI,2003,2315935752.71653 -Fiji,FJI,2004,2727507212.92556 -Fiji,FJI,2005,3006725014.78415 -Fiji,FJI,2006,3102741451.01664 -Fiji,FJI,2007,3405050611.68726 -Fiji,FJI,2008,3523185919.55826 -Fiji,FJI,2009,2870624635.68032 -Fiji,FJI,2010,3140508835.9485 -Fiji,FJI,2011,3774530615.65916 -Fiji,FJI,2012,3972012570.53467 -Fiji,FJI,2013,4190143206.25611 -Fiji,FJI,2014,4469810099.08335 -Fiji,FJI,2015,4391064780.77249 -Fiji,FJI,2016,4631626233.96998 -Finland,FIN,1960,5224102195.52771 -Finland,FIN,1961,5921659485.03284 -Finland,FIN,1962,6340580854.39073 -Finland,FIN,1963,6885920328.66187 -Finland,FIN,1964,7766655085.78588 -Finland,FIN,1965,8589340019.02985 -Finland,FIN,1966,9208524504.87684 -Finland,FIN,1967,9368954010.3132 -Finland,FIN,1968,8823033880.32993 -Finland,FIN,1969,10070766720.5011 -Finland,FIN,1970,11365953567.3839 -Finland,FIN,1971,12536710287.0134 -Finland,FIN,1972,14754136507.0261 -Finland,FIN,1973,19486826979.9284 -Finland,FIN,1974,24867278714.3532 -Finland,FIN,1975,29494515597.22 -Finland,FIN,1976,31873171718.726 -Finland,FIN,1977,33524682307.8058 -Finland,FIN,1978,36283091407.9422 -Finland,FIN,1979,44498283620.8213 -Finland,FIN,1980,53685049410.2646 -Finland,FIN,1981,52485533204.7396 -Finland,FIN,1982,52832120389.7866 -Finland,FIN,1983,51014090520.9223 -Finland,FIN,1984,52926394934.7052 -Finland,FIN,1985,55914236377.5902 -Finland,FIN,1986,73586676049.7302 -Finland,FIN,1987,91642093872.5822 -Finland,FIN,1988,109103056147.832 -Finland,FIN,1989,119064708327.56 -Finland,FIN,1990,141517648888.198 -Finland,FIN,1991,127866490222.026 -Finland,FIN,1992,112625431377.754 -Finland,FIN,1993,89255751014.885 -Finland,FIN,1994,103321570859.419 -Finland,FIN,1995,134199346405.229 -Finland,FIN,1996,132099404607.818 -Finland,FIN,1997,126833123353.568 -Finland,FIN,1998,133936359590.565 -Finland,FIN,1999,135225868314.511 -Finland,FIN,2000,125539893126.958 -Finland,FIN,2001,129250111856.823 -Finland,FIN,2002,139552983248.635 -Finland,FIN,2003,171071106094.808 -Finland,FIN,2004,196768065557.487 -Finland,FIN,2005,204436015420.968 -Finland,FIN,2006,216552502822.732 -Finland,FIN,2007,255384615384.615 -Finland,FIN,2008,283742493042.332 -Finland,FIN,2009,251499027507.641 -Finland,FIN,2010,247799815768.477 -Finland,FIN,2011,273674236772.815 -Finland,FIN,2012,256706466091.089 -Finland,FIN,2013,269980111642.898 -Finland,FIN,2014,272609288689.575 -Finland,FIN,2015,232361689855.142 -Finland,FIN,2016,236785046710.878 -France,FRA,1960,62651474946.6007 -France,FRA,1961,68346741504.4257 -France,FRA,1962,76313782251.6964 -France,FRA,1963,85551113767.3727 -France,FRA,1964,94906593388.3107 -France,FRA,1965,102160571409.274 -France,FRA,1966,110597467198.645 -France,FRA,1967,119466139619.589 -France,FRA,1968,129847107787.883 -France,FRA,1969,140725497222.277 -France,FRA,1970,148948860281.091 -France,FRA,1971,166564460755.298 -France,FRA,1972,204283485045.514 -France,FRA,1973,265381555686.506 -France,FRA,1974,286526186579.378 -France,FRA,1975,362000917852.226 -France,FRA,1976,373410270417.919 -France,FRA,1977,411464295266.114 -France,FRA,1978,508183139534.884 -France,FRA,1979,615834104224.484 -France,FRA,1980,703525302701.025 -France,FRA,1981,617589619794.81 -France,FRA,1982,586837009681.605 -France,FRA,1983,561852138738.274 -France,FRA,1984,532648802822.187 -France,FRA,1985,555197109067.017 -France,FRA,1986,774556302680.178 -France,FRA,1987,938368438284.405 -France,FRA,1988,1023504019381.13 -France,FRA,1989,1030122352457.33 -France,FRA,1990,1275300566196.84 -France,FRA,1991,1275563306592.26 -France,FRA,1992,1408724907063.2 -France,FRA,1993,1330094973361.13 -France,FRA,1994,1401636342155.01 -France,FRA,1995,1609892232882.11 -France,FRA,1996,1614245416078.98 -France,FRA,1997,1460709148123.17 -France,FRA,1998,1510758283299.98 -France,FRA,1999,1500275942893.67 -France,FRA,2000,1368438363736.87 -France,FRA,2001,1382218344519.02 -France,FRA,2002,1500337850555.24 -France,FRA,2003,1848124153498.87 -France,FRA,2004,2124112242364.04 -France,FRA,2005,2203678646934.46 -France,FRA,2006,2325011918203.49 -France,FRA,2007,2663112510265.54 -France,FRA,2008,2923465651091.26 -France,FRA,2009,2693827452070.02 -France,FRA,2010,2646837111794.78 -France,FRA,2011,2862680142625.14 -France,FRA,2012,2681416108537.39 -France,FRA,2013,2808511203185.39 -France,FRA,2014,2849305322684.76 -France,FRA,2015,2433562015516.21 -France,FRA,2016,2465453975282.24 -French Polynesia,PYF,1965,176534589.603389 -French Polynesia,PYF,1966,215659455.017302 -French Polynesia,PYF,1967,220984369.12915 -French Polynesia,PYF,1968,259590076.293001 -French Polynesia,PYF,1969,242943776.862299 -French Polynesia,PYF,1970,254035999.217197 -French Polynesia,PYF,1971,296613496.873269 -French Polynesia,PYF,1972,325843254.667123 -French Polynesia,PYF,1973,431254103.046477 -French Polynesia,PYF,1974,555337985.682991 -French Polynesia,PYF,1975,690319754.911192 -French Polynesia,PYF,1976,732286143.34291 -French Polynesia,PYF,1977,793193187.41557 -French Polynesia,PYF,1978,1005573294.20763 -French Polynesia,PYF,1979,1215031775.26795 -French Polynesia,PYF,1980,1362151523.68993 -French Polynesia,PYF,1981,1279972866.38172 -French Polynesia,PYF,1982,1286462642.63697 -French Polynesia,PYF,1983,1335895286.3918 -French Polynesia,PYF,1984,1378991403.37881 -French Polynesia,PYF,1985,1507230778.89921 -French Polynesia,PYF,1986,2301514717.29807 -French Polynesia,PYF,1987,2543199148.3893 -French Polynesia,PYF,1988,2687472829.62988 -French Polynesia,PYF,1989,2636461517.1052 -French Polynesia,PYF,1990,3181206304.81549 -French Polynesia,PYF,1991,3267367609.89528 -French Polynesia,PYF,1992,3558215110.24809 -French Polynesia,PYF,1993,3694600399.89225 -French Polynesia,PYF,1994,3522272321.40766 -French Polynesia,PYF,1995,3982374845.92709 -French Polynesia,PYF,1996,3954696873.74892 -French Polynesia,PYF,1997,3567062511.87293 -French Polynesia,PYF,1998,3775160797.38928 -French Polynesia,PYF,1999,3797016068.69688 -French Polynesia,PYF,2000,3447543137.9415 -Gabon,GAB,1960,141468977.570007 -Gabon,GAB,1961,167637907.381723 -Gabon,GAB,1962,182796536.499884 -Gabon,GAB,1963,154480244.246844 -Gabon,GAB,1964,215679855.272516 -Gabon,GAB,1965,226474285.587109 -Gabon,GAB,1966,245849781.7159 -Gabon,GAB,1967,271543680.279285 -Gabon,GAB,1968,294468564.534369 -Gabon,GAB,1969,318124701.048949 -Gabon,GAB,1970,323802475.480977 -Gabon,GAB,1971,381687073.058558 -Gabon,GAB,1972,430508357.723916 -Gabon,GAB,1973,722780701.123251 -Gabon,GAB,1974,1544216003.9841 -Gabon,GAB,1975,2157592936.60712 -Gabon,GAB,1976,3009409970.90514 -Gabon,GAB,1977,2809349074.17738 -Gabon,GAB,1978,2389479269.18878 -Gabon,GAB,1979,3030251116.35999 -Gabon,GAB,1980,4279637933.85126 -Gabon,GAB,1981,3862269126.92642 -Gabon,GAB,1982,3618007844.44919 -Gabon,GAB,1983,3391275731.31834 -Gabon,GAB,1984,3561451562.23569 -Gabon,GAB,1985,3339914759.37269 -Gabon,GAB,1986,3403638193.57912 -Gabon,GAB,1987,3281797038.66591 -Gabon,GAB,1988,3834503378.35525 -Gabon,GAB,1989,4186411457.4569 -Gabon,GAB,1990,5952293765.84484 -Gabon,GAB,1991,5402919956.93831 -Gabon,GAB,1992,5592390848.52648 -Gabon,GAB,1993,4378645081.01769 -Gabon,GAB,1994,4190819314.02958 -Gabon,GAB,1995,4958845906.34769 -Gabon,GAB,1996,5694040336.82571 -Gabon,GAB,1997,5326816858.99586 -Gabon,GAB,1998,4483417119.83928 -Gabon,GAB,1999,4662992036.2073 -Gabon,GAB,2000,5067865320.7979 -Gabon,GAB,2001,5018874179.18704 -Gabon,GAB,2002,5310381151.35952 -Gabon,GAB,2003,6497305662.09274 -Gabon,GAB,2004,7756293574.98077 -Gabon,GAB,2005,9458884812.18106 -Gabon,GAB,2006,10154041929.6521 -Gabon,GAB,2007,12438956756.4455 -Gabon,GAB,2008,15508574820.3516 -Gabon,GAB,2009,12065138272.7538 -Gabon,GAB,2010,14358584300.3006 -Gabon,GAB,2011,18186478119.9582 -Gabon,GAB,2012,17171447372.3334 -Gabon,GAB,2013,17590716232.4913 -Gabon,GAB,2014,18179717776.1597 -Gabon,GAB,2015,14262032470.9041 -Gabon,GAB,2016,14213558130.1817 -"Gambia, The",GMB,1966,44212353.6988296 -"Gambia, The",GMB,1967,46695363.1558873 -"Gambia, The",GMB,1968,41160658.5705371 -"Gambia, The",GMB,1969,45168722.6995632 -"Gambia, The",GMB,1970,52296836.749388 -"Gambia, The",GMB,1971,55728608.974983 -"Gambia, The",GMB,1972,59161544.9957528 -"Gambia, The",GMB,1973,75187969.924812 -"Gambia, The",GMB,1974,95797533.4619206 -"Gambia, The",GMB,1975,115182522.123894 -"Gambia, The",GMB,1976,112189468.481826 -"Gambia, The",GMB,1977,138094243.349324 -"Gambia, The",GMB,1978,171836793.402695 -"Gambia, The",GMB,1979,207114382.546071 -"Gambia, The",GMB,1980,241080708.89018 -"Gambia, The",GMB,1981,218764445.784343 -"Gambia, The",GMB,1982,216051495.959817 -"Gambia, The",GMB,1983,213446562.57106 -"Gambia, The",GMB,1984,177338801.93075 -"Gambia, The",GMB,1985,225724851.691107 -"Gambia, The",GMB,1986,185646209.386282 -"Gambia, The",GMB,1987,220626484.224811 -"Gambia, The",GMB,1988,266673126.229801 -"Gambia, The",GMB,1989,284119692.49433 -"Gambia, The",GMB,1990,317083373.524559 -"Gambia, The",GMB,1991,690314321.374999 -"Gambia, The",GMB,1992,714255460.503389 -"Gambia, The",GMB,1993,755042548.055824 -"Gambia, The",GMB,1994,746491692.583857 -"Gambia, The",GMB,1995,785996982.492168 -"Gambia, The",GMB,1996,848237108.56163 -"Gambia, The",GMB,1997,803630742.53446 -"Gambia, The",GMB,1998,840285264.631545 -"Gambia, The",GMB,1999,814723460.08372 -"Gambia, The",GMB,2000,782915402.421095 -"Gambia, The",GMB,2001,687408804.630527 -"Gambia, The",GMB,2002,578236035.104279 -"Gambia, The",GMB,2003,487038821.611959 -"Gambia, The",GMB,2004,578785278.7703 -"Gambia, The",GMB,2005,624174723.713404 -"Gambia, The",GMB,2006,655068695.952711 -"Gambia, The",GMB,2007,798870894.208271 -"Gambia, The",GMB,2008,965769128.170004 -"Gambia, The",GMB,2009,900639747.93953 -"Gambia, The",GMB,2010,952429030.415536 -"Gambia, The",GMB,2011,904256643.415984 -"Gambia, The",GMB,2012,912569686.7859 -"Gambia, The",GMB,2013,903779326.206421 -"Gambia, The",GMB,2014,849122624.781348 -"Gambia, The",GMB,2015,938794719.358588 -"Gambia, The",GMB,2016,964599177.535474 -Georgia,GEO,1990,7753501867.76095 -Georgia,GEO,1991,6357615894.03974 -Georgia,GEO,1992,3690328963.64086 -Georgia,GEO,1993,2701181331.30816 -Georgia,GEO,1994,2513870586.73344 -Georgia,GEO,1995,2693731865.97036 -Georgia,GEO,1996,3094915505.9093 -Georgia,GEO,1997,3510540809.24855 -Georgia,GEO,1998,3613500117.24928 -Georgia,GEO,1999,2800024313.95144 -Georgia,GEO,2000,3057453482.55826 -Georgia,GEO,2001,3219487824.87911 -Georgia,GEO,2002,3395778673.79183 -Georgia,GEO,2003,3991374548.50512 -Georgia,GEO,2004,5125273880.74998 -Georgia,GEO,2005,6410941012.59189 -Georgia,GEO,2006,7745406200.85374 -Georgia,GEO,2007,10172869679.7366 -Georgia,GEO,2008,12795044472.7663 -Georgia,GEO,2009,10766809099.0721 -Georgia,GEO,2010,11638536834.4274 -Georgia,GEO,2011,14434619982.2117 -Georgia,GEO,2012,15846474595.773 -Georgia,GEO,2013,16140047012.1438 -Georgia,GEO,2014,16509305827.7171 -Georgia,GEO,2015,13993546732.4726 -Georgia,GEO,2016,14332880086.196 -Germany,DEU,1970,215021806498.156 -Germany,DEU,1971,249039217364.635 -Germany,DEU,1972,298667219346.133 -Germany,DEU,1973,396866742553.97 -Germany,DEU,1974,443618642959.716 -Germany,DEU,1975,488780155338.262 -Germany,DEU,1976,517787921003.573 -Germany,DEU,1977,598226205424.071 -Germany,DEU,1978,737668356280.428 -Germany,DEU,1979,878010536975.776 -Germany,DEU,1980,946695355820.96 -Germany,DEU,1981,797443405711.813 -Germany,DEU,1982,773638200773.757 -Germany,DEU,1983,767768378016.086 -Germany,DEU,1984,722367608343.069 -Germany,DEU,1985,729763282952.432 -Germany,DEU,1986,1042300769791.95 -Germany,DEU,1987,1293264353318.82 -Germany,DEU,1988,1395931548502.06 -Germany,DEU,1989,1393674332154.37 -Germany,DEU,1990,1764967948916.6 -Germany,DEU,1991,1861873895109.02 -Germany,DEU,1992,2123130870381.97 -Germany,DEU,1993,2068555542410.98 -Germany,DEU,1994,2205966011811.5 -Germany,DEU,1995,2591620035485.19 -Germany,DEU,1996,2503665193657.4 -Germany,DEU,1997,2218689375140.99 -Germany,DEU,1998,2243225519617.65 -Germany,DEU,1999,2199957383336.88 -Germany,DEU,2000,1949953934033.54 -Germany,DEU,2001,1950648769574.94 -Germany,DEU,2002,2079136081309.99 -Germany,DEU,2003,2505733634311.51 -Germany,DEU,2004,2819245095604.67 -Germany,DEU,2005,2861410272354.18 -Germany,DEU,2006,3002446368084.31 -Germany,DEU,2007,3439953462907.2 -Germany,DEU,2008,3752365607148.09 -Germany,DEU,2009,3418005001389.27 -Germany,DEU,2010,3417094562648.95 -Germany,DEU,2011,3757698281117.55 -Germany,DEU,2012,3543983909148.01 -Germany,DEU,2013,3752513503278.41 -Germany,DEU,2014,3879276587198.91 -Germany,DEU,2015,3363599907529.78 -Germany,DEU,2016,3466756880460.62 -Ghana,GHA,1960,1217230094.97205 -Ghana,GHA,1961,1302674324.88378 -Ghana,GHA,1962,1382515654.47343 -Ghana,GHA,1963,1540797588.57221 -Ghana,GHA,1964,1731296199.52296 -Ghana,GHA,1965,2053462968.0426 -Ghana,GHA,1966,2126300672.22965 -Ghana,GHA,1967,1747187644.9031 -Ghana,GHA,1968,1666909517.65205 -Ghana,GHA,1969,1962050555.7775 -Ghana,GHA,1970,2215028588.45646 -Ghana,GHA,1971,2417108577.52739 -Ghana,GHA,1972,2112293279.98507 -Ghana,GHA,1973,2465493032.25878 -Ghana,GHA,1974,2894409912.1709 -Ghana,GHA,1975,2810106390.10618 -Ghana,GHA,1976,2765254360.20623 -Ghana,GHA,1977,3189428571.42857 -Ghana,GHA,1978,3662478172.79996 -Ghana,GHA,1979,4020227931.15097 -Ghana,GHA,1980,4445228057.45354 -Ghana,GHA,1981,4222441673.17049 -Ghana,GHA,1982,4035994383.38367 -Ghana,GHA,1983,4057275077.68156 -Ghana,GHA,1984,4412279865.40315 -Ghana,GHA,1985,4504342152.98679 -Ghana,GHA,1986,5727602648.75537 -Ghana,GHA,1987,5074829931.97279 -Ghana,GHA,1988,5197840972.6857 -Ghana,GHA,1989,5251764269.91812 -Ghana,GHA,1990,5889174833.90034 -Ghana,GHA,1991,6596546195.65217 -Ghana,GHA,1992,6413901601.83066 -Ghana,GHA,1993,5966255778.12018 -Ghana,GHA,1994,5444560669.45607 -Ghana,GHA,1995,6465137614.6789 -Ghana,GHA,1996,6934984709.48012 -Ghana,GHA,1997,6891308593.75 -Ghana,GHA,1998,7480968858.13149 -Ghana,GHA,1999,7719354838.70968 -Ghana,GHA,2000,4983024408.14828 -Ghana,GHA,2001,5314909953.92992 -Ghana,GHA,2002,6166330136.2948 -Ghana,GHA,2003,7632406552.83803 -Ghana,GHA,2004,8881368538.07671 -Ghana,GHA,2005,10731634116.7384 -Ghana,GHA,2006,20409257610.4746 -Ghana,GHA,2007,24758819717.7074 -Ghana,GHA,2008,28526891010.4925 -Ghana,GHA,2009,25977847813.7422 -Ghana,GHA,2010,32174772955.9748 -Ghana,GHA,2011,39566292432.8615 -Ghana,GHA,2012,41939728978.7281 -Ghana,GHA,2013,47805069494.9082 -Ghana,GHA,2014,38616536131.648 -Ghana,GHA,2015,37543361203.5609 -Ghana,GHA,2016,42689783733.873 -Greece,GRC,1960,4446528164.67559 -Greece,GRC,1961,5016048786.22753 -Greece,GRC,1962,5327573509.09843 -Greece,GRC,1963,5949478034.88751 -Greece,GRC,1964,6680298250.57961 -Greece,GRC,1965,7600579093.1158 -Greece,GRC,1966,8455611129.27936 -Greece,GRC,1967,9136711287.82434 -Greece,GRC,1968,9915140546.35072 -Greece,GRC,1969,11266091570.5718 -Greece,GRC,1970,13139862500 -Greece,GRC,1971,14591755681.8182 -Greece,GRC,1972,16885506818.1818 -Greece,GRC,1973,22347844649.0219 -Greece,GRC,1974,25351305681.8182 -Greece,GRC,1975,28525872476.0893 -Greece,GRC,1976,31152840485.0746 -Greece,GRC,1977,36176233117.4838 -Greece,GRC,1978,44270203153.9889 -Greece,GRC,1979,54481875804.9678 -Greece,GRC,1980,56829663469.2246 -Greece,GRC,1981,52346507380.0738 -Greece,GRC,1982,54617991326.5306 -Greece,GRC,1983,49428872678.0186 -Greece,GRC,1984,48020024788.3918 -Greece,GRC,1985,47820850974.5867 -Greece,GRC,1986,56379593719.5716 -Greece,GRC,1987,65652751132.3603 -Greece,GRC,1988,76261278404.9964 -Greece,GRC,1989,79169043642.4675 -Greece,GRC,1990,97891090928.6328 -Greece,GRC,1991,105143232379.884 -Greece,GRC,1992,116224673042.546 -Greece,GRC,1993,108809058858.502 -Greece,GRC,1994,116601802106.742 -Greece,GRC,1995,136878366230.328 -Greece,GRC,1996,145861612825.595 -Greece,GRC,1997,143157600024.959 -Greece,GRC,1998,144428172835.236 -Greece,GRC,1999,142540728958.023 -Greece,GRC,2000,130133845771.144 -Greece,GRC,2001,136191353467.562 -Greece,GRC,2002,153830947016.751 -Greece,GRC,2003,201924270316.027 -Greece,GRC,2004,240521260988.329 -Greece,GRC,2005,247783001865.44 -Greece,GRC,2006,273317737046.795 -Greece,GRC,2007,318497936901.177 -Greece,GRC,2008,354460802548.704 -Greece,GRC,2009,330000252153.376 -Greece,GRC,2010,299361576558.217 -Greece,GRC,2011,287797822093.178 -Greece,GRC,2012,245670666639.047 -Greece,GRC,2013,239862011450.103 -Greece,GRC,2014,236079774688.445 -Greece,GRC,2015,194860187692.451 -Greece,GRC,2016,194558651275.836 -Greenland,GRL,1970,69520026.6666667 -Greenland,GRL,1971,88570952.8688525 -Greenland,GRL,1972,106101175.65798 -Greenland,GRL,1973,140153748.243656 -Greenland,GRL,1974,169918948.629182 -Greenland,GRL,1975,211194305.702999 -Greenland,GRL,1976,240780413.56493 -Greenland,GRL,1977,282269373.001066 -Greenland,GRL,1978,355989047.256374 -Greenland,GRL,1979,420642463.409998 -Greenland,GRL,1980,476055288.418886 -Greenland,GRL,1981,435746974.759244 -Greenland,GRL,1982,402405069.367769 -Greenland,GRL,1983,416183706.943685 -Greenland,GRL,1984,379371608.442925 -Greenland,GRL,1985,412876071.118493 -Greenland,GRL,1986,603015696.452849 -Greenland,GRL,1987,787392365.831908 -Greenland,GRL,1988,898611007.947709 -Greenland,GRL,1989,929796722.387896 -Greenland,GRL,1990,1018970364.86443 -Greenland,GRL,1991,1016493394.8253 -Greenland,GRL,1992,1037921836.9477 -Greenland,GRL,1993,927219728.866886 -Greenland,GRL,1994,1005879948.43254 -Greenland,GRL,1995,1208946165.92889 -Greenland,GRL,1996,1197509786.67632 -Greenland,GRL,1997,1072147778.03013 -Greenland,GRL,1998,1149862702.96084 -Greenland,GRL,1999,1131561595.13775 -Greenland,GRL,2000,1068030829.75591 -Greenland,GRL,2001,1086172922.57413 -Greenland,GRL,2002,1169138789.31435 -Greenland,GRL,2003,1407866174.84099 -Greenland,GRL,2004,1621822369.84861 -Greenland,GRL,2005,1656172355.71712 -Greenland,GRL,2006,1818759669.06572 -Greenland,GRL,2007,2049139372.11823 -Greenland,GRL,2008,2310743218.06163 -Greenland,GRL,2009,2324870823.92882 -Greenland,GRL,2010,2306502373.71313 -Greenland,GRL,2011,2515245776.44495 -Greenland,GRL,2012,2408666378.93828 -Greenland,GRL,2013,2483396542.2075 -Greenland,GRL,2014,2551126948.77506 -Greenland,GRL,2015,2220380802.33059 -Grenada,GRD,1977,71494495.1851852 -Grenada,GRD,1978,88322386.2962963 -Grenada,GRD,1979,102244362.222222 -Grenada,GRD,1980,110900457.037037 -Grenada,GRD,1981,115651918.888889 -Grenada,GRD,1982,125435590 -Grenada,GRD,1983,131803552.222222 -Grenada,GRD,1984,145533310.740741 -Grenada,GRD,1985,167728455.185185 -Grenada,GRD,1986,187589522.592593 -Grenada,GRD,1987,215009569.62963 -Grenada,GRD,1988,236357523.703704 -Grenada,GRD,1989,267327642.222222 -Grenada,GRD,1990,278098762.962963 -Grenada,GRD,1991,300757900 -Grenada,GRD,1992,310160455.925926 -Grenada,GRD,1993,309812192.962963 -Grenada,GRD,1994,325111808.148148 -Grenada,GRD,1995,342172523.703704 -Grenada,GRD,1996,366911440.37037 -Grenada,GRD,1997,392190585.925926 -Grenada,GRD,1998,445903598.888889 -Grenada,GRD,1999,482009371.481481 -Grenada,GRD,2000,520044370.37037 -Grenada,GRD,2001,520444185.185185 -Grenada,GRD,2002,540336925.925926 -Grenada,GRD,2003,591018407.407407 -Grenada,GRD,2004,599118592.592593 -Grenada,GRD,2005,695370296.296296 -Grenada,GRD,2006,698518518.518518 -Grenada,GRD,2007,758518518.518518 -Grenada,GRD,2008,825925925.925926 -Grenada,GRD,2009,771278111.111111 -Grenada,GRD,2010,771015888.888889 -Grenada,GRD,2011,778648666.666667 -Grenada,GRD,2012,799882148.148148 -Grenada,GRD,2013,842571333.333333 -Grenada,GRD,2014,911481481.481481 -Grenada,GRD,2015,984074074.074074 -Grenada,GRD,2016,1016208194.81481 -Guam,GUM,2002,3385000000 -Guam,GUM,2003,3560000000 -Guam,GUM,2004,3857000000 -Guam,GUM,2005,4197000000 -Guam,GUM,2006,4213000000 -Guam,GUM,2007,4375000000 -Guam,GUM,2008,4621000000 -Guam,GUM,2009,4781000000 -Guam,GUM,2010,4895000000 -Guam,GUM,2011,4928000000 -Guam,GUM,2012,5199000000 -Guam,GUM,2013,5364000000 -Guam,GUM,2014,5566000000 -Guam,GUM,2015,5734000000 -Guatemala,GTM,1960,1043599900 -Guatemala,GTM,1961,1076699900 -Guatemala,GTM,1962,1143600000 -Guatemala,GTM,1963,1262800000 -Guatemala,GTM,1964,1299099900 -Guatemala,GTM,1965,1331399900 -Guatemala,GTM,1966,1390700000 -Guatemala,GTM,1967,1453500000 -Guatemala,GTM,1968,1610500000 -Guatemala,GTM,1969,1715399900 -Guatemala,GTM,1970,1904000000 -Guatemala,GTM,1971,1984800000 -Guatemala,GTM,1972,2101300000 -Guatemala,GTM,1973,2569200100 -Guatemala,GTM,1974,3161499900 -Guatemala,GTM,1975,3645900000 -Guatemala,GTM,1976,4365300200 -Guatemala,GTM,1977,5480500200 -Guatemala,GTM,1978,6070600200 -Guatemala,GTM,1979,6902600200 -Guatemala,GTM,1980,7878700000 -Guatemala,GTM,1981,8607500300 -Guatemala,GTM,1982,8716999700 -Guatemala,GTM,1983,9050000400 -Guatemala,GTM,1984,9470000100 -Guatemala,GTM,1985,9721652086.95652 -Guatemala,GTM,1986,7231963515.98173 -Guatemala,GTM,1987,7084399840 -Guatemala,GTM,1988,7841602824.42748 -Guatemala,GTM,1989,8410724360.79546 -Guatemala,GTM,1990,7650125217.35253 -Guatemala,GTM,1991,9406097735.09117 -Guatemala,GTM,1992,10440842165.3193 -Guatemala,GTM,1993,11399942453.0646 -Guatemala,GTM,1994,12983235568.2292 -Guatemala,GTM,1995,14655487455.7333 -Guatemala,GTM,1996,15674852771.1356 -Guatemala,GTM,1997,17790095900.9809 -Guatemala,GTM,1998,19395461989.5391 -Guatemala,GTM,1999,18318512501.0256 -Guatemala,GTM,2000,19288926545.3759 -Guatemala,GTM,2001,18702802394.8286 -Guatemala,GTM,2002,20776669466.6053 -Guatemala,GTM,2003,21917706490.5299 -Guatemala,GTM,2004,23965275995.7214 -Guatemala,GTM,2005,27211377225.2715 -Guatemala,GTM,2006,30231249362.0604 -Guatemala,GTM,2007,34113107085.6085 -Guatemala,GTM,2008,39136893345.1501 -Guatemala,GTM,2009,37733994976.4137 -Guatemala,GTM,2010,41338595380.8159 -Guatemala,GTM,2011,47654841112.8523 -Guatemala,GTM,2012,50388454861.1111 -Guatemala,GTM,2013,53851058955.2999 -Guatemala,GTM,2014,58722323918.1604 -Guatemala,GTM,2015,63767597193.9175 -Guatemala,GTM,2016,68763255963.8943 -Guinea,GIN,1986,1922600899.3841 -Guinea,GIN,1987,2041538057.02893 -Guinea,GIN,1988,2384295763.72549 -Guinea,GIN,1989,2432029380.43694 -Guinea,GIN,1990,2666616176.91609 -Guinea,GIN,1991,3014890569.04099 -Guinea,GIN,1992,3284625277.16186 -Guinea,GIN,1993,3279063317.63475 -Guinea,GIN,1994,3383218922.79336 -Guinea,GIN,1995,3693753379.05992 -Guinea,GIN,1996,3869032270.91633 -Guinea,GIN,1997,3783788551.0819 -Guinea,GIN,1998,3588376057.01536 -Guinea,GIN,1999,3461282293.64624 -Guinea,GIN,2000,2995360969.16199 -Guinea,GIN,2001,2833442750.43639 -Guinea,GIN,2002,2949637039.04424 -Guinea,GIN,2003,3446442218.89829 -Guinea,GIN,2004,3666349049.42641 -Guinea,GIN,2005,2937071767.25576 -Guinea,GIN,2006,2931625104.50109 -Guinea,GIN,2007,4134173275.1244 -Guinea,GIN,2008,4515824647.43939 -Guinea,GIN,2009,4609923756.18485 -Guinea,GIN,2010,4735956493.06479 -Guinea,GIN,2011,5067360009.39196 -Guinea,GIN,2012,5667229758.9878 -Guinea,GIN,2013,6231725484.55943 -Guinea,GIN,2014,6624068015.50039 -Guinea,GIN,2015,6699203543.29047 -Guinea,GIN,2016,6298927773.1587 -Guinea-Bissau,GNB,1970,78733594.8444943 -Guinea-Bissau,GNB,1971,78540057.1428572 -Guinea-Bissau,GNB,1972,87702828.5714286 -Guinea-Bissau,GNB,1973,89374237.2881356 -Guinea-Bissau,GNB,1974,98775328.9473684 -Guinea-Bissau,GNB,1975,108985740.159382 -Guinea-Bissau,GNB,1976,112386489.013558 -Guinea-Bissau,GNB,1977,114971207.198201 -Guinea-Bissau,GNB,1978,122666858.789625 -Guinea-Bissau,GNB,1979,118537875.125881 -Guinea-Bissau,GNB,1980,110653830.726033 -Guinea-Bissau,GNB,1981,154731969.69697 -Guinea-Bissau,GNB,1982,165523634.49692 -Guinea-Bissau,GNB,1983,163577538.330494 -Guinea-Bissau,GNB,1984,138478900.626886 -Guinea-Bissau,GNB,1985,143856253.125 -Guinea-Bissau,GNB,1986,130225018.751674 -Guinea-Bissau,GNB,1987,173836362.010107 -Guinea-Bissau,GNB,1988,164458120.314078 -Guinea-Bissau,GNB,1989,213143016.443434 -Guinea-Bissau,GNB,1990,243961995.509711 -Guinea-Bissau,GNB,1991,257150573.215747 -Guinea-Bissau,GNB,1992,226313492.713567 -Guinea-Bissau,GNB,1993,236880813.821765 -Guinea-Bissau,GNB,1994,235619994.759074 -Guinea-Bissau,GNB,1995,253966919.939838 -Guinea-Bissau,GNB,1996,270419779.418107 -Guinea-Bissau,GNB,1997,268551010.941186 -Guinea-Bissau,GNB,1998,206457553.397101 -Guinea-Bissau,GNB,1999,224446652.14622 -Guinea-Bissau,GNB,2000,370173851.946119 -Guinea-Bissau,GNB,2001,392278168.199897 -Guinea-Bissau,GNB,2002,415843481.998691 -Guinea-Bissau,GNB,2003,476388260.639232 -Guinea-Bissau,GNB,2004,531109356.165462 -Guinea-Bissau,GNB,2005,586791883.717707 -Guinea-Bissau,GNB,2006,591829908.426264 -Guinea-Bissau,GNB,2007,695606288.605845 -Guinea-Bissau,GNB,2008,864136712.986648 -Guinea-Bissau,GNB,2009,825828703.628208 -Guinea-Bissau,GNB,2010,846332456.382994 -Guinea-Bissau,GNB,2011,1105497854.79398 -Guinea-Bissau,GNB,2012,995582062.343018 -Guinea-Bissau,GNB,2013,1026664188.52724 -Guinea-Bissau,GNB,2014,1109007299.94033 -Guinea-Bissau,GNB,2015,1056776896.92865 -Guinea-Bissau,GNB,2016,1126122707.91534 -Guyana,GUY,1960,170215248.206265 -Guyana,GUY,1961,185848451.262906 -Guyana,GUY,1962,194948375.430205 -Guyana,GUY,1963,175756868.692761 -Guyana,GUY,1964,194773376.888526 -Guyana,GUY,1965,213235294.117647 -Guyana,GUY,1966,228705882.352941 -Guyana,GUY,1967,250176470.588235 -Guyana,GUY,1968,229750000 -Guyana,GUY,1969,249300000 -Guyana,GUY,1970,267800000 -Guyana,GUY,1971,282050000 -Guyana,GUY,1972,285380952.380952 -Guyana,GUY,1973,307047619.047619 -Guyana,GUY,1974,433954545.454545 -Guyana,GUY,1975,494791666.666667 -Guyana,GUY,1976,454440000 -Guyana,GUY,1977,449880000 -Guyana,GUY,1978,507080000 -Guyana,GUY,1979,530440000 -Guyana,GUY,1980,603200000 -Guyana,GUY,1981,570357107.142857 -Guyana,GUY,1982,482000000 -Guyana,GUY,1983,489333333.333333 -Guyana,GUY,1984,437631605.263158 -Guyana,GUY,1985,453488372.093023 -Guyana,GUY,1986,504651139.534884 -Guyana,GUY,1987,354591846.938775 -Guyana,GUY,1988,413799990 -Guyana,GUY,1989,379779389.705882 -Guyana,GUY,1990,396582263.291139 -Guyana,GUY,1991,336708419.499106 -Guyana,GUY,1992,368281378.896883 -Guyana,GUY,1993,442273433.179724 -Guyana,GUY,1994,540874934.201012 -Guyana,GUY,1995,621626785.915493 -Guyana,GUY,1996,705406001.424501 -Guyana,GUY,1997,749138009.564539 -Guyana,GUY,1998,717530683.169567 -Guyana,GUY,1999,694754988.258295 -Guyana,GUY,2000,712667896.727512 -Guyana,GUY,2001,696281471.678532 -Guyana,GUY,2002,722460886.371384 -Guyana,GUY,2003,741929342.788749 -Guyana,GUY,2004,785918769.587635 -Guyana,GUY,2005,824880550.343965 -Guyana,GUY,2006,1458446872.26976 -Guyana,GUY,2007,1740334781.83731 -Guyana,GUY,2008,1922598121.23066 -Guyana,GUY,2009,2025565089.48272 -Guyana,GUY,2010,2259288396.24467 -Guyana,GUY,2011,2576602497.33479 -Guyana,GUY,2012,2851154075.95385 -Guyana,GUY,2013,2990006533.77749 -Guyana,GUY,2014,3077086275.94585 -Guyana,GUY,2015,3179104116.22276 -Guyana,GUY,2016,3446266343.82567 -Haiti,HTI,1991,3473562850.25798 -Haiti,HTI,1992,2257129873.66261 -Haiti,HTI,1993,1878253818.07845 -Haiti,HTI,1994,2167569095.11746 -Haiti,HTI,1995,2813313281.80715 -Haiti,HTI,1996,2907517543.3645 -Haiti,HTI,1997,3338949151.59927 -Haiti,HTI,1998,3723903723.63772 -Haiti,HTI,1999,4153725966.87677 -Haiti,HTI,2000,3953839593.78427 -Haiti,HTI,2001,3596448035.44747 -Haiti,HTI,2002,3472194099.40131 -Haiti,HTI,2003,2960306120.93557 -Haiti,HTI,2004,3537721020.41158 -Haiti,HTI,2005,4310356252.83669 -Haiti,HTI,2006,4756204069.61876 -Haiti,HTI,2007,5885321655.91684 -Haiti,HTI,2008,6548530572.35291 -Haiti,HTI,2009,6584649419.28348 -Haiti,HTI,2010,6622541528.56888 -Haiti,HTI,2011,7516834160.25277 -Haiti,HTI,2012,7890216507.68913 -Haiti,HTI,2013,8452509315.87722 -Haiti,HTI,2014,8776360623.29898 -Haiti,HTI,2015,8724656126.49849 -Haiti,HTI,2016,8022638721.92013 -Honduras,HND,1960,335650000 -Honduras,HND,1961,356200000 -Honduras,HND,1962,387750000 -Honduras,HND,1963,410200000 -Honduras,HND,1964,457000000 -Honduras,HND,1965,508650000 -Honduras,HND,1966,549950000 -Honduras,HND,1967,598100000 -Honduras,HND,1968,646800000 -Honduras,HND,1969,668000050 -Honduras,HND,1970,723000000 -Honduras,HND,1971,731000000 -Honduras,HND,1972,802999950 -Honduras,HND,1973,912499950 -Honduras,HND,1974,1034500000 -Honduras,HND,1975,1124000000 -Honduras,HND,1976,1347999950 -Honduras,HND,1977,1669499950 -Honduras,HND,1978,1929499950 -Honduras,HND,1979,2251499950 -Honduras,HND,1980,2566000050 -Honduras,HND,1981,2819500000 -Honduras,HND,1982,2903500050 -Honduras,HND,1983,3076999950 -Honduras,HND,1984,3319000000 -Honduras,HND,1985,3639499950 -Honduras,HND,1986,3808500050 -Honduras,HND,1987,4152499950 -Honduras,HND,1988,3970386266.09442 -Honduras,HND,1989,3563448310.34483 -Honduras,HND,1990,3048881322.9572 -Honduras,HND,1991,3068444711.94538 -Honduras,HND,1992,3419487440.65916 -Honduras,HND,1993,3481990761.34498 -Honduras,HND,1994,3432356578.82219 -Honduras,HND,1995,3911053180.39625 -Honduras,HND,1996,4034037162.16216 -Honduras,HND,1997,4663193916.34981 -Honduras,HND,1998,5202215657.31167 -Honduras,HND,1999,5372543554.00697 -Honduras,HND,2000,7103529494.37412 -Honduras,HND,2001,7565869927.73763 -Honduras,HND,2002,7775078402.92785 -Honduras,HND,2003,8140271080.5604 -Honduras,HND,2004,8772194250.27021 -Honduras,HND,2005,9672035709.39793 -Honduras,HND,2006,10841742347.7968 -Honduras,HND,2007,12275501784.2971 -Honduras,HND,2008,13789715132.502 -Honduras,HND,2009,14587496229.1811 -Honduras,HND,2010,15839344591.9842 -Honduras,HND,2011,17710275997.4437 -Honduras,HND,2012,18528554861.015 -Honduras,HND,2013,18499729063.3889 -Honduras,HND,2014,19756533658.1136 -Honduras,HND,2015,20844308600.8656 -Honduras,HND,2016,21516915352.6217 -"Hong Kong SAR, China",HKG,1960,1320796651.69457 -"Hong Kong SAR, China",HKG,1961,1383681651.13776 -"Hong Kong SAR, China",HKG,1962,1612346412.26475 -"Hong Kong SAR, China",HKG,1963,1935298266.45384 -"Hong Kong SAR, China",HKG,1964,2206466461.26434 -"Hong Kong SAR, China",HKG,1965,2435078534.03141 -"Hong Kong SAR, China",HKG,1966,2489845016.64894 -"Hong Kong SAR, China",HKG,1967,2692474989.12571 -"Hong Kong SAR, China",HKG,1968,2716964388.42418 -"Hong Kong SAR, China",HKG,1969,3189740055.13982 -"Hong Kong SAR, China",HKG,1970,3800766535.62088 -"Hong Kong SAR, China",HKG,1971,4476001946.01486 -"Hong Kong SAR, China",HKG,1972,5710107420.14394 -"Hong Kong SAR, China",HKG,1973,8030117555.62033 -"Hong Kong SAR, China",HKG,1974,9388663645.7588 -"Hong Kong SAR, China",HKG,1975,10048022369.9141 -"Hong Kong SAR, China",HKG,1976,12876366008.8077 -"Hong Kong SAR, China",HKG,1977,15719433719.4337 -"Hong Kong SAR, China",HKG,1978,18315007365.9713 -"Hong Kong SAR, China",HKG,1979,22526035940.5921 -"Hong Kong SAR, China",HKG,1980,28861759209.0191 -"Hong Kong SAR, China",HKG,1981,31055409443.043 -"Hong Kong SAR, China",HKG,1982,32291306281.8168 -"Hong Kong SAR, China",HKG,1983,29907091339.5364 -"Hong Kong SAR, China",HKG,1984,33511383985.6741 -"Hong Kong SAR, China",HKG,1985,35699543050.7778 -"Hong Kong SAR, China",HKG,1986,41075570591.9291 -"Hong Kong SAR, China",HKG,1987,50622571586.1149 -"Hong Kong SAR, China",HKG,1988,59707404560.5944 -"Hong Kong SAR, China",HKG,1989,68790369107.2962 -"Hong Kong SAR, China",HKG,1990,76928290841.8701 -"Hong Kong SAR, China",HKG,1991,88959620135.8864 -"Hong Kong SAR, China",HKG,1992,104272278634.731 -"Hong Kong SAR, China",HKG,1993,120353947980.764 -"Hong Kong SAR, China",HKG,1994,135812069768.646 -"Hong Kong SAR, China",HKG,1995,144652912433.103 -"Hong Kong SAR, China",HKG,1996,159717233621.659 -"Hong Kong SAR, China",HKG,1997,177352785419.977 -"Hong Kong SAR, China",HKG,1998,168886163221.567 -"Hong Kong SAR, China",HKG,1999,165768095391.557 -"Hong Kong SAR, China",HKG,2000,171668164082.555 -"Hong Kong SAR, China",HKG,2001,169403241524.337 -"Hong Kong SAR, China",HKG,2002,166349228737.386 -"Hong Kong SAR, China",HKG,2003,161384522525.299 -"Hong Kong SAR, China",HKG,2004,169099768875.193 -"Hong Kong SAR, China",HKG,2005,181570082162.19 -"Hong Kong SAR, China",HKG,2006,193536265094.364 -"Hong Kong SAR, China",HKG,2007,211597405593.868 -"Hong Kong SAR, China",HKG,2008,219279678430.164 -"Hong Kong SAR, China",HKG,2009,214046415026.187 -"Hong Kong SAR, China",HKG,2010,228637697575.04 -"Hong Kong SAR, China",HKG,2011,248513617677.287 -"Hong Kong SAR, China",HKG,2012,262629441493.476 -"Hong Kong SAR, China",HKG,2013,275696879834.966 -"Hong Kong SAR, China",HKG,2014,291459356985.337 -"Hong Kong SAR, China",HKG,2015,309403880389.071 -"Hong Kong SAR, China",HKG,2016,320912235498.728 -Hungary,HUN,1991,34650782427.2429 -Hungary,HUN,1992,38616036221.8202 -Hungary,HUN,1993,40006243367.539 -Hungary,HUN,1994,43039008829.7659 -Hungary,HUN,1995,46288369007.4588 -Hungary,HUN,1996,46538169511.6894 -Hungary,HUN,1997,47178241568.5704 -Hungary,HUN,1998,48661666395.3691 -Hungary,HUN,1999,49074725337.7458 -Hungary,HUN,2000,47209471853.3471 -Hungary,HUN,2001,53696730223.8318 -Hungary,HUN,2002,67561285378.7259 -Hungary,HUN,2003,85050281601.04 -Hungary,HUN,2004,103694527827.457 -Hungary,HUN,2005,112589039620.207 -Hungary,HUN,2006,114801188269.404 -Hungary,HUN,2007,139198195460.551 -Hungary,HUN,2008,157290970540.917 -Hungary,HUN,2009,129965360575.699 -Hungary,HUN,2010,130255637530.908 -Hungary,HUN,2011,140091591852.976 -Hungary,HUN,2012,127321135030.078 -Hungary,HUN,2013,134680475647.645 -Hungary,HUN,2014,139294565100.565 -Hungary,HUN,2015,121715203207.647 -Hungary,HUN,2016,124342940194.419 -Iceland,ISL,1960,248434096.968726 -Iceland,ISL,1961,253885656.329253 -Iceland,ISL,1962,284916516.159537 -Iceland,ISL,1963,340061650.119898 -Iceland,ISL,1964,434267936.914583 -Iceland,ISL,1965,523694949.370689 -Iceland,ISL,1966,628893310.399926 -Iceland,ISL,1967,621225962.154708 -Iceland,ISL,1968,474399471.622359 -Iceland,ISL,1969,414709311.35296 -Iceland,ISL,1970,531004659.090909 -Iceland,ISL,1971,675722954.545455 -Iceland,ISL,1972,846506911.398142 -Iceland,ISL,1973,1163864529.01365 -Iceland,ISL,1974,1527559579.78989 -Iceland,ISL,1975,1418360312.29668 -Iceland,ISL,1976,1683117417.79656 -Iceland,ISL,1977,2226538693.61895 -Iceland,ISL,1978,2532331673.49047 -Iceland,ISL,1979,2876729410.09643 -Iceland,ISL,1980,3409023699.34967 -Iceland,ISL,1981,3521512388.91504 -Iceland,ISL,1982,3232804218.11116 -Iceland,ISL,1983,2788530415.2511 -Iceland,ISL,1984,2887825523.68452 -Iceland,ISL,1985,3008412959.52317 -Iceland,ISL,1986,4022192403.69597 -Iceland,ISL,1987,5565384032.45323 -Iceland,ISL,1988,6156487920.21202 -Iceland,ISL,1989,5718878001.74609 -Iceland,ISL,1990,6521544489.20626 -Iceland,ISL,1991,6966138525.63635 -Iceland,ISL,1992,7138787995.32199 -Iceland,ISL,1993,6269347502.78093 -Iceland,ISL,1994,6441621297.77366 -Iceland,ISL,1995,7181787873.86945 -Iceland,ISL,1996,7501950115.78947 -Iceland,ISL,1997,7596126045.95208 -Iceland,ISL,1998,8468339855.94356 -Iceland,ISL,1999,8931365460.57043 -Iceland,ISL,2000,8946079678.43696 -Iceland,ISL,2001,8146073989.52626 -Iceland,ISL,2002,9199643907.97902 -Iceland,ISL,2003,11304084266.5137 -Iceland,ISL,2004,13703315349.2507 -Iceland,ISL,2005,16691213479.471 -Iceland,ISL,2006,17043245939.014 -Iceland,ISL,2007,21295012098.9774 -Iceland,ISL,2008,17640375722.4448 -Iceland,ISL,2009,12887072301.1621 -Iceland,ISL,2010,13254818331.1893 -Iceland,ISL,2011,14674650434.6757 -Iceland,ISL,2012,14218575093.024 -Iceland,ISL,2013,15479256844.8708 -Iceland,ISL,2014,17178962757.4324 -Iceland,ISL,2015,16783714958.4498 -Iceland,ISL,2016,20047413006.3471 -India,IND,1960,36535925031.34 -India,IND,1961,38709096075.6305 -India,IND,1962,41599070242.3094 -India,IND,1963,47776000900.0302 -India,IND,1964,55726873083.5543 -India,IND,1965,58760424669.8482 -India,IND,1966,45253641303.1897 -India,IND,1967,49466168890.9507 -India,IND,1968,52377324284.1951 -India,IND,1969,57668330026.3629 -India,IND,1970,61589800519.5084 -India,IND,1971,66452561865.8332 -India,IND,1972,70509913049.4003 -India,IND,1973,84374541630.2062 -India,IND,1974,98198276856.6209 -India,IND,1975,97159222024.1364 -India,IND,1976,101346972433.934 -India,IND,1977,119866746574.408 -India,IND,1978,135468782808.69 -India,IND,1979,150950826964.424 -India,IND,1980,183839864649.15 -India,IND,1981,190909548789.769 -India,IND,1982,198037712681.605 -India,IND,1983,215350771428.331 -India,IND,1984,209328156800.867 -India,IND,1985,229410293759.071 -India,IND,1986,245664654062.873 -India,IND,1987,275311425331.64 -India,IND,1988,292632656262.687 -India,IND,1989,292093308319.642 -India,IND,1990,316697337894.513 -India,IND,1991,266502281094.117 -India,IND,1992,284363884080.101 -India,IND,1993,275570363431.902 -India,IND,1994,322909902308.892 -India,IND,1995,355475984177.451 -India,IND,1996,387656017798.596 -India,IND,1997,410320300470.283 -India,IND,1998,415730874171.13 -India,IND,1999,452699998386.914 -India,IND,2000,462146799337.698 -India,IND,2001,478965491060.771 -India,IND,2002,508068952065.901 -India,IND,2003,599592902016.345 -India,IND,2004,699688852930.276 -India,IND,2005,808901077222.839 -India,IND,2006,920316529729.747 -India,IND,2007,1201111768410.27 -India,IND,2008,1186952757636.11 -India,IND,2009,1323940295874.06 -India,IND,2010,1656617073124.71 -India,IND,2011,1823049927772.05 -India,IND,2012,1827637859136.23 -India,IND,2013,1856722121394.42 -India,IND,2014,2035393459980.06 -India,IND,2015,2111751098184.5 -India,IND,2016,2263522518124.03 -Indonesia,IDN,1967,5667756644.83099 -Indonesia,IDN,1968,7076465295.33327 -Indonesia,IDN,1969,8337423312.88344 -Indonesia,IDN,1970,9150684931.50685 -Indonesia,IDN,1971,9333536359.79807 -Indonesia,IDN,1972,10997590361.4458 -Indonesia,IDN,1973,16273253012.0482 -Indonesia,IDN,1974,25802409638.5542 -Indonesia,IDN,1975,30463855421.6867 -Indonesia,IDN,1976,37269156626.506 -Indonesia,IDN,1977,45808915662.6506 -Indonesia,IDN,1978,51455719099.9244 -Indonesia,IDN,1979,51400186379.3033 -Indonesia,IDN,1980,72482337370.3493 -Indonesia,IDN,1981,85518233450.774 -Indonesia,IDN,1982,90158449307.2387 -Indonesia,IDN,1983,81052283404.6079 -Indonesia,IDN,1984,84853699994.0508 -Indonesia,IDN,1985,85289491750.3225 -Indonesia,IDN,1986,79954072569.8533 -Indonesia,IDN,1987,75929617576.8776 -Indonesia,IDN,1988,84300174477.2018 -Indonesia,IDN,1989,94451427898.3405 -Indonesia,IDN,1990,106140727357.035 -Indonesia,IDN,1991,116621996217.133 -Indonesia,IDN,1992,128026966579.964 -Indonesia,IDN,1993,158006700301.533 -Indonesia,IDN,1994,176892143931.505 -Indonesia,IDN,1995,202132028723.115 -Indonesia,IDN,1996,227369679374.973 -Indonesia,IDN,1997,215748998609.635 -Indonesia,IDN,1998,95445547872.715 -Indonesia,IDN,1999,140001351215.462 -Indonesia,IDN,2000,165021012077.81 -Indonesia,IDN,2001,160446947784.909 -Indonesia,IDN,2002,195660611165.183 -Indonesia,IDN,2003,234772463823.808 -Indonesia,IDN,2004,256836875295.452 -Indonesia,IDN,2005,285868618224.017 -Indonesia,IDN,2006,364570514304.85 -Indonesia,IDN,2007,432216737774.861 -Indonesia,IDN,2008,510228635279.289 -Indonesia,IDN,2009,539580088908.138 -Indonesia,IDN,2010,755094160363.071 -Indonesia,IDN,2011,892969107923.094 -Indonesia,IDN,2012,917869910105.749 -Indonesia,IDN,2013,912524136718.018 -Indonesia,IDN,2014,890814755233.225 -Indonesia,IDN,2015,861256351277.359 -Indonesia,IDN,2016,932259177765.307 -"Iran, Islamic Rep.",IRN,1960,4199134389.43894 -"Iran, Islamic Rep.",IRN,1961,4426949094.38944 -"Iran, Islamic Rep.",IRN,1962,4693566415.84158 -"Iran, Islamic Rep.",IRN,1963,4928628018.48185 -"Iran, Islamic Rep.",IRN,1964,5379845647.52475 -"Iran, Islamic Rep.",IRN,1965,6197319928.71287 -"Iran, Islamic Rep.",IRN,1966,6789938671.9472 -"Iran, Islamic Rep.",IRN,1967,7555383689.76898 -"Iran, Islamic Rep.",IRN,1968,8623172959.73597 -"Iran, Islamic Rep.",IRN,1969,9743089607.92079 -"Iran, Islamic Rep.",IRN,1970,10976245153.7954 -"Iran, Islamic Rep.",IRN,1971,13731801564.3564 -"Iran, Islamic Rep.",IRN,1972,17153463263.3663 -"Iran, Islamic Rep.",IRN,1973,27081698249.1798 -"Iran, Islamic Rep.",IRN,1974,46209092072.4584 -"Iran, Islamic Rep.",IRN,1975,51776222349.8518 -"Iran, Islamic Rep.",IRN,1976,68055295080.4565 -"Iran, Islamic Rep.",IRN,1977,80600122702.2202 -"Iran, Islamic Rep.",IRN,1978,77994316621.497 -"Iran, Islamic Rep.",IRN,1979,90391877325.2927 -"Iran, Islamic Rep.",IRN,1980,94362275579.4621 -"Iran, Islamic Rep.",IRN,1981,100499312749.447 -"Iran, Islamic Rep.",IRN,1982,125948756439.161 -"Iran, Islamic Rep.",IRN,1983,156365156618.288 -"Iran, Islamic Rep.",IRN,1984,162276728619.617 -"Iran, Islamic Rep.",IRN,1985,180183629600.036 -"Iran, Islamic Rep.",IRN,1986,209094561834.095 -"Iran, Islamic Rep.",IRN,1987,134009995922.987 -"Iran, Islamic Rep.",IRN,1988,123057861333.933 -"Iran, Islamic Rep.",IRN,1989,120496362916.372 -"Iran, Islamic Rep.",IRN,1990,124813263926.374 -"Iran, Islamic Rep.",IRN,1993,63743623232.012 -"Iran, Islamic Rep.",IRN,1994,71841461172.5964 -"Iran, Islamic Rep.",IRN,1995,96419225743.6737 -"Iran, Islamic Rep.",IRN,1996,120403931885.441 -"Iran, Islamic Rep.",IRN,1997,113919163421.155 -"Iran, Islamic Rep.",IRN,1998,110276913362.508 -"Iran, Islamic Rep.",IRN,1999,113848450088.351 -"Iran, Islamic Rep.",IRN,2000,109591707802.216 -"Iran, Islamic Rep.",IRN,2001,126878750295.944 -"Iran, Islamic Rep.",IRN,2002,128626917503.72 -"Iran, Islamic Rep.",IRN,2003,153544751395.43 -"Iran, Islamic Rep.",IRN,2004,183697185041.72 -"Iran, Islamic Rep.",IRN,2005,219845971945.264 -"Iran, Islamic Rep.",IRN,2006,258645743978.386 -"Iran, Islamic Rep.",IRN,2007,337474485087.271 -"Iran, Islamic Rep.",IRN,2008,397189565318.895 -"Iran, Islamic Rep.",IRN,2009,398978104575.331 -"Iran, Islamic Rep.",IRN,2010,467790215915.476 -"Iran, Islamic Rep.",IRN,2011,592037800186.865 -"Iran, Islamic Rep.",IRN,2012,587209369682.67 -"Iran, Islamic Rep.",IRN,2013,511620875086.78 -"Iran, Islamic Rep.",IRN,2014,425326068422.881 -"Iran, Islamic Rep.",IRN,2015,393436064441.692 -Iraq,IRQ,1960,1684121534.58415 -Iraq,IRQ,1961,1831700364.04369 -Iraq,IRQ,1962,1954634836.18034 -Iraq,IRQ,1963,1978437692.5231 -Iraq,IRQ,1964,2340521142.5371 -Iraq,IRQ,1968,2896947633.71605 -Iraq,IRQ,1969,3008120974.51694 -Iraq,IRQ,1970,3281713805.65668 -Iraq,IRQ,1971,3865346534.65347 -Iraq,IRQ,1972,4113848002.40312 -Iraq,IRQ,1973,5134367778.1446 -Iraq,IRQ,1974,11516762614.2906 -Iraq,IRQ,1975,13458516762.6143 -Iraq,IRQ,1976,17754825601.0836 -Iraq,IRQ,1977,19838130714.5276 -Iraq,IRQ,1978,23762275651.8794 -Iraq,IRQ,1979,37816457839.4853 -Iraq,IRQ,1980,53405689129.6986 -Iraq,IRQ,1981,38424991534.0332 -Iraq,IRQ,1982,42595309882.7471 -Iraq,IRQ,1983,40595046638.7906 -Iraq,IRQ,1984,46802508845.2879 -Iraq,IRQ,1985,48284979092.9559 -Iraq,IRQ,1986,47127693792.2161 -Iraq,IRQ,1987,56609842393.0524 -Iraq,IRQ,1988,62503055644.9019 -Iraq,IRQ,1989,65641363782.5668 -Iraq,IRQ,1990,179885815374.719 -Iraq,IRQ,2004,36627901762.063 -Iraq,IRQ,2005,49954890353.2609 -Iraq,IRQ,2006,65140293687.5395 -Iraq,IRQ,2007,88840050497.0957 -Iraq,IRQ,2008,131613661510.475 -Iraq,IRQ,2009,111660855042.735 -Iraq,IRQ,2010,138516722649.573 -Iraq,IRQ,2011,185749664444.444 -Iraq,IRQ,2012,218000986222.639 -Iraq,IRQ,2013,234648370497.427 -Iraq,IRQ,2014,234648370497.427 -Iraq,IRQ,2015,179640210726.448 -Iraq,IRQ,2016,171489001692.047 -Ireland,IRL,1960,1939329775.43739 -Ireland,IRL,1961,2088012282.35667 -Ireland,IRL,1962,2260349684.08625 -Ireland,IRL,1963,2430843768.44553 -Ireland,IRL,1964,2766608945.87402 -Ireland,IRL,1965,2945704142.99765 -Ireland,IRL,1966,3104034393.23162 -Ireland,IRL,1967,3343636773.36759 -Ireland,IRL,1968,3278584478.33023 -Ireland,IRL,1969,3787077343.72783 -Ireland,IRL,1970,4400344547.34455 -Ireland,IRL,1971,5103293982.36872 -Ireland,IRL,1972,6324312352.47836 -Ireland,IRL,1973,7488574956.58885 -Ireland,IRL,1974,7904673172.52808 -Ireland,IRL,1975,9493191637.63066 -Ireland,IRL,1976,9463110246.24965 -Ireland,IRL,1977,11259469295.2329 -Ireland,IRL,1978,14662488976.1401 -Ireland,IRL,1979,18337460025.7898 -Ireland,IRL,1980,21769374170.5778 -Ireland,IRL,1981,20690641399.4169 -Ireland,IRL,1982,21496001229.5998 -Ireland,IRL,1983,20786594499.3638 -Ireland,IRL,1984,20126542854.7038 -Ireland,IRL,1985,21291058299.3254 -Ireland,IRL,1986,28742982513.777 -Ireland,IRL,1987,33954080524.3446 -Ireland,IRL,1988,37810270545.8908 -Ireland,IRL,1989,39277216207.166 -Ireland,IRL,1990,49354416568.9723 -Ireland,IRL,1991,49836763468.1202 -Ireland,IRL,1992,55973865067.6672 -Ireland,IRL,1993,52469340621.0024 -Ireland,IRL,1994,57154150176.6784 -Ireland,IRL,1995,69208232323.2323 -Ireland,IRL,1996,75864982358.871 -Ireland,IRL,1997,82816774116.5234 -Ireland,IRL,1998,90111618257.2614 -Ireland,IRL,1999,98781557639.0369 -Ireland,IRL,2000,99855067256.3111 -Ireland,IRL,2001,109119123042.506 -Ireland,IRL,2002,127941699604.743 -Ireland,IRL,2003,164285609480.813 -Ireland,IRL,2004,193870908865.16 -Ireland,IRL,2005,211684827757.742 -Ireland,IRL,2006,232167519759.127 -Ireland,IRL,2007,270043019436.08 -Ireland,IRL,2008,274919027391.241 -Ireland,IRL,2009,235765976660.183 -Ireland,IRL,2010,221343483668.837 -Ireland,IRL,2011,240590736123.315 -Ireland,IRL,2012,225819189160.686 -Ireland,IRL,2013,239271158532.518 -Ireland,IRL,2014,256271345442.586 -Ireland,IRL,2015,283716006697.636 -Ireland,IRL,2016,294053595685.717 -Isle of Man,IMN,1995,914727080.643268 -Isle of Man,IMN,1996,1023086918.62768 -Isle of Man,IMN,1997,1180919719.40764 -Isle of Man,IMN,1998,1382548249.78303 -Isle of Man,IMN,1999,1567465656.8505 -Isle of Man,IMN,2000,1563667799.61578 -Isle of Man,IMN,2001,1614595290.9182 -Isle of Man,IMN,2002,1897606791.43353 -Isle of Man,IMN,2003,2264911806.90354 -Isle of Man,IMN,2004,2758117365.04863 -Isle of Man,IMN,2005,2971167185.35511 -Isle of Man,IMN,2006,3344402193.24608 -Isle of Man,IMN,2007,5685988395.35814 -Isle of Man,IMN,2008,5827468750 -Isle of Man,IMN,2009,5047909331.6716 -Isle of Man,IMN,2010,5420118974.04203 -Isle of Man,IMN,2011,6066454093.89521 -Isle of Man,IMN,2012,6433357030.0158 -Isle of Man,IMN,2013,6754330154.76004 -Isle of Man,IMN,2014,7428280401.5139 -Israel,ISR,1960,2598500000 -Israel,ISR,1961,3138500000 -Israel,ISR,1962,2510000000 -Israel,ISR,1963,2992333333.33333 -Israel,ISR,1964,3405333333.33333 -Israel,ISR,1965,3663333333.33333 -Israel,ISR,1966,3980000000 -Israel,ISR,1967,4030000000 -Israel,ISR,1968,4619000000 -Israel,ISR,1969,5329333333.33333 -Israel,ISR,1970,6267666666.66667 -Israel,ISR,1971,5851750000 -Israel,ISR,1972,7496250000 -Israel,ISR,1973,9692000000 -Israel,ISR,1974,13986250000 -Israel,ISR,1975,13028166666.6667 -Israel,ISR,1976,12359875000 -Israel,ISR,1977,14390000000 -Israel,ISR,1978,13967647058.8235 -Israel,ISR,1979,17796000000 -Israel,ISR,1980,21884705882.3529 -Israel,ISR,1981,23258596491.2281 -Israel,ISR,1982,24539341563.786 -Israel,ISR,1983,27442580071.1744 -Israel,ISR,1984,26043655184.1746 -Israel,ISR,1985,24121638985.495 -Israel,ISR,1986,29702243917.1932 -Israel,ISR,1987,35477234541.5778 -Israel,ISR,1988,43893303708.7998 -Israel,ISR,1989,44599771759.5491 -Israel,ISR,1990,52490327348.4773 -Israel,ISR,1991,59170286560.4844 -Israel,ISR,1992,65771216420.6417 -Israel,ISR,1993,65925583866.2945 -Israel,ISR,1994,74669719504.5 -Israel,ISR,1995,99968784246.0067 -Israel,ISR,1996,109774101575.963 -Israel,ISR,1997,114543978662.956 -Israel,ISR,1998,115838004263.046 -Israel,ISR,1999,117212358383.458 -Israel,ISR,2000,132396684080.151 -Israel,ISR,2001,130751599020.377 -Israel,ISR,2002,121092701253.746 -Israel,ISR,2003,126749741990.734 -Israel,ISR,2004,135418563141.455 -Israel,ISR,2005,142837533703.233 -Israel,ISR,2006,154511423313.434 -Israel,ISR,2007,179564275455.807 -Israel,ISR,2008,216760312151.616 -Israel,ISR,2009,208068814688.605 -Israel,ISR,2010,233754747258.625 -Israel,ISR,2011,261374751963.332 -Israel,ISR,2012,257641795689.722 -Israel,ISR,2013,293314777888.557 -Israel,ISR,2014,308769389865.564 -Israel,ISR,2015,299415714726.768 -Israel,ISR,2016,318743685882.414 -Italy,ITA,1960,40385288344.1911 -Italy,ITA,1961,44842760293.1924 -Italy,ITA,1962,50383891898.9911 -Italy,ITA,1963,57710743059.8341 -Italy,ITA,1964,63175417019.0094 -Italy,ITA,1965,67978153850.5191 -Italy,ITA,1966,73654870011.2757 -Italy,ITA,1967,81133120065.4202 -Italy,ITA,1968,87942231678.3505 -Italy,ITA,1969,97085082807.3751 -Italy,ITA,1970,113021272614.622 -Italy,ITA,1971,124261125780.275 -Italy,ITA,1972,144780888114.21 -Italy,ITA,1973,174913182995.683 -Italy,ITA,1974,198906211372.432 -Italy,ITA,1975,226944778173.191 -Italy,ITA,1976,223976031867.876 -Italy,ITA,1977,256746611586.57 -Italy,ITA,1978,314019079397.673 -Italy,ITA,1979,392378586343.51 -Italy,ITA,1980,475682508026.227 -Italy,ITA,1981,429282144779.424 -Italy,ITA,1982,425863253400.143 -Italy,ITA,1983,441580964558.899 -Italy,ITA,1984,436443282455.367 -Italy,ITA,1985,450725817665.551 -Italy,ITA,1986,638273988310.17 -Italy,ITA,1987,803055421720.944 -Italy,ITA,1988,888667916542.696 -Italy,ITA,1989,925598071408.411 -Italy,ITA,1990,1177326298642.53 -Italy,ITA,1991,1242109402060.25 -Italy,ITA,1992,1315806990573.45 -Italy,ITA,1993,1061445229481.97 -Italy,ITA,1994,1095590837536.02 -Italy,ITA,1995,1170787357066.44 -Italy,ITA,1996,1308929305684.53 -Italy,ITA,1997,1239050936221.01 -Italy,ITA,1998,1266309223820.68 -Italy,ITA,1999,1248563148945.24 -Italy,ITA,2000,1141760021927.4 -Italy,ITA,2001,1162317840447.43 -Italy,ITA,2002,1266510668642.95 -Italy,ITA,2003,1569649631715.58 -Italy,ITA,2004,1798314755525.2 -Italy,ITA,2005,1852661936077.6 -Italy,ITA,2006,1942633841801.53 -Italy,ITA,2007,2203053327128.39 -Italy,ITA,2008,2390729210487.77 -Italy,ITA,2009,2185160158794.11 -Italy,ITA,2010,2125058270201.64 -Italy,ITA,2011,2276292459232.78 -Italy,ITA,2012,2072823111961.1 -Italy,ITA,2013,2130491269673.44 -Italy,ITA,2014,2151732834411.5 -Italy,ITA,2015,1824902219021.73 -Italy,ITA,2016,1849970464191.78 -Jamaica,JAM,1960,699050678.98642 -Jamaica,JAM,1961,748028839.423211 -Jamaica,JAM,1962,777712445.751085 -Jamaica,JAM,1963,826690466.190676 -Jamaica,JAM,1964,897931401.371972 -Jamaica,JAM,1965,972140557.188856 -Jamaica,JAM,1966,1096738065.2387 -Jamaica,JAM,1967,1148025407.34604 -Jamaica,JAM,1968,1083883355.33421 -Jamaica,JAM,1969,1191287651.50606 -Jamaica,JAM,1970,1404776071.04284 -Jamaica,JAM,1971,1539865513.92891 -Jamaica,JAM,1972,1875048859.93485 -Jamaica,JAM,1973,1905917553.19149 -Jamaica,JAM,1974,2375096249.03751 -Jamaica,JAM,1975,2860411285.88714 -Jamaica,JAM,1976,2966010229.8977 -Jamaica,JAM,1977,3249697393.02607 -Jamaica,JAM,1978,2644449232.29321 -Jamaica,JAM,1979,2425033998.18676 -Jamaica,JAM,1980,2679409453.23903 -Jamaica,JAM,1981,2979061412.37229 -Jamaica,JAM,1982,3293533288.42483 -Jamaica,JAM,1983,3619294120.69144 -Jamaica,JAM,1984,2373566957.49214 -Jamaica,JAM,1985,2100223149.71396 -Jamaica,JAM,1986,2754566176.20212 -Jamaica,JAM,1987,3286987551.71597 -Jamaica,JAM,1988,3828310734.97795 -Jamaica,JAM,1989,4404970058.83786 -Jamaica,JAM,1990,4592224067.37194 -Jamaica,JAM,1991,4071219198.03601 -Jamaica,JAM,1992,3530892749.02131 -Jamaica,JAM,1993,4859766160.89207 -Jamaica,JAM,1994,4907861405.82758 -Jamaica,JAM,1995,5779285207.92079 -Jamaica,JAM,1996,6504445801.34228 -Jamaica,JAM,1997,7450324787.38384 -Jamaica,JAM,1998,8718300136.42565 -Jamaica,JAM,1999,8795765306.12245 -Jamaica,JAM,2000,8929375580.31569 -Jamaica,JAM,2001,9087918836.80556 -Jamaica,JAM,2002,9694161516.27524 -Jamaica,JAM,2003,9399452787.8474 -Jamaica,JAM,2004,10150978154.5484 -Jamaica,JAM,2005,11204416000 -Jamaica,JAM,2006,11905525197.3285 -Jamaica,JAM,2007,12824094989.8639 -Jamaica,JAM,2008,13678551837.6303 -Jamaica,JAM,2009,12038998756.9217 -Jamaica,JAM,2010,13192229343.0991 -Jamaica,JAM,2011,14440457548.68 -Jamaica,JAM,2012,14802430172.5391 -Jamaica,JAM,2013,14276559215.7309 -Jamaica,JAM,2014,13897561173.4853 -Jamaica,JAM,2015,14261995113.6721 -Jamaica,JAM,2016,14027151472.7053 -Japan,JPN,1960,44307342950.4 -Japan,JPN,1961,53508617739.3778 -Japan,JPN,1962,60723018683.7333 -Japan,JPN,1963,69498131797.3333 -Japan,JPN,1964,81749006381.5111 -Japan,JPN,1965,90950278257.7778 -Japan,JPN,1966,105628070343.111 -Japan,JPN,1967,123781880217.6 -Japan,JPN,1968,146601072685.511 -Japan,JPN,1969,172204199480.889 -Japan,JPN,1970,211514189326.389 -Japan,JPN,1971,238914956436.922 -Japan,JPN,1972,316393344649.993 -Japan,JPN,1973,429857320166.565 -Japan,JPN,1974,477155786487.722 -Japan,JPN,1975,518855814542.728 -Japan,JPN,1976,583142956487.974 -Japan,JPN,1977,717696307916.651 -Japan,JPN,1978,1008391778690.25 -Japan,JPN,1979,1049578503045.09 -Japan,JPN,1980,1099692917412.75 -Japan,JPN,1981,1215508719880.85 -Japan,JPN,1982,1129894523635.09 -Japan,JPN,1983,1232343804284.17 -Japan,JPN,1984,1309740021609.74 -Japan,JPN,1985,1400714806812.65 -Japan,JPN,1986,2075034242192.31 -Japan,JPN,1987,2514283894261.86 -Japan,JPN,1988,3050637784817.52 -Japan,JPN,1989,3052315661954.82 -Japan,JPN,1990,3139974443543 -Japan,JPN,1991,3578139437172.02 -Japan,JPN,1992,3897826229662.86 -Japan,JPN,1993,4466565327401.26 -Japan,JPN,1994,4907039384469.68 -Japan,JPN,1995,5449116304981.1 -Japan,JPN,1996,4833712542207.1 -Japan,JPN,1997,4414732843544.43 -Japan,JPN,1998,4032509760872.94 -Japan,JPN,1999,4562078822335.45 -Japan,JPN,2000,4887519660744.86 -Japan,JPN,2001,4303544259842.72 -Japan,JPN,2002,4115116279069.77 -Japan,JPN,2003,4445658071221.86 -Japan,JPN,2004,4815148854362.11 -Japan,JPN,2005,4755410630912.14 -Japan,JPN,2006,4530377224970.4 -Japan,JPN,2007,4515264514430.57 -Japan,JPN,2008,5037908465114.48 -Japan,JPN,2009,5231382674593.7 -Japan,JPN,2010,5700098114744.41 -Japan,JPN,2011,6157459594823.72 -Japan,JPN,2012,6203213121334.12 -Japan,JPN,2013,5155717056270.83 -Japan,JPN,2014,4848733415523.53 -Japan,JPN,2015,4383076298081.86 -Japan,JPN,2016,4939383909875.27 -Jordan,JOR,1965,599831979.837581 -Jordan,JOR,1966,658078969.476337 -Jordan,JOR,1967,631755810.697284 -Jordan,JOR,1968,561187342.481098 -Jordan,JOR,1969,698963875.66508 -Jordan,JOR,1970,639596751.610193 -Jordan,JOR,1971,678241388.966676 -Jordan,JOR,1972,788574628.955475 -Jordan,JOR,1973,943700547.778454 -Jordan,JOR,1974,1197454206.76808 -Jordan,JOR,1975,1363039399.62477 -Jordan,JOR,1976,1708734939.75904 -Jordan,JOR,1977,2096568478.59095 -Jordan,JOR,1978,2602748691.09948 -Jordan,JOR,1979,3271728271.72827 -Jordan,JOR,1980,3910036925.14267 -Jordan,JOR,1981,4384685230.02421 -Jordan,JOR,1982,4680567375.88653 -Jordan,JOR,1983,4920407601.21179 -Jordan,JOR,1984,4966710013.0039 -Jordan,JOR,1985,4993829194.12063 -Jordan,JOR,1986,6401380000 -Jordan,JOR,1987,6755599113.73707 -Jordan,JOR,1988,6277197435.2124 -Jordan,JOR,1989,4220945005.22102 -Jordan,JOR,1990,4160003917.43258 -Jordan,JOR,1991,4344250257.01278 -Jordan,JOR,1992,5311329067.37276 -Jordan,JOR,1993,5605841535.57512 -Jordan,JOR,1994,6237739516.24445 -Jordan,JOR,1995,6727446632.42009 -Jordan,JOR,1996,6928359238.36389 -Jordan,JOR,1997,7246188575.45839 -Jordan,JOR,1998,7912327362.48237 -Jordan,JOR,1999,8149106064.88011 -Jordan,JOR,2000,8460424400.56418 -Jordan,JOR,2001,8975689844.8519 -Jordan,JOR,2002,9582453032.44006 -Jordan,JOR,2003,10195660789.8449 -Jordan,JOR,2004,11411390409.0268 -Jordan,JOR,2005,12588665303.244 -Jordan,JOR,2006,15056929760.2257 -Jordan,JOR,2007,17110587447.1086 -Jordan,JOR,2008,21972004086.2336 -Jordan,JOR,2009,23820230000 -Jordan,JOR,2010,26425379436.6197 -Jordan,JOR,2011,28840263380.2817 -Jordan,JOR,2012,30937277605.6338 -Jordan,JOR,2013,33593843661.9718 -Jordan,JOR,2014,35826925774.6479 -Jordan,JOR,2015,37517410281.6901 -Jordan,JOR,2016,38654727746.4789 -Kazakhstan,KAZ,1990,26932728898.8146 -Kazakhstan,KAZ,1991,24881135586.399 -Kazakhstan,KAZ,1992,24906939560.1098 -Kazakhstan,KAZ,1993,23409027475.6879 -Kazakhstan,KAZ,1994,21250839258.0901 -Kazakhstan,KAZ,1995,20374307047.115 -Kazakhstan,KAZ,1996,21035357832.8019 -Kazakhstan,KAZ,1997,22165932062.966 -Kazakhstan,KAZ,1998,22135245413.2312 -Kazakhstan,KAZ,1999,16870817134.7767 -Kazakhstan,KAZ,2000,18291990619.137 -Kazakhstan,KAZ,2001,22152689129.5583 -Kazakhstan,KAZ,2002,24636598581.0204 -Kazakhstan,KAZ,2003,30833692831.3955 -Kazakhstan,KAZ,2004,43151647002.6096 -Kazakhstan,KAZ,2005,57123671733.8952 -Kazakhstan,KAZ,2006,81003884545.4099 -Kazakhstan,KAZ,2007,104849886825.584 -Kazakhstan,KAZ,2008,133441612246.798 -Kazakhstan,KAZ,2009,115308661142.927 -Kazakhstan,KAZ,2010,148047348240.643 -Kazakhstan,KAZ,2011,192626507971.584 -Kazakhstan,KAZ,2012,207998568865.789 -Kazakhstan,KAZ,2013,236634552078.102 -Kazakhstan,KAZ,2014,221415572819.5 -Kazakhstan,KAZ,2015,184388432148.715 -Kazakhstan,KAZ,2016,133657084404.957 -Kenya,KEN,1960,791265458.813328 -Kenya,KEN,1961,792959472.134266 -Kenya,KEN,1962,868111400.008864 -Kenya,KEN,1963,926589348.567393 -Kenya,KEN,1964,998759333.637333 -Kenya,KEN,1965,997919319.974061 -Kenya,KEN,1966,1164519673.19064 -Kenya,KEN,1967,1232559505.9162 -Kenya,KEN,1968,1353295457.51798 -Kenya,KEN,1969,1458379415.39403 -Kenya,KEN,1970,1603447357.24209 -Kenya,KEN,1971,1778391289.20054 -Kenya,KEN,1972,2107279157.38336 -Kenya,KEN,1973,2502142444.14182 -Kenya,KEN,1974,2973309272.02986 -Kenya,KEN,1975,3259344935.75357 -Kenya,KEN,1976,3474542392.04597 -Kenya,KEN,1977,4494378855.32203 -Kenya,KEN,1978,5303734882.51159 -Kenya,KEN,1979,6234390975.29871 -Kenya,KEN,1980,7265315331.62273 -Kenya,KEN,1981,6854491453.91471 -Kenya,KEN,1982,6431579357.30273 -Kenya,KEN,1983,5979198463.82274 -Kenya,KEN,1984,6191437070.43467 -Kenya,KEN,1985,6135034338.30431 -Kenya,KEN,1986,7239126716.93219 -Kenya,KEN,1987,7970820530.76691 -Kenya,KEN,1988,8355380879.12955 -Kenya,KEN,1989,8283114648.38116 -Kenya,KEN,1990,8572359162.86876 -Kenya,KEN,1991,8151479004.21334 -Kenya,KEN,1992,8209129171.73649 -Kenya,KEN,1993,5751789915.05363 -Kenya,KEN,1994,7148145375.78545 -Kenya,KEN,1995,9046326059.98857 -Kenya,KEN,1996,12045858436.2399 -Kenya,KEN,1997,13115773737.5664 -Kenya,KEN,1998,14093998843.7334 -Kenya,KEN,1999,12896013576.7324 -Kenya,KEN,2000,12705357103.0056 -Kenya,KEN,2001,12986007425.8781 -Kenya,KEN,2002,13147743910.7241 -Kenya,KEN,2003,14904517649.8476 -Kenya,KEN,2004,16095337093.8366 -Kenya,KEN,2005,18737897744.7948 -Kenya,KEN,2006,25825524820.8064 -Kenya,KEN,2007,31958195182.2406 -Kenya,KEN,2008,35895153327.8497 -Kenya,KEN,2009,37021512048.8158 -Kenya,KEN,2010,39999659233.7555 -Kenya,KEN,2011,41953433591.4101 -Kenya,KEN,2012,50412754821.9795 -Kenya,KEN,2013,55097343447.5616 -Kenya,KEN,2014,61445345999.0765 -Kenya,KEN,2015,63767539356.6051 -Kenya,KEN,2016,70529014778.3251 -Kiribati,KIR,1970,14295279.5446937 -Kiribati,KIR,1971,15278632.4786325 -Kiribati,KIR,1972,18936526.9461078 -Kiribati,KIR,1973,31710657.7257811 -Kiribati,KIR,1974,85637174.3722131 -Kiribati,KIR,1975,55081816.9917528 -Kiribati,KIR,1976,41109617.4996945 -Kiribati,KIR,1977,38748059.4366822 -Kiribati,KIR,1978,45210026.3248255 -Kiribati,KIR,1979,42620165.4370668 -Kiribati,KIR,1980,38715554.5433842 -Kiribati,KIR,1981,41369800.0459664 -Kiribati,KIR,1982,40572066.1324678 -Kiribati,KIR,1983,37837837.8378378 -Kiribati,KIR,1984,41246160.596753 -Kiribati,KIR,1985,32125148.4042182 -Kiribati,KIR,1986,32085561.4973262 -Kiribati,KIR,1987,33608738.2719507 -Kiribati,KIR,1988,42972107.1958747 -Kiribati,KIR,1989,41119721.651115 -Kiribati,KIR,1990,39809538.6776989 -Kiribati,KIR,1991,47515189.2818196 -Kiribati,KIR,1992,47737955.346651 -Kiribati,KIR,1993,46919624.6430029 -Kiribati,KIR,1994,54832577.8622606 -Kiribati,KIR,1995,56338028.1690141 -Kiribati,KIR,1996,66515376.7900462 -Kiribati,KIR,1997,67537479.5903221 -Kiribati,KIR,1998,65334841.0604347 -Kiribati,KIR,1999,69032258.0645161 -Kiribati,KIR,2000,67254174.3970315 -Kiribati,KIR,2001,63101272.3699183 -Kiribati,KIR,2002,72196457.6768445 -Kiribati,KIR,2003,90231856.8000519 -Kiribati,KIR,2004,102367039.270481 -Kiribati,KIR,2005,112133944.253532 -Kiribati,KIR,2006,108545632.53012 -Kiribati,KIR,2007,130754915.906619 -Kiribati,KIR,2008,139125482.301627 -Kiribati,KIR,2009,130465372.016846 -Kiribati,KIR,2010,153275912.676573 -Kiribati,KIR,2011,177142135.121196 -Kiribati,KIR,2012,188045661.627666 -Kiribati,KIR,2013,187153601.08129 -Kiribati,KIR,2014,186066973.138634 -Kiribati,KIR,2015,160121929.231463 -Kiribati,KIR,2016,165765016.354445 -"Korea, Rep.",KOR,1960,3957873925.93719 -"Korea, Rep.",KOR,1961,2417237753.94419 -"Korea, Rep.",KOR,1962,2813933899.74577 -"Korea, Rep.",KOR,1963,3988246108.63888 -"Korea, Rep.",KOR,1964,3458518493.92483 -"Korea, Rep.",KOR,1965,3120307807.80781 -"Korea, Rep.",KOR,1966,3928171298.00251 -"Korea, Rep.",KOR,1967,4854576371.4328 -"Korea, Rep.",KOR,1968,6117260075.90819 -"Korea, Rep.",KOR,1969,7675805108.27318 -"Korea, Rep.",KOR,1970,8999227202.47295 -"Korea, Rep.",KOR,1971,9889961111.91128 -"Korea, Rep.",KOR,1972,10842220468.8335 -"Korea, Rep.",KOR,1973,13841885920.8676 -"Korea, Rep.",KOR,1974,19482038222.8595 -"Korea, Rep.",KOR,1975,21704752066.1157 -"Korea, Rep.",KOR,1976,29779338842.9752 -"Korea, Rep.",KOR,1977,38265082644.6281 -"Korea, Rep.",KOR,1978,51700619834.7107 -"Korea, Rep.",KOR,1979,66567975206.6116 -"Korea, Rep.",KOR,1980,64980820835.3226 -"Korea, Rep.",KOR,1981,72425590649.4574 -"Korea, Rep.",KOR,1982,77773431088.253 -"Korea, Rep.",KOR,1983,87024427972.9294 -"Korea, Rep.",KOR,1984,96597434179.5082 -"Korea, Rep.",KOR,1985,100273097170.18 -"Korea, Rep.",KOR,1986,115537126325.94 -"Korea, Rep.",KOR,1987,146133338196.141 -"Korea, Rep.",KOR,1988,196964195387.371 -"Korea, Rep.",KOR,1989,243526047716.915 -"Korea, Rep.",KOR,1990,279349355713.801 -"Korea, Rep.",KOR,1991,325734233312.879 -"Korea, Rep.",KOR,1992,350051111253.443 -"Korea, Rep.",KOR,1993,386302839273.923 -"Korea, Rep.",KOR,1994,455602962225.403 -"Korea, Rep.",KOR,1995,556130926912.754 -"Korea, Rep.",KOR,1996,598099073901.423 -"Korea, Rep.",KOR,1997,557503074772.151 -"Korea, Rep.",KOR,1998,374241351752.483 -"Korea, Rep.",KOR,1999,485248229336.653 -"Korea, Rep.",KOR,2000,561633125839.994 -"Korea, Rep.",KOR,2001,533052076313.527 -"Korea, Rep.",KOR,2002,609020054512.465 -"Korea, Rep.",KOR,2003,680520724062.403 -"Korea, Rep.",KOR,2004,764880644710.649 -"Korea, Rep.",KOR,2005,898137194716.188 -"Korea, Rep.",KOR,2006,1011797457138.5 -"Korea, Rep.",KOR,2007,1122679154632.41 -"Korea, Rep.",KOR,2008,1002219052967.54 -"Korea, Rep.",KOR,2009,901934953364.711 -"Korea, Rep.",KOR,2010,1094499338702.72 -"Korea, Rep.",KOR,2011,1202463682633.85 -"Korea, Rep.",KOR,2012,1222807284485.31 -"Korea, Rep.",KOR,2013,1305604981271.91 -"Korea, Rep.",KOR,2014,1411333926201.24 -"Korea, Rep.",KOR,2015,1382764027113.82 -"Korea, Rep.",KOR,2016,1411245589976.63 -Kosovo,XKX,2000,1849196082.05507 -Kosovo,XKX,2001,2535333631.88536 -Kosovo,XKX,2002,2702427046.9355 -Kosovo,XKX,2003,3355083116.58939 -Kosovo,XKX,2004,3639935347.50715 -Kosovo,XKX,2005,3736599925.38241 -Kosovo,XKX,2006,4078158323.92423 -Kosovo,XKX,2007,4833561456.33726 -Kosovo,XKX,2008,5687488208.58356 -Kosovo,XKX,2009,5653792720.20006 -Kosovo,XKX,2010,5829933774.83444 -Kosovo,XKX,2011,6649291075.89658 -Kosovo,XKX,2012,6473724784.78736 -Kosovo,XKX,2013,7072092405.73553 -Kosovo,XKX,2014,7386891336.07536 -Kosovo,XKX,2015,6440501275.36875 -Kosovo,XKX,2016,6649888888.88889 -Kuwait,KWT,1965,2097451694.2033 -Kuwait,KWT,1966,2391486978.43741 -Kuwait,KWT,1967,2441893027.16326 -Kuwait,KWT,1968,2663119574.34892 -Kuwait,KWT,1969,2769532343.88127 -Kuwait,KWT,1970,2873984878.18538 -Kuwait,KWT,1971,3880370401.57259 -Kuwait,KWT,1972,4451200972.9401 -Kuwait,KWT,1973,5408293998.65138 -Kuwait,KWT,1974,13004774556.6166 -Kuwait,KWT,1975,12024138275.8621 -Kuwait,KWT,1976,13131668946.6484 -Kuwait,KWT,1977,14135729588.2763 -Kuwait,KWT,1978,15500908760.4507 -Kuwait,KWT,1979,24746019536.903 -Kuwait,KWT,1980,28638550499.4451 -Kuwait,KWT,1981,25056672166.4275 -Kuwait,KWT,1982,21577977770.059 -Kuwait,KWT,1983,20869434305.3173 -Kuwait,KWT,1984,21697297872.3404 -Kuwait,KWT,1985,21442619680.8511 -Kuwait,KWT,1986,17903681693.0489 -Kuwait,KWT,1987,22365734481.5213 -Kuwait,KWT,1988,20692472759.8566 -Kuwait,KWT,1989,24312117767.1886 -Kuwait,KWT,1990,18427777777.7778 -Kuwait,KWT,1991,11008793176.2223 -Kuwait,KWT,1992,19858555214.7239 -Kuwait,KWT,1993,23941391390.7285 -Kuwait,KWT,1994,24848483838.3838 -Kuwait,KWT,1995,27191689008.0429 -Kuwait,KWT,1996,31493987641.9506 -Kuwait,KWT,1997,30354434553.2476 -Kuwait,KWT,1998,25941929461.9423 -Kuwait,KWT,1999,30121879434.954 -Kuwait,KWT,2000,37711864406.7797 -Kuwait,KWT,2001,34890772742.0933 -Kuwait,KWT,2002,38137545245.1464 -Kuwait,KWT,2003,47875838926.1745 -Kuwait,KWT,2004,59440108585.0017 -Kuwait,KWT,2005,80797945205.4795 -Kuwait,KWT,2006,101550654720.882 -Kuwait,KWT,2007,114641097818.438 -Kuwait,KWT,2008,147395833333.333 -Kuwait,KWT,2009,105899930507.297 -Kuwait,KWT,2010,115419050942.08 -Kuwait,KWT,2011,154027536231.884 -Kuwait,KWT,2012,174070025008.932 -Kuwait,KWT,2013,174161495063.47 -Kuwait,KWT,2014,162631763879.129 -Kuwait,KWT,2015,114041209704.221 -Kyrgyz Republic,KGZ,1990,2674000000 -Kyrgyz Republic,KGZ,1991,2570833333.33333 -Kyrgyz Republic,KGZ,1992,2316562500 -Kyrgyz Republic,KGZ,1993,2028295454.54545 -Kyrgyz Republic,KGZ,1994,1681006993.00699 -Kyrgyz Republic,KGZ,1995,1661018518.51852 -Kyrgyz Republic,KGZ,1996,1827570586.16784 -Kyrgyz Republic,KGZ,1997,1767864035.71943 -Kyrgyz Republic,KGZ,1998,1645963749.83146 -Kyrgyz Republic,KGZ,1999,1249062025.13805 -Kyrgyz Republic,KGZ,2000,1369693171.43504 -Kyrgyz Republic,KGZ,2001,1525112241.84376 -Kyrgyz Republic,KGZ,2002,1605640633.42189 -Kyrgyz Republic,KGZ,2003,1919012780.97086 -Kyrgyz Republic,KGZ,2004,2211535311.62834 -Kyrgyz Republic,KGZ,2005,2460248026.17783 -Kyrgyz Republic,KGZ,2006,2834168889.42019 -Kyrgyz Republic,KGZ,2007,3802566170.81543 -Kyrgyz Republic,KGZ,2008,5139957784.91084 -Kyrgyz Republic,KGZ,2009,4690062255.12247 -Kyrgyz Republic,KGZ,2010,4794357795.07139 -Kyrgyz Republic,KGZ,2011,6197766118.59856 -Kyrgyz Republic,KGZ,2012,6605139933.41063 -Kyrgyz Republic,KGZ,2013,7335027591.91628 -Kyrgyz Republic,KGZ,2014,7468096566.71158 -Kyrgyz Republic,KGZ,2015,6678178340.45121 -Kyrgyz Republic,KGZ,2016,6551287937.62632 -Lao PDR,LAO,1984,1757142805.71429 -Lao PDR,LAO,1985,2366666615.55556 -Lao PDR,LAO,1986,1776842041.05263 -Lao PDR,LAO,1987,1087273103.69639 -Lao PDR,LAO,1988,598961269.297879 -Lao PDR,LAO,1989,714046821.093797 -Lao PDR,LAO,1990,865559856.1639 -Lao PDR,LAO,1991,1028087972.31085 -Lao PDR,LAO,1992,1127806944.61513 -Lao PDR,LAO,1993,1327748654.65969 -Lao PDR,LAO,1994,1543606345.11684 -Lao PDR,LAO,1995,1763536304.53964 -Lao PDR,LAO,1996,1873671550.34636 -Lao PDR,LAO,1997,1747011857.33107 -Lao PDR,LAO,1998,1280177838.71905 -Lao PDR,LAO,1999,1454430642.49183 -Lao PDR,LAO,2000,1731198022.45494 -Lao PDR,LAO,2001,1768619058.34647 -Lao PDR,LAO,2002,1758176653.07746 -Lao PDR,LAO,2003,2023324407.30316 -Lao PDR,LAO,2004,2366398119.8821 -Lao PDR,LAO,2005,2735558726.25625 -Lao PDR,LAO,2006,3452882514.00166 -Lao PDR,LAO,2007,4222962987.53859 -Lao PDR,LAO,2008,5443915120.50795 -Lao PDR,LAO,2009,5832915387.08908 -Lao PDR,LAO,2010,7127792629.58294 -Lao PDR,LAO,2011,8261299199.6817 -Lao PDR,LAO,2012,10191367558.2708 -Lao PDR,LAO,2013,11942157500.4254 -Lao PDR,LAO,2014,13268297521.6066 -Lao PDR,LAO,2015,14390323462.0115 -Lao PDR,LAO,2016,15903437789.8552 -Latvia,LVA,1995,5788368511.12379 -Latvia,LVA,1996,5970044665.64574 -Latvia,LVA,1997,6525676264.21486 -Latvia,LVA,1998,7174985106.63648 -Latvia,LVA,1999,7533187605.09248 -Latvia,LVA,2000,7937758980.30127 -Latvia,LVA,2001,8350252966.19655 -Latvia,LVA,2002,9546441564.34743 -Latvia,LVA,2003,11748433157.0533 -Latvia,LVA,2004,14373269155.7174 -Latvia,LVA,2005,16922504044.804 -Latvia,LVA,2006,21447021570.1028 -Latvia,LVA,2007,30901399261.387 -Latvia,LVA,2008,35596016664.2304 -Latvia,LVA,2009,26169854045.0375 -Latvia,LVA,2010,23757368290.0955 -Latvia,LVA,2011,28223552824.7508 -Latvia,LVA,2012,28119996053.2511 -Latvia,LVA,2013,30254571077.6726 -Latvia,LVA,2014,31352249349.5712 -Latvia,LVA,2015,27026037600.3392 -Latvia,LVA,2016,27677391316.3405 -Lebanon,LBN,1988,3313540067.93246 -Lebanon,LBN,1989,2717998687.71002 -Lebanon,LBN,1990,2838485353.96187 -Lebanon,LBN,1991,4451497288.27108 -Lebanon,LBN,1992,5545921947.46583 -Lebanon,LBN,1993,7535259851.03597 -Lebanon,LBN,1994,9599127049.9375 -Lebanon,LBN,1995,11718795528.4939 -Lebanon,LBN,1996,13690217333.2697 -Lebanon,LBN,1997,15751867489.4446 -Lebanon,LBN,1998,17247179005.5219 -Lebanon,LBN,1999,17391056369.2265 -Lebanon,LBN,2000,17260364842.4544 -Lebanon,LBN,2001,17649751243.7811 -Lebanon,LBN,2002,19152238805.9701 -Lebanon,LBN,2003,20082918739.6352 -Lebanon,LBN,2004,20955223880.597 -Lebanon,LBN,2005,21287562189.0547 -Lebanon,LBN,2006,21796351575.4561 -Lebanon,LBN,2007,24577114427.8607 -Lebanon,LBN,2008,28829850746.2687 -Lebanon,LBN,2009,35139635157.5456 -Lebanon,LBN,2010,38009950248.7562 -Lebanon,LBN,2011,40078938640.1327 -Lebanon,LBN,2012,43205095854.063 -Lebanon,LBN,2013,44352417910.4478 -Lebanon,LBN,2014,45730945273.6318 -Lebanon,LBN,2015,47084703150.9121 -Lebanon,LBN,2016,47536798648.0929 -Lesotho,LSO,1960,34579308.4138317 -Lesotho,LSO,1961,35699286.0142797 -Lesotho,LSO,1962,41859162.8167437 -Lesotho,LSO,1963,47039059.2188156 -Lesotho,LSO,1964,51938961.2207756 -Lesotho,LSO,1965,54878902.4219516 -Lesotho,LSO,1966,56698866.0226795 -Lesotho,LSO,1967,59260814.7837043 -Lesotho,LSO,1968,61444771.1045779 -Lesotho,LSO,1969,65966680.6663867 -Lesotho,LSO,1970,68738625.2274955 -Lesotho,LSO,1971,76482102.9082774 -Lesotho,LSO,1972,80915831.9240276 -Lesotho,LSO,1973,121181556.195965 -Lesotho,LSO,1974,150846210.448859 -Lesotho,LSO,1975,149560513.860717 -Lesotho,LSO,1976,147654093.836247 -Lesotho,LSO,1977,193307267.709292 -Lesotho,LSO,1978,266559337.626495 -Lesotho,LSO,1979,290142517.814727 -Lesotho,LSO,1980,431561376.476631 -Lesotho,LSO,1981,434188034.188034 -Lesotho,LSO,1982,348746792.515574 -Lesotho,LSO,1983,386699344.059023 -Lesotho,LSO,1984,333158502.306626 -Lesotho,LSO,1985,268626893.690796 -Lesotho,LSO,1986,318862870.333317 -Lesotho,LSO,1987,402774850.256341 -Lesotho,LSO,1988,470389190.094405 -Lesotho,LSO,1989,495404890.865006 -Lesotho,LSO,1990,596415106.633185 -Lesotho,LSO,1991,704329193.303687 -Lesotho,LSO,1992,831033946.369022 -Lesotho,LSO,1993,835592816.316424 -Lesotho,LSO,1994,878250452.815718 -Lesotho,LSO,1995,1001889845.5807 -Lesotho,LSO,1996,946123280.510758 -Lesotho,LSO,1997,997996034.86775 -Lesotho,LSO,1998,928458201.135383 -Lesotho,LSO,1999,912771283.593936 -Lesotho,LSO,2000,887295262.184165 -Lesotho,LSO,2001,825706966.802027 -Lesotho,LSO,2002,775780697.302945 -Lesotho,LSO,2003,1157832935.83899 -Lesotho,LSO,2004,1511236652.019 -Lesotho,LSO,2005,1682350941.54943 -Lesotho,LSO,2006,1800105593.03747 -Lesotho,LSO,2007,1820597204.99096 -Lesotho,LSO,2008,1868776303.14958 -Lesotho,LSO,2009,1864004707.45587 -Lesotho,LSO,2010,2394097298.85591 -Lesotho,LSO,2011,2791545696.37485 -Lesotho,LSO,2012,2678243067.38507 -Lesotho,LSO,2013,2532392022.47022 -Lesotho,LSO,2014,2520952363.38624 -Lesotho,LSO,2015,2335194894.3494 -Lesotho,LSO,2016,2199709488.86039 -Liberia,LBR,1960,190495600 -Liberia,LBR,1961,183920900 -Liberia,LBR,1962,191861800 -Liberia,LBR,1963,200229600 -Liberia,LBR,1964,218929100 -Liberia,LBR,1965,229260800 -Liberia,LBR,1966,244459500 -Liberia,LBR,1967,261024300 -Liberia,LBR,1968,276820700 -Liberia,LBR,1969,306961800 -Liberia,LBR,1970,323099700 -Liberia,LBR,1971,341543100 -Liberia,LBR,1972,368098000 -Liberia,LBR,1973,386968300 -Liberia,LBR,1974,486955000 -Liberia,LBR,1975,577549300 -Liberia,LBR,1976,596675700 -Liberia,LBR,1977,673010600 -Liberia,LBR,1978,717240400 -Liberia,LBR,1979,814067900 -Liberia,LBR,1980,854711500 -Liberia,LBR,1981,846514500 -Liberia,LBR,1982,863933200 -Liberia,LBR,1983,823374900 -Liberia,LBR,1984,848478300 -Liberia,LBR,1985,851296100 -Liberia,LBR,1986,840964400 -Liberia,LBR,1987,972800000 -Liberia,LBR,1988,1038300000 -Liberia,LBR,1989,786300000 -Liberia,LBR,1990,384400000 -Liberia,LBR,1991,348000000 -Liberia,LBR,1992,223500000 -Liberia,LBR,1993,160400000 -Liberia,LBR,1994,132200000 -Liberia,LBR,1995,134800000 -Liberia,LBR,1996,159400000 -Liberia,LBR,1997,295900000 -Liberia,LBR,1998,359600000 -Liberia,LBR,1999,441800000 -Liberia,LBR,2000,529064600 -Liberia,LBR,2001,521000000 -Liberia,LBR,2002,543000000 -Liberia,LBR,2003,416000000 -Liberia,LBR,2004,474700000 -Liberia,LBR,2005,550000000 -Liberia,LBR,2006,604028900 -Liberia,LBR,2007,739027200 -Liberia,LBR,2008,850040500 -Liberia,LBR,2009,1155147400 -Liberia,LBR,2010,1292697100 -Liberia,LBR,2011,1545400000 -Liberia,LBR,2012,1735500000 -Liberia,LBR,2013,1946500000 -Liberia,LBR,2014,2013000000 -Liberia,LBR,2015,2034000000 -Liberia,LBR,2016,2101000000 -Libya,LBY,1990,28901836158.1921 -Libya,LBY,1991,31995012468.8279 -Libya,LBY,1992,33881392045.4545 -Libya,LBY,1993,30657030223.3903 -Libya,LBY,1994,28607921928.8175 -Libya,LBY,1995,25544128198.9955 -Libya,LBY,1996,27884615384.6154 -Libya,LBY,1997,30698633109.1343 -Libya,LBY,1998,27249786142.0017 -Libya,LBY,1999,35976714100.9056 -Libya,LBY,2000,38270206950.41 -Libya,LBY,2001,34110064452.1567 -Libya,LBY,2002,20481889763.7795 -Libya,LBY,2003,26265625000 -Libya,LBY,2004,33122307692.3077 -Libya,LBY,2005,47334148578.4164 -Libya,LBY,2006,54961936662.6066 -Libya,LBY,2007,67516236337.7158 -Libya,LBY,2008,87140405361.2292 -Libya,LBY,2009,63028320702.0343 -Libya,LBY,2010,74773444900.5368 -Libya,LBY,2011,34699395523.6073 -Liechtenstein,LIE,1970,90098330.6654471 -Liechtenstein,LIE,1971,104888628.171944 -Liechtenstein,LIE,1972,124941925.010473 -Liechtenstein,LIE,1973,165930611.729019 -Liechtenstein,LIE,1974,193983720.461869 -Liechtenstein,LIE,1975,246387479.177159 -Liechtenstein,LIE,1976,272493879.020643 -Liechtenstein,LIE,1977,303496276.263782 -Liechtenstein,LIE,1978,436918176.733781 -Liechtenstein,LIE,1979,503180669.994587 -Liechtenstein,LIE,1980,534701915.617354 -Liechtenstein,LIE,1981,511658690.561043 -Liechtenstein,LIE,1982,522090331.478107 -Liechtenstein,LIE,1983,524034109.856605 -Liechtenstein,LIE,1984,502617355.407073 -Liechtenstein,LIE,1985,529078995.563876 -Liechtenstein,LIE,1986,779365167.602424 -Liechtenstein,LIE,1987,1052843347.63948 -Liechtenstein,LIE,1988,1161757671.01756 -Liechtenstein,LIE,1989,1120000916.92646 -Liechtenstein,LIE,1990,1421466239.56234 -Liechtenstein,LIE,1991,1484152022.3152 -Liechtenstein,LIE,1992,1631197909.259 -Liechtenstein,LIE,1993,1673104493.77369 -Liechtenstein,LIE,1994,1948118227.68151 -Liechtenstein,LIE,1995,2428461395.34884 -Liechtenstein,LIE,1996,2504033252.42718 -Liechtenstein,LIE,1997,2298410390.68421 -Liechtenstein,LIE,1998,2479721340.8746 -Liechtenstein,LIE,1999,2664026095.06058 -Liechtenstein,LIE,2000,2483953102.79488 -Liechtenstein,LIE,2001,2491822706.80256 -Liechtenstein,LIE,2002,2688630822.53304 -Liechtenstein,LIE,2003,3070691319.52179 -Liechtenstein,LIE,2004,3454362685.96703 -Liechtenstein,LIE,2005,3659251525.8593 -Liechtenstein,LIE,2006,4000239272.61126 -Liechtenstein,LIE,2007,4601299566.81106 -Liechtenstein,LIE,2008,5081432924.0144 -Liechtenstein,LIE,2009,4504549214.22663 -Liechtenstein,LIE,2010,5082366478.08994 -Liechtenstein,LIE,2011,5739977477.47748 -Liechtenstein,LIE,2012,5456009384.66461 -Liechtenstein,LIE,2013,6391735893.83968 -Liechtenstein,LIE,2014,6663501418.90417 -Lithuania,LTU,1995,7870782260.51698 -Lithuania,LTU,1996,8385109020.28485 -Lithuania,LTU,1997,10120274492.8787 -Lithuania,LTU,1998,11240360897.7126 -Lithuania,LTU,1999,10972878636.1675 -Lithuania,LTU,2000,11539211480.3625 -Lithuania,LTU,2001,12252498921.0186 -Lithuania,LTU,2002,14278357283.7419 -Lithuania,LTU,2003,18802576988.1557 -Lithuania,LTU,2004,22649930576.2543 -Lithuania,LTU,2005,26125575942.2814 -Lithuania,LTU,2006,30216060233.4044 -Lithuania,LTU,2007,39738180076.6283 -Lithuania,LTU,2008,47850551148.8365 -Lithuania,LTU,2009,37440673477.8982 -Lithuania,LTU,2010,37120517693.8622 -Lithuania,LTU,2011,43476878139.2577 -Lithuania,LTU,2012,42847900765.8065 -Lithuania,LTU,2013,46473646001.5672 -Lithuania,LTU,2014,48545251795.561 -Lithuania,LTU,2015,41402022148.2053 -Lithuania,LTU,2016,42738875963.3703 -Luxembourg,LUX,1960,703925705.942958 -Luxembourg,LUX,1961,704145671.350213 -Luxembourg,LUX,1962,741509480.796284 -Luxembourg,LUX,1963,791140595.772755 -Luxembourg,LUX,1964,903158753.943622 -Luxembourg,LUX,1965,921600736.304026 -Luxembourg,LUX,1966,968440149.470951 -Luxembourg,LUX,1967,974721762.535327 -Luxembourg,LUX,1968,1066447130.82052 -Luxembourg,LUX,1969,1234878980.502 -Luxembourg,LUX,1970,1509155062.52521 -Luxembourg,LUX,1971,1572310771.77053 -Luxembourg,LUX,1972,1968733021.7212 -Luxembourg,LUX,1973,2701874663.63072 -Luxembourg,LUX,1974,3295861019.05551 -Luxembourg,LUX,1975,3233431611.27564 -Luxembourg,LUX,1976,3544268025.07837 -Luxembourg,LUX,1977,3922895891.95273 -Luxembourg,LUX,1978,4884869091.84066 -Luxembourg,LUX,1979,5711457760.04403 -Luxembourg,LUX,1980,6232005655.95255 -Luxembourg,LUX,1981,5231808670.14342 -Luxembourg,LUX,1982,4764549532.05015 -Luxembourg,LUX,1983,4683697830.37475 -Luxembourg,LUX,1984,4594891580.56409 -Luxembourg,LUX,1985,4738559684.76119 -Luxembourg,LUX,1986,6921264132.20155 -Luxembourg,LUX,1987,8614215559.15721 -Luxembourg,LUX,1988,9750161053.209 -Luxembourg,LUX,1989,10391504709.2547 -Luxembourg,LUX,1990,13229247947.8513 -Luxembourg,LUX,1991,14321878795.0384 -Luxembourg,LUX,1992,16065740777.9172 -Luxembourg,LUX,1993,16486900186.5672 -Luxembourg,LUX,1994,18325791415.4811 -Luxembourg,LUX,1995,21588170498.0843 -Luxembourg,LUX,1996,21776609771.987 -Luxembourg,LUX,1997,19731912494.3617 -Luxembourg,LUX,1998,20209122027.1171 -Luxembourg,LUX,1999,22235929043.2559 -Luxembourg,LUX,2000,21263514833.2412 -Luxembourg,LUX,2001,21272418791.9463 -Luxembourg,LUX,2002,23616328816.1114 -Luxembourg,LUX,2003,29557325056.4334 -Luxembourg,LUX,2004,34685281847.5292 -Luxembourg,LUX,2005,37347394602.6614 -Luxembourg,LUX,2006,42414308116.9239 -Luxembourg,LUX,2007,50888134410.0739 -Luxembourg,LUX,2008,55849686538.7432 -Luxembourg,LUX,2009,51370543206.4462 -Luxembourg,LUX,2010,53212476812.2957 -Luxembourg,LUX,2011,60004630234.4135 -Luxembourg,LUX,2012,56677961787.0717 -Luxembourg,LUX,2013,61808178300.1352 -Luxembourg,LUX,2014,66298060521.7586 -Luxembourg,LUX,2015,58048242436.0611 -Luxembourg,LUX,2016,59947781147.4776 -"Macao SAR, China",MAC,1982,1130457130.00739 -"Macao SAR, China",MAC,1983,1121486562.52512 -"Macao SAR, China",MAC,1984,1292297736.23885 -"Macao SAR, China",MAC,1985,1348827324.09861 -"Macao SAR, China",MAC,1986,1517496131.38322 -"Macao SAR, China",MAC,1987,1941246972.45874 -"Macao SAR, China",MAC,1988,2269233639.28065 -"Macao SAR, China",MAC,1989,2683254708.17411 -"Macao SAR, China",MAC,1990,3220920084.77746 -"Macao SAR, China",MAC,1991,3735117374.41125 -"Macao SAR, China",MAC,1992,4879018601.90911 -"Macao SAR, China",MAC,1993,5625533410.31176 -"Macao SAR, China",MAC,1994,6265844252.10105 -"Macao SAR, China",MAC,1995,6996034036.99892 -"Macao SAR, China",MAC,1996,7122539666.59972 -"Macao SAR, China",MAC,1997,7211264780.00828 -"Macao SAR, China",MAC,1998,6742367273.27418 -"Macao SAR, China",MAC,1999,6490571703.85015 -"Macao SAR, China",MAC,2000,6720492405.83611 -"Macao SAR, China",MAC,2001,6811227982.82193 -"Macao SAR, China",MAC,2002,7322677820.10108 -"Macao SAR, China",MAC,2003,8195033162.12038 -"Macao SAR, China",MAC,2004,10585624890.9277 -"Macao SAR, China",MAC,2005,12092222041.9168 -"Macao SAR, China",MAC,2006,14789661809.1834 -"Macao SAR, China",MAC,2007,18340447242.9971 -"Macao SAR, China",MAC,2008,20917444919.6394 -"Macao SAR, China",MAC,2009,21475520709.3922 -"Macao SAR, China",MAC,2010,28123640998.7253 -"Macao SAR, China",MAC,2011,36709860068.3445 -"Macao SAR, China",MAC,2012,43031577366.4251 -"Macao SAR, China",MAC,2013,51552075901.5183 -"Macao SAR, China",MAC,2014,55347998647.8196 -"Macao SAR, China",MAC,2015,45415278647.464 -"Macao SAR, China",MAC,2016,44802641829.9265 -"Macedonia, FYR",MKD,1990,4471828621.90813 -"Macedonia, FYR",MKD,1991,4694744897.95918 -"Macedonia, FYR",MKD,1992,2316618542.52603 -"Macedonia, FYR",MKD,1993,2550195043.10345 -"Macedonia, FYR",MKD,1994,3381270207.85219 -"Macedonia, FYR",MKD,1995,4449375346.45669 -"Macedonia, FYR",MKD,1996,4422160017.54386 -"Macedonia, FYR",MKD,1997,3735312142.57028 -"Macedonia, FYR",MKD,1998,3571043102.5641 -"Macedonia, FYR",MKD,1999,3673288263.62039 -"Macedonia, FYR",MKD,2000,3772851420.24763 -"Macedonia, FYR",MKD,2001,3709637829.94866 -"Macedonia, FYR",MKD,2002,4018365247.44444 -"Macedonia, FYR",MKD,2003,4946292774.79046 -"Macedonia, FYR",MKD,2004,5682719260.0763 -"Macedonia, FYR",MKD,2005,6258600713.82627 -"Macedonia, FYR",MKD,2006,6861222331.96317 -"Macedonia, FYR",MKD,2007,8336478142.08872 -"Macedonia, FYR",MKD,2008,9909548410.82744 -"Macedonia, FYR",MKD,2009,9401731495.71661 -"Macedonia, FYR",MKD,2010,9407168702.4313 -"Macedonia, FYR",MKD,2011,10494632699.3859 -"Macedonia, FYR",MKD,2012,9745251126.0109 -"Macedonia, FYR",MKD,2013,10817712138.9451 -"Macedonia, FYR",MKD,2014,11362272837.8818 -"Macedonia, FYR",MKD,2015,10051659161.1733 -"Macedonia, FYR",MKD,2016,10899583154.6499 -Madagascar,MDG,1960,673081724.075966 -Madagascar,MDG,1961,699161943.856733 -Madagascar,MDG,1962,739286906.851163 -Madagascar,MDG,1963,759345862.970929 -Madagascar,MDG,1964,802482182.923768 -Madagascar,MDG,1965,833563472.161911 -Madagascar,MDG,1966,900264583.687729 -Madagascar,MDG,1967,956436931.141842 -Madagascar,MDG,1968,1031669636.36062 -Madagascar,MDG,1969,1056391054.53794 -Madagascar,MDG,1970,1111859569.77066 -Madagascar,MDG,1971,1199507629.99222 -Madagascar,MDG,1972,1341590681.586 -Madagascar,MDG,1973,1653062347.36378 -Madagascar,MDG,1974,1917508190.04689 -Madagascar,MDG,1975,2283049233.28581 -Madagascar,MDG,1976,2181844193.92388 -Madagascar,MDG,1977,2358930406.42896 -Madagascar,MDG,1978,2669755115.50372 -Madagascar,MDG,1979,3463565881.42215 -Madagascar,MDG,1980,4042139901.36379 -Madagascar,MDG,1981,3594868208.41664 -Madagascar,MDG,1982,3526198070.09789 -Madagascar,MDG,1983,3511573991.89606 -Madagascar,MDG,1984,2939485471.50097 -Madagascar,MDG,1985,2857889712.4808 -Madagascar,MDG,1986,3258288890.58647 -Madagascar,MDG,1987,2565634382.28729 -Madagascar,MDG,1988,2442507588.38468 -Madagascar,MDG,1989,2498059014.77295 -Madagascar,MDG,1990,3081479800.28735 -Madagascar,MDG,1991,2653141958.52585 -Madagascar,MDG,1992,3024459564.32157 -Madagascar,MDG,1993,3370842210.90955 -Madagascar,MDG,1994,2977040722.47057 -Madagascar,MDG,1995,3159901231.97468 -Madagascar,MDG,1996,3995028592.78722 -Madagascar,MDG,1997,3545776697.12109 -Madagascar,MDG,1998,3738704467.51878 -Madagascar,MDG,1999,3717515282.53319 -Madagascar,MDG,2000,3877673539.09084 -Madagascar,MDG,2001,4529575347.56805 -Madagascar,MDG,2002,4397254607.61164 -Madagascar,MDG,2003,5474030080.24451 -Madagascar,MDG,2004,4363934494.37405 -Madagascar,MDG,2005,5039293030.82367 -Madagascar,MDG,2006,5515884348.54904 -Madagascar,MDG,2007,7342923489.09616 -Madagascar,MDG,2008,9413002920.97008 -Madagascar,MDG,2009,8550363974.79243 -Madagascar,MDG,2010,8729936135.74487 -Madagascar,MDG,2011,9892702357.56691 -Madagascar,MDG,2012,9919780071.28764 -Madagascar,MDG,2013,10601690871.7611 -Madagascar,MDG,2014,10673516672.6664 -Madagascar,MDG,2015,9738652322.17001 -Madagascar,MDG,2016,9990653078.19497 -Malawi,MWI,1960,162960130.465802 -Malawi,MWI,1961,174580139.768776 -Malawi,MWI,1962,183120146.605902 -Malawi,MWI,1963,190820152.770523 -Malawi,MWI,1964,194740155.908875 -Malawi,MWI,1965,229460183.705713 -Malawi,MWI,1966,260400208.476282 -Malawi,MWI,1967,269812781.79847 -Malawi,MWI,1968,245160098.113071 -Malawi,MWI,1969,265800106.373203 -Malawi,MWI,1970,290520116.266151 -Malawi,MWI,1971,365389567.21636 -Malawi,MWI,1972,406084197.385471 -Malawi,MWI,1973,444302221.260027 -Malawi,MWI,1974,548618789.94423 -Malawi,MWI,1975,613196872.560739 -Malawi,MWI,1976,670309252.98248 -Malawi,MWI,1977,806265763.845459 -Malawi,MWI,1978,948983308.780545 -Malawi,MWI,1979,1058297676.33572 -Malawi,MWI,1980,1237662066.78974 -Malawi,MWI,1981,1237686960.55408 -Malawi,MWI,1982,1180094061.48178 -Malawi,MWI,1983,1223225019.32697 -Malawi,MWI,1984,1208026079.75492 -Malawi,MWI,1985,1131349992.22735 -Malawi,MWI,1986,1183671788.12366 -Malawi,MWI,1987,1183071363.00406 -Malawi,MWI,1988,1379923808.24718 -Malawi,MWI,1989,1590201656.14301 -Malawi,MWI,1990,1880784191.81484 -Malawi,MWI,1991,2203536031.03471 -Malawi,MWI,1992,1799529357.0981 -Malawi,MWI,1993,2070647127.03808 -Malawi,MWI,1994,1181801919.66833 -Malawi,MWI,1995,1397454122.24047 -Malawi,MWI,1996,2281039097.69299 -Malawi,MWI,1997,2663238982.8009 -Malawi,MWI,1998,1750585204.44813 -Malawi,MWI,1999,1775920039.58919 -Malawi,MWI,2000,1743506287.41519 -Malawi,MWI,2001,1716502862.2954 -Malawi,MWI,2002,3495748397.63025 -Malawi,MWI,2003,3208837077.25069 -Malawi,MWI,2004,3476094498.87517 -Malawi,MWI,2005,3655909664.1423 -Malawi,MWI,2006,3997852636.24547 -Malawi,MWI,2007,4432192843.58998 -Malawi,MWI,2008,5320925102.29496 -Malawi,MWI,2009,6190991712.12014 -Malawi,MWI,2010,6959697194.02096 -Malawi,MWI,2011,8003300198.30166 -Malawi,MWI,2012,6028470988.53624 -Malawi,MWI,2013,5518901971.40057 -Malawi,MWI,2014,6054750320.3278 -Malawi,MWI,2015,6373201160.03248 -Malawi,MWI,2016,5441852138.14605 -Malaysia,MYS,1960,1916241996.60264 -Malaysia,MYS,1961,1901868548.28172 -Malaysia,MYS,1962,2001502678.6881 -Malaysia,MYS,1963,2510126747.68065 -Malaysia,MYS,1964,2674441395.53116 -Malaysia,MYS,1965,2956356984.18921 -Malaysia,MYS,1966,3143538481.64119 -Malaysia,MYS,1967,3188945511.56409 -Malaysia,MYS,1968,3330393309.81315 -Malaysia,MYS,1969,3664575983.27453 -Malaysia,MYS,1970,3864170913.36731 -Malaysia,MYS,1971,4244340333.51899 -Malaysia,MYS,1972,5043268548.73032 -Malaysia,MYS,1973,7662996766.66803 -Malaysia,MYS,1974,9496074114.07918 -Malaysia,MYS,1975,9298800799.46702 -Malaysia,MYS,1976,11050125904.9418 -Malaysia,MYS,1977,13139397879.1695 -Malaysia,MYS,1978,16358376511.2263 -Malaysia,MYS,1979,21213672089.1976 -Malaysia,MYS,1980,24488033442.0506 -Malaysia,MYS,1981,25004557093.8761 -Malaysia,MYS,1982,26804401815.5348 -Malaysia,MYS,1983,30346788437.5135 -Malaysia,MYS,1984,33943505717.6993 -Malaysia,MYS,1985,31200161095.4491 -Malaysia,MYS,1986,27734562640.4277 -Malaysia,MYS,1987,32181695507.2234 -Malaysia,MYS,1988,35271880250.4964 -Malaysia,MYS,1989,38848567631.4235 -Malaysia,MYS,1990,44024178343.0071 -Malaysia,MYS,1991,49142784405.0044 -Malaysia,MYS,1992,59167157497.9385 -Malaysia,MYS,1993,66894448545.1226 -Malaysia,MYS,1994,74477975918.3051 -Malaysia,MYS,1995,88704944178.6284 -Malaysia,MYS,1996,100854996422.609 -Malaysia,MYS,1997,100005323301.867 -Malaysia,MYS,1998,72167753770.8928 -Malaysia,MYS,1999,79148947368.4211 -Malaysia,MYS,2000,93789736842.1053 -Malaysia,MYS,2001,92783947368.4211 -Malaysia,MYS,2002,100845263157.895 -Malaysia,MYS,2003,110202368421.053 -Malaysia,MYS,2004,124749736842.105 -Malaysia,MYS,2005,143534102611.497 -Malaysia,MYS,2006,162690965596.205 -Malaysia,MYS,2007,193547824063.3 -Malaysia,MYS,2008,230813597937.526 -Malaysia,MYS,2009,202257586267.556 -Malaysia,MYS,2010,255016609232.871 -Malaysia,MYS,2011,297951960784.314 -Malaysia,MYS,2012,314442825692.826 -Malaysia,MYS,2013,323276841537.339 -Malaysia,MYS,2014,338068990803.263 -Malaysia,MYS,2015,296283190372.552 -Malaysia,MYS,2016,296359118754.525 -Maldives,MDV,1980,42463576.1589404 -Maldives,MDV,1981,44781456.9536424 -Maldives,MDV,1982,47935843.7935844 -Maldives,MDV,1983,57829787.2340425 -Maldives,MDV,1984,109503546.099291 -Maldives,MDV,1985,127154929.577465 -Maldives,MDV,1986,141902097.902098 -Maldives,MDV,1987,141268980.477223 -Maldives,MDV,1988,168610478.359909 -Maldives,MDV,1989,189535398.230089 -Maldives,MDV,1990,215089005.235602 -Maldives,MDV,1991,244468292.682927 -Maldives,MDV,1992,284853358.561968 -Maldives,MDV,1993,322326642.335766 -Maldives,MDV,1994,355884383.08887 -Maldives,MDV,1995,398988954.970263 -Maldives,MDV,1996,450382327.952421 -Maldives,MDV,1997,508223602.37893 -Maldives,MDV,1998,540096397.621071 -Maldives,MDV,1999,589239753.610875 -Maldives,MDV,2000,624337145.284622 -Maldives,MDV,2001,870179738.562091 -Maldives,MDV,2002,897031250 -Maldives,MDV,2003,1043403343.75 -Maldives,MDV,2004,1202240023.4375 -Maldives,MDV,2005,1119806500 -Maldives,MDV,2006,1474698125 -Maldives,MDV,2007,1745998937.5 -Maldives,MDV,2008,2109960937.5 -Maldives,MDV,2009,2149257812.5 -Maldives,MDV,2010,2323401757.8125 -Maldives,MDV,2011,2449576516.91549 -Maldives,MDV,2012,2518312129.02218 -Maldives,MDV,2013,2795147949.78753 -Maldives,MDV,2014,3094197810.2 -Maldives,MDV,2015,3435244658.76626 -Maldives,MDV,2016,3591112750.83939 -Mali,MLI,1967,275494520.141999 -Mali,MLI,1968,343771964.662167 -Mali,MLI,1969,339913833.096246 -Mali,MLI,1970,359772363.262207 -Mali,MLI,1971,430096738.369216 -Mali,MLI,1972,486617332.387405 -Mali,MLI,1973,563683660.31194 -Mali,MLI,1974,538747268.333356 -Mali,MLI,1975,830710615.179954 -Mali,MLI,1976,939227993.66396 -Mali,MLI,1977,1049838492.55759 -Mali,MLI,1978,1222702356.10946 -Mali,MLI,1979,1595423285.64659 -Mali,MLI,1980,1759690811.60699 -Mali,MLI,1981,1538972158.1782 -Mali,MLI,1982,1333754034.23489 -Mali,MLI,1983,1297765448.50498 -Mali,MLI,1984,1232932008.13719 -Mali,MLI,1985,1392195933.33971 -Mali,MLI,1986,1852163474.54664 -Mali,MLI,1987,2090629722.63611 -Mali,MLI,1988,2169040741.55896 -Mali,MLI,1989,2181821902.43953 -Mali,MLI,1990,2681912030.49384 -Mali,MLI,1991,2724131545.16958 -Mali,MLI,1992,2830673388.82429 -Mali,MLI,1993,2818280876.07615 -Mali,MLI,1994,2081846482.74771 -Mali,MLI,1995,2706425298.36818 -Mali,MLI,1996,2780422212.26995 -Mali,MLI,1997,2697105694.07956 -Mali,MLI,1998,2920358586.75234 -Mali,MLI,1999,3439463140.35541 -Mali,MLI,2000,2954129565.82965 -Mali,MLI,2001,3465305993.47783 -Mali,MLI,2002,3889758023.73699 -Mali,MLI,2003,4703504466.53245 -Mali,MLI,2004,5444474268.42491 -Mali,MLI,2005,6245031690.06808 -Mali,MLI,2006,6899799785.8441 -Mali,MLI,2007,8145694631.88354 -Mali,MLI,2008,9750822511.47988 -Mali,MLI,2009,10181021770.4326 -Mali,MLI,2010,10678749467.4697 -Mali,MLI,2011,12978107560.5982 -Mali,MLI,2012,12442747897.2223 -Mali,MLI,2013,12813248724.7996 -Mali,MLI,2014,14004067516.3577 -Mali,MLI,2015,12746688961.7795 -Mali,MLI,2016,14045098237.528 -Malta,MLT,1970,250721821.553678 -Malta,MLT,1971,264579879.784878 -Malta,MLT,1972,295118249.324932 -Malta,MLT,1973,345602025.375393 -Malta,MLT,1974,376094108.475331 -Malta,MLT,1975,474620439.58496 -Malta,MLT,1976,527936988.791275 -Malta,MLT,1977,625573345.532174 -Malta,MLT,1978,793675169.878579 -Malta,MLT,1979,1001300838.32335 -Malta,MLT,1980,1250242107.87969 -Malta,MLT,1981,1243469360.56838 -Malta,MLT,1982,1234518125 -Malta,MLT,1983,1165771369.00625 -Malta,MLT,1984,1101828568.76804 -Malta,MLT,1985,1117835285.50512 -Malta,MLT,1986,1435079200.34957 -Malta,MLT,1987,1751247763.41948 -Malta,MLT,1988,2019474244.19359 -Malta,MLT,1989,2118574772.11136 -Malta,MLT,1990,2547163582.33149 -Malta,MLT,1991,2750041434.26295 -Malta,MLT,1992,3021910216.71827 -Malta,MLT,1993,2709178326.78271 -Malta,MLT,1994,2998570146.54095 -Malta,MLT,1995,3439931906.61479 -Malta,MLT,1996,3570271557.88471 -Malta,MLT,1997,3705372038.70537 -Malta,MLT,1998,3923637971.04652 -Malta,MLT,1999,4127313818.33836 -Malta,MLT,2000,4306192435.82207 -Malta,MLT,2001,4331870647.71535 -Malta,MLT,2002,4689832689.83269 -Malta,MLT,2003,5456583589.39342 -Malta,MLT,2004,6062780269.0583 -Malta,MLT,2005,6394851386.64345 -Malta,MLT,2006,6757119558.3992 -Malta,MLT,2007,7880509170.54476 -Malta,MLT,2008,8977149553.24447 -Malta,MLT,2009,8528202278.41067 -Malta,MLT,2010,8741059602.64901 -Malta,MLT,2011,9500001983.37933 -Malta,MLT,2012,9198987219.66026 -Malta,MLT,2013,10131419448.978 -Malta,MLT,2014,11188785252.7566 -Malta,MLT,2015,10287007021.1557 -Malta,MLT,2016,10949092471.597 -Marshall Islands,MHL,1981,31020000 -Marshall Islands,MHL,1982,34918000 -Marshall Islands,MHL,1983,41749000 -Marshall Islands,MHL,1984,45144000 -Marshall Islands,MHL,1985,43879000 -Marshall Islands,MHL,1986,55989000 -Marshall Islands,MHL,1987,62983000 -Marshall Islands,MHL,1988,70688000 -Marshall Islands,MHL,1989,72798000 -Marshall Islands,MHL,1990,78476000 -Marshall Islands,MHL,1991,82507000 -Marshall Islands,MHL,1992,91063000 -Marshall Islands,MHL,1993,99461000 -Marshall Islands,MHL,1994,108071000 -Marshall Islands,MHL,1995,120230000 -Marshall Islands,MHL,1996,110858000 -Marshall Islands,MHL,1997,106289100 -Marshall Islands,MHL,1998,108702100 -Marshall Islands,MHL,1999,107978900 -Marshall Islands,MHL,2000,110937700 -Marshall Islands,MHL,2001,115152100 -Marshall Islands,MHL,2002,124735100 -Marshall Islands,MHL,2003,126887600 -Marshall Islands,MHL,2004,131106400 -Marshall Islands,MHL,2005,137744500 -Marshall Islands,MHL,2006,143656600 -Marshall Islands,MHL,2007,150851598.261375 -Marshall Islands,MHL,2008,152901100 -Marshall Islands,MHL,2009,152631200 -Marshall Islands,MHL,2010,164751300 -Marshall Islands,MHL,2011,172674900 -Marshall Islands,MHL,2012,185055800 -Marshall Islands,MHL,2013,190992000 -Marshall Islands,MHL,2014,183114100 -Marshall Islands,MHL,2015,179432600 -Marshall Islands,MHL,2016,183000000 -Mauritania,MRT,1960,92609222.6912849 -Mauritania,MRT,1961,107726181.218304 -Mauritania,MRT,1962,111148585.592024 -Mauritania,MRT,1963,113797356.813964 -Mauritania,MRT,1964,151897168.106199 -Mauritania,MRT,1965,172767213.286516 -Mauritania,MRT,1966,180340653.822049 -Mauritania,MRT,1967,191221777.800889 -Mauritania,MRT,1968,210695183.760251 -Mauritania,MRT,1969,199643444.567995 -Mauritania,MRT,1970,209348253.60877 -Mauritania,MRT,1971,227051054.984972 -Mauritania,MRT,1972,265009395.148159 -Mauritania,MRT,1973,333731874.379051 -Mauritania,MRT,1974,414772351.88069 -Mauritania,MRT,1975,475916514.745785 -Mauritania,MRT,1976,524407931.940588 -Mauritania,MRT,1977,540635389.589072 -Mauritania,MRT,1978,544424605.052283 -Mauritania,MRT,1979,644070364.889076 -Mauritania,MRT,1980,709041452.217718 -Mauritania,MRT,1981,747994681.876653 -Mauritania,MRT,1982,750214410.723584 -Mauritania,MRT,1983,788371855.945127 -Mauritania,MRT,1984,726937320.846135 -Mauritania,MRT,1985,683193885.003343 -Mauritania,MRT,1986,802890746.890756 -Mauritania,MRT,1987,909820553.400741 -Mauritania,MRT,1988,957377507.476686 -Mauritania,MRT,1989,981529400.534373 -Mauritania,MRT,1990,1019600770.6038 -Mauritania,MRT,1991,1443688869.96039 -Mauritania,MRT,1992,1464392416.14671 -Mauritania,MRT,1993,1249944999.42056 -Mauritania,MRT,1994,1315932644.95246 -Mauritania,MRT,1995,1415296704.11812 -Mauritania,MRT,1996,1442598431.0096 -Mauritania,MRT,1997,1401946853.20672 -Mauritania,MRT,1998,1375115534.0733 -Mauritania,MRT,1999,1405662878.85296 -Mauritania,MRT,2000,1293654175.2102 -Mauritania,MRT,2001,1295539448.36484 -Mauritania,MRT,2002,1324426606.62378 -Mauritania,MRT,2003,1563074859.52173 -Mauritania,MRT,2004,1833444740.37736 -Mauritania,MRT,2005,2184444848.97637 -Mauritania,MRT,2006,3040716679.07669 -Mauritania,MRT,2007,3356757497.1208 -Mauritania,MRT,2008,3978425730.72183 -Mauritania,MRT,2009,3670515695.69153 -Mauritania,MRT,2010,4343665119.8875 -Mauritania,MRT,2011,5179689613.50618 -Mauritania,MRT,2012,5225532807.25025 -Mauritania,MRT,2013,5724227536.49393 -Mauritania,MRT,2014,5391475878.08153 -Mauritania,MRT,2015,4844223517.89396 -Mauritania,MRT,2016,4634588338.07171 -Mauritius,MUS,1976,706991274.414428 -Mauritius,MUS,1977,827094668.018707 -Mauritius,MUS,1978,1019630847.11113 -Mauritius,MUS,1979,1216229419.31802 -Mauritius,MUS,1980,1136543003.2664 -Mauritius,MUS,1981,1147192916.68998 -Mauritius,MUS,1982,1082939379.16762 -Mauritius,MUS,1983,1094857357.63954 -Mauritius,MUS,1984,1044928624.74004 -Mauritius,MUS,1985,1080642033.34952 -Mauritius,MUS,1986,1469046114.77455 -Mauritius,MUS,1987,1888754655.15367 -Mauritius,MUS,1988,2143484487.67274 -Mauritius,MUS,1989,2191096860.28669 -Mauritius,MUS,1990,2653480001.34558 -Mauritius,MUS,1991,2856890680.60285 -Mauritius,MUS,1992,3224267547.80508 -Mauritius,MUS,1993,3263368410.01813 -Mauritius,MUS,1994,3558137040.37772 -Mauritius,MUS,1995,4040345933.29231 -Mauritius,MUS,1996,4421943910.49749 -Mauritius,MUS,1997,4187367601.73431 -Mauritius,MUS,1998,4169664285.38681 -Mauritius,MUS,1999,4291172815.63421 -Mauritius,MUS,2000,4582555124.64952 -Mauritius,MUS,2001,4536538210.66761 -Mauritius,MUS,2002,4767303153.99506 -Mauritius,MUS,2003,5609831328.0648 -Mauritius,MUS,2004,6385695187.0102 -Mauritius,MUS,2005,6283803256.01264 -Mauritius,MUS,2006,7028803365.70151 -Mauritius,MUS,2007,8150138757.15741 -Mauritius,MUS,2008,9990370016.30771 -Mauritius,MUS,2009,9128843109.15588 -Mauritius,MUS,2010,10003670690.3497 -Mauritius,MUS,2011,11518393367.2403 -Mauritius,MUS,2012,11668685524.1265 -Mauritius,MUS,2013,12129642296.4425 -Mauritius,MUS,2014,12803445933.5894 -Mauritius,MUS,2015,11681761261.0428 -Mauritius,MUS,2016,12164207329.5437 -Mexico,MEX,1960,13056168000 -Mexico,MEX,1961,14153952000 -Mexico,MEX,1962,15221056000 -Mexico,MEX,1963,16936336000 -Mexico,MEX,1964,20070136000 -Mexico,MEX,1965,21829712000 -Mexico,MEX,1966,24337232000 -Mexico,MEX,1967,26556376000 -Mexico,MEX,1968,29363632000 -Mexico,MEX,1969,32515752000 -Mexico,MEX,1970,35541712000 -Mexico,MEX,1971,39200880000 -Mexico,MEX,1972,45178120000 -Mexico,MEX,1973,55271304000 -Mexico,MEX,1974,71976544000 -Mexico,MEX,1975,88003984000 -Mexico,MEX,1976,89023915584.4156 -Mexico,MEX,1977,81825783185.8407 -Mexico,MEX,1978,102517451754.386 -Mexico,MEX,1979,134540324561.404 -Mexico,MEX,1980,194356826086.957 -Mexico,MEX,1981,250083020408.163 -Mexico,MEX,1982,173720851063.83 -Mexico,MEX,1983,148866910907.577 -Mexico,MEX,1984,175632157330.155 -Mexico,MEX,1985,184473106267.03 -Mexico,MEX,1986,129440194508.009 -Mexico,MEX,1987,140263679436.947 -Mexico,MEX,1988,183144268180.018 -Mexico,MEX,1989,222977035953.687 -Mexico,MEX,1990,262709776007.964 -Mexico,MEX,1991,314453890803.074 -Mexico,MEX,1992,363609256195.677 -Mexico,MEX,1993,503962832199.255 -Mexico,MEX,1994,527318753518.414 -Mexico,MEX,1995,343792792161.261 -Mexico,MEX,1996,397404140458.457 -Mexico,MEX,1997,480554644187.662 -Mexico,MEX,1998,502010250656.743 -Mexico,MEX,1999,579459682649.262 -Mexico,MEX,2000,683647965226.955 -Mexico,MEX,2001,724703603502.349 -Mexico,MEX,2002,741559509631.317 -Mexico,MEX,2003,713284231624.803 -Mexico,MEX,2004,770267585947.191 -Mexico,MEX,2005,866345821213.261 -Mexico,MEX,2006,965281191371.844 -Mexico,MEX,2007,1043471321169.09 -Mexico,MEX,2008,1101275278668.79 -Mexico,MEX,2009,894948748436.748 -Mexico,MEX,2010,1051128603513.77 -Mexico,MEX,2011,1171187519660.64 -Mexico,MEX,2012,1186598324461.82 -Mexico,MEX,2013,1261981728468.52 -Mexico,MEX,2014,1298398654278.73 -Mexico,MEX,2015,1151037122909.08 -Mexico,MEX,2016,1045998068645.15 -"Micronesia, Fed. Sts.",FSM,1983,106500000 -"Micronesia, Fed. Sts.",FSM,1986,112210000 -"Micronesia, Fed. Sts.",FSM,1987,116700000 -"Micronesia, Fed. Sts.",FSM,1988,124700000 -"Micronesia, Fed. Sts.",FSM,1989,135200000 -"Micronesia, Fed. Sts.",FSM,1990,147200000 -"Micronesia, Fed. Sts.",FSM,1991,166200000 -"Micronesia, Fed. Sts.",FSM,1992,178100000 -"Micronesia, Fed. Sts.",FSM,1993,198400000 -"Micronesia, Fed. Sts.",FSM,1994,202500000 -"Micronesia, Fed. Sts.",FSM,1995,222103600 -"Micronesia, Fed. Sts.",FSM,1996,218845700 -"Micronesia, Fed. Sts.",FSM,1997,206900300 -"Micronesia, Fed. Sts.",FSM,1998,219646200 -"Micronesia, Fed. Sts.",FSM,1999,220660500 -"Micronesia, Fed. Sts.",FSM,2000,233226300 -"Micronesia, Fed. Sts.",FSM,2001,240051900 -"Micronesia, Fed. Sts.",FSM,2002,241543400 -"Micronesia, Fed. Sts.",FSM,2003,244991000 -"Micronesia, Fed. Sts.",FSM,2004,239563300 -"Micronesia, Fed. Sts.",FSM,2005,249845600 -"Micronesia, Fed. Sts.",FSM,2006,252991200 -"Micronesia, Fed. Sts.",FSM,2007,255890800 -"Micronesia, Fed. Sts.",FSM,2008,261339600 -"Micronesia, Fed. Sts.",FSM,2009,277510900 -"Micronesia, Fed. Sts.",FSM,2010,294117200 -"Micronesia, Fed. Sts.",FSM,2011,310287500 -"Micronesia, Fed. Sts.",FSM,2012,325835200 -"Micronesia, Fed. Sts.",FSM,2013,315725600 -"Micronesia, Fed. Sts.",FSM,2014,318072000 -"Micronesia, Fed. Sts.",FSM,2015,314971100 -"Micronesia, Fed. Sts.",FSM,2016,322000000 -Moldova,MDA,1995,1752975841.35916 -Moldova,MDA,1996,1695130456.52174 -Moldova,MDA,1997,1930071406.92641 -Moldova,MDA,1998,1639497206.70391 -Moldova,MDA,1999,1170785047.79461 -Moldova,MDA,2000,1288429150.51394 -Moldova,MDA,2001,1480656884.38462 -Moldova,MDA,2002,1661818168.4226 -Moldova,MDA,2003,1980901553.51226 -Moldova,MDA,2004,2598231467.43671 -Moldova,MDA,2005,2988338439.31553 -Moldova,MDA,2006,3408272498.11516 -Moldova,MDA,2007,4401154128.12297 -Moldova,MDA,2008,6054806100.8468 -Moldova,MDA,2009,5439422031.39627 -Moldova,MDA,2010,5811604051.96737 -Moldova,MDA,2011,7015206498.21955 -Moldova,MDA,2012,7284686576.2835 -Moldova,MDA,2013,7985349731.46471 -Moldova,MDA,2014,7983271110.60446 -Moldova,MDA,2015,6512899540.34594 -Moldova,MDA,2016,6749515654.64419 -Monaco,MCO,1970,293073868.023221 -Monaco,MCO,1971,327651487.962757 -Monaco,MCO,1972,402460333.237637 -Monaco,MCO,1973,523552815.119127 -Monaco,MCO,1974,563939670.704419 -Monaco,MCO,1975,711922994.225545 -Monaco,MCO,1976,735339911.935065 -Monaco,MCO,1977,811250927.388998 -Monaco,MCO,1978,1000535735.38751 -Monaco,MCO,1979,1209898293.46372 -Monaco,MCO,1980,1378130995.65913 -Monaco,MCO,1981,1205166025.51592 -Monaco,MCO,1982,1143229071.77943 -Monaco,MCO,1983,1092551781.01486 -Monaco,MCO,1984,1037314956.25083 -Monaco,MCO,1985,1082851076.52158 -Monaco,MCO,1986,1515209588.2378 -Monaco,MCO,1987,1839095595.25655 -Monaco,MCO,1988,2000674667.08261 -Monaco,MCO,1989,2010116851.20284 -Monaco,MCO,1990,2481316053.85316 -Monaco,MCO,1991,2480497547.84881 -Monaco,MCO,1992,2737066955.91266 -Monaco,MCO,1993,2574439973.17387 -Monaco,MCO,1994,2720297738.93904 -Monaco,MCO,1995,3130270918.79061 -Monaco,MCO,1996,3137848783.08404 -Monaco,MCO,1997,2840182191.77105 -Monaco,MCO,1998,2934578788.86478 -Monaco,MCO,1999,2906009307.6651 -Monaco,MCO,2000,2647883820.18625 -Monaco,MCO,2001,2671401082.76436 -Monaco,MCO,2002,2905973022.1746 -Monaco,MCO,2003,3588988600.70294 -Monaco,MCO,2004,4110348444.49411 -Monaco,MCO,2005,4280072625.97622 -Monaco,MCO,2006,4663488363.0977 -Monaco,MCO,2007,5974371695.95045 -Monaco,MCO,2008,6919241412.09365 -Monaco,MCO,2009,5557245122.31576 -Monaco,MCO,2010,5350674803.33858 -Monaco,MCO,2011,6074884388.58937 -Mongolia,MNG,1981,2310099100 -Mongolia,MNG,1982,2552401933.33333 -Mongolia,MNG,1983,2725736633.33333 -Mongolia,MNG,1984,2098734600 -Mongolia,MNG,1985,2186505475 -Mongolia,MNG,1986,2896178866.66667 -Mongolia,MNG,1987,3020611600 -Mongolia,MNG,1988,3204461566.66667 -Mongolia,MNG,1989,3576966800 -Mongolia,MNG,1990,2560785660 -Mongolia,MNG,1991,2379018326.31579 -Mongolia,MNG,1992,1317611863.84977 -Mongolia,MNG,1993,768401634.154573 -Mongolia,MNG,1994,925817092.217484 -Mongolia,MNG,1995,1452165005.2384 -Mongolia,MNG,1996,1345719472.35883 -Mongolia,MNG,1997,1180934202.83801 -Mongolia,MNG,1998,1124440248.9783 -Mongolia,MNG,1999,1057408588.68269 -Mongolia,MNG,2000,1136896123.61298 -Mongolia,MNG,2001,1267997934.3125 -Mongolia,MNG,2002,1396555719.97409 -Mongolia,MNG,2003,1595297355.78349 -Mongolia,MNG,2004,1992066808.09598 -Mongolia,MNG,2005,2523471532.01083 -Mongolia,MNG,2006,3414055566.1138 -Mongolia,MNG,2007,4234999823.30839 -Mongolia,MNG,2008,5623216448.86851 -Mongolia,MNG,2009,4583850367.88972 -Mongolia,MNG,2010,7189481853.10614 -Mongolia,MNG,2011,10409797610.3499 -Mongolia,MNG,2012,12292770631.1967 -Mongolia,MNG,2013,12582122604.1921 -Mongolia,MNG,2014,12226514746.1243 -Mongolia,MNG,2015,11741338841.1321 -Mongolia,MNG,2016,11160356497.9404 -Montenegro,MNE,2000,984279598.325251 -Montenegro,MNE,2001,1159860290.16658 -Montenegro,MNE,2002,1284446123.33554 -Montenegro,MNE,2003,1707678389.68676 -Montenegro,MNE,2004,2073255525.20487 -Montenegro,MNE,2005,2257174480.78597 -Montenegro,MNE,2006,2696020574.58286 -Montenegro,MNE,2007,3668857103.75034 -Montenegro,MNE,2008,4519731946.68229 -Montenegro,MNE,2009,4141382328.42456 -Montenegro,MNE,2010,4139192052.98013 -Montenegro,MNE,2011,4538198498.74896 -Montenegro,MNE,2012,4087724527.81704 -Montenegro,MNE,2013,4464260488.58205 -Montenegro,MNE,2014,4587928884.17142 -Montenegro,MNE,2015,4019889098.36975 -Montenegro,MNE,2016,4173255530.97345 -Morocco,MAR,1960,2037150716.33238 -Morocco,MAR,1961,2025689536.60705 -Morocco,MAR,1962,2379606422.29029 -Morocco,MAR,1963,2657247327.3392 -Morocco,MAR,1964,2798339768.79755 -Morocco,MAR,1965,2948325264.30195 -Morocco,MAR,1966,2876395613.08171 -Morocco,MAR,1967,3046339294.53611 -Morocco,MAR,1968,3271415867.99723 -Morocco,MAR,1969,3651615453.01848 -Morocco,MAR,1970,3956328426.04486 -Morocco,MAR,1971,4356633663.36634 -Morocco,MAR,1972,5074117544.77482 -Morocco,MAR,1973,6242177798.33938 -Morocco,MAR,1974,7675408485.51421 -Morocco,MAR,1975,8984824182.60333 -Morocco,MAR,1976,9584323309.12136 -Morocco,MAR,1977,11049896742.3889 -Morocco,MAR,1978,13236854105.1672 -Morocco,MAR,1979,15912133569.2852 -Morocco,MAR,1980,21728770055.3777 -Morocco,MAR,1981,17788171722.4446 -Morocco,MAR,1982,17692341358.1272 -Morocco,MAR,1983,16251460689.3254 -Morocco,MAR,1984,14824728528.4604 -Morocco,MAR,1985,14991283215.7408 -Morocco,MAR,1986,19462175321.8224 -Morocco,MAR,1987,21765261041.7265 -Morocco,MAR,1988,25705296183.5037 -Morocco,MAR,1989,26314220188.0257 -Morocco,MAR,1990,30180108561.9305 -Morocco,MAR,1991,32285388165.2999 -Morocco,MAR,1992,33711069430.78 -Morocco,MAR,1993,31655473663.8348 -Morocco,MAR,1994,35604137422.5796 -Morocco,MAR,1995,39030285468.3841 -Morocco,MAR,1996,43161452678.4383 -Morocco,MAR,1997,39147844526.0838 -Morocco,MAR,1998,41806219378.6181 -Morocco,MAR,1999,41632027599.8531 -Morocco,MAR,2000,38857251336.3448 -Morocco,MAR,2001,39459581217.3759 -Morocco,MAR,2002,42236836820.6152 -Morocco,MAR,2003,52064058833.9739 -Morocco,MAR,2004,59626020162.3816 -Morocco,MAR,2005,62343022650.8742 -Morocco,MAR,2006,68640825480.9223 -Morocco,MAR,2007,79041294874.4553 -Morocco,MAR,2008,92507257783.5697 -Morocco,MAR,2009,92897320375.8176 -Morocco,MAR,2010,93216746661.5977 -Morocco,MAR,2011,101370474295.109 -Morocco,MAR,2012,98266306615.3632 -Morocco,MAR,2013,106825649872.108 -Morocco,MAR,2014,109881398474.953 -Morocco,MAR,2015,100593283696.732 -Morocco,MAR,2016,101445004812.643 -Mozambique,MOZ,1980,3526287037.03704 -Mozambique,MOZ,1981,3537099150.14164 -Mozambique,MOZ,1982,3612171957.67196 -Mozambique,MOZ,1983,3236430348.25871 -Mozambique,MOZ,1984,3376172169.81132 -Mozambique,MOZ,1985,4456240740.74074 -Mozambique,MOZ,1986,5247193069.30693 -Mozambique,MOZ,1987,2354117303.06158 -Mozambique,MOZ,1988,2093571673.65612 -Mozambique,MOZ,1989,2314159887.23319 -Mozambique,MOZ,1990,2512079324.07706 -Mozambique,MOZ,1991,3263761937.95748 -Mozambique,MOZ,1992,2291175764.66004 -Mozambique,MOZ,1993,2394823061.93212 -Mozambique,MOZ,1994,2460670287.73707 -Mozambique,MOZ,1995,2521738759.58885 -Mozambique,MOZ,1996,3523842274.89662 -Mozambique,MOZ,1997,4227273069.05991 -Mozambique,MOZ,1998,4873242526.06404 -Mozambique,MOZ,1999,5302532113.25156 -Mozambique,MOZ,2000,5016469068.50898 -Mozambique,MOZ,2001,4766928746.6914 -Mozambique,MOZ,2002,5031510908.86055 -Mozambique,MOZ,2003,5597367853.40358 -Mozambique,MOZ,2004,6831808930.39816 -Mozambique,MOZ,2005,7723846194.87446 -Mozambique,MOZ,2006,8312078525.08582 -Mozambique,MOZ,2007,9366742309.49331 -Mozambique,MOZ,2008,11494837053.4061 -Mozambique,MOZ,2009,10911698208.1015 -Mozambique,MOZ,2010,10154238250.1818 -Mozambique,MOZ,2011,13131168011.807 -Mozambique,MOZ,2012,14534278446.3087 -Mozambique,MOZ,2013,16018848990.669 -Mozambique,MOZ,2014,16961127045.8266 -Mozambique,MOZ,2015,14798399861.5582 -Mozambique,MOZ,2016,11014858591.8422 -Myanmar,MMR,2000,8905066163.58643 -Myanmar,MMR,2001,6477790688.22844 -Myanmar,MMR,2002,6777632512.0781 -Myanmar,MMR,2003,10467109977.6717 -Myanmar,MMR,2004,10567354056.4049 -Myanmar,MMR,2005,11986972418.5103 -Myanmar,MMR,2006,14502553709.8303 -Myanmar,MMR,2007,20182477480.5512 -Myanmar,MMR,2008,31862554101.9378 -Myanmar,MMR,2009,36906181380.8127 -Myanmar,MMR,2010,49540813342.4834 -Myanmar,MMR,2011,59977326085.9908 -Myanmar,MMR,2012,59731122170.0865 -Myanmar,MMR,2013,60132854536.7832 -Myanmar,MMR,2014,65574726566.3779 -Myanmar,MMR,2015,62600906116.0987 -Myanmar,MMR,2016,67429590535.8518 -Namibia,NAM,1980,2434884951.20699 -Namibia,NAM,1981,2259179124.88605 -Namibia,NAM,1982,2128089611.34647 -Namibia,NAM,1983,2308102953.05628 -Namibia,NAM,1984,1960567071.10418 -Namibia,NAM,1985,1615776820.56804 -Namibia,NAM,1986,1816754048.14004 -Namibia,NAM,1987,2310454960.70727 -Namibia,NAM,1988,2506554607.43347 -Namibia,NAM,1989,2547340984.48164 -Namibia,NAM,1990,2804379662.19611 -Namibia,NAM,1991,3012742078.00674 -Namibia,NAM,1992,3448326858.34502 -Namibia,NAM,1993,3218475900.48046 -Namibia,NAM,1994,3636645995.26867 -Namibia,NAM,1995,3942478205.72909 -Namibia,NAM,1996,3945340776.40546 -Namibia,NAM,1997,4102648719.61806 -Namibia,NAM,1998,3826527630.55551 -Namibia,NAM,1999,3818954447.99083 -Namibia,NAM,2000,3908661517.62299 -Namibia,NAM,2001,3546783708.12619 -Namibia,NAM,2002,3361251197.73829 -Namibia,NAM,2003,4931312147.21007 -Namibia,NAM,2004,6606858786.01174 -Namibia,NAM,2005,7261333794.60003 -Namibia,NAM,2006,7978734401.53585 -Namibia,NAM,2007,8740865600.24981 -Namibia,NAM,2008,8486721916.9128 -Namibia,NAM,2009,8876191120.76189 -Namibia,NAM,2010,11282192605.0374 -Namibia,NAM,2011,12409629835.6998 -Namibia,NAM,2012,13016272898.9038 -Namibia,NAM,2013,12713366873.4658 -Namibia,NAM,2014,12853963142.8124 -Namibia,NAM,2015,11491507355.6498 -Namibia,NAM,2016,10267157279.9956 -Nauru,NRU,2007,20432742.1126982 -Nauru,NRU,2008,39333572.3247894 -Nauru,NRU,2009,44290951.9252006 -Nauru,NRU,2010,49248810.5726872 -Nauru,NRU,2011,72751801.046087 -Nauru,NRU,2012,103811958.762887 -Nauru,NRU,2013,108601538.461538 -Nauru,NRU,2014,117020381.931693 -Nauru,NRU,2015,100459782.608696 -Nauru,NRU,2016,102060129.577055 -Nepal,NPL,1960,508334413.965087 -Nepal,NPL,1961,531959561.62226 -Nepal,NPL,1962,574091101.194382 -Nepal,NPL,1963,496947904.443033 -Nepal,NPL,1964,496098775.308642 -Nepal,NPL,1965,735267082.294264 -Nepal,NPL,1966,906811943.824649 -Nepal,NPL,1967,841974025.462659 -Nepal,NPL,1968,772228643.405428 -Nepal,NPL,1969,788641965.432099 -Nepal,NPL,1970,865975308.641975 -Nepal,NPL,1971,882765471.604938 -Nepal,NPL,1972,1024098804.93827 -Nepal,NPL,1973,972101724.995368 -Nepal,NPL,1974,1217953546.97604 -Nepal,NPL,1975,1575789254.46938 -Nepal,NPL,1976,1452792989.10865 -Nepal,NPL,1977,1382400000 -Nepal,NPL,1978,1604162497.45945 -Nepal,NPL,1979,1851250008.33333 -Nepal,NPL,1980,1945916583.33333 -Nepal,NPL,1981,2275583316.66667 -Nepal,NPL,1982,2395429852.43076 -Nepal,NPL,1983,2447174803.37791 -Nepal,NPL,1984,2581207387.79709 -Nepal,NPL,1985,2619913955.51556 -Nepal,NPL,1986,2850784523.37711 -Nepal,NPL,1987,2957255379.54315 -Nepal,NPL,1988,3487009748.35638 -Nepal,NPL,1989,3525228153.17361 -Nepal,NPL,1990,3627562402.66027 -Nepal,NPL,1991,3921476084.89072 -Nepal,NPL,1992,3401211581.29176 -Nepal,NPL,1993,3660041666.66667 -Nepal,NPL,1994,4066775510.20408 -Nepal,NPL,1995,4401104417.67068 -Nepal,NPL,1996,4521580381.47139 -Nepal,NPL,1997,4918691916.53516 -Nepal,NPL,1998,4856255044.39064 -Nepal,NPL,1999,5033642384.10596 -Nepal,NPL,2000,5494252207.90502 -Nepal,NPL,2001,6007061224.48979 -Nepal,NPL,2002,6050875806.66403 -Nepal,NPL,2003,6330473096.54071 -Nepal,NPL,2004,7273938314.71988 -Nepal,NPL,2005,8130258041.46706 -Nepal,NPL,2006,9043715355.8881 -Nepal,NPL,2007,10325618017.379 -Nepal,NPL,2008,12545438605.3959 -Nepal,NPL,2009,12854985464.0764 -Nepal,NPL,2010,16002656434.4746 -Nepal,NPL,2011,18913574370.76 -Nepal,NPL,2012,18851513891.066 -Nepal,NPL,2013,19271168018.482 -Nepal,NPL,2014,20002968837.9471 -Nepal,NPL,2015,21313549578.6984 -Nepal,NPL,2016,21143873417.4002 -Netherlands,NLD,1960,12276734172.0828 -Netherlands,NLD,1961,13493833739.9949 -Netherlands,NLD,1962,14647057370.1418 -Netherlands,NLD,1963,15891241386.291 -Netherlands,NLD,1964,18699380731.3465 -Netherlands,NLD,1965,21000586933.2041 -Netherlands,NLD,1966,22867203317.4022 -Netherlands,NLD,1967,25087562181.3218 -Netherlands,NLD,1968,27817605743.2503 -Netherlands,NLD,1969,31503868835.1853 -Netherlands,NLD,1970,37677621537.7123 -Netherlands,NLD,1971,44010160463.6591 -Netherlands,NLD,1972,54008338917.8797 -Netherlands,NLD,1973,70924006306.1643 -Netherlands,NLD,1974,86129928026.8875 -Netherlands,NLD,1975,98970041042.175 -Netherlands,NLD,1976,107775403067.178 -Netherlands,NLD,1977,125395875998.923 -Netherlands,NLD,1978,153870462415.971 -Netherlands,NLD,1979,177376289135.45 -Netherlands,NLD,1980,192661371425.405 -Netherlands,NLD,1981,162039376225.382 -Netherlands,NLD,1982,156456858050.673 -Netherlands,NLD,1983,151487045479.114 -Netherlands,NLD,1984,142075910370.879 -Netherlands,NLD,1985,142009922306.263 -Netherlands,NLD,1986,198298498021.227 -Netherlands,NLD,1987,241918791122.715 -Netherlands,NLD,1988,258567751142.825 -Netherlands,NLD,1989,255039560739.894 -Netherlands,NLD,1990,314267667675.178 -Netherlands,NLD,1991,323320449905.705 -Netherlands,NLD,1992,358330385839.599 -Netherlands,NLD,1993,349037818106.312 -Netherlands,NLD,1994,374291430318.44 -Netherlands,NLD,1995,446528959648.641 -Netherlands,NLD,1996,445704575163.399 -Netherlands,NLD,1997,412199006098.938 -Netherlands,NLD,1998,432476116418.574 -Netherlands,NLD,1999,441975282335.393 -Netherlands,NLD,2000,412807259996.315 -Netherlands,NLD,2001,426573601789.709 -Netherlands,NLD,2002,465368906455.863 -Netherlands,NLD,2003,571863431151.242 -Netherlands,NLD,2004,650532654581.574 -Netherlands,NLD,2005,678533764457.157 -Netherlands,NLD,2006,726649102998.369 -Netherlands,NLD,2007,839419655078.018 -Netherlands,NLD,2008,936228211513.11 -Netherlands,NLD,2009,857932759099.75 -Netherlands,NLD,2010,836389937229.197 -Netherlands,NLD,2011,893757287201.688 -Netherlands,NLD,2012,828946812396.788 -Netherlands,NLD,2013,866680000367.264 -Netherlands,NLD,2014,879635084124.987 -Netherlands,NLD,2015,750318056805.557 -Netherlands,NLD,2016,770845046231.727 -New Caledonia,NCL,1965,159594493.548808 -New Caledonia,NCL,1966,164206537.561675 -New Caledonia,NCL,1967,180036768.87301 -New Caledonia,NCL,1968,215507164.034258 -New Caledonia,NCL,1969,263108834.536684 -New Caledonia,NCL,1970,358815681.903215 -New Caledonia,NCL,1971,413634335.270097 -New Caledonia,NCL,1972,505892512.861927 -New Caledonia,NCL,1973,542294864.81243 -New Caledonia,NCL,1974,637400199.110489 -New Caledonia,NCL,1975,816647865.83143 -New Caledonia,NCL,1976,798310509.647434 -New Caledonia,NCL,1977,837616756.533737 -New Caledonia,NCL,1978,846007597.720396 -New Caledonia,NCL,1979,1047225130.24333 -New Caledonia,NCL,1980,1182457142.60648 -New Caledonia,NCL,1981,972563810.230325 -New Caledonia,NCL,1982,904619629.797268 -New Caledonia,NCL,1983,823832940.450511 -New Caledonia,NCL,1984,796018978.4713 -New Caledonia,NCL,1985,854823821.723177 -New Caledonia,NCL,1986,1201262517.87644 -New Caledonia,NCL,1987,1488113532.28584 -New Caledonia,NCL,1988,2072735787.31779 -New Caledonia,NCL,1989,2185072798.33184 -New Caledonia,NCL,1990,2529310103.83608 -New Caledonia,NCL,1991,2653781596.46008 -New Caledonia,NCL,1992,2923764926.39718 -New Caledonia,NCL,1993,3070161471.04451 -New Caledonia,NCL,1994,3038727617.03901 -New Caledonia,NCL,1995,3628440274.67 -New Caledonia,NCL,1996,3606968433.92682 -New Caledonia,NCL,1997,3291489840.57141 -New Caledonia,NCL,1998,3158806480.26107 -New Caledonia,NCL,1999,3056999988.09146 -New Caledonia,NCL,2000,2682347064.3642 -New Zealand,NZL,1960,5485854791.97096 -New Zealand,NZL,1961,5670064168.21773 -New Zealand,NZL,1962,6077496267.76294 -New Zealand,NZL,1963,6638937283.13963 -New Zealand,NZL,1964,7274144350.81809 -New Zealand,NZL,1965,5654463586.00366 -New Zealand,NZL,1966,5863733230.97616 -New Zealand,NZL,1967,5961418093.53003 -New Zealand,NZL,1968,5180597620.64135 -New Zealand,NZL,1969,5761588761.69421 -New Zealand,NZL,1971,7912290825.15868 -New Zealand,NZL,1972,9567331064.65727 -New Zealand,NZL,1973,12802281897.8712 -New Zealand,NZL,1974,13940981798.1247 -New Zealand,NZL,1975,12861983284.3912 -New Zealand,NZL,1976,13604832424.0062 -New Zealand,NZL,1977,15446825318.4556 -New Zealand,NZL,1978,18530518394.6488 -New Zealand,NZL,1979,20730241410.3977 -New Zealand,NZL,1980,23245512449.3341 -New Zealand,NZL,1981,24417617184.2478 -New Zealand,NZL,1982,24164603058.9949 -New Zealand,NZL,1983,24308622502.6288 -New Zealand,NZL,1984,21665456808.0473 -New Zealand,NZL,1985,24680306905.3708 -New Zealand,NZL,1986,30605196451.2041 -New Zealand,NZL,1987,40377592076.7564 -New Zealand,NZL,1988,45176167471.8196 -New Zealand,NZL,1989,43920222524.7085 -New Zealand,NZL,1990,45495727006.5141 -New Zealand,NZL,1991,42745329732.163 -New Zealand,NZL,1992,41649298170.9911 -New Zealand,NZL,1993,46775067750.6775 -New Zealand,NZL,1994,55315342817.0218 -New Zealand,NZL,1995,63918703506.9075 -New Zealand,NZL,1996,70140835299.0148 -New Zealand,NZL,1997,66074513017.7142 -New Zealand,NZL,1998,56227169851.0448 -New Zealand,NZL,1999,58761741657.5847 -New Zealand,NZL,2000,52623281956.7031 -New Zealand,NZL,2001,53872425916.6248 -New Zealand,NZL,2002,66628222189.3637 -New Zealand,NZL,2003,88250885550.2626 -New Zealand,NZL,2004,103905882352.941 -New Zealand,NZL,2005,114719425473.492 -New Zealand,NZL,2006,111606899682.251 -New Zealand,NZL,2007,137314617476.299 -New Zealand,NZL,2008,133279679482.674 -New Zealand,NZL,2009,121337372727.841 -New Zealand,NZL,2010,146580949348.893 -New Zealand,NZL,2011,168461998741.295 -New Zealand,NZL,2012,176192886551.397 -New Zealand,NZL,2013,190521142196.379 -New Zealand,NZL,2014,200696291789.952 -New Zealand,NZL,2015,175564427552.782 -New Zealand,NZL,2016,185017316092.654 -Nicaragua,NIC,1960,223854666.666667 -Nicaragua,NIC,1961,240524723.428571 -Nicaragua,NIC,1962,265291588.666667 -Nicaragua,NIC,1963,292916241.142857 -Nicaragua,NIC,1964,341973758.857143 -Nicaragua,NIC,1965,566542872.357143 -Nicaragua,NIC,1966,606671444 -Nicaragua,NIC,1967,657171436.714286 -Nicaragua,NIC,1968,695899980.428571 -Nicaragua,NIC,1969,747971449.571429 -Nicaragua,NIC,1970,776585681.071429 -Nicaragua,NIC,1971,826571413.428571 -Nicaragua,NIC,1972,880842890.071429 -Nicaragua,NIC,1973,1093571441.5 -Nicaragua,NIC,1974,1520900045.14286 -Nicaragua,NIC,1975,1590428522.64286 -Nicaragua,NIC,1976,1847871371.71429 -Nicaragua,NIC,1977,2239857060.57143 -Nicaragua,NIC,1978,2142128603.78571 -Nicaragua,NIC,1979,1527852635.63158 -Nicaragua,NIC,1980,2189347367.52632 -Nicaragua,NIC,1981,2448290109.65 -Nicaragua,NIC,1982,2465165179.69565 -Nicaragua,NIC,1983,2743341724.08333 -Nicaragua,NIC,1984,3105517091.41379 -Nicaragua,NIC,1985,2683816288.7907 -Nicaragua,NIC,1986,2885710608.8808 -Nicaragua,NIC,1987,3851213727.67857 -Nicaragua,NIC,1988,2630904261.83247 -Nicaragua,NIC,1989,1013184745.70715 -Nicaragua,NIC,1990,1009455476.05583 -Nicaragua,NIC,1991,1488804123.71134 -Nicaragua,NIC,1992,1792800000 -Nicaragua,NIC,1993,1756454248.36601 -Nicaragua,NIC,1994,3863185119.04762 -Nicaragua,NIC,1995,4140470000 -Nicaragua,NIC,1996,4308351902.78601 -Nicaragua,NIC,1997,4389965590.96538 -Nicaragua,NIC,1998,4635267224.84195 -Nicaragua,NIC,1999,4855717874.68247 -Nicaragua,NIC,2000,5107329007.0922 -Nicaragua,NIC,2001,5323146565.70315 -Nicaragua,NIC,2002,5224213017.54386 -Nicaragua,NIC,2003,5322454925.84746 -Nicaragua,NIC,2004,5795568204.64532 -Nicaragua,NIC,2005,6321335612.22233 -Nicaragua,NIC,2006,6763671610.70006 -Nicaragua,NIC,2007,7423377429.05927 -Nicaragua,NIC,2008,8496965842.2767 -Nicaragua,NIC,2009,8298695144.91507 -Nicaragua,NIC,2010,8758622328.66962 -Nicaragua,NIC,2011,9774316692.15985 -Nicaragua,NIC,2012,10532001129.67 -Nicaragua,NIC,2013,10982972256.3787 -Nicaragua,NIC,2014,11880438824.4494 -Nicaragua,NIC,2015,12747741539.7259 -Nicaragua,NIC,2016,13230844686.858 -Niger,NER,1960,449526872.565561 -Niger,NER,1961,485785231.729353 -Niger,NER,1962,531736599.930736 -Niger,NER,1963,586294879.4719 -Niger,NER,1964,582816396.216401 -Niger,NER,1965,673383510.242124 -Niger,NER,1966,702296079.857695 -Niger,NER,1967,665586872.839162 -Niger,NER,1968,641214226.839012 -Niger,NER,1969,625867984.42818 -Niger,NER,1970,649916621.179857 -Niger,NER,1971,693573704.422866 -Niger,NER,1972,742779659.455167 -Niger,NER,1973,946385104.967731 -Niger,NER,1974,1026137112.43707 -Niger,NER,1975,1048690931.5406 -Niger,NER,1976,1064517600.10051 -Niger,NER,1977,1291458043.7403 -Niger,NER,1978,1774365587.86851 -Niger,NER,1979,2109277663.09748 -Niger,NER,1980,2508524715.79516 -Niger,NER,1981,2170893417.98129 -Niger,NER,1982,2017612217.82752 -Niger,NER,1983,1803099561.08393 -Niger,NER,1984,1461243326.83775 -Niger,NER,1985,1440581653.32328 -Niger,NER,1986,1904097000.74963 -Niger,NER,1987,2233006101.94476 -Niger,NER,1988,2280356194.14559 -Niger,NER,1989,2179567111.0004 -Niger,NER,1990,2480673304.74309 -Niger,NER,1991,2327986215.86356 -Niger,NER,1992,2344987614.27441 -Niger,NER,1993,1606581743.78497 -Niger,NER,1994,1563207224.65066 -Niger,NER,1995,1880803361.68562 -Niger,NER,1996,1987770898.54334 -Niger,NER,1997,1845599608.44272 -Niger,NER,1998,2076737356.67897 -Niger,NER,1999,2018193703.06047 -Niger,NER,2000,1798374468.36362 -Niger,NER,2001,1945327564.65042 -Niger,NER,2002,2170481508.86916 -Niger,NER,2003,2731416346.48158 -Niger,NER,2004,3052898739.4678 -Niger,NER,2005,3405134831.8505 -Niger,NER,2006,3646728060.06463 -Niger,NER,2007,4291363390.91295 -Niger,NER,2008,5403363917.3096 -Niger,NER,2009,5397121856.35204 -Niger,NER,2010,5718589799.24366 -Niger,NER,2011,6409169889.50891 -Niger,NER,2012,6942209594.55433 -Niger,NER,2013,7667951987.6933 -Niger,NER,2014,8245312136.56543 -Niger,NER,2015,7142951342.4223 -Niger,NER,2016,7508986509.27487 -Nigeria,NGA,1960,4196092258.15484 -Nigeria,NGA,1961,4467200335.99328 -Nigeria,NGA,1962,4909302953.94092 -Nigeria,NGA,1963,5165489010.2198 -Nigeria,NGA,1964,5552822483.55033 -Nigeria,NGA,1965,5874422511.54977 -Nigeria,NGA,1966,6366792664.14672 -Nigeria,NGA,1967,5203135937.28125 -Nigeria,NGA,1968,5200895982.08036 -Nigeria,NGA,1969,6634187316.25367 -Nigeria,NGA,1970,12545849083.0183 -Nigeria,NGA,1971,9181769911.50443 -Nigeria,NGA,1972,12274416017.7976 -Nigeria,NGA,1973,15162871287.1287 -Nigeria,NGA,1974,24846641318.1242 -Nigeria,NGA,1975,27778934624.6973 -Nigeria,NGA,1976,36308883248.731 -Nigeria,NGA,1977,36035407725.3219 -Nigeria,NGA,1978,36527862208.7133 -Nigeria,NGA,1979,47259911894.2731 -Nigeria,NGA,1980,64201788122.6054 -Nigeria,NGA,1981,61076493506.4935 -Nigeria,NGA,1982,51397461685.8237 -Nigeria,NGA,1983,35451565749.2355 -Nigeria,NGA,1984,28500815241.471 -Nigeria,NGA,1985,28873977228.1115 -Nigeria,NGA,1986,20721499308.4371 -Nigeria,NGA,1987,24093203444.564 -Nigeria,NGA,1988,23272161396.8853 -Nigeria,NGA,1989,24231168858.7187 -Nigeria,NGA,1990,30757075595.3681 -Nigeria,NGA,1991,27392886872.5547 -Nigeria,NGA,1992,29300903643.0584 -Nigeria,NGA,1993,15789003752.7594 -Nigeria,NGA,1994,18086400535.5777 -Nigeria,NGA,1995,28546958641.2735 -Nigeria,NGA,1996,34987951375 -Nigeria,NGA,1997,35822342617.6978 -Nigeria,NGA,1998,32004613750 -Nigeria,NGA,1999,35870792987.9432 -Nigeria,NGA,2000,46386011231.37 -Nigeria,NGA,2001,44137994251.618 -Nigeria,NGA,2002,59116847821.5797 -Nigeria,NGA,2003,67655813930.0926 -Nigeria,NGA,2004,87845420504.485 -Nigeria,NGA,2005,112248353104.911 -Nigeria,NGA,2006,145429764861.249 -Nigeria,NGA,2007,166451213395.64 -Nigeria,NGA,2008,208064753766.47 -Nigeria,NGA,2009,169481317540.364 -Nigeria,NGA,2010,369062464570.387 -Nigeria,NGA,2011,411743801711.642 -Nigeria,NGA,2012,460953836444.364 -Nigeria,NGA,2013,514966287206.505 -Nigeria,NGA,2014,568498939784.021 -Nigeria,NGA,2015,481066152870.266 -Nigeria,NGA,2016,405082677659.868 -Northern Mariana Islands,MNP,2002,1284000000 -Northern Mariana Islands,MNP,2003,1239000000 -Northern Mariana Islands,MNP,2004,1210000000 -Northern Mariana Islands,MNP,2005,1061000000 -Northern Mariana Islands,MNP,2006,990000000 -Northern Mariana Islands,MNP,2007,938000000 -Northern Mariana Islands,MNP,2008,939000000 -Northern Mariana Islands,MNP,2009,795000000 -Northern Mariana Islands,MNP,2010,799000000 -Northern Mariana Islands,MNP,2011,733000000 -Northern Mariana Islands,MNP,2012,751000000 -Northern Mariana Islands,MNP,2013,780000000 -Northern Mariana Islands,MNP,2014,836000000 -Northern Mariana Islands,MNP,2015,922000000 -Norway,NOR,1960,5163271598.15702 -Norway,NOR,1961,5632460936.54576 -Norway,NOR,1962,6066976682.67364 -Norway,NOR,1963,6510239502.76489 -Norway,NOR,1964,7159202706.48027 -Norway,NOR,1965,8058681060.159 -Norway,NOR,1966,8696460205.3397 -Norway,NOR,1967,9514496703.39762 -Norway,NOR,1968,10159934136.7838 -Norway,NOR,1969,11063065083.4888 -Norway,NOR,1970,12814123115.2613 -Norway,NOR,1971,14583114840.0629 -Norway,NOR,1972,17358610849.701 -Norway,NOR,1973,22534253702.8686 -Norway,NOR,1974,27145693810.1341 -Norway,NOR,1975,32877805200.023 -Norway,NOR,1976,35942270686.3374 -Norway,NOR,1977,41508030431.1074 -Norway,NOR,1978,46523091009.6713 -Norway,NOR,1979,53132244623.9213 -Norway,NOR,1980,64439382896.0156 -Norway,NOR,1981,63596654760.8677 -Norway,NOR,1982,62647195537.6511 -Norway,NOR,1983,61627240831.0948 -Norway,NOR,1984,62057955032.7758 -Norway,NOR,1985,65416879914.3907 -Norway,NOR,1986,78693253275.995 -Norway,NOR,1987,94230055658.6271 -Norway,NOR,1988,101900260856.222 -Norway,NOR,1989,102633789557.535 -Norway,NOR,1990,119791683307.507 -Norway,NOR,1991,121872464483.487 -Norway,NOR,1992,130838040067.584 -Norway,NOR,1993,120579072750.596 -Norway,NOR,1994,127131461119.927 -Norway,NOR,1995,152027402449.804 -Norway,NOR,1996,163517783497.163 -Norway,NOR,1997,161354369892.838 -Norway,NOR,1998,154165219811.533 -Norway,NOR,1999,162286003692.686 -Norway,NOR,2000,171315639982.731 -Norway,NOR,2001,174003247439.305 -Norway,NOR,2002,195418347152.985 -Norway,NOR,2003,228752436371.854 -Norway,NOR,2004,264357494659.388 -Norway,NOR,2005,308722079937.912 -Norway,NOR,2006,345424664369.357 -Norway,NOR,2007,400883873279.083 -Norway,NOR,2008,461946808510.638 -Norway,NOR,2009,386383919342.271 -Norway,NOR,2010,428527064662.898 -Norway,NOR,2011,498156756965.081 -Norway,NOR,2012,509704856037.817 -Norway,NOR,2013,522746212765.957 -Norway,NOR,2014,498339751388.521 -Norway,NOR,2015,386578443732.562 -Norway,NOR,2016,370556666666.667 -Oman,OMN,1965,63287594.5113414 -Oman,OMN,1966,67768132.1758611 -Oman,OMN,1967,107152720.243027 -Oman,OMN,1968,188864890.808735 -Oman,OMN,1969,239980801.535877 -Oman,OMN,1970,256299496.040317 -Oman,OMN,1971,301010587.102984 -Oman,OMN,1972,366857738.40542 -Oman,OMN,1973,483033932.135729 -Oman,OMN,1974,1645917776.49103 -Oman,OMN,1975,2096699189.34569 -Oman,OMN,1976,2560220034.74233 -Oman,OMN,1977,2741169947.88651 -Oman,OMN,1978,2740301389.69311 -Oman,OMN,1979,3733352634.62652 -Oman,OMN,1980,5981760277.93862 -Oman,OMN,1981,7259120150.55009 -Oman,OMN,1982,7554719455.70353 -Oman,OMN,1983,7932541690.79328 -Oman,OMN,1984,8821366531.55762 -Oman,OMN,1985,10005500579.0388 -Oman,OMN,1986,7323822251.3089 -Oman,OMN,1987,7811183094.92848 -Oman,OMN,1988,8386215864.75943 -Oman,OMN,1989,9372171651.49545 -Oman,OMN,1990,11685045513.6541 -Oman,OMN,1991,11341482444.7334 -Oman,OMN,1992,12452275682.7048 -Oman,OMN,1993,12493107932.3797 -Oman,OMN,1994,12918855656.697 -Oman,OMN,1995,13802600780.2341 -Oman,OMN,1996,15277763328.9987 -Oman,OMN,1997,15837451235.3706 -Oman,OMN,1998,14085373211.9636 -Oman,OMN,1999,15710148244.4733 -Oman,OMN,2000,19507412223.6671 -Oman,OMN,2001,19452015604.6814 -Oman,OMN,2002,20142782834.8505 -Oman,OMN,2003,21633810143.0429 -Oman,OMN,2004,24763589076.723 -Oman,OMN,2005,31081924577.3732 -Oman,OMN,2006,37215864759.4278 -Oman,OMN,2007,42085305591.6775 -Oman,OMN,2008,60905331599.4798 -Oman,OMN,2009,48388296488.9467 -Oman,OMN,2010,58641621957.8941 -Oman,OMN,2011,67937307405.122 -Oman,OMN,2012,76689583316.9189 -Oman,OMN,2013,78938585285.6905 -Oman,OMN,2014,81034395037.5246 -Oman,OMN,2015,69831770995.5405 -Oman,OMN,2016,66293368010.4031 -Pakistan,PAK,1960,3707055900.88198 -Pakistan,PAK,1961,4054599181.01638 -Pakistan,PAK,1962,4233095590.0882 -Pakistan,PAK,1963,4540529105.41789 -Pakistan,PAK,1964,5130407727.84544 -Pakistan,PAK,1965,5884712095.75809 -Pakistan,PAK,1966,6466610751.78496 -Pakistan,PAK,1967,7403821902.56195 -Pakistan,PAK,1968,8090088555.2289 -Pakistan,PAK,1969,8632927257.45485 -Pakistan,PAK,1970,10027088849.223 -Pakistan,PAK,1971,10602058189.8362 -Pakistan,PAK,1972,9309109764.07784 -Pakistan,PAK,1973,6324884129.38617 -Pakistan,PAK,1974,8773030424.24242 -Pakistan,PAK,1975,11340000242.4242 -Pakistan,PAK,1976,13338484979.798 -Pakistan,PAK,1977,15126059646.4646 -Pakistan,PAK,1978,17820100626.2626 -Pakistan,PAK,1979,19707979303.0303 -Pakistan,PAK,1980,23689696767.6768 -Pakistan,PAK,1981,28100605515.1515 -Pakistan,PAK,1982,30725972786.7299 -Pakistan,PAK,1983,28691890433.0709 -Pakistan,PAK,1984,31151824658.6524 -Pakistan,PAK,1985,31144920554.0897 -Pakistan,PAK,1986,31899071053.9368 -Pakistan,PAK,1987,33351528115.351 -Pakistan,PAK,1988,38472741737.3968 -Pakistan,PAK,1989,40171019643.3511 -Pakistan,PAK,1990,40010424928.715 -Pakistan,PAK,1991,45451960731.7204 -Pakistan,PAK,1992,48635176852.7673 -Pakistan,PAK,1993,51478304859.5879 -Pakistan,PAK,1994,51894781281.8919 -Pakistan,PAK,1995,60636022422.6176 -Pakistan,PAK,1996,63320122807.1223 -Pakistan,PAK,1997,62433300338.0941 -Pakistan,PAK,1998,62191955814.3478 -Pakistan,PAK,1999,62973855718.8874 -Pakistan,PAK,2000,73952374969.7995 -Pakistan,PAK,2001,72309738921.3329 -Pakistan,PAK,2002,72306820396.2325 -Pakistan,PAK,2003,83244801092.7096 -Pakistan,PAK,2004,97977766197.6724 -Pakistan,PAK,2005,109502102510.883 -Pakistan,PAK,2006,137264061106.043 -Pakistan,PAK,2007,152385716311.916 -Pakistan,PAK,2008,170077814106.305 -Pakistan,PAK,2009,168152775283.032 -Pakistan,PAK,2010,177406854514.885 -Pakistan,PAK,2011,213587413183.996 -Pakistan,PAK,2012,224383620829.57 -Pakistan,PAK,2013,231218567178.979 -Pakistan,PAK,2014,244360888750.807 -Pakistan,PAK,2015,271049886672.733 -Pakistan,PAK,2016,283659980698.255 -Palau,PLW,1990,76888000 -Palau,PLW,1991,83855000 -Palau,PLW,1992,82451000 -Palau,PLW,1993,75907000 -Palau,PLW,1994,83527000 -Palau,PLW,1995,95237000 -Palau,PLW,1996,108203000 -Palau,PLW,1997,113213000 -Palau,PLW,1998,117320000 -Palau,PLW,1999,113485000 -Palau,PLW,2000,149300000 -Palau,PLW,2001,160000000 -Palau,PLW,2002,163500000 -Palau,PLW,2003,159900000 -Palau,PLW,2004,175300000 -Palau,PLW,2005,193300000 -Palau,PLW,2006,194700000 -Palau,PLW,2007,196000000 -Palau,PLW,2008,198100000 -Palau,PLW,2009,186400000 -Palau,PLW,2010,183800000 -Palau,PLW,2011,199900000 -Palau,PLW,2012,214200000 -Palau,PLW,2013,228700000 -Palau,PLW,2014,250900000 -Palau,PLW,2015,287400000 -Palau,PLW,2016,293000000 -Panama,PAN,1960,537147100 -Panama,PAN,1961,599026300 -Panama,PAN,1962,652120900 -Panama,PAN,1963,722784500 -Panama,PAN,1964,776137500 -Panama,PAN,1965,852485300 -Panama,PAN,1966,928833000 -Panama,PAN,1967,1034376400 -Panama,PAN,1968,1112791100 -Panama,PAN,1969,1221305700 -Panama,PAN,1970,1351006400 -Panama,PAN,1971,1523917200 -Panama,PAN,1972,1673411700 -Panama,PAN,1973,1913793400 -Panama,PAN,1974,2188307600 -Panama,PAN,1975,2435304100 -Panama,PAN,1976,2588106000 -Panama,PAN,1977,2738261900 -Panama,PAN,1978,3244558600 -Panama,PAN,1979,3704551600 -Panama,PAN,1980,4614086400 -Panama,PAN,1981,5222421500 -Panama,PAN,1982,5769767900 -Panama,PAN,1983,5923755900 -Panama,PAN,1984,6183387100 -Panama,PAN,1985,6541517100 -Panama,PAN,1986,6797834200 -Panama,PAN,1987,6827665300 -Panama,PAN,1988,5902783400 -Panama,PAN,1989,5918469800 -Panama,PAN,1990,6433967000 -Panama,PAN,1991,7074675500 -Panama,PAN,1992,8042337700 -Panama,PAN,1993,8782585400 -Panama,PAN,1994,9365289800 -Panama,PAN,1995,9573813700 -Panama,PAN,1996,9870494000 -Panama,PAN,1997,10677286100 -Panama,PAN,1998,11575486400 -Panama,PAN,1999,12130252200 -Panama,PAN,2000,12304115000 -Panama,PAN,2001,12502013400 -Panama,PAN,2002,12994310400 -Panama,PAN,2003,13693981200 -Panama,PAN,2004,15013381700 -Panama,PAN,2005,16374393900 -Panama,PAN,2006,18141666300 -Panama,PAN,2007,20958000000 -Panama,PAN,2008,24522200000 -Panama,PAN,2009,26593500000 -Panama,PAN,2010,28917200000 -Panama,PAN,2011,34373820500 -Panama,PAN,2012,39954761200 -Panama,PAN,2013,44856189500 -Panama,PAN,2014,49165773100 -Panama,PAN,2015,52132289700 -Panama,PAN,2016,55187700000 -Papua New Guinea,PNG,1960,230496032.972722 -Papua New Guinea,PNG,1961,244832035.023504 -Papua New Guinea,PNG,1962,261184037.362676 -Papua New Guinea,PNG,1963,275968039.477545 -Papua New Guinea,PNG,1964,305312043.675238 -Papua New Guinea,PNG,1965,344159480.344943 -Papua New Guinea,PNG,1966,390973233.284802 -Papua New Guinea,PNG,1967,441706910.068317 -Papua New Guinea,PNG,1968,485160824.280435 -Papua New Guinea,PNG,1969,551237316.608803 -Papua New Guinea,PNG,1970,645537126.217942 -Papua New Guinea,PNG,1971,717716130.493883 -Papua New Guinea,PNG,1972,858802035.928144 -Papua New Guinea,PNG,1973,1299105240.73285 -Papua New Guinea,PNG,1974,1467346059.99713 -Papua New Guinea,PNG,1975,1356591176.85561 -Papua New Guinea,PNG,1976,1511856584.25833 -Papua New Guinea,PNG,1977,1640763204.44781 -Papua New Guinea,PNG,1978,1947947524.33347 -Papua New Guinea,PNG,1979,2293621944.3664 -Papua New Guinea,PNG,1980,2545983007.89984 -Papua New Guinea,PNG,1981,2498068350.66865 -Papua New Guinea,PNG,1982,2368584969.53284 -Papua New Guinea,PNG,1983,2562492524.81761 -Papua New Guinea,PNG,1984,2552526263.0759 -Papua New Guinea,PNG,1985,2423373088.07358 -Papua New Guinea,PNG,1986,2648033765.69899 -Papua New Guinea,PNG,1987,3143848331.31402 -Papua New Guinea,PNG,1988,3655979702.45646 -Papua New Guinea,PNG,1989,3546460176.99115 -Papua New Guinea,PNG,1990,3219730365 -Papua New Guinea,PNG,1991,3787352286.66667 -Papua New Guinea,PNG,1992,4377984100 -Papua New Guinea,PNG,1993,4974662910 -Papua New Guinea,PNG,1994,5502648500 -Papua New Guinea,PNG,1995,4636113480.00002 -Papua New Guinea,PNG,1996,5155485419.7 -Papua New Guinea,PNG,1997,4936605079.99998 -Papua New Guinea,PNG,1998,3789428160.00001 -Papua New Guinea,PNG,1999,3477060138.33333 -Papua New Guinea,PNG,2000,3521348154.79666 -Papua New Guinea,PNG,2001,3081029665.98233 -Papua New Guinea,PNG,2002,2999542369.42117 -Papua New Guinea,PNG,2003,3536459111.2438 -Papua New Guinea,PNG,2004,3927114465.90565 -Papua New Guinea,PNG,2005,4865971718.29732 -Papua New Guinea,PNG,2006,5527856839.07482 -Papua New Guinea,PNG,2007,6340673793.54534 -Papua New Guinea,PNG,2008,8000074071.33069 -Papua New Guinea,PNG,2009,8105331929.8755 -Papua New Guinea,PNG,2010,9716103408.96554 -Papua New Guinea,PNG,2011,12873049346.2674 -Papua New Guinea,PNG,2012,15391629871.3765 -Papua New Guinea,PNG,2013,15413163674.9224 -Papua New Guinea,PNG,2014,16928680397.4185 -Paraguay,PRY,1965,400129691.269841 -Paraguay,PRY,1966,421700442.063492 -Paraguay,PRY,1967,451524124.603175 -Paraguay,PRY,1968,477012512.698413 -Paraguay,PRY,1969,512728946.031746 -Paraguay,PRY,1970,548758098.412698 -Paraguay,PRY,1971,609047284.920635 -Paraguay,PRY,1972,697291727.777778 -Paraguay,PRY,1973,889357059.52381 -Paraguay,PRY,1974,1199618980.15873 -Paraguay,PRY,1975,1351889403.1746 -Paraguay,PRY,1976,1540820245.2381 -Paraguay,PRY,1977,1912353339.68254 -Paraguay,PRY,1978,2350329157.14286 -Paraguay,PRY,1979,3135123879.36508 -Paraguay,PRY,1980,4094810488.09524 -Paraguay,PRY,1981,5219516810.31746 -Paraguay,PRY,1982,5067450002.20588 -Paraguay,PRY,1983,5237432542.46575 -Paraguay,PRY,1984,4067222369.30652 -Paraguay,PRY,1985,2966234106.19469 -Paraguay,PRY,1986,3439716561.65443 -Paraguay,PRY,1987,3778316380.23952 -Paraguay,PRY,1988,4082625952.73809 -Paraguay,PRY,1989,4599970618.44348 -Paraguay,PRY,1990,5695201563.42495 -Paraguay,PRY,1991,6984367762.90371 -Paraguay,PRY,1992,7157424031.06045 -Paraguay,PRY,1993,7249533620.30614 -Paraguay,PRY,1994,7870982170.98217 -Paraguay,PRY,1995,9062131307.88275 -Paraguay,PRY,1996,9788391732.82899 -Paraguay,PRY,1997,9965225496.5884 -Paraguay,PRY,1998,9024567484.2013 -Paraguay,PRY,1999,8392549702.31511 -Paraguay,PRY,2000,8195993230.74275 -Paraguay,PRY,2001,7662595075.90241 -Paraguay,PRY,2002,6325151760.0669 -Paraguay,PRY,2003,6588103836.34739 -Paraguay,PRY,2004,8033877360.41697 -Paraguay,PRY,2005,8734653809.49561 -Paraguay,PRY,2006,10646157920.3209 -Paraguay,PRY,2007,13794910633.8518 -Paraguay,PRY,2008,18504130752.9922 -Paraguay,PRY,2009,15929902138.1363 -Paraguay,PRY,2010,20030528042.9171 -Paraguay,PRY,2011,25099681460.8943 -Paraguay,PRY,2012,24595319573.7548 -Paraguay,PRY,2013,28965906502.2306 -Paraguay,PRY,2014,30881166852.3116 -Paraguay,PRY,2015,27282581335.7964 -Paraguay,PRY,2016,27440632933.5561 -Peru,PER,1960,2571908062.07692 -Peru,PER,1961,2899654840.36567 -Peru,PER,1962,3286773187.87687 -Peru,PER,1963,3600957771.15299 -Peru,PER,1964,4356913870.23508 -Peru,PER,1965,5166861068.42164 -Peru,PER,1966,6113607728.15672 -Peru,PER,1967,6204253758.57616 -Peru,PER,1968,5736083835.22481 -Peru,PER,1969,6420909789.63824 -Peru,PER,1970,7432223176.77261 -Peru,PER,1971,8289582883.50129 -Peru,PER,1972,9189413409.01292 -Peru,PER,1973,10994381894.7984 -Peru,PER,1974,13858441211.2196 -Peru,PER,1975,16877163792.1284 -Peru,PER,1976,15947709379.6507 -Peru,PER,1977,14620386673.8544 -Peru,PER,1978,12495779622.071 -Peru,PER,1979,15962459447.2168 -Peru,PER,1980,18134029179.6393 -Peru,PER,1981,21649137620.3055 -Peru,PER,1982,21793496819.3379 -Peru,PER,1983,17345624453.6916 -Peru,PER,1984,17599660054.286 -Peru,PER,1985,16548827018.2872 -Peru,PER,1986,15244232957.876 -Peru,PER,1987,20702298396.9717 -Peru,PER,1988,15439408447.2288 -Peru,PER,1989,22499559086.0343 -Peru,PER,1990,26410386669.3609 -Peru,PER,1991,34672122380.7687 -Peru,PER,1992,36139225287.9079 -Peru,PER,1993,35158109999.4973 -Peru,PER,1994,44882079766.8913 -Peru,PER,1995,53312793687.3836 -Peru,PER,1996,55252414130.3019 -Peru,PER,1997,58147522522.5225 -Peru,PER,1998,55501467877.381 -Peru,PER,1999,50187324567.883 -Peru,PER,2000,51744749133.213 -Peru,PER,2001,52030158775.4055 -Peru,PER,2002,54777553515.0809 -Peru,PER,2003,58731030121.8671 -Peru,PER,2004,66768703497.5687 -Peru,PER,2005,76060606060.606 -Peru,PER,2006,88643193061.748 -Peru,PER,2007,102170981144.136 -Peru,PER,2008,120550599815.441 -Peru,PER,2009,120822986521.479 -Peru,PER,2010,147528937028.778 -Peru,PER,2011,171761737046.585 -Peru,PER,2012,192648999090.082 -Peru,PER,2013,201217661645.509 -Peru,PER,2014,201049665375.132 -Peru,PER,2015,189212096470.293 -Peru,PER,2016,192093512185.011 -Philippines,PHL,1960,6684568805.06881 -Philippines,PHL,1961,7256966966.22556 -Philippines,PHL,1962,4399827767.96704 -Philippines,PHL,1963,4875309866.34017 -Philippines,PHL,1964,5271404668.36735 -Philippines,PHL,1965,5784398976.9821 -Philippines,PHL,1966,6371459304.41018 -Philippines,PHL,1967,6809134235.54298 -Philippines,PHL,1968,7591603053.43511 -Philippines,PHL,1969,8408229699.14295 -Philippines,PHL,1970,6687204834.3687 -Philippines,PHL,1971,7408305735.65309 -Philippines,PHL,1972,8017468688.2004 -Philippines,PHL,1973,10082885603.0668 -Philippines,PHL,1974,13781139969.6519 -Philippines,PHL,1975,14893969287.6557 -Philippines,PHL,1976,17097563270.2982 -Philippines,PHL,1977,19648106122.0079 -Philippines,PHL,1978,22706155475.3048 -Philippines,PHL,1979,27502168726.9573 -Philippines,PHL,1980,32450541843.0652 -Philippines,PHL,1981,35646416952.5425 -Philippines,PHL,1982,37140163934.4262 -Philippines,PHL,1983,33212180658.1659 -Philippines,PHL,1984,31408492876.691 -Philippines,PHL,1985,30734335448.9905 -Philippines,PHL,1986,29868339080.8263 -Philippines,PHL,1987,33195933429.6008 -Philippines,PHL,1988,37885440418.6834 -Philippines,PHL,1989,42575183905.5606 -Philippines,PHL,1990,44311593755.7845 -Philippines,PHL,1991,45417561302.2497 -Philippines,PHL,1992,52976344928.9564 -Philippines,PHL,1993,54368083953.1119 -Philippines,PHL,1994,64084460124.4644 -Philippines,PHL,1995,74119987244.5011 -Philippines,PHL,1996,82848140618.0266 -Philippines,PHL,1997,82344260570.6685 -Philippines,PHL,1998,72207025219.4752 -Philippines,PHL,1999,82995147089.9742 -Philippines,PHL,2000,81026297144.2795 -Philippines,PHL,2001,76262072022.215 -Philippines,PHL,2002,81357602950.1818 -Philippines,PHL,2003,83908206456.0645 -Philippines,PHL,2004,91371239764.8818 -Philippines,PHL,2005,103071585462.599 -Philippines,PHL,2006,122210719245.902 -Philippines,PHL,2007,149359920005.894 -Philippines,PHL,2008,174195135053.121 -Philippines,PHL,2009,168334599538.168 -Philippines,PHL,2010,199590774784.581 -Philippines,PHL,2011,224143083706.777 -Philippines,PHL,2012,250092093547.532 -Philippines,PHL,2013,271836123723.678 -Philippines,PHL,2014,284584522898.935 -Philippines,PHL,2015,292774099014.19 -Philippines,PHL,2016,304905406845.908 -Poland,POL,1990,65977749038.438 -Poland,POL,1991,85500935934.9901 -Poland,POL,1992,94337050693.2727 -Poland,POL,1993,96045645026.178 -Poland,POL,1994,110803391516.698 -Poland,POL,1995,142137319587.629 -Poland,POL,1996,159942880456.956 -Poland,POL,1997,159117799530.388 -Poland,POL,1998,174388271853.6 -Poland,POL,1999,169717677900.734 -Poland,POL,2000,171885598582.637 -Poland,POL,2001,190521263343.023 -Poland,POL,2002,198680637254.902 -Poland,POL,2003,217518642324.505 -Poland,POL,2004,255102252843.395 -Poland,POL,2005,306134635593.744 -Poland,POL,2006,344826430298.147 -Poland,POL,2007,429249647594.607 -Poland,POL,2008,533815789473.684 -Poland,POL,2009,439796160379.475 -Poland,POL,2010,479321128909.23 -Poland,POL,2011,528819945375.376 -Poland,POL,2012,500344281382.345 -Poland,POL,2013,524214789307.993 -Poland,POL,2014,545151778520.387 -Poland,POL,2015,477336782066.587 -Poland,POL,2016,469508680416.119 -Portugal,PRT,1960,3193200404.37297 -Portugal,PRT,1961,3417516639.37596 -Portugal,PRT,1962,3668222357.65702 -Portugal,PRT,1963,3905734459.72693 -Portugal,PRT,1964,4235608177.67102 -Portugal,PRT,1965,4687464054.83455 -Portugal,PRT,1966,5135387845.97108 -Portugal,PRT,1967,5740241165.63433 -Portugal,PRT,1968,6354262628.33537 -Portugal,PRT,1969,6969025825.62869 -Portugal,PRT,1970,8109032775.45328 -Portugal,PRT,1971,9202512367.49117 -Portugal,PRT,1972,11240223128.2431 -Portugal,PRT,1973,15092052330.3352 -Portugal,PRT,1974,17514112075.7695 -Portugal,PRT,1975,19349512941.1765 -Portugal,PRT,1976,20334835543.7666 -Portugal,PRT,1977,21441635411.2101 -Portugal,PRT,1978,23489924726.2774 -Portugal,PRT,1979,26625439344.2623 -Portugal,PRT,1980,32899759311.1734 -Portugal,PRT,1981,31980423452.7687 -Portugal,PRT,1982,30530759334.0061 -Portugal,PRT,1983,27242331885.6316 -Portugal,PRT,1984,25220451794.029 -Portugal,PRT,1985,27118476173.6675 -Portugal,PRT,1986,38749715721.7531 -Portugal,PRT,1987,48187667852.5687 -Portugal,PRT,1988,56352797353.7604 -Portugal,PRT,1989,60600056659.0272 -Portugal,PRT,1990,78721607509.4923 -Portugal,PRT,1991,89242382961.0101 -Portugal,PRT,1992,107602689040.689 -Portugal,PRT,1993,95019103603.042 -Portugal,PRT,1994,99698453260.8696 -Portugal,PRT,1995,118133634071.912 -Portugal,PRT,1996,122629812841.175 -Portugal,PRT,1997,117046198970.84 -Portugal,PRT,1998,123981736420.303 -Portugal,PRT,1999,127465545493.288 -Portugal,PRT,2000,118358489957.619 -Portugal,PRT,2001,121545880984.34 -Portugal,PRT,2002,134228697534.35 -Portugal,PRT,2003,164964195259.594 -Portugal,PRT,2004,189187437298.237 -Portugal,PRT,2005,197304513120.259 -Portugal,PRT,2006,208566948939.907 -Portugal,PRT,2007,240169336162.059 -Portugal,PRT,2008,262007590449.685 -Portugal,PRT,2009,243745748819.116 -Portugal,PRT,2010,238303443425.21 -Portugal,PRT,2011,244895101712.451 -Portugal,PRT,2012,216368178659.447 -Portugal,PRT,2013,226073492966.495 -Portugal,PRT,2014,229629822121.601 -Portugal,PRT,2015,199082291239.307 -Portugal,PRT,2016,204564700289.118 -Puerto Rico,PRI,1960,1691900000 -Puerto Rico,PRI,1961,1865100000 -Puerto Rico,PRI,1962,2094400000 -Puerto Rico,PRI,1963,2333600000 -Puerto Rico,PRI,1964,2570500000 -Puerto Rico,PRI,1965,2881500000 -Puerto Rico,PRI,1966,3170500000 -Puerto Rico,PRI,1967,3532700000 -Puerto Rico,PRI,1968,3941700000 -Puerto Rico,PRI,1969,4460700000 -Puerto Rico,PRI,1970,5034700000 -Puerto Rico,PRI,1971,5646800000 -Puerto Rico,PRI,1972,6328900000 -Puerto Rico,PRI,1973,7002400000 -Puerto Rico,PRI,1974,7684800000 -Puerto Rico,PRI,1975,8198300000 -Puerto Rico,PRI,1976,8968600000 -Puerto Rico,PRI,1977,9910900000 -Puerto Rico,PRI,1978,11165000000 -Puerto Rico,PRI,1979,12750000000 -Puerto Rico,PRI,1980,14436100000 -Puerto Rico,PRI,1981,15955700000 -Puerto Rico,PRI,1982,16764200000 -Puerto Rico,PRI,1983,17276600000 -Puerto Rico,PRI,1984,19162600000 -Puerto Rico,PRI,1985,20289200000 -Puerto Rico,PRI,1986,21969400000 -Puerto Rico,PRI,1987,23878000000 -Puerto Rico,PRI,1988,26178400000 -Puerto Rico,PRI,1989,28266800000 -Puerto Rico,PRI,1990,30603919000 -Puerto Rico,PRI,1991,32287031000 -Puerto Rico,PRI,1992,34630430000 -Puerto Rico,PRI,1993,36922456000 -Puerto Rico,PRI,1994,39690630000 -Puerto Rico,PRI,1995,42647331000 -Puerto Rico,PRI,1996,45340835000 -Puerto Rico,PRI,1997,48187039000 -Puerto Rico,PRI,1998,54086409000 -Puerto Rico,PRI,1999,57840954000 -Puerto Rico,PRI,2000,61701810000 -Puerto Rico,PRI,2001,69668635000 -Puerto Rico,PRI,2002,72546194000 -Puerto Rico,PRI,2003,75833996000 -Puerto Rico,PRI,2004,80322313000 -Puerto Rico,PRI,2005,83914521340.5431 -Puerto Rico,PRI,2006,87276164364.6388 -Puerto Rico,PRI,2007,89524131617.1909 -Puerto Rico,PRI,2008,93639316000 -Puerto Rico,PRI,2009,96385638000 -Puerto Rico,PRI,2010,98381268000 -Puerto Rico,PRI,2011,100351670000 -Puerto Rico,PRI,2012,101080738000 -Puerto Rico,PRI,2013,103134778000 -Qatar,QAT,1970,301791301.791302 -Qatar,QAT,1971,387700084.245998 -Qatar,QAT,1972,510259940.720474 -Qatar,QAT,1973,793884368.040437 -Qatar,QAT,1974,2401403227.44085 -Qatar,QAT,1975,2512784033.37828 -Qatar,QAT,1976,3284301332.18953 -Qatar,QAT,1977,3617580171.76055 -Qatar,QAT,1978,4052000412.70087 -Qatar,QAT,1979,5633000318.02401 -Qatar,QAT,1980,7829094613.07082 -Qatar,QAT,1981,8661263763.73626 -Qatar,QAT,1982,7596703214.28571 -Qatar,QAT,1983,6467582307.69231 -Qatar,QAT,1984,6704395824.17583 -Qatar,QAT,1985,6153296456.04396 -Qatar,QAT,1986,5053021950.54945 -Qatar,QAT,1987,5446428681.31868 -Qatar,QAT,1988,6038187032.96703 -Qatar,QAT,1989,6487912087.91209 -Qatar,QAT,1990,7360439423.07692 -Qatar,QAT,1991,6883516483.51648 -Qatar,QAT,1992,7646153983.51648 -Qatar,QAT,1993,7156593653.84615 -Qatar,QAT,1994,7374450769.23077 -Qatar,QAT,1995,8137911978.02198 -Qatar,QAT,1996,9059340384.61539 -Qatar,QAT,1997,11297802115.3846 -Qatar,QAT,1998,10255495027.4725 -Qatar,QAT,1999,12393131868.1319 -Qatar,QAT,2000,17759890109.8901 -Qatar,QAT,2001,17538461538.4615 -Qatar,QAT,2002,19363736263.7363 -Qatar,QAT,2003,23533791208.7912 -Qatar,QAT,2004,31734065934.0659 -Qatar,QAT,2005,44530494505.4945 -Qatar,QAT,2006,60882142857.1428 -Qatar,QAT,2007,79712087912.0879 -Qatar,QAT,2008,115270054945.055 -Qatar,QAT,2009,97798351648.3516 -Qatar,QAT,2010,125122306346.154 -Qatar,QAT,2011,167775274725.275 -Qatar,QAT,2012,186833516483.516 -Qatar,QAT,2013,198727747252.747 -Qatar,QAT,2014,206224725274.725 -Qatar,QAT,2015,164641483516.484 -Qatar,QAT,2016,152468681318.681 -Romania,ROU,1987,38413636363.6364 -Romania,ROU,1988,40809523809.5238 -Romania,ROU,1989,42105263157.8947 -Romania,ROU,1990,38995454545.4545 -Romania,ROU,1991,28998684210.5263 -Romania,ROU,1992,25121666666.6667 -Romania,ROU,1993,26362894736.8421 -Romania,ROU,1994,30074440483.3837 -Romania,ROU,1995,37662075750.123 -Romania,ROU,1996,37182938696.0752 -Romania,ROU,1997,35838588169.6429 -Romania,ROU,1998,41976002703.9207 -Romania,ROU,1999,36183003978.3474 -Romania,ROU,2000,37438527799.5302 -Romania,ROU,2001,40716836998.0386 -Romania,ROU,2002,46174557555.5892 -Romania,ROU,2003,59867801204.8193 -Romania,ROU,2004,76216441462.1442 -Romania,ROU,2005,99697566667.8107 -Romania,ROU,2006,123533036667.853 -Romania,ROU,2007,171536685395.563 -Romania,ROU,2008,208181626900.631 -Romania,ROU,2009,167422949529.4 -Romania,ROU,2010,167998080493.408 -Romania,ROU,2011,185362855081.021 -Romania,ROU,2012,171664638717.49 -Romania,ROU,2013,191549024910.604 -Romania,ROU,2014,199493490982.921 -Romania,ROU,2015,177522705145.168 -Romania,ROU,2016,186690595273.12 -Russian Federation,RUS,1989,506500154001.466 -Russian Federation,RUS,1990,516814258695.568 -Russian Federation,RUS,1991,517962962962.963 -Russian Federation,RUS,1992,460290556900.726 -Russian Federation,RUS,1993,435083713850.837 -Russian Federation,RUS,1994,395077301248.464 -Russian Federation,RUS,1995,395531066563.296 -Russian Federation,RUS,1996,391719993756.828 -Russian Federation,RUS,1997,404926534140.017 -Russian Federation,RUS,1998,270953116950.026 -Russian Federation,RUS,1999,195905767668.562 -Russian Federation,RUS,2000,259708496267.33 -Russian Federation,RUS,2001,306602673980.117 -Russian Federation,RUS,2002,345110438692.185 -Russian Federation,RUS,2003,430347770731.787 -Russian Federation,RUS,2004,591016690742.798 -Russian Federation,RUS,2005,764017107992.391 -Russian Federation,RUS,2006,989930542278.695 -Russian Federation,RUS,2007,1299705247685.76 -Russian Federation,RUS,2008,1660844408499.61 -Russian Federation,RUS,2009,1222643696991.85 -Russian Federation,RUS,2010,1524916112078.87 -Russian Federation,RUS,2011,2031768558635.85 -Russian Federation,RUS,2012,2170143623037.67 -Russian Federation,RUS,2013,2230625004653.55 -Russian Federation,RUS,2014,2063662281005.13 -Russian Federation,RUS,2015,1365865245098.18 -Russian Federation,RUS,2016,1283162348132.89 -Rwanda,RWA,1960,119000024 -Rwanda,RWA,1961,122000016 -Rwanda,RWA,1962,125000008 -Rwanda,RWA,1963,128000000 -Rwanda,RWA,1964,129999994 -Rwanda,RWA,1965,148799980 -Rwanda,RWA,1966,124525702.857143 -Rwanda,RWA,1967,159560018 -Rwanda,RWA,1968,172200018 -Rwanda,RWA,1969,188700037 -Rwanda,RWA,1970,219900006 -Rwanda,RWA,1971,222952578.196381 -Rwanda,RWA,1972,246457838.336681 -Rwanda,RWA,1973,290746157.145921 -Rwanda,RWA,1974,308458423.183854 -Rwanda,RWA,1975,571863295.740122 -Rwanda,RWA,1976,637754162.101094 -Rwanda,RWA,1977,746650558.55469 -Rwanda,RWA,1978,905709147.27019 -Rwanda,RWA,1979,1109346220.52885 -Rwanda,RWA,1980,1254765349.93185 -Rwanda,RWA,1981,1407062607.63214 -Rwanda,RWA,1982,1407242640.23211 -Rwanda,RWA,1983,1479688125.8852 -Rwanda,RWA,1984,1587412957.22263 -Rwanda,RWA,1985,1715625839.17973 -Rwanda,RWA,1986,1944711061.30888 -Rwanda,RWA,1987,2157434025.16467 -Rwanda,RWA,1988,2395493877.51365 -Rwanda,RWA,1989,2405021932.89997 -Rwanda,RWA,1990,2550185618.14774 -Rwanda,RWA,1991,1911600969.76612 -Rwanda,RWA,1992,2029026704.02707 -Rwanda,RWA,1993,1971525998.87685 -Rwanda,RWA,1994,753636370.454546 -Rwanda,RWA,1995,1293535010.94467 -Rwanda,RWA,1996,1382334879.40812 -Rwanda,RWA,1997,1851558301.7002 -Rwanda,RWA,1998,1989343495.21844 -Rwanda,RWA,1999,1817655328.06755 -Rwanda,RWA,2000,1734938264.47371 -Rwanda,RWA,2001,1674685094.01639 -Rwanda,RWA,2002,1677447150.10691 -Rwanda,RWA,2003,1845979298.99285 -Rwanda,RWA,2004,2089188828.797 -Rwanda,RWA,2005,2581465863.87859 -Rwanda,RWA,2006,3152016556.51526 -Rwanda,RWA,2007,3824811913.22869 -Rwanda,RWA,2008,4860576609.21568 -Rwanda,RWA,2009,5379378135.44102 -Rwanda,RWA,2010,5774003744.2708 -Rwanda,RWA,2011,6491683831.5094 -Rwanda,RWA,2012,7315702176.36442 -Rwanda,RWA,2013,7622526429.08839 -Rwanda,RWA,2014,8016288347.03577 -Rwanda,RWA,2015,8261034257.63248 -Rwanda,RWA,2016,8376048904.58291 -Samoa,WSM,1982,121221651.619316 -Samoa,WSM,1983,111862823.574979 -Samoa,WSM,1984,109200934.328518 -Samoa,WSM,1985,95572172.9835657 -Samoa,WSM,1986,100947848.64478 -Samoa,WSM,1987,111713922.141578 -Samoa,WSM,1988,133016065.416065 -Samoa,WSM,1989,122888609.715243 -Samoa,WSM,1990,125766269.755358 -Samoa,WSM,1991,125597205.422315 -Samoa,WSM,1992,132303041.36253 -Samoa,WSM,1993,133122897.196262 -Samoa,WSM,1994,221098106.508876 -Samoa,WSM,1995,224865731.381903 -Samoa,WSM,1996,249908970.658971 -Samoa,WSM,1997,285475591.89651 -Samoa,WSM,1998,269481523.200465 -Samoa,WSM,1999,258833766.580017 -Samoa,WSM,2000,269019710.327456 -Samoa,WSM,2001,273088357.1637 -Samoa,WSM,2002,288078881.433056 -Samoa,WSM,2003,338838639.378435 -Samoa,WSM,2004,420320176.359437 -Samoa,WSM,2005,462644663.06818 -Samoa,WSM,2006,508505414.405727 -Samoa,WSM,2007,550967295.278082 -Samoa,WSM,2008,644143266.155792 -Samoa,WSM,2009,560967765.481746 -Samoa,WSM,2010,643056627.690783 -Samoa,WSM,2011,739777274.127838 -Samoa,WSM,2012,801152293.280623 -Samoa,WSM,2013,804816205.686687 -Samoa,WSM,2014,803574789.064072 -Samoa,WSM,2015,803976511.515065 -Samoa,WSM,2016,785916937.388673 -San Marino,SMR,1999,853373879.731819 -San Marino,SMR,2000,773907642.414748 -San Marino,SMR,2001,815205233.062791 -San Marino,SMR,2002,879957209.923907 -San Marino,SMR,2003,1122981525.35502 -San Marino,SMR,2004,1317357834.61634 -San Marino,SMR,2005,1375416604.48689 -San Marino,SMR,2006,1469000145.311 -San Marino,SMR,2007,1687567364.11695 -San Marino,SMR,2008,1899879955.48332 -Sao Tome and Principe,STP,2001,72230284.4325876 -Sao Tome and Principe,STP,2002,80531992.1217606 -Sao Tome and Principe,STP,2003,96343906.4298042 -Sao Tome and Principe,STP,2004,105360801.941831 -Sao Tome and Principe,STP,2005,126194166.230985 -Sao Tome and Principe,STP,2006,134441116.924998 -Sao Tome and Principe,STP,2007,145827429.572302 -Sao Tome and Principe,STP,2008,188021168.8418 -Sao Tome and Principe,STP,2009,187821029.033169 -Sao Tome and Principe,STP,2010,197454053.145088 -Sao Tome and Principe,STP,2011,233213522.645348 -Sao Tome and Principe,STP,2012,252560557.083061 -Sao Tome and Principe,STP,2013,302925489.683914 -Sao Tome and Principe,STP,2014,348463457.918686 -Sao Tome and Principe,STP,2015,317696178.684618 -Sao Tome and Principe,STP,2016,351054248.477335 -Saudi Arabia,SAU,1968,4187777711.11111 -Saudi Arabia,SAU,1969,4485777644.44444 -Saudi Arabia,SAU,1970,5377333333.33333 -Saudi Arabia,SAU,1971,7184853347.5974 -Saudi Arabia,SAU,1972,9664157498.5524 -Saudi Arabia,SAU,1973,14947391140.1284 -Saudi Arabia,SAU,1974,45412957746.4789 -Saudi Arabia,SAU,1975,46773368205.5947 -Saudi Arabia,SAU,1976,64005665722.3796 -Saudi Arabia,SAU,1977,74188249978.724 -Saudi Arabia,SAU,1978,80265619484.6452 -Saudi Arabia,SAU,1979,111859676267.555 -Saudi Arabia,SAU,1980,164541738058.737 -Saudi Arabia,SAU,1981,184291796008.869 -Saudi Arabia,SAU,1982,153239017560.236 -Saudi Arabia,SAU,1983,129171635311.143 -Saudi Arabia,SAU,1984,119624858115.778 -Saudi Arabia,SAU,1985,103897846493.65 -Saudi Arabia,SAU,1986,86961922765.3254 -Saudi Arabia,SAU,1987,85695861148.1976 -Saudi Arabia,SAU,1988,88256074766.3551 -Saudi Arabia,SAU,1989,95344459279.0387 -Saudi Arabia,SAU,1990,117630271802.48 -Saudi Arabia,SAU,1991,132223268484.752 -Saudi Arabia,SAU,1992,137087876662.752 -Saudi Arabia,SAU,1993,132967901424.382 -Saudi Arabia,SAU,1994,135174886501.234 -Saudi Arabia,SAU,1995,143343036351.096 -Saudi Arabia,SAU,1996,158662398750.805 -Saudi Arabia,SAU,1997,165963557420.458 -Saudi Arabia,SAU,1998,146775498092.612 -Saudi Arabia,SAU,1999,161716960000 -Saudi Arabia,SAU,2000,189514926222.667 -Saudi Arabia,SAU,2001,184137469724.863 -Saudi Arabia,SAU,2002,189605920240.516 -Saudi Arabia,SAU,2003,215807655244.424 -Saudi Arabia,SAU,2004,258742133333.333 -Saudi Arabia,SAU,2005,328459608764.111 -Saudi Arabia,SAU,2006,376900133511.348 -Saudi Arabia,SAU,2007,415964509673.115 -Saudi Arabia,SAU,2008,519796800000 -Saudi Arabia,SAU,2009,429097866666.667 -Saudi Arabia,SAU,2010,528207200000 -Saudi Arabia,SAU,2011,671238840108.229 -Saudi Arabia,SAU,2012,735974843348.664 -Saudi Arabia,SAU,2013,746647127407.619 -Saudi Arabia,SAU,2014,756350347320.381 -Saudi Arabia,SAU,2015,654269902888.715 -Saudi Arabia,SAU,2016,646438380568.715 -Senegal,SEN,1960,792824707.345294 -Senegal,SEN,1961,836493109.152284 -Senegal,SEN,1962,857425916.243935 -Senegal,SEN,1963,886387156.125059 -Senegal,SEN,1964,939145851.154484 -Senegal,SEN,1965,955834893.28571 -Senegal,SEN,1966,984942988.068955 -Senegal,SEN,1967,984605369.32995 -Senegal,SEN,1968,1034293645.25718 -Senegal,SEN,1969,983621024.109038 -Senegal,SEN,1970,1024832915.04328 -Senegal,SEN,1971,1058120427.15534 -Senegal,SEN,1972,1280328245.00174 -Senegal,SEN,1973,1471913473.60034 -Senegal,SEN,1974,1658273721.28587 -Senegal,SEN,1975,2235746644.74234 -Senegal,SEN,1976,2266860655.65881 -Senegal,SEN,1977,2320786490.70314 -Senegal,SEN,1978,2591178368.03735 -Senegal,SEN,1979,3226678628.31043 -Senegal,SEN,1980,3503282102.95741 -Senegal,SEN,1981,3176771103.46059 -Senegal,SEN,1982,3109677455.66655 -Senegal,SEN,1983,2774199193.31559 -Senegal,SEN,1984,2705535756.06004 -Senegal,SEN,1985,2962199835.95355 -Senegal,SEN,1986,4189860416.18118 -Senegal,SEN,1987,5040708115.08482 -Senegal,SEN,1988,4985153202.5374 -Senegal,SEN,1989,4913065110.53161 -Senegal,SEN,1990,5716644272.04692 -Senegal,SEN,1991,5617236032.86556 -Senegal,SEN,1992,6004885321.34354 -Senegal,SEN,1993,5678827998.8247 -Senegal,SEN,1994,3877196914.93966 -Senegal,SEN,1995,4878719133.22771 -Senegal,SEN,1996,5065830414.04947 -Senegal,SEN,1997,4672503920.19866 -Senegal,SEN,1998,5030344074.0413 -Senegal,SEN,1999,5144045359.98185 -Senegal,SEN,2000,4679604753.55711 -Senegal,SEN,2001,4877602059.50983 -Senegal,SEN,2002,5333862371.27113 -Senegal,SEN,2003,6858952880.10003 -Senegal,SEN,2004,8031344381.09898 -Senegal,SEN,2005,8707015771.00113 -Senegal,SEN,2006,9358710935.43366 -Senegal,SEN,2007,11284603070.5653 -Senegal,SEN,2008,13428461873.5568 -Senegal,SEN,2009,12809044977.5918 -Senegal,SEN,2010,12937300245.1506 -Senegal,SEN,2011,14368348214.2024 -Senegal,SEN,2012,14202389641.9262 -Senegal,SEN,2013,14810978041.4667 -Senegal,SEN,2014,15308965398.5779 -Senegal,SEN,2015,13609978076.4224 -Senegal,SEN,2016,14765462631.3216 -Serbia,SRB,1995,16750000000 -Serbia,SRB,1996,20948677839.851 -Serbia,SRB,1997,24147996549.5662 -Serbia,SRB,1998,18284194680.3844 -Serbia,SRB,1999,18409364146.9794 -Serbia,SRB,2000,6540247190.33529 -Serbia,SRB,2001,12267175481.2542 -Serbia,SRB,2002,16116843146.4806 -Serbia,SRB,2003,21188704081.2428 -Serbia,SRB,2004,24861483280.6339 -Serbia,SRB,2005,26252007830.4639 -Serbia,SRB,2006,30607991862.4843 -Serbia,SRB,2007,40289556656.1455 -Serbia,SRB,2008,49259526052.7426 -Serbia,SRB,2009,42616653299.9115 -Serbia,SRB,2010,39460357730.5224 -Serbia,SRB,2011,46466728666.6103 -Serbia,SRB,2012,40742313861.1374 -Serbia,SRB,2013,45519650911.4138 -Serbia,SRB,2014,44210806365.6817 -Serbia,SRB,2015,37160332465.1645 -Serbia,SRB,2016,37745114708.3113 -Seychelles,SYC,1960,12012025.2477875 -Seychelles,SYC,1961,11592024.3649978 -Seychelles,SYC,1962,12642026.5719722 -Seychelles,SYC,1963,13923029.264481 -Seychelles,SYC,1964,15393032.3542452 -Seychelles,SYC,1965,15603032.7956401 -Seychelles,SYC,1966,16443034.5612196 -Seychelles,SYC,1967,16632032.8138977 -Seychelles,SYC,1968,16074027.3495878 -Seychelles,SYC,1969,16452027.9927472 -Seychelles,SYC,1970,18432031.3616773 -Seychelles,SYC,1971,21965951.7214804 -Seychelles,SYC,1972,30645121.0127585 -Seychelles,SYC,1973,36896278.223337 -Seychelles,SYC,1974,43134498.6932177 -Seychelles,SYC,1975,47803145.9560303 -Seychelles,SYC,1976,49278979.547035 -Seychelles,SYC,1977,64526398.6582547 -Seychelles,SYC,1978,85552369.9145942 -Seychelles,SYC,1979,127261099.24396 -Seychelles,SYC,1980,147357222.779802 -Seychelles,SYC,1981,154902869.02139 -Seychelles,SYC,1982,147912069.766502 -Seychelles,SYC,1983,146712850.50997 -Seychelles,SYC,1984,151313241.983564 -Seychelles,SYC,1985,168887539.130029 -Seychelles,SYC,1986,207850623.638215 -Seychelles,SYC,1987,249267039.781191 -Seychelles,SYC,1988,283828769.031683 -Seychelles,SYC,1989,304832867.395046 -Seychelles,SYC,1990,368584758.942457 -Seychelles,SYC,1991,374359556.084926 -Seychelles,SYC,1992,433667193.814795 -Seychelles,SYC,1993,473916819.453826 -Seychelles,SYC,1994,486451204.557142 -Seychelles,SYC,1995,508221508.221508 -Seychelles,SYC,1996,503068472.20266 -Seychelles,SYC,1997,562958836.519905 -Seychelles,SYC,1998,608369282.225727 -Seychelles,SYC,1999,622985493.682733 -Seychelles,SYC,2000,614879764.780006 -Seychelles,SYC,2001,622262057.191635 -Seychelles,SYC,2002,697518248.175182 -Seychelles,SYC,2003,705704816.042365 -Seychelles,SYC,2004,839319927.272727 -Seychelles,SYC,2005,919103254.545455 -Seychelles,SYC,2006,1016418229.25159 -Seychelles,SYC,2007,1033561654.0568 -Seychelles,SYC,2008,967199593.960157 -Seychelles,SYC,2009,847397850.094417 -Seychelles,SYC,2010,969936525.298729 -Seychelles,SYC,2011,1065826669.89742 -Seychelles,SYC,2012,1134267367.19206 -Seychelles,SYC,2013,1411061260.70839 -Seychelles,SYC,2014,1422530791.5588 -Seychelles,SYC,2015,1437722206.38754 -Seychelles,SYC,2016,1427323889.0961 -Sierra Leone,SLE,1960,322009471.57364 -Sierra Leone,SLE,1961,327834680.563822 -Sierra Leone,SLE,1962,342721579.824661 -Sierra Leone,SLE,1963,348546952.141512 -Sierra Leone,SLE,1964,371848114.755577 -Sierra Leone,SLE,1965,359379856.248057 -Sierra Leone,SLE,1966,375479849.80806 -Sierra Leone,SLE,1967,348795303.000385 -Sierra Leone,SLE,1968,329860091.944037 -Sierra Leone,SLE,1969,408690163.476065 -Sierra Leone,SLE,1970,434410373.76415 -Sierra Leone,SLE,1971,419549425.077086 -Sierra Leone,SLE,1972,465381089.98454 -Sierra Leone,SLE,1973,575230234.387058 -Sierra Leone,SLE,1974,648590642.939888 -Sierra Leone,SLE,1975,679335901.117451 -Sierra Leone,SLE,1976,594895672.333848 -Sierra Leone,SLE,1977,691777758.395115 -Sierra Leone,SLE,1978,960728338.93643 -Sierra Leone,SLE,1979,1109374722.08294 -Sierra Leone,SLE,1980,1100685844.92284 -Sierra Leone,SLE,1981,1114830471.91787 -Sierra Leone,SLE,1982,1295361885.92419 -Sierra Leone,SLE,1983,995104305.347074 -Sierra Leone,SLE,1984,1087471861.98928 -Sierra Leone,SLE,1985,856890498.625834 -Sierra Leone,SLE,1986,490181456.62441 -Sierra Leone,SLE,1987,701307602.28443 -Sierra Leone,SLE,1988,1055083945.37738 -Sierra Leone,SLE,1989,932974411.917142 -Sierra Leone,SLE,1990,649644826.800447 -Sierra Leone,SLE,1991,779981458.921489 -Sierra Leone,SLE,1992,679997997.597117 -Sierra Leone,SLE,1993,768812334.801762 -Sierra Leone,SLE,1994,911915970.683484 -Sierra Leone,SLE,1995,870758739.40678 -Sierra Leone,SLE,1996,941742152.709895 -Sierra Leone,SLE,1997,850218033.622007 -Sierra Leone,SLE,1998,672375927.347148 -Sierra Leone,SLE,1999,669384768.87263 -Sierra Leone,SLE,2000,635874002.198748 -Sierra Leone,SLE,2001,1079478387.83576 -Sierra Leone,SLE,2002,1239004287.75607 -Sierra Leone,SLE,2003,1371442565.69701 -Sierra Leone,SLE,2004,1431208677.30352 -Sierra Leone,SLE,2005,1627854494.80246 -Sierra Leone,SLE,2006,1885112201.85278 -Sierra Leone,SLE,2007,2158496872.85796 -Sierra Leone,SLE,2008,2505458705.03338 -Sierra Leone,SLE,2009,2489985963.16808 -Sierra Leone,SLE,2010,2616610911.07222 -Sierra Leone,SLE,2011,2942546781.04548 -Sierra Leone,SLE,2012,3801862611.36414 -Sierra Leone,SLE,2013,4920343194.99339 -Sierra Leone,SLE,2014,5015157815.73406 -Sierra Leone,SLE,2015,4251779857.0134 -Sierra Leone,SLE,2016,3668876080.33846 -Singapore,SGP,1960,704462302.365086 -Singapore,SGP,1961,764308114.464916 -Singapore,SGP,1962,825885273.748857 -Singapore,SGP,1963,917222004.442702 -Singapore,SGP,1964,893734483.209199 -Singapore,SGP,1965,974193126.878348 -Singapore,SGP,1966,1095910100.61414 -Singapore,SGP,1967,1237423232.7192 -Singapore,SGP,1968,1425029400.2352 -Singapore,SGP,1969,1659055272.44218 -Singapore,SGP,1970,1919508689.40285 -Singapore,SGP,1971,2262544100.3528 -Singapore,SGP,1972,2719900350.73917 -Singapore,SGP,1973,3693760000 -Singapore,SGP,1974,5216773825.99496 -Singapore,SGP,1975,5633386679.7981 -Singapore,SGP,1976,6326445409.69089 -Singapore,SGP,1977,6617532782.90432 -Singapore,SGP,1978,7515823563.17127 -Singapore,SGP,1979,9294635004.39754 -Singapore,SGP,1980,11893405683.8039 -Singapore,SGP,1981,14171819540.4446 -Singapore,SGP,1982,16078856439.627 -Singapore,SGP,1983,17775280373.8318 -Singapore,SGP,1984,19735920492.1912 -Singapore,SGP,1985,19138296376.1661 -Singapore,SGP,1986,18569292304.8952 -Singapore,SGP,1987,20897630201.1573 -Singapore,SGP,1988,25337226970.5603 -Singapore,SGP,1989,30423573842.1785 -Singapore,SGP,1990,36152027893.1446 -Singapore,SGP,1991,45474442836.4689 -Singapore,SGP,1992,52156414978.5144 -Singapore,SGP,1993,60644572348.0629 -Singapore,SGP,1994,73777792326.8299 -Singapore,SGP,1995,87890009877.24 -Singapore,SGP,1996,96403758865.2482 -Singapore,SGP,1997,100163995150.862 -Singapore,SGP,1998,85707636233.2696 -Singapore,SGP,1999,86283126843.6578 -Singapore,SGP,2000,95833932714.6172 -Singapore,SGP,2001,89286208628.6767 -Singapore,SGP,2002,91941192896.2359 -Singapore,SGP,2003,97001377568.5914 -Singapore,SGP,2004,114188557567.152 -Singapore,SGP,2005,127417688055.756 -Singapore,SGP,2006,147797218201.271 -Singapore,SGP,2007,179981288567.447 -Singapore,SGP,2008,192225881687.752 -Singapore,SGP,2009,192408387762.118 -Singapore,SGP,2010,236421782178.218 -Singapore,SGP,2011,275599459373.509 -Singapore,SGP,2012,289162118908.538 -Singapore,SGP,2013,302510668904.339 -Singapore,SGP,2014,308142766948.149 -Singapore,SGP,2015,296840704102.415 -Singapore,SGP,2016,296965712342.019 -Slovak Republic,SVK,1990,12694544692.7374 -Slovak Republic,SVK,1991,14213045493.8806 -Slovak Republic,SVK,1992,15431288006.2104 -Slovak Republic,SVK,1993,16452201100.9604 -Slovak Republic,SVK,1994,20079363625.5784 -Slovak Republic,SVK,1995,25733043137.2549 -Slovak Republic,SVK,1996,27821913814.9556 -Slovak Republic,SVK,1997,27660149541.1805 -Slovak Republic,SVK,1998,29828899205.7277 -Slovak Republic,SVK,1999,30415095887.492 -Slovak Republic,SVK,2000,29114875621.8905 -Slovak Republic,SVK,2001,30703017449.6644 -Slovak Republic,SVK,2002,35083608130.9994 -Slovak Republic,SVK,2003,46731767494.3567 -Slovak Republic,SVK,2004,57240535137.8197 -Slovak Republic,SVK,2005,62697540106.9519 -Slovak Republic,SVK,2006,70596729394.0534 -Slovak Republic,SVK,2007,86304245825.349 -Slovak Republic,SVK,2008,100324627215.468 -Slovak Republic,SVK,2009,88945625173.6593 -Slovak Republic,SVK,2010,89501012915.7314 -Slovak Republic,SVK,2011,98181259740.0919 -Slovak Republic,SVK,2012,93413992955.8972 -Slovak Republic,SVK,2013,98478349315.3252 -Slovak Republic,SVK,2014,100760596988.198 -Slovak Republic,SVK,2015,87267593788.1986 -Slovak Republic,SVK,2016,89551834322.5767 -Slovenia,SVN,1995,21273055398.3017 -Slovenia,SVN,1996,21480023016.9972 -Slovenia,SVN,1997,20749140606.2425 -Slovenia,SVN,1998,22125435372.187 -Slovenia,SVN,1999,22689994990.1121 -Slovenia,SVN,2000,20342201356.0052 -Slovenia,SVN,2001,20875387068.1145 -Slovenia,SVN,2002,23563576758.1047 -Slovenia,SVN,2003,29697448108.2957 -Slovenia,SVN,2004,34470227453.9113 -Slovenia,SVN,2005,36346974008.2079 -Slovenia,SVN,2006,39587732028.6037 -Slovenia,SVN,2007,48114688201.4782 -Slovenia,SVN,2008,55589849128.4605 -Slovenia,SVN,2009,50244793831.6199 -Slovenia,SVN,2010,48013606745.4803 -Slovenia,SVN,2011,51290792018.1074 -Slovenia,SVN,2012,46258247574.7506 -Slovenia,SVN,2013,47688566993.1107 -Slovenia,SVN,2014,49530147015.8794 -Slovenia,SVN,2015,42776716631.0769 -Slovenia,SVN,2016,43990635176.0523 -Solomon Islands,SLB,1967,25203524.0325638 -Solomon Islands,SLB,1968,28084252.7582748 -Solomon Islands,SLB,1969,28606411.398041 -Solomon Islands,SLB,1971,50056882.8213879 -Solomon Islands,SLB,1972,40606712.050639 -Solomon Islands,SLB,1973,55272108.8435374 -Solomon Islands,SLB,1974,84539332.282562 -Solomon Islands,SLB,1975,74617096.4785967 -Solomon Islands,SLB,1976,83099107.9066357 -Solomon Islands,SLB,1977,93147039.2548237 -Solomon Islands,SLB,1978,111022089.96223 -Solomon Islands,SLB,1979,151270207.852194 -Solomon Islands,SLB,1980,168715353.097132 -Solomon Islands,SLB,1981,187313261.319237 -Solomon Islands,SLB,1982,188446092.06055 -Solomon Islands,SLB,1983,180219397.527425 -Solomon Islands,SLB,1984,252806783.386983 -Solomon Islands,SLB,1985,232306861.156132 -Solomon Islands,SLB,1986,210737869.652598 -Solomon Islands,SLB,1987,238606299.605651 -Solomon Islands,SLB,1988,310684273.709484 -Solomon Islands,SLB,1989,332286760.858189 -Solomon Islands,SLB,1990,302515026.890225 -Solomon Islands,SLB,1991,320355090.61441 -Solomon Islands,SLB,1992,378778047.197842 -Solomon Islands,SLB,1993,410923236.189102 -Solomon Islands,SLB,1994,464756638.512487 -Solomon Islands,SLB,1995,519334096.714525 -Solomon Islands,SLB,1996,565163750.56079 -Solomon Islands,SLB,1997,567919502.811483 -Solomon Islands,SLB,1998,471177008.057148 -Solomon Islands,SLB,1999,482214092.308964 -Solomon Islands,SLB,2000,435103853.485036 -Solomon Islands,SLB,2001,400463452.065176 -Solomon Islands,SLB,2002,341661643.551446 -Solomon Islands,SLB,2003,332738245.913215 -Solomon Islands,SLB,2004,375111894.932329 -Solomon Islands,SLB,2005,413909879.281265 -Solomon Islands,SLB,2006,456705433.996978 -Solomon Islands,SLB,2007,516074228.959749 -Solomon Islands,SLB,2008,608293860.271816 -Solomon Islands,SLB,2009,597765363.128492 -Solomon Islands,SLB,2010,671585343.170686 -Solomon Islands,SLB,2011,886498370.696086 -Solomon Islands,SLB,2012,1025125081.57494 -Solomon Islands,SLB,2013,1059695156.18795 -Solomon Islands,SLB,2014,1156563122.85602 -Solomon Islands,SLB,2015,1129164718.81436 -Solomon Islands,SLB,2016,1202125000 -Somalia,SOM,2013,5352000000 -Somalia,SOM,2014,5647000000 -Somalia,SOM,2015,5925000000 -Somalia,SOM,2016,6217000000 -South Africa,ZAF,1960,7575248495.0301 -South Africa,ZAF,1961,7972840543.18914 -South Africa,ZAF,1962,8497830043.39913 -South Africa,ZAF,1963,9423211535.76928 -South Africa,ZAF,1964,10373792524.1495 -South Africa,ZAF,1965,11334173316.5337 -South Africa,ZAF,1966,12354752904.9419 -South Africa,ZAF,1967,13777124457.5108 -South Africa,ZAF,1968,14894302113.9577 -South Africa,ZAF,1969,16780064398.712 -South Africa,ZAF,1970,18418031639.3672 -South Africa,ZAF,1971,20334172259.5078 -South Africa,ZAF,1972,21358137114.6091 -South Africa,ZAF,1973,29293948126.8012 -South Africa,ZAF,1974,36806475349.5217 -South Africa,ZAF,1975,38114942528.7356 -South Africa,ZAF,1976,36601885924.563 -South Africa,ZAF,1977,40649724011.0396 -South Africa,ZAF,1978,46737580496.7801 -South Africa,ZAF,1979,57647268408.5511 -South Africa,ZAF,1980,82984078068.8238 -South Africa,ZAF,1981,89629496832.7955 -South Africa,ZAF,1982,82696902010.2943 -South Africa,ZAF,1983,88786580362.8407 -South Africa,ZAF,1984,87880468268.6383 -South Africa,ZAF,1985,69208451592.5576 -South Africa,ZAF,1986,82107924006.1732 -South Africa,ZAF,1987,107414974090.178 -South Africa,ZAF,1988,118331510445.149 -South Africa,ZAF,1989,128902675070.723 -South Africa,ZAF,1990,115553279480.54 -South Africa,ZAF,1991,123943432441.241 -South Africa,ZAF,1992,134545231416.55 -South Africa,ZAF,1993,134309759157.817 -South Africa,ZAF,1994,139752450152.078 -South Africa,ZAF,1995,155460285076.232 -South Africa,ZAF,1996,147607982694.857 -South Africa,ZAF,1997,152586154513.889 -South Africa,ZAF,1998,137774361015.14 -South Africa,ZAF,1999,136631966609.379 -South Africa,ZAF,2000,136361854808.496 -South Africa,ZAF,2001,121516070204.783 -South Africa,ZAF,2002,115482368343.658 -South Africa,ZAF,2003,175256916996.047 -South Africa,ZAF,2004,228593566165.088 -South Africa,ZAF,2005,257772710832.953 -South Africa,ZAF,2006,271638484826.109 -South Africa,ZAF,2007,299415505152.298 -South Africa,ZAF,2008,286769839732.726 -South Africa,ZAF,2009,295936485832.635 -South Africa,ZAF,2010,375349396273.835 -South Africa,ZAF,2011,416418862155.872 -South Africa,ZAF,2012,396327771010.962 -South Africa,ZAF,2013,366623856821.783 -South Africa,ZAF,2014,350850571747.123 -South Africa,ZAF,2015,317406594612.388 -South Africa,ZAF,2016,294840648284.114 -South Sudan,SSD,2008,15550136278.8696 -South Sudan,SSD,2009,12231362022.6859 -South Sudan,SSD,2010,15727363443.0995 -South Sudan,SSD,2011,17826697892.2717 -South Sudan,SSD,2012,10368813559.322 -South Sudan,SSD,2013,13257635694.9153 -South Sudan,SSD,2014,13282084033.8983 -South Sudan,SSD,2015,9015221096.24474 -Spain,ESP,1960,12072126075.397 -Spain,ESP,1961,13834300571.4849 -Spain,ESP,1962,16138545209.246 -Spain,ESP,1963,19074913947.7196 -Spain,ESP,1964,21343844643.7341 -Spain,ESP,1965,24756958694.9238 -Spain,ESP,1966,28721062242.1634 -Spain,ESP,1967,31647119228.1982 -Spain,ESP,1968,31475548481.4095 -Spain,ESP,1969,36038711599.541 -Spain,ESP,1970,40881655098.6451 -Spain,ESP,1971,46492797365.2695 -Spain,ESP,1972,58971806626.9739 -Spain,ESP,1973,78425934894.3461 -Spain,ESP,1974,97009800115.3735 -Spain,ESP,1975,114465300289.855 -Spain,ESP,1976,118185307386.222 -Spain,ESP,1977,132089531434.83 -Spain,ESP,1978,160163483072.917 -Spain,ESP,1979,214019077342.588 -Spain,ESP,1980,232134606637.271 -Spain,ESP,1981,202257045774.013 -Spain,ESP,1982,195464408602.151 -Spain,ESP,1983,170486866357.309 -Spain,ESP,1984,171635463361.623 -Spain,ESP,1985,180302412230.92 -Spain,ESP,1986,250638463466.793 -Spain,ESP,1987,317882187036.787 -Spain,ESP,1988,375138723325.239 -Spain,ESP,1989,413630538018.271 -Spain,ESP,1990,535101248775.71 -Spain,ESP,1991,575598537069.656 -Spain,ESP,1992,629202392003.901 -Spain,ESP,1993,523649481762.322 -Spain,ESP,1994,529121577319.588 -Spain,ESP,1995,612939685081.398 -Spain,ESP,1996,640998292394.588 -Spain,ESP,1997,588692045454.545 -Spain,ESP,1998,617041986858.225 -Spain,ESP,1999,633194118900.49 -Spain,ESP,2000,595402616546.895 -Spain,ESP,2001,625975838926.175 -Spain,ESP,2002,705145868624.13 -Spain,ESP,2003,906853273137.698 -Spain,ESP,2004,1069555500372.49 -Spain,ESP,2005,1157276458151.97 -Spain,ESP,2006,1264551499184.54 -Spain,ESP,2007,1479341637010.68 -Spain,ESP,2008,1634989014208.29 -Spain,ESP,2009,1499074742984.16 -Spain,ESP,2010,1431587612302.26 -Spain,ESP,2011,1488017213511.01 -Spain,ESP,2012,1335945712662.3 -Spain,ESP,2013,1361775869855.87 -Spain,ESP,2014,1375856057716.82 -Spain,ESP,2015,1192955480686.43 -Spain,ESP,2016,1232088185030.31 -Sri Lanka,LKA,1960,1409873949.57983 -Sri Lanka,LKA,1961,1444327731.09244 -Sri Lanka,LKA,1962,1434156378.60082 -Sri Lanka,LKA,1963,1240672268.90756 -Sri Lanka,LKA,1964,1309747899.15966 -Sri Lanka,LKA,1965,1698319327.73109 -Sri Lanka,LKA,1966,1751470588.23529 -Sri Lanka,LKA,1967,1859465020.57613 -Sri Lanka,LKA,1968,1801344537.81513 -Sri Lanka,LKA,1969,1965546218.48739 -Sri Lanka,LKA,1970,2296470588.23529 -Sri Lanka,LKA,1971,2369308600.33727 -Sri Lanka,LKA,1972,2553936348.40871 -Sri Lanka,LKA,1973,2875625000 -Sri Lanka,LKA,1974,3574586466.16541 -Sri Lanka,LKA,1975,3791298145.50642 -Sri Lanka,LKA,1976,3591319857.31272 -Sri Lanka,LKA,1977,4104509582.86359 -Sri Lanka,LKA,1978,2733183856.50224 -Sri Lanka,LKA,1979,3364611432.24149 -Sri Lanka,LKA,1980,4024621899.57653 -Sri Lanka,LKA,1981,4415844155.84416 -Sri Lanka,LKA,1982,4768765016.81884 -Sri Lanka,LKA,1983,5167913302.16745 -Sri Lanka,LKA,1984,6043474842.76729 -Sri Lanka,LKA,1985,5978460972.01767 -Sri Lanka,LKA,1986,6405210563.88294 -Sri Lanka,LKA,1987,6682167119.56522 -Sri Lanka,LKA,1988,6978371581.26375 -Sri Lanka,LKA,1989,6987267683.77254 -Sri Lanka,LKA,1990,8032551173.24014 -Sri Lanka,LKA,1991,9000362581.58086 -Sri Lanka,LKA,1992,9703011635.86585 -Sri Lanka,LKA,1993,10338679635.7616 -Sri Lanka,LKA,1994,11717604208.8223 -Sri Lanka,LKA,1995,13029697560.9756 -Sri Lanka,LKA,1996,13897738375.2488 -Sri Lanka,LKA,1997,15091913883.7091 -Sri Lanka,LKA,1998,15794972847.1683 -Sri Lanka,LKA,1999,15656327859.5696 -Sri Lanka,LKA,2000,16330814179.9766 -Sri Lanka,LKA,2001,15746229581.5619 -Sri Lanka,LKA,2002,16536535647.0834 -Sri Lanka,LKA,2003,18881765437.2151 -Sri Lanka,LKA,2004,20662525941.2986 -Sri Lanka,LKA,2005,24406252456.5141 -Sri Lanka,LKA,2006,28279814924.5918 -Sri Lanka,LKA,2007,32350248410.8216 -Sri Lanka,LKA,2008,40713812309.7316 -Sri Lanka,LKA,2009,42066217871.5349 -Sri Lanka,LKA,2010,56725745039.336 -Sri Lanka,LKA,2011,65292741296.5382 -Sri Lanka,LKA,2012,68434399083.41 -Sri Lanka,LKA,2013,74317806754.5267 -Sri Lanka,LKA,2014,79356456990.2891 -Sri Lanka,LKA,2015,80611989527.2158 -Sri Lanka,LKA,2016,81321876307.2556 -St. Kitts and Nevis,KNA,1960,12366563.6119699 -St. Kitts and Nevis,KNA,1961,12483229.3064224 -St. Kitts and Nevis,KNA,1962,12541562.1536487 -St. Kitts and Nevis,KNA,1963,12833226.3897801 -St. Kitts and Nevis,KNA,1964,13416554.8620428 -St. Kitts and Nevis,KNA,1965,13593932.3220537 -St. Kitts and Nevis,KNA,1966,14469078.1796966 -St. Kitts and Nevis,KNA,1967,16742338.2519864 -St. Kitts and Nevis,KNA,1968,14600000 -St. Kitts and Nevis,KNA,1969,15850000 -St. Kitts and Nevis,KNA,1970,16300000 -St. Kitts and Nevis,KNA,1971,19624746.4503043 -St. Kitts and Nevis,KNA,1972,22944849.1155047 -St. Kitts and Nevis,KNA,1973,24196018.3767228 -St. Kitts and Nevis,KNA,1974,31514856.3078422 -St. Kitts and Nevis,KNA,1975,33364055.2995392 -St. Kitts and Nevis,KNA,1976,30095602.2944551 -St. Kitts and Nevis,KNA,1977,44680000 -St. Kitts and Nevis,KNA,1978,49095407.4074074 -St. Kitts and Nevis,KNA,1979,58296666.6666667 -St. Kitts and Nevis,KNA,1980,67715444.4444444 -St. Kitts and Nevis,KNA,1981,79026037.037037 -St. Kitts and Nevis,KNA,1982,84381407.4074074 -St. Kitts and Nevis,KNA,1983,85100481.4814815 -St. Kitts and Nevis,KNA,1984,95898444.4444444 -St. Kitts and Nevis,KNA,1985,106057000 -St. Kitts and Nevis,KNA,1986,125272259.259259 -St. Kitts and Nevis,KNA,1987,140705629.62963 -St. Kitts and Nevis,KNA,1988,165745740.740741 -St. Kitts and Nevis,KNA,1989,185094777.777778 -St. Kitts and Nevis,KNA,1990,208740444.444444 -St. Kitts and Nevis,KNA,1991,209880962.962963 -St. Kitts and Nevis,KNA,1992,229434518.518519 -St. Kitts and Nevis,KNA,1993,249676000 -St. Kitts and Nevis,KNA,1994,277567259.259259 -St. Kitts and Nevis,KNA,1995,299699666.666667 -St. Kitts and Nevis,KNA,1996,318742962.962963 -St. Kitts and Nevis,KNA,1997,357237682.126571 -St. Kitts and Nevis,KNA,1998,364975456.93842 -St. Kitts and Nevis,KNA,1999,389984428.873318 -St. Kitts and Nevis,KNA,2000,420515112.890668 -St. Kitts and Nevis,KNA,2001,461078096.244393 -St. Kitts and Nevis,KNA,2002,483120201.312424 -St. Kitts and Nevis,KNA,2003,465850733.325919 -St. Kitts and Nevis,KNA,2004,502561637.037037 -St. Kitts and Nevis,KNA,2005,543167674.444444 -St. Kitts and Nevis,KNA,2006,636218025.185185 -St. Kitts and Nevis,KNA,2007,674008481.481481 -St. Kitts and Nevis,KNA,2008,738942555.555555 -St. Kitts and Nevis,KNA,2009,723209111.111111 -St. Kitts and Nevis,KNA,2010,705015370.37037 -St. Kitts and Nevis,KNA,2011,753225962.962963 -St. Kitts and Nevis,KNA,2012,734462666.666667 -St. Kitts and Nevis,KNA,2013,788163888.888889 -St. Kitts and Nevis,KNA,2014,847778185.185185 -St. Kitts and Nevis,KNA,2015,876478555.555555 -St. Kitts and Nevis,KNA,2016,916896555.555555 -St. Lucia,LCA,1977,87350296.2962963 -St. Lucia,LCA,1978,102094111.111111 -St. Lucia,LCA,1979,123935518.518519 -St. Lucia,LCA,1980,146341370.37037 -St. Lucia,LCA,1981,167970111.111111 -St. Lucia,LCA,1982,182754000 -St. Lucia,LCA,1983,197228777.777778 -St. Lucia,LCA,1984,217663037.037037 -St. Lucia,LCA,1985,241273000 -St. Lucia,LCA,1986,289689703.703704 -St. Lucia,LCA,1987,319999000 -St. Lucia,LCA,1988,366541074.074074 -St. Lucia,LCA,1989,415518111.111111 -St. Lucia,LCA,1990,483962444.444444 -St. Lucia,LCA,1991,513753814.814815 -St. Lucia,LCA,1992,566894740.740741 -St. Lucia,LCA,1993,574870407.407407 -St. Lucia,LCA,1994,600005555.555556 -St. Lucia,LCA,1995,640449518.518518 -St. Lucia,LCA,1996,662196185.185185 -St. Lucia,LCA,1997,676949592.592593 -St. Lucia,LCA,1998,737554888.888889 -St. Lucia,LCA,1999,775934814.814815 -St. Lucia,LCA,2000,784159222.222222 -St. Lucia,LCA,2001,743808074.074074 -St. Lucia,LCA,2002,748346592.592593 -St. Lucia,LCA,2003,823837148.148148 -St. Lucia,LCA,2004,893107222.222222 -St. Lucia,LCA,2005,951207370.37037 -St. Lucia,LCA,2006,1062617148.14815 -St. Lucia,LCA,2007,1150526259.25926 -St. Lucia,LCA,2008,1187075814.81481 -St. Lucia,LCA,2009,1180949888.88889 -St. Lucia,LCA,2010,1241892814.81481 -St. Lucia,LCA,2011,1280623888.88889 -St. Lucia,LCA,2012,1298815407.40741 -St. Lucia,LCA,2013,1318052185.18519 -St. Lucia,LCA,2014,1386188629.62963 -St. Lucia,LCA,2015,1431135703.7037 -St. Lucia,LCA,2016,1378627407.40741 -St. Vincent and the Grenadines,VCT,1960,13066557.7786852 -St. Vincent and the Grenadines,VCT,1961,13999883.3343055 -St. Vincent and the Grenadines,VCT,1962,14524878.959342 -St. Vincent and the Grenadines,VCT,1963,13708219.0981742 -St. Vincent and the Grenadines,VCT,1964,14758210.3482471 -St. Vincent and the Grenadines,VCT,1965,15108207.4316047 -St. Vincent and the Grenadines,VCT,1966,16099865.8344514 -St. Vincent and the Grenadines,VCT,1967,15835177.9329133 -St. Vincent and the Grenadines,VCT,1968,15350000 -St. Vincent and the Grenadines,VCT,1969,16650000 -St. Vincent and the Grenadines,VCT,1970,18450000 -St. Vincent and the Grenadines,VCT,1971,20051648.1847182 -St. Vincent and the Grenadines,VCT,1972,27585488.9918284 -St. Vincent and the Grenadines,VCT,1973,30165373.6218865 -St. Vincent and the Grenadines,VCT,1974,32924215.8581726 -St. Vincent and the Grenadines,VCT,1975,33237164.715642 -St. Vincent and the Grenadines,VCT,1976,32792480.9729606 -St. Vincent and the Grenadines,VCT,1977,49353148.1481481 -St. Vincent and the Grenadines,VCT,1978,60844777.7777778 -St. Vincent and the Grenadines,VCT,1979,71096370.3703704 -St. Vincent and the Grenadines,VCT,1980,82340333.3333333 -St. Vincent and the Grenadines,VCT,1981,102086555.555556 -St. Vincent and the Grenadines,VCT,1982,113759185.185185 -St. Vincent and the Grenadines,VCT,1983,122255333.333333 -St. Vincent and the Grenadines,VCT,1984,135025000 -St. Vincent and the Grenadines,VCT,1985,145641703.703704 -St. Vincent and the Grenadines,VCT,1986,160846666.666667 -St. Vincent and the Grenadines,VCT,1987,175580629.62963 -St. Vincent and the Grenadines,VCT,1988,200726703.703704 -St. Vincent and the Grenadines,VCT,1989,214745000 -St. Vincent and the Grenadines,VCT,1990,240365259.259259 -St. Vincent and the Grenadines,VCT,1991,254829629.62963 -St. Vincent and the Grenadines,VCT,1992,277954111.111111 -St. Vincent and the Grenadines,VCT,1993,286307814.814815 -St. Vincent and the Grenadines,VCT,1994,289438481.481481 -St. Vincent and the Grenadines,VCT,1995,316008481.481481 -St. Vincent and the Grenadines,VCT,1996,331489703.703704 -St. Vincent and the Grenadines,VCT,1997,347770000 -St. Vincent and the Grenadines,VCT,1998,373619851.851852 -St. Vincent and the Grenadines,VCT,1999,390719148.148148 -St. Vincent and the Grenadines,VCT,2000,396270000 -St. Vincent and the Grenadines,VCT,2001,430040370.37037 -St. Vincent and the Grenadines,VCT,2002,461883444.444444 -St. Vincent and the Grenadines,VCT,2003,481806296.296296 -St. Vincent and the Grenadines,VCT,2004,521975111.111111 -St. Vincent and the Grenadines,VCT,2005,550728666.666667 -St. Vincent and the Grenadines,VCT,2006,610930044.444444 -St. Vincent and the Grenadines,VCT,2007,651833314.814815 -St. Vincent and the Grenadines,VCT,2008,695428851.851852 -St. Vincent and the Grenadines,VCT,2009,674922481.481482 -St. Vincent and the Grenadines,VCT,2010,681225962.962963 -St. Vincent and the Grenadines,VCT,2011,676129407.407407 -St. Vincent and the Grenadines,VCT,2012,692933740.740741 -St. Vincent and the Grenadines,VCT,2013,721207148.148148 -St. Vincent and the Grenadines,VCT,2014,727912814.814815 -St. Vincent and the Grenadines,VCT,2015,737683555.555555 -St. Vincent and the Grenadines,VCT,2016,770796555.555556 -Sudan,SDN,1960,1307333333.33333 -Sudan,SDN,1961,1419333333.33333 -Sudan,SDN,1962,1541666666.66667 -Sudan,SDN,1963,1568333333.33333 -Sudan,SDN,1964,1611333333.33333 -Sudan,SDN,1965,1679333333.33333 -Sudan,SDN,1966,1723000000 -Sudan,SDN,1967,1865666666.66667 -Sudan,SDN,1968,1947333333.33333 -Sudan,SDN,1969,2144333333.33333 -Sudan,SDN,1970,2437666666.66667 -Sudan,SDN,1971,2656000000 -Sudan,SDN,1972,2882000000 -Sudan,SDN,1973,3571666666.66667 -Sudan,SDN,1974,4595000000 -Sudan,SDN,1975,5598000000 -Sudan,SDN,1976,6979333333.33333 -Sudan,SDN,1977,8704000000 -Sudan,SDN,1978,7670500000 -Sudan,SDN,1979,9032250000 -Sudan,SDN,1980,7459833333.33333 -Sudan,SDN,1981,10016500000 -Sudan,SDN,1982,9240000000 -Sudan,SDN,1983,8230153846.15384 -Sudan,SDN,1984,9701357142.85714 -Sudan,SDN,1985,12403733333.3333 -Sudan,SDN,1986,15769062500 -Sudan,SDN,1987,20155555555.5556 -Sudan,SDN,1988,15399166666.6667 -Sudan,SDN,1989,15291507936.5079 -Sudan,SDN,1990,12408647540.9836 -Sudan,SDN,1991,11379222222.2222 -Sudan,SDN,1992,7034219712.52567 -Sudan,SDN,1993,8881785938.48085 -Sudan,SDN,1994,12794192334.2541 -Sudan,SDN,1995,13829744878.6366 -Sudan,SDN,1996,9018243044.45155 -Sudan,SDN,1997,11681494637.3041 -Sudan,SDN,1998,11250327988.0478 -Sudan,SDN,1999,10682045258.3647 -Sudan,SDN,2000,12257418326.0734 -Sudan,SDN,2001,13182979783.533 -Sudan,SDN,2002,14803189092.7044 -Sudan,SDN,2003,17646503525.1743 -Sudan,SDN,2004,21457470202.7839 -Sudan,SDN,2005,26524538565.7403 -Sudan,SDN,2006,35822408611.5588 -Sudan,SDN,2007,45898948564.0593 -Sudan,SDN,2008,54526580231.5568 -Sudan,SDN,2009,53150209167.934 -Sudan,SDN,2010,65634109236.7736 -Sudan,SDN,2011,67327289319.733 -Sudan,SDN,2012,68125631150.2939 -Sudan,SDN,2013,72065940085.772 -Sudan,SDN,2014,82151588418.8325 -Sudan,SDN,2015,97156119150 -Sudan,SDN,2016,95584380032.2061 -Suriname,SUR,1960,93850000 -Suriname,SUR,1961,98400000 -Suriname,SUR,1962,103500000 -Suriname,SUR,1963,110000000 -Suriname,SUR,1964,120850000 -Suriname,SUR,1965,138650000 -Suriname,SUR,1966,171100000 -Suriname,SUR,1967,198450000 -Suriname,SUR,1968,220600000 -Suriname,SUR,1969,233450000 -Suriname,SUR,1970,247150000 -Suriname,SUR,1971,270650000 -Suriname,SUR,1972,287600000 -Suriname,SUR,1973,305300000 -Suriname,SUR,1974,368600000 -Suriname,SUR,1975,465000000 -Suriname,SUR,1976,505500000 -Suriname,SUR,1977,641000000 -Suriname,SUR,1978,735500000 -Suriname,SUR,1979,783000000 -Suriname,SUR,1980,794900000 -Suriname,SUR,1981,889050000 -Suriname,SUR,1982,915150000 -Suriname,SUR,1983,883600000 -Suriname,SUR,1984,864150000 -Suriname,SUR,1985,873250000 -Suriname,SUR,1986,891000000 -Suriname,SUR,1987,979850000 -Suriname,SUR,1988,1160900000 -Suriname,SUR,1989,542520000 -Suriname,SUR,1990,388300000 -Suriname,SUR,1991,448300000 -Suriname,SUR,1992,404600000 -Suriname,SUR,1993,428794117.647059 -Suriname,SUR,1994,605492537.313433 -Suriname,SUR,1995,693970588.235294 -Suriname,SUR,1996,860630922.693267 -Suriname,SUR,1997,929607500 -Suriname,SUR,1998,945000000 -Suriname,SUR,1999,885444186.046512 -Suriname,SUR,2000,892164393.939394 -Suriname,SUR,2001,763465550.458716 -Suriname,SUR,2002,1078402127.65957 -Suriname,SUR,2003,1271196078.43137 -Suriname,SUR,2004,1484092538.40527 -Suriname,SUR,2005,1793754804.70037 -Suriname,SUR,2006,2626380435.17877 -Suriname,SUR,2007,2936612021.85792 -Suriname,SUR,2008,3532969034.60838 -Suriname,SUR,2009,3875409836.06557 -Suriname,SUR,2010,4368398047.64333 -Suriname,SUR,2011,4422276621.78703 -Suriname,SUR,2012,4980000000 -Suriname,SUR,2013,5145757575.75758 -Suriname,SUR,2014,5240606060.60606 -Suriname,SUR,2015,4878731707.26948 -Suriname,SUR,2016,3620699735.1962 -Swaziland,SWZ,1960,35076158.4768305 -Swaziland,SWZ,1961,43025199.4960101 -Swaziland,SWZ,1962,45927061.4587708 -Swaziland,SWZ,1963,54128377.4324513 -Swaziland,SWZ,1964,64979280.4143917 -Swaziland,SWZ,1965,70278594.4281114 -Swaziland,SWZ,1966,76858462.8307434 -Swaziland,SWZ,1967,74758504.8299034 -Swaziland,SWZ,1968,79798404.0319194 -Swaziland,SWZ,1969,105417891.642167 -Swaziland,SWZ,1970,112137757.244855 -Swaziland,SWZ,1971,136465324.384787 -Swaziland,SWZ,1972,146741251.46351 -Swaziland,SWZ,1973,221902017.291066 -Swaziland,SWZ,1974,264311994.113319 -Swaziland,SWZ,1975,288302907.369844 -Swaziland,SWZ,1976,272539098.436063 -Swaziland,SWZ,1977,304047838.086477 -Swaziland,SWZ,1978,340616375.344986 -Swaziland,SWZ,1979,412093133.760988 -Swaziland,SWZ,1980,542000513.610683 -Swaziland,SWZ,1981,571542674.577818 -Swaziland,SWZ,1982,537575980.843618 -Swaziland,SWZ,1983,555336145.767884 -Swaziland,SWZ,1984,494475699.857656 -Swaziland,SWZ,1985,361014890.45841 -Swaziland,SWZ,1986,449146608.315098 -Swaziland,SWZ,1987,584135559.921414 -Swaziland,SWZ,1988,692016714.317132 -Swaziland,SWZ,1989,696915430.663057 -Swaziland,SWZ,1990,1114703088.1614 -Swaziland,SWZ,1991,1156141998.33412 -Swaziland,SWZ,1992,1284766234.2216 -Swaziland,SWZ,1993,1357206995.74624 -Swaziland,SWZ,1994,1419293454.99606 -Swaziland,SWZ,1995,1698982437.76019 -Swaziland,SWZ,1996,1602760100.48147 -Swaziland,SWZ,1997,1716699913.19444 -Swaziland,SWZ,1998,1576904292.4588 -Swaziland,SWZ,1999,1547884442.26205 -Swaziland,SWZ,2000,1738100848.09721 -Swaziland,SWZ,2001,1542477354.99355 -Swaziland,SWZ,2002,1432228172.702 -Swaziland,SWZ,2003,2197612760.58535 -Swaziland,SWZ,2004,2770082815.20915 -Swaziland,SWZ,2005,3178126547.9298 -Swaziland,SWZ,2006,3291353812.85535 -Swaziland,SWZ,2007,3469363931.16431 -Swaziland,SWZ,2008,3294093359.62088 -Swaziland,SWZ,2009,3580417156.54024 -Swaziland,SWZ,2010,4438778553.63533 -Swaziland,SWZ,2011,4820499498.18209 -Swaziland,SWZ,2012,4807282468.0268 -Swaziland,SWZ,2013,4575596300.78922 -Swaziland,SWZ,2014,4486261555.30421 -Swaziland,SWZ,2015,4137638726.69274 -Swaziland,SWZ,2016,3727303664.17403 -Sweden,SWE,1960,14842870293.4207 -Sweden,SWE,1961,16147160122.7882 -Sweden,SWE,1962,17511477311.4463 -Sweden,SWE,1963,18954132365.5148 -Sweden,SWE,1964,21137242560.8543 -Sweden,SWE,1965,23260320646.2745 -Sweden,SWE,1966,25302033132.3312 -Sweden,SWE,1967,27463409201.8822 -Sweden,SWE,1968,29143383490.5896 -Sweden,SWE,1969,31649203885.888 -Sweden,SWE,1970,37555366021.0315 -Sweden,SWE,1971,40980345656.3725 -Sweden,SWE,1972,48263914958.8443 -Sweden,SWE,1973,58567384058.8006 -Sweden,SWE,1974,65082581294.7696 -Sweden,SWE,1975,81716751697.8951 -Sweden,SWE,1976,88102107647.0993 -Sweden,SWE,1977,93136775102.6419 -Sweden,SWE,1978,102969762221.976 -Sweden,SWE,1979,121646718574.328 -Sweden,SWE,1980,140088635568.375 -Sweden,SWE,1981,127858412114.39 -Sweden,SWE,1982,112767844570.719 -Sweden,SWE,1983,103533702638.547 -Sweden,SWE,1984,107661673734.858 -Sweden,SWE,1985,112514448261.835 -Sweden,SWE,1986,148376104539.839 -Sweden,SWE,1987,180429286795.786 -Sweden,SWE,1988,204068257817.6 -Sweden,SWE,1989,214875344909.957 -Sweden,SWE,1990,258154283908.9 -Sweden,SWE,1991,270362531376.602 -Sweden,SWE,1992,280312318915.485 -Sweden,SWE,1993,209950792712.696 -Sweden,SWE,1994,226079963711.768 -Sweden,SWE,1995,264051981551.316 -Sweden,SWE,1996,288103936773.039 -Sweden,SWE,1997,264477727278.681 -Sweden,SWE,1998,266800462898.904 -Sweden,SWE,1999,270847937645.236 -Sweden,SWE,2000,259802012617.057 -Sweden,SWE,2001,239917320966.977 -Sweden,SWE,2002,263926220332.543 -Sweden,SWE,2003,331108912605.271 -Sweden,SWE,2004,381705425301.746 -Sweden,SWE,2005,389042298376.845 -Sweden,SWE,2006,420032121655.688 -Sweden,SWE,2007,487816328342.309 -Sweden,SWE,2008,513965650650.119 -Sweden,SWE,2009,429657033107.737 -Sweden,SWE,2010,488377689564.921 -Sweden,SWE,2011,563109663291.177 -Sweden,SWE,2012,543880647757.404 -Sweden,SWE,2013,578742001487.571 -Sweden,SWE,2014,573817719109.402 -Sweden,SWE,2015,495694356611.551 -Sweden,SWE,2016,510999796581.597 -Switzerland,CHE,1960,9522746719.21614 -Switzerland,CHE,1961,10712712465.0522 -Switzerland,CHE,1962,11879982758.5619 -Switzerland,CHE,1963,13063643795.7884 -Switzerland,CHE,1964,14480556571.5476 -Switzerland,CHE,1965,15346741669.7575 -Switzerland,CHE,1966,16480058704.8531 -Switzerland,CHE,1967,17740013179.26 -Switzerland,CHE,1968,18942729779.1 -Switzerland,CHE,1969,20524886616.4789 -Switzerland,CHE,1980,118710309542.281 -Switzerland,CHE,1981,108721034568.781 -Switzerland,CHE,1982,111431738019.012 -Switzerland,CHE,1983,111035571006.622 -Switzerland,CHE,1984,106019113631.527 -Switzerland,CHE,1985,107496240242.562 -Switzerland,CHE,1986,154095512368.67 -Switzerland,CHE,1987,192981619165.773 -Switzerland,CHE,1988,208774024533.588 -Switzerland,CHE,1989,201572650956.66 -Switzerland,CHE,1990,257420293190.325 -Switzerland,CHE,1991,260459896582.985 -Switzerland,CHE,1992,271133679206.372 -Switzerland,CHE,1993,263691005481.862 -Switzerland,CHE,1994,291913801052.862 -Switzerland,CHE,1995,341759012938.689 -Switzerland,CHE,1996,329619351051.78 -Switzerland,CHE,1997,286604024805.347 -Switzerland,CHE,1998,294977518761.208 -Switzerland,CHE,1999,289884127679.404 -Switzerland,CHE,2000,271659728209.379 -Switzerland,CHE,2001,278628772872.719 -Switzerland,CHE,2002,301127808995.252 -Switzerland,CHE,2003,351982634291.23 -Switzerland,CHE,2004,393541693928.428 -Switzerland,CHE,2005,407535656039.19 -Switzerland,CHE,2006,429195591242.622 -Switzerland,CHE,2007,477407802315.895 -Switzerland,CHE,2008,551546962699.658 -Switzerland,CHE,2009,539528229942.101 -Switzerland,CHE,2010,581208562423.374 -Switzerland,CHE,2011,696278717728.137 -Switzerland,CHE,2012,665054050620.785 -Switzerland,CHE,2013,684835034384.327 -Switzerland,CHE,2014,702705544908.583 -Switzerland,CHE,2015,670789928809.882 -Switzerland,CHE,2016,659827235193.83 -Syrian Arab Republic,SYR,1960,857704431.686497 -Syrian Arab Republic,SYR,1961,945244992.211306 -Syrian Arab Republic,SYR,1962,1110565863.53737 -Syrian Arab Republic,SYR,1963,1200447429.35563 -Syrian Arab Republic,SYR,1964,1339494290.42432 -Syrian Arab Republic,SYR,1965,1472036550.70992 -Syrian Arab Republic,SYR,1966,1342287556.59602 -Syrian Arab Republic,SYR,1967,1580229795.10881 -Syrian Arab Republic,SYR,1968,1753746369.66049 -Syrian Arab Republic,SYR,1969,2245011571.98652 -Syrian Arab Republic,SYR,1970,2140383695.94618 -Syrian Arab Republic,SYR,1971,2589851693.01656 -Syrian Arab Republic,SYR,1972,3059682162.06566 -Syrian Arab Republic,SYR,1973,3239488104.60091 -Syrian Arab Republic,SYR,1974,5159557176.25012 -Syrian Arab Republic,SYR,1975,6826980766.8048 -Syrian Arab Republic,SYR,1976,7633528920.63247 -Syrian Arab Republic,SYR,1977,7696011359.94156 -Syrian Arab Republic,SYR,1978,9275203105.57946 -Syrian Arab Republic,SYR,1979,9929682184.32718 -Syrian Arab Republic,SYR,1980,13062421024.9337 -Syrian Arab Republic,SYR,1981,15518199247.3393 -Syrian Arab Republic,SYR,1982,16298905397.0701 -Syrian Arab Republic,SYR,1983,17589184556.6946 -Syrian Arab Republic,SYR,1984,17503082982.2832 -Syrian Arab Republic,SYR,1985,16403544510.5268 -Syrian Arab Republic,SYR,1986,13293209270.1036 -Syrian Arab Republic,SYR,1987,11356215712.9326 -Syrian Arab Republic,SYR,1988,10577042354.799 -Syrian Arab Republic,SYR,1989,9853396225.58749 -Syrian Arab Republic,SYR,1990,12308624283.9787 -Syrian Arab Republic,SYR,1991,12981833333.3333 -Syrian Arab Republic,SYR,1992,13253565898.9558 -Syrian Arab Republic,SYR,1993,13695962019.2084 -Syrian Arab Republic,SYR,1994,10122020000 -Syrian Arab Republic,SYR,1995,11396706586.8263 -Syrian Arab Republic,SYR,1996,13789560878.2435 -Syrian Arab Republic,SYR,1997,14505233968.8716 -Syrian Arab Republic,SYR,1998,15200846138.4615 -Syrian Arab Republic,SYR,1999,15873875968.9922 -Syrian Arab Republic,SYR,2000,19325894913.1254 -Syrian Arab Republic,SYR,2001,21099833783.503 -Syrian Arab Republic,SYR,2002,21582248881.6592 -Syrian Arab Republic,SYR,2003,21828144686.0394 -Syrian Arab Republic,SYR,2004,25086930693.0693 -Syrian Arab Republic,SYR,2005,28858965517.2414 -Syrian Arab Republic,SYR,2006,33332844574.7801 -Syrian Arab Republic,SYR,2007,40405006007.2086 -Tajikistan,TJK,1990,2629395066.27017 -Tajikistan,TJK,1991,2534720480.3244 -Tajikistan,TJK,1992,1909246640.80838 -Tajikistan,TJK,1993,1646693642.11088 -Tajikistan,TJK,1994,1346074611.47792 -Tajikistan,TJK,1995,1231523034.78397 -Tajikistan,TJK,1996,1043893062.60575 -Tajikistan,TJK,1997,921843144.229059 -Tajikistan,TJK,1998,1320126706.15503 -Tajikistan,TJK,1999,1086567377.60543 -Tajikistan,TJK,2000,860550305.832491 -Tajikistan,TJK,2001,1080774007.25065 -Tajikistan,TJK,2002,1221113780.25397 -Tajikistan,TJK,2003,1554125530.8029 -Tajikistan,TJK,2004,2076148695.50581 -Tajikistan,TJK,2005,2312319579.02843 -Tajikistan,TJK,2006,2830236053.84429 -Tajikistan,TJK,2007,3719497371.09659 -Tajikistan,TJK,2008,5161336170.46084 -Tajikistan,TJK,2009,4979481980.35098 -Tajikistan,TJK,2010,5642178579.58438 -Tajikistan,TJK,2011,6522732202.50748 -Tajikistan,TJK,2012,7633049792.09321 -Tajikistan,TJK,2013,8506674782.75471 -Tajikistan,TJK,2014,9236309138.04277 -Tajikistan,TJK,2015,7853450374.0001 -Tajikistan,TJK,2016,6951657158.90093 -Tanzania,TZA,1988,5100405772.46327 -Tanzania,TZA,1989,4420168102.39306 -Tanzania,TZA,1990,4258743262.82876 -Tanzania,TZA,1991,4956588278.56144 -Tanzania,TZA,1992,4601413263.52894 -Tanzania,TZA,1993,4257702196.53864 -Tanzania,TZA,1994,4510846967.8742 -Tanzania,TZA,1995,5255221424.80962 -Tanzania,TZA,1996,6496195450.61034 -Tanzania,TZA,1997,7683852496.84499 -Tanzania,TZA,1998,9345174219.07253 -Tanzania,TZA,1999,9697847263.63196 -Tanzania,TZA,2000,10185786382.8283 -Tanzania,TZA,2001,10383560602.8537 -Tanzania,TZA,2002,10805599892.7355 -Tanzania,TZA,2003,11659129888.8021 -Tanzania,TZA,2004,12825801580.9281 -Tanzania,TZA,2005,16929976600.142 -Tanzania,TZA,2006,18610460326.5437 -Tanzania,TZA,2007,21501741757.484 -Tanzania,TZA,2008,27368386358.131 -Tanzania,TZA,2009,28573777052.4542 -Tanzania,TZA,2010,31407908612.0943 -Tanzania,TZA,2011,33878631649.4157 -Tanzania,TZA,2012,39087748240.4403 -Tanzania,TZA,2013,44333456244.744 -Tanzania,TZA,2014,48197218326.7942 -Tanzania,TZA,2015,45628247290.4618 -Tanzania,TZA,2016,47431038892.2441 -Thailand,THA,1960,2760747471.88624 -Thailand,THA,1961,3034043574.06071 -Thailand,THA,1962,3308912796.93487 -Thailand,THA,1963,3540403456.55305 -Thailand,THA,1964,3889129942.30769 -Thailand,THA,1965,4388937649.03846 -Thailand,THA,1966,5279230817.30769 -Thailand,THA,1967,5638461442.30769 -Thailand,THA,1968,6081009427.88461 -Thailand,THA,1969,6695336567.30769 -Thailand,THA,1970,7086538437.5 -Thailand,THA,1971,7375000024.03846 -Thailand,THA,1972,8177884552.88461 -Thailand,THA,1973,10838587357.7466 -Thailand,THA,1974,13703000530.0587 -Thailand,THA,1975,14882747955.0328 -Thailand,THA,1976,16985211146.0238 -Thailand,THA,1977,19779315170.0237 -Thailand,THA,1978,24006570178.1561 -Thailand,THA,1979,27371699082.7126 -Thailand,THA,1980,32353440726.8856 -Thailand,THA,1981,34846107862.3673 -Thailand,THA,1982,36589797857.4006 -Thailand,THA,1983,40042826244.2337 -Thailand,THA,1984,41797592963.4424 -Thailand,THA,1985,38900692712.1496 -Thailand,THA,1986,43096746122.4614 -Thailand,THA,1987,50535438696.4094 -Thailand,THA,1988,61667199834.7428 -Thailand,THA,1989,72250877410.3183 -Thailand,THA,1990,85343063965.9182 -Thailand,THA,1991,98234695722.0341 -Thailand,THA,1992,111452869378.467 -Thailand,THA,1993,128889832382.818 -Thailand,THA,1994,146683499005.964 -Thailand,THA,1995,169278552851.272 -Thailand,THA,1996,183035154107.494 -Thailand,THA,1997,150180268649.388 -Thailand,THA,1998,113675706127.265 -Thailand,THA,1999,126668932159.508 -Thailand,THA,2000,126392308497.749 -Thailand,THA,2001,120296746256.631 -Thailand,THA,2002,134300851255.002 -Thailand,THA,2003,152280653543.725 -Thailand,THA,2004,172895476152.592 -Thailand,THA,2005,189318499954.003 -Thailand,THA,2006,221758486880.313 -Thailand,THA,2007,262942650543.771 -Thailand,THA,2008,291383081231.82 -Thailand,THA,2009,281710095724.761 -Thailand,THA,2010,341105009515.333 -Thailand,THA,2011,370818747396.833 -Thailand,THA,2012,397559992407.45 -Thailand,THA,2013,420528737876.717 -Thailand,THA,2014,406521561093.357 -Thailand,THA,2015,399234547137.472 -Thailand,THA,2016,406839679301.943 -Timor-Leste,TLS,2000,368000000 -Timor-Leste,TLS,2001,452000000 -Timor-Leste,TLS,2002,444000000 -Timor-Leste,TLS,2003,453000000 -Timor-Leste,TLS,2004,466000000 -Timor-Leste,TLS,2005,491000000 -Timor-Leste,TLS,2006,463000000 -Timor-Leste,TLS,2007,559000000 -Timor-Leste,TLS,2008,694000000 -Timor-Leste,TLS,2009,827000000 -Timor-Leste,TLS,2010,943000000 -Timor-Leste,TLS,2011,1148000000 -Timor-Leste,TLS,2012,1293000000 -Timor-Leste,TLS,2013,1312000000 -Timor-Leste,TLS,2014,1399000000 -Timor-Leste,TLS,2015,1441718600 -Togo,TGO,1960,121128073.114022 -Togo,TGO,1961,126396469.707058 -Togo,TGO,1962,132237441.630863 -Togo,TGO,1963,143255784.510751 -Togo,TGO,1964,166104067.630043 -Togo,TGO,1965,187300336.365369 -Togo,TGO,1966,216136263.912497 -Togo,TGO,1967,231706475.464114 -Togo,TGO,1968,241956910.658103 -Togo,TGO,1969,267732446.378413 -Togo,TGO,1970,253976626.166639 -Togo,TGO,1971,286537524.990331 -Togo,TGO,1972,335677636.893737 -Togo,TGO,1973,406479906.159652 -Togo,TGO,1974,560437742.594972 -Togo,TGO,1975,617321669.390877 -Togo,TGO,1976,619375134.18051 -Togo,TGO,1977,777435020.475847 -Togo,TGO,1978,824263841.539264 -Togo,TGO,1979,891775906.631015 -Togo,TGO,1980,1136408814.19692 -Togo,TGO,1981,962347000.991788 -Togo,TGO,1982,821651918.724626 -Togo,TGO,1983,765746590.616849 -Togo,TGO,1984,718148959.610872 -Togo,TGO,1985,762359722.701402 -Togo,TGO,1986,1060911735.26065 -Togo,TGO,1987,1249099130.02277 -Togo,TGO,1988,1378847487.41137 -Togo,TGO,1989,1352949662.75172 -Togo,TGO,1990,1628427515.41881 -Togo,TGO,1991,1602299862.9243 -Togo,TGO,1992,1692959110.18022 -Togo,TGO,1993,1233496846.33493 -Togo,TGO,1994,982624324.505898 -Togo,TGO,1995,1309382885.33029 -Togo,TGO,1996,1465448290.34132 -Togo,TGO,1997,1498950899.08774 -Togo,TGO,1998,1587345950.9743 -Togo,TGO,1999,1576094566.48548 -Togo,TGO,2000,1294250233.18894 -Togo,TGO,2001,1332328999.09077 -Togo,TGO,2002,1474630207.08242 -Togo,TGO,2003,1673690429.61609 -Togo,TGO,2004,1937074572.08687 -Togo,TGO,2005,2115154262.03025 -Togo,TGO,2006,2202809251.31304 -Togo,TGO,2007,2523462557.38975 -Togo,TGO,2008,3163416242.05877 -Togo,TGO,2009,3163000528.8167 -Togo,TGO,2010,3172945644.5585 -Togo,TGO,2011,3756023159.96 -Togo,TGO,2012,3866617462.61854 -Togo,TGO,2013,4080929201.27925 -Togo,TGO,2014,4482880424.33988 -Togo,TGO,2015,4087628275.95594 -Togo,TGO,2016,4399995986.56477 -Tonga,TON,1975,32506741.7201204 -Tonga,TON,1976,30036416.9619944 -Tonga,TON,1977,34139387.8908849 -Tonga,TON,1978,41567471.6721987 -Tonga,TON,1979,44667002.0120724 -Tonga,TON,1980,53260077.4311091 -Tonga,TON,1981,62242013.3302689 -Tonga,TON,1982,62068161.0711025 -Tonga,TON,1983,60863963.963964 -Tonga,TON,1984,64248354.5414656 -Tonga,TON,1985,60058663.3144773 -Tonga,TON,1986,68195855.6149733 -Tonga,TON,1987,81667133.4546982 -Tonga,TON,1988,106657267.367342 -Tonga,TON,1989,106344854.986095 -Tonga,TON,1990,113563821.577404 -Tonga,TON,1991,132201141.446861 -Tonga,TON,1992,137066290.550071 -Tonga,TON,1993,138489884.393064 -Tonga,TON,1994,193775943.038933 -Tonga,TON,1995,202547013.927138 -Tonga,TON,1996,219583570.094975 -Tonga,TON,1997,212155124.65374 -Tonga,TON,1998,188686997.319035 -Tonga,TON,1999,196686674.669868 -Tonga,TON,2000,202363492.160332 -Tonga,TON,2001,181244788.473329 -Tonga,TON,2002,182737040.095422 -Tonga,TON,2003,202543202.004099 -Tonga,TON,2004,229358214.792003 -Tonga,TON,2005,262176133.72543 -Tonga,TON,2006,294137737.070038 -Tonga,TON,2007,300143056.873221 -Tonga,TON,2008,349459648.569023 -Tonga,TON,2009,318151987.342379 -Tonga,TON,2010,369435481.362435 -Tonga,TON,2011,423015937.994651 -Tonga,TON,2012,472441382.972447 -Tonga,TON,2013,449387934.017765 -Tonga,TON,2014,443475142.084644 -Tonga,TON,2015,435430325.223892 -Tonga,TON,2016,395159628.7518 -Trinidad and Tobago,TTO,1960,535670127.748935 -Trinidad and Tobago,TTO,1961,584961208.656595 -Trinidad and Tobago,TTO,1962,619319197.340022 -Trinidad and Tobago,TTO,1963,678235373.038558 -Trinidad and Tobago,TTO,1964,711893367.55527 -Trinidad and Tobago,TTO,1965,736568861.926151 -Trinidad and Tobago,TTO,1966,723735635.536371 -Trinidad and Tobago,TTO,1967,761981474.023359 -Trinidad and Tobago,TTO,1968,758899950 -Trinidad and Tobago,TTO,1969,779200000 -Trinidad and Tobago,TTO,1970,821850000 -Trinidad and Tobago,TTO,1971,896754316.674262 -Trinidad and Tobago,TTO,1972,1083381044.08473 -Trinidad and Tobago,TTO,1973,1308799458.96284 -Trinidad and Tobago,TTO,1974,2042031901.42217 -Trinidad and Tobago,TTO,1975,2442667573.04821 -Trinidad and Tobago,TTO,1976,2500410583.79177 -Trinidad and Tobago,TTO,1977,3138666666.66667 -Trinidad and Tobago,TTO,1978,3562333458.33333 -Trinidad and Tobago,TTO,1979,4602416625 -Trinidad and Tobago,TTO,1980,6235833333.33333 -Trinidad and Tobago,TTO,1981,6992083333.33333 -Trinidad and Tobago,TTO,1982,8140416666.66667 -Trinidad and Tobago,TTO,1983,7763750000 -Trinidad and Tobago,TTO,1984,7757083333.33333 -Trinidad and Tobago,TTO,1985,7375918367.34694 -Trinidad and Tobago,TTO,1986,4794444444.44444 -Trinidad and Tobago,TTO,1987,4797777777.77778 -Trinidad and Tobago,TTO,1988,4496852073.46896 -Trinidad and Tobago,TTO,1989,4323058823.52941 -Trinidad and Tobago,TTO,1990,5068000000 -Trinidad and Tobago,TTO,1991,5307905882.35294 -Trinidad and Tobago,TTO,1992,5439552941.17647 -Trinidad and Tobago,TTO,1993,4669488516.37981 -Trinidad and Tobago,TTO,1994,4947205860.01451 -Trinidad and Tobago,TTO,1995,5329214163.22001 -Trinidad and Tobago,TTO,1996,5759537726.26601 -Trinidad and Tobago,TTO,1997,5737751331.63779 -Trinidad and Tobago,TTO,1998,6043694330.21609 -Trinidad and Tobago,TTO,1999,6808982520.75759 -Trinidad and Tobago,TTO,2000,8154338232.95978 -Trinidad and Tobago,TTO,2001,8824873259.32105 -Trinidad and Tobago,TTO,2002,9008273720.93395 -Trinidad and Tobago,TTO,2003,11305459802.0683 -Trinidad and Tobago,TTO,2004,13280275123.0354 -Trinidad and Tobago,TTO,2005,15982282462.3786 -Trinidad and Tobago,TTO,2006,18369070085.3888 -Trinidad and Tobago,TTO,2007,21642304045.512 -Trinidad and Tobago,TTO,2008,27870257894.2347 -Trinidad and Tobago,TTO,2009,19175196445.7936 -Trinidad and Tobago,TTO,2010,22157948396.2042 -Trinidad and Tobago,TTO,2011,25433011405.3017 -Trinidad and Tobago,TTO,2012,25694164489.2373 -Trinidad and Tobago,TTO,2013,26436221401.2976 -Trinidad and Tobago,TTO,2014,26175906133.4665 -Trinidad and Tobago,TTO,2015,23559287483.9276 -Trinidad and Tobago,TTO,2016,20989155539.8436 -Tunisia,TUN,1965,991047619.047619 -Tunisia,TUN,1966,1040952380.95238 -Tunisia,TUN,1967,1085714285.71429 -Tunisia,TUN,1968,1214666666.66667 -Tunisia,TUN,1969,1289904761.90476 -Tunisia,TUN,1970,1439238095.2381 -Tunisia,TUN,1971,1685217058.71103 -Tunisia,TUN,1972,2237476420.03773 -Tunisia,TUN,1973,2730787476.28084 -Tunisia,TUN,1974,3545933562.42841 -Tunisia,TUN,1975,4328610489.68432 -Tunisia,TUN,1976,4507929104.47761 -Tunisia,TUN,1977,5109324009.32401 -Tunisia,TUN,1978,5968044209.51466 -Tunisia,TUN,1979,7188191881.91882 -Tunisia,TUN,1980,8744134354.16152 -Tunisia,TUN,1981,8428513568.24625 -Tunisia,TUN,1982,8133401049.60217 -Tunisia,TUN,1983,8350176782.55746 -Tunisia,TUN,1984,8254891864.05767 -Tunisia,TUN,1985,8410185739.96405 -Tunisia,TUN,1986,9018136020.15113 -Tunisia,TUN,1987,9696271268.25148 -Tunisia,TUN,1988,10096292842.1543 -Tunisia,TUN,1989,10102075213.3151 -Tunisia,TUN,1990,12290568181.8182 -Tunisia,TUN,1991,13074782608.6957 -Tunisia,TUN,1992,15497286295.7938 -Tunisia,TUN,1993,14608946896.483 -Tunisia,TUN,1994,15632463424.2784 -Tunisia,TUN,1995,18030876599.3444 -Tunisia,TUN,1996,19587322786.1105 -Tunisia,TUN,1997,20746360430.4187 -Tunisia,TUN,1998,21803372266.6198 -Tunisia,TUN,1999,22943685719.103 -Tunisia,TUN,2000,21473188881.5933 -Tunisia,TUN,2001,22066101341.4888 -Tunisia,TUN,2002,23142294436.2383 -Tunisia,TUN,2003,27453084982.5378 -Tunisia,TUN,2004,31183139301.4853 -Tunisia,TUN,2005,32273007553.5687 -Tunisia,TUN,2006,34378437265.2141 -Tunisia,TUN,2007,38908069299.204 -Tunisia,TUN,2008,44856586316.0458 -Tunisia,TUN,2009,43454935940.1614 -Tunisia,TUN,2010,44050929160.2627 -Tunisia,TUN,2011,45810626509.4474 -Tunisia,TUN,2012,45044176963.9542 -Tunisia,TUN,2013,46255308672.3703 -Tunisia,TUN,2014,47603227896.5659 -Tunisia,TUN,2015,43156606851.5498 -Tunisia,TUN,2016,42062549394.7859 -Turkey,TUR,1960,13995067817.5092 -Turkey,TUR,1961,8022222222.22222 -Turkey,TUR,1962,8922222222.22222 -Turkey,TUR,1963,10355555555.5556 -Turkey,TUR,1964,11177777777.7778 -Turkey,TUR,1965,11944444444.4444 -Turkey,TUR,1966,14122222222.2222 -Turkey,TUR,1967,15666666666.6667 -Turkey,TUR,1968,17500000000 -Turkey,TUR,1969,19466666666.6667 -Turkey,TUR,1970,17086956521.7391 -Turkey,TUR,1971,16256619963.7997 -Turkey,TUR,1972,20431095406.3604 -Turkey,TUR,1973,25724381625.4417 -Turkey,TUR,1974,35599913836.4328 -Turkey,TUR,1975,44633707242.7642 -Turkey,TUR,1976,51280134554.2889 -Turkey,TUR,1977,58676813687.3681 -Turkey,TUR,1978,65147022485.7919 -Turkey,TUR,1979,89394085658.2038 -Turkey,TUR,1980,68789289565.7434 -Turkey,TUR,1981,71040020140.4436 -Turkey,TUR,1982,64546332580.7583 -Turkey,TUR,1983,61678280115.4987 -Turkey,TUR,1984,59989909457.8379 -Turkey,TUR,1985,67234948264.5987 -Turkey,TUR,1986,75728009962.7878 -Turkey,TUR,1987,87172789528.3316 -Turkey,TUR,1988,90852814004.9917 -Turkey,TUR,1989,107143348667.094 -Turkey,TUR,1990,150676291094.21 -Turkey,TUR,1991,150027833333.333 -Turkey,TUR,1992,158459130434.783 -Turkey,TUR,1993,180169736363.636 -Turkey,TUR,1994,130690172297.297 -Turkey,TUR,1995,169485941048.035 -Turkey,TUR,1996,181475555282.555 -Turkey,TUR,1997,189834649111.257 -Turkey,TUR,1998,275768695818.949 -Turkey,TUR,1999,255884300382.044 -Turkey,TUR,2000,272979390595.01 -Turkey,TUR,2001,200254104151.474 -Turkey,TUR,2002,238423907922.754 -Turkey,TUR,2003,311825946795.017 -Turkey,TUR,2004,404776328437.599 -Turkey,TUR,2005,501422832613.554 -Turkey,TUR,2006,552504962256.438 -Turkey,TUR,2007,675754121015.013 -Turkey,TUR,2008,764322933264.927 -Turkey,TUR,2009,644656538878.423 -Turkey,TUR,2010,771876943465.616 -Turkey,TUR,2011,832546462299.564 -Turkey,TUR,2012,873981840596.288 -Turkey,TUR,2013,950595641011.836 -Turkey,TUR,2014,934167774215.031 -Turkey,TUR,2015,859383637728.94 -Turkey,TUR,2016,857748989287.642 -Turkmenistan,TKM,1987,2331358819.75954 -Turkmenistan,TKM,1988,3010982414.24425 -Turkmenistan,TKM,1989,3006988216.55045 -Turkmenistan,TKM,1990,3189539641.3171 -Turkmenistan,TKM,1991,3208098919.0146 -Turkmenistan,TKM,1992,3200539816.0601 -Turkmenistan,TKM,1993,3179225948.58114 -Turkmenistan,TKM,1994,2561118608.35516 -Turkmenistan,TKM,1995,2482228439.71407 -Turkmenistan,TKM,1996,2379281767.9558 -Turkmenistan,TKM,1997,2450084970.24741 -Turkmenistan,TKM,1998,2605688065.08338 -Turkmenistan,TKM,1999,2450686659.778 -Turkmenistan,TKM,2000,2904662604.82053 -Turkmenistan,TKM,2001,3534771968.51189 -Turkmenistan,TKM,2002,4462028988.72949 -Turkmenistan,TKM,2003,5977440582.80171 -Turkmenistan,TKM,2004,6838351088.46688 -Turkmenistan,TKM,2005,8104355716.8784 -Turkmenistan,TKM,2006,10277598152.4249 -Turkmenistan,TKM,2007,12664165103.1895 -Turkmenistan,TKM,2008,19271523178.8079 -Turkmenistan,TKM,2009,20214385964.9123 -Turkmenistan,TKM,2010,22583157894.7368 -Turkmenistan,TKM,2011,29233333333.3333 -Turkmenistan,TKM,2012,35164210526.3158 -Turkmenistan,TKM,2013,39197543859.6491 -Turkmenistan,TKM,2014,43524210526.3158 -Turkmenistan,TKM,2015,35799628571.4286 -Turkmenistan,TKM,2016,36179885714.2857 -Tuvalu,TUV,1990,8824447.74022325 -Tuvalu,TUV,1991,9365165.91369372 -Tuvalu,TUV,1992,9742949.47121034 -Tuvalu,TUV,1993,9630762.95389637 -Tuvalu,TUV,1994,10886825.5592923 -Tuvalu,TUV,1995,11025945.1445515 -Tuvalu,TUV,1996,12334846.2320995 -Tuvalu,TUV,1997,12700905.4475286 -Tuvalu,TUV,1998,12757632.8684508 -Tuvalu,TUV,1999,13687141.1058778 -Tuvalu,TUV,2000,13742057.0500928 -Tuvalu,TUV,2001,13196544.946726 -Tuvalu,TUV,2002,15450994.2410084 -Tuvalu,TUV,2003,18231078.5394643 -Tuvalu,TUV,2004,21534931.6075894 -Tuvalu,TUV,2005,21839098.8927071 -Tuvalu,TUV,2006,22902861.4457831 -Tuvalu,TUV,2007,27030374.0272781 -Tuvalu,TUV,2008,30290219.7617849 -Tuvalu,TUV,2009,27101076.2751521 -Tuvalu,TUV,2010,31823518.6204366 -Tuvalu,TUV,2011,39312016.5033522 -Tuvalu,TUV,2012,39875750.6730172 -Tuvalu,TUV,2013,38322359.5288666 -Tuvalu,TUV,2014,37259689.9224806 -Tuvalu,TUV,2015,32673277.7402149 -Tuvalu,TUV,2016,34218878.4390841 -Uganda,UGA,1960,423008385.744235 -Uganda,UGA,1961,441524109.014675 -Uganda,UGA,1962,449012578.616352 -Uganda,UGA,1963,516147798.742138 -Uganda,UGA,1964,589056603.773585 -Uganda,UGA,1965,884873949.579832 -Uganda,UGA,1966,925770308.123249 -Uganda,UGA,1967,967647058.823529 -Uganda,UGA,1968,1037815126.05042 -Uganda,UGA,1969,1169047619.04762 -Uganda,UGA,1970,1260084033.61345 -Uganda,UGA,1971,1417787114.84594 -Uganda,UGA,1972,1491596638.65546 -Uganda,UGA,1973,1702521008.40336 -Uganda,UGA,1974,2100142653.35235 -Uganda,UGA,1975,2359555555.55556 -Uganda,UGA,1976,2447300000 -Uganda,UGA,1977,2936470588.23529 -Uganda,UGA,1978,2420260869.56522 -Uganda,UGA,1979,2139025000 -Uganda,UGA,1980,1244610000 -Uganda,UGA,1981,1337300000 -Uganda,UGA,1982,2177500000 -Uganda,UGA,1983,2240333333.33333 -Uganda,UGA,1984,3615647477.05434 -Uganda,UGA,1985,3519666338.52454 -Uganda,UGA,1986,3923232122.12784 -Uganda,UGA,1987,6269511614.66235 -Uganda,UGA,1988,6508931651.66667 -Uganda,UGA,1989,5276480985.99937 -Uganda,UGA,1990,4304398865.88268 -Uganda,UGA,1991,3321729057.12215 -Uganda,UGA,1992,2857457860.05088 -Uganda,UGA,1993,3220439044.18949 -Uganda,UGA,1994,3990430446.71216 -Uganda,UGA,1995,5755818947.42125 -Uganda,UGA,1996,6044585326.938 -Uganda,UGA,1997,6269333313.17108 -Uganda,UGA,1998,6584815846.52754 -Uganda,UGA,1999,5998563257.94659 -Uganda,UGA,2000,6193246837.09687 -Uganda,UGA,2001,5840503868.57245 -Uganda,UGA,2002,6178563590.89254 -Uganda,UGA,2003,6336696288.98214 -Uganda,UGA,2004,7940362799.17997 -Uganda,UGA,2005,9013834373.41246 -Uganda,UGA,2006,9942597779.99265 -Uganda,UGA,2007,12292813603.2327 -Uganda,UGA,2008,14239026629.639 -Uganda,UGA,2009,21203769124.656 -Uganda,UGA,2010,20179411062.934 -Uganda,UGA,2011,20508595015.4506 -Uganda,UGA,2012,23516083900.4013 -Uganda,UGA,2013,24879053946.9135 -Uganda,UGA,2014,27927875335.8068 -Uganda,UGA,2015,27856380083.2478 -Uganda,UGA,2016,25527910090.6285 -Ukraine,UKR,1987,64087694038.2333 -Ukraine,UKR,1988,74703517902.6642 -Ukraine,UKR,1989,82709161099.1244 -Ukraine,UKR,1990,81456918678.5008 -Ukraine,UKR,1991,77464561149.5103 -Ukraine,UKR,1992,73942235330.437 -Ukraine,UKR,1993,65648559903.0571 -Ukraine,UKR,1994,52549555149.1978 -Ukraine,UKR,1995,48213868178.0873 -Ukraine,UKR,1996,44558077827.135 -Ukraine,UKR,1997,50150399791.647 -Ukraine,UKR,1998,41883241471.7365 -Ukraine,UKR,1999,31580639045.454 -Ukraine,UKR,2000,31261527363.144 -Ukraine,UKR,2001,38009344576.6088 -Ukraine,UKR,2002,42392896031.2394 -Ukraine,UKR,2003,50132953288.203 -Ukraine,UKR,2004,64883060725.7003 -Ukraine,UKR,2005,86142018069.3504 -Ukraine,UKR,2006,107753069306.931 -Ukraine,UKR,2007,142719009900.99 -Ukraine,UKR,2008,179992405832.321 -Ukraine,UKR,2009,117227769791.56 -Ukraine,UKR,2010,136013155905.036 -Ukraine,UKR,2011,163159671670.265 -Ukraine,UKR,2012,175781379051.433 -Ukraine,UKR,2013,183310146378.081 -Ukraine,UKR,2014,133503411375.739 -Ukraine,UKR,2015,91030959454.6961 -Ukraine,UKR,2016,93270479388.5243 -United Arab Emirates,ARE,1975,14720672506.5004 -United Arab Emirates,ARE,1976,19213022691.0526 -United Arab Emirates,ARE,1977,24871775164.6043 -United Arab Emirates,ARE,1978,23775831783.4263 -United Arab Emirates,ARE,1979,31225463217.7582 -United Arab Emirates,ARE,1980,43598748449.0479 -United Arab Emirates,ARE,1981,49333424135.1131 -United Arab Emirates,ARE,1982,46622718605.2847 -United Arab Emirates,ARE,1983,42803323345.1376 -United Arab Emirates,ARE,1984,41807954235.903 -United Arab Emirates,ARE,1985,40603650231.5445 -United Arab Emirates,ARE,1986,33943612094.7971 -United Arab Emirates,ARE,1987,36384908744.2114 -United Arab Emirates,ARE,1988,36275674203.2144 -United Arab Emirates,ARE,1989,41464995913.9199 -United Arab Emirates,ARE,1990,50701443748.2975 -United Arab Emirates,ARE,1991,51552165622.4462 -United Arab Emirates,ARE,1992,54239171887.769 -United Arab Emirates,ARE,1993,55625170253.337 -United Arab Emirates,ARE,1994,59305093979.842 -United Arab Emirates,ARE,1995,65743666575.8649 -United Arab Emirates,ARE,1996,73571233996.1863 -United Arab Emirates,ARE,1997,78839008444.5655 -United Arab Emirates,ARE,1998,75674336283.1858 -United Arab Emirates,ARE,1999,84445473110.9598 -United Arab Emirates,ARE,2000,104337372362.151 -United Arab Emirates,ARE,2001,103311640571.818 -United Arab Emirates,ARE,2002,109816201497.617 -United Arab Emirates,ARE,2003,124346358066.712 -United Arab Emirates,ARE,2004,147824370319.946 -United Arab Emirates,ARE,2005,180617018379.85 -United Arab Emirates,ARE,2006,222116541865.214 -United Arab Emirates,ARE,2007,257916133424.098 -United Arab Emirates,ARE,2008,315474615738.598 -United Arab Emirates,ARE,2009,253547358747.447 -United Arab Emirates,ARE,2010,289880430197.25 -United Arab Emirates,ARE,2011,350908390046.358 -United Arab Emirates,ARE,2012,374817974113.476 -United Arab Emirates,ARE,2013,390427289210.786 -United Arab Emirates,ARE,2014,403197682887.717 -United Arab Emirates,ARE,2015,357949199759.586 -United Arab Emirates,ARE,2016,348743265715.395 -United Kingdom,GBR,1960,72328047042.1588 -United Kingdom,GBR,1961,76694360635.9159 -United Kingdom,GBR,1962,80601939635.2483 -United Kingdom,GBR,1963,85443766670.4279 -United Kingdom,GBR,1964,93387598813.9269 -United Kingdom,GBR,1965,100595782309.165 -United Kingdom,GBR,1966,107090721447.057 -United Kingdom,GBR,1967,111185383409.521 -United Kingdom,GBR,1968,104702736248.084 -United Kingdom,GBR,1969,112676874821.987 -United Kingdom,GBR,1970,130671946244.3 -United Kingdom,GBR,1971,148113896325.14 -United Kingdom,GBR,1972,169965034965.035 -United Kingdom,GBR,1973,192537971582.558 -United Kingdom,GBR,1974,206131369798.971 -United Kingdom,GBR,1975,241756637168.142 -United Kingdom,GBR,1976,232614555256.065 -United Kingdom,GBR,1977,263066457352.172 -United Kingdom,GBR,1978,335883029721.956 -United Kingdom,GBR,1979,438994070309.191 -United Kingdom,GBR,1980,564947710899.373 -United Kingdom,GBR,1981,540765675241.158 -United Kingdom,GBR,1982,515048916841.37 -United Kingdom,GBR,1983,489618008185.539 -United Kingdom,GBR,1984,461487097632.349 -United Kingdom,GBR,1985,489285164271.047 -United Kingdom,GBR,1986,601452653180.885 -United Kingdom,GBR,1987,745162608269.325 -United Kingdom,GBR,1988,910122732123.799 -United Kingdom,GBR,1989,926884816753.927 -United Kingdom,GBR,1990,1093169389204.55 -United Kingdom,GBR,1991,1142797178130.51 -United Kingdom,GBR,1992,1179659529659.53 -United Kingdom,GBR,1993,1061388722255.55 -United Kingdom,GBR,1994,1140489745944.29 -United Kingdom,GBR,1995,1320255641470.73 -United Kingdom,GBR,1996,1392979719188.77 -United Kingdom,GBR,1997,1537090700720.37 -United Kingdom,GBR,1998,1623564094070.88 -United Kingdom,GBR,1999,1652167933991.26 -United Kingdom,GBR,2000,1635441065214.1 -United Kingdom,GBR,2001,1613034403339.57 -United Kingdom,GBR,2002,1757571942446.04 -United Kingdom,GBR,2003,2028488163265.31 -United Kingdom,GBR,2004,2389004027828.63 -United Kingdom,GBR,2005,2508103636363.64 -United Kingdom,GBR,2006,2678277828886.84 -United Kingdom,GBR,2007,3063005202080.83 -United Kingdom,GBR,2008,2875463235294.12 -United Kingdom,GBR,2009,2367127278392.27 -United Kingdom,GBR,2010,2429680444512.61 -United Kingdom,GBR,2011,2608824654243.59 -United Kingdom,GBR,2012,2646002634059.62 -United Kingdom,GBR,2013,2719509472492.7 -United Kingdom,GBR,2014,2998833559195.71 -United Kingdom,GBR,2015,2861090726739.55 -United Kingdom,GBR,2016,2618885692029.18 -United States,USA,1960,543300000000 -United States,USA,1961,563300000000 -United States,USA,1962,605100000000 -United States,USA,1963,638600000000 -United States,USA,1964,685800000000 -United States,USA,1965,743700000000 -United States,USA,1966,815000000000 -United States,USA,1967,861700000000 -United States,USA,1968,942500000000 -United States,USA,1969,1019900000000 -United States,USA,1970,1075884000000 -United States,USA,1971,1167770000000 -United States,USA,1972,1282449000000 -United States,USA,1973,1428549000000 -United States,USA,1974,1548825000000 -United States,USA,1975,1688923000000 -United States,USA,1976,1877587000000 -United States,USA,1977,2085951000000 -United States,USA,1978,2356571000000 -United States,USA,1979,2632143000000 -United States,USA,1980,2862505000000 -United States,USA,1981,3210956000000 -United States,USA,1982,3344991000000 -United States,USA,1983,3638137000000 -United States,USA,1984,4040693000000 -United States,USA,1985,4346734000000 -United States,USA,1986,4590155000000 -United States,USA,1987,4870217000000 -United States,USA,1988,5252629000000 -United States,USA,1989,5657693000000 -United States,USA,1990,5979589000000 -United States,USA,1991,6174043000000 -United States,USA,1992,6539299000000 -United States,USA,1993,6878718000000 -United States,USA,1994,7308755000000 -United States,USA,1995,7664060000000 -United States,USA,1996,8100201000000 -United States,USA,1997,8608515000000 -United States,USA,1998,9089168000000 -United States,USA,1999,9660624000000 -United States,USA,2000,10284779000000 -United States,USA,2001,10621824000000 -United States,USA,2002,10977514000000 -United States,USA,2003,11510670000000 -United States,USA,2004,12274928000000 -United States,USA,2005,13093726000000 -United States,USA,2006,13855888000000 -United States,USA,2007,14477635000000 -United States,USA,2008,14718582000000 -United States,USA,2009,14418739000000 -United States,USA,2010,14964372000000 -United States,USA,2011,15517926000000 -United States,USA,2012,16155255000000 -United States,USA,2013,16691517000000 -United States,USA,2014,17393103000000 -United States,USA,2015,18036648000000 -United States,USA,2016,18569100000000 -Uruguay,URY,1960,1242289212.04285 -Uruguay,URY,1961,1547388812.89969 -Uruguay,URY,1962,1710004464.40897 -Uruguay,URY,1963,1539681533.63786 -Uruguay,URY,1964,1975701727.50862 -Uruguay,URY,1965,1890769326.14221 -Uruguay,URY,1966,1809183974.52669 -Uruguay,URY,1967,1597721080.00991 -Uruguay,URY,1968,1593675330.16467 -Uruguay,URY,1969,2004435483.87097 -Uruguay,URY,1970,2137096774.19355 -Uruguay,URY,1971,2807258064.51613 -Uruguay,URY,1972,2189418001.37898 -Uruguay,URY,1973,3964295672.52444 -Uruguay,URY,1974,4090209681.97172 -Uruguay,URY,1975,3538283322.07726 -Uruguay,URY,1976,3667161241.48372 -Uruguay,URY,1977,4114667062.64917 -Uruguay,URY,1978,4910257282.93153 -Uruguay,URY,1979,7181185277.98651 -Uruguay,URY,1980,10163020115.7344 -Uruguay,URY,1981,11048335541.4933 -Uruguay,URY,1982,9178802162.6616 -Uruguay,URY,1983,5102281255.99986 -Uruguay,URY,1984,4850241442.17643 -Uruguay,URY,1985,4732017873.38369 -Uruguay,URY,1986,5880112788.40947 -Uruguay,URY,1987,7367494080.40014 -Uruguay,URY,1988,8213515458.51139 -Uruguay,URY,1989,8438951476.06644 -Uruguay,URY,1990,9298839655.23139 -Uruguay,URY,1991,11206193313.0458 -Uruguay,URY,1992,12878157305.7481 -Uruguay,URY,1993,15002144584.3663 -Uruguay,URY,1994,17474578502.4346 -Uruguay,URY,1995,19297663096.5506 -Uruguay,URY,1996,20515465834.0682 -Uruguay,URY,1997,23969746849.9221 -Uruguay,URY,1998,25385928198.3212 -Uruguay,URY,1999,23983945190.6202 -Uruguay,URY,2000,22823255801.8447 -Uruguay,URY,2001,20898788416.6348 -Uruguay,URY,2002,13606494599.4261 -Uruguay,URY,2003,12045631092.5353 -Uruguay,URY,2004,13686329890.1191 -Uruguay,URY,2005,17362857683.8545 -Uruguay,URY,2006,19579457966.0538 -Uruguay,URY,2007,23410572621.533 -Uruguay,URY,2008,30366213095.4256 -Uruguay,URY,2009,31660911290.3226 -Uruguay,URY,2010,40284481661.8726 -Uruguay,URY,2011,47962439293.3697 -Uruguay,URY,2012,51264390121.4144 -Uruguay,URY,2013,57531233350.9101 -Uruguay,URY,2014,57236013077.5187 -Uruguay,URY,2015,53274304214.8174 -Uruguay,URY,2016,52419720713.7316 -Uzbekistan,UZB,1990,13360607990.6751 -Uzbekistan,UZB,1991,13677622222.2222 -Uzbekistan,UZB,1992,12941297376.0933 -Uzbekistan,UZB,1993,13099013835.5111 -Uzbekistan,UZB,1994,12899156990.6156 -Uzbekistan,UZB,1995,13350468917.4115 -Uzbekistan,UZB,1996,13948892215.5689 -Uzbekistan,UZB,1997,14744603773.5849 -Uzbekistan,UZB,1998,14988971210.8383 -Uzbekistan,UZB,1999,17078465982.0282 -Uzbekistan,UZB,2000,13760374487.51 -Uzbekistan,UZB,2001,11401351420.1718 -Uzbekistan,UZB,2002,9687951055.22541 -Uzbekistan,UZB,2003,10128112401.4248 -Uzbekistan,UZB,2004,12030023547.8807 -Uzbekistan,UZB,2005,14307509838.8053 -Uzbekistan,UZB,2006,17330833852.919 -Uzbekistan,UZB,2007,22311393927.8817 -Uzbekistan,UZB,2008,29549438883.8338 -Uzbekistan,UZB,2009,33689223673.2577 -Uzbekistan,UZB,2010,39332770928.9426 -Uzbekistan,UZB,2011,45915191189.3237 -Uzbekistan,UZB,2012,51821573338.1312 -Uzbekistan,UZB,2013,57690453460.6205 -Uzbekistan,UZB,2014,63067077178.5381 -Uzbekistan,UZB,2015,66903804142.5395 -Uzbekistan,UZB,2016,67220335569.6147 -Vanuatu,VUT,1979,119258835.335525 -Vanuatu,VUT,1980,113423181.338956 -Vanuatu,VUT,1981,98746405.3924806 -Vanuatu,VUT,1982,98144643.8965575 -Vanuatu,VUT,1983,110123779.812821 -Vanuatu,VUT,1984,135553763.982667 -Vanuatu,VUT,1985,123698506.111363 -Vanuatu,VUT,1986,118691396.764915 -Vanuatu,VUT,1987,130834145.053665 -Vanuatu,VUT,1988,148545381.418421 -Vanuatu,VUT,1989,144482170.248703 -Vanuatu,VUT,1990,158397403.041175 -Vanuatu,VUT,1991,188869985.673352 -Vanuatu,VUT,1992,196142585.014816 -Vanuatu,VUT,1993,188080374.400605 -Vanuatu,VUT,1994,219260341.050642 -Vanuatu,VUT,1995,233902114.8683 -Vanuatu,VUT,1996,245177633.168933 -Vanuatu,VUT,1997,255890221.800293 -Vanuatu,VUT,1998,262301252.769228 -Vanuatu,VUT,1999,267999225.256634 -Vanuatu,VUT,2000,272014693.050806 -Vanuatu,VUT,2001,257926881.72043 -Vanuatu,VUT,2002,262603781.799059 -Vanuatu,VUT,2003,314463144.04219 -Vanuatu,VUT,2004,364996869.129618 -Vanuatu,VUT,2005,394962552.336108 -Vanuatu,VUT,2006,439376794.094041 -Vanuatu,VUT,2007,526428309.945088 -Vanuatu,VUT,2008,607958616.143415 -Vanuatu,VUT,2009,610066628.693058 -Vanuatu,VUT,2010,700804286.224354 -Vanuatu,VUT,2011,792149700.679116 -Vanuatu,VUT,2012,781702874.106058 -Vanuatu,VUT,2013,801787555.861121 -Vanuatu,VUT,2014,814954306.971033 -Vanuatu,VUT,2015,742432131.041002 -Vanuatu,VUT,2016,773502895.927602 -"Venezuela, RB",VEN,1960,8736939393.93939 -"Venezuela, RB",VEN,1961,9058121212.12121 -"Venezuela, RB",VEN,1962,10022000000 -"Venezuela, RB",VEN,1963,10823878787.8788 -"Venezuela, RB",VEN,1964,9111000000 -"Venezuela, RB",VEN,1965,9496244444.44444 -"Venezuela, RB",VEN,1966,9984400000 -"Venezuela, RB",VEN,1967,10356422222.2222 -"Venezuela, RB",VEN,1968,11343444444.4444 -"Venezuela, RB",VEN,1969,11795044444.4444 -"Venezuela, RB",VEN,1970,12848755555.5556 -"Venezuela, RB",VEN,1971,14625295454.5455 -"Venezuela, RB",VEN,1972,15922863636.3636 -"Venezuela, RB",VEN,1973,19466279069.7674 -"Venezuela, RB",VEN,1974,28985627906.9767 -"Venezuela, RB",VEN,1975,31303581395.3488 -"Venezuela, RB",VEN,1976,36187023255.814 -"Venezuela, RB",VEN,1977,42263209302.3256 -"Venezuela, RB",VEN,1978,46426511627.907 -"Venezuela, RB",VEN,1979,55653325581.3953 -"Venezuela, RB",VEN,1980,67018023255.814 -"Venezuela, RB",VEN,1981,75367139534.8837 -"Venezuela, RB",VEN,1982,76559883720.9302 -"Venezuela, RB",VEN,1983,78540255813.9535 -"Venezuela, RB",VEN,1984,56091900000 -"Venezuela, RB",VEN,1985,57935746666.6667 -"Venezuela, RB",VEN,1986,58793864197.5309 -"Venezuela, RB",VEN,1987,45343793103.4483 -"Venezuela, RB",VEN,1988,58428406896.5517 -"Venezuela, RB",VEN,1989,42119835734.8703 -"Venezuela, RB",VEN,1990,47028010660.9808 -"Venezuela, RB",VEN,1991,51749026408.4507 -"Venezuela, RB",VEN,1992,58450099415.2047 -"Venezuela, RB",VEN,1993,58124193832.5991 -"Venezuela, RB",VEN,1994,56531046464.6465 -"Venezuela, RB",VEN,1995,74906532239.819 -"Venezuela, RB",VEN,1996,68263823148.8138 -"Venezuela, RB",VEN,1997,85843534588.6206 -"Venezuela, RB",VEN,1998,91331203433.1629 -"Venezuela, RB",VEN,1999,97976886247.3172 -"Venezuela, RB",VEN,2000,117140723529.412 -"Venezuela, RB",VEN,2001,122903960204.505 -"Venezuela, RB",VEN,2002,92893587733.6549 -"Venezuela, RB",VEN,2003,83620628582.1082 -"Venezuela, RB",VEN,2004,112453382329.615 -"Venezuela, RB",VEN,2005,145510008134.75 -"Venezuela, RB",VEN,2006,183477522123.894 -"Venezuela, RB",VEN,2007,230364012575.687 -"Venezuela, RB",VEN,2008,315953388510.678 -"Venezuela, RB",VEN,2009,329787628928.472 -"Venezuela, RB",VEN,2010,393190682070.491 -"Venezuela, RB",VEN,2011,316482190800.364 -"Venezuela, RB",VEN,2012,381286237847.667 -"Venezuela, RB",VEN,2013,371006299120.244 -Vietnam,VNM,1985,14094687820.7445 -Vietnam,VNM,1986,26336617261.6954 -Vietnam,VNM,1987,36658108340.6777 -Vietnam,VNM,1988,25423812719.4906 -Vietnam,VNM,1989,6293304840.51995 -Vietnam,VNM,1990,6471740490.99897 -Vietnam,VNM,1991,9613369548.20359 -Vietnam,VNM,1992,9866990092.18743 -Vietnam,VNM,1993,13180953965.6854 -Vietnam,VNM,1994,16286434068.4834 -Vietnam,VNM,1995,20736163924.0492 -Vietnam,VNM,1996,24657470352.545 -Vietnam,VNM,1997,26843701147.496 -Vietnam,VNM,1998,27209601995.8245 -Vietnam,VNM,1999,28683657995.128 -Vietnam,VNM,2000,33640085738.648 -Vietnam,VNM,2001,35291349197.4254 -Vietnam,VNM,2002,37947904054.452 -Vietnam,VNM,2003,42717072869.3917 -Vietnam,VNM,2004,49424107709.8946 -Vietnam,VNM,2005,57633255618.2731 -Vietnam,VNM,2006,66371664817.0436 -Vietnam,VNM,2007,77414425532.2452 -Vietnam,VNM,2008,99130304099.1274 -Vietnam,VNM,2009,106014601171.036 -Vietnam,VNM,2010,115931749697.241 -Vietnam,VNM,2011,135539487317.008 -Vietnam,VNM,2012,155820001920.492 -Vietnam,VNM,2013,171222025117.381 -Vietnam,VNM,2014,186204652922.262 -Vietnam,VNM,2015,193241108709.536 -Vietnam,VNM,2016,202615893443.73 -Virgin Islands (U.S.),VIR,1960,24200000 -Virgin Islands (U.S.),VIR,1961,25700000 -Virgin Islands (U.S.),VIR,1962,36900000 -Virgin Islands (U.S.),VIR,1963,41400000 -Virgin Islands (U.S.),VIR,1964,53800000 -Virgin Islands (U.S.),VIR,1965,66500000 -Virgin Islands (U.S.),VIR,1966,84100000 -Virgin Islands (U.S.),VIR,1967,115400000 -Virgin Islands (U.S.),VIR,1968,173800000 -Virgin Islands (U.S.),VIR,1969,211300000 -Virgin Islands (U.S.),VIR,1970,219000000 -Virgin Islands (U.S.),VIR,1971,257000000 -Virgin Islands (U.S.),VIR,1972,307100000 -Virgin Islands (U.S.),VIR,1973,351600000 -Virgin Islands (U.S.),VIR,1974,395400000 -Virgin Islands (U.S.),VIR,1975,399800000 -Virgin Islands (U.S.),VIR,1976,440000000 -Virgin Islands (U.S.),VIR,1977,461800000 -Virgin Islands (U.S.),VIR,1978,512900000 -Virgin Islands (U.S.),VIR,1979,606700032 -Virgin Islands (U.S.),VIR,1980,727800000 -Virgin Islands (U.S.),VIR,1981,821800000 -Virgin Islands (U.S.),VIR,1982,832600000 -Virgin Islands (U.S.),VIR,1983,916899968 -Virgin Islands (U.S.),VIR,1984,985400000 -Virgin Islands (U.S.),VIR,1985,990400000 -Virgin Islands (U.S.),VIR,1986,1035600000 -Virgin Islands (U.S.),VIR,1987,1147800064 -Virgin Islands (U.S.),VIR,1988,1204600064 -Virgin Islands (U.S.),VIR,1989,1343900032 -Virgin Islands (U.S.),VIR,1990,1564700032 -Virgin Islands (U.S.),VIR,1991,1671200000 -Virgin Islands (U.S.),VIR,1992,1770899968 -Virgin Islands (U.S.),VIR,1993,1996000000 -Virgin Islands (U.S.),VIR,2002,3269000000 -Virgin Islands (U.S.),VIR,2003,3453000000 -Virgin Islands (U.S.),VIR,2004,3799000000 -Virgin Islands (U.S.),VIR,2005,4439000000 -Virgin Islands (U.S.),VIR,2006,4504000000 -Virgin Islands (U.S.),VIR,2007,4803000000 -Virgin Islands (U.S.),VIR,2008,4250000000 -Virgin Islands (U.S.),VIR,2009,4203000000 -Virgin Islands (U.S.),VIR,2010,4339000000 -Virgin Islands (U.S.),VIR,2011,4239000000 -Virgin Islands (U.S.),VIR,2012,4095000000 -Virgin Islands (U.S.),VIR,2013,3764000000 -Virgin Islands (U.S.),VIR,2014,3624000000 -Virgin Islands (U.S.),VIR,2015,3765000000 -West Bank and Gaza,PSE,1994,2843300000 -West Bank and Gaza,PSE,1995,3282800000 -West Bank and Gaza,PSE,1996,3409600000 -West Bank and Gaza,PSE,1997,3759800000 -West Bank and Gaza,PSE,1998,4067800000 -West Bank and Gaza,PSE,1999,4271200000 -West Bank and Gaza,PSE,2000,4313600000 -West Bank and Gaza,PSE,2001,4003700000 -West Bank and Gaza,PSE,2002,3555800000 -West Bank and Gaza,PSE,2003,3968000000 -West Bank and Gaza,PSE,2004,4329200000 -West Bank and Gaza,PSE,2005,4831800000 -West Bank and Gaza,PSE,2006,4910100000 -West Bank and Gaza,PSE,2007,5505800000 -West Bank and Gaza,PSE,2008,6673500000 -West Bank and Gaza,PSE,2009,7268200000 -West Bank and Gaza,PSE,2010,8913100000 -West Bank and Gaza,PSE,2011,10465400000 -West Bank and Gaza,PSE,2012,11279400000 -West Bank and Gaza,PSE,2013,12476000000 -West Bank and Gaza,PSE,2014,12715600000 -West Bank and Gaza,PSE,2015,12673000000 -West Bank and Gaza,PSE,2016,13397100000 -"Yemen, Rep.",YEM,1990,5647251908.39695 -"Yemen, Rep.",YEM,1991,5930370370.37037 -"Yemen, Rep.",YEM,1992,6463649985.01648 -"Yemen, Rep.",YEM,1993,5368270614.8468 -"Yemen, Rep.",YEM,1994,4167356037.1517 -"Yemen, Rep.",YEM,1995,4258788725.44991 -"Yemen, Rep.",YEM,1996,5785685310.86668 -"Yemen, Rep.",YEM,1997,6839039029.748 -"Yemen, Rep.",YEM,1998,6325219772.93811 -"Yemen, Rep.",YEM,1999,7641101221.43876 -"Yemen, Rep.",YEM,2000,9636342274.82408 -"Yemen, Rep.",YEM,2001,9854042164.67463 -"Yemen, Rep.",YEM,2002,10693278291.8149 -"Yemen, Rep.",YEM,2003,11777768086.8693 -"Yemen, Rep.",YEM,2004,13873500887.5612 -"Yemen, Rep.",YEM,2005,16753769531.6987 -"Yemen, Rep.",YEM,2006,19081722875.3022 -"Yemen, Rep.",YEM,2007,21656517484.2538 -"Yemen, Rep.",YEM,2008,26910851361.7555 -"Yemen, Rep.",YEM,2009,25130274124.2524 -"Yemen, Rep.",YEM,2010,30906749533.221 -"Yemen, Rep.",YEM,2011,32726417878.391 -"Yemen, Rep.",YEM,2012,35401339869.3055 -"Yemen, Rep.",YEM,2013,40415233436.1767 -"Yemen, Rep.",YEM,2014,43228583935.0365 -"Yemen, Rep.",YEM,2015,37733919936.2465 -"Yemen, Rep.",YEM,2016,27317605346.0714 -Zambia,ZMB,1960,713000000 -Zambia,ZMB,1961,696285714.285714 -Zambia,ZMB,1962,693142857.142857 -Zambia,ZMB,1963,718714285.714286 -Zambia,ZMB,1964,839428571.428571 -Zambia,ZMB,1965,1082857142.85714 -Zambia,ZMB,1966,1264285714.28571 -Zambia,ZMB,1967,1368000000 -Zambia,ZMB,1968,1605857142.85714 -Zambia,ZMB,1969,1965714285.71429 -Zambia,ZMB,1970,1825285714.28571 -Zambia,ZMB,1971,1687000000 -Zambia,ZMB,1972,1910714285.71429 -Zambia,ZMB,1973,2268714285.71429 -Zambia,ZMB,1974,3121833333.33333 -Zambia,ZMB,1975,2618666666.66667 -Zambia,ZMB,1976,2746714285.71429 -Zambia,ZMB,1977,2483000000 -Zambia,ZMB,1978,2813375000 -Zambia,ZMB,1979,3325500000 -Zambia,ZMB,1980,3829500000 -Zambia,ZMB,1981,3872666666.66667 -Zambia,ZMB,1982,3994777777.77778 -Zambia,ZMB,1983,3216307692.30769 -Zambia,ZMB,1984,2739444444.44445 -Zambia,ZMB,1985,2281258064.51613 -Zambia,ZMB,1986,1661948717.94872 -Zambia,ZMB,1987,2269894736.84211 -Zambia,ZMB,1988,3713614457.83133 -Zambia,ZMB,1989,3998637681.15942 -Zambia,ZMB,1990,3285217391.30435 -Zambia,ZMB,1991,3378882352.94118 -Zambia,ZMB,1992,3181921787.7095 -Zambia,ZMB,1993,3273237853.35689 -Zambia,ZMB,1994,3656647744.24858 -Zambia,ZMB,1995,3807067121.8609 -Zambia,ZMB,1996,3597220962.00017 -Zambia,ZMB,1997,4303281932.29365 -Zambia,ZMB,1998,3537683046.02331 -Zambia,ZMB,1999,3404311976.54941 -Zambia,ZMB,2000,3600683039.73254 -Zambia,ZMB,2001,4094480988.11931 -Zambia,ZMB,2002,4193845678.17033 -Zambia,ZMB,2003,4901839731.26571 -Zambia,ZMB,2004,6221077674.77871 -Zambia,ZMB,2005,8331870169.14977 -Zambia,ZMB,2006,12756858899.2812 -Zambia,ZMB,2007,14056957976.2648 -Zambia,ZMB,2008,17910858637.9048 -Zambia,ZMB,2009,15328342303.9575 -Zambia,ZMB,2010,20265556273.582 -Zambia,ZMB,2011,23460098339.7453 -Zambia,ZMB,2012,25503370699.2015 -Zambia,ZMB,2013,28045460442.1876 -Zambia,ZMB,2014,27150630607.2032 -Zambia,ZMB,2015,21154394545.895 -Zambia,ZMB,2016,19551093303.3377 -Zimbabwe,ZWE,1960,1052990400 -Zimbabwe,ZWE,1961,1096646600 -Zimbabwe,ZWE,1962,1117601600 -Zimbabwe,ZWE,1963,1159511700 -Zimbabwe,ZWE,1964,1217138000 -Zimbabwe,ZWE,1965,1311435800 -Zimbabwe,ZWE,1966,1281749500 -Zimbabwe,ZWE,1967,1397002000 -Zimbabwe,ZWE,1968,1479599900 -Zimbabwe,ZWE,1969,1747998800 -Zimbabwe,ZWE,1970,1884206300 -Zimbabwe,ZWE,1971,2178716300 -Zimbabwe,ZWE,1972,2677729400 -Zimbabwe,ZWE,1973,3309353600 -Zimbabwe,ZWE,1974,3982161400 -Zimbabwe,ZWE,1975,4371300700 -Zimbabwe,ZWE,1976,4318372000 -Zimbabwe,ZWE,1977,4364382100 -Zimbabwe,ZWE,1978,4351600500 -Zimbabwe,ZWE,1979,5177459400 -Zimbabwe,ZWE,1980,6678868200 -Zimbabwe,ZWE,1981,8011373800 -Zimbabwe,ZWE,1982,8539700700 -Zimbabwe,ZWE,1983,7764067000 -Zimbabwe,ZWE,1984,6352125900 -Zimbabwe,ZWE,1985,5637259300 -Zimbabwe,ZWE,1986,6217523700 -Zimbabwe,ZWE,1987,6741215100 -Zimbabwe,ZWE,1988,7814784100 -Zimbabwe,ZWE,1989,8286322700 -Zimbabwe,ZWE,1990,8783816700 -Zimbabwe,ZWE,1991,8641481700 -Zimbabwe,ZWE,1992,6751472200 -Zimbabwe,ZWE,1993,6563813300 -Zimbabwe,ZWE,1994,6890675000 -Zimbabwe,ZWE,1995,7111270700 -Zimbabwe,ZWE,1996,8553146600 -Zimbabwe,ZWE,1997,8529571600 -Zimbabwe,ZWE,1998,6401968200 -Zimbabwe,ZWE,1999,6858013100 -Zimbabwe,ZWE,2000,6689957600 -Zimbabwe,ZWE,2001,6777384700 -Zimbabwe,ZWE,2002,6342116400 -Zimbabwe,ZWE,2003,5727591800 -Zimbabwe,ZWE,2004,5805598400 -Zimbabwe,ZWE,2005,5755215200 -Zimbabwe,ZWE,2006,5443896500 -Zimbabwe,ZWE,2007,5291950100 -Zimbabwe,ZWE,2008,4415702800 -Zimbabwe,ZWE,2009,8366794000 -Zimbabwe,ZWE,2010,10052045200 -Zimbabwe,ZWE,2011,12071733500 -Zimbabwe,ZWE,2012,14058378300 -Zimbabwe,ZWE,2013,15223528900 -Zimbabwe,ZWE,2014,15834069900 -Zimbabwe,ZWE,2015,16072380200 -Zimbabwe,ZWE,2016,16289212000 diff --git a/main/tests/server/src/com/google/refine/tests/ProjectManagerStub.java b/main/tests/server/src/com/google/refine/tests/ProjectManagerStub.java index 983631935..4c3ee3e86 100644 --- a/main/tests/server/src/com/google/refine/tests/ProjectManagerStub.java +++ b/main/tests/server/src/com/google/refine/tests/ProjectManagerStub.java @@ -39,9 +39,9 @@ import java.io.InputStream; import org.apache.tools.tar.TarOutputStream; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.history.HistoryEntryManager; import com.google.refine.model.Project; -import com.google.refine.model.metadata.IMetadata; /** * Stub used to make protected methods public for testing @@ -83,7 +83,7 @@ public class ProjectManagerStub extends ProjectManager { } @Override - public void saveMetadata(IMetadata metadata, long projectId) throws Exception { + public void saveMetadata(ProjectMetadata metadata, long projectId) throws Exception { // empty } @@ -103,4 +103,5 @@ public class ProjectManagerStub extends ProjectManager { protected void saveWorkspace() { // empty } + } diff --git a/main/tests/server/src/com/google/refine/tests/ProjectManagerTests.java b/main/tests/server/src/com/google/refine/tests/ProjectManagerTests.java index bfcdc2c35..0f356f7e5 100644 --- a/main/tests/server/src/com/google/refine/tests/ProjectManagerTests.java +++ b/main/tests/server/src/com/google/refine/tests/ProjectManagerTests.java @@ -51,9 +51,8 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.process.ProcessManager; import com.google.refine.tests.model.ProjectStub; @@ -74,14 +73,11 @@ public class ProjectManagerTests extends RefineTest { public void SetUp(){ pm = new ProjectManagerStub(); SUT = spy(pm); - project = mock(Project.class); metadata = mock(ProjectMetadata.class); - procmgr = mock(ProcessManager.class); when(project.getProcessManager()).thenReturn(procmgr); when(procmgr.hasPending()).thenReturn(false); // always false for now, but should test separately - when(project.getMetadata()).thenReturn(metadata); // cannot wire metadata directly with project, need mock object } @AfterMethod @@ -94,9 +90,12 @@ public class ProjectManagerTests extends RefineTest { @Test public void canRegisterProject(){ + SUT.registerProject(project, metadata); - verify(metadata).getTags(); + AssertProjectRegistered(); + verify(metadata, times(1)).getTags(); + verifyNoMoreInteractions(project); verifyNoMoreInteractions(metadata); } @@ -111,18 +110,16 @@ public class ProjectManagerTests extends RefineTest { //run test SUT.ensureProjectSaved(project.id); - //assert and verify it's registered under ProjectManager + //assert and verify AssertProjectRegistered(); - try { - // make sure the ProjectManager does save the metadata - verify(SUT).saveMetadata(metadata, project.id); + verify(SUT, times(1)).saveMetadata(metadata, project.id); } catch (Exception e) { Assert.fail(); } this.verifySaveTimeCompared(1); - verify(SUT).saveProject(project); - verify(metadata).getTags(); + verify(SUT, times(1)).saveProject(project); + verify(metadata, times(1)).getTags(); //ensure end verifyNoMoreInteractions(project); @@ -133,24 +130,25 @@ public class ProjectManagerTests extends RefineTest { @Test public void canSaveAllModified(){ - // 1. register project 1 whenGetSaveTimes(project, metadata); //5 minute difference registerProject(project, metadata); - // 2. add a second project to the cache + //add a second project to the cache Project project2 = spy(new ProjectStub(2)); ProjectMetadata metadata2 = mock(ProjectMetadata.class); whenGetSaveTimes(project2, metadata2, 10); //not modified since the last save but within 30 seconds flush limit registerProject(project2, metadata2); - // 3. check that the two projects are not the same + //check that the two projects are not the same Assert.assertFalse(project.id == project2.id); - // 4. save all projects SUT.save(true); + verifySaved(project, metadata); -// verifySaved(project2, metadata2); - verify(SUT).saveWorkspace(); + + verifySaved(project2, metadata2); + + verify(SUT, times(1)).saveWorkspace(); } @Test @@ -162,18 +160,17 @@ public class ProjectManagerTests extends RefineTest { SUT.save(true); - verify(metadata).getModified(); - verify(metadata).getTags(); - verify(project, never()).getMetadata(); - verify(project).getProcessManager(); - verify(project).getLastSave(); - verify(project).dispose(); + verify(metadata, times(1)).getModified(); + verify(metadata, times(1)).getTags(); + verify(project, times(1)).getProcessManager(); + verify(project, times(2)).getLastSave(); + verify(project, times(1)).dispose(); verify(SUT, never()).saveProject(project); Assert.assertEquals(SUT.getProject(0), null); verifyNoMoreInteractions(project); verifyNoMoreInteractions(metadata); - verify(SUT).saveWorkspace(); + verify(SUT, times(1)).saveWorkspace(); } @Test @@ -185,7 +182,7 @@ public class ProjectManagerTests extends RefineTest { verify(SUT, never()).saveProjects(Mockito.anyBoolean()); verify(SUT, never()).saveWorkspace(); - verify(metadata).getTags(); + verify(metadata, times(1)).getTags(); verifyNoMoreInteractions(project); verifyNoMoreInteractions(metadata); } @@ -200,7 +197,7 @@ public class ProjectManagerTests extends RefineTest { SUT.save(false); //not busy verifySaved(project, metadata); - verify(SUT).saveWorkspace(); + verify(SUT, times(1)).saveWorkspace(); } //TODO test canSaveAllModifiedWithRaceCondition @@ -208,11 +205,10 @@ public class ProjectManagerTests extends RefineTest { //-------------helpers------------- protected void registerProject(){ - SUT.registerProject(project, metadata); + this.registerProject(project, metadata); } - - protected void registerProject(Project proj, ProjectMetadata metadata) { - SUT.registerProject(proj, metadata); + protected void registerProject(Project proj, ProjectMetadata meta){ + SUT.registerProject(proj, meta); } protected void AssertProjectRegistered(){ @@ -248,17 +244,12 @@ public class ProjectManagerTests extends RefineTest { verify(metadata, times(times)).getModified(); verify(project, times(times)).getLastSave(); } - - /** - * @see ProjectManager#save(boolean allModified) - * @param proj - * @param meta - */ + protected void verifySaved(Project proj, ProjectMetadata meta){ - verify(meta).getModified(); - verify(proj).getLastSave(); - verify(SUT).saveProject(proj); - verify(meta).getTags(); + verify(meta, times(1)).getModified(); + verify(proj, times(2)).getLastSave(); + verify(SUT, times(1)).saveProject(proj); + verify(meta, times(1)).getTags(); verifyNoMoreInteractions(proj); verifyNoMoreInteractions(meta); diff --git a/main/tests/server/src/com/google/refine/tests/RefineTest.java b/main/tests/server/src/com/google/refine/tests/RefineTest.java index a4429c74b..769bba1ed 100644 --- a/main/tests/server/src/com/google/refine/tests/RefineTest.java +++ b/main/tests/server/src/com/google/refine/tests/RefineTest.java @@ -60,6 +60,7 @@ import com.fasterxml.jackson.databind.node.IntNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.importers.SeparatorBasedImporter; import com.google.refine.importing.ImportingJob; @@ -70,7 +71,6 @@ import com.google.refine.model.Column; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.util.TestUtils; import com.google.refine.util.JSONUtilities; diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java index 5d9b14baf..3fd556b40 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java @@ -44,11 +44,11 @@ import org.testng.annotations.Test; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; +import com.google.refine.model.ModelException; +import com.google.refine.model.Project; import com.google.refine.browsing.RowFilter; import com.google.refine.browsing.facets.TextSearchFacet; import com.google.refine.browsing.facets.TextSearchFacet.TextSearchFacetConfig; -import com.google.refine.model.ModelException; -import com.google.refine.model.Project; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; import com.google.refine.util.ParsingUtilities; diff --git a/main/tests/server/src/com/google/refine/tests/commands/project/SetProjectMetadataCommandTests.java b/main/tests/server/src/com/google/refine/tests/commands/project/SetProjectMetadataCommandTests.java index 9647684ba..0e8ae9a2c 100644 --- a/main/tests/server/src/com/google/refine/tests/commands/project/SetProjectMetadataCommandTests.java +++ b/main/tests/server/src/com/google/refine/tests/commands/project/SetProjectMetadataCommandTests.java @@ -33,7 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.tests.commands.project; -import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Matchers.anyLong; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -57,9 +57,9 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.commands.project.SetProjectMetadataCommand; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.RefineTest; public class SetProjectMetadataCommandTests extends RefineTest { @@ -102,8 +102,6 @@ public class SetProjectMetadataCommandTests extends RefineTest { // mock dependencies when(request.getParameter("project")).thenReturn(PROJECT_ID); when(projMan.getProject(anyLong())).thenReturn(proj); - - // below two should return the same object when(proj.getMetadata()).thenReturn(metadata); try { @@ -143,7 +141,7 @@ public class SetProjectMetadataCommandTests extends RefineTest { } // verify - verify(request, times(1)).getParameter("name"); + verify(request, times(2)).getParameter("project"); verify(projMan, times(1)).getProject(PROJECT_ID_LONG); verify(response, times(1)) @@ -156,7 +154,6 @@ public class SetProjectMetadataCommandTests extends RefineTest { } verify(pw, times(1)).write("{ \"code\" : \"ok\" }"); -// Assert.assertEquals(proj.getProjectMetadata().getName(), "subject"); Assert.assertEquals(proj.getMetadata().getSubject(), SUBJECT); } @@ -192,7 +189,7 @@ public class SetProjectMetadataCommandTests extends RefineTest { } verify(pw, times(1)).write("{ \"code\" : \"ok\" }"); - JSONObject obj = (JSONObject) ((ProjectMetadata)proj.getMetadata()).getUserMetadata().get(0); + JSONObject obj = (JSONObject) proj.getMetadata().getUserMetadata().get(0); Assert.assertEquals(obj.get("name"), "clientID"); Assert.assertEquals(obj.get("value"), "IBM"); } diff --git a/main/tests/server/src/com/google/refine/tests/commands/project/ValidateOperationTests.java b/main/tests/server/src/com/google/refine/tests/commands/project/ValidateOperationTests.java deleted file mode 100644 index 8582d657c..000000000 --- a/main/tests/server/src/com/google/refine/tests/commands/project/ValidateOperationTests.java +++ /dev/null @@ -1,269 +0,0 @@ -package com.google.refine.tests.commands.project; - -import static org.mockito.Mockito.mock; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.StringReader; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.everit.json.schema.ValidationException; -import org.json.JSONException; -import org.json.JSONObject; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.BDDMockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.testng.Assert; - -import com.google.refine.ProjectManager; -import com.google.refine.importers.SeparatorBasedImporter; -import com.google.refine.model.Column; -import com.google.refine.model.metadata.DataPackageMetadata; -import com.google.refine.model.metadata.MetadataFactory; -import com.google.refine.model.metadata.MetadataFormat; -import com.google.refine.model.metadata.validator.ValidateOperation; -import com.google.refine.tests.importers.TsvCsvImporterTests; -import com.google.refine.util.ParsingUtilities; - -import io.frictionlessdata.tableschema.Field; -import io.frictionlessdata.tableschema.exceptions.ForeignKeyException; -import io.frictionlessdata.tableschema.exceptions.PrimaryKeyException; - -@RunWith(PowerMockRunner.class) -@PrepareForTest(MetadataFactory.class) -public class ValidateOperationTests extends TsvCsvImporterTests { - private SeparatorBasedImporter parser = null; - - // variables - private static String input; - private DataPackageMetadata dataPackageMetadata; - - // mocks - private ProjectManager projMan = null; - - private String optionsString; - - @BeforeClass - public static void readData() throws IOException{ - //create input to test with - input = getFileContent("gdp.csv"); - // create an data type issue on the fly - input = input.replace("28434203615.4795", "XXXXXXXXXXXXX"); -// String input = "Country Name,Country Code,Year,Value\n" + -// "Arab World,ARB,1968,25760683041.0826\n" + -// "China, CHN,1968,16289212000\n" + -// "Arab World,ARB,1969,28434203615.4795XXX\n"; - } - - @Before - public void SetUp() throws JSONException, IOException, ValidationException, PrimaryKeyException, ForeignKeyException { - super.setUp(); - - optionsString = "{\"columnNames\": [\"Country Name\",\"Country Code\",\"Year\",\"Value\"]}"; - - // mockup - projMan = mock(ProjectManager.class); - ProjectManager.singleton = projMan; - - dataPackageMetadata = new DataPackageMetadata(); - String content = getJSONContent("datapackage-sample.json"); - dataPackageMetadata.loadFromStream(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8.name()))); - - // mock dependencies - //given - PowerMockito.mockStatic(MetadataFactory.class); - BDDMockito.given(MetadataFactory.buildMetadata(MetadataFormat.DATAPACKAGE_METADATA)).willReturn(dataPackageMetadata); - - parser = new SeparatorBasedImporter(); - parseOneFile(); - } - - @After - public void TearDown() { - projMan = null; - ProjectManager.singleton = null; - project = null; - } - - /** - * type or format error - */ - @Test - public void testTypeorFormatError() { - JSONObject optionObj = new JSONObject(optionsString); - // run - JSONObject result = startValidateOperation(optionObj); - - Assert.assertTrue(result.getJSONArray("validation-reports").length() > 0, - "should get records in report"); - } - - @Test - public void testMinimumConstraint() { - // options - optionsString = "{\"columnNames\": [\"Year\"]}"; - JSONObject optionObj = new JSONObject(optionsString); - - // add Constraint - String contraintKey = Field.CONSTRAINT_KEY_MINIMUM; - String contraintValue = "1962"; - Column column = project.columnModel.getColumnByName("Year"); - column.setType(Field.FIELD_TYPE_STRING); - addConstraint(column, contraintKey, contraintValue); - - // run - JSONObject result = startValidateOperation(optionObj); - - Assert.assertTrue(result.getJSONArray("validation-reports").length() > 0, - "should get records in report"); - } - - @Test - public void testMaximumConstraint() { - // options - optionsString = "{\"columnNames\": [\"Year\"]}"; - JSONObject optionObj = new JSONObject(optionsString); - - // add Constraint - String contraintKey = Field.CONSTRAINT_KEY_MAXIMUM; - String contraintValue = "2015"; - Column column = project.columnModel.getColumnByName("Year"); - column.setType(Field.FIELD_TYPE_STRING); - addConstraint(column, contraintKey, contraintValue); - - // run - JSONObject result = startValidateOperation(optionObj); - - Assert.assertTrue(result.getJSONArray("validation-reports").length() > 0, - "should get records in report"); - } - - @Test - public void testPatternConstraint() { - // options - optionsString = "{\"columnNames\": [\"Year\"]}"; - JSONObject optionObj = new JSONObject(optionsString); - - // add Constraint - String contraintKey = Field.CONSTRAINT_KEY_PATTERN; - String contraintValue = "[0-9]{4}"; - Column column = project.columnModel.getColumnByName("Year"); - column.setType(Field.FIELD_TYPE_STRING); - addConstraint(column, contraintKey, contraintValue); - - // run - JSONObject result = startValidateOperation(optionObj); - - Assert.assertTrue(result.getJSONArray("validation-reports").length() == 0, - "should NOT get records in re" - + "port"); - } - - @Test - public void testEnumerableConstraint() { - // options - optionsString = "{\"columnNames\": [\"Year\"]}"; - JSONObject optionObj = new JSONObject(optionsString); - - // add Constraint - String contraintKey = Field.CONSTRAINT_KEY_ENUM; - String contraintValueStr = "[\"2010\",\"1990\",\"2015\"]"; - List contraintValue = ParsingUtilities.evaluateJsonStringToArray(contraintValueStr).toList(); - Column column = project.columnModel.getColumnByName("Year"); - column.setType(Field.FIELD_TYPE_STRING); - addConstraint(column, contraintKey, contraintValue); - - // run - JSONObject result = startValidateOperation(optionObj); - - Assert.assertTrue(result.getJSONArray("validation-reports").length() > 0, - "should get records in report"); - } - - @Test - public void testEnumerableConstraint_ShouldReturnEmpty() { - // options - optionsString = "{\"columnNames\": [\"Year\"]}"; - JSONObject optionObj = new JSONObject(optionsString); - - // add Constraint - String contraintKey = Field.CONSTRAINT_KEY_ENUM; - String contraintValueStr = "["; - for (int i = 1950;i < 2018;i++) { - contraintValueStr += "\"" + i + "\","; - } - contraintValueStr += "]"; - - List contraintValue = ParsingUtilities.evaluateJsonStringToArray(contraintValueStr).toList(); - Column column = project.columnModel.getColumnByName("Year"); - column.setType(Field.FIELD_TYPE_STRING); - addConstraint(column, contraintKey, contraintValue); - - // run - JSONObject result = startValidateOperation(optionObj); - - Assert.assertEquals(result.getJSONArray("validation-reports").length(), 0); - } - - - private void addConstraint(Column column, String contraintKey, Object contraintValue) { - java.lang.reflect.Field f1; - try { - f1 = column.getClass().getDeclaredField("constraints"); - f1.setAccessible(true); - Map existingMap = (HashMap)f1.get(column); - if (existingMap == null) { - existingMap = new HashMap(); - } - existingMap.put(contraintKey, contraintValue); - f1.set(column, existingMap); - } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { - e.printStackTrace(); - } - } - - - private JSONObject startValidateOperation(JSONObject options) { - // SUT - JSONObject report = new ValidateOperation(project, options).startProcess(); - - System.out.println("validation report:" + report.toString(2)); - - return report; - } - - private String getJSONContent(String fileName) throws IOException { - InputStream in = this.getClass().getClassLoader() - .getResourceAsStream(fileName); - String content = org.apache.commons.io.IOUtils.toString(in); - - return content; - } - - - private void parseOneFile() throws IOException{ - String sep = ","; - prepareOptions(sep, -1, 0, 0, 1, false, false); - parseOneFile(parser, new StringReader(input)); - - Assert.assertEquals(project.columnModel.columns.size(), 4); - } - - private static String getFileContent(String fileName) throws IOException { - InputStream in = ValidateOperationTests.class.getClassLoader() - .getResourceAsStream(fileName); - String content = org.apache.commons.io.IOUtils.toString(in); - - return content; - } -} diff --git a/main/tests/server/src/com/google/refine/tests/exporters/CsvExporterTests.java b/main/tests/server/src/com/google/refine/tests/exporters/CsvExporterTests.java index 789823d1b..88b37809c 100644 --- a/main/tests/server/src/com/google/refine/tests/exporters/CsvExporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/exporters/CsvExporterTests.java @@ -42,7 +42,6 @@ import java.io.IOException; import java.io.StringWriter; import java.util.Properties; -import org.apache.commons.lang3.StringUtils; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.AfterMethod; @@ -231,8 +230,13 @@ public class CsvExporterTests extends RefineTest { Assert.fail(); } +<<<<<<< HEAD String expectedOutput = ParsingUtilities.instantToLocalDateTimeString(calendar.toInstant()) + "," + ParsingUtilities.instantToLocalDateTimeString(date.toInstant()) + "\n"; +======= + String expectedOutput = ParsingUtilities.localDateToString(localDate) + "," + + ParsingUtilities.dateToString(date) + "\n"; +>>>>>>> parent of c4b0ff6be... data package metadata (#1398) Assert.assertEquals(writer.toString(), expectedOutput); } @@ -260,36 +264,4 @@ public class CsvExporterTests extends RefineTest { project.rows.add(row); } } - - /** - * Given 2017-12-15T22:30:36.65(Z), convert to 2017-12-15T22:30:36.650(Z) - * @param dateTime - * @return - */ - protected String alignFractionalDigits(String dateTime) { - String[] parts = dateTime.split("\\."); - if (parts.length < 2) - return dateTime; - - String fraction = parts[1].replace("Z", ""); - - return parts[0] + "." + - StringUtils.rightPad(fraction, 3, "0") + - (dateTime.endsWith("Z") ? "Z" : ""); - } - - @Test - public void alignFractionalDigitsTest(){ - String input = "2017-12-15T22:30:36.65"; - String expected = "2017-12-15T22:30:36.650"; - Assert.assertEquals(alignFractionalDigits(input), expected); - } - - @Test - public void alignFractionalDigitsWithZTest(){ - String input = "2017-12-15T22:30:36.65Z"; - String expected = "2017-12-15T22:30:36.650Z"; - Assert.assertEquals(alignFractionalDigits(input), expected); - } - } diff --git a/main/tests/server/src/com/google/refine/tests/exporters/HtmlExporterTests.java b/main/tests/server/src/com/google/refine/tests/exporters/HtmlExporterTests.java index 252808a93..4c49d075d 100644 --- a/main/tests/server/src/com/google/refine/tests/exporters/HtmlExporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/exporters/HtmlExporterTests.java @@ -50,6 +50,7 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.browsing.Engine; import com.google.refine.exporters.HtmlTableExporter; import com.google.refine.exporters.WriterExporter; @@ -58,7 +59,6 @@ import com.google.refine.model.Column; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.ProjectManagerStub; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/exporters/TemplatingExporterTests.java b/main/tests/server/src/com/google/refine/tests/exporters/TemplatingExporterTests.java index 439b2e22c..d9830a067 100644 --- a/main/tests/server/src/com/google/refine/tests/exporters/TemplatingExporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/exporters/TemplatingExporterTests.java @@ -48,6 +48,7 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.browsing.Engine; import com.google.refine.exporters.TemplatingExporter; import com.google.refine.exporters.WriterExporter; @@ -56,7 +57,6 @@ import com.google.refine.model.Column; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.ProjectManagerStub; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/exporters/XlsExporterTests.java b/main/tests/server/src/com/google/refine/tests/exporters/XlsExporterTests.java index a3a64b7a6..53060e916 100644 --- a/main/tests/server/src/com/google/refine/tests/exporters/XlsExporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/exporters/XlsExporterTests.java @@ -51,6 +51,7 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.browsing.Engine; import com.google.refine.exporters.StreamExporter; import com.google.refine.exporters.XlsExporter; @@ -59,7 +60,6 @@ import com.google.refine.model.Column; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.ProjectManagerStub; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/exporters/sql/SqlExporterTests.java b/main/tests/server/src/com/google/refine/tests/exporters/sql/SqlExporterTests.java index 9243596be..68198fb38 100644 --- a/main/tests/server/src/com/google/refine/tests/exporters/sql/SqlExporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/exporters/sql/SqlExporterTests.java @@ -58,6 +58,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.browsing.Engine; import com.google.refine.exporters.sql.SqlCreateBuilder; import com.google.refine.exporters.sql.SqlData; @@ -68,7 +69,6 @@ import com.google.refine.model.Column; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.ProjectManagerStub; import com.google.refine.tests.RefineTest; import com.google.refine.util.ParsingUtilities; diff --git a/main/tests/server/src/com/google/refine/tests/history/HistoryTests.java b/main/tests/server/src/com/google/refine/tests/history/HistoryTests.java index 81641b3fa..7a79b7530 100644 --- a/main/tests/server/src/com/google/refine/tests/history/HistoryTests.java +++ b/main/tests/server/src/com/google/refine/tests/history/HistoryTests.java @@ -48,11 +48,11 @@ import org.testng.annotations.Test; import com.google.refine.ProjectManager; import com.google.refine.history.Change; +import com.google.refine.ProjectMetadata; import com.google.refine.history.History; import com.google.refine.history.HistoryEntry; import com.google.refine.history.HistoryEntryManager; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; diff --git a/main/tests/server/src/com/google/refine/tests/importers/ImporterTest.java b/main/tests/server/src/com/google/refine/tests/importers/ImporterTest.java index 58704b353..053550d4a 100644 --- a/main/tests/server/src/com/google/refine/tests/importers/ImporterTest.java +++ b/main/tests/server/src/com/google/refine/tests/importers/ImporterTest.java @@ -12,6 +12,7 @@ import java.util.List; import org.mockito.Mockito; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.importers.ImportingParserBase; import com.google.refine.importers.tree.ImportColumnGroup; @@ -20,12 +21,11 @@ import com.google.refine.importers.tree.XmlImportUtilities; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingManager; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.RefineServletStub; import com.google.refine.tests.RefineTest; import com.google.refine.util.ParsingUtilities; -abstract public class ImporterTest extends RefineTest { +abstract class ImporterTest extends RefineTest { //mock dependencies protected Project project; protected ProjectMetadata metadata; diff --git a/main/tests/server/src/com/google/refine/tests/importers/JsonImporterTests.java b/main/tests/server/src/com/google/refine/tests/importers/JsonImporterTests.java index b893d3834..6942235ba 100644 --- a/main/tests/server/src/com/google/refine/tests/importers/JsonImporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/importers/JsonImporterTests.java @@ -97,6 +97,7 @@ public class JsonImporterTests extends ImporterTest { public void canParseSample(){ RunTest(getSample()); + log(project); assertProjectCreated(project, 4, 6); Row row = project.rows.get(0); @@ -109,6 +110,7 @@ public class JsonImporterTests extends ImporterTest { public void canParseSampleWithDuplicateNestedElements(){ RunTest(getSampleWithDuplicateNestedElements()); + log(project); assertProjectCreated(project, 4, 12); Row row = project.rows.get(0); @@ -124,6 +126,7 @@ public class JsonImporterTests extends ImporterTest { RunTest(getSampleWithLineBreak()); + log(project); assertProjectCreated(project, 4, 6); Row row = project.rows.get(3); @@ -137,6 +140,7 @@ public class JsonImporterTests extends ImporterTest { public void testElementsWithVaryingStructure(){ RunTest(getSampleWithVaryingStructure()); + log(project); assertProjectCreated(project, 5, 6); Assert.assertEquals( project.columnModel.getColumnByCellIndex(4).getName(), JsonImporter.ANONYMOUS + " - genre"); @@ -153,6 +157,7 @@ public class JsonImporterTests extends ImporterTest { @Test public void testElementWithNestedTree(){ RunTest(getSampleWithTreeStructure()); + log(project); assertProjectCreated(project, 5, 6); Assert.assertEquals(project.columnModel.columnGroups.size(),1); @@ -176,6 +181,7 @@ public class JsonImporterTests extends ImporterTest { JSONUtilities.safePut(options, "recordPath", path); RunTest(mqlOutput, options); + log(project); assertProjectCreated(project,3,16); } @@ -209,6 +215,7 @@ public class JsonImporterTests extends ImporterTest { " }\n" + "]\n"; RunTest(ScraperwikiOutput); + log(project); assertProjectCreated(project,9,2); } @@ -293,6 +300,7 @@ public class JsonImporterTests extends ImporterTest { public void testJsonDatatypes(){ RunTest(getSampleWithDataTypes()); + log(project); assertProjectCreated(project, 2, 21,4); Assert.assertEquals( project.columnModel.getColumnByCellIndex(0).getName(), JsonImporter.ANONYMOUS + " - id"); @@ -363,6 +371,7 @@ public class JsonImporterTests extends ImporterTest { String fileName = "grid_small.json"; RunComplexJSONTest(getComplexJSON(fileName)); + log(project); logger.info("************************ columnu number:" + project.columnModel.columns.size() + ". \tcolumn groups number:" + project.columnModel.columnGroups.size() + ".\trow number:" + project.rows.size() + ".\trecord number:" + project.recordModel.getRecordCount()) ; diff --git a/main/tests/server/src/com/google/refine/tests/importers/TsvCsvImporterTests.java b/main/tests/server/src/com/google/refine/tests/importers/TsvCsvImporterTests.java index 8481a98d6..98107678d 100644 --- a/main/tests/server/src/com/google/refine/tests/importers/TsvCsvImporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/importers/TsvCsvImporterTests.java @@ -55,10 +55,10 @@ public class TsvCsvImporterTests extends ImporterTest { } //constants - private String SAMPLE_ROW = "NDB_No,Shrt_Desc,Water"; + String SAMPLE_ROW = "NDB_No,Shrt_Desc,Water"; //System Under Test - private SeparatorBasedImporter SUT = null; + SeparatorBasedImporter SUT = null; @Override @BeforeMethod @@ -590,7 +590,7 @@ public class TsvCsvImporterTests extends ImporterTest { prepareOptions(sep, limit, skip, ignoreLines, headerLines, guessValueType, ignoreQuotes, "\""); } - protected void prepareOptions( + private void prepareOptions( String sep, int limit, int skip, int ignoreLines, int headerLines, boolean guessValueType, boolean ignoreQuotes, String quoteCharacter) { diff --git a/main/tests/server/src/com/google/refine/tests/importing/ImportingUtilitiesTests.java b/main/tests/server/src/com/google/refine/tests/importing/ImportingUtilitiesTests.java index 0edd996d8..8a305224b 100644 --- a/main/tests/server/src/com/google/refine/tests/importing/ImportingUtilitiesTests.java +++ b/main/tests/server/src/com/google/refine/tests/importing/ImportingUtilitiesTests.java @@ -1,7 +1,6 @@ package com.google.refine.tests.importing; -import java.io.InputStream; import java.util.LinkedList; import org.testng.Assert; @@ -10,12 +9,10 @@ import org.testng.annotations.Test; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.refine.importers.XmlImporter; +import com.google.refine.ProjectMetadata; import com.google.refine.importers.tree.TreeImportingParserBase; import com.google.refine.importing.ImportingJob; -import com.google.refine.importing.ImportingManager; import com.google.refine.importing.ImportingUtilities; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.importers.ImporterTest; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; @@ -38,28 +35,6 @@ public class ImportingUtilitiesTests extends ImporterTest { Assert.assertEquals(pm.getEncoding(), "UTF-8"); Assert.assertTrue(pm.getTags().length == 0); } - - @Test - public void inferColumnTypeTest() - throws Exception { - ImportingManager.registerFormat("text/xml", "XML files", "XmlParserUI", new com.google.refine.importers.XmlImporter()); - XmlImporter xmlImporter = new XmlImporter(); - String fileName = "jorf.xml"; - InputStream in = this.getClass().getClassLoader() - .getResourceAsStream(fileName); - options = getNestedOptions(job, xmlImporter); - job.getRetrievalRecord(); - - parseOneInputStream(new XmlImporter(), - in, - options); - - ImportingUtilities.inferColumnType(project); - - Assert.assertTrue(project.columnModel.columns.size() == 58); - Assert.assertTrue(project.columnModel.getColumnByName("result - source_id").getType().equals("string")); - Assert.assertTrue(project.columnModel.getColumnByName("result - person - sexe").getType().equals("boolean")); - } private ObjectNode getNestedOptions(ImportingJob job, TreeImportingParserBase parser) { ObjectNode options = parser.createParserUIInitializationData( diff --git a/main/tests/server/src/com/google/refine/tests/io/FileProjectManagerTests.java b/main/tests/server/src/com/google/refine/tests/io/FileProjectManagerTests.java index 8d7294e1d..9ebe0d81c 100644 --- a/main/tests/server/src/com/google/refine/tests/io/FileProjectManagerTests.java +++ b/main/tests/server/src/com/google/refine/tests/io/FileProjectManagerTests.java @@ -9,8 +9,8 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.google.refine.io.FileProjectManager; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.tests.util.TestUtils; +import com.google.refine.ProjectMetadata; public class FileProjectManagerTests { protected File workspaceDir; diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java index a80bca841..5177b9298 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java @@ -52,6 +52,7 @@ import org.testng.annotations.Test; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.refine.ProjectManager; +import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.importers.SeparatorBasedImporter; import com.google.refine.importing.ImportingJob; @@ -60,7 +61,6 @@ import com.google.refine.io.FileProjectManager; import com.google.refine.model.AbstractOperation; import com.google.refine.model.ModelException; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.cell.KeyValueColumnizeOperation; import com.google.refine.process.Process; diff --git a/main/tests/server/src/com/google/refine/tests/process/HistoryProcessTests.java b/main/tests/server/src/com/google/refine/tests/process/HistoryProcessTests.java index 0c4da94da..881aa0acf 100644 --- a/main/tests/server/src/com/google/refine/tests/process/HistoryProcessTests.java +++ b/main/tests/server/src/com/google/refine/tests/process/HistoryProcessTests.java @@ -11,7 +11,7 @@ import com.google.refine.history.HistoryEntry; import com.google.refine.history.HistoryProcess; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; -import com.google.refine.model.metadata.ProjectMetadata; +import com.google.refine.ProjectMetadata; import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; diff --git a/main/webapp/modules/core/MOD-INF/controller.js b/main/webapp/modules/core/MOD-INF/controller.js index f20b0db84..75a975104 100644 --- a/main/webapp/modules/core/MOD-INF/controller.js +++ b/main/webapp/modules/core/MOD-INF/controller.js @@ -65,12 +65,10 @@ function registerCommands() { RS.registerCommand(module, "import-project", new Packages.com.google.refine.commands.project.ImportProjectCommand()); RS.registerCommand(module, "export-project", new Packages.com.google.refine.commands.project.ExportProjectCommand()); RS.registerCommand(module, "export-rows", new Packages.com.google.refine.commands.project.ExportRowsCommand()); - RS.registerCommand(module, "project-data-package", new Packages.com.google.refine.commands.project.PackageProjectCommand()); RS.registerCommand(module, "get-project-metadata", new Packages.com.google.refine.commands.project.GetProjectMetadataCommand()); RS.registerCommand(module, "get-all-project-metadata", new Packages.com.google.refine.commands.workspace.GetAllProjectMetadataCommand()); RS.registerCommand(module, "set-metaData", new Packages.com.google.refine.commands.project.SetProjectMetadataCommand()); - RS.registerCommand(module, "get-imetaData", new Packages.com.google.refine.commands.project.GetMetadataCommand()); RS.registerCommand(module, "get-all-project-tags", new Packages.com.google.refine.commands.workspace.GetAllProjectTagsCommand()); RS.registerCommand(module, "set-project-tags", new Packages.com.google.refine.commands.project.SetProjectTagsCommand()); @@ -294,8 +292,6 @@ function registerImporting() { IM.registerMimeType("application/marc", "text/marc"); - IM.registerUrlRewriter(new Packages.com.google.refine.model.metadata.DataPackageUrlRewriter()); - /* * Format guessers: these take a format derived from extensions or mime-types, * look at the actual files' content, and try to guess a better format. @@ -342,7 +338,6 @@ function init() { "externals/jquery.i18n.js", "externals/tablesorter/jquery.tablesorter.min.js", "externals/moment-with-locales.min.js", - "externals/jsoneditor/jsoneditor.js", "externals/select2/select2.min.js", "externals/jquery.lavalamp.min.js", "externals/jquery.i18n.messagestore.js", @@ -385,8 +380,7 @@ function init() { "scripts/index/parser-interfaces/wikitext-parser-ui.js", "scripts/reconciliation/recon-manager.js", // so that reconciliation functions are available to importers - "scripts/index/edit-metadata-dialog.js", - "scripts/project/edit-general-metadata-dialog.js" + "scripts/index/edit-metadata-dialog.js" ] ); @@ -402,7 +396,6 @@ function init() { "styles/pure.css", "styles/util/dialog.less", "styles/util/encoding.less", - "externals/jsoneditor/jsoneditor.css", "styles/index.less", "styles/index/create-project-ui.less", @@ -418,7 +411,7 @@ function init() { "styles/index/fixed-width-parser-ui.less", "styles/index/xml-parser-ui.less", "styles/index/json-parser-ui.less", - "styles/index/wikitext-parser-ui.less" + "styles/index/wikitext-parser-ui.less", ] ); @@ -439,7 +432,6 @@ function init() { "externals/jquery.i18n.emitter.js", "externals/jquery.i18n.language.js", "externals/underscore-min.js", - "externals/jsoneditor/jsoneditor.js", "scripts/project.js", @@ -493,7 +485,6 @@ function init() { "scripts/dialogs/custom-tabular-exporter-dialog.js", "scripts/dialogs/sql-exporter-dialog.js", "scripts/dialogs/expression-column-dialog.js", - "scripts/project/edit-general-metadata-dialog.js", "scripts/dialogs/http-headers-dialog.js", ] ); @@ -505,7 +496,6 @@ function init() { "externals/suggest/css/suggest-4_3.min.css", "externals/jquery-ui/css/ui-lightness/jquery-ui-1.10.3.custom.css", "externals/imgareaselect/css/imgareaselect-default.css", - "externals/jsoneditor/jsoneditor.css", "styles/jquery-ui-overrides.less", "styles/common.less", diff --git a/main/webapp/modules/core/externals/jsoneditor/img/jsoneditor-icons.png b/main/webapp/modules/core/externals/jsoneditor/img/jsoneditor-icons.png deleted file mode 100644 index c9ae20b469a7f54bc5623db8abe26f1b6a85771e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5287 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 Hg@^nHo+l4_ diff --git a/main/webapp/modules/core/externals/jsoneditor/img/jsoneditor-icons.svg b/main/webapp/modules/core/externals/jsoneditor/img/jsoneditor-icons.svg deleted file mode 100644 index 9e48bdcb0..000000000 --- a/main/webapp/modules/core/externals/jsoneditor/img/jsoneditor-icons.svg +++ /dev/null @@ -1,899 +0,0 @@ - - - JSON Editor Icons - - - - image/svg+xml - - JSON Editor Icons - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/main/webapp/modules/core/externals/jsoneditor/jsoneditor.css b/main/webapp/modules/core/externals/jsoneditor/jsoneditor.css deleted file mode 100644 index a490eb3db..000000000 --- a/main/webapp/modules/core/externals/jsoneditor/jsoneditor.css +++ /dev/null @@ -1,1065 +0,0 @@ -/* reset styling (prevent conflicts with bootstrap, materialize.css, etc.) */ - -div.jsoneditor .jsoneditor-search input { - height: auto; - border: inherit; -} - -div.jsoneditor .jsoneditor-search input:focus { - border: none !important; - box-shadow: none !important; -} - -div.jsoneditor table { - border-collapse: collapse; - width: auto; -} - -div.jsoneditor td, -div.jsoneditor th { - padding: 0; - display: table-cell; - text-align: left; - vertical-align: inherit; - border-radius: inherit; -} - - -div.jsoneditor-field, -div.jsoneditor-value, -div.jsoneditor-readonly { - border: 1px solid transparent; - min-height: 16px; - min-width: 32px; - padding: 2px; - margin: 1px; - word-wrap: break-word; - float: left; -} - -/* adjust margin of p elements inside editable divs, needed for Opera, IE */ - -div.jsoneditor-field p, -div.jsoneditor-value p { - margin: 0; -} - -div.jsoneditor-value { - word-break: break-word; -} - -div.jsoneditor-readonly { - min-width: 16px; - color: gray; -} - -div.jsoneditor-empty { - border-color: lightgray; - border-style: dashed; - border-radius: 2px; -} - -div.jsoneditor-field.jsoneditor-empty::after, -div.jsoneditor-value.jsoneditor-empty::after { - pointer-events: none; - color: lightgray; - font-size: 8pt; -} - -div.jsoneditor-field.jsoneditor-empty::after { - content: "field"; -} - -div.jsoneditor-value.jsoneditor-empty::after { - content: "value"; -} - -div.jsoneditor-value.jsoneditor-url, -a.jsoneditor-value.jsoneditor-url { - color: green; - text-decoration: underline; -} - -a.jsoneditor-value.jsoneditor-url { - display: inline-block; - padding: 2px; - margin: 2px; -} - -a.jsoneditor-value.jsoneditor-url:hover, -a.jsoneditor-value.jsoneditor-url:focus { - color: #ee422e; -} - -div.jsoneditor td.jsoneditor-separator { - padding: 3px 0; - vertical-align: top; - color: gray; -} - -div.jsoneditor-field[contenteditable=true]:focus, -div.jsoneditor-field[contenteditable=true]:hover, -div.jsoneditor-value[contenteditable=true]:focus, -div.jsoneditor-value[contenteditable=true]:hover, -div.jsoneditor-field.jsoneditor-highlight, -div.jsoneditor-value.jsoneditor-highlight { - background-color: #FFFFAB; - border: 1px solid yellow; - border-radius: 2px; -} - -div.jsoneditor-field.jsoneditor-highlight-active, -div.jsoneditor-field.jsoneditor-highlight-active:focus, -div.jsoneditor-field.jsoneditor-highlight-active:hover, -div.jsoneditor-value.jsoneditor-highlight-active, -div.jsoneditor-value.jsoneditor-highlight-active:focus, -div.jsoneditor-value.jsoneditor-highlight-active:hover { - background-color: #ffee00; - border: 1px solid #ffc700; - border-radius: 2px; -} - -div.jsoneditor-value.jsoneditor-string { - color: #008000; -} - -div.jsoneditor-value.jsoneditor-object, -div.jsoneditor-value.jsoneditor-array { - min-width: 16px; - color: #808080; -} - -div.jsoneditor-value.jsoneditor-number { - color: #ee422e; -} - -div.jsoneditor-value.jsoneditor-boolean { - color: #ff8c00; -} - -div.jsoneditor-value.jsoneditor-null { - color: #004ED0; -} - -div.jsoneditor-value.jsoneditor-invalid { - color: #000000; -} - -div.jsoneditor-tree button { - width: 24px; - height: 24px; - padding: 0; - margin: 0; - border: none; - cursor: pointer; - background: transparent url("img/jsoneditor-icons.png"); -} - -div.jsoneditor-mode-view tr.jsoneditor-expandable td.jsoneditor-tree, -div.jsoneditor-mode-form tr.jsoneditor-expandable td.jsoneditor-tree { - cursor: pointer; -} - -div.jsoneditor-tree button.jsoneditor-collapsed { - background-position: 0 -48px; -} - -div.jsoneditor-tree button.jsoneditor-expanded { - background-position: 0 -72px; -} - -div.jsoneditor-tree button.jsoneditor-contextmenu { - background-position: -48px -72px; -} - -div.jsoneditor-tree button.jsoneditor-contextmenu:hover, -div.jsoneditor-tree button.jsoneditor-contextmenu:focus, -div.jsoneditor-tree button.jsoneditor-contextmenu.jsoneditor-selected, -tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu { - background-position: -48px -48px; -} - -div.jsoneditor-tree *:focus { - outline: none; -} - -div.jsoneditor-tree button:focus { - /* TODO: nice outline for buttons with focus - outline: #97B0F8 solid 2px; - box-shadow: 0 0 8px #97B0F8; - */ - background-color: #f5f5f5; - outline: #e5e5e5 solid 1px; -} - -div.jsoneditor-tree button.jsoneditor-invisible { - visibility: hidden; - background: none; -} - -div.jsoneditor { - color: #1A1A1A; - border: 1px solid #3883fa; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - width: 100%; - height: 100%; - position: relative; - padding: 0; - line-height: 100%; -} - -div.jsoneditor-tree table.jsoneditor-tree { - border-collapse: collapse; - border-spacing: 0; - width: 100%; - margin: 0; -} - -div.jsoneditor-outer { - position: static; - width: 100%; - height: 100%; - margin: -35px 0 0 0; - padding: 35px 0 0 0; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; -} - -div.jsoneditor-outer.has-nav-bar { - margin: -61px 0 0 0; - padding: 61px 0 0 0; -} - -div.jsoneditor-outer.has-status-bar { - margin: -35px 0 -26px 0; - padding: 35px 0 26px 0; -} - -textarea.jsoneditor-text, -.ace-jsoneditor { - min-height: 150px; -} - -div.jsoneditor-tree { - width: 100%; - height: 100%; - position: relative; - overflow: auto; -} - -textarea.jsoneditor-text { - width: 100%; - height: 100%; - margin: 0; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - outline-width: 0; - border: none; - background-color: white; - resize: none; -} - -tr.jsoneditor-highlight, -tr.jsoneditor-selected { - background-color: #d3d3d3; -} - -tr.jsoneditor-selected button.jsoneditor-dragarea, -tr.jsoneditor-selected button.jsoneditor-contextmenu { - visibility: hidden; -} - -tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea, -tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu { - visibility: visible; -} - -div.jsoneditor-tree button.jsoneditor-dragarea { - background: url("img/jsoneditor-icons.png") -72px -72px; - cursor: move; -} - -div.jsoneditor-tree button.jsoneditor-dragarea:hover, -div.jsoneditor-tree button.jsoneditor-dragarea:focus, -tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea { - background-position: -72px -48px; -} - -div.jsoneditor tr, -div.jsoneditor th, -div.jsoneditor td { - padding: 0; - margin: 0; -} - -div.jsoneditor td { - vertical-align: top; -} - -div.jsoneditor td.jsoneditor-tree { - vertical-align: top; -} - -div.jsoneditor-field, -div.jsoneditor-value, -div.jsoneditor td, -div.jsoneditor th, -div.jsoneditor textarea, -.jsoneditor-schema-error { - font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif; - font-size: 10pt; - color: #1A1A1A; -} - -/* popover */ - -.jsoneditor-schema-error { - cursor: default; - display: inline-block; - /*font-family: arial, sans-serif;*/ - height: 24px; - line-height: 24px; - position: relative; - text-align: center; - width: 24px; -} - -div.jsoneditor-tree .jsoneditor-schema-error { - width: 24px; - height: 24px; - padding: 0; - margin: 0 4px 0 0; - background: url("img/jsoneditor-icons.png") -168px -48px; -} - -.jsoneditor-schema-error .jsoneditor-popover { - background-color: #4c4c4c; - border-radius: 3px; - box-shadow: 0 0 5px rgba(0,0,0,0.4); - color: #fff; - display: none; - padding: 7px 10px; - position: absolute; - width: 200px; - z-index: 4; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above { - bottom: 32px; - left: -98px; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below { - top: 32px; - left: -98px; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left { - top: -7px; - right: 32px; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right { - top: -7px; - left: 32px; -} - -.jsoneditor-schema-error .jsoneditor-popover:before { - border-right: 7px solid transparent; - border-left: 7px solid transparent; - content: ''; - display: block; - left: 50%; - margin-left: -7px; - position: absolute; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above:before { - border-top: 7px solid #4c4c4c; - bottom: -7px; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below:before { - border-bottom: 7px solid #4c4c4c; - top: -7px; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left:before { - border-left: 7px solid #4c4c4c; - border-top: 7px solid transparent; - border-bottom: 7px solid transparent; - content: ''; - top: 19px; - right: -14px; - left: inherit; - margin-left: inherit; - margin-top: -7px; - position: absolute; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right:before { - border-right: 7px solid #4c4c4c; - border-top: 7px solid transparent; - border-bottom: 7px solid transparent; - content: ''; - top: 19px; - left: -14px; - margin-left: inherit; - margin-top: -7px; - position: absolute; -} - -.jsoneditor-schema-error:hover .jsoneditor-popover, -.jsoneditor-schema-error:focus .jsoneditor-popover { - display: block; - -webkit-animation: fade-in .3s linear 1, move-up .3s linear 1; - -moz-animation: fade-in .3s linear 1, move-up .3s linear 1; - -ms-animation: fade-in .3s linear 1, move-up .3s linear 1; -} - -@-webkit-keyframes fade-in { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - -@-moz-keyframes fade-in { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - -@-ms-keyframes fade-in { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - -/*@-webkit-keyframes move-up {*/ - -/*from { bottom: 24px; }*/ - -/*to { bottom: 32px; }*/ - -/*}*/ - -/*@-moz-keyframes move-up {*/ - -/*from { bottom: 24px; }*/ - -/*to { bottom: 32px; }*/ - -/*}*/ - -/*@-ms-keyframes move-up {*/ - -/*from { bottom: 24px; }*/ - -/*to { bottom: 32px; }*/ - -/*}*/ - -/* JSON schema errors displayed at the bottom of the editor in mode text and code */ - -.jsoneditor .jsoneditor-text-errors { - width: 100%; - border-collapse: collapse; - background-color: #ffef8b; - border-top: 1px solid #ffd700; -} - -.jsoneditor .jsoneditor-text-errors td { - padding: 3px 6px; - vertical-align: middle; -} - -.jsoneditor-text-errors .jsoneditor-schema-error { - border: none; - width: 24px; - height: 24px; - padding: 0; - margin: 0 4px 0 0; - background: url("img/jsoneditor-icons.png") -168px -48px; -} -/* ContextMenu - main menu */ - -div.jsoneditor-contextmenu-root { - position: relative; - width: 0; - height: 0; -} - -div.jsoneditor-contextmenu { - position: absolute; - box-sizing: content-box; - z-index: 99999; -} - -div.jsoneditor-contextmenu ul, -div.jsoneditor-contextmenu li { - box-sizing: content-box; - position: relative; -} - -div.jsoneditor-contextmenu ul { - position: relative; - left: 0; - top: 0; - width: 128px; - background: white; - border: 1px solid #d3d3d3; - box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); - list-style: none; - margin: 0; - padding: 0; -} - -div.jsoneditor-contextmenu ul li button { - position: relative; - padding: 0 4px 0 0; - margin: 0; - width: 128px; - height: auto; - border: none; - cursor: pointer; - color: #4d4d4d; - background: transparent; - font-size: 10pt; - font-family: arial, sans-serif; - box-sizing: border-box; - text-align: left; -} - -/* Fix button padding in firefox */ - -div.jsoneditor-contextmenu ul li button::-moz-focus-inner { - padding: 0; - border: 0; -} - -div.jsoneditor-contextmenu ul li button:hover, -div.jsoneditor-contextmenu ul li button:focus { - color: #1a1a1a; - background-color: #f5f5f5; - outline: none; -} - -div.jsoneditor-contextmenu ul li button.jsoneditor-default { - width: 96px; - /* 128px - 32px */ -} - -div.jsoneditor-contextmenu ul li button.jsoneditor-expand { - float: right; - width: 32px; - height: 24px; - border-left: 1px solid #e5e5e5; -} - -div.jsoneditor-contextmenu div.jsoneditor-icon { - position: absolute; - top: 0; - left: 0; - width: 24px; - height: 24px; - border: none; - padding: 0; - margin: 0; - background: url url("img/jsoneditor-icons.png"); -} - -div.jsoneditor-contextmenu ul li ul div.jsoneditor-icon { - margin-left: 24px; -} - -div.jsoneditor-contextmenu div.jsoneditor-text { - padding: 4px 0 4px 24px; - word-wrap: break-word; -} - -div.jsoneditor-contextmenu div.jsoneditor-text.jsoneditor-right-margin { - padding-right: 24px; -} - -div.jsoneditor-contextmenu ul li button div.jsoneditor-expand { - position: absolute; - top: 0; - right: 0; - width: 24px; - height: 24px; - padding: 0; - margin: 0 4px 0 0; - background: url("img/jsoneditor-icons.png") 0 -72px; - opacity: 0.4; -} - -div.jsoneditor-contextmenu ul li button:hover div.jsoneditor-expand, -div.jsoneditor-contextmenu ul li button:focus div.jsoneditor-expand, -div.jsoneditor-contextmenu ul li.jsoneditor-selected div.jsoneditor-expand, -div.jsoneditor-contextmenu ul li button.jsoneditor-expand:hover div.jsoneditor-expand, -div.jsoneditor-contextmenu ul li button.jsoneditor-expand:focus div.jsoneditor-expand { - opacity: 1; -} - -div.jsoneditor-contextmenu div.jsoneditor-separator { - height: 0; - border-top: 1px solid #e5e5e5; - padding-top: 5px; - margin-top: 5px; -} - -div.jsoneditor-contextmenu button.jsoneditor-remove > div.jsoneditor-icon { - background-position: -24px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-remove:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-remove:focus > div.jsoneditor-icon { - background-position: -24px 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-append > div.jsoneditor-icon { - background-position: 0 -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-append:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-append:focus > div.jsoneditor-icon { - background-position: 0 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-insert > div.jsoneditor-icon { - background-position: 0 -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-insert:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-insert:focus > div.jsoneditor-icon { - background-position: 0 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-duplicate > div.jsoneditor-icon { - background-position: -48px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-duplicate:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-duplicate:focus > div.jsoneditor-icon { - background-position: -48px 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-sort-asc > div.jsoneditor-icon { - background-position: -168px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-sort-asc:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-sort-asc:focus > div.jsoneditor-icon { - background-position: -168px 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-sort-desc > div.jsoneditor-icon { - background-position: -192px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-sort-desc:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-sort-desc:focus > div.jsoneditor-icon { - background-position: -192px 0; -} - -/* ContextMenu - sub menu */ - -div.jsoneditor-contextmenu ul li button.jsoneditor-selected, -div.jsoneditor-contextmenu ul li button.jsoneditor-selected:hover, -div.jsoneditor-contextmenu ul li button.jsoneditor-selected:focus { - color: white; - background-color: #ee422e; -} - -div.jsoneditor-contextmenu ul li { - overflow: hidden; -} - -div.jsoneditor-contextmenu ul li ul { - display: none; - position: relative; - left: -10px; - top: 0; - border: none; - box-shadow: inset 0 0 10px rgba(128, 128, 128, 0.5); - padding: 0 10px; - /* TODO: transition is not supported on IE8-9 */ - -webkit-transition: all 0.3s ease-out; - -moz-transition: all 0.3s ease-out; - -o-transition: all 0.3s ease-out; - transition: all 0.3s ease-out; -} - - - -div.jsoneditor-contextmenu ul li ul li button { - padding-left: 24px; - animation: all ease-in-out 1s; -} - -div.jsoneditor-contextmenu ul li ul li button:hover, -div.jsoneditor-contextmenu ul li ul li button:focus { - background-color: #f5f5f5; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-string > div.jsoneditor-icon { - background-position: -144px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-string:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-string:focus > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-string.jsoneditor-selected > div.jsoneditor-icon { - background-position: -144px 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-auto > div.jsoneditor-icon { - background-position: -120px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-auto:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-auto:focus > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-auto.jsoneditor-selected > div.jsoneditor-icon { - background-position: -120px 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-object > div.jsoneditor-icon { - background-position: -72px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-object:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-object:focus > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-object.jsoneditor-selected > div.jsoneditor-icon { - background-position: -72px 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-array > div.jsoneditor-icon { - background-position: -96px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-array:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-array:focus > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-array.jsoneditor-selected > div.jsoneditor-icon { - background-position: -96px 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon { - background: url none; - width: 6px; -} -div.jsoneditor-menu { - width: 100%; - height: 35px; - padding: 2px; - margin: 0; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - color: white; - background-color: #3883fa; - border-bottom: 1px solid #3883fa; -} - -div.jsoneditor-menu > button, -div.jsoneditor-menu > div.jsoneditor-modes > button { - width: 26px; - height: 26px; - margin: 2px; - padding: 0; - border-radius: 2px; - border: 1px solid transparent; - background: transparent url("img/jsoneditor-icons.png"); - color: white; - opacity: 0.8; - font-family: arial, sans-serif; - font-size: 10pt; - float: left; -} - -div.jsoneditor-menu > button:hover, -div.jsoneditor-menu > div.jsoneditor-modes > button:hover { - background-color: rgba(255,255,255,0.2); - border: 1px solid rgba(255,255,255,0.4); -} - -div.jsoneditor-menu > button:focus, -div.jsoneditor-menu > button:active, -div.jsoneditor-menu > div.jsoneditor-modes > button:focus, -div.jsoneditor-menu > div.jsoneditor-modes > button:active { - background-color: rgba(255,255,255,0.3); -} - -div.jsoneditor-menu > button:disabled, -div.jsoneditor-menu > div.jsoneditor-modes > button:disabled { - opacity: 0.5; -} - -div.jsoneditor-menu > button.jsoneditor-collapse-all { - background-position: 0 -96px; -} - -div.jsoneditor-menu > button.jsoneditor-expand-all { - background-position: 0 -120px; -} - -div.jsoneditor-menu > button.jsoneditor-undo { - background-position: -24px -96px; -} - -div.jsoneditor-menu > button.jsoneditor-undo:disabled { - background-position: -24px -120px; -} - -div.jsoneditor-menu > button.jsoneditor-redo { - background-position: -48px -96px; -} - -div.jsoneditor-menu > button.jsoneditor-redo:disabled { - background-position: -48px -120px; -} - -div.jsoneditor-menu > button.jsoneditor-compact { - background-position: -72px -96px; -} - -div.jsoneditor-menu > button.jsoneditor-format { - background-position: -72px -120px; -} - -div.jsoneditor-menu > button.jsoneditor-repair { - background-position: -96px -96px; -} - -div.jsoneditor-menu > div.jsoneditor-modes { - display: inline-block; - float: left; -} - -div.jsoneditor-menu > div.jsoneditor-modes > button { - background: url none; - width: auto; - padding-left: 6px; - padding-right: 6px; -} - -div.jsoneditor-menu > button.jsoneditor-separator, -div.jsoneditor-menu > div.jsoneditor-modes > button.jsoneditor-separator { - margin-left: 10px; -} - -div.jsoneditor-menu a { - font-family: arial, sans-serif; - font-size: 10pt; - color: white; - opacity: 0.8; - vertical-align: middle; -} - -div.jsoneditor-menu a:hover { - opacity: 1; -} - -div.jsoneditor-menu a.jsoneditor-poweredBy { - font-size: 8pt; - position: absolute; - right: 0; - top: 0; - padding: 10px; -} -table.jsoneditor-search input, -table.jsoneditor-search div.jsoneditor-results { - font-family: arial, sans-serif; - font-size: 10pt; - color: #1A1A1A; - background: transparent; - /* For Firefox */ -} - -table.jsoneditor-search div.jsoneditor-results { - color: white; - padding-right: 5px; - line-height: 24px; -} - -table.jsoneditor-search { - position: absolute; - right: 4px; - top: 4px; - border-collapse: collapse; - border-spacing: 0; -} - -table.jsoneditor-search div.jsoneditor-frame { - border: 1px solid transparent; - background-color: white; - padding: 0 2px; - margin: 0; -} - -table.jsoneditor-search div.jsoneditor-frame table { - border-collapse: collapse; -} - -table.jsoneditor-search input { - width: 120px; - border: none; - outline: none; - margin: 1px; - line-height: 20px; -} - -table.jsoneditor-search button { - width: 16px; - height: 24px; - padding: 0; - margin: 0; - border: none; - background: url("img/jsoneditor-icons.png"); - vertical-align: top; -} - -table.jsoneditor-search button:hover { - background-color: transparent; -} - -table.jsoneditor-search button.jsoneditor-refresh { - width: 18px; - background-position: -99px -73px; -} - -table.jsoneditor-search button.jsoneditor-next { - cursor: pointer; - background-position: -124px -73px; -} - -table.jsoneditor-search button.jsoneditor-next:hover { - background-position: -124px -49px; -} - -table.jsoneditor-search button.jsoneditor-previous { - cursor: pointer; - background-position: -148px -73px; - margin-right: 2px; -} - -table.jsoneditor-search button.jsoneditor-previous:hover { - background-position: -148px -49px; -} -div.jsoneditor div.autocomplete.dropdown { - position: absolute; - background: white; - box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); - border: 1px solid #d3d3d3; - z-index: 100; - overflow-x: hidden; - overflow-y: auto; - cursor: default; - margin: 0; - padding-left: 2pt; - padding-right: 5pt; - text-align: left; - outline: 0; - font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif; - font-size: 10pt; -} - -div.jsoneditor div.autocomplete.dropdown .item { - color: #333; -} - -div.jsoneditor div.autocomplete.dropdown .item.hover { - background-color: #ddd; -} - -div.jsoneditor div.autocomplete.hint { - color: #aaa; - top: 4px; - left: 4px; -} -div.jsoneditor-treepath { - padding: 0 5px; - overflow: hidden; -} - -div.jsoneditor-treepath div.jsoneditor-contextmenu-root { - position: absolute; - left: 0; -} - -div.jsoneditor-treepath span.jsoneditor-treepath-element { - margin: 1px; - font-family: arial, sans-serif; - font-size: 10pt; -} - -div.jsoneditor-treepath span.jsoneditor-treepath-seperator { - margin: 2px; - font-size: 9pt; - font-family: arial, sans-serif; -} - -div.jsoneditor-treepath span.jsoneditor-treepath-element:hover, -div.jsoneditor-treepath span.jsoneditor-treepath-seperator:hover { - cursor: pointer; - text-decoration: underline; -} -div.jsoneditor-statusbar { - line-height: 26px; - height: 26px; - margin-top: -26px; - color: #808080; - background-color: #ebebeb; - border-top: 1px solid #d3d3d3; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - font-size: 10pt; -} - -div.jsoneditor-statusbar > .jsoneditor-curserinfo-label { - margin: 0 2px 0 4px; -} - -div.jsoneditor-statusbar > .jsoneditor-curserinfo-val { - margin-right: 12px; -} - -div.jsoneditor-statusbar > .jsoneditor-curserinfo-count { - margin-left: 4px; -} -div.jsoneditor-navigation-bar { - width: 100%; - height: 26px; - line-height: 26px; - padding: 0; - margin: 0; - border-bottom: 1px solid #d3d3d3; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - color: #808080; - background-color: #ebebeb; - font-size: 10pt; -} - -div.jsoneditor-navigation-bar.nav-bar-empty:after { - content: 'Select a node ...'; - color: rgba(104, 104, 91, 0.56); - position: absolute; - margin-left: 5px; -} \ No newline at end of file diff --git a/main/webapp/modules/core/externals/jsoneditor/jsoneditor.js b/main/webapp/modules/core/externals/jsoneditor/jsoneditor.js deleted file mode 100644 index c48653054..000000000 --- a/main/webapp/modules/core/externals/jsoneditor/jsoneditor.js +++ /dev/null @@ -1,38359 +0,0 @@ -/*! - * jsoneditor.js - * - * @brief - * JSONEditor is a web-based tool to view, edit, format, and validate JSON. - * It has various modes such as a tree editor, a code editor, and a plain text - * editor. - * - * Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+ - * - * @license - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - * Copyright (c) 2011-2017 Jos de Jong, http://jsoneditoronline.org - * - * @author Jos de Jong, - * @version 5.11.0 - * @date 2017-11-22 - */ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else if(typeof exports === 'object') - exports["JSONEditor"] = factory(); - else - root["JSONEditor"] = factory(); -})(this, function() { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; - -/******/ // The require function -/******/ function __webpack_require__(moduleId) { - -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; - -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; - -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - -/******/ // Flag the module as loaded -/******/ module.loaded = true; - -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } - - -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; - -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; - -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; - -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var Ajv; - try { - Ajv = __webpack_require__(1); - } - catch (err) { - // no problem... when we need Ajv we will throw a neat exception - } - - var treemode = __webpack_require__(51); - var textmode = __webpack_require__(64); - var util = __webpack_require__(54); - - /** - * @constructor JSONEditor - * @param {Element} container Container element - * @param {Object} [options] Object with options. available options: - * {String} mode Editor mode. Available values: - * 'tree' (default), 'view', - * 'form', 'text', and 'code'. - * {function} onChange Callback method, triggered - * on change of contents - * {function} onError Callback method, triggered - * when an error occurs - * {Boolean} search Enable search box. - * True by default - * Only applicable for modes - * 'tree', 'view', and 'form' - * {Boolean} history Enable history (undo/redo). - * True by default - * Only applicable for modes - * 'tree', 'view', and 'form' - * {String} name Field name for the root node. - * Only applicable for modes - * 'tree', 'view', and 'form' - * {Number} indentation Number of indentation - * spaces. 4 by default. - * Only applicable for - * modes 'text' and 'code' - * {boolean} escapeUnicode If true, unicode - * characters are escaped. - * false by default. - * {boolean} sortObjectKeys If true, object keys are - * sorted before display. - * false by default. - * @param {Object | undefined} json JSON object - */ - function JSONEditor (container, options, json) { - if (!(this instanceof JSONEditor)) { - throw new Error('JSONEditor constructor called without "new".'); - } - - // check for unsupported browser (IE8 and older) - var ieVersion = util.getInternetExplorerVersion(); - if (ieVersion != -1 && ieVersion < 9) { - throw new Error('Unsupported browser, IE9 or newer required. ' + - 'Please install the newest version of your browser.'); - } - - if (options) { - // check for deprecated options - if (options.error) { - console.warn('Option "error" has been renamed to "onError"'); - options.onError = options.error; - delete options.error; - } - if (options.change) { - console.warn('Option "change" has been renamed to "onChange"'); - options.onChange = options.change; - delete options.change; - } - if (options.editable) { - console.warn('Option "editable" has been renamed to "onEditable"'); - options.onEditable = options.editable; - delete options.editable; - } - - // validate options - if (options) { - var VALID_OPTIONS = [ - 'ajv', 'schema', 'schemaRefs','templates', - 'ace', 'theme','autocomplete', - 'onChange', 'onEditable', 'onError', 'onModeChange', - 'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation', - 'sortObjectKeys', 'navigationBar', 'statusBar' - ]; - - Object.keys(options).forEach(function (option) { - if (VALID_OPTIONS.indexOf(option) === -1) { - console.warn('Unknown option "' + option + '". This option will be ignored'); - } - }); - } - } - - if (arguments.length) { - this._create(container, options, json); - } - } - - /** - * Configuration for all registered modes. Example: - * { - * tree: { - * mixin: TreeEditor, - * data: 'json' - * }, - * text: { - * mixin: TextEditor, - * data: 'text' - * } - * } - * - * @type { Object. } - */ - JSONEditor.modes = {}; - - // debounce interval for JSON schema vaidation in milliseconds - JSONEditor.prototype.DEBOUNCE_INTERVAL = 150; - - /** - * Create the JSONEditor - * @param {Element} container Container element - * @param {Object} [options] See description in constructor - * @param {Object | undefined} json JSON object - * @private - */ - JSONEditor.prototype._create = function (container, options, json) { - this.container = container; - this.options = options || {}; - this.json = json || {}; - - var mode = this.options.mode || (this.options.modes && this.options.modes[0]) || 'tree'; - this.setMode(mode); - }; - - /** - * Destroy the editor. Clean up DOM, event listeners, and web workers. - */ - JSONEditor.prototype.destroy = function () {}; - - /** - * Set JSON object in editor - * @param {Object | undefined} json JSON data - */ - JSONEditor.prototype.set = function (json) { - this.json = json; - }; - - /** - * Get JSON from the editor - * @returns {Object} json - */ - JSONEditor.prototype.get = function () { - return this.json; - }; - - /** - * Set string containing JSON for the editor - * @param {String | undefined} jsonText - */ - JSONEditor.prototype.setText = function (jsonText) { - this.json = util.parse(jsonText); - }; - - /** - * Get stringified JSON contents from the editor - * @returns {String} jsonText - */ - JSONEditor.prototype.getText = function () { - return JSON.stringify(this.json); - }; - - /** - * Set a field name for the root node. - * @param {String | undefined} name - */ - JSONEditor.prototype.setName = function (name) { - if (!this.options) { - this.options = {}; - } - this.options.name = name; - }; - - /** - * Get the field name for the root node. - * @return {String | undefined} name - */ - JSONEditor.prototype.getName = function () { - return this.options && this.options.name; - }; - - /** - * Change the mode of the editor. - * JSONEditor will be extended with all methods needed for the chosen mode. - * @param {String} mode Available modes: 'tree' (default), 'view', 'form', - * 'text', and 'code'. - */ - JSONEditor.prototype.setMode = function (mode) { - var container = this.container; - var options = util.extend({}, this.options); - var oldMode = options.mode; - var data; - var name; - - options.mode = mode; - var config = JSONEditor.modes[mode]; - if (config) { - try { - var asText = (config.data == 'text'); - name = this.getName(); - data = this[asText ? 'getText' : 'get'](); // get text or json - - this.destroy(); - util.clear(this); - util.extend(this, config.mixin); - this.create(container, options); - - this.setName(name); - this[asText ? 'setText' : 'set'](data); // set text or json - - if (typeof config.load === 'function') { - try { - config.load.call(this); - } - catch (err) { - console.error(err); - } - } - - if (typeof options.onModeChange === 'function' && mode !== oldMode) { - try { - options.onModeChange(mode, oldMode); - } - catch (err) { - console.error(err); - } - } - } - catch (err) { - this._onError(err); - } - } - else { - throw new Error('Unknown mode "' + options.mode + '"'); - } - }; - - /** - * Get the current mode - * @return {string} - */ - JSONEditor.prototype.getMode = function () { - return this.options.mode; - }; - - /** - * Throw an error. If an error callback is configured in options.error, this - * callback will be invoked. Else, a regular error is thrown. - * @param {Error} err - * @private - */ - JSONEditor.prototype._onError = function(err) { - if (this.options && typeof this.options.onError === 'function') { - this.options.onError(err); - } - else { - throw err; - } - }; - - /** - * Set a JSON schema for validation of the JSON object. - * To remove the schema, call JSONEditor.setSchema(null) - * @param {Object | null} schema - * @param {Object.=} schemaRefs Schemas that are referenced using the `$ref` property from the JSON schema that are set in the `schema` option, - + the object structure in the form of `{reference_key: schemaObject}` - */ - JSONEditor.prototype.setSchema = function (schema, schemaRefs) { - // compile a JSON schema validator if a JSON schema is provided - if (schema) { - var ajv; - try { - // grab ajv from options if provided, else create a new instance - ajv = this.options.ajv || Ajv({ allErrors: true, verbose: true }); - - } - catch (err) { - console.warn('Failed to create an instance of Ajv, JSON Schema validation is not available. Please use a JSONEditor bundle including Ajv, or pass an instance of Ajv as via the configuration option `ajv`.'); - } - - if (ajv) { - if(schemaRefs) { - for (var ref in schemaRefs) { - ajv.removeSchema(ref); // When updating a schema - old refs has to be removed first - if(schemaRefs[ref]) { - ajv.addSchema(schemaRefs[ref], ref); - } - } - this.options.schemaRefs = schemaRefs; - } - this.validateSchema = ajv.compile(schema); - - // add schema to the options, so that when switching to an other mode, - // the set schema is not lost - this.options.schema = schema; - - // validate now - this.validate(); - } - - this.refresh(); // update DOM - } - else { - // remove current schema - this.validateSchema = null; - this.options.schema = null; - this.options.schemaRefs = null; - this.validate(); // to clear current error messages - this.refresh(); // update DOM - } - }; - - /** - * Validate current JSON object against the configured JSON schema - * Throws an exception when no JSON schema is configured - */ - JSONEditor.prototype.validate = function () { - // must be implemented by treemode and textmode - }; - - /** - * Refresh the rendered contents - */ - JSONEditor.prototype.refresh = function () { - // can be implemented by treemode and textmode - }; - - /** - * Register a plugin with one ore multiple modes for the JSON Editor. - * - * A mode is described as an object with properties: - * - * - `mode: String` The name of the mode. - * - `mixin: Object` An object containing the mixin functions which - * will be added to the JSONEditor. Must contain functions - * create, get, getText, set, and setText. May have - * additional functions. - * When the JSONEditor switches to a mixin, all mixin - * functions are added to the JSONEditor, and then - * the function `create(container, options)` is executed. - * - `data: 'text' | 'json'` The type of data that will be used to load the mixin. - * - `[load: function]` An optional function called after the mixin - * has been loaded. - * - * @param {Object | Array} mode A mode object or an array with multiple mode objects. - */ - JSONEditor.registerMode = function (mode) { - var i, prop; - - if (util.isArray(mode)) { - // multiple modes - for (i = 0; i < mode.length; i++) { - JSONEditor.registerMode(mode[i]); - } - } - else { - // validate the new mode - if (!('mode' in mode)) throw new Error('Property "mode" missing'); - if (!('mixin' in mode)) throw new Error('Property "mixin" missing'); - if (!('data' in mode)) throw new Error('Property "data" missing'); - var name = mode.mode; - if (name in JSONEditor.modes) { - throw new Error('Mode "' + name + '" already registered'); - } - - // validate the mixin - if (typeof mode.mixin.create !== 'function') { - throw new Error('Required function "create" missing on mixin'); - } - var reserved = ['setMode', 'registerMode', 'modes']; - for (i = 0; i < reserved.length; i++) { - prop = reserved[i]; - if (prop in mode.mixin) { - throw new Error('Reserved property "' + prop + '" not allowed in mixin'); - } - } - - JSONEditor.modes[name] = mode; - } - }; - - // register tree and text modes - JSONEditor.registerMode(treemode); - JSONEditor.registerMode(textmode); - - module.exports = JSONEditor; - - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var compileSchema = __webpack_require__(2) - , resolve = __webpack_require__(3) - , Cache = __webpack_require__(19) - , SchemaObject = __webpack_require__(13) - , stableStringify = __webpack_require__(16) - , formats = __webpack_require__(20) - , rules = __webpack_require__(21) - , $dataMetaSchema = __webpack_require__(44) - , patternGroups = __webpack_require__(45) - , util = __webpack_require__(11) - , co = __webpack_require__(18); - - module.exports = Ajv; - - Ajv.prototype.validate = validate; - Ajv.prototype.compile = compile; - Ajv.prototype.addSchema = addSchema; - Ajv.prototype.addMetaSchema = addMetaSchema; - Ajv.prototype.validateSchema = validateSchema; - Ajv.prototype.getSchema = getSchema; - Ajv.prototype.removeSchema = removeSchema; - Ajv.prototype.addFormat = addFormat; - Ajv.prototype.errorsText = errorsText; - - Ajv.prototype._addSchema = _addSchema; - Ajv.prototype._compile = _compile; - - Ajv.prototype.compileAsync = __webpack_require__(46); - var customKeyword = __webpack_require__(47); - Ajv.prototype.addKeyword = customKeyword.add; - Ajv.prototype.getKeyword = customKeyword.get; - Ajv.prototype.removeKeyword = customKeyword.remove; - - var errorClasses = __webpack_require__(15); - Ajv.ValidationError = errorClasses.Validation; - Ajv.MissingRefError = errorClasses.MissingRef; - Ajv.$dataMetaSchema = $dataMetaSchema; - - var META_SCHEMA_ID = 'http://json-schema.org/draft-06/schema'; - - var META_IGNORE_OPTIONS = [ 'removeAdditional', 'useDefaults', 'coerceTypes' ]; - var META_SUPPORT_DATA = ['/properties']; - - /** - * Creates validator instance. - * Usage: `Ajv(opts)` - * @param {Object} opts optional options - * @return {Object} ajv instance - */ - function Ajv(opts) { - if (!(this instanceof Ajv)) return new Ajv(opts); - opts = this._opts = util.copy(opts) || {}; - setLogger(this); - this._schemas = {}; - this._refs = {}; - this._fragments = {}; - this._formats = formats(opts.format); - var schemaUriFormat = this._schemaUriFormat = this._formats['uri-reference']; - this._schemaUriFormatFunc = function (str) { return schemaUriFormat.test(str); }; - - this._cache = opts.cache || new Cache; - this._loadingSchemas = {}; - this._compilations = []; - this.RULES = rules(); - this._getId = chooseGetId(opts); - - opts.loopRequired = opts.loopRequired || Infinity; - if (opts.errorDataPath == 'property') opts._errorDataPathProperty = true; - if (opts.serialize === undefined) opts.serialize = stableStringify; - this._metaOpts = getMetaSchemaOptions(this); - - if (opts.formats) addInitialFormats(this); - addDraft6MetaSchema(this); - if (typeof opts.meta == 'object') this.addMetaSchema(opts.meta); - addInitialSchemas(this); - if (opts.patternGroups) patternGroups(this); - } - - - - /** - * Validate data using schema - * Schema will be compiled and cached (using serialized JSON as key. [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used to serialize. - * @this Ajv - * @param {String|Object} schemaKeyRef key, ref or schema object - * @param {Any} data to be validated - * @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`). - */ - function validate(schemaKeyRef, data) { - var v; - if (typeof schemaKeyRef == 'string') { - v = this.getSchema(schemaKeyRef); - if (!v) throw new Error('no schema with key or ref "' + schemaKeyRef + '"'); - } else { - var schemaObj = this._addSchema(schemaKeyRef); - v = schemaObj.validate || this._compile(schemaObj); - } - - var valid = v(data); - if (v.$async === true) - return this._opts.async == '*' ? co(valid) : valid; - this.errors = v.errors; - return valid; - } - - - /** - * Create validating function for passed schema. - * @this Ajv - * @param {Object} schema schema object - * @param {Boolean} _meta true if schema is a meta-schema. Used internally to compile meta schemas of custom keywords. - * @return {Function} validating function - */ - function compile(schema, _meta) { - var schemaObj = this._addSchema(schema, undefined, _meta); - return schemaObj.validate || this._compile(schemaObj); - } - - - /** - * Adds schema to the instance. - * @this Ajv - * @param {Object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored. - * @param {String} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`. - * @param {Boolean} _skipValidation true to skip schema validation. Used internally, option validateSchema should be used instead. - * @param {Boolean} _meta true if schema is a meta-schema. Used internally, addMetaSchema should be used instead. - */ - function addSchema(schema, key, _skipValidation, _meta) { - if (Array.isArray(schema)){ - for (var i=0; i} errors optional array of validation errors, if not passed errors from the instance are used. - * @param {Object} options optional options with properties `separator` and `dataVar`. - * @return {String} human readable string with all errors descriptions - */ - function errorsText(errors, options) { - errors = errors || this.errors; - if (!errors) return 'No errors'; - options = options || {}; - var separator = options.separator === undefined ? ', ' : options.separator; - var dataVar = options.dataVar === undefined ? 'data' : options.dataVar; - - var text = ''; - for (var i=0; i= 0) return { index: index, compiling: true }; - index = this._compilations.length; - this._compilations[index] = { - schema: schema, - root: root, - baseId: baseId - }; - return { index: index, compiling: false }; - } - - - /** - * Removes the schema from the currently compiled list - * @this Ajv - * @param {Object} schema schema to compile - * @param {Object} root root object - * @param {String} baseId base schema ID - */ - function endCompiling(schema, root, baseId) { - /* jshint validthis: true */ - var i = compIndex.call(this, schema, root, baseId); - if (i >= 0) this._compilations.splice(i, 1); - } - - - /** - * Index of schema compilation in the currently compiled list - * @this Ajv - * @param {Object} schema schema to compile - * @param {Object} root root object - * @param {String} baseId base schema ID - * @return {Integer} compilation index - */ - function compIndex(schema, root, baseId) { - /* jshint validthis: true */ - for (var i=0; i', '"', '`', ' ', '\r', '\n', '\t'], - - // RFC 2396: characters not allowed for various reasons. - unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), - - // Allowed by RFCs, but cause of XSS attacks. Always escape these. - autoEscape = ['\''].concat(unwise), - // Characters that are never ever allowed in a hostname. - // Note that any invalid chars are also handled, but these - // are the ones that are *expected* to be seen, so we fast-path - // them. - nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), - hostEndingChars = ['/', '?', '#'], - hostnameMaxLen = 255, - hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, - hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, - // protocols that can allow "unsafe" and "unwise" chars. - unsafeProtocol = { - 'javascript': true, - 'javascript:': true - }, - // protocols that never have a hostname. - hostlessProtocol = { - 'javascript': true, - 'javascript:': true - }, - // protocols that always contain a // bit. - slashedProtocol = { - 'http': true, - 'https': true, - 'ftp': true, - 'gopher': true, - 'file': true, - 'http:': true, - 'https:': true, - 'ftp:': true, - 'gopher:': true, - 'file:': true - }, - querystring = __webpack_require__(7); - - function urlParse(url, parseQueryString, slashesDenoteHost) { - if (url && isObject(url) && url instanceof Url) return url; - - var u = new Url; - u.parse(url, parseQueryString, slashesDenoteHost); - return u; - } - - Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { - if (!isString(url)) { - throw new TypeError("Parameter 'url' must be a string, not " + typeof url); - } - - var rest = url; - - // trim before proceeding. - // This is to support parse stuff like " http://foo.com \n" - rest = rest.trim(); - - var proto = protocolPattern.exec(rest); - if (proto) { - proto = proto[0]; - var lowerProto = proto.toLowerCase(); - this.protocol = lowerProto; - rest = rest.substr(proto.length); - } - - // figure out if it's got a host - // user@server is *always* interpreted as a hostname, and url - // resolution will treat //foo/bar as host=foo,path=bar because that's - // how the browser resolves relative URLs. - if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { - var slashes = rest.substr(0, 2) === '//'; - if (slashes && !(proto && hostlessProtocol[proto])) { - rest = rest.substr(2); - this.slashes = true; - } - } - - if (!hostlessProtocol[proto] && - (slashes || (proto && !slashedProtocol[proto]))) { - - // there's a hostname. - // the first instance of /, ?, ;, or # ends the host. - // - // If there is an @ in the hostname, then non-host chars *are* allowed - // to the left of the last @ sign, unless some host-ending character - // comes *before* the @-sign. - // URLs are obnoxious. - // - // ex: - // http://a@b@c/ => user:a@b host:c - // http://a@b?@c => user:a host:c path:/?@c - - // v0.12 TODO(isaacs): This is not quite how Chrome does things. - // Review our test case against browsers more comprehensively. - - // find the first instance of any hostEndingChars - var hostEnd = -1; - for (var i = 0; i < hostEndingChars.length; i++) { - var hec = rest.indexOf(hostEndingChars[i]); - if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) - hostEnd = hec; - } - - // at this point, either we have an explicit point where the - // auth portion cannot go past, or the last @ char is the decider. - var auth, atSign; - if (hostEnd === -1) { - // atSign can be anywhere. - atSign = rest.lastIndexOf('@'); - } else { - // atSign must be in auth portion. - // http://a@b/c@d => host:b auth:a path:/c@d - atSign = rest.lastIndexOf('@', hostEnd); - } - - // Now we have a portion which is definitely the auth. - // Pull that off. - if (atSign !== -1) { - auth = rest.slice(0, atSign); - rest = rest.slice(atSign + 1); - this.auth = decodeURIComponent(auth); - } - - // the host is the remaining to the left of the first non-host char - hostEnd = -1; - for (var i = 0; i < nonHostChars.length; i++) { - var hec = rest.indexOf(nonHostChars[i]); - if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) - hostEnd = hec; - } - // if we still have not hit it, then the entire thing is a host. - if (hostEnd === -1) - hostEnd = rest.length; - - this.host = rest.slice(0, hostEnd); - rest = rest.slice(hostEnd); - - // pull out port. - this.parseHost(); - - // we've indicated that there is a hostname, - // so even if it's empty, it has to be present. - this.hostname = this.hostname || ''; - - // if hostname begins with [ and ends with ] - // assume that it's an IPv6 address. - var ipv6Hostname = this.hostname[0] === '[' && - this.hostname[this.hostname.length - 1] === ']'; - - // validate a little. - if (!ipv6Hostname) { - var hostparts = this.hostname.split(/\./); - for (var i = 0, l = hostparts.length; i < l; i++) { - var part = hostparts[i]; - if (!part) continue; - if (!part.match(hostnamePartPattern)) { - var newpart = ''; - for (var j = 0, k = part.length; j < k; j++) { - if (part.charCodeAt(j) > 127) { - // we replace non-ASCII char with a temporary placeholder - // we need this to make sure size of hostname is not - // broken by replacing non-ASCII by nothing - newpart += 'x'; - } else { - newpart += part[j]; - } - } - // we test again with ASCII char only - if (!newpart.match(hostnamePartPattern)) { - var validParts = hostparts.slice(0, i); - var notHost = hostparts.slice(i + 1); - var bit = part.match(hostnamePartStart); - if (bit) { - validParts.push(bit[1]); - notHost.unshift(bit[2]); - } - if (notHost.length) { - rest = '/' + notHost.join('.') + rest; - } - this.hostname = validParts.join('.'); - break; - } - } - } - } - - if (this.hostname.length > hostnameMaxLen) { - this.hostname = ''; - } else { - // hostnames are always lower case. - this.hostname = this.hostname.toLowerCase(); - } - - if (!ipv6Hostname) { - // IDNA Support: Returns a puny coded representation of "domain". - // It only converts the part of the domain name that - // has non ASCII characters. I.e. it dosent matter if - // you call it with a domain that already is in ASCII. - var domainArray = this.hostname.split('.'); - var newOut = []; - for (var i = 0; i < domainArray.length; ++i) { - var s = domainArray[i]; - newOut.push(s.match(/[^A-Za-z0-9_-]/) ? - 'xn--' + punycode.encode(s) : s); - } - this.hostname = newOut.join('.'); - } - - var p = this.port ? ':' + this.port : ''; - var h = this.hostname || ''; - this.host = h + p; - this.href += this.host; - - // strip [ and ] from the hostname - // the host field still retains them, though - if (ipv6Hostname) { - this.hostname = this.hostname.substr(1, this.hostname.length - 2); - if (rest[0] !== '/') { - rest = '/' + rest; - } - } - } - - // now rest is set to the post-host stuff. - // chop off any delim chars. - if (!unsafeProtocol[lowerProto]) { - - // First, make 100% sure that any "autoEscape" chars get - // escaped, even if encodeURIComponent doesn't think they - // need to be. - for (var i = 0, l = autoEscape.length; i < l; i++) { - var ae = autoEscape[i]; - var esc = encodeURIComponent(ae); - if (esc === ae) { - esc = escape(ae); - } - rest = rest.split(ae).join(esc); - } - } - - - // chop off from the tail first. - var hash = rest.indexOf('#'); - if (hash !== -1) { - // got a fragment string. - this.hash = rest.substr(hash); - rest = rest.slice(0, hash); - } - var qm = rest.indexOf('?'); - if (qm !== -1) { - this.search = rest.substr(qm); - this.query = rest.substr(qm + 1); - if (parseQueryString) { - this.query = querystring.parse(this.query); - } - rest = rest.slice(0, qm); - } else if (parseQueryString) { - // no query string, but parseQueryString still requested - this.search = ''; - this.query = {}; - } - if (rest) this.pathname = rest; - if (slashedProtocol[lowerProto] && - this.hostname && !this.pathname) { - this.pathname = '/'; - } - - //to support http.request - if (this.pathname || this.search) { - var p = this.pathname || ''; - var s = this.search || ''; - this.path = p + s; - } - - // finally, reconstruct the href based on what has been validated. - this.href = this.format(); - return this; - }; - - // format a parsed object into a url string - function urlFormat(obj) { - // ensure it's an object, and not a string url. - // If it's an obj, this is a no-op. - // this way, you can call url_format() on strings - // to clean up potentially wonky urls. - if (isString(obj)) obj = urlParse(obj); - if (!(obj instanceof Url)) return Url.prototype.format.call(obj); - return obj.format(); - } - - Url.prototype.format = function() { - var auth = this.auth || ''; - if (auth) { - auth = encodeURIComponent(auth); - auth = auth.replace(/%3A/i, ':'); - auth += '@'; - } - - var protocol = this.protocol || '', - pathname = this.pathname || '', - hash = this.hash || '', - host = false, - query = ''; - - if (this.host) { - host = auth + this.host; - } else if (this.hostname) { - host = auth + (this.hostname.indexOf(':') === -1 ? - this.hostname : - '[' + this.hostname + ']'); - if (this.port) { - host += ':' + this.port; - } - } - - if (this.query && - isObject(this.query) && - Object.keys(this.query).length) { - query = querystring.stringify(this.query); - } - - var search = this.search || (query && ('?' + query)) || ''; - - if (protocol && protocol.substr(-1) !== ':') protocol += ':'; - - // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. - // unless they had them to begin with. - if (this.slashes || - (!protocol || slashedProtocol[protocol]) && host !== false) { - host = '//' + (host || ''); - if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; - } else if (!host) { - host = ''; - } - - if (hash && hash.charAt(0) !== '#') hash = '#' + hash; - if (search && search.charAt(0) !== '?') search = '?' + search; - - pathname = pathname.replace(/[?#]/g, function(match) { - return encodeURIComponent(match); - }); - search = search.replace('#', '%23'); - - return protocol + host + pathname + search + hash; - }; - - function urlResolve(source, relative) { - return urlParse(source, false, true).resolve(relative); - } - - Url.prototype.resolve = function(relative) { - return this.resolveObject(urlParse(relative, false, true)).format(); - }; - - function urlResolveObject(source, relative) { - if (!source) return relative; - return urlParse(source, false, true).resolveObject(relative); - } - - Url.prototype.resolveObject = function(relative) { - if (isString(relative)) { - var rel = new Url(); - rel.parse(relative, false, true); - relative = rel; - } - - var result = new Url(); - Object.keys(this).forEach(function(k) { - result[k] = this[k]; - }, this); - - // hash is always overridden, no matter what. - // even href="" will remove it. - result.hash = relative.hash; - - // if the relative url is empty, then there's nothing left to do here. - if (relative.href === '') { - result.href = result.format(); - return result; - } - - // hrefs like //foo/bar always cut to the protocol. - if (relative.slashes && !relative.protocol) { - // take everything except the protocol from relative - Object.keys(relative).forEach(function(k) { - if (k !== 'protocol') - result[k] = relative[k]; - }); - - //urlParse appends trailing / to urls like http://www.example.com - if (slashedProtocol[result.protocol] && - result.hostname && !result.pathname) { - result.path = result.pathname = '/'; - } - - result.href = result.format(); - return result; - } - - if (relative.protocol && relative.protocol !== result.protocol) { - // if it's a known url protocol, then changing - // the protocol does weird things - // first, if it's not file:, then we MUST have a host, - // and if there was a path - // to begin with, then we MUST have a path. - // if it is file:, then the host is dropped, - // because that's known to be hostless. - // anything else is assumed to be absolute. - if (!slashedProtocol[relative.protocol]) { - Object.keys(relative).forEach(function(k) { - result[k] = relative[k]; - }); - result.href = result.format(); - return result; - } - - result.protocol = relative.protocol; - if (!relative.host && !hostlessProtocol[relative.protocol]) { - var relPath = (relative.pathname || '').split('/'); - while (relPath.length && !(relative.host = relPath.shift())); - if (!relative.host) relative.host = ''; - if (!relative.hostname) relative.hostname = ''; - if (relPath[0] !== '') relPath.unshift(''); - if (relPath.length < 2) relPath.unshift(''); - result.pathname = relPath.join('/'); - } else { - result.pathname = relative.pathname; - } - result.search = relative.search; - result.query = relative.query; - result.host = relative.host || ''; - result.auth = relative.auth; - result.hostname = relative.hostname || relative.host; - result.port = relative.port; - // to support http.request - if (result.pathname || result.search) { - var p = result.pathname || ''; - var s = result.search || ''; - result.path = p + s; - } - result.slashes = result.slashes || relative.slashes; - result.href = result.format(); - return result; - } - - var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), - isRelAbs = ( - relative.host || - relative.pathname && relative.pathname.charAt(0) === '/' - ), - mustEndAbs = (isRelAbs || isSourceAbs || - (result.host && relative.pathname)), - removeAllDots = mustEndAbs, - srcPath = result.pathname && result.pathname.split('/') || [], - relPath = relative.pathname && relative.pathname.split('/') || [], - psychotic = result.protocol && !slashedProtocol[result.protocol]; - - // if the url is a non-slashed url, then relative - // links like ../.. should be able - // to crawl up to the hostname, as well. This is strange. - // result.protocol has already been set by now. - // Later on, put the first path part into the host field. - if (psychotic) { - result.hostname = ''; - result.port = null; - if (result.host) { - if (srcPath[0] === '') srcPath[0] = result.host; - else srcPath.unshift(result.host); - } - result.host = ''; - if (relative.protocol) { - relative.hostname = null; - relative.port = null; - if (relative.host) { - if (relPath[0] === '') relPath[0] = relative.host; - else relPath.unshift(relative.host); - } - relative.host = null; - } - mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); - } - - if (isRelAbs) { - // it's absolute. - result.host = (relative.host || relative.host === '') ? - relative.host : result.host; - result.hostname = (relative.hostname || relative.hostname === '') ? - relative.hostname : result.hostname; - result.search = relative.search; - result.query = relative.query; - srcPath = relPath; - // fall through to the dot-handling below. - } else if (relPath.length) { - // it's relative - // throw away the existing file, and take the new path instead. - if (!srcPath) srcPath = []; - srcPath.pop(); - srcPath = srcPath.concat(relPath); - result.search = relative.search; - result.query = relative.query; - } else if (!isNullOrUndefined(relative.search)) { - // just pull out the search. - // like href='?foo'. - // Put this after the other two cases because it simplifies the booleans - if (psychotic) { - result.hostname = result.host = srcPath.shift(); - //occationaly the auth can get stuck only in host - //this especialy happens in cases like - //url.resolveObject('mailto:local1@domain1', 'local2@domain2') - var authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; - if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); - } - } - result.search = relative.search; - result.query = relative.query; - //to support http.request - if (!isNull(result.pathname) || !isNull(result.search)) { - result.path = (result.pathname ? result.pathname : '') + - (result.search ? result.search : ''); - } - result.href = result.format(); - return result; - } - - if (!srcPath.length) { - // no path at all. easy. - // we've already handled the other stuff above. - result.pathname = null; - //to support http.request - if (result.search) { - result.path = '/' + result.search; - } else { - result.path = null; - } - result.href = result.format(); - return result; - } - - // if a url ENDs in . or .., then it must get a trailing slash. - // however, if it ends in anything else non-slashy, - // then it must NOT get a trailing slash. - var last = srcPath.slice(-1)[0]; - var hasTrailingSlash = ( - (result.host || relative.host) && (last === '.' || last === '..') || - last === ''); - - // strip single dots, resolve double dots to parent dir - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = srcPath.length; i >= 0; i--) { - last = srcPath[i]; - if (last == '.') { - srcPath.splice(i, 1); - } else if (last === '..') { - srcPath.splice(i, 1); - up++; - } else if (up) { - srcPath.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (!mustEndAbs && !removeAllDots) { - for (; up--; up) { - srcPath.unshift('..'); - } - } - - if (mustEndAbs && srcPath[0] !== '' && - (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { - srcPath.unshift(''); - } - - if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { - srcPath.push(''); - } - - var isAbsolute = srcPath[0] === '' || - (srcPath[0] && srcPath[0].charAt(0) === '/'); - - // put the host back - if (psychotic) { - result.hostname = result.host = isAbsolute ? '' : - srcPath.length ? srcPath.shift() : ''; - //occationaly the auth can get stuck only in host - //this especialy happens in cases like - //url.resolveObject('mailto:local1@domain1', 'local2@domain2') - var authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; - if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); - } - } - - mustEndAbs = mustEndAbs || (result.host && srcPath.length); - - if (mustEndAbs && !isAbsolute) { - srcPath.unshift(''); - } - - if (!srcPath.length) { - result.pathname = null; - result.path = null; - } else { - result.pathname = srcPath.join('/'); - } - - //to support request.http - if (!isNull(result.pathname) || !isNull(result.search)) { - result.path = (result.pathname ? result.pathname : '') + - (result.search ? result.search : ''); - } - result.auth = relative.auth || result.auth; - result.slashes = result.slashes || relative.slashes; - result.href = result.format(); - return result; - }; - - Url.prototype.parseHost = function() { - var host = this.host; - var port = portPattern.exec(host); - if (port) { - port = port[0]; - if (port !== ':') { - this.port = port.substr(1); - } - host = host.substr(0, host.length - port.length); - } - if (host) this.hostname = host; - }; - - function isString(arg) { - return typeof arg === "string"; - } - - function isObject(arg) { - return typeof arg === 'object' && arg !== null; - } - - function isNull(arg) { - return arg === null; - } - function isNullOrUndefined(arg) { - return arg == null; - } - - -/***/ }, -/* 5 */ -/***/ function(module, exports, __webpack_require__) { - - var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */ - ;(function(root) { - - /** Detect free variables */ - var freeExports = typeof exports == 'object' && exports && - !exports.nodeType && exports; - var freeModule = typeof module == 'object' && module && - !module.nodeType && module; - var freeGlobal = typeof global == 'object' && global; - if ( - freeGlobal.global === freeGlobal || - freeGlobal.window === freeGlobal || - freeGlobal.self === freeGlobal - ) { - root = freeGlobal; - } - - /** - * The `punycode` object. - * @name punycode - * @type Object - */ - var punycode, - - /** Highest positive signed 32-bit float value */ - maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 - - /** Bootstring parameters */ - base = 36, - tMin = 1, - tMax = 26, - skew = 38, - damp = 700, - initialBias = 72, - initialN = 128, // 0x80 - delimiter = '-', // '\x2D' - - /** Regular expressions */ - regexPunycode = /^xn--/, - regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars - regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators - - /** Error messages */ - errors = { - 'overflow': 'Overflow: input needs wider integers to process', - 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', - 'invalid-input': 'Invalid input' - }, - - /** Convenience shortcuts */ - baseMinusTMin = base - tMin, - floor = Math.floor, - stringFromCharCode = String.fromCharCode, - - /** Temporary variable */ - key; - - /*--------------------------------------------------------------------------*/ - - /** - * A generic error utility function. - * @private - * @param {String} type The error type. - * @returns {Error} Throws a `RangeError` with the applicable error message. - */ - function error(type) { - throw RangeError(errors[type]); - } - - /** - * A generic `Array#map` utility function. - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function that gets called for every array - * item. - * @returns {Array} A new array of values returned by the callback function. - */ - function map(array, fn) { - var length = array.length; - var result = []; - while (length--) { - result[length] = fn(array[length]); - } - return result; - } - - /** - * A simple `Array#map`-like wrapper to work with domain name strings or email - * addresses. - * @private - * @param {String} domain The domain name or email address. - * @param {Function} callback The function that gets called for every - * character. - * @returns {Array} A new string of characters returned by the callback - * function. - */ - function mapDomain(string, fn) { - var parts = string.split('@'); - var result = ''; - if (parts.length > 1) { - // In email addresses, only the domain name should be punycoded. Leave - // the local part (i.e. everything up to `@`) intact. - result = parts[0] + '@'; - string = parts[1]; - } - // Avoid `split(regex)` for IE8 compatibility. See #17. - string = string.replace(regexSeparators, '\x2E'); - var labels = string.split('.'); - var encoded = map(labels, fn).join('.'); - return result + encoded; - } - - /** - * Creates an array containing the numeric code points of each Unicode - * character in the string. While JavaScript uses UCS-2 internally, - * this function will convert a pair of surrogate halves (each of which - * UCS-2 exposes as separate characters) into a single code point, - * matching UTF-16. - * @see `punycode.ucs2.encode` - * @see - * @memberOf punycode.ucs2 - * @name decode - * @param {String} string The Unicode input string (UCS-2). - * @returns {Array} The new array of code points. - */ - function ucs2decode(string) { - var output = [], - counter = 0, - length = string.length, - value, - extra; - while (counter < length) { - value = string.charCodeAt(counter++); - if (value >= 0xD800 && value <= 0xDBFF && counter < length) { - // high surrogate, and there is a next character - extra = string.charCodeAt(counter++); - if ((extra & 0xFC00) == 0xDC00) { // low surrogate - output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); - } else { - // unmatched surrogate; only append this code unit, in case the next - // code unit is the high surrogate of a surrogate pair - output.push(value); - counter--; - } - } else { - output.push(value); - } - } - return output; - } - - /** - * Creates a string based on an array of numeric code points. - * @see `punycode.ucs2.decode` - * @memberOf punycode.ucs2 - * @name encode - * @param {Array} codePoints The array of numeric code points. - * @returns {String} The new Unicode string (UCS-2). - */ - function ucs2encode(array) { - return map(array, function(value) { - var output = ''; - if (value > 0xFFFF) { - value -= 0x10000; - output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); - value = 0xDC00 | value & 0x3FF; - } - output += stringFromCharCode(value); - return output; - }).join(''); - } - - /** - * Converts a basic code point into a digit/integer. - * @see `digitToBasic()` - * @private - * @param {Number} codePoint The basic numeric code point value. - * @returns {Number} The numeric value of a basic code point (for use in - * representing integers) in the range `0` to `base - 1`, or `base` if - * the code point does not represent a value. - */ - function basicToDigit(codePoint) { - if (codePoint - 48 < 10) { - return codePoint - 22; - } - if (codePoint - 65 < 26) { - return codePoint - 65; - } - if (codePoint - 97 < 26) { - return codePoint - 97; - } - return base; - } - - /** - * Converts a digit/integer into a basic code point. - * @see `basicToDigit()` - * @private - * @param {Number} digit The numeric value of a basic code point. - * @returns {Number} The basic code point whose value (when used for - * representing integers) is `digit`, which needs to be in the range - * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is - * used; else, the lowercase form is used. The behavior is undefined - * if `flag` is non-zero and `digit` has no uppercase form. - */ - function digitToBasic(digit, flag) { - // 0..25 map to ASCII a..z or A..Z - // 26..35 map to ASCII 0..9 - return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); - } - - /** - * Bias adaptation function as per section 3.4 of RFC 3492. - * http://tools.ietf.org/html/rfc3492#section-3.4 - * @private - */ - function adapt(delta, numPoints, firstTime) { - var k = 0; - delta = firstTime ? floor(delta / damp) : delta >> 1; - delta += floor(delta / numPoints); - for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { - delta = floor(delta / baseMinusTMin); - } - return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); - } - - /** - * Converts a Punycode string of ASCII-only symbols to a string of Unicode - * symbols. - * @memberOf punycode - * @param {String} input The Punycode string of ASCII-only symbols. - * @returns {String} The resulting string of Unicode symbols. - */ - function decode(input) { - // Don't use UCS-2 - var output = [], - inputLength = input.length, - out, - i = 0, - n = initialN, - bias = initialBias, - basic, - j, - index, - oldi, - w, - k, - digit, - t, - /** Cached calculation results */ - baseMinusT; - - // Handle the basic code points: let `basic` be the number of input code - // points before the last delimiter, or `0` if there is none, then copy - // the first basic code points to the output. - - basic = input.lastIndexOf(delimiter); - if (basic < 0) { - basic = 0; - } - - for (j = 0; j < basic; ++j) { - // if it's not a basic code point - if (input.charCodeAt(j) >= 0x80) { - error('not-basic'); - } - output.push(input.charCodeAt(j)); - } - - // Main decoding loop: start just after the last delimiter if any basic code - // points were copied; start at the beginning otherwise. - - for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { - - // `index` is the index of the next character to be consumed. - // Decode a generalized variable-length integer into `delta`, - // which gets added to `i`. The overflow checking is easier - // if we increase `i` as we go, then subtract off its starting - // value at the end to obtain `delta`. - for (oldi = i, w = 1, k = base; /* no condition */; k += base) { - - if (index >= inputLength) { - error('invalid-input'); - } - - digit = basicToDigit(input.charCodeAt(index++)); - - if (digit >= base || digit > floor((maxInt - i) / w)) { - error('overflow'); - } - - i += digit * w; - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - - if (digit < t) { - break; - } - - baseMinusT = base - t; - if (w > floor(maxInt / baseMinusT)) { - error('overflow'); - } - - w *= baseMinusT; - - } - - out = output.length + 1; - bias = adapt(i - oldi, out, oldi == 0); - - // `i` was supposed to wrap around from `out` to `0`, - // incrementing `n` each time, so we'll fix that now: - if (floor(i / out) > maxInt - n) { - error('overflow'); - } - - n += floor(i / out); - i %= out; - - // Insert `n` at position `i` of the output - output.splice(i++, 0, n); - - } - - return ucs2encode(output); - } - - /** - * Converts a string of Unicode symbols (e.g. a domain name label) to a - * Punycode string of ASCII-only symbols. - * @memberOf punycode - * @param {String} input The string of Unicode symbols. - * @returns {String} The resulting Punycode string of ASCII-only symbols. - */ - function encode(input) { - var n, - delta, - handledCPCount, - basicLength, - bias, - j, - m, - q, - k, - t, - currentValue, - output = [], - /** `inputLength` will hold the number of code points in `input`. */ - inputLength, - /** Cached calculation results */ - handledCPCountPlusOne, - baseMinusT, - qMinusT; - - // Convert the input in UCS-2 to Unicode - input = ucs2decode(input); - - // Cache the length - inputLength = input.length; - - // Initialize the state - n = initialN; - delta = 0; - bias = initialBias; - - // Handle the basic code points - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue < 0x80) { - output.push(stringFromCharCode(currentValue)); - } - } - - handledCPCount = basicLength = output.length; - - // `handledCPCount` is the number of code points that have been handled; - // `basicLength` is the number of basic code points. - - // Finish the basic string - if it is not empty - with a delimiter - if (basicLength) { - output.push(delimiter); - } - - // Main encoding loop: - while (handledCPCount < inputLength) { - - // All non-basic code points < n have been handled already. Find the next - // larger one: - for (m = maxInt, j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue >= n && currentValue < m) { - m = currentValue; - } - } - - // Increase `delta` enough to advance the decoder's state to , - // but guard against overflow - handledCPCountPlusOne = handledCPCount + 1; - if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { - error('overflow'); - } - - delta += (m - n) * handledCPCountPlusOne; - n = m; - - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - - if (currentValue < n && ++delta > maxInt) { - error('overflow'); - } - - if (currentValue == n) { - // Represent delta as a generalized variable-length integer - for (q = delta, k = base; /* no condition */; k += base) { - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - if (q < t) { - break; - } - qMinusT = q - t; - baseMinusT = base - t; - output.push( - stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) - ); - q = floor(qMinusT / baseMinusT); - } - - output.push(stringFromCharCode(digitToBasic(q, 0))); - bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); - delta = 0; - ++handledCPCount; - } - } - - ++delta; - ++n; - - } - return output.join(''); - } - - /** - * Converts a Punycode string representing a domain name or an email address - * to Unicode. Only the Punycoded parts of the input will be converted, i.e. - * it doesn't matter if you call it on a string that has already been - * converted to Unicode. - * @memberOf punycode - * @param {String} input The Punycoded domain name or email address to - * convert to Unicode. - * @returns {String} The Unicode representation of the given Punycode - * string. - */ - function toUnicode(input) { - return mapDomain(input, function(string) { - return regexPunycode.test(string) - ? decode(string.slice(4).toLowerCase()) - : string; - }); - } - - /** - * Converts a Unicode string representing a domain name or an email address to - * Punycode. Only the non-ASCII parts of the domain name will be converted, - * i.e. it doesn't matter if you call it with a domain that's already in - * ASCII. - * @memberOf punycode - * @param {String} input The domain name or email address to convert, as a - * Unicode string. - * @returns {String} The Punycode representation of the given domain name or - * email address. - */ - function toASCII(input) { - return mapDomain(input, function(string) { - return regexNonASCII.test(string) - ? 'xn--' + encode(string) - : string; - }); - } - - /*--------------------------------------------------------------------------*/ - - /** Define the public API */ - punycode = { - /** - * A string representing the current Punycode.js version number. - * @memberOf punycode - * @type String - */ - 'version': '1.3.2', - /** - * An object of methods to convert from JavaScript's internal character - * representation (UCS-2) to Unicode code points, and back. - * @see - * @memberOf punycode - * @type Object - */ - 'ucs2': { - 'decode': ucs2decode, - 'encode': ucs2encode - }, - 'decode': decode, - 'encode': encode, - 'toASCII': toASCII, - 'toUnicode': toUnicode - }; - - /** Expose `punycode` */ - // Some AMD build optimizers, like r.js, check for specific condition patterns - // like the following: - if ( - true - ) { - !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { - return punycode; - }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if (freeExports && freeModule) { - if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+ - freeModule.exports = punycode; - } else { // in Narwhal or RingoJS v0.7.0- - for (key in punycode) { - punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); - } - } - } else { // in Rhino or a web browser - root.punycode = punycode; - } - - }(this)); - - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(6)(module), (function() { return this; }()))) - -/***/ }, -/* 6 */ -/***/ function(module, exports) { - - module.exports = function(module) { - if(!module.webpackPolyfill) { - module.deprecate = function() {}; - module.paths = []; - // module.parent = undefined by default - module.children = []; - module.webpackPolyfill = 1; - } - return module; - } - - -/***/ }, -/* 7 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - exports.decode = exports.parse = __webpack_require__(8); - exports.encode = exports.stringify = __webpack_require__(9); - - -/***/ }, -/* 8 */ -/***/ function(module, exports) { - - // Copyright Joyent, Inc. and other Node contributors. - // - // Permission is hereby granted, free of charge, to any person obtaining a - // copy of this software and associated documentation files (the - // "Software"), to deal in the Software without restriction, including - // without limitation the rights to use, copy, modify, merge, publish, - // distribute, sublicense, and/or sell copies of the Software, and to permit - // persons to whom the Software is furnished to do so, subject to the - // following conditions: - // - // The above copyright notice and this permission notice shall be included - // in all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - // USE OR OTHER DEALINGS IN THE SOFTWARE. - - 'use strict'; - - // If obj.hasOwnProperty has been overridden, then calling - // obj.hasOwnProperty(prop) will break. - // See: https://github.com/joyent/node/issues/1707 - function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); - } - - module.exports = function(qs, sep, eq, options) { - sep = sep || '&'; - eq = eq || '='; - var obj = {}; - - if (typeof qs !== 'string' || qs.length === 0) { - return obj; - } - - var regexp = /\+/g; - qs = qs.split(sep); - - var maxKeys = 1000; - if (options && typeof options.maxKeys === 'number') { - maxKeys = options.maxKeys; - } - - var len = qs.length; - // maxKeys <= 0 means that we should not limit keys count - if (maxKeys > 0 && len > maxKeys) { - len = maxKeys; - } - - for (var i = 0; i < len; ++i) { - var x = qs[i].replace(regexp, '%20'), - idx = x.indexOf(eq), - kstr, vstr, k, v; - - if (idx >= 0) { - kstr = x.substr(0, idx); - vstr = x.substr(idx + 1); - } else { - kstr = x; - vstr = ''; - } - - k = decodeURIComponent(kstr); - v = decodeURIComponent(vstr); - - if (!hasOwnProperty(obj, k)) { - obj[k] = v; - } else if (Array.isArray(obj[k])) { - obj[k].push(v); - } else { - obj[k] = [obj[k], v]; - } - } - - return obj; - }; - - -/***/ }, -/* 9 */ -/***/ function(module, exports) { - - // Copyright Joyent, Inc. and other Node contributors. - // - // Permission is hereby granted, free of charge, to any person obtaining a - // copy of this software and associated documentation files (the - // "Software"), to deal in the Software without restriction, including - // without limitation the rights to use, copy, modify, merge, publish, - // distribute, sublicense, and/or sell copies of the Software, and to permit - // persons to whom the Software is furnished to do so, subject to the - // following conditions: - // - // The above copyright notice and this permission notice shall be included - // in all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - // USE OR OTHER DEALINGS IN THE SOFTWARE. - - 'use strict'; - - var stringifyPrimitive = function(v) { - switch (typeof v) { - case 'string': - return v; - - case 'boolean': - return v ? 'true' : 'false'; - - case 'number': - return isFinite(v) ? v : ''; - - default: - return ''; - } - }; - - module.exports = function(obj, sep, eq, name) { - sep = sep || '&'; - eq = eq || '='; - if (obj === null) { - obj = undefined; - } - - if (typeof obj === 'object') { - return Object.keys(obj).map(function(k) { - var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; - if (Array.isArray(obj[k])) { - return obj[k].map(function(v) { - return ks + encodeURIComponent(stringifyPrimitive(v)); - }).join(sep); - } else { - return ks + encodeURIComponent(stringifyPrimitive(obj[k])); - } - }).join(sep); - - } - - if (!name) return ''; - return encodeURIComponent(stringifyPrimitive(name)) + eq + - encodeURIComponent(stringifyPrimitive(obj)); - }; - - -/***/ }, -/* 10 */ -/***/ function(module, exports) { - - 'use strict'; - - module.exports = function equal(a, b) { - if (a === b) return true; - - var arrA = Array.isArray(a) - , arrB = Array.isArray(b) - , i; - - if (arrA && arrB) { - if (a.length != b.length) return false; - for (i = 0; i < a.length; i++) - if (!equal(a[i], b[i])) return false; - return true; - } - - if (arrA != arrB) return false; - - if (a && b && typeof a === 'object' && typeof b === 'object') { - var keys = Object.keys(a); - if (keys.length !== Object.keys(b).length) return false; - - var dateA = a instanceof Date - , dateB = b instanceof Date; - if (dateA && dateB) return a.getTime() == b.getTime(); - if (dateA != dateB) return false; - - var regexpA = a instanceof RegExp - , regexpB = b instanceof RegExp; - if (regexpA && regexpB) return a.toString() == b.toString(); - if (regexpA != regexpB) return false; - - for (i = 0; i < keys.length; i++) - if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false; - - for (i = 0; i < keys.length; i++) - if(!equal(a[keys[i]], b[keys[i]])) return false; - - return true; - } - - return false; - }; - - -/***/ }, -/* 11 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - - module.exports = { - copy: copy, - checkDataType: checkDataType, - checkDataTypes: checkDataTypes, - coerceToTypes: coerceToTypes, - toHash: toHash, - getProperty: getProperty, - escapeQuotes: escapeQuotes, - equal: __webpack_require__(10), - ucs2length: __webpack_require__(12), - varOccurences: varOccurences, - varReplace: varReplace, - cleanUpCode: cleanUpCode, - finalCleanUpCode: finalCleanUpCode, - schemaHasRules: schemaHasRules, - schemaHasRulesExcept: schemaHasRulesExcept, - toQuotedString: toQuotedString, - getPathExpr: getPathExpr, - getPath: getPath, - getData: getData, - unescapeFragment: unescapeFragment, - unescapeJsonPointer: unescapeJsonPointer, - escapeFragment: escapeFragment, - escapeJsonPointer: escapeJsonPointer - }; - - - function copy(o, to) { - to = to || {}; - for (var key in o) to[key] = o[key]; - return to; - } - - - function checkDataType(dataType, data, negate) { - var EQUAL = negate ? ' !== ' : ' === ' - , AND = negate ? ' || ' : ' && ' - , OK = negate ? '!' : '' - , NOT = negate ? '' : '!'; - switch (dataType) { - case 'null': return data + EQUAL + 'null'; - case 'array': return OK + 'Array.isArray(' + data + ')'; - case 'object': return '(' + OK + data + AND + - 'typeof ' + data + EQUAL + '"object"' + AND + - NOT + 'Array.isArray(' + data + '))'; - case 'integer': return '(typeof ' + data + EQUAL + '"number"' + AND + - NOT + '(' + data + ' % 1)' + - AND + data + EQUAL + data + ')'; - default: return 'typeof ' + data + EQUAL + '"' + dataType + '"'; - } - } - - - function checkDataTypes(dataTypes, data) { - switch (dataTypes.length) { - case 1: return checkDataType(dataTypes[0], data, true); - default: - var code = ''; - var types = toHash(dataTypes); - if (types.array && types.object) { - code = types.null ? '(': '(!' + data + ' || '; - code += 'typeof ' + data + ' !== "object")'; - delete types.null; - delete types.array; - delete types.object; - } - if (types.number) delete types.integer; - for (var t in types) - code += (code ? ' && ' : '' ) + checkDataType(t, data, true); - - return code; - } - } - - - var COERCE_TO_TYPES = toHash([ 'string', 'number', 'integer', 'boolean', 'null' ]); - function coerceToTypes(optionCoerceTypes, dataTypes) { - if (Array.isArray(dataTypes)) { - var types = []; - for (var i=0; i= lvl) throw new Error('Cannot access property/index ' + up + ' levels up, current level is ' + lvl); - return paths[lvl - up]; - } - - if (up > lvl) throw new Error('Cannot access data ' + up + ' levels up, current level is ' + lvl); - data = 'data' + ((lvl - up) || ''); - if (!jsonPointer) return data; - } - - var expr = data; - var segments = jsonPointer.split('/'); - for (var i=0; i= 0xD800 && value <= 0xDBFF && pos < len) { - // high surrogate, and there is a next character - value = str.charCodeAt(pos); - if ((value & 0xFC00) == 0xDC00) pos++; // low surrogate - } - } - return length; - }; - - -/***/ }, -/* 13 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var util = __webpack_require__(11); - - module.exports = SchemaObject; - - function SchemaObject(obj) { - util.copy(obj, this); - } - - -/***/ }, -/* 14 */ -/***/ function(module, exports) { - - 'use strict'; - - var traverse = module.exports = function (schema, opts, cb) { - if (typeof opts == 'function') { - cb = opts; - opts = {}; - } - _traverse(opts, cb, schema, '', schema); - }; - - - traverse.keywords = { - additionalItems: true, - items: true, - contains: true, - additionalProperties: true, - propertyNames: true, - not: true - }; - - traverse.arrayKeywords = { - items: true, - allOf: true, - anyOf: true, - oneOf: true - }; - - traverse.propsKeywords = { - definitions: true, - properties: true, - patternProperties: true, - dependencies: true - }; - - traverse.skipKeywords = { - enum: true, - const: true, - required: true, - maximum: true, - minimum: true, - exclusiveMaximum: true, - exclusiveMinimum: true, - multipleOf: true, - maxLength: true, - minLength: true, - pattern: true, - format: true, - maxItems: true, - minItems: true, - uniqueItems: true, - maxProperties: true, - minProperties: true - }; - - - function _traverse(opts, cb, schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex) { - if (schema && typeof schema == 'object' && !Array.isArray(schema)) { - cb(schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex); - for (var key in schema) { - var sch = schema[key]; - if (Array.isArray(sch)) { - if (key in traverse.arrayKeywords) { - for (var i=0; i 2) res = slice.call(arguments, 1); - resolve(res); - }); - }); - } - - /** - * Convert an array of "yieldables" to a promise. - * Uses `Promise.all()` internally. - * - * @param {Array} obj - * @return {Promise} - * @api private - */ - - function arrayToPromise(obj) { - return Promise.all(obj.map(toPromise, this)); - } - - /** - * Convert an object of "yieldables" to a promise. - * Uses `Promise.all()` internally. - * - * @param {Object} obj - * @return {Promise} - * @api private - */ - - function objectToPromise(obj){ - var results = new obj.constructor(); - var keys = Object.keys(obj); - var promises = []; - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - var promise = toPromise.call(this, obj[key]); - if (promise && isPromise(promise)) defer(promise, key); - else results[key] = obj[key]; - } - return Promise.all(promises).then(function () { - return results; - }); - - function defer(promise, key) { - // predefine the key in the result - results[key] = undefined; - promises.push(promise.then(function (res) { - results[key] = res; - })); - } - } - - /** - * Check if `obj` is a promise. - * - * @param {Object} obj - * @return {Boolean} - * @api private - */ - - function isPromise(obj) { - return 'function' == typeof obj.then; - } - - /** - * Check if `obj` is a generator. - * - * @param {Mixed} obj - * @return {Boolean} - * @api private - */ - - function isGenerator(obj) { - return 'function' == typeof obj.next && 'function' == typeof obj.throw; - } - - /** - * Check if `obj` is a generator function. - * - * @param {Mixed} obj - * @return {Boolean} - * @api private - */ - function isGeneratorFunction(obj) { - var constructor = obj.constructor; - if (!constructor) return false; - if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true; - return isGenerator(constructor.prototype); - } - - /** - * Check for plain object. - * - * @param {Mixed} val - * @return {Boolean} - * @api private - */ - - function isObject(val) { - return Object == val.constructor; - } - - -/***/ }, -/* 19 */ -/***/ function(module, exports) { - - 'use strict'; - - - var Cache = module.exports = function Cache() { - this._cache = {}; - }; - - - Cache.prototype.put = function Cache_put(key, value) { - this._cache[key] = value; - }; - - - Cache.prototype.get = function Cache_get(key) { - return this._cache[key]; - }; - - - Cache.prototype.del = function Cache_del(key) { - delete this._cache[key]; - }; - - - Cache.prototype.clear = function Cache_clear() { - this._cache = {}; - }; - - -/***/ }, -/* 20 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var util = __webpack_require__(11); - - var DATE = /^\d\d\d\d-(\d\d)-(\d\d)$/; - var DAYS = [0,31,29,31,30,31,30,31,31,30,31,30,31]; - var TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i; - var HOSTNAME = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*$/i; - var URI = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i; - var URIREF = /^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i; - // uri-template: https://tools.ietf.org/html/rfc6570 - var URITEMPLATE = /^(?:(?:[^\x00-\x20"'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i; - // For the source: https://gist.github.com/dperini/729294 - // For test cases: https://mathiasbynens.be/demo/url-regex - // @todo Delete current URL in favour of the commented out URL rule when this issue is fixed https://github.com/eslint/eslint/issues/7983. - // var URL = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u{00a1}-\u{ffff}0-9]+-?)*[a-z\u{00a1}-\u{ffff}0-9]+)(?:\.(?:[a-z\u{00a1}-\u{ffff}0-9]+-?)*[a-z\u{00a1}-\u{ffff}0-9]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu; - var URL = /^(?:(?:http[s\u017F]?|ftp):\/\/)(?:(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+(?::(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?@)?(?:(?!10(?:\.[0-9]{1,3}){3})(?!127(?:\.[0-9]{1,3}){3})(?!169\.254(?:\.[0-9]{1,3}){2})(?!192\.168(?:\.[0-9]{1,3}){2})(?!172\.(?:1[6-9]|2[0-9]|3[01])(?:\.[0-9]{1,3}){2})(?:[1-9][0-9]?|1[0-9][0-9]|2[01][0-9]|22[0-3])(?:\.(?:1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])){2}(?:\.(?:[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))|(?:(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)(?:\.(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)*(?:\.(?:(?:[KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){2,})))(?::[0-9]{2,5})?(?:\/(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?$/i; - var UUID = /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i; - var JSON_POINTER = /^(?:\/(?:[^~/]|~0|~1)*)*$|^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i; - var RELATIVE_JSON_POINTER = /^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/; - - - module.exports = formats; - - function formats(mode) { - mode = mode == 'full' ? 'full' : 'fast'; - return util.copy(formats[mode]); - } - - - formats.fast = { - // date: http://tools.ietf.org/html/rfc3339#section-5.6 - date: /^\d\d\d\d-[0-1]\d-[0-3]\d$/, - // date-time: http://tools.ietf.org/html/rfc3339#section-5.6 - time: /^[0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:z|[+-]\d\d:\d\d)?$/i, - 'date-time': /^\d\d\d\d-[0-1]\d-[0-3]\d[t\s][0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:z|[+-]\d\d:\d\d)$/i, - // uri: https://github.com/mafintosh/is-my-json-valid/blob/master/formats.js - uri: /^(?:[a-z][a-z0-9+-.]*)(?::|\/)\/?[^\s]*$/i, - 'uri-reference': /^(?:(?:[a-z][a-z0-9+-.]*:)?\/\/)?[^\s]*$/i, - 'uri-template': URITEMPLATE, - url: URL, - // email (sources from jsen validator): - // http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address#answer-8829363 - // http://www.w3.org/TR/html5/forms.html#valid-e-mail-address (search for 'willful violation') - email: /^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i, - hostname: HOSTNAME, - // optimized https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html - ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/, - // optimized http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses - ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i, - regex: regex, - // uuid: http://tools.ietf.org/html/rfc4122 - uuid: UUID, - // JSON-pointer: https://tools.ietf.org/html/rfc6901 - // uri fragment: https://tools.ietf.org/html/rfc3986#appendix-A - 'json-pointer': JSON_POINTER, - // relative JSON-pointer: http://tools.ietf.org/html/draft-luff-relative-json-pointer-00 - 'relative-json-pointer': RELATIVE_JSON_POINTER - }; - - - formats.full = { - date: date, - time: time, - 'date-time': date_time, - uri: uri, - 'uri-reference': URIREF, - 'uri-template': URITEMPLATE, - url: URL, - email: /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&''*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i, - hostname: hostname, - ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/, - ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i, - regex: regex, - uuid: UUID, - 'json-pointer': JSON_POINTER, - 'relative-json-pointer': RELATIVE_JSON_POINTER - }; - - - function date(str) { - // full-date from http://tools.ietf.org/html/rfc3339#section-5.6 - var matches = str.match(DATE); - if (!matches) return false; - - var month = +matches[1]; - var day = +matches[2]; - return month >= 1 && month <= 12 && day >= 1 && day <= DAYS[month]; - } - - - function time(str, full) { - var matches = str.match(TIME); - if (!matches) return false; - - var hour = matches[1]; - var minute = matches[2]; - var second = matches[3]; - var timeZone = matches[5]; - return hour <= 23 && minute <= 59 && second <= 59 && (!full || timeZone); - } - - - var DATE_TIME_SEPARATOR = /t|\s/i; - function date_time(str) { - // http://tools.ietf.org/html/rfc3339#section-5.6 - var dateTime = str.split(DATE_TIME_SEPARATOR); - return dateTime.length == 2 && date(dateTime[0]) && time(dateTime[1], true); - } - - - function hostname(str) { - // https://tools.ietf.org/html/rfc1034#section-3.5 - // https://tools.ietf.org/html/rfc1123#section-2 - return str.length <= 255 && HOSTNAME.test(str); - } - - - var NOT_URI_FRAGMENT = /\/|:/; - function uri(str) { - // http://jmrware.com/articles/2009/uri_regexp/URI_regex.html + optional protocol + required "." - return NOT_URI_FRAGMENT.test(str) && URI.test(str); - } - - - var Z_ANCHOR = /[^\\]\\Z/; - function regex(str) { - if (Z_ANCHOR.test(str)) return false; - try { - new RegExp(str); - return true; - } catch(e) { - return false; - } - } - - -/***/ }, -/* 21 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var ruleModules = __webpack_require__(22) - , toHash = __webpack_require__(11).toHash; - - module.exports = function rules() { - var RULES = [ - { type: 'number', - rules: [ { 'maximum': ['exclusiveMaximum'] }, - { 'minimum': ['exclusiveMinimum'] }, 'multipleOf', 'format'] }, - { type: 'string', - rules: [ 'maxLength', 'minLength', 'pattern', 'format' ] }, - { type: 'array', - rules: [ 'maxItems', 'minItems', 'uniqueItems', 'contains', 'items' ] }, - { type: 'object', - rules: [ 'maxProperties', 'minProperties', 'required', 'dependencies', 'propertyNames', - { 'properties': ['additionalProperties', 'patternProperties'] } ] }, - { rules: [ '$ref', 'const', 'enum', 'not', 'anyOf', 'oneOf', 'allOf' ] } - ]; - - var ALL = [ 'type' ]; - var KEYWORDS = [ - 'additionalItems', '$schema', '$id', 'id', 'title', - 'description', 'default', 'definitions' - ]; - var TYPES = [ 'number', 'integer', 'string', 'array', 'object', 'boolean', 'null' ]; - RULES.all = toHash(ALL); - RULES.types = toHash(TYPES); - - RULES.forEach(function (group) { - group.rules = group.rules.map(function (keyword) { - var implKeywords; - if (typeof keyword == 'object') { - var key = Object.keys(keyword)[0]; - implKeywords = keyword[key]; - keyword = key; - implKeywords.forEach(function (k) { - ALL.push(k); - RULES.all[k] = true; - }); - } - ALL.push(keyword); - var rule = RULES.all[keyword] = { - keyword: keyword, - code: ruleModules[keyword], - implements: implKeywords - }; - return rule; - }); - - if (group.type) RULES.types[group.type] = group; - }); - - RULES.keywords = toHash(ALL.concat(KEYWORDS)); - RULES.custom = {}; - - return RULES; - }; - - -/***/ }, -/* 22 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - //all requires must be explicit because browserify won't work with dynamic requires - module.exports = { - '$ref': __webpack_require__(23), - allOf: __webpack_require__(24), - anyOf: __webpack_require__(25), - const: __webpack_require__(26), - contains: __webpack_require__(27), - dependencies: __webpack_require__(28), - 'enum': __webpack_require__(29), - format: __webpack_require__(30), - items: __webpack_require__(31), - maximum: __webpack_require__(32), - minimum: __webpack_require__(32), - maxItems: __webpack_require__(33), - minItems: __webpack_require__(33), - maxLength: __webpack_require__(34), - minLength: __webpack_require__(34), - maxProperties: __webpack_require__(35), - minProperties: __webpack_require__(35), - multipleOf: __webpack_require__(36), - not: __webpack_require__(37), - oneOf: __webpack_require__(38), - pattern: __webpack_require__(39), - properties: __webpack_require__(40), - propertyNames: __webpack_require__(41), - required: __webpack_require__(42), - uniqueItems: __webpack_require__(43), - validate: __webpack_require__(17) - }; - - -/***/ }, -/* 23 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_ref(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - var $valid = 'valid' + $lvl; - var $async, $refCode; - if ($schema == '#' || $schema == '#/') { - if (it.isRoot) { - $async = it.async; - $refCode = 'validate'; - } else { - $async = it.root.schema.$async === true; - $refCode = 'root.refVal[0]'; - } - } else { - var $refVal = it.resolveRef(it.baseId, $schema, it.isRoot); - if ($refVal === undefined) { - var $message = it.MissingRefError.message(it.baseId, $schema); - if (it.opts.missingRefs == 'fail') { - it.logger.error($message); - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('$ref') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { ref: \'' + (it.util.escapeQuotes($schema)) + '\' } '; - if (it.opts.messages !== false) { - out += ' , message: \'can\\\'t resolve reference ' + (it.util.escapeQuotes($schema)) + '\' '; - } - if (it.opts.verbose) { - out += ' , schema: ' + (it.util.toQuotedString($schema)) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - if ($breakOnError) { - out += ' if (false) { '; - } - } else if (it.opts.missingRefs == 'ignore') { - it.logger.warn($message); - if ($breakOnError) { - out += ' if (true) { '; - } - } else { - throw new it.MissingRefError(it.baseId, $schema, $message); - } - } else if ($refVal.inline) { - var $it = it.util.copy(it); - $it.level++; - var $nextValid = 'valid' + $it.level; - $it.schema = $refVal.schema; - $it.schemaPath = ''; - $it.errSchemaPath = $schema; - var $code = it.validate($it).replace(/validate\.schema/g, $refVal.code); - out += ' ' + ($code) + ' '; - if ($breakOnError) { - out += ' if (' + ($nextValid) + ') { '; - } - } else { - $async = $refVal.$async === true; - $refCode = $refVal.code; - } - } - if ($refCode) { - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; - if (it.opts.passContext) { - out += ' ' + ($refCode) + '.call(this, '; - } else { - out += ' ' + ($refCode) + '( '; - } - out += ' ' + ($data) + ', (dataPath || \'\')'; - if (it.errorPath != '""') { - out += ' + ' + (it.errorPath); - } - var $parentData = $dataLvl ? 'data' + (($dataLvl - 1) || '') : 'parentData', - $parentDataProperty = $dataLvl ? it.dataPathArr[$dataLvl] : 'parentDataProperty'; - out += ' , ' + ($parentData) + ' , ' + ($parentDataProperty) + ', rootData) '; - var __callValidate = out; - out = $$outStack.pop(); - if ($async) { - if (!it.async) throw new Error('async schema referenced by sync schema'); - if ($breakOnError) { - out += ' var ' + ($valid) + '; '; - } - out += ' try { ' + (it.yieldAwait) + ' ' + (__callValidate) + '; '; - if ($breakOnError) { - out += ' ' + ($valid) + ' = true; '; - } - out += ' } catch (e) { if (!(e instanceof ValidationError)) throw e; if (vErrors === null) vErrors = e.errors; else vErrors = vErrors.concat(e.errors); errors = vErrors.length; '; - if ($breakOnError) { - out += ' ' + ($valid) + ' = false; '; - } - out += ' } '; - if ($breakOnError) { - out += ' if (' + ($valid) + ') { '; - } - } else { - out += ' if (!' + (__callValidate) + ') { if (vErrors === null) vErrors = ' + ($refCode) + '.errors; else vErrors = vErrors.concat(' + ($refCode) + '.errors); errors = vErrors.length; } '; - if ($breakOnError) { - out += ' else { '; - } - } - } - return out; - } - - -/***/ }, -/* 24 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_allOf(it, $keyword, $ruleType) { - var out = ' '; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $it = it.util.copy(it); - var $closingBraces = ''; - $it.level++; - var $nextValid = 'valid' + $it.level; - var $currentBaseId = $it.baseId, - $allSchemasEmpty = true; - var arr1 = $schema; - if (arr1) { - var $sch, $i = -1, - l1 = arr1.length - 1; - while ($i < l1) { - $sch = arr1[$i += 1]; - if (it.util.schemaHasRules($sch, it.RULES.all)) { - $allSchemasEmpty = false; - $it.schema = $sch; - $it.schemaPath = $schemaPath + '[' + $i + ']'; - $it.errSchemaPath = $errSchemaPath + '/' + $i; - out += ' ' + (it.validate($it)) + ' '; - $it.baseId = $currentBaseId; - if ($breakOnError) { - out += ' if (' + ($nextValid) + ') { '; - $closingBraces += '}'; - } - } - } - } - if ($breakOnError) { - if ($allSchemasEmpty) { - out += ' if (true) { '; - } else { - out += ' ' + ($closingBraces.slice(0, -1)) + ' '; - } - } - out = it.util.cleanUpCode(out); - return out; - } - - -/***/ }, -/* 25 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_anyOf(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - var $valid = 'valid' + $lvl; - var $errs = 'errs__' + $lvl; - var $it = it.util.copy(it); - var $closingBraces = ''; - $it.level++; - var $nextValid = 'valid' + $it.level; - var $noEmptySchema = $schema.every(function($sch) { - return it.util.schemaHasRules($sch, it.RULES.all); - }); - if ($noEmptySchema) { - var $currentBaseId = $it.baseId; - out += ' var ' + ($errs) + ' = errors; var ' + ($valid) + ' = false; '; - var $wasComposite = it.compositeRule; - it.compositeRule = $it.compositeRule = true; - var arr1 = $schema; - if (arr1) { - var $sch, $i = -1, - l1 = arr1.length - 1; - while ($i < l1) { - $sch = arr1[$i += 1]; - $it.schema = $sch; - $it.schemaPath = $schemaPath + '[' + $i + ']'; - $it.errSchemaPath = $errSchemaPath + '/' + $i; - out += ' ' + (it.validate($it)) + ' '; - $it.baseId = $currentBaseId; - out += ' ' + ($valid) + ' = ' + ($valid) + ' || ' + ($nextValid) + '; if (!' + ($valid) + ') { '; - $closingBraces += '}'; - } - } - it.compositeRule = $it.compositeRule = $wasComposite; - out += ' ' + ($closingBraces) + ' if (!' + ($valid) + ') { var err = '; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('anyOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; - if (it.opts.messages !== false) { - out += ' , message: \'should match some schema in anyOf\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError(vErrors); '; - } else { - out += ' validate.errors = vErrors; return false; '; - } - } - out += ' } else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } '; - if (it.opts.allErrors) { - out += ' } '; - } - out = it.util.cleanUpCode(out); - } else { - if ($breakOnError) { - out += ' if (true) { '; - } - } - return out; - } - - -/***/ }, -/* 26 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_const(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - var $valid = 'valid' + $lvl; - var $isData = it.opts.$data && $schema && $schema.$data, - $schemaValue; - if ($isData) { - out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; - $schemaValue = 'schema' + $lvl; - } else { - $schemaValue = $schema; - } - if (!$isData) { - out += ' var schema' + ($lvl) + ' = validate.schema' + ($schemaPath) + ';'; - } - out += 'var ' + ($valid) + ' = equal(' + ($data) + ', schema' + ($lvl) + '); if (!' + ($valid) + ') { '; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('const') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; - if (it.opts.messages !== false) { - out += ' , message: \'should be equal to constant\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += ' }'; - if ($breakOnError) { - out += ' else { '; - } - return out; - } - - -/***/ }, -/* 27 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_contains(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - var $valid = 'valid' + $lvl; - var $errs = 'errs__' + $lvl; - var $it = it.util.copy(it); - var $closingBraces = ''; - $it.level++; - var $nextValid = 'valid' + $it.level; - var $idx = 'i' + $lvl, - $dataNxt = $it.dataLevel = it.dataLevel + 1, - $nextData = 'data' + $dataNxt, - $currentBaseId = it.baseId, - $nonEmptySchema = it.util.schemaHasRules($schema, it.RULES.all); - out += 'var ' + ($errs) + ' = errors;var ' + ($valid) + ';'; - if ($nonEmptySchema) { - var $wasComposite = it.compositeRule; - it.compositeRule = $it.compositeRule = true; - $it.schema = $schema; - $it.schemaPath = $schemaPath; - $it.errSchemaPath = $errSchemaPath; - out += ' var ' + ($nextValid) + ' = false; for (var ' + ($idx) + ' = 0; ' + ($idx) + ' < ' + ($data) + '.length; ' + ($idx) + '++) { '; - $it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true); - var $passData = $data + '[' + $idx + ']'; - $it.dataPathArr[$dataNxt] = $idx; - var $code = it.validate($it); - $it.baseId = $currentBaseId; - if (it.util.varOccurences($code, $nextData) < 2) { - out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; - } else { - out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; - } - out += ' if (' + ($nextValid) + ') break; } '; - it.compositeRule = $it.compositeRule = $wasComposite; - out += ' ' + ($closingBraces) + ' if (!' + ($nextValid) + ') {'; - } else { - out += ' if (' + ($data) + '.length == 0) {'; - } - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('contains') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; - if (it.opts.messages !== false) { - out += ' , message: \'should contain a valid item\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += ' } else { '; - if ($nonEmptySchema) { - out += ' errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } '; - } - if (it.opts.allErrors) { - out += ' } '; - } - out = it.util.cleanUpCode(out); - return out; - } - - -/***/ }, -/* 28 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_dependencies(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - var $errs = 'errs__' + $lvl; - var $it = it.util.copy(it); - var $closingBraces = ''; - $it.level++; - var $nextValid = 'valid' + $it.level; - var $schemaDeps = {}, - $propertyDeps = {}, - $ownProperties = it.opts.ownProperties; - for ($property in $schema) { - var $sch = $schema[$property]; - var $deps = Array.isArray($sch) ? $propertyDeps : $schemaDeps; - $deps[$property] = $sch; - } - out += 'var ' + ($errs) + ' = errors;'; - var $currentErrorPath = it.errorPath; - out += 'var missing' + ($lvl) + ';'; - for (var $property in $propertyDeps) { - $deps = $propertyDeps[$property]; - if ($deps.length) { - out += ' if ( ' + ($data) + (it.util.getProperty($property)) + ' !== undefined '; - if ($ownProperties) { - out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($property)) + '\') '; - } - if ($breakOnError) { - out += ' && ( '; - var arr1 = $deps; - if (arr1) { - var $propertyKey, $i = -1, - l1 = arr1.length - 1; - while ($i < l1) { - $propertyKey = arr1[$i += 1]; - if ($i) { - out += ' || '; - } - var $prop = it.util.getProperty($propertyKey), - $useData = $data + $prop; - out += ' ( ( ' + ($useData) + ' === undefined '; - if ($ownProperties) { - out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; - } - out += ') && (missing' + ($lvl) + ' = ' + (it.util.toQuotedString(it.opts.jsonPointers ? $propertyKey : $prop)) + ') ) '; - } - } - out += ')) { '; - var $propertyPath = 'missing' + $lvl, - $missingProperty = '\' + ' + $propertyPath + ' + \''; - if (it.opts._errorDataPathProperty) { - it.errorPath = it.opts.jsonPointers ? it.util.getPathExpr($currentErrorPath, $propertyPath, true) : $currentErrorPath + ' + ' + $propertyPath; - } - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('dependencies') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { property: \'' + (it.util.escapeQuotes($property)) + '\', missingProperty: \'' + ($missingProperty) + '\', depsCount: ' + ($deps.length) + ', deps: \'' + (it.util.escapeQuotes($deps.length == 1 ? $deps[0] : $deps.join(", "))) + '\' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should have '; - if ($deps.length == 1) { - out += 'property ' + (it.util.escapeQuotes($deps[0])); - } else { - out += 'properties ' + (it.util.escapeQuotes($deps.join(", "))); - } - out += ' when property ' + (it.util.escapeQuotes($property)) + ' is present\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - } else { - out += ' ) { '; - var arr2 = $deps; - if (arr2) { - var $propertyKey, i2 = -1, - l2 = arr2.length - 1; - while (i2 < l2) { - $propertyKey = arr2[i2 += 1]; - var $prop = it.util.getProperty($propertyKey), - $missingProperty = it.util.escapeQuotes($propertyKey), - $useData = $data + $prop; - if (it.opts._errorDataPathProperty) { - it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers); - } - out += ' if ( ' + ($useData) + ' === undefined '; - if ($ownProperties) { - out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; - } - out += ') { var err = '; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('dependencies') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { property: \'' + (it.util.escapeQuotes($property)) + '\', missingProperty: \'' + ($missingProperty) + '\', depsCount: ' + ($deps.length) + ', deps: \'' + (it.util.escapeQuotes($deps.length == 1 ? $deps[0] : $deps.join(", "))) + '\' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should have '; - if ($deps.length == 1) { - out += 'property ' + (it.util.escapeQuotes($deps[0])); - } else { - out += 'properties ' + (it.util.escapeQuotes($deps.join(", "))); - } - out += ' when property ' + (it.util.escapeQuotes($property)) + ' is present\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } '; - } - } - } - out += ' } '; - if ($breakOnError) { - $closingBraces += '}'; - out += ' else { '; - } - } - } - it.errorPath = $currentErrorPath; - var $currentBaseId = $it.baseId; - for (var $property in $schemaDeps) { - var $sch = $schemaDeps[$property]; - if (it.util.schemaHasRules($sch, it.RULES.all)) { - out += ' ' + ($nextValid) + ' = true; if ( ' + ($data) + (it.util.getProperty($property)) + ' !== undefined '; - if ($ownProperties) { - out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($property)) + '\') '; - } - out += ') { '; - $it.schema = $sch; - $it.schemaPath = $schemaPath + it.util.getProperty($property); - $it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($property); - out += ' ' + (it.validate($it)) + ' '; - $it.baseId = $currentBaseId; - out += ' } '; - if ($breakOnError) { - out += ' if (' + ($nextValid) + ') { '; - $closingBraces += '}'; - } - } - } - if ($breakOnError) { - out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; - } - out = it.util.cleanUpCode(out); - return out; - } - - -/***/ }, -/* 29 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_enum(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - var $valid = 'valid' + $lvl; - var $isData = it.opts.$data && $schema && $schema.$data, - $schemaValue; - if ($isData) { - out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; - $schemaValue = 'schema' + $lvl; - } else { - $schemaValue = $schema; - } - var $i = 'i' + $lvl, - $vSchema = 'schema' + $lvl; - if (!$isData) { - out += ' var ' + ($vSchema) + ' = validate.schema' + ($schemaPath) + ';'; - } - out += 'var ' + ($valid) + ';'; - if ($isData) { - out += ' if (schema' + ($lvl) + ' === undefined) ' + ($valid) + ' = true; else if (!Array.isArray(schema' + ($lvl) + ')) ' + ($valid) + ' = false; else {'; - } - out += '' + ($valid) + ' = false;for (var ' + ($i) + '=0; ' + ($i) + '<' + ($vSchema) + '.length; ' + ($i) + '++) if (equal(' + ($data) + ', ' + ($vSchema) + '[' + ($i) + '])) { ' + ($valid) + ' = true; break; }'; - if ($isData) { - out += ' } '; - } - out += ' if (!' + ($valid) + ') { '; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('enum') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { allowedValues: schema' + ($lvl) + ' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should be equal to one of the allowed values\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += ' }'; - if ($breakOnError) { - out += ' else { '; - } - return out; - } - - -/***/ }, -/* 30 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_format(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - if (it.opts.format === false) { - if ($breakOnError) { - out += ' if (true) { '; - } - return out; - } - var $isData = it.opts.$data && $schema && $schema.$data, - $schemaValue; - if ($isData) { - out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; - $schemaValue = 'schema' + $lvl; - } else { - $schemaValue = $schema; - } - var $unknownFormats = it.opts.unknownFormats, - $allowUnknown = Array.isArray($unknownFormats); - if ($isData) { - var $format = 'format' + $lvl, - $isObject = 'isObject' + $lvl, - $formatType = 'formatType' + $lvl; - out += ' var ' + ($format) + ' = formats[' + ($schemaValue) + ']; var ' + ($isObject) + ' = typeof ' + ($format) + ' == \'object\' && !(' + ($format) + ' instanceof RegExp) && ' + ($format) + '.validate; var ' + ($formatType) + ' = ' + ($isObject) + ' && ' + ($format) + '.type || \'string\'; if (' + ($isObject) + ') { '; - if (it.async) { - out += ' var async' + ($lvl) + ' = ' + ($format) + '.async; '; - } - out += ' ' + ($format) + ' = ' + ($format) + '.validate; } if ( '; - if ($isData) { - out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'string\') || '; - } - out += ' ('; - if ($unknownFormats != 'ignore') { - out += ' (' + ($schemaValue) + ' && !' + ($format) + ' '; - if ($allowUnknown) { - out += ' && self._opts.unknownFormats.indexOf(' + ($schemaValue) + ') == -1 '; - } - out += ') || '; - } - out += ' (' + ($format) + ' && ' + ($formatType) + ' == \'' + ($ruleType) + '\' && !(typeof ' + ($format) + ' == \'function\' ? '; - if (it.async) { - out += ' (async' + ($lvl) + ' ? ' + (it.yieldAwait) + ' ' + ($format) + '(' + ($data) + ') : ' + ($format) + '(' + ($data) + ')) '; - } else { - out += ' ' + ($format) + '(' + ($data) + ') '; - } - out += ' : ' + ($format) + '.test(' + ($data) + '))))) {'; - } else { - var $format = it.formats[$schema]; - if (!$format) { - if ($unknownFormats == 'ignore') { - it.logger.warn('unknown format "' + $schema + '" ignored in schema at path "' + it.errSchemaPath + '"'); - if ($breakOnError) { - out += ' if (true) { '; - } - return out; - } else if ($allowUnknown && $unknownFormats.indexOf($schema) >= 0) { - if ($breakOnError) { - out += ' if (true) { '; - } - return out; - } else { - throw new Error('unknown format "' + $schema + '" is used in schema at path "' + it.errSchemaPath + '"'); - } - } - var $isObject = typeof $format == 'object' && !($format instanceof RegExp) && $format.validate; - var $formatType = $isObject && $format.type || 'string'; - if ($isObject) { - var $async = $format.async === true; - $format = $format.validate; - } - if ($formatType != $ruleType) { - if ($breakOnError) { - out += ' if (true) { '; - } - return out; - } - if ($async) { - if (!it.async) throw new Error('async format in sync schema'); - var $formatRef = 'formats' + it.util.getProperty($schema) + '.validate'; - out += ' if (!(' + (it.yieldAwait) + ' ' + ($formatRef) + '(' + ($data) + '))) { '; - } else { - out += ' if (! '; - var $formatRef = 'formats' + it.util.getProperty($schema); - if ($isObject) $formatRef += '.validate'; - if (typeof $format == 'function') { - out += ' ' + ($formatRef) + '(' + ($data) + ') '; - } else { - out += ' ' + ($formatRef) + '.test(' + ($data) + ') '; - } - out += ') { '; - } - } - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('format') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { format: '; - if ($isData) { - out += '' + ($schemaValue); - } else { - out += '' + (it.util.toQuotedString($schema)); - } - out += ' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should match format "'; - if ($isData) { - out += '\' + ' + ($schemaValue) + ' + \''; - } else { - out += '' + (it.util.escapeQuotes($schema)); - } - out += '"\' '; - } - if (it.opts.verbose) { - out += ' , schema: '; - if ($isData) { - out += 'validate.schema' + ($schemaPath); - } else { - out += '' + (it.util.toQuotedString($schema)); - } - out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += ' } '; - if ($breakOnError) { - out += ' else { '; - } - return out; - } - - -/***/ }, -/* 31 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_items(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - var $valid = 'valid' + $lvl; - var $errs = 'errs__' + $lvl; - var $it = it.util.copy(it); - var $closingBraces = ''; - $it.level++; - var $nextValid = 'valid' + $it.level; - var $idx = 'i' + $lvl, - $dataNxt = $it.dataLevel = it.dataLevel + 1, - $nextData = 'data' + $dataNxt, - $currentBaseId = it.baseId; - out += 'var ' + ($errs) + ' = errors;var ' + ($valid) + ';'; - if (Array.isArray($schema)) { - var $additionalItems = it.schema.additionalItems; - if ($additionalItems === false) { - out += ' ' + ($valid) + ' = ' + ($data) + '.length <= ' + ($schema.length) + '; '; - var $currErrSchemaPath = $errSchemaPath; - $errSchemaPath = it.errSchemaPath + '/additionalItems'; - out += ' if (!' + ($valid) + ') { '; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('additionalItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schema.length) + ' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should NOT have more than ' + ($schema.length) + ' items\' '; - } - if (it.opts.verbose) { - out += ' , schema: false , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += ' } '; - $errSchemaPath = $currErrSchemaPath; - if ($breakOnError) { - $closingBraces += '}'; - out += ' else { '; - } - } - var arr1 = $schema; - if (arr1) { - var $sch, $i = -1, - l1 = arr1.length - 1; - while ($i < l1) { - $sch = arr1[$i += 1]; - if (it.util.schemaHasRules($sch, it.RULES.all)) { - out += ' ' + ($nextValid) + ' = true; if (' + ($data) + '.length > ' + ($i) + ') { '; - var $passData = $data + '[' + $i + ']'; - $it.schema = $sch; - $it.schemaPath = $schemaPath + '[' + $i + ']'; - $it.errSchemaPath = $errSchemaPath + '/' + $i; - $it.errorPath = it.util.getPathExpr(it.errorPath, $i, it.opts.jsonPointers, true); - $it.dataPathArr[$dataNxt] = $i; - var $code = it.validate($it); - $it.baseId = $currentBaseId; - if (it.util.varOccurences($code, $nextData) < 2) { - out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; - } else { - out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; - } - out += ' } '; - if ($breakOnError) { - out += ' if (' + ($nextValid) + ') { '; - $closingBraces += '}'; - } - } - } - } - if (typeof $additionalItems == 'object' && it.util.schemaHasRules($additionalItems, it.RULES.all)) { - $it.schema = $additionalItems; - $it.schemaPath = it.schemaPath + '.additionalItems'; - $it.errSchemaPath = it.errSchemaPath + '/additionalItems'; - out += ' ' + ($nextValid) + ' = true; if (' + ($data) + '.length > ' + ($schema.length) + ') { for (var ' + ($idx) + ' = ' + ($schema.length) + '; ' + ($idx) + ' < ' + ($data) + '.length; ' + ($idx) + '++) { '; - $it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true); - var $passData = $data + '[' + $idx + ']'; - $it.dataPathArr[$dataNxt] = $idx; - var $code = it.validate($it); - $it.baseId = $currentBaseId; - if (it.util.varOccurences($code, $nextData) < 2) { - out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; - } else { - out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; - } - if ($breakOnError) { - out += ' if (!' + ($nextValid) + ') break; '; - } - out += ' } } '; - if ($breakOnError) { - out += ' if (' + ($nextValid) + ') { '; - $closingBraces += '}'; - } - } - } else if (it.util.schemaHasRules($schema, it.RULES.all)) { - $it.schema = $schema; - $it.schemaPath = $schemaPath; - $it.errSchemaPath = $errSchemaPath; - out += ' for (var ' + ($idx) + ' = ' + (0) + '; ' + ($idx) + ' < ' + ($data) + '.length; ' + ($idx) + '++) { '; - $it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true); - var $passData = $data + '[' + $idx + ']'; - $it.dataPathArr[$dataNxt] = $idx; - var $code = it.validate($it); - $it.baseId = $currentBaseId; - if (it.util.varOccurences($code, $nextData) < 2) { - out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; - } else { - out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; - } - if ($breakOnError) { - out += ' if (!' + ($nextValid) + ') break; '; - } - out += ' }'; - } - if ($breakOnError) { - out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; - } - out = it.util.cleanUpCode(out); - return out; - } - - -/***/ }, -/* 32 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate__limit(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $errorKeyword; - var $data = 'data' + ($dataLvl || ''); - var $isData = it.opts.$data && $schema && $schema.$data, - $schemaValue; - if ($isData) { - out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; - $schemaValue = 'schema' + $lvl; - } else { - $schemaValue = $schema; - } - var $isMax = $keyword == 'maximum', - $exclusiveKeyword = $isMax ? 'exclusiveMaximum' : 'exclusiveMinimum', - $schemaExcl = it.schema[$exclusiveKeyword], - $isDataExcl = it.opts.$data && $schemaExcl && $schemaExcl.$data, - $op = $isMax ? '<' : '>', - $notOp = $isMax ? '>' : '<', - $errorKeyword = undefined; - if ($isDataExcl) { - var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr), - $exclusive = 'exclusive' + $lvl, - $exclType = 'exclType' + $lvl, - $exclIsNumber = 'exclIsNumber' + $lvl, - $opExpr = 'op' + $lvl, - $opStr = '\' + ' + $opExpr + ' + \''; - out += ' var schemaExcl' + ($lvl) + ' = ' + ($schemaValueExcl) + '; '; - $schemaValueExcl = 'schemaExcl' + $lvl; - out += ' var ' + ($exclusive) + '; var ' + ($exclType) + ' = typeof ' + ($schemaValueExcl) + '; if (' + ($exclType) + ' != \'boolean\' && ' + ($exclType) + ' != \'undefined\' && ' + ($exclType) + ' != \'number\') { '; - var $errorKeyword = $exclusiveKeyword; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ($errorKeyword || '_exclusiveLimit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; - if (it.opts.messages !== false) { - out += ' , message: \'' + ($exclusiveKeyword) + ' should be boolean\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += ' } else if ( '; - if ($isData) { - out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; - } - out += ' ' + ($exclType) + ' == \'number\' ? ( (' + ($exclusive) + ' = ' + ($schemaValue) + ' === undefined || ' + ($schemaValueExcl) + ' ' + ($op) + '= ' + ($schemaValue) + ') ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaValueExcl) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) : ( (' + ($exclusive) + ' = ' + ($schemaValueExcl) + ' === true) ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaValue) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) || ' + ($data) + ' !== ' + ($data) + ') { var op' + ($lvl) + ' = ' + ($exclusive) + ' ? \'' + ($op) + '\' : \'' + ($op) + '=\';'; - } else { - var $exclIsNumber = typeof $schemaExcl == 'number', - $opStr = $op; - if ($exclIsNumber && $isData) { - var $opExpr = '\'' + $opStr + '\''; - out += ' if ( '; - if ($isData) { - out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; - } - out += ' ( ' + ($schemaValue) + ' === undefined || ' + ($schemaExcl) + ' ' + ($op) + '= ' + ($schemaValue) + ' ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaExcl) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) || ' + ($data) + ' !== ' + ($data) + ') { '; - } else { - if ($exclIsNumber && $schema === undefined) { - $exclusive = true; - $errorKeyword = $exclusiveKeyword; - $errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword; - $schemaValue = $schemaExcl; - $notOp += '='; - } else { - if ($exclIsNumber) $schemaValue = Math[$isMax ? 'min' : 'max']($schemaExcl, $schema); - if ($schemaExcl === ($exclIsNumber ? $schemaValue : true)) { - $exclusive = true; - $errorKeyword = $exclusiveKeyword; - $errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword; - $notOp += '='; - } else { - $exclusive = false; - $opStr += '='; - } - } - var $opExpr = '\'' + $opStr + '\''; - out += ' if ( '; - if ($isData) { - out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; - } - out += ' ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' || ' + ($data) + ' !== ' + ($data) + ') { '; - } - } - $errorKeyword = $errorKeyword || $keyword; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ($errorKeyword || '_limit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { comparison: ' + ($opExpr) + ', limit: ' + ($schemaValue) + ', exclusive: ' + ($exclusive) + ' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should be ' + ($opStr) + ' '; - if ($isData) { - out += '\' + ' + ($schemaValue); - } else { - out += '' + ($schemaValue) + '\''; - } - } - if (it.opts.verbose) { - out += ' , schema: '; - if ($isData) { - out += 'validate.schema' + ($schemaPath); - } else { - out += '' + ($schema); - } - out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += ' } '; - if ($breakOnError) { - out += ' else { '; - } - return out; - } - - -/***/ }, -/* 33 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate__limitItems(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $errorKeyword; - var $data = 'data' + ($dataLvl || ''); - var $isData = it.opts.$data && $schema && $schema.$data, - $schemaValue; - if ($isData) { - out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; - $schemaValue = 'schema' + $lvl; - } else { - $schemaValue = $schema; - } - var $op = $keyword == 'maxItems' ? '>' : '<'; - out += 'if ( '; - if ($isData) { - out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; - } - out += ' ' + ($data) + '.length ' + ($op) + ' ' + ($schemaValue) + ') { '; - var $errorKeyword = $keyword; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ($errorKeyword || '_limitItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schemaValue) + ' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should NOT have '; - if ($keyword == 'maxItems') { - out += 'more'; - } else { - out += 'less'; - } - out += ' than '; - if ($isData) { - out += '\' + ' + ($schemaValue) + ' + \''; - } else { - out += '' + ($schema); - } - out += ' items\' '; - } - if (it.opts.verbose) { - out += ' , schema: '; - if ($isData) { - out += 'validate.schema' + ($schemaPath); - } else { - out += '' + ($schema); - } - out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += '} '; - if ($breakOnError) { - out += ' else { '; - } - return out; - } - - -/***/ }, -/* 34 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate__limitLength(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $errorKeyword; - var $data = 'data' + ($dataLvl || ''); - var $isData = it.opts.$data && $schema && $schema.$data, - $schemaValue; - if ($isData) { - out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; - $schemaValue = 'schema' + $lvl; - } else { - $schemaValue = $schema; - } - var $op = $keyword == 'maxLength' ? '>' : '<'; - out += 'if ( '; - if ($isData) { - out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; - } - if (it.opts.unicode === false) { - out += ' ' + ($data) + '.length '; - } else { - out += ' ucs2length(' + ($data) + ') '; - } - out += ' ' + ($op) + ' ' + ($schemaValue) + ') { '; - var $errorKeyword = $keyword; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ($errorKeyword || '_limitLength') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schemaValue) + ' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should NOT be '; - if ($keyword == 'maxLength') { - out += 'longer'; - } else { - out += 'shorter'; - } - out += ' than '; - if ($isData) { - out += '\' + ' + ($schemaValue) + ' + \''; - } else { - out += '' + ($schema); - } - out += ' characters\' '; - } - if (it.opts.verbose) { - out += ' , schema: '; - if ($isData) { - out += 'validate.schema' + ($schemaPath); - } else { - out += '' + ($schema); - } - out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += '} '; - if ($breakOnError) { - out += ' else { '; - } - return out; - } - - -/***/ }, -/* 35 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate__limitProperties(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $errorKeyword; - var $data = 'data' + ($dataLvl || ''); - var $isData = it.opts.$data && $schema && $schema.$data, - $schemaValue; - if ($isData) { - out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; - $schemaValue = 'schema' + $lvl; - } else { - $schemaValue = $schema; - } - var $op = $keyword == 'maxProperties' ? '>' : '<'; - out += 'if ( '; - if ($isData) { - out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; - } - out += ' Object.keys(' + ($data) + ').length ' + ($op) + ' ' + ($schemaValue) + ') { '; - var $errorKeyword = $keyword; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ($errorKeyword || '_limitProperties') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schemaValue) + ' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should NOT have '; - if ($keyword == 'maxProperties') { - out += 'more'; - } else { - out += 'less'; - } - out += ' than '; - if ($isData) { - out += '\' + ' + ($schemaValue) + ' + \''; - } else { - out += '' + ($schema); - } - out += ' properties\' '; - } - if (it.opts.verbose) { - out += ' , schema: '; - if ($isData) { - out += 'validate.schema' + ($schemaPath); - } else { - out += '' + ($schema); - } - out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += '} '; - if ($breakOnError) { - out += ' else { '; - } - return out; - } - - -/***/ }, -/* 36 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_multipleOf(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - var $isData = it.opts.$data && $schema && $schema.$data, - $schemaValue; - if ($isData) { - out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; - $schemaValue = 'schema' + $lvl; - } else { - $schemaValue = $schema; - } - out += 'var division' + ($lvl) + ';if ('; - if ($isData) { - out += ' ' + ($schemaValue) + ' !== undefined && ( typeof ' + ($schemaValue) + ' != \'number\' || '; - } - out += ' (division' + ($lvl) + ' = ' + ($data) + ' / ' + ($schemaValue) + ', '; - if (it.opts.multipleOfPrecision) { - out += ' Math.abs(Math.round(division' + ($lvl) + ') - division' + ($lvl) + ') > 1e-' + (it.opts.multipleOfPrecision) + ' '; - } else { - out += ' division' + ($lvl) + ' !== parseInt(division' + ($lvl) + ') '; - } - out += ' ) '; - if ($isData) { - out += ' ) '; - } - out += ' ) { '; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('multipleOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { multipleOf: ' + ($schemaValue) + ' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should be multiple of '; - if ($isData) { - out += '\' + ' + ($schemaValue); - } else { - out += '' + ($schemaValue) + '\''; - } - } - if (it.opts.verbose) { - out += ' , schema: '; - if ($isData) { - out += 'validate.schema' + ($schemaPath); - } else { - out += '' + ($schema); - } - out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += '} '; - if ($breakOnError) { - out += ' else { '; - } - return out; - } - - -/***/ }, -/* 37 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_not(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - var $errs = 'errs__' + $lvl; - var $it = it.util.copy(it); - $it.level++; - var $nextValid = 'valid' + $it.level; - if (it.util.schemaHasRules($schema, it.RULES.all)) { - $it.schema = $schema; - $it.schemaPath = $schemaPath; - $it.errSchemaPath = $errSchemaPath; - out += ' var ' + ($errs) + ' = errors; '; - var $wasComposite = it.compositeRule; - it.compositeRule = $it.compositeRule = true; - $it.createErrors = false; - var $allErrorsOption; - if ($it.opts.allErrors) { - $allErrorsOption = $it.opts.allErrors; - $it.opts.allErrors = false; - } - out += ' ' + (it.validate($it)) + ' '; - $it.createErrors = true; - if ($allErrorsOption) $it.opts.allErrors = $allErrorsOption; - it.compositeRule = $it.compositeRule = $wasComposite; - out += ' if (' + ($nextValid) + ') { '; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('not') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; - if (it.opts.messages !== false) { - out += ' , message: \'should NOT be valid\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += ' } else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } '; - if (it.opts.allErrors) { - out += ' } '; - } - } else { - out += ' var err = '; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('not') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; - if (it.opts.messages !== false) { - out += ' , message: \'should NOT be valid\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - if ($breakOnError) { - out += ' if (false) { '; - } - } - return out; - } - - -/***/ }, -/* 38 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_oneOf(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - var $valid = 'valid' + $lvl; - var $errs = 'errs__' + $lvl; - var $it = it.util.copy(it); - var $closingBraces = ''; - $it.level++; - var $nextValid = 'valid' + $it.level; - out += 'var ' + ($errs) + ' = errors;var prevValid' + ($lvl) + ' = false;var ' + ($valid) + ' = false;'; - var $currentBaseId = $it.baseId; - var $wasComposite = it.compositeRule; - it.compositeRule = $it.compositeRule = true; - var arr1 = $schema; - if (arr1) { - var $sch, $i = -1, - l1 = arr1.length - 1; - while ($i < l1) { - $sch = arr1[$i += 1]; - if (it.util.schemaHasRules($sch, it.RULES.all)) { - $it.schema = $sch; - $it.schemaPath = $schemaPath + '[' + $i + ']'; - $it.errSchemaPath = $errSchemaPath + '/' + $i; - out += ' ' + (it.validate($it)) + ' '; - $it.baseId = $currentBaseId; - } else { - out += ' var ' + ($nextValid) + ' = true; '; - } - if ($i) { - out += ' if (' + ($nextValid) + ' && prevValid' + ($lvl) + ') ' + ($valid) + ' = false; else { '; - $closingBraces += '}'; - } - out += ' if (' + ($nextValid) + ') ' + ($valid) + ' = prevValid' + ($lvl) + ' = true;'; - } - } - it.compositeRule = $it.compositeRule = $wasComposite; - out += '' + ($closingBraces) + 'if (!' + ($valid) + ') { var err = '; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('oneOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; - if (it.opts.messages !== false) { - out += ' , message: \'should match exactly one schema in oneOf\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError(vErrors); '; - } else { - out += ' validate.errors = vErrors; return false; '; - } - } - out += '} else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; }'; - if (it.opts.allErrors) { - out += ' } '; - } - return out; - } - - -/***/ }, -/* 39 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_pattern(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - var $isData = it.opts.$data && $schema && $schema.$data, - $schemaValue; - if ($isData) { - out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; - $schemaValue = 'schema' + $lvl; - } else { - $schemaValue = $schema; - } - var $regexp = $isData ? '(new RegExp(' + $schemaValue + '))' : it.usePattern($schema); - out += 'if ( '; - if ($isData) { - out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'string\') || '; - } - out += ' !' + ($regexp) + '.test(' + ($data) + ') ) { '; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('pattern') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { pattern: '; - if ($isData) { - out += '' + ($schemaValue); - } else { - out += '' + (it.util.toQuotedString($schema)); - } - out += ' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should match pattern "'; - if ($isData) { - out += '\' + ' + ($schemaValue) + ' + \''; - } else { - out += '' + (it.util.escapeQuotes($schema)); - } - out += '"\' '; - } - if (it.opts.verbose) { - out += ' , schema: '; - if ($isData) { - out += 'validate.schema' + ($schemaPath); - } else { - out += '' + (it.util.toQuotedString($schema)); - } - out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += '} '; - if ($breakOnError) { - out += ' else { '; - } - return out; - } - - -/***/ }, -/* 40 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_properties(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - var $valid = 'valid' + $lvl; - var $errs = 'errs__' + $lvl; - var $it = it.util.copy(it); - var $closingBraces = ''; - $it.level++; - var $nextValid = 'valid' + $it.level; - var $key = 'key' + $lvl, - $idx = 'idx' + $lvl, - $dataNxt = $it.dataLevel = it.dataLevel + 1, - $nextData = 'data' + $dataNxt, - $dataProperties = 'dataProperties' + $lvl; - var $schemaKeys = Object.keys($schema || {}), - $pProperties = it.schema.patternProperties || {}, - $pPropertyKeys = Object.keys($pProperties), - $aProperties = it.schema.additionalProperties, - $someProperties = $schemaKeys.length || $pPropertyKeys.length, - $noAdditional = $aProperties === false, - $additionalIsSchema = typeof $aProperties == 'object' && Object.keys($aProperties).length, - $removeAdditional = it.opts.removeAdditional, - $checkAdditional = $noAdditional || $additionalIsSchema || $removeAdditional, - $ownProperties = it.opts.ownProperties, - $currentBaseId = it.baseId; - var $required = it.schema.required; - if ($required && !(it.opts.v5 && $required.$data) && $required.length < it.opts.loopRequired) var $requiredHash = it.util.toHash($required); - if (it.opts.patternGroups) { - var $pgProperties = it.schema.patternGroups || {}, - $pgPropertyKeys = Object.keys($pgProperties); - } - out += 'var ' + ($errs) + ' = errors;var ' + ($nextValid) + ' = true;'; - if ($ownProperties) { - out += ' var ' + ($dataProperties) + ' = undefined;'; - } - if ($checkAdditional) { - if ($ownProperties) { - out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; '; - } else { - out += ' for (var ' + ($key) + ' in ' + ($data) + ') { '; - } - if ($someProperties) { - out += ' var isAdditional' + ($lvl) + ' = !(false '; - if ($schemaKeys.length) { - if ($schemaKeys.length > 5) { - out += ' || validate.schema' + ($schemaPath) + '[' + ($key) + '] '; - } else { - var arr1 = $schemaKeys; - if (arr1) { - var $propertyKey, i1 = -1, - l1 = arr1.length - 1; - while (i1 < l1) { - $propertyKey = arr1[i1 += 1]; - out += ' || ' + ($key) + ' == ' + (it.util.toQuotedString($propertyKey)) + ' '; - } - } - } - } - if ($pPropertyKeys.length) { - var arr2 = $pPropertyKeys; - if (arr2) { - var $pProperty, $i = -1, - l2 = arr2.length - 1; - while ($i < l2) { - $pProperty = arr2[$i += 1]; - out += ' || ' + (it.usePattern($pProperty)) + '.test(' + ($key) + ') '; - } - } - } - if (it.opts.patternGroups && $pgPropertyKeys.length) { - var arr3 = $pgPropertyKeys; - if (arr3) { - var $pgProperty, $i = -1, - l3 = arr3.length - 1; - while ($i < l3) { - $pgProperty = arr3[$i += 1]; - out += ' || ' + (it.usePattern($pgProperty)) + '.test(' + ($key) + ') '; - } - } - } - out += ' ); if (isAdditional' + ($lvl) + ') { '; - } - if ($removeAdditional == 'all') { - out += ' delete ' + ($data) + '[' + ($key) + ']; '; - } else { - var $currentErrorPath = it.errorPath; - var $additionalProperty = '\' + ' + $key + ' + \''; - if (it.opts._errorDataPathProperty) { - it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); - } - if ($noAdditional) { - if ($removeAdditional) { - out += ' delete ' + ($data) + '[' + ($key) + ']; '; - } else { - out += ' ' + ($nextValid) + ' = false; '; - var $currErrSchemaPath = $errSchemaPath; - $errSchemaPath = it.errSchemaPath + '/additionalProperties'; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('additionalProperties') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { additionalProperty: \'' + ($additionalProperty) + '\' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should NOT have additional properties\' '; - } - if (it.opts.verbose) { - out += ' , schema: false , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - $errSchemaPath = $currErrSchemaPath; - if ($breakOnError) { - out += ' break; '; - } - } - } else if ($additionalIsSchema) { - if ($removeAdditional == 'failing') { - out += ' var ' + ($errs) + ' = errors; '; - var $wasComposite = it.compositeRule; - it.compositeRule = $it.compositeRule = true; - $it.schema = $aProperties; - $it.schemaPath = it.schemaPath + '.additionalProperties'; - $it.errSchemaPath = it.errSchemaPath + '/additionalProperties'; - $it.errorPath = it.opts._errorDataPathProperty ? it.errorPath : it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); - var $passData = $data + '[' + $key + ']'; - $it.dataPathArr[$dataNxt] = $key; - var $code = it.validate($it); - $it.baseId = $currentBaseId; - if (it.util.varOccurences($code, $nextData) < 2) { - out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; - } else { - out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; - } - out += ' if (!' + ($nextValid) + ') { errors = ' + ($errs) + '; if (validate.errors !== null) { if (errors) validate.errors.length = errors; else validate.errors = null; } delete ' + ($data) + '[' + ($key) + ']; } '; - it.compositeRule = $it.compositeRule = $wasComposite; - } else { - $it.schema = $aProperties; - $it.schemaPath = it.schemaPath + '.additionalProperties'; - $it.errSchemaPath = it.errSchemaPath + '/additionalProperties'; - $it.errorPath = it.opts._errorDataPathProperty ? it.errorPath : it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); - var $passData = $data + '[' + $key + ']'; - $it.dataPathArr[$dataNxt] = $key; - var $code = it.validate($it); - $it.baseId = $currentBaseId; - if (it.util.varOccurences($code, $nextData) < 2) { - out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; - } else { - out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; - } - if ($breakOnError) { - out += ' if (!' + ($nextValid) + ') break; '; - } - } - } - it.errorPath = $currentErrorPath; - } - if ($someProperties) { - out += ' } '; - } - out += ' } '; - if ($breakOnError) { - out += ' if (' + ($nextValid) + ') { '; - $closingBraces += '}'; - } - } - var $useDefaults = it.opts.useDefaults && !it.compositeRule; - if ($schemaKeys.length) { - var arr4 = $schemaKeys; - if (arr4) { - var $propertyKey, i4 = -1, - l4 = arr4.length - 1; - while (i4 < l4) { - $propertyKey = arr4[i4 += 1]; - var $sch = $schema[$propertyKey]; - if (it.util.schemaHasRules($sch, it.RULES.all)) { - var $prop = it.util.getProperty($propertyKey), - $passData = $data + $prop, - $hasDefault = $useDefaults && $sch.default !== undefined; - $it.schema = $sch; - $it.schemaPath = $schemaPath + $prop; - $it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($propertyKey); - $it.errorPath = it.util.getPath(it.errorPath, $propertyKey, it.opts.jsonPointers); - $it.dataPathArr[$dataNxt] = it.util.toQuotedString($propertyKey); - var $code = it.validate($it); - $it.baseId = $currentBaseId; - if (it.util.varOccurences($code, $nextData) < 2) { - $code = it.util.varReplace($code, $nextData, $passData); - var $useData = $passData; - } else { - var $useData = $nextData; - out += ' var ' + ($nextData) + ' = ' + ($passData) + '; '; - } - if ($hasDefault) { - out += ' ' + ($code) + ' '; - } else { - if ($requiredHash && $requiredHash[$propertyKey]) { - out += ' if ( ' + ($useData) + ' === undefined '; - if ($ownProperties) { - out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; - } - out += ') { ' + ($nextValid) + ' = false; '; - var $currentErrorPath = it.errorPath, - $currErrSchemaPath = $errSchemaPath, - $missingProperty = it.util.escapeQuotes($propertyKey); - if (it.opts._errorDataPathProperty) { - it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers); - } - $errSchemaPath = it.errSchemaPath + '/required'; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; - if (it.opts.messages !== false) { - out += ' , message: \''; - if (it.opts._errorDataPathProperty) { - out += 'is a required property'; - } else { - out += 'should have required property \\\'' + ($missingProperty) + '\\\''; - } - out += '\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - $errSchemaPath = $currErrSchemaPath; - it.errorPath = $currentErrorPath; - out += ' } else { '; - } else { - if ($breakOnError) { - out += ' if ( ' + ($useData) + ' === undefined '; - if ($ownProperties) { - out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; - } - out += ') { ' + ($nextValid) + ' = true; } else { '; - } else { - out += ' if (' + ($useData) + ' !== undefined '; - if ($ownProperties) { - out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; - } - out += ' ) { '; - } - } - out += ' ' + ($code) + ' } '; - } - } - if ($breakOnError) { - out += ' if (' + ($nextValid) + ') { '; - $closingBraces += '}'; - } - } - } - } - if ($pPropertyKeys.length) { - var arr5 = $pPropertyKeys; - if (arr5) { - var $pProperty, i5 = -1, - l5 = arr5.length - 1; - while (i5 < l5) { - $pProperty = arr5[i5 += 1]; - var $sch = $pProperties[$pProperty]; - if (it.util.schemaHasRules($sch, it.RULES.all)) { - $it.schema = $sch; - $it.schemaPath = it.schemaPath + '.patternProperties' + it.util.getProperty($pProperty); - $it.errSchemaPath = it.errSchemaPath + '/patternProperties/' + it.util.escapeFragment($pProperty); - if ($ownProperties) { - out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; '; - } else { - out += ' for (var ' + ($key) + ' in ' + ($data) + ') { '; - } - out += ' if (' + (it.usePattern($pProperty)) + '.test(' + ($key) + ')) { '; - $it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); - var $passData = $data + '[' + $key + ']'; - $it.dataPathArr[$dataNxt] = $key; - var $code = it.validate($it); - $it.baseId = $currentBaseId; - if (it.util.varOccurences($code, $nextData) < 2) { - out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; - } else { - out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; - } - if ($breakOnError) { - out += ' if (!' + ($nextValid) + ') break; '; - } - out += ' } '; - if ($breakOnError) { - out += ' else ' + ($nextValid) + ' = true; '; - } - out += ' } '; - if ($breakOnError) { - out += ' if (' + ($nextValid) + ') { '; - $closingBraces += '}'; - } - } - } - } - } - if (it.opts.patternGroups && $pgPropertyKeys.length) { - var arr6 = $pgPropertyKeys; - if (arr6) { - var $pgProperty, i6 = -1, - l6 = arr6.length - 1; - while (i6 < l6) { - $pgProperty = arr6[i6 += 1]; - var $pgSchema = $pgProperties[$pgProperty], - $sch = $pgSchema.schema; - if (it.util.schemaHasRules($sch, it.RULES.all)) { - $it.schema = $sch; - $it.schemaPath = it.schemaPath + '.patternGroups' + it.util.getProperty($pgProperty) + '.schema'; - $it.errSchemaPath = it.errSchemaPath + '/patternGroups/' + it.util.escapeFragment($pgProperty) + '/schema'; - out += ' var pgPropCount' + ($lvl) + ' = 0; '; - if ($ownProperties) { - out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; '; - } else { - out += ' for (var ' + ($key) + ' in ' + ($data) + ') { '; - } - out += ' if (' + (it.usePattern($pgProperty)) + '.test(' + ($key) + ')) { pgPropCount' + ($lvl) + '++; '; - $it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); - var $passData = $data + '[' + $key + ']'; - $it.dataPathArr[$dataNxt] = $key; - var $code = it.validate($it); - $it.baseId = $currentBaseId; - if (it.util.varOccurences($code, $nextData) < 2) { - out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; - } else { - out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; - } - if ($breakOnError) { - out += ' if (!' + ($nextValid) + ') break; '; - } - out += ' } '; - if ($breakOnError) { - out += ' else ' + ($nextValid) + ' = true; '; - } - out += ' } '; - if ($breakOnError) { - out += ' if (' + ($nextValid) + ') { '; - $closingBraces += '}'; - } - var $pgMin = $pgSchema.minimum, - $pgMax = $pgSchema.maximum; - if ($pgMin !== undefined || $pgMax !== undefined) { - out += ' var ' + ($valid) + ' = true; '; - var $currErrSchemaPath = $errSchemaPath; - if ($pgMin !== undefined) { - var $limit = $pgMin, - $reason = 'minimum', - $moreOrLess = 'less'; - out += ' ' + ($valid) + ' = pgPropCount' + ($lvl) + ' >= ' + ($pgMin) + '; '; - $errSchemaPath = it.errSchemaPath + '/patternGroups/minimum'; - out += ' if (!' + ($valid) + ') { '; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('patternGroups') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { reason: \'' + ($reason) + '\', limit: ' + ($limit) + ', pattern: \'' + (it.util.escapeQuotes($pgProperty)) + '\' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should NOT have ' + ($moreOrLess) + ' than ' + ($limit) + ' properties matching pattern "' + (it.util.escapeQuotes($pgProperty)) + '"\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += ' } '; - if ($pgMax !== undefined) { - out += ' else '; - } - } - if ($pgMax !== undefined) { - var $limit = $pgMax, - $reason = 'maximum', - $moreOrLess = 'more'; - out += ' ' + ($valid) + ' = pgPropCount' + ($lvl) + ' <= ' + ($pgMax) + '; '; - $errSchemaPath = it.errSchemaPath + '/patternGroups/maximum'; - out += ' if (!' + ($valid) + ') { '; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('patternGroups') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { reason: \'' + ($reason) + '\', limit: ' + ($limit) + ', pattern: \'' + (it.util.escapeQuotes($pgProperty)) + '\' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should NOT have ' + ($moreOrLess) + ' than ' + ($limit) + ' properties matching pattern "' + (it.util.escapeQuotes($pgProperty)) + '"\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += ' } '; - } - $errSchemaPath = $currErrSchemaPath; - if ($breakOnError) { - out += ' if (' + ($valid) + ') { '; - $closingBraces += '}'; - } - } - } - } - } - } - if ($breakOnError) { - out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; - } - out = it.util.cleanUpCode(out); - return out; - } - - -/***/ }, -/* 41 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_propertyNames(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - var $errs = 'errs__' + $lvl; - var $it = it.util.copy(it); - var $closingBraces = ''; - $it.level++; - var $nextValid = 'valid' + $it.level; - if (it.util.schemaHasRules($schema, it.RULES.all)) { - $it.schema = $schema; - $it.schemaPath = $schemaPath; - $it.errSchemaPath = $errSchemaPath; - var $key = 'key' + $lvl, - $idx = 'idx' + $lvl, - $i = 'i' + $lvl, - $invalidName = '\' + ' + $key + ' + \'', - $dataNxt = $it.dataLevel = it.dataLevel + 1, - $nextData = 'data' + $dataNxt, - $dataProperties = 'dataProperties' + $lvl, - $ownProperties = it.opts.ownProperties, - $currentBaseId = it.baseId; - out += ' var ' + ($errs) + ' = errors; '; - if ($ownProperties) { - out += ' var ' + ($dataProperties) + ' = undefined; '; - } - if ($ownProperties) { - out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; '; - } else { - out += ' for (var ' + ($key) + ' in ' + ($data) + ') { '; - } - out += ' var startErrs' + ($lvl) + ' = errors; '; - var $passData = $key; - var $wasComposite = it.compositeRule; - it.compositeRule = $it.compositeRule = true; - var $code = it.validate($it); - $it.baseId = $currentBaseId; - if (it.util.varOccurences($code, $nextData) < 2) { - out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; - } else { - out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; - } - it.compositeRule = $it.compositeRule = $wasComposite; - out += ' if (!' + ($nextValid) + ') { for (var ' + ($i) + '=startErrs' + ($lvl) + '; ' + ($i) + '= it.opts.loopRequired, - $ownProperties = it.opts.ownProperties; - if ($breakOnError) { - out += ' var missing' + ($lvl) + '; '; - if ($loopRequired) { - if (!$isData) { - out += ' var ' + ($vSchema) + ' = validate.schema' + ($schemaPath) + '; '; - } - var $i = 'i' + $lvl, - $propertyPath = 'schema' + $lvl + '[' + $i + ']', - $missingProperty = '\' + ' + $propertyPath + ' + \''; - if (it.opts._errorDataPathProperty) { - it.errorPath = it.util.getPathExpr($currentErrorPath, $propertyPath, it.opts.jsonPointers); - } - out += ' var ' + ($valid) + ' = true; '; - if ($isData) { - out += ' if (schema' + ($lvl) + ' === undefined) ' + ($valid) + ' = true; else if (!Array.isArray(schema' + ($lvl) + ')) ' + ($valid) + ' = false; else {'; - } - out += ' for (var ' + ($i) + ' = 0; ' + ($i) + ' < ' + ($vSchema) + '.length; ' + ($i) + '++) { ' + ($valid) + ' = ' + ($data) + '[' + ($vSchema) + '[' + ($i) + ']] !== undefined '; - if ($ownProperties) { - out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', ' + ($vSchema) + '[' + ($i) + ']) '; - } - out += '; if (!' + ($valid) + ') break; } '; - if ($isData) { - out += ' } '; - } - out += ' if (!' + ($valid) + ') { '; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; - if (it.opts.messages !== false) { - out += ' , message: \''; - if (it.opts._errorDataPathProperty) { - out += 'is a required property'; - } else { - out += 'should have required property \\\'' + ($missingProperty) + '\\\''; - } - out += '\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += ' } else { '; - } else { - out += ' if ( '; - var arr2 = $required; - if (arr2) { - var $propertyKey, $i = -1, - l2 = arr2.length - 1; - while ($i < l2) { - $propertyKey = arr2[$i += 1]; - if ($i) { - out += ' || '; - } - var $prop = it.util.getProperty($propertyKey), - $useData = $data + $prop; - out += ' ( ( ' + ($useData) + ' === undefined '; - if ($ownProperties) { - out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; - } - out += ') && (missing' + ($lvl) + ' = ' + (it.util.toQuotedString(it.opts.jsonPointers ? $propertyKey : $prop)) + ') ) '; - } - } - out += ') { '; - var $propertyPath = 'missing' + $lvl, - $missingProperty = '\' + ' + $propertyPath + ' + \''; - if (it.opts._errorDataPathProperty) { - it.errorPath = it.opts.jsonPointers ? it.util.getPathExpr($currentErrorPath, $propertyPath, true) : $currentErrorPath + ' + ' + $propertyPath; - } - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; - if (it.opts.messages !== false) { - out += ' , message: \''; - if (it.opts._errorDataPathProperty) { - out += 'is a required property'; - } else { - out += 'should have required property \\\'' + ($missingProperty) + '\\\''; - } - out += '\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += ' } else { '; - } - } else { - if ($loopRequired) { - if (!$isData) { - out += ' var ' + ($vSchema) + ' = validate.schema' + ($schemaPath) + '; '; - } - var $i = 'i' + $lvl, - $propertyPath = 'schema' + $lvl + '[' + $i + ']', - $missingProperty = '\' + ' + $propertyPath + ' + \''; - if (it.opts._errorDataPathProperty) { - it.errorPath = it.util.getPathExpr($currentErrorPath, $propertyPath, it.opts.jsonPointers); - } - if ($isData) { - out += ' if (' + ($vSchema) + ' && !Array.isArray(' + ($vSchema) + ')) { var err = '; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; - if (it.opts.messages !== false) { - out += ' , message: \''; - if (it.opts._errorDataPathProperty) { - out += 'is a required property'; - } else { - out += 'should have required property \\\'' + ($missingProperty) + '\\\''; - } - out += '\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } else if (' + ($vSchema) + ' !== undefined) { '; - } - out += ' for (var ' + ($i) + ' = 0; ' + ($i) + ' < ' + ($vSchema) + '.length; ' + ($i) + '++) { if (' + ($data) + '[' + ($vSchema) + '[' + ($i) + ']] === undefined '; - if ($ownProperties) { - out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', ' + ($vSchema) + '[' + ($i) + ']) '; - } - out += ') { var err = '; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; - if (it.opts.messages !== false) { - out += ' , message: \''; - if (it.opts._errorDataPathProperty) { - out += 'is a required property'; - } else { - out += 'should have required property \\\'' + ($missingProperty) + '\\\''; - } - out += '\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } } '; - if ($isData) { - out += ' } '; - } - } else { - var arr3 = $required; - if (arr3) { - var $propertyKey, i3 = -1, - l3 = arr3.length - 1; - while (i3 < l3) { - $propertyKey = arr3[i3 += 1]; - var $prop = it.util.getProperty($propertyKey), - $missingProperty = it.util.escapeQuotes($propertyKey), - $useData = $data + $prop; - if (it.opts._errorDataPathProperty) { - it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers); - } - out += ' if ( ' + ($useData) + ' === undefined '; - if ($ownProperties) { - out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; - } - out += ') { var err = '; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; - if (it.opts.messages !== false) { - out += ' , message: \''; - if (it.opts._errorDataPathProperty) { - out += 'is a required property'; - } else { - out += 'should have required property \\\'' + ($missingProperty) + '\\\''; - } - out += '\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } '; - } - } - } - } - it.errorPath = $currentErrorPath; - } else if ($breakOnError) { - out += ' if (true) {'; - } - return out; - } - - -/***/ }, -/* 43 */ -/***/ function(module, exports) { - - 'use strict'; - module.exports = function generate_uniqueItems(it, $keyword, $ruleType) { - var out = ' '; - var $lvl = it.level; - var $dataLvl = it.dataLevel; - var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + it.util.getProperty($keyword); - var $errSchemaPath = it.errSchemaPath + '/' + $keyword; - var $breakOnError = !it.opts.allErrors; - var $data = 'data' + ($dataLvl || ''); - var $valid = 'valid' + $lvl; - var $isData = it.opts.$data && $schema && $schema.$data, - $schemaValue; - if ($isData) { - out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; - $schemaValue = 'schema' + $lvl; - } else { - $schemaValue = $schema; - } - if (($schema || $isData) && it.opts.uniqueItems !== false) { - if ($isData) { - out += ' var ' + ($valid) + '; if (' + ($schemaValue) + ' === false || ' + ($schemaValue) + ' === undefined) ' + ($valid) + ' = true; else if (typeof ' + ($schemaValue) + ' != \'boolean\') ' + ($valid) + ' = false; else { '; - } - out += ' var ' + ($valid) + ' = true; if (' + ($data) + '.length > 1) { var i = ' + ($data) + '.length, j; outer: for (;i--;) { for (j = i; j--;) { if (equal(' + ($data) + '[i], ' + ($data) + '[j])) { ' + ($valid) + ' = false; break outer; } } } } '; - if ($isData) { - out += ' } '; - } - out += ' if (!' + ($valid) + ') { '; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ('uniqueItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { i: i, j: j } '; - if (it.opts.messages !== false) { - out += ' , message: \'should NOT have duplicate items (items ## \' + j + \' and \' + i + \' are identical)\' '; - } - if (it.opts.verbose) { - out += ' , schema: '; - if ($isData) { - out += 'validate.schema' + ($schemaPath); - } else { - out += '' + ($schema); - } - out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - out += ' } '; - if ($breakOnError) { - out += ' else { '; - } - } else { - if ($breakOnError) { - out += ' if (true) { '; - } - } - return out; - } - - -/***/ }, -/* 44 */ -/***/ function(module, exports) { - - 'use strict'; - - var KEYWORDS = [ - 'multipleOf', - 'maximum', - 'exclusiveMaximum', - 'minimum', - 'exclusiveMinimum', - 'maxLength', - 'minLength', - 'pattern', - 'additionalItems', - 'maxItems', - 'minItems', - 'uniqueItems', - 'maxProperties', - 'minProperties', - 'required', - 'additionalProperties', - 'enum', - 'format', - 'const' - ]; - - module.exports = function (metaSchema, keywordsJsonPointers) { - for (var i=0; i 0) { - this.autoScrollStep = ((top + margin) - mouseY) / 3; - } - else if (mouseY > bottom - margin && - height + content.scrollTop < content.scrollHeight) { - this.autoScrollStep = ((bottom - margin) - mouseY) / 3; - } - else { - this.autoScrollStep = undefined; - } - - if (this.autoScrollStep) { - if (!this.autoScrollTimer) { - this.autoScrollTimer = setInterval(function () { - if (me.autoScrollStep) { - content.scrollTop -= me.autoScrollStep; - } - else { - me.stopAutoScroll(); - } - }, interval); - } - } - else { - this.stopAutoScroll(); - } - }; - - /** - * Stop auto scrolling. Only applicable when scrolling - */ - treemode.stopAutoScroll = function () { - if (this.autoScrollTimer) { - clearTimeout(this.autoScrollTimer); - delete this.autoScrollTimer; - } - if (this.autoScrollStep) { - delete this.autoScrollStep; - } - }; - - - /** - * Set the focus to an element in the editor, set text selection, and - * set scroll position. - * @param {Object} selection An object containing fields: - * {Element | undefined} dom The dom element - * which has focus - * {Range | TextRange} range A text selection - * {Node[]} nodes Nodes in case of multi selection - * {Number} scrollTop Scroll position - */ - treemode.setSelection = function (selection) { - if (!selection) { - return; - } - - if ('scrollTop' in selection && this.content) { - // TODO: animated scroll - this.content.scrollTop = selection.scrollTop; - } - if (selection.nodes) { - // multi-select - this.select(selection.nodes); - } - if (selection.range) { - util.setSelectionOffset(selection.range); - } - if (selection.dom) { - selection.dom.focus(); - } - }; - - /** - * Get the current focus - * @return {Object} selection An object containing fields: - * {Element | undefined} dom The dom element - * which has focus - * {Range | TextRange} range A text selection - * {Node[]} nodes Nodes in case of multi selection - * {Number} scrollTop Scroll position - */ - treemode.getSelection = function () { - var range = util.getSelectionOffset(); - if (range && range.container.nodeName !== 'DIV') { // filter on (editable) divs) - range = null; - } - - return { - dom: this.focusTarget, - range: range, - nodes: this.multiselection.nodes.slice(0), - scrollTop: this.content ? this.content.scrollTop : 0 - }; - }; - - /** - * Adjust the scroll position such that given top position is shown at 1/4 - * of the window height. - * @param {Number} top - * @param {function(boolean)} [callback] Callback, executed when animation is - * finished. The callback returns true - * when animation is finished, or false - * when not. - */ - treemode.scrollTo = function (top, callback) { - var content = this.content; - if (content) { - var editor = this; - // cancel any running animation - if (editor.animateTimeout) { - clearTimeout(editor.animateTimeout); - delete editor.animateTimeout; - } - if (editor.animateCallback) { - editor.animateCallback(false); - delete editor.animateCallback; - } - - // calculate final scroll position - var height = content.clientHeight; - var bottom = content.scrollHeight - height; - var finalScrollTop = Math.min(Math.max(top - height / 4, 0), bottom); - - // animate towards the new scroll position - var animate = function () { - var scrollTop = content.scrollTop; - var diff = (finalScrollTop - scrollTop); - if (Math.abs(diff) > 3) { - content.scrollTop += diff / 3; - editor.animateCallback = callback; - editor.animateTimeout = setTimeout(animate, 50); - } - else { - // finished - if (callback) { - callback(true); - } - content.scrollTop = finalScrollTop; - delete editor.animateTimeout; - delete editor.animateCallback; - } - }; - animate(); - } - else { - if (callback) { - callback(false); - } - } - }; - - /** - * Create main frame - * @private - */ - treemode._createFrame = function () { - // create the frame - this.frame = document.createElement('div'); - this.frame.className = 'jsoneditor jsoneditor-mode-' + this.options.mode; - this.container.appendChild(this.frame); - - // create one global event listener to handle all events from all nodes - var editor = this; - function onEvent(event) { - // when switching to mode "code" or "text" via the menu, some events - // are still fired whilst the _onEvent methods is already removed. - if (editor._onEvent) { - editor._onEvent(event); - } - } - this.frame.onclick = function (event) { - var target = event.target;// || event.srcElement; - - onEvent(event); - - // prevent default submit action of buttons when editor is located - // inside a form - if (target.nodeName == 'BUTTON') { - event.preventDefault(); - } - }; - this.frame.oninput = onEvent; - this.frame.onchange = onEvent; - this.frame.onkeydown = onEvent; - this.frame.onkeyup = onEvent; - this.frame.oncut = onEvent; - this.frame.onpaste = onEvent; - this.frame.onmousedown = onEvent; - this.frame.onmouseup = onEvent; - this.frame.onmouseover = onEvent; - this.frame.onmouseout = onEvent; - // Note: focus and blur events do not propagate, therefore they defined - // using an eventListener with useCapture=true - // see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html - util.addEventListener(this.frame, 'focus', onEvent, true); - util.addEventListener(this.frame, 'blur', onEvent, true); - this.frame.onfocusin = onEvent; // for IE - this.frame.onfocusout = onEvent; // for IE - - // create menu - this.menu = document.createElement('div'); - this.menu.className = 'jsoneditor-menu'; - this.frame.appendChild(this.menu); - - // create expand all button - var expandAll = document.createElement('button'); - expandAll.type = 'button'; - expandAll.className = 'jsoneditor-expand-all'; - expandAll.title = 'Expand all fields'; - expandAll.onclick = function () { - editor.expandAll(); - }; - this.menu.appendChild(expandAll); - - // create collapse all button - var collapseAll = document.createElement('button'); - collapseAll.type = 'button'; - collapseAll.title = 'Collapse all fields'; - collapseAll.className = 'jsoneditor-collapse-all'; - collapseAll.onclick = function () { - editor.collapseAll(); - }; - this.menu.appendChild(collapseAll); - - // create undo/redo buttons - if (this.history) { - // create undo button - var undo = document.createElement('button'); - undo.type = 'button'; - undo.className = 'jsoneditor-undo jsoneditor-separator'; - undo.title = 'Undo last action (Ctrl+Z)'; - undo.onclick = function () { - editor._onUndo(); - }; - this.menu.appendChild(undo); - this.dom.undo = undo; - - // create redo button - var redo = document.createElement('button'); - redo.type = 'button'; - redo.className = 'jsoneditor-redo'; - redo.title = 'Redo (Ctrl+Shift+Z)'; - redo.onclick = function () { - editor._onRedo(); - }; - this.menu.appendChild(redo); - this.dom.redo = redo; - - // register handler for onchange of history - this.history.onChange = function () { - undo.disabled = !editor.history.canUndo(); - redo.disabled = !editor.history.canRedo(); - }; - this.history.onChange(); - } - - // create mode box - if (this.options && this.options.modes && this.options.modes.length) { - var me = this; - this.modeSwitcher = new ModeSwitcher(this.menu, this.options.modes, this.options.mode, function onSwitch(mode) { - me.modeSwitcher.destroy(); - - // switch mode and restore focus - me.setMode(mode); - me.modeSwitcher.focus(); - }); - } - - // create search box - if (this.options.search) { - this.searchBox = new SearchBox(this, this.menu); - } - - if(this.options.navigationBar) { - // create second menu row for treepath - this.navBar = document.createElement('div'); - this.navBar.className = 'jsoneditor-navigation-bar nav-bar-empty'; - this.frame.appendChild(this.navBar); - - this.treePath = new TreePath(this.navBar); - this.treePath.onSectionSelected(this._onTreePathSectionSelected.bind(this)); - this.treePath.onContextMenuItemSelected(this._onTreePathMenuItemSelected.bind(this)); - } - }; - - /** - * Perform an undo action - * @private - */ - treemode._onUndo = function () { - if (this.history) { - // undo last action - this.history.undo(); - - // fire change event - this._onChange(); - } - }; - - /** - * Perform a redo action - * @private - */ - treemode._onRedo = function () { - if (this.history) { - // redo last action - this.history.redo(); - - // fire change event - this._onChange(); - } - }; - - /** - * Event handler - * @param event - * @private - */ - treemode._onEvent = function (event) { - if (event.type == 'keydown') { - this._onKeyDown(event); - } - - if (event.type == 'focus') { - this.focusTarget = event.target; - } - - if (event.type == 'mousedown') { - this._startDragDistance(event); - } - if (event.type == 'mousemove' || event.type == 'mouseup' || event.type == 'click') { - this._updateDragDistance(event); - } - - var node = Node.getNodeFromTarget(event.target); - - if (this.options && this.options.navigationBar && node && (event.type == 'keydown' || event.type == 'mousedown')) { - this._updateTreePath(node.getNodePath()); - } - - if (node && node.selected) { - if (event.type == 'click') { - if (event.target == node.dom.menu) { - this.showContextMenu(event.target); - - // stop propagation (else we will open the context menu of a single node) - return; - } - - // deselect a multi selection - if (!event.hasMoved) { - this.deselect(); - } - } - - if (event.type == 'mousedown') { - // drag multiple nodes - Node.onDragStart(this.multiselection.nodes, event); - } - } - else { - if (event.type == 'mousedown') { - this.deselect(); - - if (node && event.target == node.dom.drag) { - // drag a singe node - Node.onDragStart(node, event); - } - else if (!node || (event.target != node.dom.field && event.target != node.dom.value && event.target != node.dom.select)) { - // select multiple nodes - this._onMultiSelectStart(event); - } - } - } - - if (node) { - node.onEvent(event); - } - }; - - /** - * Update TreePath components - * @param {Array} pathNodes list of nodes in path from root to selection - * @private - */ - treemode._updateTreePath = function (pathNodes) { - if (pathNodes && pathNodes.length) { - util.removeClassName(this.navBar, 'nav-bar-empty'); - - var pathObjs = []; - pathNodes.forEach(function (node) { - var pathObj = { - name: getName(node), - node: node, - children: [] - } - if (node.childs && node.childs.length) { - node.childs.forEach(function (childNode) { - pathObj.children.push({ - name: getName(childNode), - node: childNode - }); - }); - } - pathObjs.push(pathObj); - }); - this.treePath.setPath(pathObjs); - } else { - util.addClassName(this.navBar, 'nav-bar-empty'); - } - - function getName(node) { - return node.field || (isNaN(node.index) ? node.type : node.index); - } - }; - - /** - * Callback for tree path section selection - focus the selected node in the tree - * @param {Object} pathObj path object that was represents the selected section node - * @private - */ - treemode._onTreePathSectionSelected = function (pathObj) { - if(pathObj && pathObj.node) { - pathObj.node.expandTo(); - pathObj.node.focus(); - } - }; - - /** - * Callback for tree path menu item selection - rebuild the path accrding to the new selection and focus the selected node in the tree - * @param {Object} pathObj path object that was represents the parent section node - * @param {String} selection selected section child - * @private - */ - treemode._onTreePathMenuItemSelected = function (pathObj, selection) { - if(pathObj && pathObj.children.length) { - var selectionObj = pathObj.children.find(function (obj) { - return obj.name === selection; - }); - if(selectionObj && selectionObj.node) { - this._updateTreePath(selectionObj.node.getNodePath()); - selectionObj.node.expandTo(); - selectionObj.node.focus(); - } - } - }; - - treemode._startDragDistance = function (event) { - this.dragDistanceEvent = { - initialTarget: event.target, - initialPageX: event.pageX, - initialPageY: event.pageY, - dragDistance: 0, - hasMoved: false - }; - }; - - treemode._updateDragDistance = function (event) { - if (!this.dragDistanceEvent) { - this._startDragDistance(event); - } - - var diffX = event.pageX - this.dragDistanceEvent.initialPageX; - var diffY = event.pageY - this.dragDistanceEvent.initialPageY; - - this.dragDistanceEvent.dragDistance = Math.sqrt(diffX * diffX + diffY * diffY); - this.dragDistanceEvent.hasMoved = - this.dragDistanceEvent.hasMoved || this.dragDistanceEvent.dragDistance > 10; - - event.dragDistance = this.dragDistanceEvent.dragDistance; - event.hasMoved = this.dragDistanceEvent.hasMoved; - - return event.dragDistance; - }; - - /** - * Start multi selection of nodes by dragging the mouse - * @param event - * @private - */ - treemode._onMultiSelectStart = function (event) { - var node = Node.getNodeFromTarget(event.target); - - if (this.options.mode !== 'tree' || this.options.onEditable !== undefined) { - // dragging not allowed in modes 'view' and 'form' - // TODO: allow multiselection of items when option onEditable is specified - return; - } - - this.multiselection = { - start: node || null, - end: null, - nodes: [] - }; - - this._startDragDistance(event); - - var editor = this; - if (!this.mousemove) { - this.mousemove = util.addEventListener(window, 'mousemove', function (event) { - editor._onMultiSelect(event); - }); - } - if (!this.mouseup) { - this.mouseup = util.addEventListener(window, 'mouseup', function (event ) { - editor._onMultiSelectEnd(event); - }); - } - - }; - - /** - * Multiselect nodes by dragging - * @param event - * @private - */ - treemode._onMultiSelect = function (event) { - event.preventDefault(); - - this._updateDragDistance(event); - if (!event.hasMoved) { - return; - } - - var node = Node.getNodeFromTarget(event.target); - - if (node) { - if (this.multiselection.start == null) { - this.multiselection.start = node; - } - this.multiselection.end = node; - } - - // deselect previous selection - this.deselect(); - - // find the selected nodes in the range from first to last - var start = this.multiselection.start; - var end = this.multiselection.end || this.multiselection.start; - if (start && end) { - // find the top level childs, all having the same parent - this.multiselection.nodes = this._findTopLevelNodes(start, end); - this.select(this.multiselection.nodes); - } - }; - - /** - * End of multiselect nodes by dragging - * @param event - * @private - */ - treemode._onMultiSelectEnd = function (event) { - // set focus to the context menu button of the first node - if (this.multiselection.nodes[0]) { - this.multiselection.nodes[0].dom.menu.focus(); - } - - this.multiselection.start = null; - this.multiselection.end = null; - - // cleanup global event listeners - if (this.mousemove) { - util.removeEventListener(window, 'mousemove', this.mousemove); - delete this.mousemove; - } - if (this.mouseup) { - util.removeEventListener(window, 'mouseup', this.mouseup); - delete this.mouseup; - } - }; - - /** - * deselect currently selected nodes - * @param {boolean} [clearStartAndEnd=false] If true, the `start` and `end` - * state is cleared too. - */ - treemode.deselect = function (clearStartAndEnd) { - this.multiselection.nodes.forEach(function (node) { - node.setSelected(false); - }); - this.multiselection.nodes = []; - - if (clearStartAndEnd) { - this.multiselection.start = null; - this.multiselection.end = null; - } - }; - - /** - * select nodes - * @param {Node[] | Node} nodes - */ - treemode.select = function (nodes) { - if (!Array.isArray(nodes)) { - return this.select([nodes]); - } - - if (nodes) { - this.deselect(); - - this.multiselection.nodes = nodes.slice(0); - - var first = nodes[0]; - nodes.forEach(function (node) { - node.setSelected(true, node === first); - }); - } - }; - - /** - * From two arbitrary selected nodes, find their shared parent node. - * From that parent node, select the two child nodes in the brances going to - * nodes `start` and `end`, and select all childs in between. - * @param {Node} start - * @param {Node} end - * @return {Array.} Returns an ordered list with child nodes - * @private - */ - treemode._findTopLevelNodes = function (start, end) { - var startPath = start.getNodePath(); - var endPath = end.getNodePath(); - var i = 0; - while (i < startPath.length && startPath[i] === endPath[i]) { - i++; - } - var root = startPath[i - 1]; - var startChild = startPath[i]; - var endChild = endPath[i]; - - if (!startChild || !endChild) { - if (root.parent) { - // startChild is a parent of endChild or vice versa - startChild = root; - endChild = root; - root = root.parent - } - else { - // we have selected the root node (which doesn't have a parent) - startChild = root.childs[0]; - endChild = root.childs[root.childs.length - 1]; - } - } - - if (root && startChild && endChild) { - var startIndex = root.childs.indexOf(startChild); - var endIndex = root.childs.indexOf(endChild); - var firstIndex = Math.min(startIndex, endIndex); - var lastIndex = Math.max(startIndex, endIndex); - - return root.childs.slice(firstIndex, lastIndex + 1); - } - else { - return []; - } - }; - - /** - * Event handler for keydown. Handles shortcut keys - * @param {Event} event - * @private - */ - treemode._onKeyDown = function (event) { - var keynum = event.which || event.keyCode; - var altKey = event.altKey; - var ctrlKey = event.ctrlKey; - var metaKey = event.metaKey; - var shiftKey = event.shiftKey; - var handled = false; - - if (keynum == 9) { // Tab or Shift+Tab - var me = this; - setTimeout(function () { - // select all text when moving focus to an editable div - util.selectContentEditable(me.focusTarget); - }, 0); - } - - if (this.searchBox) { - if (ctrlKey && keynum == 70) { // Ctrl+F - this.searchBox.dom.search.focus(); - this.searchBox.dom.search.select(); - handled = true; - } - else if (keynum == 114 || (ctrlKey && keynum == 71)) { // F3 or Ctrl+G - var focus = true; - if (!shiftKey) { - // select next search result (F3 or Ctrl+G) - this.searchBox.next(focus); - } - else { - // select previous search result (Shift+F3 or Ctrl+Shift+G) - this.searchBox.previous(focus); - } - - handled = true; - } - } - - if (this.history) { - if (ctrlKey && !shiftKey && keynum == 90) { // Ctrl+Z - // undo - this._onUndo(); - handled = true; - } - else if (ctrlKey && shiftKey && keynum == 90) { // Ctrl+Shift+Z - // redo - this._onRedo(); - handled = true; - } - } - - if ((this.options.autocomplete) && (!handled)) { - if (!ctrlKey && !altKey && !metaKey && (event.key.length == 1 || keynum == 8 || keynum == 46)) { - handled = false; - var jsonElementType = ""; - if (event.target.className.indexOf("jsoneditor-value") >= 0) jsonElementType = "value"; - if (event.target.className.indexOf("jsoneditor-field") >= 0) jsonElementType = "field"; - - var node = Node.getNodeFromTarget(event.target); - // Activate autocomplete - setTimeout(function (hnode, element) { - if (element.innerText.length > 0) { - var result = this.options.autocomplete.getOptions(element.innerText, hnode.getPath(), jsonElementType, hnode.editor); - if (typeof result.then === 'function') { - // probably a promise - if (result.then(function (obj) { - if (obj.options) - this.autocomplete.show(element, obj.startFrom, obj.options); - else - this.autocomplete.show(element, 0, obj); - }.bind(this))); - } else { - // definitely not a promise - if (result.options) - this.autocomplete.show(element, result.startFrom, result.options); - else - this.autocomplete.show(element, 0, result); - } - } - else - this.autocomplete.hideDropDown(); - - }.bind(this, node, event.target), 50); - } - } - - if (handled) { - event.preventDefault(); - event.stopPropagation(); - } - }; - - /** - * Create main table - * @private - */ - treemode._createTable = function () { - var contentOuter = document.createElement('div'); - contentOuter.className = 'jsoneditor-outer'; - if(this.options.navigationBar) { - util.addClassName(contentOuter, 'has-nav-bar'); - } - this.contentOuter = contentOuter; - - this.content = document.createElement('div'); - this.content.className = 'jsoneditor-tree'; - contentOuter.appendChild(this.content); - - this.table = document.createElement('table'); - this.table.className = 'jsoneditor-tree'; - this.content.appendChild(this.table); - - // create colgroup where the first two columns don't have a fixed - // width, and the edit columns do have a fixed width - var col; - this.colgroupContent = document.createElement('colgroup'); - if (this.options.mode === 'tree') { - col = document.createElement('col'); - col.width = "24px"; - this.colgroupContent.appendChild(col); - } - col = document.createElement('col'); - col.width = "24px"; - this.colgroupContent.appendChild(col); - col = document.createElement('col'); - this.colgroupContent.appendChild(col); - this.table.appendChild(this.colgroupContent); - - this.tbody = document.createElement('tbody'); - this.table.appendChild(this.tbody); - - this.frame.appendChild(contentOuter); - }; - - /** - * Show a contextmenu for this node. - * Used for multiselection - * @param {HTMLElement} anchor Anchor element to attach the context menu to. - * @param {function} [onClose] Callback method called when the context menu - * is being closed. - */ - treemode.showContextMenu = function (anchor, onClose) { - var items = []; - var editor = this; - - // create duplicate button - items.push({ - text: 'Duplicate', - title: 'Duplicate selected fields (Ctrl+D)', - className: 'jsoneditor-duplicate', - click: function () { - Node.onDuplicate(editor.multiselection.nodes); - } - }); - - // create remove button - items.push({ - text: 'Remove', - title: 'Remove selected fields (Ctrl+Del)', - className: 'jsoneditor-remove', - click: function () { - Node.onRemove(editor.multiselection.nodes); - } - }); - - var menu = new ContextMenu(items, {close: onClose}); - menu.show(anchor, this.content); - }; - - - // define modes - module.exports = [ - { - mode: 'tree', - mixin: treemode, - data: 'json' - }, - { - mode: 'view', - mixin: treemode, - data: 'json' - }, - { - mode: 'form', - mixin: treemode, - data: 'json' - } - ]; - - -/***/ }, -/* 52 */ -/***/ function(module, exports) { - - 'use strict'; - - /** - * The highlighter can highlight/unhighlight a node, and - * animate the visibility of a context menu. - * @constructor Highlighter - */ - function Highlighter () { - this.locked = false; - } - - /** - * Hightlight given node and its childs - * @param {Node} node - */ - Highlighter.prototype.highlight = function (node) { - if (this.locked) { - return; - } - - if (this.node != node) { - // unhighlight current node - if (this.node) { - this.node.setHighlight(false); - } - - // highlight new node - this.node = node; - this.node.setHighlight(true); - } - - // cancel any current timeout - this._cancelUnhighlight(); - }; - - /** - * Unhighlight currently highlighted node. - * Will be done after a delay - */ - Highlighter.prototype.unhighlight = function () { - if (this.locked) { - return; - } - - var me = this; - if (this.node) { - this._cancelUnhighlight(); - - // do the unhighlighting after a small delay, to prevent re-highlighting - // the same node when moving from the drag-icon to the contextmenu-icon - // or vice versa. - this.unhighlightTimer = setTimeout(function () { - me.node.setHighlight(false); - me.node = undefined; - me.unhighlightTimer = undefined; - }, 0); - } - }; - - /** - * Cancel an unhighlight action (if before the timeout of the unhighlight action) - * @private - */ - Highlighter.prototype._cancelUnhighlight = function () { - if (this.unhighlightTimer) { - clearTimeout(this.unhighlightTimer); - this.unhighlightTimer = undefined; - } - }; - - /** - * Lock highlighting or unhighlighting nodes. - * methods highlight and unhighlight do not work while locked. - */ - Highlighter.prototype.lock = function () { - this.locked = true; - }; - - /** - * Unlock highlighting or unhighlighting nodes - */ - Highlighter.prototype.unlock = function () { - this.locked = false; - }; - - module.exports = Highlighter; - - -/***/ }, -/* 53 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var util = __webpack_require__(54); - - /** - * @constructor History - * Store action history, enables undo and redo - * @param {JSONEditor} editor - */ - function History (editor) { - this.editor = editor; - this.history = []; - this.index = -1; - - this.clear(); - - // map with all supported actions - this.actions = { - 'editField': { - 'undo': function (params) { - params.node.updateField(params.oldValue); - }, - 'redo': function (params) { - params.node.updateField(params.newValue); - } - }, - 'editValue': { - 'undo': function (params) { - params.node.updateValue(params.oldValue); - }, - 'redo': function (params) { - params.node.updateValue(params.newValue); - } - }, - 'changeType': { - 'undo': function (params) { - params.node.changeType(params.oldType); - }, - 'redo': function (params) { - params.node.changeType(params.newType); - } - }, - - 'appendNodes': { - 'undo': function (params) { - params.nodes.forEach(function (node) { - params.parent.removeChild(node); - }); - }, - 'redo': function (params) { - params.nodes.forEach(function (node) { - params.parent.appendChild(node); - }); - } - }, - 'insertBeforeNodes': { - 'undo': function (params) { - params.nodes.forEach(function (node) { - params.parent.removeChild(node); - }); - }, - 'redo': function (params) { - params.nodes.forEach(function (node) { - params.parent.insertBefore(node, params.beforeNode); - }); - } - }, - 'insertAfterNodes': { - 'undo': function (params) { - params.nodes.forEach(function (node) { - params.parent.removeChild(node); - }); - }, - 'redo': function (params) { - var afterNode = params.afterNode; - params.nodes.forEach(function (node) { - params.parent.insertAfter(params.node, afterNode); - afterNode = node; - }); - } - }, - 'removeNodes': { - 'undo': function (params) { - var parent = params.parent; - var beforeNode = parent.childs[params.index] || parent.append; - params.nodes.forEach(function (node) { - parent.insertBefore(node, beforeNode); - }); - }, - 'redo': function (params) { - params.nodes.forEach(function (node) { - params.parent.removeChild(node); - }); - } - }, - 'duplicateNodes': { - 'undo': function (params) { - params.nodes.forEach(function (node) { - params.parent.removeChild(node); - }); - }, - 'redo': function (params) { - var afterNode = params.afterNode; - params.nodes.forEach(function (node) { - params.parent.insertAfter(node, afterNode); - afterNode = node; - }); - } - }, - 'moveNodes': { - 'undo': function (params) { - params.nodes.forEach(function (node) { - params.oldBeforeNode.parent.moveBefore(node, params.oldBeforeNode); - }); - }, - 'redo': function (params) { - params.nodes.forEach(function (node) { - params.newBeforeNode.parent.moveBefore(node, params.newBeforeNode); - }); - } - }, - - 'sort': { - 'undo': function (params) { - var node = params.node; - node.hideChilds(); - node.sort = params.oldSort; - node.childs = params.oldChilds; - node.showChilds(); - }, - 'redo': function (params) { - var node = params.node; - node.hideChilds(); - node.sort = params.newSort; - node.childs = params.newChilds; - node.showChilds(); - } - } - - // TODO: restore the original caret position and selection with each undo - // TODO: implement history for actions "expand", "collapse", "scroll", "setDocument" - }; - } - - /** - * The method onChange is executed when the History is changed, and can - * be overloaded. - */ - History.prototype.onChange = function () {}; - - /** - * Add a new action to the history - * @param {String} action The executed action. Available actions: "editField", - * "editValue", "changeType", "appendNode", - * "removeNode", "duplicateNode", "moveNode" - * @param {Object} params Object containing parameters describing the change. - * The parameters in params depend on the action (for - * example for "editValue" the Node, old value, and new - * value are provided). params contains all information - * needed to undo or redo the action. - */ - History.prototype.add = function (action, params) { - this.index++; - this.history[this.index] = { - 'action': action, - 'params': params, - 'timestamp': new Date() - }; - - // remove redo actions which are invalid now - if (this.index < this.history.length - 1) { - this.history.splice(this.index + 1, this.history.length - this.index - 1); - } - - // fire onchange event - this.onChange(); - }; - - /** - * Clear history - */ - History.prototype.clear = function () { - this.history = []; - this.index = -1; - - // fire onchange event - this.onChange(); - }; - - /** - * Check if there is an action available for undo - * @return {Boolean} canUndo - */ - History.prototype.canUndo = function () { - return (this.index >= 0); - }; - - /** - * Check if there is an action available for redo - * @return {Boolean} canRedo - */ - History.prototype.canRedo = function () { - return (this.index < this.history.length - 1); - }; - - /** - * Undo the last action - */ - History.prototype.undo = function () { - if (this.canUndo()) { - var obj = this.history[this.index]; - if (obj) { - var action = this.actions[obj.action]; - if (action && action.undo) { - action.undo(obj.params); - if (obj.params.oldSelection) { - this.editor.setSelection(obj.params.oldSelection); - } - } - else { - console.error(new Error('unknown action "' + obj.action + '"')); - } - } - this.index--; - - // fire onchange event - this.onChange(); - } - }; - - /** - * Redo the last action - */ - History.prototype.redo = function () { - if (this.canRedo()) { - this.index++; - - var obj = this.history[this.index]; - if (obj) { - var action = this.actions[obj.action]; - if (action && action.redo) { - action.redo(obj.params); - if (obj.params.newSelection) { - this.editor.setSelection(obj.params.newSelection); - } - } - else { - console.error(new Error('unknown action "' + obj.action + '"')); - } - } - - // fire onchange event - this.onChange(); - } - }; - - /** - * Destroy history - */ - History.prototype.destroy = function () { - this.editor = null; - - this.history = []; - this.index = -1; - }; - - module.exports = History; - - -/***/ }, -/* 54 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var jsonlint = __webpack_require__(55); - - /** - * Parse JSON using the parser built-in in the browser. - * On exception, the jsonString is validated and a detailed error is thrown. - * @param {String} jsonString - * @return {JSON} json - */ - exports.parse = function parse(jsonString) { - try { - return JSON.parse(jsonString); - } - catch (err) { - // try to throw a more detailed error message using validate - exports.validate(jsonString); - - // rethrow the original error - throw err; - } - }; - - /** - * Sanitize a JSON-like string containing. For example changes JavaScript - * notation into JSON notation. - * This function for example changes a string like "{a: 2, 'b': {c: 'd'}" - * into '{"a": 2, "b": {"c": "d"}' - * @param {string} jsString - * @returns {string} json - */ - exports.sanitize = function (jsString) { - // escape all single and double quotes inside strings - var chars = []; - var i = 0; - - //If JSON starts with a function (characters/digits/"_-"), remove this function. - //This is useful for "stripping" JSONP objects to become JSON - //For example: /* some comment */ function_12321321 ( [{"a":"b"}] ); => [{"a":"b"}] - var match = jsString.match(/^\s*(\/\*(.|[\r\n])*?\*\/)?\s*[\da-zA-Z_$]+\s*\(([\s\S]*)\)\s*;?\s*$/); - if (match) { - jsString = match[3]; - } - - var controlChars = { - '\b': '\\b', - '\f': '\\f', - '\n': '\\n', - '\r': '\\r', - '\t': '\\t' - }; - - var quote = '\''; - var quoteDbl = '"'; - var quoteLeft = '\u2018'; - var quoteRight = '\u2019'; - var quoteDblLeft = '\u201C'; - var quoteDblRight = '\u201D'; - var graveAccent = '\u0060'; - var acuteAccent = '\u00B4'; - - // helper functions to get the current/prev/next character - function curr () { return jsString.charAt(i); } - function next() { return jsString.charAt(i + 1); } - function prev() { return jsString.charAt(i - 1); } - - // get the last parsed non-whitespace character - function lastNonWhitespace () { - var p = chars.length - 1; - - while (p >= 0) { - var pp = chars[p]; - if (pp !== ' ' && pp !== '\n' && pp !== '\r' && pp !== '\t') { // non whitespace - return pp; - } - p--; - } - - return ''; - } - - // skip a block comment '/* ... */' - function skipBlockComment () { - i += 2; - while (i < jsString.length && (curr() !== '*' || next() !== '/')) { - i++; - } - i += 2; - } - - // skip a comment '// ...' - function skipComment () { - i += 2; - while (i < jsString.length && (curr() !== '\n')) { - i++; - } - } - - // parse single or double quoted string - function parseString(endQuote) { - chars.push('"'); - i++; - var c = curr(); - while (i < jsString.length && c !== endQuote) { - if (c === '"' && prev() !== '\\') { - // unescaped double quote, escape it - chars.push('\\"'); - } - else if (controlChars.hasOwnProperty(c)) { - // replace unescaped control characters with escaped ones - chars.push(controlChars[c]) - } - else if (c === '\\') { - // remove the escape character when followed by a single quote ', not needed - i++; - c = curr(); - if (c !== '\'') { - chars.push('\\'); - } - chars.push(c); - } - else { - // regular character - chars.push(c); - } - - i++; - c = curr(); - } - if (c === endQuote) { - chars.push('"'); - i++; - } - } - - // parse an unquoted key - function parseKey() { - var specialValues = ['null', 'true', 'false']; - var key = ''; - var c = curr(); - - var regexp = /[a-zA-Z_$\d]/; // letter, number, underscore, dollar character - while (regexp.test(c)) { - key += c; - i++; - c = curr(); - } - - if (specialValues.indexOf(key) === -1) { - chars.push('"' + key + '"'); - } - else { - chars.push(key); - } - } - - while(i < jsString.length) { - var c = curr(); - - if (c === '/' && next() === '*') { - skipBlockComment(); - } - else if (c === '/' && next() === '/') { - skipComment(); - } - else if (c === '\u00A0' || (c >= '\u2000' && c <= '\u200A') || c === '\u202F' || c === '\u205F' || c === '\u3000') { - // special white spaces (like non breaking space) - chars.push(' ') - i++ - } - else if (c === quote) { - parseString(quote); - } - else if (c === quoteDbl) { - parseString(quoteDbl); - } - else if (c === graveAccent) { - parseString(acuteAccent); - } - else if (c === quoteLeft) { - parseString(quoteRight); - } - else if (c === quoteDblLeft) { - parseString(quoteDblRight); - } - else if (/[a-zA-Z_$]/.test(c) && ['{', ','].indexOf(lastNonWhitespace()) !== -1) { - // an unquoted object key (like a in '{a:2}') - parseKey(); - } - else { - chars.push(c); - i++; - } - } - - return chars.join(''); - }; - - /** - * Escape unicode characters. - * For example input '\u2661' (length 1) will output '\\u2661' (length 5). - * @param {string} text - * @return {string} - */ - exports.escapeUnicodeChars = function (text) { - // see https://www.wikiwand.com/en/UTF-16 - // note: we leave surrogate pairs as two individual chars, - // as JSON doesn't interpret them as a single unicode char. - return text.replace(/[\u007F-\uFFFF]/g, function(c) { - return '\\u'+('0000' + c.charCodeAt(0).toString(16)).slice(-4); - }) - }; - - /** - * Validate a string containing a JSON object - * This method uses JSONLint to validate the String. If JSONLint is not - * available, the built-in JSON parser of the browser is used. - * @param {String} jsonString String with an (invalid) JSON object - * @throws Error - */ - exports.validate = function validate(jsonString) { - if (typeof(jsonlint) != 'undefined') { - jsonlint.parse(jsonString); - } - else { - JSON.parse(jsonString); - } - }; - - /** - * Extend object a with the properties of object b - * @param {Object} a - * @param {Object} b - * @return {Object} a - */ - exports.extend = function extend(a, b) { - for (var prop in b) { - if (b.hasOwnProperty(prop)) { - a[prop] = b[prop]; - } - } - return a; - }; - - /** - * Remove all properties from object a - * @param {Object} a - * @return {Object} a - */ - exports.clear = function clear (a) { - for (var prop in a) { - if (a.hasOwnProperty(prop)) { - delete a[prop]; - } - } - return a; - }; - - /** - * Get the type of an object - * @param {*} object - * @return {String} type - */ - exports.type = function type (object) { - if (object === null) { - return 'null'; - } - if (object === undefined) { - return 'undefined'; - } - if ((object instanceof Number) || (typeof object === 'number')) { - return 'number'; - } - if ((object instanceof String) || (typeof object === 'string')) { - return 'string'; - } - if ((object instanceof Boolean) || (typeof object === 'boolean')) { - return 'boolean'; - } - if ((object instanceof RegExp) || (typeof object === 'regexp')) { - return 'regexp'; - } - if (exports.isArray(object)) { - return 'array'; - } - - return 'object'; - }; - - /** - * Test whether a text contains a url (matches when a string starts - * with 'http://*' or 'https://*' and has no whitespace characters) - * @param {String} text - */ - var isUrlRegex = /^https?:\/\/\S+$/; - exports.isUrl = function isUrl (text) { - return (typeof text == 'string' || text instanceof String) && - isUrlRegex.test(text); - }; - - /** - * Tes whether given object is an Array - * @param {*} obj - * @returns {boolean} returns true when obj is an array - */ - exports.isArray = function (obj) { - return Object.prototype.toString.call(obj) === '[object Array]'; - }; - - /** - * Retrieve the absolute left value of a DOM element - * @param {Element} elem A dom element, for example a div - * @return {Number} left The absolute left position of this element - * in the browser page. - */ - exports.getAbsoluteLeft = function getAbsoluteLeft(elem) { - var rect = elem.getBoundingClientRect(); - return rect.left + window.pageXOffset || document.scrollLeft || 0; - }; - - /** - * Retrieve the absolute top value of a DOM element - * @param {Element} elem A dom element, for example a div - * @return {Number} top The absolute top position of this element - * in the browser page. - */ - exports.getAbsoluteTop = function getAbsoluteTop(elem) { - var rect = elem.getBoundingClientRect(); - return rect.top + window.pageYOffset || document.scrollTop || 0; - }; - - /** - * add a className to the given elements style - * @param {Element} elem - * @param {String} className - */ - exports.addClassName = function addClassName(elem, className) { - var classes = elem.className.split(' '); - if (classes.indexOf(className) == -1) { - classes.push(className); // add the class to the array - elem.className = classes.join(' '); - } - }; - - /** - * add a className to the given elements style - * @param {Element} elem - * @param {String} className - */ - exports.removeClassName = function removeClassName(elem, className) { - var classes = elem.className.split(' '); - var index = classes.indexOf(className); - if (index != -1) { - classes.splice(index, 1); // remove the class from the array - elem.className = classes.join(' '); - } - }; - - /** - * Strip the formatting from the contents of a div - * the formatting from the div itself is not stripped, only from its childs. - * @param {Element} divElement - */ - exports.stripFormatting = function stripFormatting(divElement) { - var childs = divElement.childNodes; - for (var i = 0, iMax = childs.length; i < iMax; i++) { - var child = childs[i]; - - // remove the style - if (child.style) { - // TODO: test if child.attributes does contain style - child.removeAttribute('style'); - } - - // remove all attributes - var attributes = child.attributes; - if (attributes) { - for (var j = attributes.length - 1; j >= 0; j--) { - var attribute = attributes[j]; - if (attribute.specified === true) { - child.removeAttribute(attribute.name); - } - } - } - - // recursively strip childs - exports.stripFormatting(child); - } - }; - - /** - * Set focus to the end of an editable div - * code from Nico Burns - * http://stackoverflow.com/users/140293/nico-burns - * http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity - * @param {Element} contentEditableElement A content editable div - */ - exports.setEndOfContentEditable = function setEndOfContentEditable(contentEditableElement) { - var range, selection; - if(document.createRange) { - range = document.createRange();//Create a range (a range is a like the selection but invisible) - range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range - range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start - selection = window.getSelection();//get the selection object (allows you to change selection) - selection.removeAllRanges();//remove any selections already made - selection.addRange(range);//make the range you have just created the visible selection - } - }; - - /** - * Select all text of a content editable div. - * http://stackoverflow.com/a/3806004/1262753 - * @param {Element} contentEditableElement A content editable div - */ - exports.selectContentEditable = function selectContentEditable(contentEditableElement) { - if (!contentEditableElement || contentEditableElement.nodeName != 'DIV') { - return; - } - - var sel, range; - if (window.getSelection && document.createRange) { - range = document.createRange(); - range.selectNodeContents(contentEditableElement); - sel = window.getSelection(); - sel.removeAllRanges(); - sel.addRange(range); - } - }; - - /** - * Get text selection - * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore - * @return {Range | TextRange | null} range - */ - exports.getSelection = function getSelection() { - if (window.getSelection) { - var sel = window.getSelection(); - if (sel.getRangeAt && sel.rangeCount) { - return sel.getRangeAt(0); - } - } - return null; - }; - - /** - * Set text selection - * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore - * @param {Range | TextRange | null} range - */ - exports.setSelection = function setSelection(range) { - if (range) { - if (window.getSelection) { - var sel = window.getSelection(); - sel.removeAllRanges(); - sel.addRange(range); - } - } - }; - - /** - * Get selected text range - * @return {Object} params object containing parameters: - * {Number} startOffset - * {Number} endOffset - * {Element} container HTML element holding the - * selected text element - * Returns null if no text selection is found - */ - exports.getSelectionOffset = function getSelectionOffset() { - var range = exports.getSelection(); - - if (range && 'startOffset' in range && 'endOffset' in range && - range.startContainer && (range.startContainer == range.endContainer)) { - return { - startOffset: range.startOffset, - endOffset: range.endOffset, - container: range.startContainer.parentNode - }; - } - - return null; - }; - - /** - * Set selected text range in given element - * @param {Object} params An object containing: - * {Element} container - * {Number} startOffset - * {Number} endOffset - */ - exports.setSelectionOffset = function setSelectionOffset(params) { - if (document.createRange && window.getSelection) { - var selection = window.getSelection(); - if(selection) { - var range = document.createRange(); - - if (!params.container.firstChild) { - params.container.appendChild(document.createTextNode('')); - } - - // TODO: do not suppose that the first child of the container is a textnode, - // but recursively find the textnodes - range.setStart(params.container.firstChild, params.startOffset); - range.setEnd(params.container.firstChild, params.endOffset); - - exports.setSelection(range); - } - } - }; - - /** - * Get the inner text of an HTML element (for example a div element) - * @param {Element} element - * @param {Object} [buffer] - * @return {String} innerText - */ - exports.getInnerText = function getInnerText(element, buffer) { - var first = (buffer == undefined); - if (first) { - buffer = { - 'text': '', - 'flush': function () { - var text = this.text; - this.text = ''; - return text; - }, - 'set': function (text) { - this.text = text; - } - }; - } - - // text node - if (element.nodeValue) { - return buffer.flush() + element.nodeValue; - } - - // divs or other HTML elements - if (element.hasChildNodes()) { - var childNodes = element.childNodes; - var innerText = ''; - - for (var i = 0, iMax = childNodes.length; i < iMax; i++) { - var child = childNodes[i]; - - if (child.nodeName == 'DIV' || child.nodeName == 'P') { - var prevChild = childNodes[i - 1]; - var prevName = prevChild ? prevChild.nodeName : undefined; - if (prevName && prevName != 'DIV' && prevName != 'P' && prevName != 'BR') { - innerText += '\n'; - buffer.flush(); - } - innerText += exports.getInnerText(child, buffer); - buffer.set('\n'); - } - else if (child.nodeName == 'BR') { - innerText += buffer.flush(); - buffer.set('\n'); - } - else { - innerText += exports.getInnerText(child, buffer); - } - } - - return innerText; - } - else { - if (element.nodeName == 'P' && exports.getInternetExplorerVersion() != -1) { - // On Internet Explorer, a

with hasChildNodes()==false is - // rendered with a new line. Note that a

with - // hasChildNodes()==true is rendered without a new line - // Other browsers always ensure there is a
inside the

, - // and if not, the

does not render a new line - return buffer.flush(); - } - } - - // br or unknown - return ''; - }; - - /** - * Returns the version of Internet Explorer or a -1 - * (indicating the use of another browser). - * Source: http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx - * @return {Number} Internet Explorer version, or -1 in case of an other browser - */ - exports.getInternetExplorerVersion = function getInternetExplorerVersion() { - if (_ieVersion == -1) { - var rv = -1; // Return value assumes failure. - if (navigator.appName == 'Microsoft Internet Explorer') - { - var ua = navigator.userAgent; - var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); - if (re.exec(ua) != null) { - rv = parseFloat( RegExp.$1 ); - } - } - - _ieVersion = rv; - } - - return _ieVersion; - }; - - /** - * Test whether the current browser is Firefox - * @returns {boolean} isFirefox - */ - exports.isFirefox = function isFirefox () { - return (navigator.userAgent.indexOf("Firefox") != -1); - }; - - /** - * cached internet explorer version - * @type {Number} - * @private - */ - var _ieVersion = -1; - - /** - * Add and event listener. Works for all browsers - * @param {Element} element An html element - * @param {string} action The action, for example "click", - * without the prefix "on" - * @param {function} listener The callback function to be executed - * @param {boolean} [useCapture] false by default - * @return {function} the created event listener - */ - exports.addEventListener = function addEventListener(element, action, listener, useCapture) { - if (element.addEventListener) { - if (useCapture === undefined) - useCapture = false; - - if (action === "mousewheel" && exports.isFirefox()) { - action = "DOMMouseScroll"; // For Firefox - } - - element.addEventListener(action, listener, useCapture); - return listener; - } else if (element.attachEvent) { - // Old IE browsers - var f = function () { - return listener.call(element, window.event); - }; - element.attachEvent("on" + action, f); - return f; - } - }; - - /** - * Remove an event listener from an element - * @param {Element} element An html dom element - * @param {string} action The name of the event, for example "mousedown" - * @param {function} listener The listener function - * @param {boolean} [useCapture] false by default - */ - exports.removeEventListener = function removeEventListener(element, action, listener, useCapture) { - if (element.removeEventListener) { - if (useCapture === undefined) - useCapture = false; - - if (action === "mousewheel" && exports.isFirefox()) { - action = "DOMMouseScroll"; // For Firefox - } - - element.removeEventListener(action, listener, useCapture); - } else if (element.detachEvent) { - // Old IE browsers - element.detachEvent("on" + action, listener); - } - }; - - /** - * Parse a JSON path like '.items[3].name' into an array - * @param {string} jsonPath - * @return {Array} - */ - exports.parsePath = function parsePath(jsonPath) { - var prop, remainder; - - if (jsonPath.length === 0) { - return []; - } - - // find a match like '.prop' - var match = jsonPath.match(/^\.(\w+)/); - if (match) { - prop = match[1]; - remainder = jsonPath.substr(prop.length + 1); - } - else if (jsonPath[0] === '[') { - // find a match like - var end = jsonPath.indexOf(']'); - if (end === -1) { - throw new SyntaxError('Character ] expected in path'); - } - if (end === 1) { - throw new SyntaxError('Index expected after ['); - } - - var value = jsonPath.substring(1, end); - if (value[0] === '\'') { - // ajv produces string prop names with single quotes, so we need - // to reformat them into valid double-quoted JSON strings - value = '\"' + value.substring(1, value.length - 1) + '\"'; - } - - prop = value === '*' ? value : JSON.parse(value); // parse string and number - remainder = jsonPath.substr(end + 1); - } - else { - throw new SyntaxError('Failed to parse path'); - } - - return [prop].concat(parsePath(remainder)) - }; - - /** - * Improve the error message of a JSON schema error - * @param {Object} error - * @return {Object} The error - */ - exports.improveSchemaError = function (error) { - if (error.keyword === 'enum' && Array.isArray(error.schema)) { - var enums = error.schema; - if (enums) { - enums = enums.map(function (value) { - return JSON.stringify(value); - }); - - if (enums.length > 5) { - var more = ['(' + (enums.length - 5) + ' more...)']; - enums = enums.slice(0, 5); - enums.push(more); - } - error.message = 'should be equal to one of: ' + enums.join(', '); - } - } - - if (error.keyword === 'additionalProperties') { - error.message = 'should NOT have additional property: ' + error.params.additionalProperty; - } - - return error; - }; - - /** - * Test whether the child rect fits completely inside the parent rect. - * @param {ClientRect} parent - * @param {ClientRect} child - * @param {number} margin - */ - exports.insideRect = function (parent, child, margin) { - var _margin = margin !== undefined ? margin : 0; - return child.left - _margin >= parent.left - && child.right + _margin <= parent.right - && child.top - _margin >= parent.top - && child.bottom + _margin <= parent.bottom; - }; - - /** - * Returns a function, that, as long as it continues to be invoked, will not - * be triggered. The function will be called after it stops being called for - * N milliseconds. - * - * Source: https://davidwalsh.name/javascript-debounce-function - * - * @param {function} func - * @param {number} wait Number in milliseconds - * @param {boolean} [immediate=false] If `immediate` is passed, trigger the - * function on the leading edge, instead - * of the trailing. - * @return {function} Return the debounced function - */ - exports.debounce = function debounce(func, wait, immediate) { - var timeout; - return function() { - var context = this, args = arguments; - var later = function() { - timeout = null; - if (!immediate) func.apply(context, args); - }; - var callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - if (callNow) func.apply(context, args); - }; - }; - - /** - * Determines the difference between two texts. - * Can only detect one removed or inserted block of characters. - * @param {string} oldText - * @param {string} newText - * @return {{start: number, end: number}} Returns the start and end - * of the changed part in newText. - */ - exports.textDiff = function textDiff(oldText, newText) { - var len = newText.length; - var start = 0; - var oldEnd = oldText.length; - var newEnd = newText.length; - - while (newText.charAt(start) === oldText.charAt(start) - && start < len) { - start++; - } - - while (newText.charAt(newEnd - 1) === oldText.charAt(oldEnd - 1) - && newEnd > start && oldEnd > 0) { - newEnd--; - oldEnd--; - } - - return {start: start, end: newEnd}; - }; - - - /** - * Return an object with the selection range or cursor position (if both have the same value) - * Support also old browsers (IE8-) - * Source: http://ourcodeworld.com/articles/read/282/how-to-get-the-current-cursor-position-and-selection-within-a-text-input-or-textarea-in-javascript - * @param {DOMElement} el A dom element of a textarea or input text. - * @return {Object} reference Object with 2 properties (start and end) with the identifier of the location of the cursor and selected text. - **/ - exports.getInputSelection = function(el) { - var start = 0, end = 0, normalizedValue, range, textInputRange, len, endRange; - - if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") { - start = el.selectionStart; - end = el.selectionEnd; - } else { - range = document.selection.createRange(); - - if (range && range.parentElement() == el) { - len = el.value.length; - normalizedValue = el.value.replace(/\r\n/g, "\n"); - - // Create a working TextRange that lives only in the input - textInputRange = el.createTextRange(); - textInputRange.moveToBookmark(range.getBookmark()); - - // Check if the start and end of the selection are at the very end - // of the input, since moveStart/moveEnd doesn't return what we want - // in those cases - endRange = el.createTextRange(); - endRange.collapse(false); - - if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { - start = end = len; - } else { - start = -textInputRange.moveStart("character", -len); - start += normalizedValue.slice(0, start).split("\n").length - 1; - - if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) { - end = len; - } else { - end = -textInputRange.moveEnd("character", -len); - end += normalizedValue.slice(0, end).split("\n").length - 1; - } - } - } - } - - return { - start: start, - end: end - }; - } - - - if (typeof Element !== 'undefined') { - // Polyfill for array remove - (function () { - function polyfill (item) { - if (item.hasOwnProperty('remove')) { - return; - } - Object.defineProperty(item, 'remove', { - configurable: true, - enumerable: true, - writable: true, - value: function remove() { - if (this.parentNode != null) - this.parentNode.removeChild(this); - } - }); - } - - if (typeof Element !== 'undefined') { polyfill(Element.prototype); } - if (typeof CharacterData !== 'undefined') { polyfill(CharacterData.prototype); } - if (typeof DocumentType !== 'undefined') { polyfill(DocumentType.prototype); } - })(); - } - - - // Polyfill for startsWith - if (!String.prototype.startsWith) { - String.prototype.startsWith = function (searchString, position) { - position = position || 0; - return this.substr(position, searchString.length) === searchString; - }; - } - - // Polyfill for Array.find - if (!Array.prototype.find) { - Array.prototype.find = function(callback) { - for (var i = 0; i < this.length; i++) { - var element = this[i]; - if ( callback.call(this, element, i, this) ) { - return element; - } - } - } - } - -/***/ }, -/* 55 */ -/***/ function(module, exports, __webpack_require__) { - - /* Jison generated parser */ - var jsonlint = (function(){ - var parser = {trace: function trace() { }, - yy: {}, - symbols_: {"error":2,"JSONString":3,"STRING":4,"JSONNumber":5,"NUMBER":6,"JSONNullLiteral":7,"NULL":8,"JSONBooleanLiteral":9,"TRUE":10,"FALSE":11,"JSONText":12,"JSONValue":13,"EOF":14,"JSONObject":15,"JSONArray":16,"{":17,"}":18,"JSONMemberList":19,"JSONMember":20,":":21,",":22,"[":23,"]":24,"JSONElementList":25,"$accept":0,"$end":1}, - terminals_: {2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"}, - productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]], - performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { - - var $0 = $$.length - 1; - switch (yystate) { - case 1: // replace escaped characters with actual character - this.$ = yytext.replace(/\\(\\|")/g, "$"+"1") - .replace(/\\n/g,'\n') - .replace(/\\r/g,'\r') - .replace(/\\t/g,'\t') - .replace(/\\v/g,'\v') - .replace(/\\f/g,'\f') - .replace(/\\b/g,'\b'); - - break; - case 2:this.$ = Number(yytext); - break; - case 3:this.$ = null; - break; - case 4:this.$ = true; - break; - case 5:this.$ = false; - break; - case 6:return this.$ = $$[$0-1]; - break; - case 13:this.$ = {}; - break; - case 14:this.$ = $$[$0-1]; - break; - case 15:this.$ = [$$[$0-2], $$[$0]]; - break; - case 16:this.$ = {}; this.$[$$[$0][0]] = $$[$0][1]; - break; - case 17:this.$ = $$[$0-2]; $$[$0-2][$$[$0][0]] = $$[$0][1]; - break; - case 18:this.$ = []; - break; - case 19:this.$ = $$[$0-1]; - break; - case 20:this.$ = [$$[$0]]; - break; - case 21:this.$ = $$[$0-2]; $$[$0-2].push($$[$0]); - break; - } - }, - table: [{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}], - defaultActions: {16:[2,6]}, - parseError: function parseError(str, hash) { - throw new Error(str); - }, - parse: function parse(input) { - var self = this, - stack = [0], - vstack = [null], // semantic value stack - lstack = [], // location stack - table = this.table, - yytext = '', - yylineno = 0, - yyleng = 0, - recovering = 0, - TERROR = 2, - EOF = 1; - - //this.reductionCount = this.shiftCount = 0; - - this.lexer.setInput(input); - this.lexer.yy = this.yy; - this.yy.lexer = this.lexer; - if (typeof this.lexer.yylloc == 'undefined') - this.lexer.yylloc = {}; - var yyloc = this.lexer.yylloc; - lstack.push(yyloc); - - if (typeof this.yy.parseError === 'function') - this.parseError = this.yy.parseError; - - function popStack (n) { - stack.length = stack.length - 2*n; - vstack.length = vstack.length - n; - lstack.length = lstack.length - n; - } - - function lex() { - var token; - token = self.lexer.lex() || 1; // $end = 1 - // if token isn't its numeric value, convert - if (typeof token !== 'number') { - token = self.symbols_[token] || token; - } - return token; - } - - var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; - while (true) { - // retreive state number from top of stack - state = stack[stack.length-1]; - - // use default actions if available - if (this.defaultActions[state]) { - action = this.defaultActions[state]; - } else { - if (symbol == null) - symbol = lex(); - // read action for current state and first input - action = table[state] && table[state][symbol]; - } - - // handle parse error - _handle_error: - if (typeof action === 'undefined' || !action.length || !action[0]) { - - if (!recovering) { - // Report error - expected = []; - for (p in table[state]) if (this.terminals_[p] && p > 2) { - expected.push("'"+this.terminals_[p]+"'"); - } - var errStr = ''; - if (this.lexer.showPosition) { - errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'"; - } else { - errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + - (symbol == 1 /*EOF*/ ? "end of input" : - ("'"+(this.terminals_[symbol] || symbol)+"'")); - } - this.parseError(errStr, - {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); - } - - // just recovered from another error - if (recovering == 3) { - if (symbol == EOF) { - throw new Error(errStr || 'Parsing halted.'); - } - - // discard current lookahead and grab another - yyleng = this.lexer.yyleng; - yytext = this.lexer.yytext; - yylineno = this.lexer.yylineno; - yyloc = this.lexer.yylloc; - symbol = lex(); - } - - // try to recover from error - while (1) { - // check for error recovery rule in this state - if ((TERROR.toString()) in table[state]) { - break; - } - if (state == 0) { - throw new Error(errStr || 'Parsing halted.'); - } - popStack(1); - state = stack[stack.length-1]; - } - - preErrorSymbol = symbol; // save the lookahead token - symbol = TERROR; // insert generic error symbol as new lookahead - state = stack[stack.length-1]; - action = table[state] && table[state][TERROR]; - recovering = 3; // allow 3 real symbols to be shifted before reporting a new error - } - - // this shouldn't happen, unless resolve defaults are off - if (action[0] instanceof Array && action.length > 1) { - throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); - } - - switch (action[0]) { - - case 1: // shift - //this.shiftCount++; - - stack.push(symbol); - vstack.push(this.lexer.yytext); - lstack.push(this.lexer.yylloc); - stack.push(action[1]); // push state - symbol = null; - if (!preErrorSymbol) { // normal execution/no error - yyleng = this.lexer.yyleng; - yytext = this.lexer.yytext; - yylineno = this.lexer.yylineno; - yyloc = this.lexer.yylloc; - if (recovering > 0) - recovering--; - } else { // error just occurred, resume old lookahead f/ before error - symbol = preErrorSymbol; - preErrorSymbol = null; - } - break; - - case 2: // reduce - //this.reductionCount++; - - len = this.productions_[action[1]][1]; - - // perform semantic action - yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 - // default location, uses first token for firsts, last for lasts - yyval._$ = { - first_line: lstack[lstack.length-(len||1)].first_line, - last_line: lstack[lstack.length-1].last_line, - first_column: lstack[lstack.length-(len||1)].first_column, - last_column: lstack[lstack.length-1].last_column - }; - r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); - - if (typeof r !== 'undefined') { - return r; - } - - // pop off stack - if (len) { - stack = stack.slice(0,-1*len*2); - vstack = vstack.slice(0, -1*len); - lstack = lstack.slice(0, -1*len); - } - - stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) - vstack.push(yyval.$); - lstack.push(yyval._$); - // goto new state = table[STATE][NONTERMINAL] - newState = table[stack[stack.length-2]][stack[stack.length-1]]; - stack.push(newState); - break; - - case 3: // accept - return true; - } - - } - - return true; - }}; - /* Jison generated lexer */ - var lexer = (function(){ - var lexer = ({EOF:1, - parseError:function parseError(str, hash) { - if (this.yy.parseError) { - this.yy.parseError(str, hash); - } else { - throw new Error(str); - } - }, - setInput:function (input) { - this._input = input; - this._more = this._less = this.done = false; - this.yylineno = this.yyleng = 0; - this.yytext = this.matched = this.match = ''; - this.conditionStack = ['INITIAL']; - this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; - return this; - }, - input:function () { - var ch = this._input[0]; - this.yytext+=ch; - this.yyleng++; - this.match+=ch; - this.matched+=ch; - var lines = ch.match(/\n/); - if (lines) this.yylineno++; - this._input = this._input.slice(1); - return ch; - }, - unput:function (ch) { - this._input = ch + this._input; - return this; - }, - more:function () { - this._more = true; - return this; - }, - less:function (n) { - this._input = this.match.slice(n) + this._input; - }, - pastInput:function () { - var past = this.matched.substr(0, this.matched.length - this.match.length); - return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); - }, - upcomingInput:function () { - var next = this.match; - if (next.length < 20) { - next += this._input.substr(0, 20-next.length); - } - return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); - }, - showPosition:function () { - var pre = this.pastInput(); - var c = new Array(pre.length + 1).join("-"); - return pre + this.upcomingInput() + "\n" + c+"^"; - }, - next:function () { - if (this.done) { - return this.EOF; - } - if (!this._input) this.done = true; - - var token, - match, - tempMatch, - index, - col, - lines; - if (!this._more) { - this.yytext = ''; - this.match = ''; - } - var rules = this._currentRules(); - for (var i=0;i < rules.length; i++) { - tempMatch = this._input.match(this.rules[rules[i]]); - if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { - match = tempMatch; - index = i; - if (!this.options.flex) break; - } - } - if (match) { - lines = match[0].match(/\n.*/g); - if (lines) this.yylineno += lines.length; - this.yylloc = {first_line: this.yylloc.last_line, - last_line: this.yylineno+1, - first_column: this.yylloc.last_column, - last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length} - this.yytext += match[0]; - this.match += match[0]; - this.yyleng = this.yytext.length; - this._more = false; - this._input = this._input.slice(match[0].length); - this.matched += match[0]; - token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]); - if (this.done && this._input) this.done = false; - if (token) return token; - else return; - } - if (this._input === "") { - return this.EOF; - } else { - this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), - {text: "", token: null, line: this.yylineno}); - } - }, - lex:function lex() { - var r = this.next(); - if (typeof r !== 'undefined') { - return r; - } else { - return this.lex(); - } - }, - begin:function begin(condition) { - this.conditionStack.push(condition); - }, - popState:function popState() { - return this.conditionStack.pop(); - }, - _currentRules:function _currentRules() { - return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; - }, - topState:function () { - return this.conditionStack[this.conditionStack.length-2]; - }, - pushState:function begin(condition) { - this.begin(condition); - }}); - lexer.options = {}; - lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { - - var YYSTATE=YY_START - switch($avoiding_name_collisions) { - case 0:/* skip whitespace */ - break; - case 1:return 6 - break; - case 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4 - break; - case 3:return 17 - break; - case 4:return 18 - break; - case 5:return 23 - break; - case 6:return 24 - break; - case 7:return 22 - break; - case 8:return 21 - break; - case 9:return 10 - break; - case 10:return 11 - break; - case 11:return 8 - break; - case 12:return 14 - break; - case 13:return 'INVALID' - break; - } - }; - lexer.rules = [/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/]; - lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}}; - - - ; - return lexer;})() - parser.lexer = lexer; - return parser; - })(); - if (true) { - exports.parser = jsonlint; - exports.parse = jsonlint.parse.bind(jsonlint); - } - -/***/ }, -/* 56 */ -/***/ function(module, exports) { - - 'use strict'; - - /** - * @constructor SearchBox - * Create a search box in given HTML container - * @param {JSONEditor} editor The JSON Editor to attach to - * @param {Element} container HTML container element of where to - * create the search box - */ - function SearchBox (editor, container) { - var searchBox = this; - - this.editor = editor; - this.timeout = undefined; - this.delay = 200; // ms - this.lastText = undefined; - - this.dom = {}; - this.dom.container = container; - - var table = document.createElement('table'); - this.dom.table = table; - table.className = 'jsoneditor-search'; - container.appendChild(table); - var tbody = document.createElement('tbody'); - this.dom.tbody = tbody; - table.appendChild(tbody); - var tr = document.createElement('tr'); - tbody.appendChild(tr); - - var td = document.createElement('td'); - tr.appendChild(td); - var results = document.createElement('div'); - this.dom.results = results; - results.className = 'jsoneditor-results'; - td.appendChild(results); - - td = document.createElement('td'); - tr.appendChild(td); - var divInput = document.createElement('div'); - this.dom.input = divInput; - divInput.className = 'jsoneditor-frame'; - divInput.title = 'Search fields and values'; - td.appendChild(divInput); - - // table to contain the text input and search button - var tableInput = document.createElement('table'); - divInput.appendChild(tableInput); - var tbodySearch = document.createElement('tbody'); - tableInput.appendChild(tbodySearch); - tr = document.createElement('tr'); - tbodySearch.appendChild(tr); - - var refreshSearch = document.createElement('button'); - refreshSearch.type = 'button'; - refreshSearch.className = 'jsoneditor-refresh'; - td = document.createElement('td'); - td.appendChild(refreshSearch); - tr.appendChild(td); - - var search = document.createElement('input'); - // search.type = 'button'; - this.dom.search = search; - search.oninput = function (event) { - searchBox._onDelayedSearch(event); - }; - search.onchange = function (event) { // For IE 9 - searchBox._onSearch(); - }; - search.onkeydown = function (event) { - searchBox._onKeyDown(event); - }; - search.onkeyup = function (event) { - searchBox._onKeyUp(event); - }; - refreshSearch.onclick = function (event) { - search.select(); - }; - - // TODO: ESC in FF restores the last input, is a FF bug, https://bugzilla.mozilla.org/show_bug.cgi?id=598819 - td = document.createElement('td'); - td.appendChild(search); - tr.appendChild(td); - - var searchNext = document.createElement('button'); - searchNext.type = 'button'; - searchNext.title = 'Next result (Enter)'; - searchNext.className = 'jsoneditor-next'; - searchNext.onclick = function () { - searchBox.next(); - }; - td = document.createElement('td'); - td.appendChild(searchNext); - tr.appendChild(td); - - var searchPrevious = document.createElement('button'); - searchPrevious.type = 'button'; - searchPrevious.title = 'Previous result (Shift+Enter)'; - searchPrevious.className = 'jsoneditor-previous'; - searchPrevious.onclick = function () { - searchBox.previous(); - }; - td = document.createElement('td'); - td.appendChild(searchPrevious); - tr.appendChild(td); - } - - /** - * Go to the next search result - * @param {boolean} [focus] If true, focus will be set to the next result - * focus is false by default. - */ - SearchBox.prototype.next = function(focus) { - if (this.results != undefined) { - var index = (this.resultIndex != undefined) ? this.resultIndex + 1 : 0; - if (index > this.results.length - 1) { - index = 0; - } - this._setActiveResult(index, focus); - } - }; - - /** - * Go to the prevous search result - * @param {boolean} [focus] If true, focus will be set to the next result - * focus is false by default. - */ - SearchBox.prototype.previous = function(focus) { - if (this.results != undefined) { - var max = this.results.length - 1; - var index = (this.resultIndex != undefined) ? this.resultIndex - 1 : max; - if (index < 0) { - index = max; - } - this._setActiveResult(index, focus); - } - }; - - /** - * Set new value for the current active result - * @param {Number} index - * @param {boolean} [focus] If true, focus will be set to the next result. - * focus is false by default. - * @private - */ - SearchBox.prototype._setActiveResult = function(index, focus) { - // de-activate current active result - if (this.activeResult) { - var prevNode = this.activeResult.node; - var prevElem = this.activeResult.elem; - if (prevElem == 'field') { - delete prevNode.searchFieldActive; - } - else { - delete prevNode.searchValueActive; - } - prevNode.updateDom(); - } - - if (!this.results || !this.results[index]) { - // out of range, set to undefined - this.resultIndex = undefined; - this.activeResult = undefined; - return; - } - - this.resultIndex = index; - - // set new node active - var node = this.results[this.resultIndex].node; - var elem = this.results[this.resultIndex].elem; - if (elem == 'field') { - node.searchFieldActive = true; - } - else { - node.searchValueActive = true; - } - this.activeResult = this.results[this.resultIndex]; - node.updateDom(); - - // TODO: not so nice that the focus is only set after the animation is finished - node.scrollTo(function () { - if (focus) { - node.focus(elem); - } - }); - }; - - /** - * Cancel any running onDelayedSearch. - * @private - */ - SearchBox.prototype._clearDelay = function() { - if (this.timeout != undefined) { - clearTimeout(this.timeout); - delete this.timeout; - } - }; - - /** - * Start a timer to execute a search after a short delay. - * Used for reducing the number of searches while typing. - * @param {Event} event - * @private - */ - SearchBox.prototype._onDelayedSearch = function (event) { - // execute the search after a short delay (reduces the number of - // search actions while typing in the search text box) - this._clearDelay(); - var searchBox = this; - this.timeout = setTimeout(function (event) { - searchBox._onSearch(); - }, - this.delay); - }; - - /** - * Handle onSearch event - * @param {boolean} [forceSearch] If true, search will be executed again even - * when the search text is not changed. - * Default is false. - * @private - */ - SearchBox.prototype._onSearch = function (forceSearch) { - this._clearDelay(); - - var value = this.dom.search.value; - var text = (value.length > 0) ? value : undefined; - if (text != this.lastText || forceSearch) { - // only search again when changed - this.lastText = text; - this.results = this.editor.search(text); - this._setActiveResult(undefined); - - // display search results - if (text != undefined) { - var resultCount = this.results.length; - switch (resultCount) { - case 0: this.dom.results.innerHTML = 'no results'; break; - case 1: this.dom.results.innerHTML = '1 result'; break; - default: this.dom.results.innerHTML = resultCount + ' results'; break; - } - } - else { - this.dom.results.innerHTML = ''; - } - } - }; - - /** - * Handle onKeyDown event in the input box - * @param {Event} event - * @private - */ - SearchBox.prototype._onKeyDown = function (event) { - var keynum = event.which; - if (keynum == 27) { // ESC - this.dom.search.value = ''; // clear search - this._onSearch(); - event.preventDefault(); - event.stopPropagation(); - } - else if (keynum == 13) { // Enter - if (event.ctrlKey) { - // force to search again - this._onSearch(true); - } - else if (event.shiftKey) { - // move to the previous search result - this.previous(); - } - else { - // move to the next search result - this.next(); - } - event.preventDefault(); - event.stopPropagation(); - } - }; - - /** - * Handle onKeyUp event in the input box - * @param {Event} event - * @private - */ - SearchBox.prototype._onKeyUp = function (event) { - var keynum = event.keyCode; - if (keynum != 27 && keynum != 13) { // !show and !Enter - this._onDelayedSearch(event); // For IE 9 - } - }; - - /** - * Clear the search results - */ - SearchBox.prototype.clear = function () { - this.dom.search.value = ''; - this._onSearch(); - }; - - /** - * Destroy the search box - */ - SearchBox.prototype.destroy = function () { - this.editor = null; - this.dom.container.removeChild(this.dom.table); - this.dom = null; - - this.results = null; - this.activeResult = null; - - this._clearDelay(); - - }; - - module.exports = SearchBox; - - -/***/ }, -/* 57 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var util = __webpack_require__(54); - - /** - * Node.getRootNode shim - * @param {Node} node node to check - * @return {Node} node's rootNode or `window` if there is ShadowDOM is not supported. - */ - function getRootNode(node){ - return node.getRootNode && node.getRootNode() || window; - } - - /** - * A context menu - * @param {Object[]} items Array containing the menu structure - * TODO: describe structure - * @param {Object} [options] Object with options. Available options: - * {function} close Callback called when the - * context menu is being closed. - * @constructor - */ - function ContextMenu (items, options) { - this.dom = {}; - - var me = this; - var dom = this.dom; - this.anchor = undefined; - this.items = items; - this.eventListeners = {}; - this.selection = undefined; // holds the selection before the menu was opened - this.onClose = options ? options.close : undefined; - - // create root element - var root = document.createElement('div'); - root.className = 'jsoneditor-contextmenu-root'; - dom.root = root; - - // create a container element - var menu = document.createElement('div'); - menu.className = 'jsoneditor-contextmenu'; - dom.menu = menu; - root.appendChild(menu); - - // create a list to hold the menu items - var list = document.createElement('ul'); - list.className = 'jsoneditor-menu'; - menu.appendChild(list); - dom.list = list; - dom.items = []; // list with all buttons - - // create a (non-visible) button to set the focus to the menu - var focusButton = document.createElement('button'); - focusButton.type = 'button'; - dom.focusButton = focusButton; - var li = document.createElement('li'); - li.style.overflow = 'hidden'; - li.style.height = '0'; - li.appendChild(focusButton); - list.appendChild(li); - - function createMenuItems (list, domItems, items) { - items.forEach(function (item) { - if (item.type == 'separator') { - // create a separator - var separator = document.createElement('div'); - separator.className = 'jsoneditor-separator'; - li = document.createElement('li'); - li.appendChild(separator); - list.appendChild(li); - } - else { - var domItem = {}; - - // create a menu item - var li = document.createElement('li'); - list.appendChild(li); - - // create a button in the menu item - var button = document.createElement('button'); - button.type = 'button'; - button.className = item.className; - domItem.button = button; - if (item.title) { - button.title = item.title; - } - if (item.click) { - button.onclick = function (event) { - event.preventDefault(); - me.hide(); - item.click(); - }; - } - li.appendChild(button); - - // create the contents of the button - if (item.submenu) { - // add the icon to the button - var divIcon = document.createElement('div'); - divIcon.className = 'jsoneditor-icon'; - button.appendChild(divIcon); - var divText = document.createElement('div'); - divText.className = 'jsoneditor-text' + - (item.click ? '' : ' jsoneditor-right-margin'); - divText.appendChild(document.createTextNode(item.text)); - button.appendChild(divText); - - var buttonSubmenu; - if (item.click) { - // submenu and a button with a click handler - button.className += ' jsoneditor-default'; - - var buttonExpand = document.createElement('button'); - buttonExpand.type = 'button'; - domItem.buttonExpand = buttonExpand; - buttonExpand.className = 'jsoneditor-expand'; - buttonExpand.innerHTML = '

'; - li.appendChild(buttonExpand); - if (item.submenuTitle) { - buttonExpand.title = item.submenuTitle; - } - - buttonSubmenu = buttonExpand; - } - else { - // submenu and a button without a click handler - var divExpand = document.createElement('div'); - divExpand.className = 'jsoneditor-expand'; - button.appendChild(divExpand); - - buttonSubmenu = button; - } - - // attach a handler to expand/collapse the submenu - buttonSubmenu.onclick = function (event) { - event.preventDefault(); - me._onExpandItem(domItem); - buttonSubmenu.focus(); - }; - - // create the submenu - var domSubItems = []; - domItem.subItems = domSubItems; - var ul = document.createElement('ul'); - domItem.ul = ul; - ul.className = 'jsoneditor-menu'; - ul.style.height = '0'; - li.appendChild(ul); - createMenuItems(ul, domSubItems, item.submenu); - } - else { - // no submenu, just a button with clickhandler - button.innerHTML = '
' + - '
' + item.text + '
'; - } - - domItems.push(domItem); - } - }); - } - createMenuItems(list, this.dom.items, items); - - // TODO: when the editor is small, show the submenu on the right instead of inline? - - // calculate the max height of the menu with one submenu expanded - this.maxHeight = 0; // height in pixels - items.forEach(function (item) { - var height = (items.length + (item.submenu ? item.submenu.length : 0)) * 24; - me.maxHeight = Math.max(me.maxHeight, height); - }); - } - - /** - * Get the currently visible buttons - * @return {Array.} buttons - * @private - */ - ContextMenu.prototype._getVisibleButtons = function () { - var buttons = []; - var me = this; - this.dom.items.forEach(function (item) { - buttons.push(item.button); - if (item.buttonExpand) { - buttons.push(item.buttonExpand); - } - if (item.subItems && item == me.expandedItem) { - item.subItems.forEach(function (subItem) { - buttons.push(subItem.button); - if (subItem.buttonExpand) { - buttons.push(subItem.buttonExpand); - } - // TODO: change to fully recursive method - }); - } - }); - - return buttons; - }; - - // currently displayed context menu, a singleton. We may only have one visible context menu - ContextMenu.visibleMenu = undefined; - - /** - * Attach the menu to an anchor - * @param {HTMLElement} anchor Anchor where the menu will be attached - * as sibling. - * @param {HTMLElement} [contentWindow] The DIV with with the (scrollable) contents - */ - ContextMenu.prototype.show = function (anchor, contentWindow) { - this.hide(); - - // determine whether to display the menu below or above the anchor - var showBelow = true; - var parent = anchor.parentNode; - var anchorRect = anchor.getBoundingClientRect(); - var parentRect = parent.getBoundingClientRect() - - if (contentWindow) { - - var contentRect = contentWindow.getBoundingClientRect(); - - if (anchorRect.bottom + this.maxHeight < contentRect.bottom) { - // fits below -> show below - } - else if (anchorRect.top - this.maxHeight > contentRect.top) { - // fits above -> show above - showBelow = false; - } - else { - // doesn't fit above nor below -> show below - } - } - - var leftGap = anchorRect.left - parentRect.left; - var topGap = anchorRect.top - parentRect.top; - - // position the menu - if (showBelow) { - // display the menu below the anchor - var anchorHeight = anchor.offsetHeight; - this.dom.menu.style.left = leftGap + 'px'; - this.dom.menu.style.top = topGap + anchorHeight + 'px'; - this.dom.menu.style.bottom = ''; - } - else { - // display the menu above the anchor - this.dom.menu.style.left = leftGap + 'px'; - this.dom.menu.style.top = topGap + 'px'; - this.dom.menu.style.bottom = '0px'; - } - - // find the root node of the page (window, or a shadow dom root element) - this.rootNode = getRootNode(anchor); - - // attach the menu to the parent of the anchor - parent.insertBefore(this.dom.root, parent.firstChild); - - // create and attach event listeners - var me = this; - var list = this.dom.list; - this.eventListeners.mousedown = util.addEventListener(this.rootNode, 'mousedown', function (event) { - // hide menu on click outside of the menu - var target = event.target; - if ((target != list) && !me._isChildOf(target, list)) { - me.hide(); - event.stopPropagation(); - event.preventDefault(); - } - }); - this.eventListeners.keydown = util.addEventListener(this.rootNode, 'keydown', function (event) { - me._onKeyDown(event); - }); - - // move focus to the first button in the context menu - this.selection = util.getSelection(); - this.anchor = anchor; - setTimeout(function () { - me.dom.focusButton.focus(); - }, 0); - - if (ContextMenu.visibleMenu) { - ContextMenu.visibleMenu.hide(); - } - ContextMenu.visibleMenu = this; - }; - - /** - * Hide the context menu if visible - */ - ContextMenu.prototype.hide = function () { - // remove the menu from the DOM - if (this.dom.root.parentNode) { - this.dom.root.parentNode.removeChild(this.dom.root); - if (this.onClose) { - this.onClose(); - } - } - - // remove all event listeners - // all event listeners are supposed to be attached to document. - for (var name in this.eventListeners) { - if (this.eventListeners.hasOwnProperty(name)) { - var fn = this.eventListeners[name]; - if (fn) { - util.removeEventListener(this.rootNode, name, fn); - } - delete this.eventListeners[name]; - } - } - - if (ContextMenu.visibleMenu == this) { - ContextMenu.visibleMenu = undefined; - } - }; - - /** - * Expand a submenu - * Any currently expanded submenu will be hided. - * @param {Object} domItem - * @private - */ - ContextMenu.prototype._onExpandItem = function (domItem) { - var me = this; - var alreadyVisible = (domItem == this.expandedItem); - - // hide the currently visible submenu - var expandedItem = this.expandedItem; - if (expandedItem) { - //var ul = expandedItem.ul; - expandedItem.ul.style.height = '0'; - expandedItem.ul.style.padding = ''; - setTimeout(function () { - if (me.expandedItem != expandedItem) { - expandedItem.ul.style.display = ''; - util.removeClassName(expandedItem.ul.parentNode, 'jsoneditor-selected'); - } - }, 300); // timeout duration must match the css transition duration - this.expandedItem = undefined; - } - - if (!alreadyVisible) { - var ul = domItem.ul; - ul.style.display = 'block'; - var height = ul.clientHeight; // force a reflow in Firefox - setTimeout(function () { - if (me.expandedItem == domItem) { - var childsHeight = 0; - for (var i = 0; i < ul.childNodes.length; i++) { - childsHeight += ul.childNodes[i].clientHeight; - } - ul.style.height = childsHeight + 'px'; - ul.style.padding = '5px 10px'; - } - }, 0); - util.addClassName(ul.parentNode, 'jsoneditor-selected'); - this.expandedItem = domItem; - } - }; - - /** - * Handle onkeydown event - * @param {Event} event - * @private - */ - ContextMenu.prototype._onKeyDown = function (event) { - var target = event.target; - var keynum = event.which; - var handled = false; - var buttons, targetIndex, prevButton, nextButton; - - if (keynum == 27) { // ESC - // hide the menu on ESC key - - // restore previous selection and focus - if (this.selection) { - util.setSelection(this.selection); - } - if (this.anchor) { - this.anchor.focus(); - } - - this.hide(); - - handled = true; - } - else if (keynum == 9) { // Tab - if (!event.shiftKey) { // Tab - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - if (targetIndex == buttons.length - 1) { - // move to first button - buttons[0].focus(); - handled = true; - } - } - else { // Shift+Tab - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - if (targetIndex == 0) { - // move to last button - buttons[buttons.length - 1].focus(); - handled = true; - } - } - } - else if (keynum == 37) { // Arrow Left - if (target.className == 'jsoneditor-expand') { - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - prevButton = buttons[targetIndex - 1]; - if (prevButton) { - prevButton.focus(); - } - } - handled = true; - } - else if (keynum == 38) { // Arrow Up - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - prevButton = buttons[targetIndex - 1]; - if (prevButton && prevButton.className == 'jsoneditor-expand') { - // skip expand button - prevButton = buttons[targetIndex - 2]; - } - if (!prevButton) { - // move to last button - prevButton = buttons[buttons.length - 1]; - } - if (prevButton) { - prevButton.focus(); - } - handled = true; - } - else if (keynum == 39) { // Arrow Right - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - nextButton = buttons[targetIndex + 1]; - if (nextButton && nextButton.className == 'jsoneditor-expand') { - nextButton.focus(); - } - handled = true; - } - else if (keynum == 40) { // Arrow Down - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - nextButton = buttons[targetIndex + 1]; - if (nextButton && nextButton.className == 'jsoneditor-expand') { - // skip expand button - nextButton = buttons[targetIndex + 2]; - } - if (!nextButton) { - // move to first button - nextButton = buttons[0]; - } - if (nextButton) { - nextButton.focus(); - handled = true; - } - handled = true; - } - // TODO: arrow left and right - - if (handled) { - event.stopPropagation(); - event.preventDefault(); - } - }; - - /** - * Test if an element is a child of a parent element. - * @param {Element} child - * @param {Element} parent - * @return {boolean} isChild - */ - ContextMenu.prototype._isChildOf = function (child, parent) { - var e = child.parentNode; - while (e) { - if (e == parent) { - return true; - } - e = e.parentNode; - } - - return false; - }; - - module.exports = ContextMenu; - - -/***/ }, -/* 58 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var ContextMenu = __webpack_require__(57); - - /** - * Creates a component that visualize path selection in tree based editors - * @param {HTMLElement} container - * @constructor - */ - function TreePath(container) { - if (container) { - this.path = document.createElement('div'); - this.path.className = 'jsoneditor-treepath'; - container.appendChild(this.path); - this.reset(); - } - }; - - /** - * Reset component to initial status - */ - TreePath.prototype.reset = function () { - this.path.innerHTML = ''; - } - - /** - * Renders the component UI according to a given path objects - * @param {Array} pathObjs a list of path objects - * - */ - TreePath.prototype.setPath = function (pathObjs) { - var me = this; - this.reset(); - if (pathObjs && pathObjs.length) { - pathObjs.forEach(function (pathObj, idx) { - var pathEl = document.createElement('span'); - var sepEl; - pathEl.className = 'jsoneditor-treepath-element'; - pathEl.innerText = pathObj.name; - pathEl.onclick = _onSegmentClick.bind(me, pathObj); - - me.path.appendChild(pathEl); - - if (pathObj.children.length) { - sepEl = document.createElement('span'); - sepEl.className = 'jsoneditor-treepath-seperator'; - sepEl.innerHTML = '►'; - - sepEl.onclick = function () { - var items = []; - pathObj.children.forEach(function (child) { - items.push({ - 'text': child.name, - 'className': 'jsoneditor-type-modes' + (pathObjs[idx + 1] + 1 && pathObjs[idx + 1].name === child.name ? ' jsoneditor-selected' : ''), - 'click': _onContextMenuItemClick.bind(me, pathObj, child.name) - }); - }); - var menu = new ContextMenu(items); - menu.show(sepEl); - }; - - me.path.appendChild(sepEl, me.container); - } - - if(idx === pathObjs.length - 1) { - var leftRectPos = (sepEl || pathEl).getBoundingClientRect().left; - if(me.path.offsetWidth < leftRectPos) { - me.path.scrollLeft = leftRectPos; - } - } - }); - } - - function _onSegmentClick(pathObj) { - if (this.selectionCallback) { - this.selectionCallback(pathObj); - } - }; - - function _onContextMenuItemClick(pathObj, selection) { - if (this.contextMenuCallback) { - this.contextMenuCallback(pathObj, selection); - } - }; - }; - - /** - * set a callback function for selection of path section - * @param {Function} callback function to invoke when section is selected - */ - TreePath.prototype.onSectionSelected = function (callback) { - if (typeof callback === 'function') { - this.selectionCallback = callback; - } - }; - - /** - * set a callback function for selection of path section - * @param {Function} callback function to invoke when section is selected - */ - TreePath.prototype.onContextMenuItemSelected = function (callback) { - if (typeof callback === 'function') { - this.contextMenuCallback = callback; - } - }; - - module.exports = TreePath; - -/***/ }, -/* 59 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var naturalSort = __webpack_require__(60); - var ContextMenu = __webpack_require__(57); - var appendNodeFactory = __webpack_require__(61); - var util = __webpack_require__(54); - - /** - * @constructor Node - * Create a new Node - * @param {./treemode} editor - * @param {Object} [params] Can contain parameters: - * {string} field - * {boolean} fieldEditable - * {*} value - * {String} type Can have values 'auto', 'array', - * 'object', or 'string'. - */ - function Node (editor, params) { - /** @type {./treemode} */ - this.editor = editor; - this.dom = {}; - this.expanded = false; - - if(params && (params instanceof Object)) { - this.setField(params.field, params.fieldEditable); - this.setValue(params.value, params.type); - } - else { - this.setField(''); - this.setValue(null); - } - - this._debouncedOnChangeValue = util.debounce(this._onChangeValue.bind(this), Node.prototype.DEBOUNCE_INTERVAL); - this._debouncedOnChangeField = util.debounce(this._onChangeField.bind(this), Node.prototype.DEBOUNCE_INTERVAL); - } - - // debounce interval for keyboard input in milliseconds - Node.prototype.DEBOUNCE_INTERVAL = 150; - - /** - * Determine whether the field and/or value of this node are editable - * @private - */ - Node.prototype._updateEditability = function () { - this.editable = { - field: true, - value: true - }; - - if (this.editor) { - this.editable.field = this.editor.options.mode === 'tree'; - this.editable.value = this.editor.options.mode !== 'view'; - - if ((this.editor.options.mode === 'tree' || this.editor.options.mode === 'form') && - (typeof this.editor.options.onEditable === 'function')) { - var editable = this.editor.options.onEditable({ - field: this.field, - value: this.value, - path: this.getPath() - }); - - if (typeof editable === 'boolean') { - this.editable.field = editable; - this.editable.value = editable; - } - else { - if (typeof editable.field === 'boolean') this.editable.field = editable.field; - if (typeof editable.value === 'boolean') this.editable.value = editable.value; - } - } - } - }; - - /** - * Get the path of this node - * @return {String[]} Array containing the path to this node - */ - Node.prototype.getPath = function () { - var node = this; - var path = []; - while (node) { - var field = !node.parent - ? undefined // do not add an (optional) field name of the root node - : (node.parent.type != 'array') - ? node.field - : node.index; - - if (field !== undefined) { - path.unshift(field); - } - node = node.parent; - } - return path; - }; - - /** - * Find a Node from a JSON path like '.items[3].name' - * @param {string} jsonPath - * @return {Node | null} Returns the Node when found, returns null if not found - */ - Node.prototype.findNode = function (jsonPath) { - var path = util.parsePath(jsonPath); - var node = this; - while (node && path.length > 0) { - var prop = path.shift(); - if (typeof prop === 'number') { - if (node.type !== 'array') { - throw new Error('Cannot get child node at index ' + prop + ': node is no array'); - } - node = node.childs[prop]; - } - else { // string - if (node.type !== 'object') { - throw new Error('Cannot get child node ' + prop + ': node is no object'); - } - node = node.childs.filter(function (child) { - return child.field === prop; - })[0]; - } - } - - return node; - }; - - /** - * Find all parents of this node. The parents are ordered from root node towards - * the original node. - * @return {Array.} - */ - Node.prototype.findParents = function () { - var parents = []; - var parent = this.parent; - while (parent) { - parents.unshift(parent); - parent = parent.parent; - } - return parents; - }; - - /** - * - * @param {{dataPath: string, keyword: string, message: string, params: Object, schemaPath: string} | null} error - * @param {Node} [child] When this is the error of a parent node, pointing - * to an invalid child node, the child node itself - * can be provided. If provided, clicking the error - * icon will set focus to the invalid child node. - */ - Node.prototype.setError = function (error, child) { - // ensure the dom exists - this.getDom(); - - this.error = error; - var tdError = this.dom.tdError; - if (error) { - if (!tdError) { - tdError = document.createElement('td'); - this.dom.tdError = tdError; - this.dom.tdValue.parentNode.appendChild(tdError); - } - - var popover = document.createElement('div'); - popover.className = 'jsoneditor-popover jsoneditor-right'; - popover.appendChild(document.createTextNode(error.message)); - - var button = document.createElement('button'); - button.type = 'button'; - button.className = 'jsoneditor-schema-error'; - button.appendChild(popover); - - // update the direction of the popover - button.onmouseover = button.onfocus = function updateDirection() { - var directions = ['right', 'above', 'below', 'left']; - for (var i = 0; i < directions.length; i++) { - var direction = directions[i]; - popover.className = 'jsoneditor-popover jsoneditor-' + direction; - - var contentRect = this.editor.content.getBoundingClientRect(); - var popoverRect = popover.getBoundingClientRect(); - var margin = 20; // account for a scroll bar - var fit = util.insideRect(contentRect, popoverRect, margin); - - if (fit) { - break; - } - } - }.bind(this); - - // when clicking the error icon, expand all nodes towards the invalid - // child node, and set focus to the child node - if (child) { - button.onclick = function showInvalidNode() { - child.findParents().forEach(function (parent) { - parent.expand(false); - }); - - child.scrollTo(function () { - child.focus(); - }); - }; - } - - // apply the error message to the node - while (tdError.firstChild) { - tdError.removeChild(tdError.firstChild); - } - tdError.appendChild(button); - } - else { - if (tdError) { - this.dom.tdError.parentNode.removeChild(this.dom.tdError); - delete this.dom.tdError; - } - } - }; - - /** - * Get the index of this node: the index in the list of childs where this - * node is part of - * @return {number} Returns the index, or -1 if this is the root node - */ - Node.prototype.getIndex = function () { - return this.parent ? this.parent.childs.indexOf(this) : -1; - }; - - /** - * Set parent node - * @param {Node} parent - */ - Node.prototype.setParent = function(parent) { - this.parent = parent; - }; - - /** - * Set field - * @param {String} field - * @param {boolean} [fieldEditable] - */ - Node.prototype.setField = function(field, fieldEditable) { - this.field = field; - this.previousField = field; - this.fieldEditable = (fieldEditable === true); - }; - - /** - * Get field - * @return {String} - */ - Node.prototype.getField = function() { - if (this.field === undefined) { - this._getDomField(); - } - - return this.field; - }; - - /** - * Set value. Value is a JSON structure or an element String, Boolean, etc. - * @param {*} value - * @param {String} [type] Specify the type of the value. Can be 'auto', - * 'array', 'object', or 'string' - */ - Node.prototype.setValue = function(value, type) { - var childValue, child; - - // first clear all current childs (if any) - var childs = this.childs; - if (childs) { - while (childs.length) { - this.removeChild(childs[0]); - } - } - - // TODO: remove the DOM of this Node - - this.type = this._getType(value); - - // check if type corresponds with the provided type - if (type && type != this.type) { - if (type == 'string' && this.type == 'auto') { - this.type = type; - } - else { - throw new Error('Type mismatch: ' + - 'cannot cast value of type "' + this.type + - ' to the specified type "' + type + '"'); - } - } - - if (this.type == 'array') { - // array - this.childs = []; - for (var i = 0, iMax = value.length; i < iMax; i++) { - childValue = value[i]; - if (childValue !== undefined && !(childValue instanceof Function)) { - // ignore undefined and functions - child = new Node(this.editor, { - value: childValue - }); - this.appendChild(child); - } - } - this.value = ''; - } - else if (this.type == 'object') { - // object - this.childs = []; - for (var childField in value) { - if (value.hasOwnProperty(childField)) { - childValue = value[childField]; - if (childValue !== undefined && !(childValue instanceof Function)) { - // ignore undefined and functions - child = new Node(this.editor, { - field: childField, - value: childValue - }); - this.appendChild(child); - } - } - } - this.value = ''; - - // sort object keys - if (this.editor.options.sortObjectKeys === true) { - this.sort('asc'); - } - } - else { - // value - this.childs = undefined; - this.value = value; - } - - this.previousValue = this.value; - }; - - /** - * Get value. Value is a JSON structure - * @return {*} value - */ - Node.prototype.getValue = function() { - //var childs, i, iMax; - - if (this.type == 'array') { - var arr = []; - this.childs.forEach (function (child) { - arr.push(child.getValue()); - }); - return arr; - } - else if (this.type == 'object') { - var obj = {}; - this.childs.forEach (function (child) { - obj[child.getField()] = child.getValue(); - }); - return obj; - } - else { - if (this.value === undefined) { - this._getDomValue(); - } - - return this.value; - } - }; - - /** - * Get the nesting level of this node - * @return {Number} level - */ - Node.prototype.getLevel = function() { - return (this.parent ? this.parent.getLevel() + 1 : 0); - }; - - /** - * Get jsonpath of the current node - * @return {Node[]} Returns an array with nodes - */ - Node.prototype.getNodePath = function () { - var path = this.parent ? this.parent.getNodePath() : []; - path.push(this); - return path; - }; - - /** - * Create a clone of a node - * The complete state of a clone is copied, including whether it is expanded or - * not. The DOM elements are not cloned. - * @return {Node} clone - */ - Node.prototype.clone = function() { - var clone = new Node(this.editor); - clone.type = this.type; - clone.field = this.field; - clone.fieldInnerText = this.fieldInnerText; - clone.fieldEditable = this.fieldEditable; - clone.value = this.value; - clone.valueInnerText = this.valueInnerText; - clone.expanded = this.expanded; - - if (this.childs) { - // an object or array - var cloneChilds = []; - this.childs.forEach(function (child) { - var childClone = child.clone(); - childClone.setParent(clone); - cloneChilds.push(childClone); - }); - clone.childs = cloneChilds; - } - else { - // a value - clone.childs = undefined; - } - - return clone; - }; - - /** - * Expand this node and optionally its childs. - * @param {boolean} [recurse] Optional recursion, true by default. When - * true, all childs will be expanded recursively - */ - Node.prototype.expand = function(recurse) { - if (!this.childs) { - return; - } - - // set this node expanded - this.expanded = true; - if (this.dom.expand) { - this.dom.expand.className = 'jsoneditor-expanded'; - } - - this.showChilds(); - - if (recurse !== false) { - this.childs.forEach(function (child) { - child.expand(recurse); - }); - } - }; - - /** - * Collapse this node and optionally its childs. - * @param {boolean} [recurse] Optional recursion, true by default. When - * true, all childs will be collapsed recursively - */ - Node.prototype.collapse = function(recurse) { - if (!this.childs) { - return; - } - - this.hideChilds(); - - // collapse childs in case of recurse - if (recurse !== false) { - this.childs.forEach(function (child) { - child.collapse(recurse); - }); - - } - - // make this node collapsed - if (this.dom.expand) { - this.dom.expand.className = 'jsoneditor-collapsed'; - } - this.expanded = false; - }; - - /** - * Recursively show all childs when they are expanded - */ - Node.prototype.showChilds = function() { - var childs = this.childs; - if (!childs) { - return; - } - if (!this.expanded) { - return; - } - - var tr = this.dom.tr; - var table = tr ? tr.parentNode : undefined; - if (table) { - // show row with append button - var append = this.getAppend(); - var nextTr = tr.nextSibling; - if (nextTr) { - table.insertBefore(append, nextTr); - } - else { - table.appendChild(append); - } - - // show childs - this.childs.forEach(function (child) { - table.insertBefore(child.getDom(), append); - child.showChilds(); - }); - } - }; - - /** - * Hide the node with all its childs - */ - Node.prototype.hide = function() { - var tr = this.dom.tr; - var table = tr ? tr.parentNode : undefined; - if (table) { - table.removeChild(tr); - } - this.hideChilds(); - }; - - - /** - * Recursively hide all childs - */ - Node.prototype.hideChilds = function() { - var childs = this.childs; - if (!childs) { - return; - } - if (!this.expanded) { - return; - } - - // hide append row - var append = this.getAppend(); - if (append.parentNode) { - append.parentNode.removeChild(append); - } - - // hide childs - this.childs.forEach(function (child) { - child.hide(); - }); - }; - - - /** - * Goes through the path from the node to the root and ensures that it is expanded - */ - Node.prototype.expandTo = function() { - var currentNode = this.parent; - while (currentNode) { - if (!currentNode.expanded) { - currentNode.expand(); - } - currentNode = currentNode.parent; - } - }; - - - /** - * Add a new child to the node. - * Only applicable when Node value is of type array or object - * @param {Node} node - */ - Node.prototype.appendChild = function(node) { - if (this._hasChilds()) { - // adjust the link to the parent - node.setParent(this); - node.fieldEditable = (this.type == 'object'); - if (this.type == 'array') { - node.index = this.childs.length; - } - this.childs.push(node); - - if (this.expanded) { - // insert into the DOM, before the appendRow - var newTr = node.getDom(); - var appendTr = this.getAppend(); - var table = appendTr ? appendTr.parentNode : undefined; - if (appendTr && table) { - table.insertBefore(newTr, appendTr); - } - - node.showChilds(); - } - - this.updateDom({'updateIndexes': true}); - node.updateDom({'recurse': true}); - } - }; - - - /** - * Move a node from its current parent to this node - * Only applicable when Node value is of type array or object - * @param {Node} node - * @param {Node} beforeNode - */ - Node.prototype.moveBefore = function(node, beforeNode) { - if (this._hasChilds()) { - // create a temporary row, to prevent the scroll position from jumping - // when removing the node - var tbody = (this.dom.tr) ? this.dom.tr.parentNode : undefined; - if (tbody) { - var trTemp = document.createElement('tr'); - trTemp.style.height = tbody.clientHeight + 'px'; - tbody.appendChild(trTemp); - } - - if (node.parent) { - node.parent.removeChild(node); - } - - if (beforeNode instanceof AppendNode) { - this.appendChild(node); - } - else { - this.insertBefore(node, beforeNode); - } - - if (tbody) { - tbody.removeChild(trTemp); - } - } - }; - - /** - * Move a node from its current parent to this node - * Only applicable when Node value is of type array or object. - * If index is out of range, the node will be appended to the end - * @param {Node} node - * @param {Number} index - */ - Node.prototype.moveTo = function (node, index) { - if (node.parent == this) { - // same parent - var currentIndex = this.childs.indexOf(node); - if (currentIndex < index) { - // compensate the index for removal of the node itself - index++; - } - } - - var beforeNode = this.childs[index] || this.append; - this.moveBefore(node, beforeNode); - }; - - /** - * Insert a new child before a given node - * Only applicable when Node value is of type array or object - * @param {Node} node - * @param {Node} beforeNode - */ - Node.prototype.insertBefore = function(node, beforeNode) { - if (this._hasChilds()) { - if (beforeNode == this.append) { - // append to the child nodes - - // adjust the link to the parent - node.setParent(this); - node.fieldEditable = (this.type == 'object'); - this.childs.push(node); - } - else { - // insert before a child node - var index = this.childs.indexOf(beforeNode); - if (index == -1) { - throw new Error('Node not found'); - } - - // adjust the link to the parent - node.setParent(this); - node.fieldEditable = (this.type == 'object'); - this.childs.splice(index, 0, node); - } - - if (this.expanded) { - // insert into the DOM - var newTr = node.getDom(); - var nextTr = beforeNode.getDom(); - var table = nextTr ? nextTr.parentNode : undefined; - if (nextTr && table) { - table.insertBefore(newTr, nextTr); - } - - node.showChilds(); - } - - this.updateDom({'updateIndexes': true}); - node.updateDom({'recurse': true}); - } - }; - - /** - * Insert a new child before a given node - * Only applicable when Node value is of type array or object - * @param {Node} node - * @param {Node} afterNode - */ - Node.prototype.insertAfter = function(node, afterNode) { - if (this._hasChilds()) { - var index = this.childs.indexOf(afterNode); - var beforeNode = this.childs[index + 1]; - if (beforeNode) { - this.insertBefore(node, beforeNode); - } - else { - this.appendChild(node); - } - } - }; - - /** - * Search in this node - * The node will be expanded when the text is found one of its childs, else - * it will be collapsed. Searches are case insensitive. - * @param {String} text - * @return {Node[]} results Array with nodes containing the search text - */ - Node.prototype.search = function(text) { - var results = []; - var index; - var search = text ? text.toLowerCase() : undefined; - - // delete old search data - delete this.searchField; - delete this.searchValue; - - // search in field - if (this.field != undefined) { - var field = String(this.field).toLowerCase(); - index = field.indexOf(search); - if (index != -1) { - this.searchField = true; - results.push({ - 'node': this, - 'elem': 'field' - }); - } - - // update dom - this._updateDomField(); - } - - // search in value - if (this._hasChilds()) { - // array, object - - // search the nodes childs - if (this.childs) { - var childResults = []; - this.childs.forEach(function (child) { - childResults = childResults.concat(child.search(text)); - }); - results = results.concat(childResults); - } - - // update dom - if (search != undefined) { - var recurse = false; - if (childResults.length == 0) { - this.collapse(recurse); - } - else { - this.expand(recurse); - } - } - } - else { - // string, auto - if (this.value != undefined ) { - var value = String(this.value).toLowerCase(); - index = value.indexOf(search); - if (index != -1) { - this.searchValue = true; - results.push({ - 'node': this, - 'elem': 'value' - }); - } - } - - // update dom - this._updateDomValue(); - } - - return results; - }; - - /** - * Move the scroll position such that this node is in the visible area. - * The node will not get the focus - * @param {function(boolean)} [callback] - */ - Node.prototype.scrollTo = function(callback) { - if (!this.dom.tr || !this.dom.tr.parentNode) { - // if the node is not visible, expand its parents - var parent = this.parent; - var recurse = false; - while (parent) { - parent.expand(recurse); - parent = parent.parent; - } - } - - if (this.dom.tr && this.dom.tr.parentNode) { - this.editor.scrollTo(this.dom.tr.offsetTop, callback); - } - }; - - - // stores the element name currently having the focus - Node.focusElement = undefined; - - /** - * Set focus to this node - * @param {String} [elementName] The field name of the element to get the - * focus available values: 'drag', 'menu', - * 'expand', 'field', 'value' (default) - */ - Node.prototype.focus = function(elementName) { - Node.focusElement = elementName; - - if (this.dom.tr && this.dom.tr.parentNode) { - var dom = this.dom; - - switch (elementName) { - case 'drag': - if (dom.drag) { - dom.drag.focus(); - } - else { - dom.menu.focus(); - } - break; - - case 'menu': - dom.menu.focus(); - break; - - case 'expand': - if (this._hasChilds()) { - dom.expand.focus(); - } - else if (dom.field && this.fieldEditable) { - dom.field.focus(); - util.selectContentEditable(dom.field); - } - else if (dom.value && !this._hasChilds()) { - dom.value.focus(); - util.selectContentEditable(dom.value); - } - else { - dom.menu.focus(); - } - break; - - case 'field': - if (dom.field && this.fieldEditable) { - dom.field.focus(); - util.selectContentEditable(dom.field); - } - else if (dom.value && !this._hasChilds()) { - dom.value.focus(); - util.selectContentEditable(dom.value); - } - else if (this._hasChilds()) { - dom.expand.focus(); - } - else { - dom.menu.focus(); - } - break; - - case 'value': - default: - if (dom.select) { - // enum select box - dom.select.focus(); - } - else if (dom.value && !this._hasChilds()) { - dom.value.focus(); - util.selectContentEditable(dom.value); - } - else if (dom.field && this.fieldEditable) { - dom.field.focus(); - util.selectContentEditable(dom.field); - } - else if (this._hasChilds()) { - dom.expand.focus(); - } - else { - dom.menu.focus(); - } - break; - } - } - }; - - /** - * Select all text in an editable div after a delay of 0 ms - * @param {Element} editableDiv - */ - Node.select = function(editableDiv) { - setTimeout(function () { - util.selectContentEditable(editableDiv); - }, 0); - }; - - /** - * Update the values from the DOM field and value of this node - */ - Node.prototype.blur = function() { - // retrieve the actual field and value from the DOM. - this._getDomValue(false); - this._getDomField(false); - }; - - /** - * Check if given node is a child. The method will check recursively to find - * this node. - * @param {Node} node - * @return {boolean} containsNode - */ - Node.prototype.containsNode = function(node) { - if (this == node) { - return true; - } - - var childs = this.childs; - if (childs) { - // TODO: use the js5 Array.some() here? - for (var i = 0, iMax = childs.length; i < iMax; i++) { - if (childs[i].containsNode(node)) { - return true; - } - } - } - - return false; - }; - - /** - * Move given node into this node - * @param {Node} node the childNode to be moved - * @param {Node} beforeNode node will be inserted before given - * node. If no beforeNode is given, - * the node is appended at the end - * @private - */ - Node.prototype._move = function(node, beforeNode) { - if (node == beforeNode) { - // nothing to do... - return; - } - - // check if this node is not a child of the node to be moved here - if (node.containsNode(this)) { - throw new Error('Cannot move a field into a child of itself'); - } - - // remove the original node - if (node.parent) { - node.parent.removeChild(node); - } - - // create a clone of the node - var clone = node.clone(); - node.clearDom(); - - // insert or append the node - if (beforeNode) { - this.insertBefore(clone, beforeNode); - } - else { - this.appendChild(clone); - } - - /* TODO: adjust the field name (to prevent equal field names) - if (this.type == 'object') { - } - */ - }; - - /** - * Remove a child from the node. - * Only applicable when Node value is of type array or object - * @param {Node} node The child node to be removed; - * @return {Node | undefined} node The removed node on success, - * else undefined - */ - Node.prototype.removeChild = function(node) { - if (this.childs) { - var index = this.childs.indexOf(node); - - if (index != -1) { - node.hide(); - - // delete old search results - delete node.searchField; - delete node.searchValue; - - var removedNode = this.childs.splice(index, 1)[0]; - removedNode.parent = null; - - this.updateDom({'updateIndexes': true}); - - return removedNode; - } - } - - return undefined; - }; - - /** - * Remove a child node node from this node - * This method is equal to Node.removeChild, except that _remove fire an - * onChange event. - * @param {Node} node - * @private - */ - Node.prototype._remove = function (node) { - this.removeChild(node); - }; - - /** - * Change the type of the value of this Node - * @param {String} newType - */ - Node.prototype.changeType = function (newType) { - var oldType = this.type; - - if (oldType == newType) { - // type is not changed - return; - } - - if ((newType == 'string' || newType == 'auto') && - (oldType == 'string' || oldType == 'auto')) { - // this is an easy change - this.type = newType; - } - else { - // change from array to object, or from string/auto to object/array - var table = this.dom.tr ? this.dom.tr.parentNode : undefined; - var lastTr; - if (this.expanded) { - lastTr = this.getAppend(); - } - else { - lastTr = this.getDom(); - } - var nextTr = (lastTr && lastTr.parentNode) ? lastTr.nextSibling : undefined; - - // hide current field and all its childs - this.hide(); - this.clearDom(); - - // adjust the field and the value - this.type = newType; - - // adjust childs - if (newType == 'object') { - if (!this.childs) { - this.childs = []; - } - - this.childs.forEach(function (child, index) { - child.clearDom(); - delete child.index; - child.fieldEditable = true; - if (child.field == undefined) { - child.field = ''; - } - }); - - if (oldType == 'string' || oldType == 'auto') { - this.expanded = true; - } - } - else if (newType == 'array') { - if (!this.childs) { - this.childs = []; - } - - this.childs.forEach(function (child, index) { - child.clearDom(); - child.fieldEditable = false; - child.index = index; - }); - - if (oldType == 'string' || oldType == 'auto') { - this.expanded = true; - } - } - else { - this.expanded = false; - } - - // create new DOM - if (table) { - if (nextTr) { - table.insertBefore(this.getDom(), nextTr); - } - else { - table.appendChild(this.getDom()); - } - } - this.showChilds(); - } - - if (newType == 'auto' || newType == 'string') { - // cast value to the correct type - if (newType == 'string') { - this.value = String(this.value); - } - else { - this.value = this._stringCast(String(this.value)); - } - - this.focus(); - } - - this.updateDom({'updateIndexes': true}); - }; - - /** - * Retrieve value from DOM - * @param {boolean} [silent] If true (default), no errors will be thrown in - * case of invalid data - * @private - */ - Node.prototype._getDomValue = function(silent) { - if (this.dom.value && this.type != 'array' && this.type != 'object') { - this.valueInnerText = util.getInnerText(this.dom.value); - } - - if (this.valueInnerText != undefined) { - try { - // retrieve the value - var value; - if (this.type == 'string') { - value = this._unescapeHTML(this.valueInnerText); - } - else { - var str = this._unescapeHTML(this.valueInnerText); - value = this._stringCast(str); - } - if (value !== this.value) { - this.value = value; - this._debouncedOnChangeValue(); - } - } - catch (err) { - this.value = undefined; - // TODO: sent an action with the new, invalid value? - if (silent !== true) { - throw err; - } - } - } - }; - - /** - * Handle a changed value - * @private - */ - Node.prototype._onChangeValue = function () { - // get current selection, then override the range such that we can select - // the added/removed text on undo/redo - var oldSelection = this.editor.getSelection(); - if (oldSelection.range) { - var undoDiff = util.textDiff(String(this.value), String(this.previousValue)); - oldSelection.range.startOffset = undoDiff.start; - oldSelection.range.endOffset = undoDiff.end; - } - var newSelection = this.editor.getSelection(); - if (newSelection.range) { - var redoDiff = util.textDiff(String(this.previousValue), String(this.value)); - newSelection.range.startOffset = redoDiff.start; - newSelection.range.endOffset = redoDiff.end; - } - - this.editor._onAction('editValue', { - node: this, - oldValue: this.previousValue, - newValue: this.value, - oldSelection: oldSelection, - newSelection: newSelection - }); - - this.previousValue = this.value; - }; - - /** - * Handle a changed field - * @private - */ - Node.prototype._onChangeField = function () { - // get current selection, then override the range such that we can select - // the added/removed text on undo/redo - var oldSelection = this.editor.getSelection(); - if (oldSelection.range) { - var undoDiff = util.textDiff(this.field, this.previousField); - oldSelection.range.startOffset = undoDiff.start; - oldSelection.range.endOffset = undoDiff.end; - } - var newSelection = this.editor.getSelection(); - if (newSelection.range) { - var redoDiff = util.textDiff(this.previousField, this.field); - newSelection.range.startOffset = redoDiff.start; - newSelection.range.endOffset = redoDiff.end; - } - - this.editor._onAction('editField', { - node: this, - oldValue: this.previousField, - newValue: this.field, - oldSelection: oldSelection, - newSelection: newSelection - }); - - this.previousField = this.field; - }; - - /** - * Update dom value: - * - the text color of the value, depending on the type of the value - * - the height of the field, depending on the width - * - background color in case it is empty - * @private - */ - Node.prototype._updateDomValue = function () { - var domValue = this.dom.value; - if (domValue) { - var classNames = ['jsoneditor-value']; - - - // set text color depending on value type - var value = this.value; - var type = (this.type == 'auto') ? util.type(value) : this.type; - var isUrl = type == 'string' && util.isUrl(value); - classNames.push('jsoneditor-' + type); - if (isUrl) { - classNames.push('jsoneditor-url'); - } - - // visual styling when empty - var isEmpty = (String(this.value) == '' && this.type != 'array' && this.type != 'object'); - if (isEmpty) { - classNames.push('jsoneditor-empty'); - } - - // highlight when there is a search result - if (this.searchValueActive) { - classNames.push('jsoneditor-highlight-active'); - } - if (this.searchValue) { - classNames.push('jsoneditor-highlight'); - } - - domValue.className = classNames.join(' '); - - // update title - if (type == 'array' || type == 'object') { - var count = this.childs ? this.childs.length : 0; - domValue.title = this.type + ' containing ' + count + ' items'; - } - else if (isUrl && this.editable.value) { - domValue.title = 'Ctrl+Click or Ctrl+Enter to open url in new window'; - } - else { - domValue.title = ''; - } - - // show checkbox when the value is a boolean - if (type === 'boolean' && this.editable.value) { - if (!this.dom.checkbox) { - this.dom.checkbox = document.createElement('input'); - this.dom.checkbox.type = 'checkbox'; - this.dom.tdCheckbox = document.createElement('td'); - this.dom.tdCheckbox.className = 'jsoneditor-tree'; - this.dom.tdCheckbox.appendChild(this.dom.checkbox); - - this.dom.tdValue.parentNode.insertBefore(this.dom.tdCheckbox, this.dom.tdValue); - } - - this.dom.checkbox.checked = this.value; - } - else { - // cleanup checkbox when displayed - if (this.dom.tdCheckbox) { - this.dom.tdCheckbox.parentNode.removeChild(this.dom.tdCheckbox); - delete this.dom.tdCheckbox; - delete this.dom.checkbox; - } - } - - if (this.enum && this.editable.value) { - // create select box when this node has an enum object - if (!this.dom.select) { - this.dom.select = document.createElement('select'); - this.id = this.field + "_" + new Date().getUTCMilliseconds(); - this.dom.select.id = this.id; - this.dom.select.name = this.dom.select.id; - - //Create the default empty option - this.dom.select.option = document.createElement('option'); - this.dom.select.option.value = ''; - this.dom.select.option.innerHTML = '--'; - this.dom.select.appendChild(this.dom.select.option); - - //Iterate all enum values and add them as options - for(var i = 0; i < this.enum.length; i++) { - this.dom.select.option = document.createElement('option'); - this.dom.select.option.value = this.enum[i]; - this.dom.select.option.innerHTML = this.enum[i]; - if(this.dom.select.option.value == this.value){ - this.dom.select.option.selected = true; - } - this.dom.select.appendChild(this.dom.select.option); - } - - this.dom.tdSelect = document.createElement('td'); - this.dom.tdSelect.className = 'jsoneditor-tree'; - this.dom.tdSelect.appendChild(this.dom.select); - this.dom.tdValue.parentNode.insertBefore(this.dom.tdSelect, this.dom.tdValue); - } - - // If the enum is inside a composite type display - // both the simple input and the dropdown field - if(this.schema && ( - !this.schema.hasOwnProperty("oneOf") && - !this.schema.hasOwnProperty("anyOf") && - !this.schema.hasOwnProperty("allOf")) - ) { - this.valueFieldHTML = this.dom.tdValue.innerHTML; - this.dom.tdValue.style.visibility = 'hidden'; - this.dom.tdValue.innerHTML = ''; - } else { - delete this.valueFieldHTML; - } - } - else { - // cleanup select box when displayed - if (this.dom.tdSelect) { - this.dom.tdSelect.parentNode.removeChild(this.dom.tdSelect); - delete this.dom.tdSelect; - delete this.dom.select; - this.dom.tdValue.innerHTML = this.valueFieldHTML; - this.dom.tdValue.style.visibility = ''; - delete this.valueFieldHTML; - } - } - - // strip formatting from the contents of the editable div - util.stripFormatting(domValue); - } - }; - - /** - * Update dom field: - * - the text color of the field, depending on the text - * - the height of the field, depending on the width - * - background color in case it is empty - * @private - */ - Node.prototype._updateDomField = function () { - var domField = this.dom.field; - if (domField) { - // make backgound color lightgray when empty - var isEmpty = (String(this.field) == '' && this.parent.type != 'array'); - if (isEmpty) { - util.addClassName(domField, 'jsoneditor-empty'); - } - else { - util.removeClassName(domField, 'jsoneditor-empty'); - } - - // highlight when there is a search result - if (this.searchFieldActive) { - util.addClassName(domField, 'jsoneditor-highlight-active'); - } - else { - util.removeClassName(domField, 'jsoneditor-highlight-active'); - } - if (this.searchField) { - util.addClassName(domField, 'jsoneditor-highlight'); - } - else { - util.removeClassName(domField, 'jsoneditor-highlight'); - } - - // strip formatting from the contents of the editable div - util.stripFormatting(domField); - } - }; - - /** - * Retrieve field from DOM - * @param {boolean} [silent] If true (default), no errors will be thrown in - * case of invalid data - * @private - */ - Node.prototype._getDomField = function(silent) { - if (this.dom.field && this.fieldEditable) { - this.fieldInnerText = util.getInnerText(this.dom.field); - } - - if (this.fieldInnerText != undefined) { - try { - var field = this._unescapeHTML(this.fieldInnerText); - - if (field !== this.field) { - this.field = field; - this._debouncedOnChangeField(); - } - } - catch (err) { - this.field = undefined; - // TODO: sent an action here, with the new, invalid value? - if (silent !== true) { - throw err; - } - } - } - }; - - /** - * Validate this node and all it's childs - * @return {Array.<{node: Node, error: {message: string}}>} Returns a list with duplicates - */ - Node.prototype.validate = function () { - var errors = []; - - // find duplicate keys - if (this.type === 'object') { - var keys = {}; - var duplicateKeys = []; - for (var i = 0; i < this.childs.length; i++) { - var child = this.childs[i]; - if (keys.hasOwnProperty(child.field)) { - duplicateKeys.push(child.field); - } - keys[child.field] = true; - } - - if (duplicateKeys.length > 0) { - errors = this.childs - .filter(function (node) { - return duplicateKeys.indexOf(node.field) !== -1; - }) - .map(function (node) { - return { - node: node, - error: { - message: 'duplicate key "' + node.field + '"' - } - } - }); - } - } - - // recurse over the childs - if (this.childs) { - for (var i = 0; i < this.childs.length; i++) { - var e = this.childs[i].validate(); - if (e.length > 0) { - errors = errors.concat(e); - } - } - } - - return errors; - }; - - /** - * Clear the dom of the node - */ - Node.prototype.clearDom = function() { - // TODO: hide the node first? - //this.hide(); - // TODO: recursively clear dom? - - this.dom = {}; - }; - - /** - * Get the HTML DOM TR element of the node. - * The dom will be generated when not yet created - * @return {Element} tr HTML DOM TR Element - */ - Node.prototype.getDom = function() { - var dom = this.dom; - if (dom.tr) { - return dom.tr; - } - - this._updateEditability(); - - // create row - dom.tr = document.createElement('tr'); - dom.tr.node = this; - - if (this.editor.options.mode === 'tree') { // note: we take here the global setting - var tdDrag = document.createElement('td'); - if (this.editable.field) { - // create draggable area - if (this.parent) { - var domDrag = document.createElement('button'); - domDrag.type = 'button'; - dom.drag = domDrag; - domDrag.className = 'jsoneditor-dragarea'; - domDrag.title = 'Drag to move this field (Alt+Shift+Arrows)'; - tdDrag.appendChild(domDrag); - } - } - dom.tr.appendChild(tdDrag); - - // create context menu - var tdMenu = document.createElement('td'); - var menu = document.createElement('button'); - menu.type = 'button'; - dom.menu = menu; - menu.className = 'jsoneditor-contextmenu'; - menu.title = 'Click to open the actions menu (Ctrl+M)'; - tdMenu.appendChild(dom.menu); - dom.tr.appendChild(tdMenu); - } - - // create tree and field - var tdField = document.createElement('td'); - dom.tr.appendChild(tdField); - dom.tree = this._createDomTree(); - tdField.appendChild(dom.tree); - - this.updateDom({'updateIndexes': true}); - - return dom.tr; - }; - - /** - * DragStart event, fired on mousedown on the dragarea at the left side of a Node - * @param {Node[] | Node} nodes - * @param {Event} event - */ - Node.onDragStart = function (nodes, event) { - if (!Array.isArray(nodes)) { - return Node.onDragStart([nodes], event); - } - if (nodes.length === 0) { - return; - } - - var firstNode = nodes[0]; - var lastNode = nodes[nodes.length - 1]; - var draggedNode = Node.getNodeFromTarget(event.target); - var beforeNode = lastNode._nextSibling(); - var editor = firstNode.editor; - - // in case of multiple selected nodes, offsetY prevents the selection from - // jumping when you start dragging one of the lower down nodes in the selection - var offsetY = util.getAbsoluteTop(draggedNode.dom.tr) - util.getAbsoluteTop(firstNode.dom.tr); - - if (!editor.mousemove) { - editor.mousemove = util.addEventListener(window, 'mousemove', function (event) { - Node.onDrag(nodes, event); - }); - } - - if (!editor.mouseup) { - editor.mouseup = util.addEventListener(window, 'mouseup',function (event ) { - Node.onDragEnd(nodes, event); - }); - } - - editor.highlighter.lock(); - editor.drag = { - oldCursor: document.body.style.cursor, - oldSelection: editor.getSelection(), - oldBeforeNode: beforeNode, - mouseX: event.pageX, - offsetY: offsetY, - level: firstNode.getLevel() - }; - document.body.style.cursor = 'move'; - - event.preventDefault(); - }; - - /** - * Drag event, fired when moving the mouse while dragging a Node - * @param {Node[] | Node} nodes - * @param {Event} event - */ - Node.onDrag = function (nodes, event) { - if (!Array.isArray(nodes)) { - return Node.onDrag([nodes], event); - } - if (nodes.length === 0) { - return; - } - - // TODO: this method has grown too large. Split it in a number of methods - var editor = nodes[0].editor; - var mouseY = event.pageY - editor.drag.offsetY; - var mouseX = event.pageX; - var trThis, trPrev, trNext, trFirst, trLast, trRoot; - var nodePrev, nodeNext; - var topThis, topPrev, topFirst, heightThis, bottomNext, heightNext; - var moved = false; - - // TODO: add an ESC option, which resets to the original position - - // move up/down - var firstNode = nodes[0]; - trThis = firstNode.dom.tr; - topThis = util.getAbsoluteTop(trThis); - heightThis = trThis.offsetHeight; - if (mouseY < topThis) { - // move up - trPrev = trThis; - do { - trPrev = trPrev.previousSibling; - nodePrev = Node.getNodeFromTarget(trPrev); - topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0; - } - while (trPrev && mouseY < topPrev); - - if (nodePrev && !nodePrev.parent) { - nodePrev = undefined; - } - - if (!nodePrev) { - // move to the first node - trRoot = trThis.parentNode.firstChild; - trPrev = trRoot ? trRoot.nextSibling : undefined; - nodePrev = Node.getNodeFromTarget(trPrev); - if (nodePrev == firstNode) { - nodePrev = undefined; - } - } - - if (nodePrev) { - // check if mouseY is really inside the found node - trPrev = nodePrev.dom.tr; - topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0; - if (mouseY > topPrev + heightThis) { - nodePrev = undefined; - } - } - - if (nodePrev) { - nodes.forEach(function (node) { - nodePrev.parent.moveBefore(node, nodePrev); - }); - moved = true; - } - } - else { - // move down - var lastNode = nodes[nodes.length - 1]; - trLast = (lastNode.expanded && lastNode.append) ? lastNode.append.getDom() : lastNode.dom.tr; - trFirst = trLast ? trLast.nextSibling : undefined; - if (trFirst) { - topFirst = util.getAbsoluteTop(trFirst); - trNext = trFirst; - do { - nodeNext = Node.getNodeFromTarget(trNext); - if (trNext) { - bottomNext = trNext.nextSibling ? - util.getAbsoluteTop(trNext.nextSibling) : 0; - heightNext = trNext ? (bottomNext - topFirst) : 0; - - if (nodeNext.parent.childs.length == nodes.length && - nodeNext.parent.childs[nodes.length - 1] == lastNode) { - // We are about to remove the last child of this parent, - // which will make the parents appendNode visible. - topThis += 27; - // TODO: dangerous to suppose the height of the appendNode a constant of 27 px. - } - } - - trNext = trNext.nextSibling; - } - while (trNext && mouseY > topThis + heightNext); - - if (nodeNext && nodeNext.parent) { - // calculate the desired level - var diffX = (mouseX - editor.drag.mouseX); - var diffLevel = Math.round(diffX / 24 / 2); - var level = editor.drag.level + diffLevel; // desired level - var levelNext = nodeNext.getLevel(); // level to be - - // find the best fitting level (move upwards over the append nodes) - trPrev = nodeNext.dom.tr.previousSibling; - while (levelNext < level && trPrev) { - nodePrev = Node.getNodeFromTarget(trPrev); - - var isDraggedNode = nodes.some(function (node) { - return node === nodePrev || nodePrev._isChildOf(node); - }); - - if (isDraggedNode) { - // neglect the dragged nodes themselves and their childs - } - else if (nodePrev instanceof AppendNode) { - var childs = nodePrev.parent.childs; - if (childs.length != nodes.length || childs[nodes.length - 1] != lastNode) { - // non-visible append node of a list of childs - // consisting of not only this node (else the - // append node will change into a visible "empty" - // text when removing this node). - nodeNext = Node.getNodeFromTarget(trPrev); - levelNext = nodeNext.getLevel(); - } - else { - break; - } - } - else { - break; - } - - trPrev = trPrev.previousSibling; - } - - // move the node when its position is changed - if (trLast.nextSibling != nodeNext.dom.tr) { - nodes.forEach(function (node) { - nodeNext.parent.moveBefore(node, nodeNext); - }); - moved = true; - } - } - } - } - - if (moved) { - // update the dragging parameters when moved - editor.drag.mouseX = mouseX; - editor.drag.level = firstNode.getLevel(); - } - - // auto scroll when hovering around the top of the editor - editor.startAutoScroll(mouseY); - - event.preventDefault(); - }; - - /** - * Drag event, fired on mouseup after having dragged a node - * @param {Node[] | Node} nodes - * @param {Event} event - */ - Node.onDragEnd = function (nodes, event) { - if (!Array.isArray(nodes)) { - return Node.onDrag([nodes], event); - } - if (nodes.length === 0) { - return; - } - - var firstNode = nodes[0]; - var editor = firstNode.editor; - var parent = firstNode.parent; - var firstIndex = parent.childs.indexOf(firstNode); - var beforeNode = parent.childs[firstIndex + nodes.length] || parent.append; - - // set focus to the context menu button of the first node - if (nodes[0]) { - nodes[0].dom.menu.focus(); - } - - var params = { - nodes: nodes, - oldSelection: editor.drag.oldSelection, - newSelection: editor.getSelection(), - oldBeforeNode: editor.drag.oldBeforeNode, - newBeforeNode: beforeNode - }; - - if (params.oldBeforeNode != params.newBeforeNode) { - // only register this action if the node is actually moved to another place - editor._onAction('moveNodes', params); - } - - document.body.style.cursor = editor.drag.oldCursor; - editor.highlighter.unlock(); - nodes.forEach(function (node) { - if (event.target !== node.dom.drag && event.target !== node.dom.menu) { - editor.highlighter.unhighlight(); - } - }); - delete editor.drag; - - if (editor.mousemove) { - util.removeEventListener(window, 'mousemove', editor.mousemove); - delete editor.mousemove; - } - if (editor.mouseup) { - util.removeEventListener(window, 'mouseup', editor.mouseup); - delete editor.mouseup; - } - - // Stop any running auto scroll - editor.stopAutoScroll(); - - event.preventDefault(); - }; - - /** - * Test if this node is a child of an other node - * @param {Node} node - * @return {boolean} isChild - * @private - */ - Node.prototype._isChildOf = function (node) { - var n = this.parent; - while (n) { - if (n == node) { - return true; - } - n = n.parent; - } - - return false; - }; - - /** - * Create an editable field - * @return {Element} domField - * @private - */ - Node.prototype._createDomField = function () { - return document.createElement('div'); - }; - - /** - * Set highlighting for this node and all its childs. - * Only applied to the currently visible (expanded childs) - * @param {boolean} highlight - */ - Node.prototype.setHighlight = function (highlight) { - if (this.dom.tr) { - if (highlight) { - util.addClassName(this.dom.tr, 'jsoneditor-highlight'); - } - else { - util.removeClassName(this.dom.tr, 'jsoneditor-highlight'); - } - - if (this.append) { - this.append.setHighlight(highlight); - } - - if (this.childs) { - this.childs.forEach(function (child) { - child.setHighlight(highlight); - }); - } - } - }; - - /** - * Select or deselect a node - * @param {boolean} selected - * @param {boolean} [isFirst] - */ - Node.prototype.setSelected = function (selected, isFirst) { - this.selected = selected; - - if (this.dom.tr) { - if (selected) { - util.addClassName(this.dom.tr, 'jsoneditor-selected'); - } - else { - util.removeClassName(this.dom.tr, 'jsoneditor-selected'); - } - - if (isFirst) { - util.addClassName(this.dom.tr, 'jsoneditor-first'); - } - else { - util.removeClassName(this.dom.tr, 'jsoneditor-first'); - } - - if (this.append) { - this.append.setSelected(selected); - } - - if (this.childs) { - this.childs.forEach(function (child) { - child.setSelected(selected); - }); - } - } - }; - - /** - * Update the value of the node. Only primitive types are allowed, no Object - * or Array is allowed. - * @param {String | Number | Boolean | null} value - */ - Node.prototype.updateValue = function (value) { - this.value = value; - this.updateDom(); - }; - - /** - * Update the field of the node. - * @param {String} field - */ - Node.prototype.updateField = function (field) { - this.field = field; - this.updateDom(); - }; - - /** - * Update the HTML DOM, optionally recursing through the childs - * @param {Object} [options] Available parameters: - * {boolean} [recurse] If true, the - * DOM of the childs will be updated recursively. - * False by default. - * {boolean} [updateIndexes] If true, the childs - * indexes of the node will be updated too. False by - * default. - */ - Node.prototype.updateDom = function (options) { - // update level indentation - var domTree = this.dom.tree; - if (domTree) { - domTree.style.marginLeft = this.getLevel() * 24 + 'px'; - } - - // apply field to DOM - var domField = this.dom.field; - if (domField) { - if (this.fieldEditable) { - // parent is an object - domField.contentEditable = this.editable.field; - domField.spellcheck = false; - domField.className = 'jsoneditor-field'; - } - else { - // parent is an array this is the root node - domField.className = 'jsoneditor-readonly'; - } - - var fieldText; - if (this.index != undefined) { - fieldText = this.index; - } - else if (this.field != undefined) { - fieldText = this.field; - } - else if (this._hasChilds()) { - fieldText = this.type; - } - else { - fieldText = ''; - } - domField.innerHTML = this._escapeHTML(fieldText); - - this._updateSchema(); - } - - // apply value to DOM - var domValue = this.dom.value; - if (domValue) { - var count = this.childs ? this.childs.length : 0; - if (this.type == 'array') { - domValue.innerHTML = '[' + count + ']'; - util.addClassName(this.dom.tr, 'jsoneditor-expandable'); - } - else if (this.type == 'object') { - domValue.innerHTML = '{' + count + '}'; - util.addClassName(this.dom.tr, 'jsoneditor-expandable'); - } - else { - domValue.innerHTML = this._escapeHTML(this.value); - util.removeClassName(this.dom.tr, 'jsoneditor-expandable'); - } - } - - // update field and value - this._updateDomField(); - this._updateDomValue(); - - // update childs indexes - if (options && options.updateIndexes === true) { - // updateIndexes is true or undefined - this._updateDomIndexes(); - } - - if (options && options.recurse === true) { - // recurse is true or undefined. update childs recursively - if (this.childs) { - this.childs.forEach(function (child) { - child.updateDom(options); - }); - } - } - - // update row with append button - if (this.append) { - this.append.updateDom(); - } - }; - - /** - * Locate the JSON schema of the node and check for any enum type - * @private - */ - Node.prototype._updateSchema = function () { - //Locating the schema of the node and checking for any enum type - if(this.editor && this.editor.options) { - // find the part of the json schema matching this nodes path - this.schema = this.editor.options.schema - ? Node._findSchema(this.editor.options.schema, this.getPath()) - : null; - if (this.schema) { - this.enum = Node._findEnum(this.schema); - } - else { - delete this.enum; - } - } - }; - - /** - * find an enum definition in a JSON schema, as property `enum` or inside - * one of the schemas composites (`oneOf`, `anyOf`, `allOf`) - * @param {Object} schema - * @return {Array | null} Returns the enum when found, null otherwise. - * @private - */ - Node._findEnum = function (schema) { - if (schema.enum) { - return schema.enum; - } - - var composite = schema.oneOf || schema.anyOf || schema.allOf; - if (composite) { - var match = composite.filter(function (entry) {return entry.enum}); - if (match.length > 0) { - return match[0].enum; - } - } - - return null - }; - - /** - * Return the part of a JSON schema matching given path. - * @param {Object} schema - * @param {Array.} path - * @return {Object | null} - * @private - */ - Node._findSchema = function (schema, path) { - var childSchema = schema; - var foundSchema = childSchema; - - var allSchemas = schema.oneOf || schema.anyOf || schema.allOf; - if (!allSchemas) { - allSchemas = [schema]; - } - - for (var j = 0; j < allSchemas.length; j++) { - childSchema = allSchemas[j]; - - for (var i = 0; i < path.length && childSchema; i++) { - var key = path[i]; - - if (typeof key === 'string' && childSchema.patternProperties && i == path.length - 1) { - for (var prop in childSchema.patternProperties) { - foundSchema = Node._findSchema(childSchema.patternProperties[prop], path.slice(i, path.length)); - } - } - else if (childSchema.items && childSchema.items.properties) { - childSchema = childSchema.items.properties[key]; - if (childSchema) { - foundSchema = Node._findSchema(childSchema, path.slice(i, path.length)); - } - } - else if (typeof key === 'string' && childSchema.properties) { - childSchema = childSchema.properties[key] || null; - if (childSchema) { - foundSchema = Node._findSchema(childSchema, path.slice(i, path.length)); - } - } - else if (typeof key === 'number' && childSchema.items) { - childSchema = childSchema.items; - if (childSchema) { - foundSchema = Node._findSchema(childSchema, path.slice(i, path.length)); - } - } - } - - } - return foundSchema - }; - - /** - * Update the DOM of the childs of a node: update indexes and undefined field - * names. - * Only applicable when structure is an array or object - * @private - */ - Node.prototype._updateDomIndexes = function () { - var domValue = this.dom.value; - var childs = this.childs; - if (domValue && childs) { - if (this.type == 'array') { - childs.forEach(function (child, index) { - child.index = index; - var childField = child.dom.field; - if (childField) { - childField.innerHTML = index; - } - }); - } - else if (this.type == 'object') { - childs.forEach(function (child) { - if (child.index != undefined) { - delete child.index; - - if (child.field == undefined) { - child.field = ''; - } - } - }); - } - } - }; - - /** - * Create an editable value - * @private - */ - Node.prototype._createDomValue = function () { - var domValue; - - if (this.type == 'array') { - domValue = document.createElement('div'); - domValue.innerHTML = '[...]'; - } - else if (this.type == 'object') { - domValue = document.createElement('div'); - domValue.innerHTML = '{...}'; - } - else { - if (!this.editable.value && util.isUrl(this.value)) { - // create a link in case of read-only editor and value containing an url - domValue = document.createElement('a'); - domValue.href = this.value; - domValue.target = '_blank'; - domValue.innerHTML = this._escapeHTML(this.value); - } - else { - // create an editable or read-only div - domValue = document.createElement('div'); - domValue.contentEditable = this.editable.value; - domValue.spellcheck = false; - domValue.innerHTML = this._escapeHTML(this.value); - } - } - - return domValue; - }; - - /** - * Create an expand/collapse button - * @return {Element} expand - * @private - */ - Node.prototype._createDomExpandButton = function () { - // create expand button - var expand = document.createElement('button'); - expand.type = 'button'; - if (this._hasChilds()) { - expand.className = this.expanded ? 'jsoneditor-expanded' : 'jsoneditor-collapsed'; - expand.title = - 'Click to expand/collapse this field (Ctrl+E). \n' + - 'Ctrl+Click to expand/collapse including all childs.'; - } - else { - expand.className = 'jsoneditor-invisible'; - expand.title = ''; - } - - return expand; - }; - - - /** - * Create a DOM tree element, containing the expand/collapse button - * @return {Element} domTree - * @private - */ - Node.prototype._createDomTree = function () { - var dom = this.dom; - var domTree = document.createElement('table'); - var tbody = document.createElement('tbody'); - domTree.style.borderCollapse = 'collapse'; // TODO: put in css - domTree.className = 'jsoneditor-values'; - domTree.appendChild(tbody); - var tr = document.createElement('tr'); - tbody.appendChild(tr); - - // create expand button - var tdExpand = document.createElement('td'); - tdExpand.className = 'jsoneditor-tree'; - tr.appendChild(tdExpand); - dom.expand = this._createDomExpandButton(); - tdExpand.appendChild(dom.expand); - dom.tdExpand = tdExpand; - - // create the field - var tdField = document.createElement('td'); - tdField.className = 'jsoneditor-tree'; - tr.appendChild(tdField); - dom.field = this._createDomField(); - tdField.appendChild(dom.field); - dom.tdField = tdField; - - // create a separator - var tdSeparator = document.createElement('td'); - tdSeparator.className = 'jsoneditor-tree'; - tr.appendChild(tdSeparator); - if (this.type != 'object' && this.type != 'array') { - tdSeparator.appendChild(document.createTextNode(':')); - tdSeparator.className = 'jsoneditor-separator'; - } - dom.tdSeparator = tdSeparator; - - // create the value - var tdValue = document.createElement('td'); - tdValue.className = 'jsoneditor-tree'; - tr.appendChild(tdValue); - dom.value = this._createDomValue(); - tdValue.appendChild(dom.value); - dom.tdValue = tdValue; - - return domTree; - }; - - /** - * Handle an event. The event is caught centrally by the editor - * @param {Event} event - */ - Node.prototype.onEvent = function (event) { - var type = event.type, - target = event.target || event.srcElement, - dom = this.dom, - node = this, - expandable = this._hasChilds(); - - // check if mouse is on menu or on dragarea. - // If so, highlight current row and its childs - if (target == dom.drag || target == dom.menu) { - if (type == 'mouseover') { - this.editor.highlighter.highlight(this); - } - else if (type == 'mouseout') { - this.editor.highlighter.unhighlight(); - } - } - - // context menu events - if (type == 'click' && target == dom.menu) { - var highlighter = node.editor.highlighter; - highlighter.highlight(node); - highlighter.lock(); - util.addClassName(dom.menu, 'jsoneditor-selected'); - this.showContextMenu(dom.menu, function () { - util.removeClassName(dom.menu, 'jsoneditor-selected'); - highlighter.unlock(); - highlighter.unhighlight(); - }); - } - - // expand events - if (type == 'click') { - if (target == dom.expand || - ((node.editor.options.mode === 'view' || node.editor.options.mode === 'form') && target.nodeName === 'DIV')) { - if (expandable) { - var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all - this._onExpand(recurse); - } - } - } - - // swap the value of a boolean when the checkbox displayed left is clicked - if (type == 'change' && target == dom.checkbox) { - this.dom.value.innerHTML = !this.value; - this._getDomValue(); - } - - // update the value of the node based on the selected option - if (type == 'change' && target == dom.select) { - this.dom.value.innerHTML = dom.select.value; - this._getDomValue(); - this._updateDomValue(); - } - - // value events - var domValue = dom.value; - if (target == domValue) { - //noinspection FallthroughInSwitchStatementJS - switch (type) { - case 'blur': - case 'change': - this._getDomValue(true); - this._updateDomValue(); - if (this.value) { - domValue.innerHTML = this._escapeHTML(this.value); - } - break; - - case 'input': - //this._debouncedGetDomValue(true); // TODO - this._getDomValue(true); - this._updateDomValue(); - break; - - case 'keydown': - case 'mousedown': - // TODO: cleanup - this.editor.selection = this.editor.getSelection(); - break; - - case 'click': - if (event.ctrlKey && this.editable.value) { - // if read-only, we use the regular click behavior of an anchor - if (util.isUrl(this.value)) { - event.preventDefault(); - window.open(this.value, '_blank'); - } - } - break; - - case 'keyup': - //this._debouncedGetDomValue(true); // TODO - this._getDomValue(true); - this._updateDomValue(); - break; - - case 'cut': - case 'paste': - setTimeout(function () { - node._getDomValue(true); - node._updateDomValue(); - }, 1); - break; - } - } - - // field events - var domField = dom.field; - if (target == domField) { - switch (type) { - case 'blur': - case 'change': - this._getDomField(true); - this._updateDomField(); - if (this.field) { - domField.innerHTML = this._escapeHTML(this.field); - } - break; - - case 'input': - this._getDomField(true); - this._updateSchema(); - this._updateDomField(); - this._updateDomValue(); - break; - - case 'keydown': - case 'mousedown': - this.editor.selection = this.editor.getSelection(); - break; - - case 'keyup': - this._getDomField(true); - this._updateDomField(); - break; - - case 'cut': - case 'paste': - setTimeout(function () { - node._getDomField(true); - node._updateDomField(); - }, 1); - break; - } - } - - // focus - // when clicked in whitespace left or right from the field or value, set focus - var domTree = dom.tree; - if (target == domTree.parentNode && type == 'click' && !event.hasMoved) { - var left = (event.offsetX != undefined) ? - (event.offsetX < (this.getLevel() + 1) * 24) : - (event.pageX < util.getAbsoluteLeft(dom.tdSeparator));// for FF - if (left || expandable) { - // node is expandable when it is an object or array - if (domField) { - util.setEndOfContentEditable(domField); - domField.focus(); - } - } - else { - if (domValue && !this.enum) { - util.setEndOfContentEditable(domValue); - domValue.focus(); - } - } - } - if (((target == dom.tdExpand && !expandable) || target == dom.tdField || target == dom.tdSeparator) && - (type == 'click' && !event.hasMoved)) { - if (domField) { - util.setEndOfContentEditable(domField); - domField.focus(); - } - } - - if (type == 'keydown') { - this.onKeyDown(event); - } - }; - - /** - * Key down event handler - * @param {Event} event - */ - Node.prototype.onKeyDown = function (event) { - var keynum = event.which || event.keyCode; - var target = event.target || event.srcElement; - var ctrlKey = event.ctrlKey; - var shiftKey = event.shiftKey; - var altKey = event.altKey; - var handled = false; - var prevNode, nextNode, nextDom, nextDom2; - var editable = this.editor.options.mode === 'tree'; - var oldSelection; - var oldBeforeNode; - var nodes; - var multiselection; - var selectedNodes = this.editor.multiselection.nodes.length > 0 - ? this.editor.multiselection.nodes - : [this]; - var firstNode = selectedNodes[0]; - var lastNode = selectedNodes[selectedNodes.length - 1]; - - // console.log(ctrlKey, keynum, event.charCode); // TODO: cleanup - if (keynum == 13) { // Enter - if (target == this.dom.value) { - if (!this.editable.value || event.ctrlKey) { - if (util.isUrl(this.value)) { - window.open(this.value, '_blank'); - handled = true; - } - } - } - else if (target == this.dom.expand) { - var expandable = this._hasChilds(); - if (expandable) { - var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all - this._onExpand(recurse); - target.focus(); - handled = true; - } - } - } - else if (keynum == 68) { // D - if (ctrlKey && editable) { // Ctrl+D - Node.onDuplicate(selectedNodes); - handled = true; - } - } - else if (keynum == 69) { // E - if (ctrlKey) { // Ctrl+E and Ctrl+Shift+E - this._onExpand(shiftKey); // recurse = shiftKey - target.focus(); // TODO: should restore focus in case of recursing expand (which takes DOM offline) - handled = true; - } - } - else if (keynum == 77 && editable) { // M - if (ctrlKey) { // Ctrl+M - this.showContextMenu(target); - handled = true; - } - } - else if (keynum == 46 && editable) { // Del - if (ctrlKey) { // Ctrl+Del - Node.onRemove(selectedNodes); - handled = true; - } - } - else if (keynum == 45 && editable) { // Ins - if (ctrlKey && !shiftKey) { // Ctrl+Ins - this._onInsertBefore(); - handled = true; - } - else if (ctrlKey && shiftKey) { // Ctrl+Shift+Ins - this._onInsertAfter(); - handled = true; - } - } - else if (keynum == 35) { // End - if (altKey) { // Alt+End - // find the last node - var endNode = this._lastNode(); - if (endNode) { - endNode.focus(Node.focusElement || this._getElementName(target)); - } - handled = true; - } - } - else if (keynum == 36) { // Home - if (altKey) { // Alt+Home - // find the first node - var homeNode = this._firstNode(); - if (homeNode) { - homeNode.focus(Node.focusElement || this._getElementName(target)); - } - handled = true; - } - } - else if (keynum == 37) { // Arrow Left - if (altKey && !shiftKey) { // Alt + Arrow Left - // move to left element - var prevElement = this._previousElement(target); - if (prevElement) { - this.focus(this._getElementName(prevElement)); - } - handled = true; - } - else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow left - if (lastNode.expanded) { - var appendDom = lastNode.getAppend(); - nextDom = appendDom ? appendDom.nextSibling : undefined; - } - else { - var dom = lastNode.getDom(); - nextDom = dom.nextSibling; - } - if (nextDom) { - nextNode = Node.getNodeFromTarget(nextDom); - nextDom2 = nextDom.nextSibling; - nextNode2 = Node.getNodeFromTarget(nextDom2); - if (nextNode && nextNode instanceof AppendNode && - !(lastNode.parent.childs.length == 1) && - nextNode2 && nextNode2.parent) { - oldSelection = this.editor.getSelection(); - oldBeforeNode = lastNode._nextSibling(); - - selectedNodes.forEach(function (node) { - nextNode2.parent.moveBefore(node, nextNode2); - }); - this.focus(Node.focusElement || this._getElementName(target)); - - this.editor._onAction('moveNodes', { - nodes: selectedNodes, - oldBeforeNode: oldBeforeNode, - newBeforeNode: nextNode2, - oldSelection: oldSelection, - newSelection: this.editor.getSelection() - }); - } - } - } - } - else if (keynum == 38) { // Arrow Up - if (altKey && !shiftKey) { // Alt + Arrow Up - // find the previous node - prevNode = this._previousNode(); - if (prevNode) { - this.editor.deselect(true); - prevNode.focus(Node.focusElement || this._getElementName(target)); - } - handled = true; - } - else if (!altKey && ctrlKey && shiftKey && editable) { // Ctrl + Shift + Arrow Up - // select multiple nodes - prevNode = this._previousNode(); - if (prevNode) { - multiselection = this.editor.multiselection; - multiselection.start = multiselection.start || this; - multiselection.end = prevNode; - nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end); - - this.editor.select(nodes); - prevNode.focus('field'); // select field as we know this always exists - } - handled = true; - } - else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Up - // find the previous node - prevNode = firstNode._previousNode(); - if (prevNode && prevNode.parent) { - oldSelection = this.editor.getSelection(); - oldBeforeNode = lastNode._nextSibling(); - - selectedNodes.forEach(function (node) { - prevNode.parent.moveBefore(node, prevNode); - }); - this.focus(Node.focusElement || this._getElementName(target)); - - this.editor._onAction('moveNodes', { - nodes: selectedNodes, - oldBeforeNode: oldBeforeNode, - newBeforeNode: prevNode, - oldSelection: oldSelection, - newSelection: this.editor.getSelection() - }); - } - handled = true; - } - } - else if (keynum == 39) { // Arrow Right - if (altKey && !shiftKey) { // Alt + Arrow Right - // move to right element - var nextElement = this._nextElement(target); - if (nextElement) { - this.focus(this._getElementName(nextElement)); - } - handled = true; - } - else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Right - dom = firstNode.getDom(); - var prevDom = dom.previousSibling; - if (prevDom) { - prevNode = Node.getNodeFromTarget(prevDom); - if (prevNode && prevNode.parent && - (prevNode instanceof AppendNode) - && !prevNode.isVisible()) { - oldSelection = this.editor.getSelection(); - oldBeforeNode = lastNode._nextSibling(); - - selectedNodes.forEach(function (node) { - prevNode.parent.moveBefore(node, prevNode); - }); - this.focus(Node.focusElement || this._getElementName(target)); - - this.editor._onAction('moveNodes', { - nodes: selectedNodes, - oldBeforeNode: oldBeforeNode, - newBeforeNode: prevNode, - oldSelection: oldSelection, - newSelection: this.editor.getSelection() - }); - } - } - } - } - else if (keynum == 40) { // Arrow Down - if (altKey && !shiftKey) { // Alt + Arrow Down - // find the next node - nextNode = this._nextNode(); - if (nextNode) { - this.editor.deselect(true); - nextNode.focus(Node.focusElement || this._getElementName(target)); - } - handled = true; - } - else if (!altKey && ctrlKey && shiftKey && editable) { // Ctrl + Shift + Arrow Down - // select multiple nodes - nextNode = this._nextNode(); - if (nextNode) { - multiselection = this.editor.multiselection; - multiselection.start = multiselection.start || this; - multiselection.end = nextNode; - nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end); - - this.editor.select(nodes); - nextNode.focus('field'); // select field as we know this always exists - } - handled = true; - } - else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Down - // find the 2nd next node and move before that one - if (lastNode.expanded) { - nextNode = lastNode.append ? lastNode.append._nextNode() : undefined; - } - else { - nextNode = lastNode._nextNode(); - } - var nextNode2 = nextNode && (nextNode._nextNode() || nextNode.parent.append); - if (nextNode2 && nextNode2.parent) { - oldSelection = this.editor.getSelection(); - oldBeforeNode = lastNode._nextSibling(); - - selectedNodes.forEach(function (node) { - nextNode2.parent.moveBefore(node, nextNode2); - }); - this.focus(Node.focusElement || this._getElementName(target)); - - this.editor._onAction('moveNodes', { - nodes: selectedNodes, - oldBeforeNode: oldBeforeNode, - newBeforeNode: nextNode2, - oldSelection: oldSelection, - newSelection: this.editor.getSelection() - }); - } - handled = true; - } - } - - if (handled) { - event.preventDefault(); - event.stopPropagation(); - } - }; - - /** - * Handle the expand event, when clicked on the expand button - * @param {boolean} recurse If true, child nodes will be expanded too - * @private - */ - Node.prototype._onExpand = function (recurse) { - if (recurse) { - // Take the table offline - var table = this.dom.tr.parentNode; // TODO: not nice to access the main table like this - var frame = table.parentNode; - var scrollTop = frame.scrollTop; - frame.removeChild(table); - } - - if (this.expanded) { - this.collapse(recurse); - } - else { - this.expand(recurse); - } - - if (recurse) { - // Put the table online again - frame.appendChild(table); - frame.scrollTop = scrollTop; - } - }; - - /** - * Remove nodes - * @param {Node[] | Node} nodes - */ - Node.onRemove = function(nodes) { - if (!Array.isArray(nodes)) { - return Node.onRemove([nodes]); - } - - if (nodes && nodes.length > 0) { - var firstNode = nodes[0]; - var parent = firstNode.parent; - var editor = firstNode.editor; - var firstIndex = firstNode.getIndex(); - editor.highlighter.unhighlight(); - - // adjust the focus - var oldSelection = editor.getSelection(); - Node.blurNodes(nodes); - var newSelection = editor.getSelection(); - - // remove the nodes - nodes.forEach(function (node) { - node.parent._remove(node); - }); - - // store history action - editor._onAction('removeNodes', { - nodes: nodes.slice(0), // store a copy of the array! - parent: parent, - index: firstIndex, - oldSelection: oldSelection, - newSelection: newSelection - }); - } - }; - - - /** - * Duplicate nodes - * duplicated nodes will be added right after the original nodes - * @param {Node[] | Node} nodes - */ - Node.onDuplicate = function(nodes) { - if (!Array.isArray(nodes)) { - return Node.onDuplicate([nodes]); - } - - if (nodes && nodes.length > 0) { - var lastNode = nodes[nodes.length - 1]; - var parent = lastNode.parent; - var editor = lastNode.editor; - - editor.deselect(editor.multiselection.nodes); - - // duplicate the nodes - var oldSelection = editor.getSelection(); - var afterNode = lastNode; - var clones = nodes.map(function (node) { - var clone = node.clone(); - parent.insertAfter(clone, afterNode); - afterNode = clone; - return clone; - }); - - // set selection to the duplicated nodes - if (nodes.length === 1) { - clones[0].focus(); - } - else { - editor.select(clones); - } - var newSelection = editor.getSelection(); - - editor._onAction('duplicateNodes', { - afterNode: lastNode, - nodes: clones, - parent: parent, - oldSelection: oldSelection, - newSelection: newSelection - }); - } - }; - - /** - * Handle insert before event - * @param {String} [field] - * @param {*} [value] - * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' - * @private - */ - Node.prototype._onInsertBefore = function (field, value, type) { - var oldSelection = this.editor.getSelection(); - - var newNode = new Node(this.editor, { - field: (field != undefined) ? field : '', - value: (value != undefined) ? value : '', - type: type - }); - newNode.expand(true); - this.parent.insertBefore(newNode, this); - this.editor.highlighter.unhighlight(); - newNode.focus('field'); - var newSelection = this.editor.getSelection(); - - this.editor._onAction('insertBeforeNodes', { - nodes: [newNode], - beforeNode: this, - parent: this.parent, - oldSelection: oldSelection, - newSelection: newSelection - }); - }; - - /** - * Handle insert after event - * @param {String} [field] - * @param {*} [value] - * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' - * @private - */ - Node.prototype._onInsertAfter = function (field, value, type) { - var oldSelection = this.editor.getSelection(); - - var newNode = new Node(this.editor, { - field: (field != undefined) ? field : '', - value: (value != undefined) ? value : '', - type: type - }); - newNode.expand(true); - this.parent.insertAfter(newNode, this); - this.editor.highlighter.unhighlight(); - newNode.focus('field'); - var newSelection = this.editor.getSelection(); - - this.editor._onAction('insertAfterNodes', { - nodes: [newNode], - afterNode: this, - parent: this.parent, - oldSelection: oldSelection, - newSelection: newSelection - }); - }; - - /** - * Handle append event - * @param {String} [field] - * @param {*} [value] - * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' - * @private - */ - Node.prototype._onAppend = function (field, value, type) { - var oldSelection = this.editor.getSelection(); - - var newNode = new Node(this.editor, { - field: (field != undefined) ? field : '', - value: (value != undefined) ? value : '', - type: type - }); - newNode.expand(true); - this.parent.appendChild(newNode); - this.editor.highlighter.unhighlight(); - newNode.focus('field'); - var newSelection = this.editor.getSelection(); - - this.editor._onAction('appendNodes', { - nodes: [newNode], - parent: this.parent, - oldSelection: oldSelection, - newSelection: newSelection - }); - }; - - /** - * Change the type of the node's value - * @param {String} newType - * @private - */ - Node.prototype._onChangeType = function (newType) { - var oldType = this.type; - if (newType != oldType) { - var oldSelection = this.editor.getSelection(); - this.changeType(newType); - var newSelection = this.editor.getSelection(); - - this.editor._onAction('changeType', { - node: this, - oldType: oldType, - newType: newType, - oldSelection: oldSelection, - newSelection: newSelection - }); - } - }; - - /** - * Sort the child's of the node. Only applicable when the node has type 'object' - * or 'array'. - * @param {String} direction Sorting direction. Available values: "asc", "desc" - * @private - */ - Node.prototype.sort = function (direction) { - if (!this._hasChilds()) { - return; - } - - var order = (direction == 'desc') ? -1 : 1; - var prop = (this.type == 'array') ? 'value': 'field'; - this.hideChilds(); - - var oldChilds = this.childs; - var oldSortOrder = this.sortOrder; - - // copy the array (the old one will be kept for an undo action - this.childs = this.childs.concat(); - - // sort the arrays - this.childs.sort(function (a, b) { - return order * naturalSort(a[prop], b[prop]); - }); - this.sortOrder = (order == 1) ? 'asc' : 'desc'; - - this.editor._onAction('sort', { - node: this, - oldChilds: oldChilds, - oldSort: oldSortOrder, - newChilds: this.childs, - newSort: this.sortOrder - }); - - this.showChilds(); - }; - - /** - * Create a table row with an append button. - * @return {HTMLElement | undefined} buttonAppend or undefined when inapplicable - */ - Node.prototype.getAppend = function () { - if (!this.append) { - this.append = new AppendNode(this.editor); - this.append.setParent(this); - } - return this.append.getDom(); - }; - - /** - * Find the node from an event target - * @param {Node} target - * @return {Node | undefined} node or undefined when not found - * @static - */ - Node.getNodeFromTarget = function (target) { - while (target) { - if (target.node) { - return target.node; - } - target = target.parentNode; - } - - return undefined; - }; - - /** - * Remove the focus of given nodes, and move the focus to the (a) node before, - * (b) the node after, or (c) the parent node. - * @param {Array. | Node} nodes - */ - Node.blurNodes = function (nodes) { - if (!Array.isArray(nodes)) { - Node.blurNodes([nodes]); - return; - } - - var firstNode = nodes[0]; - var parent = firstNode.parent; - var firstIndex = firstNode.getIndex(); - - if (parent.childs[firstIndex + nodes.length]) { - parent.childs[firstIndex + nodes.length].focus(); - } - else if (parent.childs[firstIndex - 1]) { - parent.childs[firstIndex - 1].focus(); - } - else { - parent.focus(); - } - }; - - /** - * Get the next sibling of current node - * @return {Node} nextSibling - * @private - */ - Node.prototype._nextSibling = function () { - var index = this.parent.childs.indexOf(this); - return this.parent.childs[index + 1] || this.parent.append; - }; - - /** - * Get the previously rendered node - * @return {Node | null} previousNode - * @private - */ - Node.prototype._previousNode = function () { - var prevNode = null; - var dom = this.getDom(); - if (dom && dom.parentNode) { - // find the previous field - var prevDom = dom; - do { - prevDom = prevDom.previousSibling; - prevNode = Node.getNodeFromTarget(prevDom); - } - while (prevDom && (prevNode instanceof AppendNode && !prevNode.isVisible())); - } - return prevNode; - }; - - /** - * Get the next rendered node - * @return {Node | null} nextNode - * @private - */ - Node.prototype._nextNode = function () { - var nextNode = null; - var dom = this.getDom(); - if (dom && dom.parentNode) { - // find the previous field - var nextDom = dom; - do { - nextDom = nextDom.nextSibling; - nextNode = Node.getNodeFromTarget(nextDom); - } - while (nextDom && (nextNode instanceof AppendNode && !nextNode.isVisible())); - } - - return nextNode; - }; - - /** - * Get the first rendered node - * @return {Node | null} firstNode - * @private - */ - Node.prototype._firstNode = function () { - var firstNode = null; - var dom = this.getDom(); - if (dom && dom.parentNode) { - var firstDom = dom.parentNode.firstChild; - firstNode = Node.getNodeFromTarget(firstDom); - } - - return firstNode; - }; - - /** - * Get the last rendered node - * @return {Node | null} lastNode - * @private - */ - Node.prototype._lastNode = function () { - var lastNode = null; - var dom = this.getDom(); - if (dom && dom.parentNode) { - var lastDom = dom.parentNode.lastChild; - lastNode = Node.getNodeFromTarget(lastDom); - while (lastDom && (lastNode instanceof AppendNode && !lastNode.isVisible())) { - lastDom = lastDom.previousSibling; - lastNode = Node.getNodeFromTarget(lastDom); - } - } - return lastNode; - }; - - /** - * Get the next element which can have focus. - * @param {Element} elem - * @return {Element | null} nextElem - * @private - */ - Node.prototype._previousElement = function (elem) { - var dom = this.dom; - // noinspection FallthroughInSwitchStatementJS - switch (elem) { - case dom.value: - if (this.fieldEditable) { - return dom.field; - } - // intentional fall through - case dom.field: - if (this._hasChilds()) { - return dom.expand; - } - // intentional fall through - case dom.expand: - return dom.menu; - case dom.menu: - if (dom.drag) { - return dom.drag; - } - // intentional fall through - default: - return null; - } - }; - - /** - * Get the next element which can have focus. - * @param {Element} elem - * @return {Element | null} nextElem - * @private - */ - Node.prototype._nextElement = function (elem) { - var dom = this.dom; - // noinspection FallthroughInSwitchStatementJS - switch (elem) { - case dom.drag: - return dom.menu; - case dom.menu: - if (this._hasChilds()) { - return dom.expand; - } - // intentional fall through - case dom.expand: - if (this.fieldEditable) { - return dom.field; - } - // intentional fall through - case dom.field: - if (!this._hasChilds()) { - return dom.value; - } - default: - return null; - } - }; - - /** - * Get the dom name of given element. returns null if not found. - * For example when element == dom.field, "field" is returned. - * @param {Element} element - * @return {String | null} elementName Available elements with name: 'drag', - * 'menu', 'expand', 'field', 'value' - * @private - */ - Node.prototype._getElementName = function (element) { - var dom = this.dom; - for (var name in dom) { - if (dom.hasOwnProperty(name)) { - if (dom[name] == element) { - return name; - } - } - } - return null; - }; - - /** - * Test if this node has childs. This is the case when the node is an object - * or array. - * @return {boolean} hasChilds - * @private - */ - Node.prototype._hasChilds = function () { - return this.type == 'array' || this.type == 'object'; - }; - - // titles with explanation for the different types - Node.TYPE_TITLES = { - 'auto': 'Field type "auto". ' + - 'The field type is automatically determined from the value ' + - 'and can be a string, number, boolean, or null.', - 'object': 'Field type "object". ' + - 'An object contains an unordered set of key/value pairs.', - 'array': 'Field type "array". ' + - 'An array contains an ordered collection of values.', - 'string': 'Field type "string". ' + - 'Field type is not determined from the value, ' + - 'but always returned as string.' - }; - - Node.prototype.addTemplates = function (menu, append) { - var node = this; - var templates = node.editor.options.templates; - if (templates == null) return; - if (templates.length) { - // create a separator - menu.push({ - 'type': 'separator' - }); - } - var appendData = function (name, data) { - node._onAppend(name, data); - }; - var insertData = function (name, data) { - node._onInsertBefore(name, data); - }; - templates.forEach(function (template) { - menu.push({ - text: template.text, - className: (template.className || 'jsoneditor-type-object'), - title: template.title, - click: (append ? appendData.bind(this, template.field, template.value) : insertData.bind(this, template.field, template.value)) - }); - }); - }; - - /** - * Show a contextmenu for this node - * @param {HTMLElement} anchor Anchor element to attach the context menu to - * as sibling. - * @param {function} [onClose] Callback method called when the context menu - * is being closed. - */ - Node.prototype.showContextMenu = function (anchor, onClose) { - var node = this; - var titles = Node.TYPE_TITLES; - var items = []; - - if (this.editable.value) { - items.push({ - text: 'Type', - title: 'Change the type of this field', - className: 'jsoneditor-type-' + this.type, - submenu: [ - { - text: 'Auto', - className: 'jsoneditor-type-auto' + - (this.type == 'auto' ? ' jsoneditor-selected' : ''), - title: titles.auto, - click: function () { - node._onChangeType('auto'); - } - }, - { - text: 'Array', - className: 'jsoneditor-type-array' + - (this.type == 'array' ? ' jsoneditor-selected' : ''), - title: titles.array, - click: function () { - node._onChangeType('array'); - } - }, - { - text: 'Object', - className: 'jsoneditor-type-object' + - (this.type == 'object' ? ' jsoneditor-selected' : ''), - title: titles.object, - click: function () { - node._onChangeType('object'); - } - }, - { - text: 'String', - className: 'jsoneditor-type-string' + - (this.type == 'string' ? ' jsoneditor-selected' : ''), - title: titles.string, - click: function () { - node._onChangeType('string'); - } - } - ] - }); - } - - if (this._hasChilds()) { - var direction = ((this.sortOrder == 'asc') ? 'desc': 'asc'); - items.push({ - text: 'Sort', - title: 'Sort the childs of this ' + this.type, - className: 'jsoneditor-sort-' + direction, - click: function () { - node.sort(direction); - }, - submenu: [ - { - text: 'Ascending', - className: 'jsoneditor-sort-asc', - title: 'Sort the childs of this ' + this.type + ' in ascending order', - click: function () { - node.sort('asc'); - } - }, - { - text: 'Descending', - className: 'jsoneditor-sort-desc', - title: 'Sort the childs of this ' + this.type +' in descending order', - click: function () { - node.sort('desc'); - } - } - ] - }); - } - - if (this.parent && this.parent._hasChilds()) { - if (items.length) { - // create a separator - items.push({ - 'type': 'separator' - }); - } - - // create append button (for last child node only) - var childs = node.parent.childs; - if (node == childs[childs.length - 1]) { - var appendSubmenu = [ - { - text: 'Auto', - className: 'jsoneditor-type-auto', - title: titles.auto, - click: function () { - node._onAppend('', '', 'auto'); - } - }, - { - text: 'Array', - className: 'jsoneditor-type-array', - title: titles.array, - click: function () { - node._onAppend('', []); - } - }, - { - text: 'Object', - className: 'jsoneditor-type-object', - title: titles.object, - click: function () { - node._onAppend('', {}); - } - }, - { - text: 'String', - className: 'jsoneditor-type-string', - title: titles.string, - click: function () { - node._onAppend('', '', 'string'); - } - } - ]; - node.addTemplates(appendSubmenu, true); - items.push({ - text: 'Append', - title: 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)', - submenuTitle: 'Select the type of the field to be appended', - className: 'jsoneditor-append', - click: function () { - node._onAppend('', '', 'auto'); - }, - submenu: appendSubmenu - }); - } - - - - // create insert button - var insertSubmenu = [ - { - text: 'Auto', - className: 'jsoneditor-type-auto', - title: titles.auto, - click: function () { - node._onInsertBefore('', '', 'auto'); - } - }, - { - text: 'Array', - className: 'jsoneditor-type-array', - title: titles.array, - click: function () { - node._onInsertBefore('', []); - } - }, - { - text: 'Object', - className: 'jsoneditor-type-object', - title: titles.object, - click: function () { - node._onInsertBefore('', {}); - } - }, - { - text: 'String', - className: 'jsoneditor-type-string', - title: titles.string, - click: function () { - node._onInsertBefore('', '', 'string'); - } - } - ]; - node.addTemplates(insertSubmenu, false); - items.push({ - text: 'Insert', - title: 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)', - submenuTitle: 'Select the type of the field to be inserted', - className: 'jsoneditor-insert', - click: function () { - node._onInsertBefore('', '', 'auto'); - }, - submenu: insertSubmenu - }); - - if (this.editable.field) { - // create duplicate button - items.push({ - text: 'Duplicate', - title: 'Duplicate this field (Ctrl+D)', - className: 'jsoneditor-duplicate', - click: function () { - Node.onDuplicate(node); - } - }); - - // create remove button - items.push({ - text: 'Remove', - title: 'Remove this field (Ctrl+Del)', - className: 'jsoneditor-remove', - click: function () { - Node.onRemove(node); - } - }); - } - } - - var menu = new ContextMenu(items, {close: onClose}); - menu.show(anchor, this.editor.content); - }; - - /** - * get the type of a value - * @param {*} value - * @return {String} type Can be 'object', 'array', 'string', 'auto' - * @private - */ - Node.prototype._getType = function(value) { - if (value instanceof Array) { - return 'array'; - } - if (value instanceof Object) { - return 'object'; - } - if (typeof(value) == 'string' && typeof(this._stringCast(value)) != 'string') { - return 'string'; - } - - return 'auto'; - }; - - /** - * cast contents of a string to the correct type. This can be a string, - * a number, a boolean, etc - * @param {String} str - * @return {*} castedStr - * @private - */ - Node.prototype._stringCast = function(str) { - var lower = str.toLowerCase(), - num = Number(str), // will nicely fail with '123ab' - numFloat = parseFloat(str); // will nicely fail with ' ' - - if (str == '') { - return ''; - } - else if (lower == 'null') { - return null; - } - else if (lower == 'true') { - return true; - } - else if (lower == 'false') { - return false; - } - else if (!isNaN(num) && !isNaN(numFloat)) { - return num; - } - else { - return str; - } - }; - - /** - * escape a text, such that it can be displayed safely in an HTML element - * @param {String} text - * @return {String} escapedText - * @private - */ - Node.prototype._escapeHTML = function (text) { - if (typeof text !== 'string') { - return String(text); - } - else { - var htmlEscaped = String(text) - .replace(/&/g, '&') // must be replaced first! - .replace(//g, '>') - .replace(/ /g, '  ') // replace double space with an nbsp and space - .replace(/^ /, ' ') // space at start - .replace(/ $/, ' '); // space at end - - var json = JSON.stringify(htmlEscaped); - var html = json.substring(1, json.length - 1); - if (this.editor.options.escapeUnicode === true) { - html = util.escapeUnicodeChars(html); - } - return html; - } - }; - - /** - * unescape a string. - * @param {String} escapedText - * @return {String} text - * @private - */ - Node.prototype._unescapeHTML = function (escapedText) { - var json = '"' + this._escapeJSON(escapedText) + '"'; - var htmlEscaped = util.parse(json); - - return htmlEscaped - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/ |\u00A0/g, ' ') - .replace(/&/g, '&'); // must be replaced last - }; - - /** - * escape a text to make it a valid JSON string. The method will: - * - replace unescaped double quotes with '\"' - * - replace unescaped backslash with '\\' - * - replace returns with '\n' - * @param {String} text - * @return {String} escapedText - * @private - */ - Node.prototype._escapeJSON = function (text) { - // TODO: replace with some smart regex (only when a new solution is faster!) - var escaped = ''; - var i = 0; - while (i < text.length) { - var c = text.charAt(i); - if (c == '\n') { - escaped += '\\n'; - } - else if (c == '\\') { - escaped += c; - i++; - - c = text.charAt(i); - if (c === '' || '"\\/bfnrtu'.indexOf(c) == -1) { - escaped += '\\'; // no valid escape character - } - escaped += c; - } - else if (c == '"') { - escaped += '\\"'; - } - else { - escaped += c; - } - i++; - } - - return escaped; - }; - - // TODO: find a nicer solution to resolve this circular dependency between Node and AppendNode - var AppendNode = appendNodeFactory(Node); - - module.exports = Node; - - -/***/ }, -/* 60 */ -/***/ function(module, exports) { - - /* - * Natural Sort algorithm for Javascript - Version 0.7 - Released under MIT license - * Author: Jim Palmer (based on chunking idea from Dave Koelle) - */ - /*jshint unused:false */ - module.exports = function naturalSort (a, b) { - "use strict"; - var re = /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, - sre = /(^[ ]*|[ ]*$)/g, - dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/, - hre = /^0x[0-9a-f]+$/i, - ore = /^0/, - i = function(s) { return naturalSort.insensitive && ('' + s).toLowerCase() || '' + s; }, - // convert all to strings strip whitespace - x = i(a).replace(sre, '') || '', - y = i(b).replace(sre, '') || '', - // chunk/tokenize - xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), - yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), - // numeric, hex or date detection - xD = parseInt(x.match(hre), 16) || (xN.length !== 1 && x.match(dre) && Date.parse(x)), - yD = parseInt(y.match(hre), 16) || xD && y.match(dre) && Date.parse(y) || null, - oFxNcL, oFyNcL; - // first try and sort Hex codes or Dates - if (yD) { - if ( xD < yD ) { return -1; } - else if ( xD > yD ) { return 1; } - } - // natural sorting through split numeric strings and default strings - for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) { - // find floats not starting with '0', string or 0 if not defined (Clint Priest) - oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0; - oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0; - // handle numeric vs string comparison - number < string - (Kyle Adams) - if (isNaN(oFxNcL) !== isNaN(oFyNcL)) { return (isNaN(oFxNcL)) ? 1 : -1; } - // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2' - else if (typeof oFxNcL !== typeof oFyNcL) { - oFxNcL += ''; - oFyNcL += ''; - } - if (oFxNcL < oFyNcL) { return -1; } - if (oFxNcL > oFyNcL) { return 1; } - } - return 0; - }; - - -/***/ }, -/* 61 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var util = __webpack_require__(54); - var ContextMenu = __webpack_require__(57); - - /** - * A factory function to create an AppendNode, which depends on a Node - * @param {Node} Node - */ - function appendNodeFactory(Node) { - /** - * @constructor AppendNode - * @extends Node - * @param {TreeEditor} editor - * Create a new AppendNode. This is a special node which is created at the - * end of the list with childs for an object or array - */ - function AppendNode (editor) { - /** @type {TreeEditor} */ - this.editor = editor; - this.dom = {}; - } - - AppendNode.prototype = new Node(); - - /** - * Return a table row with an append button. - * @return {Element} dom TR element - */ - AppendNode.prototype.getDom = function () { - // TODO: implement a new solution for the append node - var dom = this.dom; - - if (dom.tr) { - return dom.tr; - } - - this._updateEditability(); - - // a row for the append button - var trAppend = document.createElement('tr'); - trAppend.node = this; - dom.tr = trAppend; - - // TODO: consistent naming - - if (this.editor.options.mode === 'tree') { - // a cell for the dragarea column - dom.tdDrag = document.createElement('td'); - - // create context menu - var tdMenu = document.createElement('td'); - dom.tdMenu = tdMenu; - var menu = document.createElement('button'); - menu.type = 'button'; - menu.className = 'jsoneditor-contextmenu'; - menu.title = 'Click to open the actions menu (Ctrl+M)'; - dom.menu = menu; - tdMenu.appendChild(dom.menu); - } - - // a cell for the contents (showing text 'empty') - var tdAppend = document.createElement('td'); - var domText = document.createElement('div'); - domText.innerHTML = '(empty)'; - domText.className = 'jsoneditor-readonly'; - tdAppend.appendChild(domText); - dom.td = tdAppend; - dom.text = domText; - - this.updateDom(); - - return trAppend; - }; - - /** - * Update the HTML dom of the Node - */ - AppendNode.prototype.updateDom = function () { - var dom = this.dom; - var tdAppend = dom.td; - if (tdAppend) { - tdAppend.style.paddingLeft = (this.getLevel() * 24 + 26) + 'px'; - // TODO: not so nice hard coded offset - } - - var domText = dom.text; - if (domText) { - domText.innerHTML = '(empty ' + this.parent.type + ')'; - } - - // attach or detach the contents of the append node: - // hide when the parent has childs, show when the parent has no childs - var trAppend = dom.tr; - if (!this.isVisible()) { - if (dom.tr.firstChild) { - if (dom.tdDrag) { - trAppend.removeChild(dom.tdDrag); - } - if (dom.tdMenu) { - trAppend.removeChild(dom.tdMenu); - } - trAppend.removeChild(tdAppend); - } - } - else { - if (!dom.tr.firstChild) { - if (dom.tdDrag) { - trAppend.appendChild(dom.tdDrag); - } - if (dom.tdMenu) { - trAppend.appendChild(dom.tdMenu); - } - trAppend.appendChild(tdAppend); - } - } - }; - - /** - * Check whether the AppendNode is currently visible. - * the AppendNode is visible when its parent has no childs (i.e. is empty). - * @return {boolean} isVisible - */ - AppendNode.prototype.isVisible = function () { - return (this.parent.childs.length == 0); - }; - - /** - * Show a contextmenu for this node - * @param {HTMLElement} anchor The element to attach the menu to. - * @param {function} [onClose] Callback method called when the context menu - * is being closed. - */ - AppendNode.prototype.showContextMenu = function (anchor, onClose) { - var node = this; - var titles = Node.TYPE_TITLES; - var appendSubmenu = [ - { - text: 'Auto', - className: 'jsoneditor-type-auto', - title: titles.auto, - click: function () { - node._onAppend('', '', 'auto'); - } - }, - { - text: 'Array', - className: 'jsoneditor-type-array', - title: titles.array, - click: function () { - node._onAppend('', []); - } - }, - { - text: 'Object', - className: 'jsoneditor-type-object', - title: titles.object, - click: function () { - node._onAppend('', {}); - } - }, - { - text: 'String', - className: 'jsoneditor-type-string', - title: titles.string, - click: function () { - node._onAppend('', '', 'string'); - } - } - ]; - node.addTemplates(appendSubmenu, true); - var items = [ - // create append button - { - 'text': 'Append', - 'title': 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)', - 'submenuTitle': 'Select the type of the field to be appended', - 'className': 'jsoneditor-insert', - 'click': function () { - node._onAppend('', '', 'auto'); - }, - 'submenu': appendSubmenu - } - ]; - - var menu = new ContextMenu(items, {close: onClose}); - menu.show(anchor, this.editor.content); - }; - - /** - * Handle an event. The event is catched centrally by the editor - * @param {Event} event - */ - AppendNode.prototype.onEvent = function (event) { - var type = event.type; - var target = event.target || event.srcElement; - var dom = this.dom; - - // highlight the append nodes parent - var menu = dom.menu; - if (target == menu) { - if (type == 'mouseover') { - this.editor.highlighter.highlight(this.parent); - } - else if (type == 'mouseout') { - this.editor.highlighter.unhighlight(); - } - } - - // context menu events - if (type == 'click' && target == dom.menu) { - var highlighter = this.editor.highlighter; - highlighter.highlight(this.parent); - highlighter.lock(); - util.addClassName(dom.menu, 'jsoneditor-selected'); - this.showContextMenu(dom.menu, function () { - util.removeClassName(dom.menu, 'jsoneditor-selected'); - highlighter.unlock(); - highlighter.unhighlight(); - }); - } - - if (type == 'keydown') { - this.onKeyDown(event); - } - }; - - return AppendNode; - } - - module.exports = appendNodeFactory; - - -/***/ }, -/* 62 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var ContextMenu = __webpack_require__(57); - - /** - * Create a select box to be used in the editor menu's, which allows to switch mode - * @param {HTMLElement} container - * @param {String[]} modes Available modes: 'code', 'form', 'text', 'tree', 'view' - * @param {String} current Available modes: 'code', 'form', 'text', 'tree', 'view' - * @param {function(mode: string)} onSwitch Callback invoked on switch - * @constructor - */ - function ModeSwitcher(container, modes, current, onSwitch) { - // available modes - var availableModes = { - code: { - 'text': 'Code', - 'title': 'Switch to code highlighter', - 'click': function () { - onSwitch('code') - } - }, - form: { - 'text': 'Form', - 'title': 'Switch to form editor', - 'click': function () { - onSwitch('form'); - } - }, - text: { - 'text': 'Text', - 'title': 'Switch to plain text editor', - 'click': function () { - onSwitch('text'); - } - }, - tree: { - 'text': 'Tree', - 'title': 'Switch to tree editor', - 'click': function () { - onSwitch('tree'); - } - }, - view: { - 'text': 'View', - 'title': 'Switch to tree view', - 'click': function () { - onSwitch('view'); - } - } - }; - - // list the selected modes - var items = []; - for (var i = 0; i < modes.length; i++) { - var mode = modes[i]; - var item = availableModes[mode]; - if (!item) { - throw new Error('Unknown mode "' + mode + '"'); - } - - item.className = 'jsoneditor-type-modes' + ((current == mode) ? ' jsoneditor-selected' : ''); - items.push(item); - } - - // retrieve the title of current mode - var currentMode = availableModes[current]; - if (!currentMode) { - throw new Error('Unknown mode "' + current + '"'); - } - var currentTitle = currentMode.text; - - // create the html element - var box = document.createElement('button'); - box.type = 'button'; - box.className = 'jsoneditor-modes jsoneditor-separator'; - box.innerHTML = currentTitle + ' ▾'; - box.title = 'Switch editor mode'; - box.onclick = function () { - var menu = new ContextMenu(items); - menu.show(box); - }; - - var frame = document.createElement('div'); - frame.className = 'jsoneditor-modes'; - frame.style.position = 'relative'; - frame.appendChild(box); - - container.appendChild(frame); - - this.dom = { - container: container, - box: box, - frame: frame - }; - } - - /** - * Set focus to switcher - */ - ModeSwitcher.prototype.focus = function () { - this.dom.box.focus(); - }; - - /** - * Destroy the ModeSwitcher, remove from DOM - */ - ModeSwitcher.prototype.destroy = function () { - if (this.dom && this.dom.frame && this.dom.frame.parentNode) { - this.dom.frame.parentNode.removeChild(this.dom.frame); - } - this.dom = null; - }; - - module.exports = ModeSwitcher; - - -/***/ }, -/* 63 */ -/***/ function(module, exports) { - - 'use strict'; - - function completely(config) { - config = config || {}; - config.confirmKeys = config.confirmKeys || [39, 35, 9] // right, end, tab - - var fontSize = ''; - var fontFamily = ''; - - var wrapper = document.createElement('div'); - wrapper.style.position = 'relative'; - wrapper.style.outline = '0'; - wrapper.style.border = '0'; - wrapper.style.margin = '0'; - wrapper.style.padding = '0'; - - var dropDown = document.createElement('div'); - dropDown.className = 'autocomplete dropdown'; - dropDown.style.position = 'absolute'; - dropDown.style.visibility = 'hidden'; - - var spacer; - var leftSide; // <-- it will contain the leftSide part of the textfield (the bit that was already autocompleted) - var createDropDownController = function (elem, rs) { - var rows = []; - var ix = 0; - var oldIndex = -1; - - var onMouseOver = function () { this.style.outline = '1px solid #ddd'; } - var onMouseOut = function () { this.style.outline = '0'; } - var onMouseDown = function () { p.hide(); p.onmouseselection(this.__hint, p.rs); } - - var p = { - rs: rs, - hide: function () { - elem.style.visibility = 'hidden'; - //rs.hideDropDown(); - }, - refresh: function (token, array) { - elem.style.visibility = 'hidden'; - ix = 0; - elem.innerHTML = ''; - var vph = (window.innerHeight || document.documentElement.clientHeight); - var rect = elem.parentNode.getBoundingClientRect(); - var distanceToTop = rect.top - 6; // heuristic give 6px - var distanceToBottom = vph - rect.bottom - 6; // distance from the browser border. - - rows = []; - for (var i = 0; i < array.length; i++) { - if (array[i].indexOf(token) !== 0) { continue; } - var divRow = document.createElement('div'); - divRow.className = 'item'; - //divRow.style.color = config.color; - divRow.onmouseover = onMouseOver; - divRow.onmouseout = onMouseOut; - divRow.onmousedown = onMouseDown; - divRow.__hint = array[i]; - divRow.innerHTML = token + '' + array[i].substring(token.length) + ''; - rows.push(divRow); - elem.appendChild(divRow); - } - if (rows.length === 0) { - return; // nothing to show. - } - if (rows.length === 1 && token === rows[0].__hint) { - return; // do not show the dropDown if it has only one element which matches what we have just displayed. - } - - if (rows.length < 2) return; - p.highlight(0); - - if (distanceToTop > distanceToBottom * 3) { // Heuristic (only when the distance to the to top is 4 times more than distance to the bottom - elem.style.maxHeight = distanceToTop + 'px'; // we display the dropDown on the top of the input text - elem.style.top = ''; - elem.style.bottom = '100%'; - } else { - elem.style.top = '100%'; - elem.style.bottom = ''; - elem.style.maxHeight = distanceToBottom + 'px'; - } - elem.style.visibility = 'visible'; - }, - highlight: function (index) { - if (oldIndex != -1 && rows[oldIndex]) { - rows[oldIndex].className = "item"; - } - rows[index].className = "item hover"; - oldIndex = index; - }, - move: function (step) { // moves the selection either up or down (unless it's not possible) step is either +1 or -1. - if (elem.style.visibility === 'hidden') return ''; // nothing to move if there is no dropDown. (this happens if the user hits escape and then down or up) - if (ix + step === -1 || ix + step === rows.length) return rows[ix].__hint; // NO CIRCULAR SCROLLING. - ix += step; - p.highlight(ix); - return rows[ix].__hint;//txtShadow.value = uRows[uIndex].__hint ; - }, - onmouseselection: function () { } // it will be overwritten. - }; - return p; - } - - function setEndOfContenteditable(contentEditableElement) { - var range, selection; - if (document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+ - { - range = document.createRange();//Create a range (a range is a like the selection but invisible) - range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range - range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start - selection = window.getSelection();//get the selection object (allows you to change selection) - selection.removeAllRanges();//remove any selections already made - selection.addRange(range);//make the range you have just created the visible selection - } - else if (document.selection)//IE 8 and lower - { - range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible) - range.moveToElementText(contentEditableElement);//Select the entire contents of the element with the range - range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start - range.select();//Select the range (make it the visible selection - } - } - - function calculateWidthForText(text) { - if (spacer === undefined) { // on first call only. - spacer = document.createElement('span'); - spacer.style.visibility = 'hidden'; - spacer.style.position = 'fixed'; - spacer.style.outline = '0'; - spacer.style.margin = '0'; - spacer.style.padding = '0'; - spacer.style.border = '0'; - spacer.style.left = '0'; - spacer.style.whiteSpace = 'pre'; - spacer.style.fontSize = fontSize; - spacer.style.fontFamily = fontFamily; - spacer.style.fontWeight = 'normal'; - document.body.appendChild(spacer); - } - - // Used to encode an HTML string into a plain text. - // taken from http://stackoverflow.com/questions/1219860/javascript-jquery-html-encoding - spacer.innerHTML = String(text).replace(/&/g, '&') - .replace(/"/g, '"') - .replace(/'/g, ''') - .replace(//g, '>'); - return spacer.getBoundingClientRect().right; - } - - var rs = { - onArrowDown: function () { }, // defaults to no action. - onArrowUp: function () { }, // defaults to no action. - onEnter: function () { }, // defaults to no action. - onTab: function () { }, // defaults to no action. - startFrom: 0, - options: [], - element: null, - elementHint: null, - elementStyle: null, - wrapper: wrapper, // Only to allow easy access to the HTML elements to the final user (possibly for minor customizations) - show: function (element, startPos, options) { - this.startFrom = startPos; - this.wrapper.remove(); - if (this.elementHint) { - this.elementHint.remove(); - this.elementHint = null; - } - - if (fontSize == '') { - fontSize = window.getComputedStyle(element).getPropertyValue('font-size'); - } - if (fontFamily == '') { - fontFamily = window.getComputedStyle(element).getPropertyValue('font-family'); - } - - var w = element.getBoundingClientRect().right - element.getBoundingClientRect().left; - dropDown.style.marginLeft = '0'; - dropDown.style.marginTop = element.getBoundingClientRect().height + 'px'; - this.options = options; - - if (this.element != element) { - this.element = element; - this.elementStyle = { - zIndex: this.element.style.zIndex, - position: this.element.style.position, - backgroundColor: this.element.style.backgroundColor, - borderColor: this.element.style.borderColor - } - } - - this.element.style.zIndex = 3; - this.element.style.position = 'relative'; - this.element.style.backgroundColor = 'transparent'; - this.element.style.borderColor = 'transparent'; - - this.elementHint = element.cloneNode(); - this.elementHint.className = 'autocomplete hint'; - this.elementHint.style.zIndex = 2; - this.elementHint.style.position = 'absolute'; - this.elementHint.onfocus = function () { this.element.focus(); }.bind(this); - - - - if (this.element.addEventListener) { - this.element.removeEventListener("keydown", keyDownHandler); - this.element.addEventListener("keydown", keyDownHandler, false); - this.element.removeEventListener("blur", onBlurHandler); - this.element.addEventListener("blur", onBlurHandler, false); - } - - wrapper.appendChild(this.elementHint); - wrapper.appendChild(dropDown); - element.parentElement.appendChild(wrapper); - - - this.repaint(element); - }, - setText: function (text) { - this.element.innerText = text; - }, - getText: function () { - return this.element.innerText; - }, - hideDropDown: function () { - this.wrapper.remove(); - if (this.elementHint) { - this.elementHint.remove(); - this.elementHint = null; - dropDownController.hide(); - this.element.style.zIndex = this.elementStyle.zIndex; - this.element.style.position = this.elementStyle.position; - this.element.style.backgroundColor = this.elementStyle.backgroundColor; - this.element.style.borderColor = this.elementStyle.borderColor; - } - - }, - repaint: function (element) { - var text = element.innerText; - text = text.replace('\n', ''); - - var startFrom = this.startFrom; - var options = this.options; - var optionsLength = this.options.length; - - // breaking text in leftSide and token. - - var token = text.substring(this.startFrom); - leftSide = text.substring(0, this.startFrom); - - for (var i = 0; i < optionsLength; i++) { - var opt = this.options[i]; - if (opt.indexOf(token) === 0) { // <-- how about upperCase vs. lowercase - this.elementHint.innerText = leftSide + opt; - break; - } - } - // moving the dropDown and refreshing it. - dropDown.style.left = calculateWidthForText(leftSide) + 'px'; - dropDownController.refresh(token, this.options); - this.elementHint.style.width = calculateWidthForText(this.elementHint.innerText) + 10 + 'px' - var wasDropDownHidden = (dropDown.style.visibility == 'hidden'); - if (!wasDropDownHidden) - this.elementHint.style.width = calculateWidthForText(this.elementHint.innerText) + dropDown.clientWidth + 'px'; - } - }; - - var dropDownController = createDropDownController(dropDown, rs); - - var keyDownHandler = function (e) { - //console.log("Keydown:" + e.keyCode); - e = e || window.event; - var keyCode = e.keyCode; - - if (this.elementHint == null) return; - - if (keyCode == 33) { return; } // page up (do nothing) - if (keyCode == 34) { return; } // page down (do nothing); - - if (keyCode == 27) { //escape - rs.hideDropDown(); - rs.element.focus(); - e.preventDefault(); - e.stopPropagation(); - return; - } - - if (config.confirmKeys.indexOf(keyCode) >= 0) { // (autocomplete triggered) - if (keyCode == 9) { - if (this.elementHint.innerText.length == 0) { - rs.onTab(); - } - } - if (this.elementHint.innerText.length > 0) { // if there is a hint - if (this.element.innerText != this.elementHint.innerText) { - this.element.innerText = this.elementHint.innerText; - rs.hideDropDown(); - setEndOfContenteditable(this.element); - if (keyCode == 9) { - rs.element.focus(); - e.preventDefault(); - e.stopPropagation(); - } - } - } - return; - } - - if (keyCode == 13) { // enter (autocomplete triggered) - if (this.elementHint.innerText.length == 0) { // if there is a hint - rs.onEnter(); - } else { - var wasDropDownHidden = (dropDown.style.visibility == 'hidden'); - dropDownController.hide(); - - if (wasDropDownHidden) { - rs.hideDropDown(); - rs.element.focus(); - rs.onEnter(); - return; - } - - this.element.innerText = this.elementHint.innerText; - rs.hideDropDown(); - setEndOfContenteditable(this.element); - e.preventDefault(); - e.stopPropagation(); - } - return; - } - - if (keyCode == 40) { // down - var m = dropDownController.move(+1); - if (m == '') { rs.onArrowDown(); } - this.elementHint.innerText = leftSide + m; - e.preventDefault(); - e.stopPropagation(); - return; - } - - if (keyCode == 38) { // up - var m = dropDownController.move(-1); - if (m == '') { rs.onArrowUp(); } - this.elementHint.innerText = leftSide + m; - e.preventDefault(); - e.stopPropagation(); - return; - } - - }.bind(rs); - - var onBlurHandler = function (e) { - rs.hideDropDown(); - //console.log("Lost focus."); - }.bind(rs); - - dropDownController.onmouseselection = function (text, rs) { - rs.element.innerText = rs.elementHint.innerText = leftSide + text; - rs.hideDropDown(); - window.setTimeout(function () { - rs.element.focus(); - setEndOfContenteditable(rs.element); - }, 1); - }; - - return rs; - } - - module.exports = completely; - -/***/ }, -/* 64 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var ace = __webpack_require__(65); - var ModeSwitcher = __webpack_require__(62); - var util = __webpack_require__(54); - - // create a mixin with the functions for text mode - var textmode = {}; - - var MAX_ERRORS = 3; // maximum number of displayed errors at the bottom - - var DEFAULT_THEME = 'ace/theme/jsoneditor'; - - /** - * Create a text editor - * @param {Element} container - * @param {Object} [options] Object with options. available options: - * {String} mode Available values: - * "text" (default) - * or "code". - * {Number} indentation Number of indentation - * spaces. 2 by default. - * {function} onChange Callback method - * triggered on change - * {function} onModeChange Callback method - * triggered after setMode - * {function} onEditable Determine if textarea is readOnly - * readOnly defaults true - * {Object} ace A custom instance of - * Ace editor. - * {boolean} escapeUnicode If true, unicode - * characters are escaped. - * false by default. - * @private - */ - textmode.create = function (container, options) { - // read options - options = options || {}; - - if(typeof options.statusBar === 'undefined') { - options.statusBar = true; - } - - this.options = options; - - // indentation - if (options.indentation) { - this.indentation = Number(options.indentation); - } - else { - this.indentation = 2; // number of spaces - } - - // grab ace from options if provided - var _ace = options.ace ? options.ace : ace; - // TODO: make the option options.ace deprecated, it's not needed anymore (see #309) - - // determine mode - this.mode = (options.mode == 'code') ? 'code' : 'text'; - if (this.mode == 'code') { - // verify whether Ace editor is available and supported - if (typeof _ace === 'undefined') { - this.mode = 'text'; - console.warn('Failed to load Ace editor, falling back to plain text mode. Please use a JSONEditor bundle including Ace, or pass Ace as via the configuration option `ace`.'); - } - } - - // determine theme - this.theme = options.theme || DEFAULT_THEME; - if (this.theme === DEFAULT_THEME && _ace) { - try { - __webpack_require__(71); - } - catch (err) { - console.error(err); - } - } - - var me = this; - this.container = container; - this.dom = {}; - this.aceEditor = undefined; // ace code editor - this.textarea = undefined; // plain text editor (fallback when Ace is not available) - this.validateSchema = null; - - // create a debounced validate function - this._debouncedValidate = util.debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL); - - this.width = container.clientWidth; - this.height = container.clientHeight; - - this.frame = document.createElement('div'); - this.frame.className = 'jsoneditor jsoneditor-mode-' + this.options.mode; - this.frame.onclick = function (event) { - // prevent default submit action when the editor is located inside a form - event.preventDefault(); - }; - this.frame.onkeydown = function (event) { - me._onKeyDown(event); - }; - - // create menu - this.menu = document.createElement('div'); - this.menu.className = 'jsoneditor-menu'; - this.frame.appendChild(this.menu); - - // create format button - var buttonFormat = document.createElement('button'); - buttonFormat.type = 'button'; - buttonFormat.className = 'jsoneditor-format'; - buttonFormat.title = 'Format JSON data, with proper indentation and line feeds (Ctrl+\\)'; - this.menu.appendChild(buttonFormat); - buttonFormat.onclick = function () { - try { - me.format(); - me._onChange(); - } - catch (err) { - me._onError(err); - } - }; - - // create compact button - var buttonCompact = document.createElement('button'); - buttonCompact.type = 'button'; - buttonCompact.className = 'jsoneditor-compact'; - buttonCompact.title = 'Compact JSON data, remove all whitespaces (Ctrl+Shift+\\)'; - this.menu.appendChild(buttonCompact); - buttonCompact.onclick = function () { - try { - me.compact(); - me._onChange(); - } - catch (err) { - me._onError(err); - } - }; - - // create repair button - var buttonRepair = document.createElement('button'); - buttonRepair.type = 'button'; - buttonRepair.className = 'jsoneditor-repair'; - buttonRepair.title = 'Repair JSON: fix quotes and escape characters, remove comments and JSONP notation, turn JavaScript objects into JSON.'; - this.menu.appendChild(buttonRepair); - buttonRepair.onclick = function () { - try { - me.repair(); - me._onChange(); - } - catch (err) { - me._onError(err); - } - }; - - // create mode box - if (this.options && this.options.modes && this.options.modes.length) { - this.modeSwitcher = new ModeSwitcher(this.menu, this.options.modes, this.options.mode, function onSwitch(mode) { - // switch mode and restore focus - me.setMode(mode); - me.modeSwitcher.focus(); - }); - } - - var emptyNode = {}; - var isReadOnly = (this.options.onEditable - && typeof(this.options.onEditable === 'function') - && !this.options.onEditable(emptyNode)); - - this.content = document.createElement('div'); - this.content.className = 'jsoneditor-outer'; - this.frame.appendChild(this.content); - - this.container.appendChild(this.frame); - - if (this.mode == 'code') { - this.editorDom = document.createElement('div'); - this.editorDom.style.height = '100%'; // TODO: move to css - this.editorDom.style.width = '100%'; // TODO: move to css - this.content.appendChild(this.editorDom); - - var aceEditor = _ace.edit(this.editorDom); - aceEditor.$blockScrolling = Infinity; - aceEditor.setTheme(this.theme); - aceEditor.setOptions({ readOnly: isReadOnly }); - aceEditor.setShowPrintMargin(false); - aceEditor.setFontSize(13); - aceEditor.getSession().setMode('ace/mode/json'); - aceEditor.getSession().setTabSize(this.indentation); - aceEditor.getSession().setUseSoftTabs(true); - aceEditor.getSession().setUseWrapMode(true); - aceEditor.commands.bindKey('Ctrl-L', null); // disable Ctrl+L (is used by the browser to select the address bar) - aceEditor.commands.bindKey('Command-L', null); // disable Ctrl+L (is used by the browser to select the address bar) - this.aceEditor = aceEditor; - - // TODO: deprecated since v5.0.0. Cleanup backward compatibility some day - if (!this.hasOwnProperty('editor')) { - Object.defineProperty(this, 'editor', { - get: function () { - console.warn('Property "editor" has been renamed to "aceEditor".'); - return me.aceEditor; - }, - set: function (aceEditor) { - console.warn('Property "editor" has been renamed to "aceEditor".'); - me.aceEditor = aceEditor; - } - }); - } - - var poweredBy = document.createElement('a'); - poweredBy.appendChild(document.createTextNode('powered by ace')); - poweredBy.href = 'http://ace.ajax.org'; - poweredBy.target = '_blank'; - poweredBy.className = 'jsoneditor-poweredBy'; - poweredBy.onclick = function () { - // TODO: this anchor falls below the margin of the content, - // therefore the normal a.href does not work. We use a click event - // for now, but this should be fixed. - window.open(poweredBy.href, poweredBy.target); - }; - this.menu.appendChild(poweredBy); - - // register onchange event - aceEditor.on('change', this._onChange.bind(this)); - aceEditor.on('changeSelection', this._onSelect.bind(this)); - } - else { - // load a plain text textarea - var textarea = document.createElement('textarea'); - textarea.className = 'jsoneditor-text'; - textarea.spellcheck = false; - this.content.appendChild(textarea); - this.textarea = textarea; - this.textarea.readOnly = isReadOnly; - - // register onchange event - if (this.textarea.oninput === null) { - this.textarea.oninput = this._onChange.bind(this); - } - else { - // oninput is undefined. For IE8- - this.textarea.onchange = this._onChange.bind(this); - } - - textarea.onselect = this._onSelect.bind(this); - textarea.onmousedown = this._onMouseDown.bind(this); - textarea.onblur = this._onBlur.bind(this); - } - - if (options.statusBar) { - if (this.mode === 'code') { - util.addClassName(this.content, 'has-status-bar'); - - this.curserInfoElements = {}; - var statusBar = document.createElement('div'); - statusBar.className = 'jsoneditor-statusbar'; - this.frame.appendChild(statusBar); - - var lnLabel = document.createElement('span'); - lnLabel.className = 'jsoneditor-curserinfo-label'; - lnLabel.innerText = 'Ln:'; - - var lnVal = document.createElement('span'); - lnVal.className = 'jsoneditor-curserinfo-val'; - lnVal.innerText = 0; - - statusBar.appendChild(lnLabel); - statusBar.appendChild(lnVal); - - var colLabel = document.createElement('span'); - colLabel.className = 'jsoneditor-curserinfo-label'; - colLabel.innerText = 'Col:'; - - var colVal = document.createElement('span'); - colVal.className = 'jsoneditor-curserinfo-val'; - colVal.innerText = 0; - - statusBar.appendChild(colLabel); - statusBar.appendChild(colVal); - - this.curserInfoElements.colVal = colVal; - this.curserInfoElements.lnVal = lnVal; - - var countLabel = document.createElement('span'); - countLabel.className = 'jsoneditor-curserinfo-label'; - countLabel.innerText = 'characters selected'; - countLabel.style.display = 'none'; - - var countVal = document.createElement('span'); - countVal.className = 'jsoneditor-curserinfo-count'; - countVal.innerText = 0; - countVal.style.display = 'none'; - - this.curserInfoElements.countLabel = countLabel; - this.curserInfoElements.countVal = countVal; - - statusBar.appendChild(countVal); - statusBar.appendChild(countLabel); - } - } - - this.setSchema(this.options.schema, this.options.schemaRefs); - }; - - /** - * Handle a change: - * - Validate JSON schema - * - Send a callback to the onChange listener if provided - * @private - */ - textmode._onChange = function () { - // validate JSON schema (if configured) - this._debouncedValidate(); - - // trigger the onChange callback - if (this.options.onChange) { - try { - this.options.onChange(); - } - catch (err) { - console.error('Error in onChange callback: ', err); - } - } - }; - - /** - * Handle text selection - * Calculates the cursor position and selection range and updates menu - * @private - */ - textmode._onSelect = function () { - if(this.options.statusBar) { - if (this.textarea) { - var selectionRange = util.getInputSelection(this.textarea); - if (selectionRange.start !== selectionRange.end) { - this._setSelectionCountDisplay(Math.abs(selectionRange.end - selectionRange.start)); - } - } else if (this.aceEditor && this.curserInfoElements) { - var curserPos = this.aceEditor.getCursorPosition(); - var selectedText = this.aceEditor.getSelectedText(); - - this.curserInfoElements.lnVal.innerText = curserPos.row + 1; - this.curserInfoElements.colVal.innerText = curserPos.column + 1; - this._setSelectionCountDisplay(selectedText.length); - } - } - }; - - /** - * Event handler for keydown. Handles shortcut keys - * @param {Event} event - * @private - */ - textmode._onKeyDown = function (event) { - var keynum = event.which || event.keyCode; - var handled = false; - - if (keynum == 220 && event.ctrlKey) { - if (event.shiftKey) { // Ctrl+Shift+\ - this.compact(); - this._onChange(); - } - else { // Ctrl+\ - this.format(); - this._onChange(); - } - handled = true; - } - - if (handled) { - event.preventDefault(); - event.stopPropagation(); - } - - this._setSelectionCountDisplay(); - }; - - /** - * Event handler for mousedown. - * @param {Event} event - * @private - */ - textmode._onMouseDown = function (event) { - this._setSelectionCountDisplay(); - }; - - /** - * Event handler for blur. - * @param {Event} event - * @private - */ - textmode._onBlur = function (event) { - this._setSelectionCountDisplay(); - }; - - textmode._setSelectionCountDisplay = function (value) { - if (this.options.statusBar && this.curserInfoElements) { - if (value && this.curserInfoElements && this.curserInfoElements.countVal) { - this.curserInfoElements.countVal.innerText = value; - this.curserInfoElements.countVal.style.display = 'inline'; - this.curserInfoElements.countLabel.style.display = 'inline'; - } else { - this.curserInfoElements.countVal.style.display = 'none'; - this.curserInfoElements.countLabel.style.display = 'none'; - } - } - }; - - /** - * Destroy the editor. Clean up DOM, event listeners, and web workers. - */ - textmode.destroy = function () { - // remove old ace editor - if (this.aceEditor) { - this.aceEditor.destroy(); - this.aceEditor = null; - } - - if (this.frame && this.container && this.frame.parentNode == this.container) { - this.container.removeChild(this.frame); - } - - if (this.modeSwitcher) { - this.modeSwitcher.destroy(); - this.modeSwitcher = null; - } - - this.textarea = null; - - this._debouncedValidate = null; - }; - - /** - * Compact the code in the text editor - */ - textmode.compact = function () { - var json = this.get(); - var text = JSON.stringify(json); - this.setText(text); - }; - - /** - * Format the code in the text editor - */ - textmode.format = function () { - var json = this.get(); - var text = JSON.stringify(json, null, this.indentation); - this.setText(text); - }; - - /** - * Repair the code in the text editor - */ - textmode.repair = function () { - var text = this.getText(); - var sanitizedText = util.sanitize(text); - this.setText(sanitizedText); - }; - - /** - * Set focus to the formatter - */ - textmode.focus = function () { - if (this.textarea) { - this.textarea.focus(); - } - if (this.aceEditor) { - this.aceEditor.focus(); - } - }; - - /** - * Resize the formatter - */ - textmode.resize = function () { - if (this.aceEditor) { - var force = false; - this.aceEditor.resize(force); - } - }; - - /** - * Set json data in the formatter - * @param {Object} json - */ - textmode.set = function(json) { - this.setText(JSON.stringify(json, null, this.indentation)); - }; - - /** - * Get json data from the formatter - * @return {Object} json - */ - textmode.get = function() { - var text = this.getText(); - var json; - - try { - json = util.parse(text); // this can throw an error - } - catch (err) { - // try to sanitize json, replace JavaScript notation with JSON notation - text = util.sanitize(text); - - // try to parse again - json = util.parse(text); // this can throw an error - } - - return json; - }; - - /** - * Get the text contents of the editor - * @return {String} jsonText - */ - textmode.getText = function() { - if (this.textarea) { - return this.textarea.value; - } - if (this.aceEditor) { - return this.aceEditor.getValue(); - } - return ''; - }; - - /** - * Set the text contents of the editor - * @param {String} jsonText - */ - textmode.setText = function(jsonText) { - var text; - - if (this.options.escapeUnicode === true) { - text = util.escapeUnicodeChars(jsonText); - } - else { - text = jsonText; - } - - if (this.textarea) { - this.textarea.value = text; - } - if (this.aceEditor) { - // prevent emitting onChange events while setting new text - var originalOnChange = this.options.onChange; - this.options.onChange = null; - - this.aceEditor.setValue(text, -1); - - this.options.onChange = originalOnChange; - } - // validate JSON schema - this.validate(); - }; - - /** - * Validate current JSON object against the configured JSON schema - * Throws an exception when no JSON schema is configured - */ - textmode.validate = function () { - // clear all current errors - if (this.dom.validationErrors) { - this.dom.validationErrors.parentNode.removeChild(this.dom.validationErrors); - this.dom.validationErrors = null; - - this.content.style.marginBottom = ''; - this.content.style.paddingBottom = ''; - } - - var doValidate = false; - var errors = []; - var json; - try { - json = this.get(); // this can fail when there is no valid json - doValidate = true; - } - catch (err) { - // no valid JSON, don't validate - } - - // only validate the JSON when parsing the JSON succeeded - if (doValidate && this.validateSchema) { - var valid = this.validateSchema(json); - if (!valid) { - errors = this.validateSchema.errors.map(function (error) { - return util.improveSchemaError(error); - }); - } - } - - if (errors.length > 0) { - // limit the number of displayed errors - var limit = errors.length > MAX_ERRORS; - if (limit) { - errors = errors.slice(0, MAX_ERRORS); - var hidden = this.validateSchema.errors.length - MAX_ERRORS; - errors.push('(' + hidden + ' more errors...)') - } - - var validationErrors = document.createElement('div'); - validationErrors.innerHTML = '' + - '' + - errors.map(function (error) { - var message; - if (typeof error === 'string') { - message = ''; - } - else { - message = '' + - ''; - } - - return '' + message + '' - }).join('') + - '' + - '
' + error + '
' + error.dataPath + '' + error.message + '
'; - - this.dom.validationErrors = validationErrors; - this.frame.appendChild(validationErrors); - - var height = validationErrors.clientHeight; - this.content.style.marginBottom = (-height) + 'px'; - this.content.style.paddingBottom = height + 'px'; - } - - // update the height of the ace editor - if (this.aceEditor) { - var force = false; - this.aceEditor.resize(force); - } - }; - - // define modes - module.exports = [ - { - mode: 'text', - mixin: textmode, - data: 'text', - load: textmode.format - }, - { - mode: 'code', - mixin: textmode, - data: 'text', - load: textmode.format - } - ]; - - -/***/ }, -/* 65 */ -/***/ function(module, exports, __webpack_require__) { - - var ace - if (window.ace) { - // use the already loaded instance of Ace - ace = window.ace - } - else { - try { - // load brace - ace = __webpack_require__(66); - - // load required Ace plugins - __webpack_require__(68); - __webpack_require__(70); - } - catch (err) { - // failed to load brace (can be minimalist bundle). - // No worries, the editor will fall back to plain text if needed. - } - } - - module.exports = ace; - - -/***/ }, -/* 66 */ -/***/ function(module, exports, __webpack_require__) { - - /* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2010, Ajax.org B.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Ajax.org B.V. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ - - /** - * Define a module along with a payload - * @param module a name for the payload - * @param payload a function to call with (acequire, exports, module) params - */ - - (function() { - - var ACE_NAMESPACE = "ace"; - - var global = (function() { return this; })(); - if (!global && typeof window != "undefined") global = window; // strict mode - - - if (!ACE_NAMESPACE && typeof acequirejs !== "undefined") - return; - - - var define = function(module, deps, payload) { - if (typeof module !== "string") { - if (define.original) - define.original.apply(this, arguments); - else { - console.error("dropping module because define wasn\'t a string."); - console.trace(); - } - return; - } - if (arguments.length == 2) - payload = deps; - if (!define.modules[module]) { - define.payloads[module] = payload; - define.modules[module] = null; - } - }; - - define.modules = {}; - define.payloads = {}; - - /** - * Get at functionality define()ed using the function above - */ - var _acequire = function(parentId, module, callback) { - if (typeof module === "string") { - var payload = lookup(parentId, module); - if (payload != undefined) { - callback && callback(); - return payload; - } - } else if (Object.prototype.toString.call(module) === "[object Array]") { - var params = []; - for (var i = 0, l = module.length; i < l; ++i) { - var dep = lookup(parentId, module[i]); - if (dep == undefined && acequire.original) - return; - params.push(dep); - } - return callback && callback.apply(null, params) || true; - } - }; - - var acequire = function(module, callback) { - var packagedModule = _acequire("", module, callback); - if (packagedModule == undefined && acequire.original) - return acequire.original.apply(this, arguments); - return packagedModule; - }; - - var normalizeModule = function(parentId, moduleName) { - // normalize plugin acequires - if (moduleName.indexOf("!") !== -1) { - var chunks = moduleName.split("!"); - return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]); - } - // normalize relative acequires - if (moduleName.charAt(0) == ".") { - var base = parentId.split("/").slice(0, -1).join("/"); - moduleName = base + "/" + moduleName; - - while(moduleName.indexOf(".") !== -1 && previous != moduleName) { - var previous = moduleName; - moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); - } - } - return moduleName; - }; - - /** - * Internal function to lookup moduleNames and resolve them by calling the - * definition function if needed. - */ - var lookup = function(parentId, moduleName) { - moduleName = normalizeModule(parentId, moduleName); - - var module = define.modules[moduleName]; - if (!module) { - module = define.payloads[moduleName]; - if (typeof module === 'function') { - var exports = {}; - var mod = { - id: moduleName, - uri: '', - exports: exports, - packaged: true - }; - - var req = function(module, callback) { - return _acequire(moduleName, module, callback); - }; - - var returnValue = module(req, exports, mod); - exports = returnValue || mod.exports; - define.modules[moduleName] = exports; - delete define.payloads[moduleName]; - } - module = define.modules[moduleName] = exports || module; - } - return module; - }; - - function exportAce(ns) { - var root = global; - if (ns) { - if (!global[ns]) - global[ns] = {}; - root = global[ns]; - } - - if (!root.define || !root.define.packaged) { - define.original = root.define; - root.define = define; - root.define.packaged = true; - } - - if (!root.acequire || !root.acequire.packaged) { - acequire.original = root.acequire; - root.acequire = acequire; - root.acequire.packaged = true; - } - } - - exportAce(ACE_NAMESPACE); - - })(); - - ace.define("ace/lib/regexp",["require","exports","module"], function(acequire, exports, module) { - "use strict"; - - var real = { - exec: RegExp.prototype.exec, - test: RegExp.prototype.test, - match: String.prototype.match, - replace: String.prototype.replace, - split: String.prototype.split - }, - compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups - compliantLastIndexIncrement = function () { - var x = /^/g; - real.test.call(x, ""); - return !x.lastIndex; - }(); - - if (compliantLastIndexIncrement && compliantExecNpcg) - return; - RegExp.prototype.exec = function (str) { - var match = real.exec.apply(this, arguments), - name, r2; - if ( typeof(str) == 'string' && match) { - if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) { - r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), "g", "")); - real.replace.call(str.slice(match.index), r2, function () { - for (var i = 1; i < arguments.length - 2; i++) { - if (arguments[i] === undefined) - match[i] = undefined; - } - }); - } - if (this._xregexp && this._xregexp.captureNames) { - for (var i = 1; i < match.length; i++) { - name = this._xregexp.captureNames[i - 1]; - if (name) - match[name] = match[i]; - } - } - if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index)) - this.lastIndex--; - } - return match; - }; - if (!compliantLastIndexIncrement) { - RegExp.prototype.test = function (str) { - var match = real.exec.call(this, str); - if (match && this.global && !match[0].length && (this.lastIndex > match.index)) - this.lastIndex--; - return !!match; - }; - } - - function getNativeFlags (regex) { - return (regex.global ? "g" : "") + - (regex.ignoreCase ? "i" : "") + - (regex.multiline ? "m" : "") + - (regex.extended ? "x" : "") + // Proposed for ES4; included in AS3 - (regex.sticky ? "y" : ""); - } - - function indexOf (array, item, from) { - if (Array.prototype.indexOf) // Use the native array method if available - return array.indexOf(item, from); - for (var i = from || 0; i < array.length; i++) { - if (array[i] === item) - return i; - } - return -1; - } - - }); - - ace.define("ace/lib/es5-shim",["require","exports","module"], function(acequire, exports, module) { - - function Empty() {} - - if (!Function.prototype.bind) { - Function.prototype.bind = function bind(that) { // .length is 1 - var target = this; - if (typeof target != "function") { - throw new TypeError("Function.prototype.bind called on incompatible " + target); - } - var args = slice.call(arguments, 1); // for normal call - var bound = function () { - - if (this instanceof bound) { - - var result = target.apply( - this, - args.concat(slice.call(arguments)) - ); - if (Object(result) === result) { - return result; - } - return this; - - } else { - return target.apply( - that, - args.concat(slice.call(arguments)) - ); - - } - - }; - if(target.prototype) { - Empty.prototype = target.prototype; - bound.prototype = new Empty(); - Empty.prototype = null; - } - return bound; - }; - } - var call = Function.prototype.call; - var prototypeOfArray = Array.prototype; - var prototypeOfObject = Object.prototype; - var slice = prototypeOfArray.slice; - var _toString = call.bind(prototypeOfObject.toString); - var owns = call.bind(prototypeOfObject.hasOwnProperty); - var defineGetter; - var defineSetter; - var lookupGetter; - var lookupSetter; - var supportsAccessors; - if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) { - defineGetter = call.bind(prototypeOfObject.__defineGetter__); - defineSetter = call.bind(prototypeOfObject.__defineSetter__); - lookupGetter = call.bind(prototypeOfObject.__lookupGetter__); - lookupSetter = call.bind(prototypeOfObject.__lookupSetter__); - } - if ([1,2].splice(0).length != 2) { - if(function() { // test IE < 9 to splice bug - see issue #138 - function makeArray(l) { - var a = new Array(l+2); - a[0] = a[1] = 0; - return a; - } - var array = [], lengthBefore; - - array.splice.apply(array, makeArray(20)); - array.splice.apply(array, makeArray(26)); - - lengthBefore = array.length; //46 - array.splice(5, 0, "XXX"); // add one element - - lengthBefore + 1 == array.length - - if (lengthBefore + 1 == array.length) { - return true;// has right splice implementation without bugs - } - }()) {//IE 6/7 - var array_splice = Array.prototype.splice; - Array.prototype.splice = function(start, deleteCount) { - if (!arguments.length) { - return []; - } else { - return array_splice.apply(this, [ - start === void 0 ? 0 : start, - deleteCount === void 0 ? (this.length - start) : deleteCount - ].concat(slice.call(arguments, 2))) - } - }; - } else {//IE8 - Array.prototype.splice = function(pos, removeCount){ - var length = this.length; - if (pos > 0) { - if (pos > length) - pos = length; - } else if (pos == void 0) { - pos = 0; - } else if (pos < 0) { - pos = Math.max(length + pos, 0); - } - - if (!(pos+removeCount < length)) - removeCount = length - pos; - - var removed = this.slice(pos, pos+removeCount); - var insert = slice.call(arguments, 2); - var add = insert.length; - if (pos === length) { - if (add) { - this.push.apply(this, insert); - } - } else { - var remove = Math.min(removeCount, length - pos); - var tailOldPos = pos + remove; - var tailNewPos = tailOldPos + add - remove; - var tailCount = length - tailOldPos; - var lengthAfterRemove = length - remove; - - if (tailNewPos < tailOldPos) { // case A - for (var i = 0; i < tailCount; ++i) { - this[tailNewPos+i] = this[tailOldPos+i]; - } - } else if (tailNewPos > tailOldPos) { // case B - for (i = tailCount; i--; ) { - this[tailNewPos+i] = this[tailOldPos+i]; - } - } // else, add == remove (nothing to do) - - if (add && pos === lengthAfterRemove) { - this.length = lengthAfterRemove; // truncate array - this.push.apply(this, insert); - } else { - this.length = lengthAfterRemove + add; // reserves space - for (i = 0; i < add; ++i) { - this[pos+i] = insert[i]; - } - } - } - return removed; - }; - } - } - if (!Array.isArray) { - Array.isArray = function isArray(obj) { - return _toString(obj) == "[object Array]"; - }; - } - var boxedString = Object("a"), - splitString = boxedString[0] != "a" || !(0 in boxedString); - - if (!Array.prototype.forEach) { - Array.prototype.forEach = function forEach(fun /*, thisp*/) { - var object = toObject(this), - self = splitString && _toString(this) == "[object String]" ? - this.split("") : - object, - thisp = arguments[1], - i = -1, - length = self.length >>> 0; - if (_toString(fun) != "[object Function]") { - throw new TypeError(); // TODO message - } - - while (++i < length) { - if (i in self) { - fun.call(thisp, self[i], i, object); - } - } - }; - } - if (!Array.prototype.map) { - Array.prototype.map = function map(fun /*, thisp*/) { - var object = toObject(this), - self = splitString && _toString(this) == "[object String]" ? - this.split("") : - object, - length = self.length >>> 0, - result = Array(length), - thisp = arguments[1]; - if (_toString(fun) != "[object Function]") { - throw new TypeError(fun + " is not a function"); - } - - for (var i = 0; i < length; i++) { - if (i in self) - result[i] = fun.call(thisp, self[i], i, object); - } - return result; - }; - } - if (!Array.prototype.filter) { - Array.prototype.filter = function filter(fun /*, thisp */) { - var object = toObject(this), - self = splitString && _toString(this) == "[object String]" ? - this.split("") : - object, - length = self.length >>> 0, - result = [], - value, - thisp = arguments[1]; - if (_toString(fun) != "[object Function]") { - throw new TypeError(fun + " is not a function"); - } - - for (var i = 0; i < length; i++) { - if (i in self) { - value = self[i]; - if (fun.call(thisp, value, i, object)) { - result.push(value); - } - } - } - return result; - }; - } - if (!Array.prototype.every) { - Array.prototype.every = function every(fun /*, thisp */) { - var object = toObject(this), - self = splitString && _toString(this) == "[object String]" ? - this.split("") : - object, - length = self.length >>> 0, - thisp = arguments[1]; - if (_toString(fun) != "[object Function]") { - throw new TypeError(fun + " is not a function"); - } - - for (var i = 0; i < length; i++) { - if (i in self && !fun.call(thisp, self[i], i, object)) { - return false; - } - } - return true; - }; - } - if (!Array.prototype.some) { - Array.prototype.some = function some(fun /*, thisp */) { - var object = toObject(this), - self = splitString && _toString(this) == "[object String]" ? - this.split("") : - object, - length = self.length >>> 0, - thisp = arguments[1]; - if (_toString(fun) != "[object Function]") { - throw new TypeError(fun + " is not a function"); - } - - for (var i = 0; i < length; i++) { - if (i in self && fun.call(thisp, self[i], i, object)) { - return true; - } - } - return false; - }; - } - if (!Array.prototype.reduce) { - Array.prototype.reduce = function reduce(fun /*, initial*/) { - var object = toObject(this), - self = splitString && _toString(this) == "[object String]" ? - this.split("") : - object, - length = self.length >>> 0; - if (_toString(fun) != "[object Function]") { - throw new TypeError(fun + " is not a function"); - } - if (!length && arguments.length == 1) { - throw new TypeError("reduce of empty array with no initial value"); - } - - var i = 0; - var result; - if (arguments.length >= 2) { - result = arguments[1]; - } else { - do { - if (i in self) { - result = self[i++]; - break; - } - if (++i >= length) { - throw new TypeError("reduce of empty array with no initial value"); - } - } while (true); - } - - for (; i < length; i++) { - if (i in self) { - result = fun.call(void 0, result, self[i], i, object); - } - } - - return result; - }; - } - if (!Array.prototype.reduceRight) { - Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) { - var object = toObject(this), - self = splitString && _toString(this) == "[object String]" ? - this.split("") : - object, - length = self.length >>> 0; - if (_toString(fun) != "[object Function]") { - throw new TypeError(fun + " is not a function"); - } - if (!length && arguments.length == 1) { - throw new TypeError("reduceRight of empty array with no initial value"); - } - - var result, i = length - 1; - if (arguments.length >= 2) { - result = arguments[1]; - } else { - do { - if (i in self) { - result = self[i--]; - break; - } - if (--i < 0) { - throw new TypeError("reduceRight of empty array with no initial value"); - } - } while (true); - } - - do { - if (i in this) { - result = fun.call(void 0, result, self[i], i, object); - } - } while (i--); - - return result; - }; - } - if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) { - Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) { - var self = splitString && _toString(this) == "[object String]" ? - this.split("") : - toObject(this), - length = self.length >>> 0; - - if (!length) { - return -1; - } - - var i = 0; - if (arguments.length > 1) { - i = toInteger(arguments[1]); - } - i = i >= 0 ? i : Math.max(0, length + i); - for (; i < length; i++) { - if (i in self && self[i] === sought) { - return i; - } - } - return -1; - }; - } - if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) { - Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) { - var self = splitString && _toString(this) == "[object String]" ? - this.split("") : - toObject(this), - length = self.length >>> 0; - - if (!length) { - return -1; - } - var i = length - 1; - if (arguments.length > 1) { - i = Math.min(i, toInteger(arguments[1])); - } - i = i >= 0 ? i : length - Math.abs(i); - for (; i >= 0; i--) { - if (i in self && sought === self[i]) { - return i; - } - } - return -1; - }; - } - if (!Object.getPrototypeOf) { - Object.getPrototypeOf = function getPrototypeOf(object) { - return object.__proto__ || ( - object.constructor ? - object.constructor.prototype : - prototypeOfObject - ); - }; - } - if (!Object.getOwnPropertyDescriptor) { - var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " + - "non-object: "; - Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { - if ((typeof object != "object" && typeof object != "function") || object === null) - throw new TypeError(ERR_NON_OBJECT + object); - if (!owns(object, property)) - return; - - var descriptor, getter, setter; - descriptor = { enumerable: true, configurable: true }; - if (supportsAccessors) { - var prototype = object.__proto__; - object.__proto__ = prototypeOfObject; - - var getter = lookupGetter(object, property); - var setter = lookupSetter(object, property); - object.__proto__ = prototype; - - if (getter || setter) { - if (getter) descriptor.get = getter; - if (setter) descriptor.set = setter; - return descriptor; - } - } - descriptor.value = object[property]; - return descriptor; - }; - } - if (!Object.getOwnPropertyNames) { - Object.getOwnPropertyNames = function getOwnPropertyNames(object) { - return Object.keys(object); - }; - } - if (!Object.create) { - var createEmpty; - if (Object.prototype.__proto__ === null) { - createEmpty = function () { - return { "__proto__": null }; - }; - } else { - createEmpty = function () { - var empty = {}; - for (var i in empty) - empty[i] = null; - empty.constructor = - empty.hasOwnProperty = - empty.propertyIsEnumerable = - empty.isPrototypeOf = - empty.toLocaleString = - empty.toString = - empty.valueOf = - empty.__proto__ = null; - return empty; - } - } - - Object.create = function create(prototype, properties) { - var object; - if (prototype === null) { - object = createEmpty(); - } else { - if (typeof prototype != "object") - throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'"); - var Type = function () {}; - Type.prototype = prototype; - object = new Type(); - object.__proto__ = prototype; - } - if (properties !== void 0) - Object.defineProperties(object, properties); - return object; - }; - } - - function doesDefinePropertyWork(object) { - try { - Object.defineProperty(object, "sentinel", {}); - return "sentinel" in object; - } catch (exception) { - } - } - if (Object.defineProperty) { - var definePropertyWorksOnObject = doesDefinePropertyWork({}); - var definePropertyWorksOnDom = typeof document == "undefined" || - doesDefinePropertyWork(document.createElement("div")); - if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) { - var definePropertyFallback = Object.defineProperty; - } - } - - if (!Object.defineProperty || definePropertyFallback) { - var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: "; - var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: " - var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " + - "on this javascript engine"; - - Object.defineProperty = function defineProperty(object, property, descriptor) { - if ((typeof object != "object" && typeof object != "function") || object === null) - throw new TypeError(ERR_NON_OBJECT_TARGET + object); - if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) - throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor); - if (definePropertyFallback) { - try { - return definePropertyFallback.call(Object, object, property, descriptor); - } catch (exception) { - } - } - if (owns(descriptor, "value")) { - - if (supportsAccessors && (lookupGetter(object, property) || - lookupSetter(object, property))) - { - var prototype = object.__proto__; - object.__proto__ = prototypeOfObject; - delete object[property]; - object[property] = descriptor.value; - object.__proto__ = prototype; - } else { - object[property] = descriptor.value; - } - } else { - if (!supportsAccessors) - throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); - if (owns(descriptor, "get")) - defineGetter(object, property, descriptor.get); - if (owns(descriptor, "set")) - defineSetter(object, property, descriptor.set); - } - - return object; - }; - } - if (!Object.defineProperties) { - Object.defineProperties = function defineProperties(object, properties) { - for (var property in properties) { - if (owns(properties, property)) - Object.defineProperty(object, property, properties[property]); - } - return object; - }; - } - if (!Object.seal) { - Object.seal = function seal(object) { - return object; - }; - } - if (!Object.freeze) { - Object.freeze = function freeze(object) { - return object; - }; - } - try { - Object.freeze(function () {}); - } catch (exception) { - Object.freeze = (function freeze(freezeObject) { - return function freeze(object) { - if (typeof object == "function") { - return object; - } else { - return freezeObject(object); - } - }; - })(Object.freeze); - } - if (!Object.preventExtensions) { - Object.preventExtensions = function preventExtensions(object) { - return object; - }; - } - if (!Object.isSealed) { - Object.isSealed = function isSealed(object) { - return false; - }; - } - if (!Object.isFrozen) { - Object.isFrozen = function isFrozen(object) { - return false; - }; - } - if (!Object.isExtensible) { - Object.isExtensible = function isExtensible(object) { - if (Object(object) === object) { - throw new TypeError(); // TODO message - } - var name = ''; - while (owns(object, name)) { - name += '?'; - } - object[name] = true; - var returnValue = owns(object, name); - delete object[name]; - return returnValue; - }; - } - if (!Object.keys) { - var hasDontEnumBug = true, - dontEnums = [ - "toString", - "toLocaleString", - "valueOf", - "hasOwnProperty", - "isPrototypeOf", - "propertyIsEnumerable", - "constructor" - ], - dontEnumsLength = dontEnums.length; - - for (var key in {"toString": null}) { - hasDontEnumBug = false; - } - - Object.keys = function keys(object) { - - if ( - (typeof object != "object" && typeof object != "function") || - object === null - ) { - throw new TypeError("Object.keys called on a non-object"); - } - - var keys = []; - for (var name in object) { - if (owns(object, name)) { - keys.push(name); - } - } - - if (hasDontEnumBug) { - for (var i = 0, ii = dontEnumsLength; i < ii; i++) { - var dontEnum = dontEnums[i]; - if (owns(object, dontEnum)) { - keys.push(dontEnum); - } - } - } - return keys; - }; - - } - if (!Date.now) { - Date.now = function now() { - return new Date().getTime(); - }; - } - var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" + - "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" + - "\u2029\uFEFF"; - if (!String.prototype.trim || ws.trim()) { - ws = "[" + ws + "]"; - var trimBeginRegexp = new RegExp("^" + ws + ws + "*"), - trimEndRegexp = new RegExp(ws + ws + "*$"); - String.prototype.trim = function trim() { - return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, ""); - }; - } - - function toInteger(n) { - n = +n; - if (n !== n) { // isNaN - n = 0; - } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) { - n = (n > 0 || -1) * Math.floor(Math.abs(n)); - } - return n; - } - - function isPrimitive(input) { - var type = typeof input; - return ( - input === null || - type === "undefined" || - type === "boolean" || - type === "number" || - type === "string" - ); - } - - function toPrimitive(input) { - var val, valueOf, toString; - if (isPrimitive(input)) { - return input; - } - valueOf = input.valueOf; - if (typeof valueOf === "function") { - val = valueOf.call(input); - if (isPrimitive(val)) { - return val; - } - } - toString = input.toString; - if (typeof toString === "function") { - val = toString.call(input); - if (isPrimitive(val)) { - return val; - } - } - throw new TypeError(); - } - var toObject = function (o) { - if (o == null) { // this matches both null and undefined - throw new TypeError("can't convert "+o+" to object"); - } - return Object(o); - }; - - }); - - ace.define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"], function(acequire, exports, module) { - "use strict"; - - acequire("./regexp"); - acequire("./es5-shim"); - - }); - - ace.define("ace/lib/dom",["require","exports","module"], function(acequire, exports, module) { - "use strict"; - - var XHTML_NS = "http://www.w3.org/1999/xhtml"; - - exports.getDocumentHead = function(doc) { - if (!doc) - doc = document; - return doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement; - }; - - exports.createElement = function(tag, ns) { - return document.createElementNS ? - document.createElementNS(ns || XHTML_NS, tag) : - document.createElement(tag); - }; - - exports.hasCssClass = function(el, name) { - var classes = (el.className + "").split(/\s+/g); - return classes.indexOf(name) !== -1; - }; - exports.addCssClass = function(el, name) { - if (!exports.hasCssClass(el, name)) { - el.className += " " + name; - } - }; - exports.removeCssClass = function(el, name) { - var classes = el.className.split(/\s+/g); - while (true) { - var index = classes.indexOf(name); - if (index == -1) { - break; - } - classes.splice(index, 1); - } - el.className = classes.join(" "); - }; - - exports.toggleCssClass = function(el, name) { - var classes = el.className.split(/\s+/g), add = true; - while (true) { - var index = classes.indexOf(name); - if (index == -1) { - break; - } - add = false; - classes.splice(index, 1); - } - if (add) - classes.push(name); - - el.className = classes.join(" "); - return add; - }; - exports.setCssClass = function(node, className, include) { - if (include) { - exports.addCssClass(node, className); - } else { - exports.removeCssClass(node, className); - } - }; - - exports.hasCssString = function(id, doc) { - var index = 0, sheets; - doc = doc || document; - - if (doc.createStyleSheet && (sheets = doc.styleSheets)) { - while (index < sheets.length) - if (sheets[index++].owningElement.id === id) return true; - } else if ((sheets = doc.getElementsByTagName("style"))) { - while (index < sheets.length) - if (sheets[index++].id === id) return true; - } - - return false; - }; - - exports.importCssString = function importCssString(cssText, id, doc) { - doc = doc || document; - if (id && exports.hasCssString(id, doc)) - return null; - - var style; - - if (id) - cssText += "\n/*# sourceURL=ace/css/" + id + " */"; - - if (doc.createStyleSheet) { - style = doc.createStyleSheet(); - style.cssText = cssText; - if (id) - style.owningElement.id = id; - } else { - style = exports.createElement("style"); - style.appendChild(doc.createTextNode(cssText)); - if (id) - style.id = id; - - exports.getDocumentHead(doc).appendChild(style); - } - }; - - exports.importCssStylsheet = function(uri, doc) { - if (doc.createStyleSheet) { - doc.createStyleSheet(uri); - } else { - var link = exports.createElement('link'); - link.rel = 'stylesheet'; - link.href = uri; - - exports.getDocumentHead(doc).appendChild(link); - } - }; - - exports.getInnerWidth = function(element) { - return ( - parseInt(exports.computedStyle(element, "paddingLeft"), 10) + - parseInt(exports.computedStyle(element, "paddingRight"), 10) + - element.clientWidth - ); - }; - - exports.getInnerHeight = function(element) { - return ( - parseInt(exports.computedStyle(element, "paddingTop"), 10) + - parseInt(exports.computedStyle(element, "paddingBottom"), 10) + - element.clientHeight - ); - }; - - exports.scrollbarWidth = function(document) { - var inner = exports.createElement("ace_inner"); - inner.style.width = "100%"; - inner.style.minWidth = "0px"; - inner.style.height = "200px"; - inner.style.display = "block"; - - var outer = exports.createElement("ace_outer"); - var style = outer.style; - - style.position = "absolute"; - style.left = "-10000px"; - style.overflow = "hidden"; - style.width = "200px"; - style.minWidth = "0px"; - style.height = "150px"; - style.display = "block"; - - outer.appendChild(inner); - - var body = document.documentElement; - body.appendChild(outer); - - var noScrollbar = inner.offsetWidth; - - style.overflow = "scroll"; - var withScrollbar = inner.offsetWidth; - - if (noScrollbar == withScrollbar) { - withScrollbar = outer.clientWidth; - } - - body.removeChild(outer); - - return noScrollbar-withScrollbar; - }; - - if (typeof document == "undefined") { - exports.importCssString = function() {}; - return; - } - - if (window.pageYOffset !== undefined) { - exports.getPageScrollTop = function() { - return window.pageYOffset; - }; - - exports.getPageScrollLeft = function() { - return window.pageXOffset; - }; - } - else { - exports.getPageScrollTop = function() { - return document.body.scrollTop; - }; - - exports.getPageScrollLeft = function() { - return document.body.scrollLeft; - }; - } - - if (window.getComputedStyle) - exports.computedStyle = function(element, style) { - if (style) - return (window.getComputedStyle(element, "") || {})[style] || ""; - return window.getComputedStyle(element, "") || {}; - }; - else - exports.computedStyle = function(element, style) { - if (style) - return element.currentStyle[style]; - return element.currentStyle; - }; - exports.setInnerHtml = function(el, innerHtml) { - var element = el.cloneNode(false);//document.createElement("div"); - element.innerHTML = innerHtml; - el.parentNode.replaceChild(element, el); - return element; - }; - - if ("textContent" in document.documentElement) { - exports.setInnerText = function(el, innerText) { - el.textContent = innerText; - }; - - exports.getInnerText = function(el) { - return el.textContent; - }; - } - else { - exports.setInnerText = function(el, innerText) { - el.innerText = innerText; - }; - - exports.getInnerText = function(el) { - return el.innerText; - }; - } - - exports.getParentWindow = function(document) { - return document.defaultView || document.parentWindow; - }; - - }); - - ace.define("ace/lib/oop",["require","exports","module"], function(acequire, exports, module) { - "use strict"; - - exports.inherits = function(ctor, superCtor) { - ctor.super_ = superCtor; - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; - - exports.mixin = function(obj, mixin) { - for (var key in mixin) { - obj[key] = mixin[key]; - } - return obj; - }; - - exports.implement = function(proto, mixin) { - exports.mixin(proto, mixin); - }; - - }); - - ace.define("ace/lib/keys",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop"], function(acequire, exports, module) { - "use strict"; - - acequire("./fixoldbrowsers"); - - var oop = acequire("./oop"); - var Keys = (function() { - var ret = { - MODIFIER_KEYS: { - 16: 'Shift', 17: 'Ctrl', 18: 'Alt', 224: 'Meta' - }, - - KEY_MODS: { - "ctrl": 1, "alt": 2, "option" : 2, "shift": 4, - "super": 8, "meta": 8, "command": 8, "cmd": 8 - }, - - FUNCTION_KEYS : { - 8 : "Backspace", - 9 : "Tab", - 13 : "Return", - 19 : "Pause", - 27 : "Esc", - 32 : "Space", - 33 : "PageUp", - 34 : "PageDown", - 35 : "End", - 36 : "Home", - 37 : "Left", - 38 : "Up", - 39 : "Right", - 40 : "Down", - 44 : "Print", - 45 : "Insert", - 46 : "Delete", - 96 : "Numpad0", - 97 : "Numpad1", - 98 : "Numpad2", - 99 : "Numpad3", - 100: "Numpad4", - 101: "Numpad5", - 102: "Numpad6", - 103: "Numpad7", - 104: "Numpad8", - 105: "Numpad9", - '-13': "NumpadEnter", - 112: "F1", - 113: "F2", - 114: "F3", - 115: "F4", - 116: "F5", - 117: "F6", - 118: "F7", - 119: "F8", - 120: "F9", - 121: "F10", - 122: "F11", - 123: "F12", - 144: "Numlock", - 145: "Scrolllock" - }, - - PRINTABLE_KEYS: { - 32: ' ', 48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5', - 54: '6', 55: '7', 56: '8', 57: '9', 59: ';', 61: '=', 65: 'a', - 66: 'b', 67: 'c', 68: 'd', 69: 'e', 70: 'f', 71: 'g', 72: 'h', - 73: 'i', 74: 'j', 75: 'k', 76: 'l', 77: 'm', 78: 'n', 79: 'o', - 80: 'p', 81: 'q', 82: 'r', 83: 's', 84: 't', 85: 'u', 86: 'v', - 87: 'w', 88: 'x', 89: 'y', 90: 'z', 107: '+', 109: '-', 110: '.', - 186: ';', 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`', - 219: '[', 220: '\\',221: ']', 222: "'", 111: '/', 106: '*' - } - }; - var name, i; - for (i in ret.FUNCTION_KEYS) { - name = ret.FUNCTION_KEYS[i].toLowerCase(); - ret[name] = parseInt(i, 10); - } - for (i in ret.PRINTABLE_KEYS) { - name = ret.PRINTABLE_KEYS[i].toLowerCase(); - ret[name] = parseInt(i, 10); - } - oop.mixin(ret, ret.MODIFIER_KEYS); - oop.mixin(ret, ret.PRINTABLE_KEYS); - oop.mixin(ret, ret.FUNCTION_KEYS); - ret.enter = ret["return"]; - ret.escape = ret.esc; - ret.del = ret["delete"]; - ret[173] = '-'; - - (function() { - var mods = ["cmd", "ctrl", "alt", "shift"]; - for (var i = Math.pow(2, mods.length); i--;) { - ret.KEY_MODS[i] = mods.filter(function(x) { - return i & ret.KEY_MODS[x]; - }).join("-") + "-"; - } - })(); - - ret.KEY_MODS[0] = ""; - ret.KEY_MODS[-1] = "input-"; - - return ret; - })(); - oop.mixin(exports, Keys); - - exports.keyCodeToString = function(keyCode) { - var keyString = Keys[keyCode]; - if (typeof keyString != "string") - keyString = String.fromCharCode(keyCode); - return keyString.toLowerCase(); - }; - - }); - - ace.define("ace/lib/useragent",["require","exports","module"], function(acequire, exports, module) { - "use strict"; - exports.OS = { - LINUX: "LINUX", - MAC: "MAC", - WINDOWS: "WINDOWS" - }; - exports.getOS = function() { - if (exports.isMac) { - return exports.OS.MAC; - } else if (exports.isLinux) { - return exports.OS.LINUX; - } else { - return exports.OS.WINDOWS; - } - }; - if (typeof navigator != "object") - return; - - var os = (navigator.platform.match(/mac|win|linux/i) || ["other"])[0].toLowerCase(); - var ua = navigator.userAgent; - exports.isWin = (os == "win"); - exports.isMac = (os == "mac"); - exports.isLinux = (os == "linux"); - exports.isIE = - (navigator.appName == "Microsoft Internet Explorer" || navigator.appName.indexOf("MSAppHost") >= 0) - ? parseFloat((ua.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]) - : parseFloat((ua.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]); // for ie - - exports.isOldIE = exports.isIE && exports.isIE < 9; - exports.isGecko = exports.isMozilla = (window.Controllers || window.controllers) && window.navigator.product === "Gecko"; - exports.isOldGecko = exports.isGecko && parseInt((ua.match(/rv:(\d+)/)||[])[1], 10) < 4; - exports.isOpera = window.opera && Object.prototype.toString.call(window.opera) == "[object Opera]"; - exports.isWebKit = parseFloat(ua.split("WebKit/")[1]) || undefined; - - exports.isChrome = parseFloat(ua.split(" Chrome/")[1]) || undefined; - - exports.isAIR = ua.indexOf("AdobeAIR") >= 0; - - exports.isIPad = ua.indexOf("iPad") >= 0; - - exports.isChromeOS = ua.indexOf(" CrOS ") >= 0; - - exports.isIOS = /iPad|iPhone|iPod/.test(ua) && !window.MSStream; - - if (exports.isIOS) exports.isMac = true; - - }); - - ace.define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/useragent"], function(acequire, exports, module) { - "use strict"; - - var keys = acequire("./keys"); - var useragent = acequire("./useragent"); - - var pressedKeys = null; - var ts = 0; - - exports.addListener = function(elem, type, callback) { - if (elem.addEventListener) { - return elem.addEventListener(type, callback, false); - } - if (elem.attachEvent) { - var wrapper = function() { - callback.call(elem, window.event); - }; - callback._wrapper = wrapper; - elem.attachEvent("on" + type, wrapper); - } - }; - - exports.removeListener = function(elem, type, callback) { - if (elem.removeEventListener) { - return elem.removeEventListener(type, callback, false); - } - if (elem.detachEvent) { - elem.detachEvent("on" + type, callback._wrapper || callback); - } - }; - exports.stopEvent = function(e) { - exports.stopPropagation(e); - exports.preventDefault(e); - return false; - }; - - exports.stopPropagation = function(e) { - if (e.stopPropagation) - e.stopPropagation(); - else - e.cancelBubble = true; - }; - - exports.preventDefault = function(e) { - if (e.preventDefault) - e.preventDefault(); - else - e.returnValue = false; - }; - exports.getButton = function(e) { - if (e.type == "dblclick") - return 0; - if (e.type == "contextmenu" || (useragent.isMac && (e.ctrlKey && !e.altKey && !e.shiftKey))) - return 2; - if (e.preventDefault) { - return e.button; - } - else { - return {1:0, 2:2, 4:1}[e.button]; - } - }; - - exports.capture = function(el, eventHandler, releaseCaptureHandler) { - function onMouseUp(e) { - eventHandler && eventHandler(e); - releaseCaptureHandler && releaseCaptureHandler(e); - - exports.removeListener(document, "mousemove", eventHandler, true); - exports.removeListener(document, "mouseup", onMouseUp, true); - exports.removeListener(document, "dragstart", onMouseUp, true); - } - - exports.addListener(document, "mousemove", eventHandler, true); - exports.addListener(document, "mouseup", onMouseUp, true); - exports.addListener(document, "dragstart", onMouseUp, true); - - return onMouseUp; - }; - - exports.addTouchMoveListener = function (el, callback) { - var startx, starty; - exports.addListener(el, "touchstart", function (e) { - var touches = e.touches; - var touchObj = touches[0]; - startx = touchObj.clientX; - starty = touchObj.clientY; - }); - exports.addListener(el, "touchmove", function (e) { - var touches = e.touches; - if (touches.length > 1) return; - - var touchObj = touches[0]; - - e.wheelX = startx - touchObj.clientX; - e.wheelY = starty - touchObj.clientY; - - startx = touchObj.clientX; - starty = touchObj.clientY; - - callback(e); - }); - }; - - exports.addMouseWheelListener = function(el, callback) { - if ("onmousewheel" in el) { - exports.addListener(el, "mousewheel", function(e) { - var factor = 8; - if (e.wheelDeltaX !== undefined) { - e.wheelX = -e.wheelDeltaX / factor; - e.wheelY = -e.wheelDeltaY / factor; - } else { - e.wheelX = 0; - e.wheelY = -e.wheelDelta / factor; - } - callback(e); - }); - } else if ("onwheel" in el) { - exports.addListener(el, "wheel", function(e) { - var factor = 0.35; - switch (e.deltaMode) { - case e.DOM_DELTA_PIXEL: - e.wheelX = e.deltaX * factor || 0; - e.wheelY = e.deltaY * factor || 0; - break; - case e.DOM_DELTA_LINE: - case e.DOM_DELTA_PAGE: - e.wheelX = (e.deltaX || 0) * 5; - e.wheelY = (e.deltaY || 0) * 5; - break; - } - - callback(e); - }); - } else { - exports.addListener(el, "DOMMouseScroll", function(e) { - if (e.axis && e.axis == e.HORIZONTAL_AXIS) { - e.wheelX = (e.detail || 0) * 5; - e.wheelY = 0; - } else { - e.wheelX = 0; - e.wheelY = (e.detail || 0) * 5; - } - callback(e); - }); - } - }; - - exports.addMultiMouseDownListener = function(elements, timeouts, eventHandler, callbackName) { - var clicks = 0; - var startX, startY, timer; - var eventNames = { - 2: "dblclick", - 3: "tripleclick", - 4: "quadclick" - }; - - function onMousedown(e) { - if (exports.getButton(e) !== 0) { - clicks = 0; - } else if (e.detail > 1) { - clicks++; - if (clicks > 4) - clicks = 1; - } else { - clicks = 1; - } - if (useragent.isIE) { - var isNewClick = Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5; - if (!timer || isNewClick) - clicks = 1; - if (timer) - clearTimeout(timer); - timer = setTimeout(function() {timer = null;}, timeouts[clicks - 1] || 600); - - if (clicks == 1) { - startX = e.clientX; - startY = e.clientY; - } - } - - e._clicks = clicks; - - eventHandler[callbackName]("mousedown", e); - - if (clicks > 4) - clicks = 0; - else if (clicks > 1) - return eventHandler[callbackName](eventNames[clicks], e); - } - function onDblclick(e) { - clicks = 2; - if (timer) - clearTimeout(timer); - timer = setTimeout(function() {timer = null;}, timeouts[clicks - 1] || 600); - eventHandler[callbackName]("mousedown", e); - eventHandler[callbackName](eventNames[clicks], e); - } - if (!Array.isArray(elements)) - elements = [elements]; - elements.forEach(function(el) { - exports.addListener(el, "mousedown", onMousedown); - if (useragent.isOldIE) - exports.addListener(el, "dblclick", onDblclick); - }); - }; - - var getModifierHash = useragent.isMac && useragent.isOpera && !("KeyboardEvent" in window) - ? function(e) { - return 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0); - } - : function(e) { - return 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0); - }; - - exports.getModifierString = function(e) { - return keys.KEY_MODS[getModifierHash(e)]; - }; - - function normalizeCommandKeys(callback, e, keyCode) { - var hashId = getModifierHash(e); - - if (!useragent.isMac && pressedKeys) { - if (e.getModifierState && (e.getModifierState("OS") || e.getModifierState("Win"))) - hashId |= 8; - if (pressedKeys.altGr) { - if ((3 & hashId) != 3) - pressedKeys.altGr = 0; - else - return; - } - if (keyCode === 18 || keyCode === 17) { - var location = "location" in e ? e.location : e.keyLocation; - if (keyCode === 17 && location === 1) { - if (pressedKeys[keyCode] == 1) - ts = e.timeStamp; - } else if (keyCode === 18 && hashId === 3 && location === 2) { - var dt = e.timeStamp - ts; - if (dt < 50) - pressedKeys.altGr = true; - } - } - } - - if (keyCode in keys.MODIFIER_KEYS) { - keyCode = -1; - } - if (hashId & 8 && (keyCode >= 91 && keyCode <= 93)) { - keyCode = -1; - } - - if (!hashId && keyCode === 13) { - var location = "location" in e ? e.location : e.keyLocation; - if (location === 3) { - callback(e, hashId, -keyCode); - if (e.defaultPrevented) - return; - } - } - - if (useragent.isChromeOS && hashId & 8) { - callback(e, hashId, keyCode); - if (e.defaultPrevented) - return; - else - hashId &= ~8; - } - if (!hashId && !(keyCode in keys.FUNCTION_KEYS) && !(keyCode in keys.PRINTABLE_KEYS)) { - return false; - } - - return callback(e, hashId, keyCode); - } - - - exports.addCommandKeyListener = function(el, callback) { - var addListener = exports.addListener; - if (useragent.isOldGecko || (useragent.isOpera && !("KeyboardEvent" in window))) { - var lastKeyDownKeyCode = null; - addListener(el, "keydown", function(e) { - lastKeyDownKeyCode = e.keyCode; - }); - addListener(el, "keypress", function(e) { - return normalizeCommandKeys(callback, e, lastKeyDownKeyCode); - }); - } else { - var lastDefaultPrevented = null; - - addListener(el, "keydown", function(e) { - pressedKeys[e.keyCode] = (pressedKeys[e.keyCode] || 0) + 1; - var result = normalizeCommandKeys(callback, e, e.keyCode); - lastDefaultPrevented = e.defaultPrevented; - return result; - }); - - addListener(el, "keypress", function(e) { - if (lastDefaultPrevented && (e.ctrlKey || e.altKey || e.shiftKey || e.metaKey)) { - exports.stopEvent(e); - lastDefaultPrevented = null; - } - }); - - addListener(el, "keyup", function(e) { - pressedKeys[e.keyCode] = null; - }); - - if (!pressedKeys) { - resetPressedKeys(); - addListener(window, "focus", resetPressedKeys); - } - } - }; - function resetPressedKeys() { - pressedKeys = Object.create(null); - } - - if (typeof window == "object" && window.postMessage && !useragent.isOldIE) { - var postMessageId = 1; - exports.nextTick = function(callback, win) { - win = win || window; - var messageName = "zero-timeout-message-" + postMessageId; - exports.addListener(win, "message", function listener(e) { - if (e.data == messageName) { - exports.stopPropagation(e); - exports.removeListener(win, "message", listener); - callback(); - } - }); - win.postMessage(messageName, "*"); - }; - } - - - exports.nextFrame = typeof window == "object" && (window.requestAnimationFrame - || window.mozRequestAnimationFrame - || window.webkitRequestAnimationFrame - || window.msRequestAnimationFrame - || window.oRequestAnimationFrame); - - if (exports.nextFrame) - exports.nextFrame = exports.nextFrame.bind(window); - else - exports.nextFrame = function(callback) { - setTimeout(callback, 17); - }; - }); - - ace.define("ace/lib/lang",["require","exports","module"], function(acequire, exports, module) { - "use strict"; - - exports.last = function(a) { - return a[a.length - 1]; - }; - - exports.stringReverse = function(string) { - return string.split("").reverse().join(""); - }; - - exports.stringRepeat = function (string, count) { - var result = ''; - while (count > 0) { - if (count & 1) - result += string; - - if (count >>= 1) - string += string; - } - return result; - }; - - var trimBeginRegexp = /^\s\s*/; - var trimEndRegexp = /\s\s*$/; - - exports.stringTrimLeft = function (string) { - return string.replace(trimBeginRegexp, ''); - }; - - exports.stringTrimRight = function (string) { - return string.replace(trimEndRegexp, ''); - }; - - exports.copyObject = function(obj) { - var copy = {}; - for (var key in obj) { - copy[key] = obj[key]; - } - return copy; - }; - - exports.copyArray = function(array){ - var copy = []; - for (var i=0, l=array.length; i PLACEHOLDER.length) - data = data.substr(9); - else if (data.substr(0, 4) == PLACEHOLDER.substr(0, 4)) - data = data.substr(4, data.length - PLACEHOLDER.length + 1); - else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0)) - data = data.slice(0, -1); - if (data == PLACEHOLDER.charAt(0)) { - } else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0)) - data = data.slice(0, -1); - - if (data) - host.onTextInput(data); - } - if (copied) { - copied = false; - } - if (afterContextMenu) - afterContextMenu = false; - }; - var onInput = function(e) { - if (inComposition) - return; - var data = text.value; - sendText(data); - resetValue(); - }; - - var handleClipboardData = function(e, data, forceIEMime) { - var clipboardData = e.clipboardData || window.clipboardData; - if (!clipboardData || BROKEN_SETDATA) - return; - var mime = USE_IE_MIME_TYPE || forceIEMime ? "Text" : "text/plain"; - try { - if (data) { - return clipboardData.setData(mime, data) !== false; - } else { - return clipboardData.getData(mime); - } - } catch(e) { - if (!forceIEMime) - return handleClipboardData(e, data, true); - } - }; - - var doCopy = function(e, isCut) { - var data = host.getCopyText(); - if (!data) - return event.preventDefault(e); - - if (handleClipboardData(e, data)) { - if (useragent.isIOS) { - cut = isCut; - text.value = "\n aa" + data + "a a\n"; - text.setSelectionRange(4, 4 + data.length); - copied = { - value: data - }; - } - isCut ? host.onCut() : host.onCopy(); - if (!useragent.isIOS) event.preventDefault(e); - } else { - copied = true; - text.value = data; - text.select(); - setTimeout(function(){ - copied = false; - resetValue(); - resetSelection(); - isCut ? host.onCut() : host.onCopy(); - }); - } - }; - - var onCut = function(e) { - doCopy(e, true); - }; - - var onCopy = function(e) { - doCopy(e, false); - }; - - var onPaste = function(e) { - var data = handleClipboardData(e); - if (typeof data == "string") { - if (data) - host.onPaste(data, e); - if (useragent.isIE) - setTimeout(resetSelection); - event.preventDefault(e); - } - else { - text.value = ""; - pasted = true; - } - }; - - event.addCommandKeyListener(text, host.onCommandKey.bind(host)); - - event.addListener(text, "select", onSelect); - - event.addListener(text, "input", onInput); - - event.addListener(text, "cut", onCut); - event.addListener(text, "copy", onCopy); - event.addListener(text, "paste", onPaste); - var onCompositionStart = function(e) { - if (inComposition || !host.onCompositionStart || host.$readOnly) - return; - inComposition = {}; - inComposition.canUndo = host.session.$undoManager; - host.onCompositionStart(); - setTimeout(onCompositionUpdate, 0); - host.on("mousedown", onCompositionEnd); - if (inComposition.canUndo && !host.selection.isEmpty()) { - host.insert(""); - host.session.markUndoGroup(); - host.selection.clearSelection(); - } - host.session.markUndoGroup(); - }; - - var onCompositionUpdate = function() { - if (!inComposition || !host.onCompositionUpdate || host.$readOnly) - return; - var val = text.value.replace(/\x01/g, ""); - if (inComposition.lastValue === val) return; - - host.onCompositionUpdate(val); - if (inComposition.lastValue) - host.undo(); - if (inComposition.canUndo) - inComposition.lastValue = val; - if (inComposition.lastValue) { - var r = host.selection.getRange(); - host.insert(inComposition.lastValue); - host.session.markUndoGroup(); - inComposition.range = host.selection.getRange(); - host.selection.setRange(r); - host.selection.clearSelection(); - } - }; - - var onCompositionEnd = function(e) { - if (!host.onCompositionEnd || host.$readOnly) return; - var c = inComposition; - inComposition = false; - var timer = setTimeout(function() { - timer = null; - var str = text.value.replace(/\x01/g, ""); - if (inComposition) - return; - else if (str == c.lastValue) - resetValue(); - else if (!c.lastValue && str) { - resetValue(); - sendText(str); - } - }); - inputHandler = function compositionInputHandler(str) { - if (timer) - clearTimeout(timer); - str = str.replace(/\x01/g, ""); - if (str == c.lastValue) - return ""; - if (c.lastValue && timer) - host.undo(); - return str; - }; - host.onCompositionEnd(); - host.removeListener("mousedown", onCompositionEnd); - if (e.type == "compositionend" && c.range) { - host.selection.setRange(c.range); - } - var needsOnInput = - (!!useragent.isChrome && useragent.isChrome >= 53) || - (!!useragent.isWebKit && useragent.isWebKit >= 603); - - if (needsOnInput) { - onInput(); - } - }; - - - - var syncComposition = lang.delayedCall(onCompositionUpdate, 50); - - event.addListener(text, "compositionstart", onCompositionStart); - if (useragent.isGecko) { - event.addListener(text, "text", function(){syncComposition.schedule();}); - } else { - event.addListener(text, "keyup", function(){syncComposition.schedule();}); - event.addListener(text, "keydown", function(){syncComposition.schedule();}); - } - event.addListener(text, "compositionend", onCompositionEnd); - - this.getElement = function() { - return text; - }; - - this.setReadOnly = function(readOnly) { - text.readOnly = readOnly; - }; - - this.onContextMenu = function(e) { - afterContextMenu = true; - resetSelection(host.selection.isEmpty()); - host._emit("nativecontextmenu", {target: host, domEvent: e}); - this.moveToMouse(e, true); - }; - - this.moveToMouse = function(e, bringToFront) { - if (!tempStyle) - tempStyle = text.style.cssText; - text.style.cssText = (bringToFront ? "z-index:100000;" : "") - + "height:" + text.style.height + ";" - + (useragent.isIE ? "opacity:0.1;" : ""); - - var rect = host.container.getBoundingClientRect(); - var style = dom.computedStyle(host.container); - var top = rect.top + (parseInt(style.borderTopWidth) || 0); - var left = rect.left + (parseInt(rect.borderLeftWidth) || 0); - var maxTop = rect.bottom - top - text.clientHeight -2; - var move = function(e) { - text.style.left = e.clientX - left - 2 + "px"; - text.style.top = Math.min(e.clientY - top - 2, maxTop) + "px"; - }; - move(e); - - if (e.type != "mousedown") - return; - - if (host.renderer.$keepTextAreaAtCursor) - host.renderer.$keepTextAreaAtCursor = null; - - clearTimeout(closeTimeout); - if (useragent.isWin) - event.capture(host.container, move, onContextMenuClose); - }; - - this.onContextMenuClose = onContextMenuClose; - var closeTimeout; - function onContextMenuClose() { - clearTimeout(closeTimeout); - closeTimeout = setTimeout(function () { - if (tempStyle) { - text.style.cssText = tempStyle; - tempStyle = ''; - } - if (host.renderer.$keepTextAreaAtCursor == null) { - host.renderer.$keepTextAreaAtCursor = true; - host.renderer.$moveTextAreaToCursor(); - } - }, 0); - } - - var onContextMenu = function(e) { - host.textInput.onContextMenu(e); - onContextMenuClose(); - }; - event.addListener(text, "mouseup", onContextMenu); - event.addListener(text, "mousedown", function(e) { - e.preventDefault(); - onContextMenuClose(); - }); - event.addListener(host.renderer.scroller, "contextmenu", onContextMenu); - event.addListener(text, "contextmenu", onContextMenu); - - if (useragent.isIOS) { - var typingResetTimeout = null; - var typing = false; - - parentNode.addEventListener("keydown", function (e) { - if (typingResetTimeout) clearTimeout(typingResetTimeout); - typing = true; - }); - - parentNode.addEventListener("keyup", function (e) { - typingResetTimeout = setTimeout(function () { - typing = false; - }, 100); - }); - var detectArrowKeys = function(e) { - if (document.activeElement !== text) return; - if (typing) return; - - if (cut) { - return setTimeout(function () { - cut = false; - }, 100); - } - var selectionStart = text.selectionStart; - var selectionEnd = text.selectionEnd; - text.setSelectionRange(4, 5); - if (selectionStart == selectionEnd) { - switch (selectionStart) { - case 0: host.onCommandKey(null, 0, KEYS.up); break; - case 1: host.onCommandKey(null, 0, KEYS.home); break; - case 2: host.onCommandKey(null, MODS.option, KEYS.left); break; - case 4: host.onCommandKey(null, 0, KEYS.left); break; - case 5: host.onCommandKey(null, 0, KEYS.right); break; - case 7: host.onCommandKey(null, MODS.option, KEYS.right); break; - case 8: host.onCommandKey(null, 0, KEYS.end); break; - case 9: host.onCommandKey(null, 0, KEYS.down); break; - } - } else { - switch (selectionEnd) { - case 6: host.onCommandKey(null, MODS.shift, KEYS.right); break; - case 7: host.onCommandKey(null, MODS.shift | MODS.option, KEYS.right); break; - case 8: host.onCommandKey(null, MODS.shift, KEYS.end); break; - case 9: host.onCommandKey(null, MODS.shift, KEYS.down); break; - } - switch (selectionStart) { - case 0: host.onCommandKey(null, MODS.shift, KEYS.up); break; - case 1: host.onCommandKey(null, MODS.shift, KEYS.home); break; - case 2: host.onCommandKey(null, MODS.shift | MODS.option, KEYS.left); break; - case 3: host.onCommandKey(null, MODS.shift, KEYS.left); break; - } - } - }; - document.addEventListener("selectionchange", detectArrowKeys); - host.on("destroy", function() { - document.removeEventListener("selectionchange", detectArrowKeys); - }); - } - }; - - exports.TextInput = TextInput; - }); - - ace.define("ace/keyboard/textinput",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/dom","ace/lib/lang","ace/keyboard/textinput_ios"], function(acequire, exports, module) { - "use strict"; - - var event = acequire("../lib/event"); - var useragent = acequire("../lib/useragent"); - var dom = acequire("../lib/dom"); - var lang = acequire("../lib/lang"); - var BROKEN_SETDATA = useragent.isChrome < 18; - var USE_IE_MIME_TYPE = useragent.isIE; - - var TextInputIOS = acequire("./textinput_ios").TextInput; - var TextInput = function(parentNode, host) { - if (useragent.isIOS) - return TextInputIOS.call(this, parentNode, host); - - var text = dom.createElement("textarea"); - text.className = "ace_text-input"; - - text.setAttribute("wrap", "off"); - text.setAttribute("autocorrect", "off"); - text.setAttribute("autocapitalize", "off"); - text.setAttribute("spellcheck", false); - - text.style.opacity = "0"; - parentNode.insertBefore(text, parentNode.firstChild); - - var PLACEHOLDER = "\u2028\u2028"; - - var copied = false; - var pasted = false; - var inComposition = false; - var tempStyle = ''; - var isSelectionEmpty = true; - try { var isFocused = document.activeElement === text; } catch(e) {} - - event.addListener(text, "blur", function(e) { - host.onBlur(e); - isFocused = false; - }); - event.addListener(text, "focus", function(e) { - isFocused = true; - host.onFocus(e); - resetSelection(); - }); - this.focus = function() { - if (tempStyle) return text.focus(); - var top = text.style.top; - text.style.position = "fixed"; - text.style.top = "0px"; - text.focus(); - setTimeout(function() { - text.style.position = ""; - if (text.style.top == "0px") - text.style.top = top; - }, 0); - }; - this.blur = function() { - text.blur(); - }; - this.isFocused = function() { - return isFocused; - }; - var syncSelection = lang.delayedCall(function() { - isFocused && resetSelection(isSelectionEmpty); - }); - var syncValue = lang.delayedCall(function() { - if (!inComposition) { - text.value = PLACEHOLDER; - isFocused && resetSelection(); - } - }); - - function resetSelection(isEmpty) { - if (inComposition) - return; - inComposition = true; - - if (inputHandler) { - var selectionStart = 0; - var selectionEnd = isEmpty ? 0 : text.value.length - 1; - } else { - var selectionStart = isEmpty ? 2 : 1; - var selectionEnd = 2; - } - try { - text.setSelectionRange(selectionStart, selectionEnd); - } catch(e){} - - inComposition = false; - } - - function resetValue() { - if (inComposition) - return; - text.value = PLACEHOLDER; - if (useragent.isWebKit) - syncValue.schedule(); - } - - useragent.isWebKit || host.addEventListener('changeSelection', function() { - if (host.selection.isEmpty() != isSelectionEmpty) { - isSelectionEmpty = !isSelectionEmpty; - syncSelection.schedule(); - } - }); - - resetValue(); - if (isFocused) - host.onFocus(); - - - var isAllSelected = function(text) { - return text.selectionStart === 0 && text.selectionEnd === text.value.length; - }; - - var onSelect = function(e) { - if (copied) { - copied = false; - } else if (isAllSelected(text)) { - host.selectAll(); - resetSelection(); - } else if (inputHandler) { - resetSelection(host.selection.isEmpty()); - } - }; - - var inputHandler = null; - this.setInputHandler = function(cb) {inputHandler = cb;}; - this.getInputHandler = function() {return inputHandler;}; - var afterContextMenu = false; - - var sendText = function(data) { - if (inputHandler) { - data = inputHandler(data); - inputHandler = null; - } - if (pasted) { - resetSelection(); - if (data) - host.onPaste(data); - pasted = false; - } else if (data == PLACEHOLDER.charAt(0)) { - if (afterContextMenu) - host.execCommand("del", {source: "ace"}); - else // some versions of android do not fire keydown when pressing backspace - host.execCommand("backspace", {source: "ace"}); - } else { - if (data.substring(0, 2) == PLACEHOLDER) - data = data.substr(2); - else if (data.charAt(0) == PLACEHOLDER.charAt(0)) - data = data.substr(1); - else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0)) - data = data.slice(0, -1); - if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0)) - data = data.slice(0, -1); - - if (data) - host.onTextInput(data); - } - if (afterContextMenu) - afterContextMenu = false; - }; - var onInput = function(e) { - if (inComposition) - return; - var data = text.value; - sendText(data); - resetValue(); - }; - - var handleClipboardData = function(e, data, forceIEMime) { - var clipboardData = e.clipboardData || window.clipboardData; - if (!clipboardData || BROKEN_SETDATA) - return; - var mime = USE_IE_MIME_TYPE || forceIEMime ? "Text" : "text/plain"; - try { - if (data) { - return clipboardData.setData(mime, data) !== false; - } else { - return clipboardData.getData(mime); - } - } catch(e) { - if (!forceIEMime) - return handleClipboardData(e, data, true); - } - }; - - var doCopy = function(e, isCut) { - var data = host.getCopyText(); - if (!data) - return event.preventDefault(e); - - if (handleClipboardData(e, data)) { - isCut ? host.onCut() : host.onCopy(); - event.preventDefault(e); - } else { - copied = true; - text.value = data; - text.select(); - setTimeout(function(){ - copied = false; - resetValue(); - resetSelection(); - isCut ? host.onCut() : host.onCopy(); - }); - } - }; - - var onCut = function(e) { - doCopy(e, true); - }; - - var onCopy = function(e) { - doCopy(e, false); - }; - - var onPaste = function(e) { - var data = handleClipboardData(e); - if (typeof data == "string") { - if (data) - host.onPaste(data, e); - if (useragent.isIE) - setTimeout(resetSelection); - event.preventDefault(e); - } - else { - text.value = ""; - pasted = true; - } - }; - - event.addCommandKeyListener(text, host.onCommandKey.bind(host)); - - event.addListener(text, "select", onSelect); - - event.addListener(text, "input", onInput); - - event.addListener(text, "cut", onCut); - event.addListener(text, "copy", onCopy); - event.addListener(text, "paste", onPaste); - if (!('oncut' in text) || !('oncopy' in text) || !('onpaste' in text)) { - event.addListener(parentNode, "keydown", function(e) { - if ((useragent.isMac && !e.metaKey) || !e.ctrlKey) - return; - - switch (e.keyCode) { - case 67: - onCopy(e); - break; - case 86: - onPaste(e); - break; - case 88: - onCut(e); - break; - } - }); - } - var onCompositionStart = function(e) { - if (inComposition || !host.onCompositionStart || host.$readOnly) - return; - inComposition = {}; - inComposition.canUndo = host.session.$undoManager; - host.onCompositionStart(); - setTimeout(onCompositionUpdate, 0); - host.on("mousedown", onCompositionEnd); - if (inComposition.canUndo && !host.selection.isEmpty()) { - host.insert(""); - host.session.markUndoGroup(); - host.selection.clearSelection(); - } - host.session.markUndoGroup(); - }; - - var onCompositionUpdate = function() { - if (!inComposition || !host.onCompositionUpdate || host.$readOnly) - return; - var val = text.value.replace(/\u2028/g, ""); - if (inComposition.lastValue === val) return; - - host.onCompositionUpdate(val); - if (inComposition.lastValue) - host.undo(); - if (inComposition.canUndo) - inComposition.lastValue = val; - if (inComposition.lastValue) { - var r = host.selection.getRange(); - host.insert(inComposition.lastValue); - host.session.markUndoGroup(); - inComposition.range = host.selection.getRange(); - host.selection.setRange(r); - host.selection.clearSelection(); - } - }; - - var onCompositionEnd = function(e) { - if (!host.onCompositionEnd || host.$readOnly) return; - var c = inComposition; - inComposition = false; - var timer = setTimeout(function() { - timer = null; - var str = text.value.replace(/\u2028/g, ""); - if (inComposition) - return; - else if (str == c.lastValue) - resetValue(); - else if (!c.lastValue && str) { - resetValue(); - sendText(str); - } - }); - inputHandler = function compositionInputHandler(str) { - if (timer) - clearTimeout(timer); - str = str.replace(/\u2028/g, ""); - if (str == c.lastValue) - return ""; - if (c.lastValue && timer) - host.undo(); - return str; - }; - host.onCompositionEnd(); - host.removeListener("mousedown", onCompositionEnd); - if (e.type == "compositionend" && c.range) { - host.selection.setRange(c.range); - } - var needsOnInput = - (!!useragent.isChrome && useragent.isChrome >= 53) || - (!!useragent.isWebKit && useragent.isWebKit >= 603); - - if (needsOnInput) { - onInput(); - } - }; - - - - var syncComposition = lang.delayedCall(onCompositionUpdate, 50); - - event.addListener(text, "compositionstart", onCompositionStart); - if (useragent.isGecko) { - event.addListener(text, "text", function(){syncComposition.schedule();}); - } else { - event.addListener(text, "keyup", function(){syncComposition.schedule();}); - event.addListener(text, "keydown", function(){syncComposition.schedule();}); - } - event.addListener(text, "compositionend", onCompositionEnd); - - this.getElement = function() { - return text; - }; - - this.setReadOnly = function(readOnly) { - text.readOnly = readOnly; - }; - - this.onContextMenu = function(e) { - afterContextMenu = true; - resetSelection(host.selection.isEmpty()); - host._emit("nativecontextmenu", {target: host, domEvent: e}); - this.moveToMouse(e, true); - }; - - this.moveToMouse = function(e, bringToFront) { - if (!tempStyle) - tempStyle = text.style.cssText; - text.style.cssText = (bringToFront ? "z-index:100000;" : "") - + "height:" + text.style.height + ";" - + (useragent.isIE ? "opacity:0.1;" : ""); - - var rect = host.container.getBoundingClientRect(); - var style = dom.computedStyle(host.container); - var top = rect.top + (parseInt(style.borderTopWidth) || 0); - var left = rect.left + (parseInt(rect.borderLeftWidth) || 0); - var maxTop = rect.bottom - top - text.clientHeight -2; - var move = function(e) { - text.style.left = e.clientX - left - 2 + "px"; - text.style.top = Math.min(e.clientY - top - 2, maxTop) + "px"; - }; - move(e); - - if (e.type != "mousedown") - return; - - if (host.renderer.$keepTextAreaAtCursor) - host.renderer.$keepTextAreaAtCursor = null; - - clearTimeout(closeTimeout); - if (useragent.isWin) - event.capture(host.container, move, onContextMenuClose); - }; - - this.onContextMenuClose = onContextMenuClose; - var closeTimeout; - function onContextMenuClose() { - clearTimeout(closeTimeout); - closeTimeout = setTimeout(function () { - if (tempStyle) { - text.style.cssText = tempStyle; - tempStyle = ''; - } - if (host.renderer.$keepTextAreaAtCursor == null) { - host.renderer.$keepTextAreaAtCursor = true; - host.renderer.$moveTextAreaToCursor(); - } - }, 0); - } - - var onContextMenu = function(e) { - host.textInput.onContextMenu(e); - onContextMenuClose(); - }; - event.addListener(text, "mouseup", onContextMenu); - event.addListener(text, "mousedown", function(e) { - e.preventDefault(); - onContextMenuClose(); - }); - event.addListener(host.renderer.scroller, "contextmenu", onContextMenu); - event.addListener(text, "contextmenu", onContextMenu); - }; - - exports.TextInput = TextInput; - }); - - ace.define("ace/mouse/default_handlers",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) { - "use strict"; - - var dom = acequire("../lib/dom"); - var event = acequire("../lib/event"); - var useragent = acequire("../lib/useragent"); - - var DRAG_OFFSET = 0; // pixels - var SCROLL_COOLDOWN_T = 250; // milliseconds - - function DefaultHandlers(mouseHandler) { - mouseHandler.$clickSelection = null; - - var editor = mouseHandler.editor; - editor.setDefaultHandler("mousedown", this.onMouseDown.bind(mouseHandler)); - editor.setDefaultHandler("dblclick", this.onDoubleClick.bind(mouseHandler)); - editor.setDefaultHandler("tripleclick", this.onTripleClick.bind(mouseHandler)); - editor.setDefaultHandler("quadclick", this.onQuadClick.bind(mouseHandler)); - editor.setDefaultHandler("mousewheel", this.onMouseWheel.bind(mouseHandler)); - editor.setDefaultHandler("touchmove", this.onTouchMove.bind(mouseHandler)); - - var exports = ["select", "startSelect", "selectEnd", "selectAllEnd", "selectByWordsEnd", - "selectByLinesEnd", "dragWait", "dragWaitEnd", "focusWait"]; - - exports.forEach(function(x) { - mouseHandler[x] = this[x]; - }, this); - - mouseHandler.selectByLines = this.extendSelectionBy.bind(mouseHandler, "getLineRange"); - mouseHandler.selectByWords = this.extendSelectionBy.bind(mouseHandler, "getWordRange"); - } - - (function() { - - this.onMouseDown = function(ev) { - var inSelection = ev.inSelection(); - var pos = ev.getDocumentPosition(); - this.mousedownEvent = ev; - var editor = this.editor; - - var button = ev.getButton(); - if (button !== 0) { - var selectionRange = editor.getSelectionRange(); - var selectionEmpty = selectionRange.isEmpty(); - editor.$blockScrolling++; - if (selectionEmpty || button == 1) - editor.selection.moveToPosition(pos); - editor.$blockScrolling--; - if (button == 2) { - editor.textInput.onContextMenu(ev.domEvent); - if (!useragent.isMozilla) - ev.preventDefault(); - } - return; - } - - this.mousedownEvent.time = Date.now(); - if (inSelection && !editor.isFocused()) { - editor.focus(); - if (this.$focusTimout && !this.$clickSelection && !editor.inMultiSelectMode) { - this.setState("focusWait"); - this.captureMouse(ev); - return; - } - } - - this.captureMouse(ev); - this.startSelect(pos, ev.domEvent._clicks > 1); - return ev.preventDefault(); - }; - - this.startSelect = function(pos, waitForClickSelection) { - pos = pos || this.editor.renderer.screenToTextCoordinates(this.x, this.y); - var editor = this.editor; - editor.$blockScrolling++; - if (this.mousedownEvent.getShiftKey()) - editor.selection.selectToPosition(pos); - else if (!waitForClickSelection) - editor.selection.moveToPosition(pos); - if (!waitForClickSelection) - this.select(); - if (editor.renderer.scroller.setCapture) { - editor.renderer.scroller.setCapture(); - } - editor.setStyle("ace_selecting"); - this.setState("select"); - editor.$blockScrolling--; - }; - - this.select = function() { - var anchor, editor = this.editor; - var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y); - editor.$blockScrolling++; - if (this.$clickSelection) { - var cmp = this.$clickSelection.comparePoint(cursor); - - if (cmp == -1) { - anchor = this.$clickSelection.end; - } else if (cmp == 1) { - anchor = this.$clickSelection.start; - } else { - var orientedRange = calcRangeOrientation(this.$clickSelection, cursor); - cursor = orientedRange.cursor; - anchor = orientedRange.anchor; - } - editor.selection.setSelectionAnchor(anchor.row, anchor.column); - } - editor.selection.selectToPosition(cursor); - editor.$blockScrolling--; - editor.renderer.scrollCursorIntoView(); - }; - - this.extendSelectionBy = function(unitName) { - var anchor, editor = this.editor; - var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y); - var range = editor.selection[unitName](cursor.row, cursor.column); - editor.$blockScrolling++; - if (this.$clickSelection) { - var cmpStart = this.$clickSelection.comparePoint(range.start); - var cmpEnd = this.$clickSelection.comparePoint(range.end); - - if (cmpStart == -1 && cmpEnd <= 0) { - anchor = this.$clickSelection.end; - if (range.end.row != cursor.row || range.end.column != cursor.column) - cursor = range.start; - } else if (cmpEnd == 1 && cmpStart >= 0) { - anchor = this.$clickSelection.start; - if (range.start.row != cursor.row || range.start.column != cursor.column) - cursor = range.end; - } else if (cmpStart == -1 && cmpEnd == 1) { - cursor = range.end; - anchor = range.start; - } else { - var orientedRange = calcRangeOrientation(this.$clickSelection, cursor); - cursor = orientedRange.cursor; - anchor = orientedRange.anchor; - } - editor.selection.setSelectionAnchor(anchor.row, anchor.column); - } - editor.selection.selectToPosition(cursor); - editor.$blockScrolling--; - editor.renderer.scrollCursorIntoView(); - }; - - this.selectEnd = - this.selectAllEnd = - this.selectByWordsEnd = - this.selectByLinesEnd = function() { - this.$clickSelection = null; - this.editor.unsetStyle("ace_selecting"); - if (this.editor.renderer.scroller.releaseCapture) { - this.editor.renderer.scroller.releaseCapture(); - } - }; - - this.focusWait = function() { - var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); - var time = Date.now(); - - if (distance > DRAG_OFFSET || time - this.mousedownEvent.time > this.$focusTimout) - this.startSelect(this.mousedownEvent.getDocumentPosition()); - }; - - this.onDoubleClick = function(ev) { - var pos = ev.getDocumentPosition(); - var editor = this.editor; - var session = editor.session; - - var range = session.getBracketRange(pos); - if (range) { - if (range.isEmpty()) { - range.start.column--; - range.end.column++; - } - this.setState("select"); - } else { - range = editor.selection.getWordRange(pos.row, pos.column); - this.setState("selectByWords"); - } - this.$clickSelection = range; - this.select(); - }; - - this.onTripleClick = function(ev) { - var pos = ev.getDocumentPosition(); - var editor = this.editor; - - this.setState("selectByLines"); - var range = editor.getSelectionRange(); - if (range.isMultiLine() && range.contains(pos.row, pos.column)) { - this.$clickSelection = editor.selection.getLineRange(range.start.row); - this.$clickSelection.end = editor.selection.getLineRange(range.end.row).end; - } else { - this.$clickSelection = editor.selection.getLineRange(pos.row); - } - this.select(); - }; - - this.onQuadClick = function(ev) { - var editor = this.editor; - - editor.selectAll(); - this.$clickSelection = editor.getSelectionRange(); - this.setState("selectAll"); - }; - - this.onMouseWheel = function(ev) { - if (ev.getAccelKey()) - return; - if (ev.getShiftKey() && ev.wheelY && !ev.wheelX) { - ev.wheelX = ev.wheelY; - ev.wheelY = 0; - } - - var editor = this.editor; - - if (!this.$lastScroll) - this.$lastScroll = { t: 0, vx: 0, vy: 0, allowed: 0 }; - - var prevScroll = this.$lastScroll; - var t = ev.domEvent.timeStamp; - var dt = t - prevScroll.t; - var vx = ev.wheelX / dt; - var vy = ev.wheelY / dt; - if (dt < SCROLL_COOLDOWN_T) { - vx = (vx + prevScroll.vx) / 2; - vy = (vy + prevScroll.vy) / 2; - } - - var direction = Math.abs(vx / vy); - - var canScroll = false; - if (direction >= 1 && editor.renderer.isScrollableBy(ev.wheelX * ev.speed, 0)) - canScroll = true; - if (direction <= 1 && editor.renderer.isScrollableBy(0, ev.wheelY * ev.speed)) - canScroll = true; - - if (canScroll) { - prevScroll.allowed = t; - } else if (t - prevScroll.allowed < SCROLL_COOLDOWN_T) { - var isSlower = Math.abs(vx) <= 1.1 * Math.abs(prevScroll.vx) - && Math.abs(vy) <= 1.1 * Math.abs(prevScroll.vy); - if (isSlower) { - canScroll = true; - prevScroll.allowed = t; - } - else { - prevScroll.allowed = 0; - } - } - - prevScroll.t = t; - prevScroll.vx = vx; - prevScroll.vy = vy; - - if (canScroll) { - editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed); - return ev.stop(); - } - }; - - this.onTouchMove = function(ev) { - this.editor._emit("mousewheel", ev); - }; - - }).call(DefaultHandlers.prototype); - - exports.DefaultHandlers = DefaultHandlers; - - function calcDistance(ax, ay, bx, by) { - return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2)); - } - - function calcRangeOrientation(range, cursor) { - if (range.start.row == range.end.row) - var cmp = 2 * cursor.column - range.start.column - range.end.column; - else if (range.start.row == range.end.row - 1 && !range.start.column && !range.end.column) - var cmp = cursor.column - 4; - else - var cmp = 2 * cursor.row - range.start.row - range.end.row; - - if (cmp < 0) - return {cursor: range.start, anchor: range.end}; - else - return {cursor: range.end, anchor: range.start}; - } - - }); - - ace.define("ace/tooltip",["require","exports","module","ace/lib/oop","ace/lib/dom"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("./lib/oop"); - var dom = acequire("./lib/dom"); - function Tooltip (parentNode) { - this.isOpen = false; - this.$element = null; - this.$parentNode = parentNode; - } - - (function() { - this.$init = function() { - this.$element = dom.createElement("div"); - this.$element.className = "ace_tooltip"; - this.$element.style.display = "none"; - this.$parentNode.appendChild(this.$element); - return this.$element; - }; - this.getElement = function() { - return this.$element || this.$init(); - }; - this.setText = function(text) { - dom.setInnerText(this.getElement(), text); - }; - this.setHtml = function(html) { - this.getElement().innerHTML = html; - }; - this.setPosition = function(x, y) { - this.getElement().style.left = x + "px"; - this.getElement().style.top = y + "px"; - }; - this.setClassName = function(className) { - dom.addCssClass(this.getElement(), className); - }; - this.show = function(text, x, y) { - if (text != null) - this.setText(text); - if (x != null && y != null) - this.setPosition(x, y); - if (!this.isOpen) { - this.getElement().style.display = "block"; - this.isOpen = true; - } - }; - - this.hide = function() { - if (this.isOpen) { - this.getElement().style.display = "none"; - this.isOpen = false; - } - }; - this.getHeight = function() { - return this.getElement().offsetHeight; - }; - this.getWidth = function() { - return this.getElement().offsetWidth; - }; - - this.destroy = function() { - this.isOpen = false; - if (this.$element && this.$element.parentNode) { - this.$element.parentNode.removeChild(this.$element); - } - }; - - }).call(Tooltip.prototype); - - exports.Tooltip = Tooltip; - }); - - ace.define("ace/mouse/default_gutter_handler",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event","ace/tooltip"], function(acequire, exports, module) { - "use strict"; - var dom = acequire("../lib/dom"); - var oop = acequire("../lib/oop"); - var event = acequire("../lib/event"); - var Tooltip = acequire("../tooltip").Tooltip; - - function GutterHandler(mouseHandler) { - var editor = mouseHandler.editor; - var gutter = editor.renderer.$gutterLayer; - var tooltip = new GutterTooltip(editor.container); - - mouseHandler.editor.setDefaultHandler("guttermousedown", function(e) { - if (!editor.isFocused() || e.getButton() != 0) - return; - var gutterRegion = gutter.getRegion(e); - - if (gutterRegion == "foldWidgets") - return; - - var row = e.getDocumentPosition().row; - var selection = editor.session.selection; - - if (e.getShiftKey()) - selection.selectTo(row, 0); - else { - if (e.domEvent.detail == 2) { - editor.selectAll(); - return e.preventDefault(); - } - mouseHandler.$clickSelection = editor.selection.getLineRange(row); - } - mouseHandler.setState("selectByLines"); - mouseHandler.captureMouse(e); - return e.preventDefault(); - }); - - - var tooltipTimeout, mouseEvent, tooltipAnnotation; - - function showTooltip() { - var row = mouseEvent.getDocumentPosition().row; - var annotation = gutter.$annotations[row]; - if (!annotation) - return hideTooltip(); - - var maxRow = editor.session.getLength(); - if (row == maxRow) { - var screenRow = editor.renderer.pixelToScreenCoordinates(0, mouseEvent.y).row; - var pos = mouseEvent.$pos; - if (screenRow > editor.session.documentToScreenRow(pos.row, pos.column)) - return hideTooltip(); - } - - if (tooltipAnnotation == annotation) - return; - tooltipAnnotation = annotation.text.join("
"); - - tooltip.setHtml(tooltipAnnotation); - tooltip.show(); - editor._signal("showGutterTooltip", tooltip); - editor.on("mousewheel", hideTooltip); - - if (mouseHandler.$tooltipFollowsMouse) { - moveTooltip(mouseEvent); - } else { - var gutterElement = mouseEvent.domEvent.target; - var rect = gutterElement.getBoundingClientRect(); - var style = tooltip.getElement().style; - style.left = rect.right + "px"; - style.top = rect.bottom + "px"; - } - } - - function hideTooltip() { - if (tooltipTimeout) - tooltipTimeout = clearTimeout(tooltipTimeout); - if (tooltipAnnotation) { - tooltip.hide(); - tooltipAnnotation = null; - editor._signal("hideGutterTooltip", tooltip); - editor.removeEventListener("mousewheel", hideTooltip); - } - } - - function moveTooltip(e) { - tooltip.setPosition(e.x, e.y); - } - - mouseHandler.editor.setDefaultHandler("guttermousemove", function(e) { - var target = e.domEvent.target || e.domEvent.srcElement; - if (dom.hasCssClass(target, "ace_fold-widget")) - return hideTooltip(); - - if (tooltipAnnotation && mouseHandler.$tooltipFollowsMouse) - moveTooltip(e); - - mouseEvent = e; - if (tooltipTimeout) - return; - tooltipTimeout = setTimeout(function() { - tooltipTimeout = null; - if (mouseEvent && !mouseHandler.isMousePressed) - showTooltip(); - else - hideTooltip(); - }, 50); - }); - - event.addListener(editor.renderer.$gutter, "mouseout", function(e) { - mouseEvent = null; - if (!tooltipAnnotation || tooltipTimeout) - return; - - tooltipTimeout = setTimeout(function() { - tooltipTimeout = null; - hideTooltip(); - }, 50); - }); - - editor.on("changeSession", hideTooltip); - } - - function GutterTooltip(parentNode) { - Tooltip.call(this, parentNode); - } - - oop.inherits(GutterTooltip, Tooltip); - - (function(){ - this.setPosition = function(x, y) { - var windowWidth = window.innerWidth || document.documentElement.clientWidth; - var windowHeight = window.innerHeight || document.documentElement.clientHeight; - var width = this.getWidth(); - var height = this.getHeight(); - x += 15; - y += 15; - if (x + width > windowWidth) { - x -= (x + width) - windowWidth; - } - if (y + height > windowHeight) { - y -= 20 + height; - } - Tooltip.prototype.setPosition.call(this, x, y); - }; - - }).call(GutterTooltip.prototype); - - - - exports.GutterHandler = GutterHandler; - - }); - - ace.define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) { - "use strict"; - - var event = acequire("../lib/event"); - var useragent = acequire("../lib/useragent"); - var MouseEvent = exports.MouseEvent = function(domEvent, editor) { - this.domEvent = domEvent; - this.editor = editor; - - this.x = this.clientX = domEvent.clientX; - this.y = this.clientY = domEvent.clientY; - - this.$pos = null; - this.$inSelection = null; - - this.propagationStopped = false; - this.defaultPrevented = false; - }; - - (function() { - - this.stopPropagation = function() { - event.stopPropagation(this.domEvent); - this.propagationStopped = true; - }; - - this.preventDefault = function() { - event.preventDefault(this.domEvent); - this.defaultPrevented = true; - }; - - this.stop = function() { - this.stopPropagation(); - this.preventDefault(); - }; - this.getDocumentPosition = function() { - if (this.$pos) - return this.$pos; - - this.$pos = this.editor.renderer.screenToTextCoordinates(this.clientX, this.clientY); - return this.$pos; - }; - this.inSelection = function() { - if (this.$inSelection !== null) - return this.$inSelection; - - var editor = this.editor; - - - var selectionRange = editor.getSelectionRange(); - if (selectionRange.isEmpty()) - this.$inSelection = false; - else { - var pos = this.getDocumentPosition(); - this.$inSelection = selectionRange.contains(pos.row, pos.column); - } - - return this.$inSelection; - }; - this.getButton = function() { - return event.getButton(this.domEvent); - }; - this.getShiftKey = function() { - return this.domEvent.shiftKey; - }; - - this.getAccelKey = useragent.isMac - ? function() { return this.domEvent.metaKey; } - : function() { return this.domEvent.ctrlKey; }; - - }).call(MouseEvent.prototype); - - }); - - ace.define("ace/mouse/dragdrop_handler",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) { - "use strict"; - - var dom = acequire("../lib/dom"); - var event = acequire("../lib/event"); - var useragent = acequire("../lib/useragent"); - - var AUTOSCROLL_DELAY = 200; - var SCROLL_CURSOR_DELAY = 200; - var SCROLL_CURSOR_HYSTERESIS = 5; - - function DragdropHandler(mouseHandler) { - - var editor = mouseHandler.editor; - - var blankImage = dom.createElement("img"); - blankImage.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; - if (useragent.isOpera) - blankImage.style.cssText = "width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;"; - - var exports = ["dragWait", "dragWaitEnd", "startDrag", "dragReadyEnd", "onMouseDrag"]; - - exports.forEach(function(x) { - mouseHandler[x] = this[x]; - }, this); - editor.addEventListener("mousedown", this.onMouseDown.bind(mouseHandler)); - - - var mouseTarget = editor.container; - var dragSelectionMarker, x, y; - var timerId, range; - var dragCursor, counter = 0; - var dragOperation; - var isInternal; - var autoScrollStartTime; - var cursorMovedTime; - var cursorPointOnCaretMoved; - - this.onDragStart = function(e) { - if (this.cancelDrag || !mouseTarget.draggable) { - var self = this; - setTimeout(function(){ - self.startSelect(); - self.captureMouse(e); - }, 0); - return e.preventDefault(); - } - range = editor.getSelectionRange(); - - var dataTransfer = e.dataTransfer; - dataTransfer.effectAllowed = editor.getReadOnly() ? "copy" : "copyMove"; - if (useragent.isOpera) { - editor.container.appendChild(blankImage); - blankImage.scrollTop = 0; - } - dataTransfer.setDragImage && dataTransfer.setDragImage(blankImage, 0, 0); - if (useragent.isOpera) { - editor.container.removeChild(blankImage); - } - dataTransfer.clearData(); - dataTransfer.setData("Text", editor.session.getTextRange()); - - isInternal = true; - this.setState("drag"); - }; - - this.onDragEnd = function(e) { - mouseTarget.draggable = false; - isInternal = false; - this.setState(null); - if (!editor.getReadOnly()) { - var dropEffect = e.dataTransfer.dropEffect; - if (!dragOperation && dropEffect == "move") - editor.session.remove(editor.getSelectionRange()); - editor.renderer.$cursorLayer.setBlinking(true); - } - this.editor.unsetStyle("ace_dragging"); - this.editor.renderer.setCursorStyle(""); - }; - - this.onDragEnter = function(e) { - if (editor.getReadOnly() || !canAccept(e.dataTransfer)) - return; - x = e.clientX; - y = e.clientY; - if (!dragSelectionMarker) - addDragMarker(); - counter++; - e.dataTransfer.dropEffect = dragOperation = getDropEffect(e); - return event.preventDefault(e); - }; - - this.onDragOver = function(e) { - if (editor.getReadOnly() || !canAccept(e.dataTransfer)) - return; - x = e.clientX; - y = e.clientY; - if (!dragSelectionMarker) { - addDragMarker(); - counter++; - } - if (onMouseMoveTimer !== null) - onMouseMoveTimer = null; - - e.dataTransfer.dropEffect = dragOperation = getDropEffect(e); - return event.preventDefault(e); - }; - - this.onDragLeave = function(e) { - counter--; - if (counter <= 0 && dragSelectionMarker) { - clearDragMarker(); - dragOperation = null; - return event.preventDefault(e); - } - }; - - this.onDrop = function(e) { - if (!dragCursor) - return; - var dataTransfer = e.dataTransfer; - if (isInternal) { - switch (dragOperation) { - case "move": - if (range.contains(dragCursor.row, dragCursor.column)) { - range = { - start: dragCursor, - end: dragCursor - }; - } else { - range = editor.moveText(range, dragCursor); - } - break; - case "copy": - range = editor.moveText(range, dragCursor, true); - break; - } - } else { - var dropData = dataTransfer.getData('Text'); - range = { - start: dragCursor, - end: editor.session.insert(dragCursor, dropData) - }; - editor.focus(); - dragOperation = null; - } - clearDragMarker(); - return event.preventDefault(e); - }; - - event.addListener(mouseTarget, "dragstart", this.onDragStart.bind(mouseHandler)); - event.addListener(mouseTarget, "dragend", this.onDragEnd.bind(mouseHandler)); - event.addListener(mouseTarget, "dragenter", this.onDragEnter.bind(mouseHandler)); - event.addListener(mouseTarget, "dragover", this.onDragOver.bind(mouseHandler)); - event.addListener(mouseTarget, "dragleave", this.onDragLeave.bind(mouseHandler)); - event.addListener(mouseTarget, "drop", this.onDrop.bind(mouseHandler)); - - function scrollCursorIntoView(cursor, prevCursor) { - var now = Date.now(); - var vMovement = !prevCursor || cursor.row != prevCursor.row; - var hMovement = !prevCursor || cursor.column != prevCursor.column; - if (!cursorMovedTime || vMovement || hMovement) { - editor.$blockScrolling += 1; - editor.moveCursorToPosition(cursor); - editor.$blockScrolling -= 1; - cursorMovedTime = now; - cursorPointOnCaretMoved = {x: x, y: y}; - } else { - var distance = calcDistance(cursorPointOnCaretMoved.x, cursorPointOnCaretMoved.y, x, y); - if (distance > SCROLL_CURSOR_HYSTERESIS) { - cursorMovedTime = null; - } else if (now - cursorMovedTime >= SCROLL_CURSOR_DELAY) { - editor.renderer.scrollCursorIntoView(); - cursorMovedTime = null; - } - } - } - - function autoScroll(cursor, prevCursor) { - var now = Date.now(); - var lineHeight = editor.renderer.layerConfig.lineHeight; - var characterWidth = editor.renderer.layerConfig.characterWidth; - var editorRect = editor.renderer.scroller.getBoundingClientRect(); - var offsets = { - x: { - left: x - editorRect.left, - right: editorRect.right - x - }, - y: { - top: y - editorRect.top, - bottom: editorRect.bottom - y - } - }; - var nearestXOffset = Math.min(offsets.x.left, offsets.x.right); - var nearestYOffset = Math.min(offsets.y.top, offsets.y.bottom); - var scrollCursor = {row: cursor.row, column: cursor.column}; - if (nearestXOffset / characterWidth <= 2) { - scrollCursor.column += (offsets.x.left < offsets.x.right ? -3 : +2); - } - if (nearestYOffset / lineHeight <= 1) { - scrollCursor.row += (offsets.y.top < offsets.y.bottom ? -1 : +1); - } - var vScroll = cursor.row != scrollCursor.row; - var hScroll = cursor.column != scrollCursor.column; - var vMovement = !prevCursor || cursor.row != prevCursor.row; - if (vScroll || (hScroll && !vMovement)) { - if (!autoScrollStartTime) - autoScrollStartTime = now; - else if (now - autoScrollStartTime >= AUTOSCROLL_DELAY) - editor.renderer.scrollCursorIntoView(scrollCursor); - } else { - autoScrollStartTime = null; - } - } - - function onDragInterval() { - var prevCursor = dragCursor; - dragCursor = editor.renderer.screenToTextCoordinates(x, y); - scrollCursorIntoView(dragCursor, prevCursor); - autoScroll(dragCursor, prevCursor); - } - - function addDragMarker() { - range = editor.selection.toOrientedRange(); - dragSelectionMarker = editor.session.addMarker(range, "ace_selection", editor.getSelectionStyle()); - editor.clearSelection(); - if (editor.isFocused()) - editor.renderer.$cursorLayer.setBlinking(false); - clearInterval(timerId); - onDragInterval(); - timerId = setInterval(onDragInterval, 20); - counter = 0; - event.addListener(document, "mousemove", onMouseMove); - } - - function clearDragMarker() { - clearInterval(timerId); - editor.session.removeMarker(dragSelectionMarker); - dragSelectionMarker = null; - editor.$blockScrolling += 1; - editor.selection.fromOrientedRange(range); - editor.$blockScrolling -= 1; - if (editor.isFocused() && !isInternal) - editor.renderer.$cursorLayer.setBlinking(!editor.getReadOnly()); - range = null; - dragCursor = null; - counter = 0; - autoScrollStartTime = null; - cursorMovedTime = null; - event.removeListener(document, "mousemove", onMouseMove); - } - var onMouseMoveTimer = null; - function onMouseMove() { - if (onMouseMoveTimer == null) { - onMouseMoveTimer = setTimeout(function() { - if (onMouseMoveTimer != null && dragSelectionMarker) - clearDragMarker(); - }, 20); - } - } - - function canAccept(dataTransfer) { - var types = dataTransfer.types; - return !types || Array.prototype.some.call(types, function(type) { - return type == 'text/plain' || type == 'Text'; - }); - } - - function getDropEffect(e) { - var copyAllowed = ['copy', 'copymove', 'all', 'uninitialized']; - var moveAllowed = ['move', 'copymove', 'linkmove', 'all', 'uninitialized']; - - var copyModifierState = useragent.isMac ? e.altKey : e.ctrlKey; - var effectAllowed = "uninitialized"; - try { - effectAllowed = e.dataTransfer.effectAllowed.toLowerCase(); - } catch (e) {} - var dropEffect = "none"; - - if (copyModifierState && copyAllowed.indexOf(effectAllowed) >= 0) - dropEffect = "copy"; - else if (moveAllowed.indexOf(effectAllowed) >= 0) - dropEffect = "move"; - else if (copyAllowed.indexOf(effectAllowed) >= 0) - dropEffect = "copy"; - - return dropEffect; - } - } - - (function() { - - this.dragWait = function() { - var interval = Date.now() - this.mousedownEvent.time; - if (interval > this.editor.getDragDelay()) - this.startDrag(); - }; - - this.dragWaitEnd = function() { - var target = this.editor.container; - target.draggable = false; - this.startSelect(this.mousedownEvent.getDocumentPosition()); - this.selectEnd(); - }; - - this.dragReadyEnd = function(e) { - this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly()); - this.editor.unsetStyle("ace_dragging"); - this.editor.renderer.setCursorStyle(""); - this.dragWaitEnd(); - }; - - this.startDrag = function(){ - this.cancelDrag = false; - var editor = this.editor; - var target = editor.container; - target.draggable = true; - editor.renderer.$cursorLayer.setBlinking(false); - editor.setStyle("ace_dragging"); - var cursorStyle = useragent.isWin ? "default" : "move"; - editor.renderer.setCursorStyle(cursorStyle); - this.setState("dragReady"); - }; - - this.onMouseDrag = function(e) { - var target = this.editor.container; - if (useragent.isIE && this.state == "dragReady") { - var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); - if (distance > 3) - target.dragDrop(); - } - if (this.state === "dragWait") { - var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); - if (distance > 0) { - target.draggable = false; - this.startSelect(this.mousedownEvent.getDocumentPosition()); - } - } - }; - - this.onMouseDown = function(e) { - if (!this.$dragEnabled) - return; - this.mousedownEvent = e; - var editor = this.editor; - - var inSelection = e.inSelection(); - var button = e.getButton(); - var clickCount = e.domEvent.detail || 1; - if (clickCount === 1 && button === 0 && inSelection) { - if (e.editor.inMultiSelectMode && (e.getAccelKey() || e.getShiftKey())) - return; - this.mousedownEvent.time = Date.now(); - var eventTarget = e.domEvent.target || e.domEvent.srcElement; - if ("unselectable" in eventTarget) - eventTarget.unselectable = "on"; - if (editor.getDragDelay()) { - if (useragent.isWebKit) { - this.cancelDrag = true; - var mouseTarget = editor.container; - mouseTarget.draggable = true; - } - this.setState("dragWait"); - } else { - this.startDrag(); - } - this.captureMouse(e, this.onMouseDrag.bind(this)); - e.defaultPrevented = true; - } - }; - - }).call(DragdropHandler.prototype); - - - function calcDistance(ax, ay, bx, by) { - return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2)); - } - - exports.DragdropHandler = DragdropHandler; - - }); - - ace.define("ace/lib/net",["require","exports","module","ace/lib/dom"], function(acequire, exports, module) { - "use strict"; - var dom = acequire("./dom"); - - exports.get = function (url, callback) { - var xhr = new XMLHttpRequest(); - xhr.open('GET', url, true); - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - callback(xhr.responseText); - } - }; - xhr.send(null); - }; - - exports.loadScript = function(path, callback) { - var head = dom.getDocumentHead(); - var s = document.createElement('script'); - - s.src = path; - head.appendChild(s); - - s.onload = s.onreadystatechange = function(_, isAbort) { - if (isAbort || !s.readyState || s.readyState == "loaded" || s.readyState == "complete") { - s = s.onload = s.onreadystatechange = null; - if (!isAbort) - callback(); - } - }; - }; - exports.qualifyURL = function(url) { - var a = document.createElement('a'); - a.href = url; - return a.href; - }; - - }); - - ace.define("ace/lib/event_emitter",["require","exports","module"], function(acequire, exports, module) { - "use strict"; - - var EventEmitter = {}; - var stopPropagation = function() { this.propagationStopped = true; }; - var preventDefault = function() { this.defaultPrevented = true; }; - - EventEmitter._emit = - EventEmitter._dispatchEvent = function(eventName, e) { - this._eventRegistry || (this._eventRegistry = {}); - this._defaultHandlers || (this._defaultHandlers = {}); - - var listeners = this._eventRegistry[eventName] || []; - var defaultHandler = this._defaultHandlers[eventName]; - if (!listeners.length && !defaultHandler) - return; - - if (typeof e != "object" || !e) - e = {}; - - if (!e.type) - e.type = eventName; - if (!e.stopPropagation) - e.stopPropagation = stopPropagation; - if (!e.preventDefault) - e.preventDefault = preventDefault; - - listeners = listeners.slice(); - for (var i=0; i 1) - base = parts[parts.length - 2]; - var path = options[component + "Path"]; - if (path == null) { - path = options.basePath; - } else if (sep == "/") { - component = sep = ""; - } - if (path && path.slice(-1) != "/") - path += "/"; - return path + component + sep + base + this.get("suffix"); - }; - - exports.setModuleUrl = function(name, subst) { - return options.$moduleUrls[name] = subst; - }; - - exports.$loading = {}; - exports.loadModule = function(moduleName, onLoad) { - var module, moduleType; - if (Array.isArray(moduleName)) { - moduleType = moduleName[0]; - moduleName = moduleName[1]; - } - - try { - module = acequire(moduleName); - } catch (e) {} - if (module && !exports.$loading[moduleName]) - return onLoad && onLoad(module); - - if (!exports.$loading[moduleName]) - exports.$loading[moduleName] = []; - - exports.$loading[moduleName].push(onLoad); - - if (exports.$loading[moduleName].length > 1) - return; - - var afterLoad = function() { - acequire([moduleName], function(module) { - exports._emit("load.module", {name: moduleName, module: module}); - var listeners = exports.$loading[moduleName]; - exports.$loading[moduleName] = null; - listeners.forEach(function(onLoad) { - onLoad && onLoad(module); - }); - }); - }; - - if (!exports.get("packaged")) - return afterLoad(); - net.loadScript(exports.moduleUrl(moduleName, moduleType), afterLoad); - }; - init(true);function init(packaged) { - - if (!global || !global.document) - return; - - options.packaged = packaged || acequire.packaged || module.packaged || (global.define && __webpack_require__(67).packaged); - - var scriptOptions = {}; - var scriptUrl = ""; - var currentScript = (document.currentScript || document._currentScript ); // native or polyfill - var currentDocument = currentScript && currentScript.ownerDocument || document; - - var scripts = currentDocument.getElementsByTagName("script"); - for (var i=0; i 0){ - if (action == 0x10){ - for(i = condPos; i < ix; i++){ - levels[i] = 1; - } - condPos = -1; - } else { - condPos = -1; - } - } - cond = impTab[newState][6]; - if (cond){ - if(condPos == -1){ - condPos = ix; - } - }else{ - if (condPos > -1){ - for(i = condPos; i < ix; i++){ - levels[i] = newLevel; - } - condPos = -1; - } - } - if (charTypes[ix] == B){ - levels[ix] = 0; - } - hiLevel |= newLevel; - } - if (hasUBAT_S){ - for(i = 0; i < len; i++){ - if(charTypes[i] == S){ - levels[i] = dir; - for(var j = i - 1; j >= 0; j--){ - if(charTypes[j] == WS){ - levels[j] = dir; - }else{ - break; - } - } - } - } - } - } - - function _invertLevel(lev, levels, _array) { - if (hiLevel < lev){ - return; - } - if (lev == 1 && dir == RTL && !hasUBAT_B){ - _array.reverse(); - return; - } - var len = _array.length, start = 0, end, lo, hi, tmp; - while(start < len){ - if (levels[start] >= lev){ - end = start + 1; - while(end < len && levels[end] >= lev){ - end++; - } - for(lo = start, hi = end - 1 ; lo < hi; lo++, hi--){ - tmp = _array[lo]; - _array[lo] = _array[hi]; - _array[hi] = tmp; - } - start = end; - } - start++; - } - } - - function _getCharClass(chars, types, classes, ix) { - var cType = types[ix], wType, nType, len, i; - switch(cType){ - case L: - case R: - lastArabic = false; - case ON: - case AN: - return cType; - case EN: - return lastArabic ? AN : EN; - case AL: - lastArabic = true; - hasUBAT_AL = true; - return R; - case WS: - return ON; - case CS: - if (ix < 1 || (ix + 1) >= types.length || - ((wType = classes[ix - 1]) != EN && wType != AN) || - ((nType = types[ix + 1]) != EN && nType != AN)){ - return ON; - } - if (lastArabic){nType = AN;} - return nType == wType ? nType : ON; - case ES: - wType = ix > 0 ? classes[ix - 1] : B; - if (wType == EN && (ix + 1) < types.length && types[ix + 1] == EN){ - return EN; - } - return ON; - case ET: - if (ix > 0 && classes[ix - 1] == EN){ - return EN; - } - if (lastArabic){ - return ON; - } - i = ix + 1; - len = types.length; - while (i < len && types[i] == ET){ - i++; - } - if (i < len && types[i] == EN){ - return EN; - } - return ON; - case NSM: - len = types.length; - i = ix + 1; - while (i < len && types[i] == NSM){ - i++; - } - if (i < len){ - var c = chars[ix], rtlCandidate = (c >= 0x0591 && c <= 0x08FF) || c == 0xFB1E; - - wType = types[i]; - if (rtlCandidate && (wType == R || wType == AL)){ - return R; - } - } - - if (ix < 1 || (wType = types[ix - 1]) == B){ - return ON; - } - return classes[ix - 1]; - case B: - lastArabic = false; - hasUBAT_B = true; - return dir; - case S: - hasUBAT_S = true; - return ON; - case LRE: - case RLE: - case LRO: - case RLO: - case PDF: - lastArabic = false; - case BN: - return ON; - } - } - - function _getCharacterType( ch ) { - var uc = ch.charCodeAt(0), hi = uc >> 8; - - if (hi == 0) { - return ((uc > 0x00BF) ? L : UnicodeTBL00[uc]); - } else if (hi == 5) { - return (/[\u0591-\u05f4]/.test(ch) ? R : L); - } else if (hi == 6) { - if (/[\u0610-\u061a\u064b-\u065f\u06d6-\u06e4\u06e7-\u06ed]/.test(ch)) - return NSM; - else if (/[\u0660-\u0669\u066b-\u066c]/.test(ch)) - return AN; - else if (uc == 0x066A) - return ET; - else if (/[\u06f0-\u06f9]/.test(ch)) - return EN; - else - return AL; - } else if (hi == 0x20 && uc <= 0x205F) { - return UnicodeTBL20[uc & 0xFF]; - } else if (hi == 0xFE) { - return (uc >= 0xFE70 ? AL : ON); - } - return ON; - } - - function _isArabicDiacritics( ch ) { - return (ch >= '\u064b' && ch <= '\u0655'); - } - exports.L = L; - exports.R = R; - exports.EN = EN; - exports.ON_R = 3; - exports.AN = 4; - exports.R_H = 5; - exports.B = 6; - - exports.DOT = "\xB7"; - exports.doBidiReorder = function(text, textCharTypes, isRtl) { - if (text.length < 2) - return {}; - - var chars = text.split(""), logicalFromVisual = new Array(chars.length), - bidiLevels = new Array(chars.length), levels = []; - - dir = isRtl ? RTL : LTR; - - _computeLevels(chars, levels, chars.length, textCharTypes); - - for (var i = 0; i < logicalFromVisual.length; logicalFromVisual[i] = i, i++); - - _invertLevel(2, levels, logicalFromVisual); - _invertLevel(1, levels, logicalFromVisual); - - for (var i = 0; i < logicalFromVisual.length - 1; i++) { //fix levels to reflect character width - if (textCharTypes[i] === AN) { - levels[i] = exports.AN; - } else if (levels[i] === R && ((textCharTypes[i] > AL && textCharTypes[i] < LRE) - || textCharTypes[i] === ON || textCharTypes[i] === BN)) { - levels[i] = exports.ON_R; - } else if ((i > 0 && chars[i - 1] === '\u0644') && /\u0622|\u0623|\u0625|\u0627/.test(chars[i])) { - levels[i - 1] = levels[i] = exports.R_H; - i++; - } - } - if (chars[chars.length - 1] === exports.DOT) - levels[chars.length - 1] = exports.B; - - for (var i = 0; i < logicalFromVisual.length; i++) { - bidiLevels[i] = levels[logicalFromVisual[i]]; - } - - return {'logicalFromVisual': logicalFromVisual, 'bidiLevels': bidiLevels}; - }; - exports.hasBidiCharacters = function(text, textCharTypes){ - var ret = false; - for (var i = 0; i < text.length; i++){ - textCharTypes[i] = _getCharacterType(text.charAt(i)); - if (!ret && (textCharTypes[i] == R || textCharTypes[i] == AL)) - ret = true; - } - return ret; - }; - exports.getVisualFromLogicalIdx = function(logIdx, rowMap) { - for (var i = 0; i < rowMap.logicalFromVisual.length; i++) { - if (rowMap.logicalFromVisual[i] == logIdx) - return i; - } - return 0; - }; - - }); - - ace.define("ace/bidihandler",["require","exports","module","ace/lib/bidiutil","ace/lib/lang","ace/lib/useragent"], function(acequire, exports, module) { - "use strict"; - - var bidiUtil = acequire("./lib/bidiutil"); - var lang = acequire("./lib/lang"); - var useragent = acequire("./lib/useragent"); - var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; - var BidiHandler = function(session) { - this.session = session; - this.bidiMap = {}; - this.currentRow = null; - this.bidiUtil = bidiUtil; - this.charWidths = []; - this.EOL = "\xAC"; - this.showInvisibles = true; - this.isRtlDir = false; - this.line = ""; - this.wrapIndent = 0; - this.isLastRow = false; - this.EOF = "\xB6"; - this.seenBidi = false; - }; - - (function() { - this.isBidiRow = function(screenRow, docRow, splitIndex) { - if (!this.seenBidi) - return false; - if (screenRow !== this.currentRow) { - this.currentRow = screenRow; - this.updateRowLine(docRow, splitIndex); - this.updateBidiMap(); - } - return this.bidiMap.bidiLevels; - }; - - this.onChange = function(delta) { - if (!this.seenBidi) { - if (delta.action == "insert" && bidiRE.test(delta.lines.join("\n"))) { - this.seenBidi = true; - this.currentRow = null; - } - } - else { - this.currentRow = null; - } - }; - - this.getDocumentRow = function() { - var docRow = 0; - var rowCache = this.session.$screenRowCache; - if (rowCache.length) { - var index = this.session.$getRowCacheIndex(rowCache, this.currentRow); - if (index >= 0) - docRow = this.session.$docRowCache[index]; - } - - return docRow; - }; - - this.getSplitIndex = function() { - var splitIndex = 0; - var rowCache = this.session.$screenRowCache; - if (rowCache.length) { - var currentIndex, prevIndex = this.session.$getRowCacheIndex(rowCache, this.currentRow); - while (this.currentRow - splitIndex > 0) { - currentIndex = this.session.$getRowCacheIndex(rowCache, this.currentRow - splitIndex - 1); - if (currentIndex !== prevIndex) - break; - - prevIndex = currentIndex; - splitIndex++; - } - } - - return splitIndex; - }; - - this.updateRowLine = function(docRow, splitIndex) { - if (docRow === undefined) - docRow = this.getDocumentRow(); - - this.wrapIndent = 0; - this.isLastRow = (docRow === this.session.getLength() - 1); - this.line = this.session.getLine(docRow); - if (this.session.$useWrapMode) { - var splits = this.session.$wrapData[docRow]; - if (splits) { - if (splitIndex === undefined) - splitIndex = this.getSplitIndex(); - - if(splitIndex > 0 && splits.length) { - this.wrapIndent = splits.indent; - this.line = (splitIndex < splits.length) ? - this.line.substring(splits[splitIndex - 1], splits[splits.length - 1]) : - this.line.substring(splits[splits.length - 1]); - } else { - this.line = this.line.substring(0, splits[splitIndex]); - } - } - } - var session = this.session, shift = 0, size; - this.line = this.line.replace(/\t|[\u1100-\u2029, \u202F-\uFFE6]/g, function(ch, i){ - if (ch === '\t' || session.isFullWidth(ch.charCodeAt(0))) { - size = (ch === '\t') ? session.getScreenTabSize(i + shift) : 2; - shift += size - 1; - return lang.stringRepeat(bidiUtil.DOT, size); - } - return ch; - }); - }; - - this.updateBidiMap = function() { - var textCharTypes = [], endOfLine = this.isLastRow ? this.EOF : this.EOL; - var line = this.line + (this.showInvisibles ? endOfLine : bidiUtil.DOT); - if (bidiUtil.hasBidiCharacters(line, textCharTypes)) { - this.bidiMap = bidiUtil.doBidiReorder(line, textCharTypes, this.isRtlDir); - } else { - this.bidiMap = {}; - } - }; - this.markAsDirty = function() { - this.currentRow = null; - }; - this.updateCharacterWidths = function(fontMetrics) { - if (!this.seenBidi) - return; - if (this.characterWidth === fontMetrics.$characterSize.width) - return; - - var characterWidth = this.characterWidth = fontMetrics.$characterSize.width; - var bidiCharWidth = fontMetrics.$measureCharWidth("\u05d4"); - - this.charWidths[bidiUtil.L] = this.charWidths[bidiUtil.EN] = this.charWidths[bidiUtil.ON_R] = characterWidth; - this.charWidths[bidiUtil.R] = this.charWidths[bidiUtil.AN] = bidiCharWidth; - this.charWidths[bidiUtil.R_H] = useragent.isChrome ? bidiCharWidth : bidiCharWidth * 0.45; - this.charWidths[bidiUtil.B] = 0; - - this.currentRow = null; - }; - - this.getShowInvisibles = function() { - return this.showInvisibles; - }; - - this.setShowInvisibles = function(showInvisibles) { - this.showInvisibles = showInvisibles; - this.currentRow = null; - }; - - this.setEolChar = function(eolChar) { - this.EOL = eolChar; - }; - - this.setTextDir = function(isRtlDir) { - this.isRtlDir = isRtlDir; - }; - this.getPosLeft = function(col) { - col -= this.wrapIndent; - var visualIdx = bidiUtil.getVisualFromLogicalIdx(col > 0 ? col - 1 : 0, this.bidiMap), - levels = this.bidiMap.bidiLevels, left = 0; - - if (col === 0 && levels[visualIdx] % 2 !== 0) - visualIdx++; - - for (var i = 0; i < visualIdx; i++) { - left += this.charWidths[levels[i]]; - } - - if (col !== 0 && levels[visualIdx] % 2 === 0) - left += this.charWidths[levels[visualIdx]]; - - if (this.wrapIndent) - left += this.wrapIndent * this.charWidths[bidiUtil.L]; - - return left; - }; - this.getSelections = function(startCol, endCol) { - var map = this.bidiMap, levels = map.bidiLevels, level, offset = this.wrapIndent * this.charWidths[bidiUtil.L], selections = [], - selColMin = Math.min(startCol, endCol) - this.wrapIndent, selColMax = Math.max(startCol, endCol) - this.wrapIndent, - isSelected = false, isSelectedPrev = false, selectionStart = 0; - - for (var logIdx, visIdx = 0; visIdx < levels.length; visIdx++) { - logIdx = map.logicalFromVisual[visIdx]; - level = levels[visIdx]; - isSelected = (logIdx >= selColMin) && (logIdx < selColMax); - if (isSelected && !isSelectedPrev) { - selectionStart = offset; - } else if (!isSelected && isSelectedPrev) { - selections.push({left: selectionStart, width: offset - selectionStart}); - } - offset += this.charWidths[level]; - isSelectedPrev = isSelected; - } - - if (isSelected && (visIdx === levels.length)) { - selections.push({left: selectionStart, width: offset - selectionStart}); - } - - return selections; - }; - this.offsetToCol = function(posX) { - var logicalIdx = 0, posX = Math.max(posX, 0), - offset = 0, visualIdx = 0, levels = this.bidiMap.bidiLevels, - charWidth = this.charWidths[levels[visualIdx]]; - - if (this.wrapIndent) { - posX -= this.wrapIndent * this.charWidths[bidiUtil.L]; - } - - while(posX > offset + charWidth/2) { - offset += charWidth; - if(visualIdx === levels.length - 1) { - charWidth = 0; - break; - } - charWidth = this.charWidths[levels[++visualIdx]]; - } - - if (visualIdx > 0 && (levels[visualIdx - 1] % 2 !== 0) && (levels[visualIdx] % 2 === 0)){ - if(posX < offset) - visualIdx--; - logicalIdx = this.bidiMap.logicalFromVisual[visualIdx]; - - } else if (visualIdx > 0 && (levels[visualIdx - 1] % 2 === 0) && (levels[visualIdx] % 2 !== 0)){ - logicalIdx = 1 + ((posX > offset) ? this.bidiMap.logicalFromVisual[visualIdx] - : this.bidiMap.logicalFromVisual[visualIdx - 1]); - - } else if ((this.isRtlDir && visualIdx === levels.length - 1 && charWidth === 0 && (levels[visualIdx - 1] % 2 === 0)) - || (!this.isRtlDir && visualIdx === 0 && (levels[visualIdx] % 2 !== 0))){ - logicalIdx = 1 + this.bidiMap.logicalFromVisual[visualIdx]; - } else { - if (visualIdx > 0 && (levels[visualIdx - 1] % 2 !== 0) && charWidth !== 0) - visualIdx--; - logicalIdx = this.bidiMap.logicalFromVisual[visualIdx]; - } - - return (logicalIdx + this.wrapIndent); - }; - - }).call(BidiHandler.prototype); - - exports.BidiHandler = BidiHandler; - }); - - ace.define("ace/range",["require","exports","module"], function(acequire, exports, module) { - "use strict"; - var comparePoints = function(p1, p2) { - return p1.row - p2.row || p1.column - p2.column; - }; - var Range = function(startRow, startColumn, endRow, endColumn) { - this.start = { - row: startRow, - column: startColumn - }; - - this.end = { - row: endRow, - column: endColumn - }; - }; - - (function() { - this.isEqual = function(range) { - return this.start.row === range.start.row && - this.end.row === range.end.row && - this.start.column === range.start.column && - this.end.column === range.end.column; - }; - this.toString = function() { - return ("Range: [" + this.start.row + "/" + this.start.column + - "] -> [" + this.end.row + "/" + this.end.column + "]"); - }; - - this.contains = function(row, column) { - return this.compare(row, column) == 0; - }; - this.compareRange = function(range) { - var cmp, - end = range.end, - start = range.start; - - cmp = this.compare(end.row, end.column); - if (cmp == 1) { - cmp = this.compare(start.row, start.column); - if (cmp == 1) { - return 2; - } else if (cmp == 0) { - return 1; - } else { - return 0; - } - } else if (cmp == -1) { - return -2; - } else { - cmp = this.compare(start.row, start.column); - if (cmp == -1) { - return -1; - } else if (cmp == 1) { - return 42; - } else { - return 0; - } - } - }; - this.comparePoint = function(p) { - return this.compare(p.row, p.column); - }; - this.containsRange = function(range) { - return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0; - }; - this.intersects = function(range) { - var cmp = this.compareRange(range); - return (cmp == -1 || cmp == 0 || cmp == 1); - }; - this.isEnd = function(row, column) { - return this.end.row == row && this.end.column == column; - }; - this.isStart = function(row, column) { - return this.start.row == row && this.start.column == column; - }; - this.setStart = function(row, column) { - if (typeof row == "object") { - this.start.column = row.column; - this.start.row = row.row; - } else { - this.start.row = row; - this.start.column = column; - } - }; - this.setEnd = function(row, column) { - if (typeof row == "object") { - this.end.column = row.column; - this.end.row = row.row; - } else { - this.end.row = row; - this.end.column = column; - } - }; - this.inside = function(row, column) { - if (this.compare(row, column) == 0) { - if (this.isEnd(row, column) || this.isStart(row, column)) { - return false; - } else { - return true; - } - } - return false; - }; - this.insideStart = function(row, column) { - if (this.compare(row, column) == 0) { - if (this.isEnd(row, column)) { - return false; - } else { - return true; - } - } - return false; - }; - this.insideEnd = function(row, column) { - if (this.compare(row, column) == 0) { - if (this.isStart(row, column)) { - return false; - } else { - return true; - } - } - return false; - }; - this.compare = function(row, column) { - if (!this.isMultiLine()) { - if (row === this.start.row) { - return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0); - } - } - - if (row < this.start.row) - return -1; - - if (row > this.end.row) - return 1; - - if (this.start.row === row) - return column >= this.start.column ? 0 : -1; - - if (this.end.row === row) - return column <= this.end.column ? 0 : 1; - - return 0; - }; - this.compareStart = function(row, column) { - if (this.start.row == row && this.start.column == column) { - return -1; - } else { - return this.compare(row, column); - } - }; - this.compareEnd = function(row, column) { - if (this.end.row == row && this.end.column == column) { - return 1; - } else { - return this.compare(row, column); - } - }; - this.compareInside = function(row, column) { - if (this.end.row == row && this.end.column == column) { - return 1; - } else if (this.start.row == row && this.start.column == column) { - return -1; - } else { - return this.compare(row, column); - } - }; - this.clipRows = function(firstRow, lastRow) { - if (this.end.row > lastRow) - var end = {row: lastRow + 1, column: 0}; - else if (this.end.row < firstRow) - var end = {row: firstRow, column: 0}; - - if (this.start.row > lastRow) - var start = {row: lastRow + 1, column: 0}; - else if (this.start.row < firstRow) - var start = {row: firstRow, column: 0}; - - return Range.fromPoints(start || this.start, end || this.end); - }; - this.extend = function(row, column) { - var cmp = this.compare(row, column); - - if (cmp == 0) - return this; - else if (cmp == -1) - var start = {row: row, column: column}; - else - var end = {row: row, column: column}; - - return Range.fromPoints(start || this.start, end || this.end); - }; - - this.isEmpty = function() { - return (this.start.row === this.end.row && this.start.column === this.end.column); - }; - this.isMultiLine = function() { - return (this.start.row !== this.end.row); - }; - this.clone = function() { - return Range.fromPoints(this.start, this.end); - }; - this.collapseRows = function() { - if (this.end.column == 0) - return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0); - else - return new Range(this.start.row, 0, this.end.row, 0); - }; - this.toScreenRange = function(session) { - var screenPosStart = session.documentToScreenPosition(this.start); - var screenPosEnd = session.documentToScreenPosition(this.end); - - return new Range( - screenPosStart.row, screenPosStart.column, - screenPosEnd.row, screenPosEnd.column - ); - }; - this.moveBy = function(row, column) { - this.start.row += row; - this.start.column += column; - this.end.row += row; - this.end.column += column; - }; - - }).call(Range.prototype); - Range.fromPoints = function(start, end) { - return new Range(start.row, start.column, end.row, end.column); - }; - Range.comparePoints = comparePoints; - - Range.comparePoints = function(p1, p2) { - return p1.row - p2.row || p1.column - p2.column; - }; - - - exports.Range = Range; - }); - - ace.define("ace/selection",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/range"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("./lib/oop"); - var lang = acequire("./lib/lang"); - var EventEmitter = acequire("./lib/event_emitter").EventEmitter; - var Range = acequire("./range").Range; - var Selection = function(session) { - this.session = session; - this.doc = session.getDocument(); - - this.clearSelection(); - this.lead = this.selectionLead = this.doc.createAnchor(0, 0); - this.anchor = this.selectionAnchor = this.doc.createAnchor(0, 0); - - var self = this; - this.lead.on("change", function(e) { - self._emit("changeCursor"); - if (!self.$isEmpty) - self._emit("changeSelection"); - if (!self.$keepDesiredColumnOnChange && e.old.column != e.value.column) - self.$desiredColumn = null; - }); - - this.selectionAnchor.on("change", function() { - if (!self.$isEmpty) - self._emit("changeSelection"); - }); - }; - - (function() { - - oop.implement(this, EventEmitter); - this.isEmpty = function() { - return (this.$isEmpty || ( - this.anchor.row == this.lead.row && - this.anchor.column == this.lead.column - )); - }; - this.isMultiLine = function() { - if (this.isEmpty()) { - return false; - } - - return this.getRange().isMultiLine(); - }; - this.getCursor = function() { - return this.lead.getPosition(); - }; - this.setSelectionAnchor = function(row, column) { - this.anchor.setPosition(row, column); - - if (this.$isEmpty) { - this.$isEmpty = false; - this._emit("changeSelection"); - } - }; - this.getSelectionAnchor = function() { - if (this.$isEmpty) - return this.getSelectionLead(); - else - return this.anchor.getPosition(); - }; - this.getSelectionLead = function() { - return this.lead.getPosition(); - }; - this.shiftSelection = function(columns) { - if (this.$isEmpty) { - this.moveCursorTo(this.lead.row, this.lead.column + columns); - return; - } - - var anchor = this.getSelectionAnchor(); - var lead = this.getSelectionLead(); - - var isBackwards = this.isBackwards(); - - if (!isBackwards || anchor.column !== 0) - this.setSelectionAnchor(anchor.row, anchor.column + columns); - - if (isBackwards || lead.column !== 0) { - this.$moveSelection(function() { - this.moveCursorTo(lead.row, lead.column + columns); - }); - } - }; - this.isBackwards = function() { - var anchor = this.anchor; - var lead = this.lead; - return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column)); - }; - this.getRange = function() { - var anchor = this.anchor; - var lead = this.lead; - - if (this.isEmpty()) - return Range.fromPoints(lead, lead); - - if (this.isBackwards()) { - return Range.fromPoints(lead, anchor); - } - else { - return Range.fromPoints(anchor, lead); - } - }; - this.clearSelection = function() { - if (!this.$isEmpty) { - this.$isEmpty = true; - this._emit("changeSelection"); - } - }; - this.selectAll = function() { - var lastRow = this.doc.getLength() - 1; - this.setSelectionAnchor(0, 0); - this.moveCursorTo(lastRow, this.doc.getLine(lastRow).length); - }; - this.setRange = - this.setSelectionRange = function(range, reverse) { - if (reverse) { - this.setSelectionAnchor(range.end.row, range.end.column); - this.selectTo(range.start.row, range.start.column); - } else { - this.setSelectionAnchor(range.start.row, range.start.column); - this.selectTo(range.end.row, range.end.column); - } - if (this.getRange().isEmpty()) - this.$isEmpty = true; - this.$desiredColumn = null; - }; - - this.$moveSelection = function(mover) { - var lead = this.lead; - if (this.$isEmpty) - this.setSelectionAnchor(lead.row, lead.column); - - mover.call(this); - }; - this.selectTo = function(row, column) { - this.$moveSelection(function() { - this.moveCursorTo(row, column); - }); - }; - this.selectToPosition = function(pos) { - this.$moveSelection(function() { - this.moveCursorToPosition(pos); - }); - }; - this.moveTo = function(row, column) { - this.clearSelection(); - this.moveCursorTo(row, column); - }; - this.moveToPosition = function(pos) { - this.clearSelection(); - this.moveCursorToPosition(pos); - }; - this.selectUp = function() { - this.$moveSelection(this.moveCursorUp); - }; - this.selectDown = function() { - this.$moveSelection(this.moveCursorDown); - }; - this.selectRight = function() { - this.$moveSelection(this.moveCursorRight); - }; - this.selectLeft = function() { - this.$moveSelection(this.moveCursorLeft); - }; - this.selectLineStart = function() { - this.$moveSelection(this.moveCursorLineStart); - }; - this.selectLineEnd = function() { - this.$moveSelection(this.moveCursorLineEnd); - }; - this.selectFileEnd = function() { - this.$moveSelection(this.moveCursorFileEnd); - }; - this.selectFileStart = function() { - this.$moveSelection(this.moveCursorFileStart); - }; - this.selectWordRight = function() { - this.$moveSelection(this.moveCursorWordRight); - }; - this.selectWordLeft = function() { - this.$moveSelection(this.moveCursorWordLeft); - }; - this.getWordRange = function(row, column) { - if (typeof column == "undefined") { - var cursor = row || this.lead; - row = cursor.row; - column = cursor.column; - } - return this.session.getWordRange(row, column); - }; - this.selectWord = function() { - this.setSelectionRange(this.getWordRange()); - }; - this.selectAWord = function() { - var cursor = this.getCursor(); - var range = this.session.getAWordRange(cursor.row, cursor.column); - this.setSelectionRange(range); - }; - - this.getLineRange = function(row, excludeLastChar) { - var rowStart = typeof row == "number" ? row : this.lead.row; - var rowEnd; - - var foldLine = this.session.getFoldLine(rowStart); - if (foldLine) { - rowStart = foldLine.start.row; - rowEnd = foldLine.end.row; - } else { - rowEnd = rowStart; - } - if (excludeLastChar === true) - return new Range(rowStart, 0, rowEnd, this.session.getLine(rowEnd).length); - else - return new Range(rowStart, 0, rowEnd + 1, 0); - }; - this.selectLine = function() { - this.setSelectionRange(this.getLineRange()); - }; - this.moveCursorUp = function() { - this.moveCursorBy(-1, 0); - }; - this.moveCursorDown = function() { - this.moveCursorBy(1, 0); - }; - this.wouldMoveIntoSoftTab = function(cursor, tabSize, direction) { - var start = cursor.column; - var end = cursor.column + tabSize; - - if (direction < 0) { - start = cursor.column - tabSize; - end = cursor.column; - } - return this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(start, end).split(" ").length-1 == tabSize; - }; - this.moveCursorLeft = function() { - var cursor = this.lead.getPosition(), - fold; - - if (fold = this.session.getFoldAt(cursor.row, cursor.column, -1)) { - this.moveCursorTo(fold.start.row, fold.start.column); - } else if (cursor.column === 0) { - if (cursor.row > 0) { - this.moveCursorTo(cursor.row - 1, this.doc.getLine(cursor.row - 1).length); - } - } - else { - var tabSize = this.session.getTabSize(); - if (this.wouldMoveIntoSoftTab(cursor, tabSize, -1) && !this.session.getNavigateWithinSoftTabs()) { - this.moveCursorBy(0, -tabSize); - } else { - this.moveCursorBy(0, -1); - } - } - }; - this.moveCursorRight = function() { - var cursor = this.lead.getPosition(), - fold; - if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1)) { - this.moveCursorTo(fold.end.row, fold.end.column); - } - else if (this.lead.column == this.doc.getLine(this.lead.row).length) { - if (this.lead.row < this.doc.getLength() - 1) { - this.moveCursorTo(this.lead.row + 1, 0); - } - } - else { - var tabSize = this.session.getTabSize(); - var cursor = this.lead; - if (this.wouldMoveIntoSoftTab(cursor, tabSize, 1) && !this.session.getNavigateWithinSoftTabs()) { - this.moveCursorBy(0, tabSize); - } else { - this.moveCursorBy(0, 1); - } - } - }; - this.moveCursorLineStart = function() { - var row = this.lead.row; - var column = this.lead.column; - var screenRow = this.session.documentToScreenRow(row, column); - var firstColumnPosition = this.session.screenToDocumentPosition(screenRow, 0); - var beforeCursor = this.session.getDisplayLine( - row, null, firstColumnPosition.row, - firstColumnPosition.column - ); - - var leadingSpace = beforeCursor.match(/^\s*/); - if (leadingSpace[0].length != column && !this.session.$useEmacsStyleLineStart) - firstColumnPosition.column += leadingSpace[0].length; - this.moveCursorToPosition(firstColumnPosition); - }; - this.moveCursorLineEnd = function() { - var lead = this.lead; - var lineEnd = this.session.getDocumentLastRowColumnPosition(lead.row, lead.column); - if (this.lead.column == lineEnd.column) { - var line = this.session.getLine(lineEnd.row); - if (lineEnd.column == line.length) { - var textEnd = line.search(/\s+$/); - if (textEnd > 0) - lineEnd.column = textEnd; - } - } - - this.moveCursorTo(lineEnd.row, lineEnd.column); - }; - this.moveCursorFileEnd = function() { - var row = this.doc.getLength() - 1; - var column = this.doc.getLine(row).length; - this.moveCursorTo(row, column); - }; - this.moveCursorFileStart = function() { - this.moveCursorTo(0, 0); - }; - this.moveCursorLongWordRight = function() { - var row = this.lead.row; - var column = this.lead.column; - var line = this.doc.getLine(row); - var rightOfCursor = line.substring(column); - - var match; - this.session.nonTokenRe.lastIndex = 0; - this.session.tokenRe.lastIndex = 0; - var fold = this.session.getFoldAt(row, column, 1); - if (fold) { - this.moveCursorTo(fold.end.row, fold.end.column); - return; - } - if (match = this.session.nonTokenRe.exec(rightOfCursor)) { - column += this.session.nonTokenRe.lastIndex; - this.session.nonTokenRe.lastIndex = 0; - rightOfCursor = line.substring(column); - } - if (column >= line.length) { - this.moveCursorTo(row, line.length); - this.moveCursorRight(); - if (row < this.doc.getLength() - 1) - this.moveCursorWordRight(); - return; - } - if (match = this.session.tokenRe.exec(rightOfCursor)) { - column += this.session.tokenRe.lastIndex; - this.session.tokenRe.lastIndex = 0; - } - - this.moveCursorTo(row, column); - }; - this.moveCursorLongWordLeft = function() { - var row = this.lead.row; - var column = this.lead.column; - var fold; - if (fold = this.session.getFoldAt(row, column, -1)) { - this.moveCursorTo(fold.start.row, fold.start.column); - return; - } - - var str = this.session.getFoldStringAt(row, column, -1); - if (str == null) { - str = this.doc.getLine(row).substring(0, column); - } - - var leftOfCursor = lang.stringReverse(str); - var match; - this.session.nonTokenRe.lastIndex = 0; - this.session.tokenRe.lastIndex = 0; - if (match = this.session.nonTokenRe.exec(leftOfCursor)) { - column -= this.session.nonTokenRe.lastIndex; - leftOfCursor = leftOfCursor.slice(this.session.nonTokenRe.lastIndex); - this.session.nonTokenRe.lastIndex = 0; - } - if (column <= 0) { - this.moveCursorTo(row, 0); - this.moveCursorLeft(); - if (row > 0) - this.moveCursorWordLeft(); - return; - } - if (match = this.session.tokenRe.exec(leftOfCursor)) { - column -= this.session.tokenRe.lastIndex; - this.session.tokenRe.lastIndex = 0; - } - - this.moveCursorTo(row, column); - }; - - this.$shortWordEndIndex = function(rightOfCursor) { - var match, index = 0, ch; - var whitespaceRe = /\s/; - var tokenRe = this.session.tokenRe; - - tokenRe.lastIndex = 0; - if (match = this.session.tokenRe.exec(rightOfCursor)) { - index = this.session.tokenRe.lastIndex; - } else { - while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch)) - index ++; - - if (index < 1) { - tokenRe.lastIndex = 0; - while ((ch = rightOfCursor[index]) && !tokenRe.test(ch)) { - tokenRe.lastIndex = 0; - index ++; - if (whitespaceRe.test(ch)) { - if (index > 2) { - index--; - break; - } else { - while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch)) - index ++; - if (index > 2) - break; - } - } - } - } - } - tokenRe.lastIndex = 0; - - return index; - }; - - this.moveCursorShortWordRight = function() { - var row = this.lead.row; - var column = this.lead.column; - var line = this.doc.getLine(row); - var rightOfCursor = line.substring(column); - - var fold = this.session.getFoldAt(row, column, 1); - if (fold) - return this.moveCursorTo(fold.end.row, fold.end.column); - - if (column == line.length) { - var l = this.doc.getLength(); - do { - row++; - rightOfCursor = this.doc.getLine(row); - } while (row < l && /^\s*$/.test(rightOfCursor)); - - if (!/^\s+/.test(rightOfCursor)) - rightOfCursor = ""; - column = 0; - } - - var index = this.$shortWordEndIndex(rightOfCursor); - - this.moveCursorTo(row, column + index); - }; - - this.moveCursorShortWordLeft = function() { - var row = this.lead.row; - var column = this.lead.column; - - var fold; - if (fold = this.session.getFoldAt(row, column, -1)) - return this.moveCursorTo(fold.start.row, fold.start.column); - - var line = this.session.getLine(row).substring(0, column); - if (column === 0) { - do { - row--; - line = this.doc.getLine(row); - } while (row > 0 && /^\s*$/.test(line)); - - column = line.length; - if (!/\s+$/.test(line)) - line = ""; - } - - var leftOfCursor = lang.stringReverse(line); - var index = this.$shortWordEndIndex(leftOfCursor); - - return this.moveCursorTo(row, column - index); - }; - - this.moveCursorWordRight = function() { - if (this.session.$selectLongWords) - this.moveCursorLongWordRight(); - else - this.moveCursorShortWordRight(); - }; - - this.moveCursorWordLeft = function() { - if (this.session.$selectLongWords) - this.moveCursorLongWordLeft(); - else - this.moveCursorShortWordLeft(); - }; - this.moveCursorBy = function(rows, chars) { - var screenPos = this.session.documentToScreenPosition( - this.lead.row, - this.lead.column - ); - - var offsetX; - - if (chars === 0) { - if (rows !== 0) { - if (this.session.$bidiHandler.isBidiRow(screenPos.row, this.lead.row)) { - offsetX = this.session.$bidiHandler.getPosLeft(screenPos.column); - screenPos.column = Math.round(offsetX / this.session.$bidiHandler.charWidths[0]); - } else { - offsetX = screenPos.column * this.session.$bidiHandler.charWidths[0]; - } - } - - if (this.$desiredColumn) - screenPos.column = this.$desiredColumn; - else - this.$desiredColumn = screenPos.column; - } - - var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenPos.column, offsetX); - - if (rows !== 0 && chars === 0 && docPos.row === this.lead.row && docPos.column === this.lead.column) { - if (this.session.lineWidgets && this.session.lineWidgets[docPos.row]) { - if (docPos.row > 0 || rows > 0) - docPos.row++; - } - } - this.moveCursorTo(docPos.row, docPos.column + chars, chars === 0); - }; - this.moveCursorToPosition = function(position) { - this.moveCursorTo(position.row, position.column); - }; - this.moveCursorTo = function(row, column, keepDesiredColumn) { - var fold = this.session.getFoldAt(row, column, 1); - if (fold) { - row = fold.start.row; - column = fold.start.column; - } - - this.$keepDesiredColumnOnChange = true; - var line = this.session.getLine(row); - if (/[\uDC00-\uDFFF]/.test(line.charAt(column)) && line.charAt(column - 1)) { - if (this.lead.row == row && this.lead.column == column + 1) - column = column - 1; - else - column = column + 1; - } - this.lead.setPosition(row, column); - this.$keepDesiredColumnOnChange = false; - - if (!keepDesiredColumn) - this.$desiredColumn = null; - }; - this.moveCursorToScreen = function(row, column, keepDesiredColumn) { - var pos = this.session.screenToDocumentPosition(row, column); - this.moveCursorTo(pos.row, pos.column, keepDesiredColumn); - }; - this.detach = function() { - this.lead.detach(); - this.anchor.detach(); - this.session = this.doc = null; - }; - - this.fromOrientedRange = function(range) { - this.setSelectionRange(range, range.cursor == range.start); - this.$desiredColumn = range.desiredColumn || this.$desiredColumn; - }; - - this.toOrientedRange = function(range) { - var r = this.getRange(); - if (range) { - range.start.column = r.start.column; - range.start.row = r.start.row; - range.end.column = r.end.column; - range.end.row = r.end.row; - } else { - range = r; - } - - range.cursor = this.isBackwards() ? range.start : range.end; - range.desiredColumn = this.$desiredColumn; - return range; - }; - this.getRangeOfMovements = function(func) { - var start = this.getCursor(); - try { - func(this); - var end = this.getCursor(); - return Range.fromPoints(start,end); - } catch(e) { - return Range.fromPoints(start,start); - } finally { - this.moveCursorToPosition(start); - } - }; - - this.toJSON = function() { - if (this.rangeCount) { - var data = this.ranges.map(function(r) { - var r1 = r.clone(); - r1.isBackwards = r.cursor == r.start; - return r1; - }); - } else { - var data = this.getRange(); - data.isBackwards = this.isBackwards(); - } - return data; - }; - - this.fromJSON = function(data) { - if (data.start == undefined) { - if (this.rangeList) { - this.toSingleRange(data[0]); - for (var i = data.length; i--; ) { - var r = Range.fromPoints(data[i].start, data[i].end); - if (data[i].isBackwards) - r.cursor = r.start; - this.addRange(r, true); - } - return; - } else - data = data[0]; - } - if (this.rangeList) - this.toSingleRange(data); - this.setSelectionRange(data, data.isBackwards); - }; - - this.isEqual = function(data) { - if ((data.length || this.rangeCount) && data.length != this.rangeCount) - return false; - if (!data.length || !this.ranges) - return this.getRange().isEqual(data); - - for (var i = this.ranges.length; i--; ) { - if (!this.ranges[i].isEqual(data[i])) - return false; - } - return true; - }; - - }).call(Selection.prototype); - - exports.Selection = Selection; - }); - - ace.define("ace/tokenizer",["require","exports","module","ace/config"], function(acequire, exports, module) { - "use strict"; - - var config = acequire("./config"); - var MAX_TOKEN_COUNT = 2000; - var Tokenizer = function(rules) { - this.states = rules; - - this.regExps = {}; - this.matchMappings = {}; - for (var key in this.states) { - var state = this.states[key]; - var ruleRegExps = []; - var matchTotal = 0; - var mapping = this.matchMappings[key] = {defaultToken: "text"}; - var flag = "g"; - - var splitterRurles = []; - for (var i = 0; i < state.length; i++) { - var rule = state[i]; - if (rule.defaultToken) - mapping.defaultToken = rule.defaultToken; - if (rule.caseInsensitive) - flag = "gi"; - if (rule.regex == null) - continue; - - if (rule.regex instanceof RegExp) - rule.regex = rule.regex.toString().slice(1, -1); - var adjustedregex = rule.regex; - var matchcount = new RegExp("(?:(" + adjustedregex + ")|(.))").exec("a").length - 2; - if (Array.isArray(rule.token)) { - if (rule.token.length == 1 || matchcount == 1) { - rule.token = rule.token[0]; - } else if (matchcount - 1 != rule.token.length) { - this.reportError("number of classes and regexp groups doesn't match", { - rule: rule, - groupCount: matchcount - 1 - }); - rule.token = rule.token[0]; - } else { - rule.tokenArray = rule.token; - rule.token = null; - rule.onMatch = this.$arrayTokens; - } - } else if (typeof rule.token == "function" && !rule.onMatch) { - if (matchcount > 1) - rule.onMatch = this.$applyToken; - else - rule.onMatch = rule.token; - } - - if (matchcount > 1) { - if (/\\\d/.test(rule.regex)) { - adjustedregex = rule.regex.replace(/\\([0-9]+)/g, function(match, digit) { - return "\\" + (parseInt(digit, 10) + matchTotal + 1); - }); - } else { - matchcount = 1; - adjustedregex = this.removeCapturingGroups(rule.regex); - } - if (!rule.splitRegex && typeof rule.token != "string") - splitterRurles.push(rule); // flag will be known only at the very end - } - - mapping[matchTotal] = i; - matchTotal += matchcount; - - ruleRegExps.push(adjustedregex); - if (!rule.onMatch) - rule.onMatch = null; - } - - if (!ruleRegExps.length) { - mapping[0] = 0; - ruleRegExps.push("$"); - } - - splitterRurles.forEach(function(rule) { - rule.splitRegex = this.createSplitterRegexp(rule.regex, flag); - }, this); - - this.regExps[key] = new RegExp("(" + ruleRegExps.join(")|(") + ")|($)", flag); - } - }; - - (function() { - this.$setMaxTokenCount = function(m) { - MAX_TOKEN_COUNT = m | 0; - }; - - this.$applyToken = function(str) { - var values = this.splitRegex.exec(str).slice(1); - var types = this.token.apply(this, values); - if (typeof types === "string") - return [{type: types, value: str}]; - - var tokens = []; - for (var i = 0, l = types.length; i < l; i++) { - if (values[i]) - tokens[tokens.length] = { - type: types[i], - value: values[i] - }; - } - return tokens; - }; - - this.$arrayTokens = function(str) { - if (!str) - return []; - var values = this.splitRegex.exec(str); - if (!values) - return "text"; - var tokens = []; - var types = this.tokenArray; - for (var i = 0, l = types.length; i < l; i++) { - if (values[i + 1]) - tokens[tokens.length] = { - type: types[i], - value: values[i + 1] - }; - } - return tokens; - }; - - this.removeCapturingGroups = function(src) { - var r = src.replace( - /\[(?:\\.|[^\]])*?\]|\\.|\(\?[:=!]|(\()/g, - function(x, y) {return y ? "(?:" : x;} - ); - return r; - }; - - this.createSplitterRegexp = function(src, flag) { - if (src.indexOf("(?=") != -1) { - var stack = 0; - var inChClass = false; - var lastCapture = {}; - src.replace(/(\\.)|(\((?:\?[=!])?)|(\))|([\[\]])/g, function( - m, esc, parenOpen, parenClose, square, index - ) { - if (inChClass) { - inChClass = square != "]"; - } else if (square) { - inChClass = true; - } else if (parenClose) { - if (stack == lastCapture.stack) { - lastCapture.end = index+1; - lastCapture.stack = -1; - } - stack--; - } else if (parenOpen) { - stack++; - if (parenOpen.length != 1) { - lastCapture.stack = stack; - lastCapture.start = index; - } - } - return m; - }); - - if (lastCapture.end != null && /^\)*$/.test(src.substr(lastCapture.end))) - src = src.substring(0, lastCapture.start) + src.substr(lastCapture.end); - } - if (src.charAt(0) != "^") src = "^" + src; - if (src.charAt(src.length - 1) != "$") src += "$"; - - return new RegExp(src, (flag||"").replace("g", "")); - }; - this.getLineTokens = function(line, startState) { - if (startState && typeof startState != "string") { - var stack = startState.slice(0); - startState = stack[0]; - if (startState === "#tmp") { - stack.shift(); - startState = stack.shift(); - } - } else - var stack = []; - - var currentState = startState || "start"; - var state = this.states[currentState]; - if (!state) { - currentState = "start"; - state = this.states[currentState]; - } - var mapping = this.matchMappings[currentState]; - var re = this.regExps[currentState]; - re.lastIndex = 0; - - var match, tokens = []; - var lastIndex = 0; - var matchAttempts = 0; - - var token = {type: null, value: ""}; - - while (match = re.exec(line)) { - var type = mapping.defaultToken; - var rule = null; - var value = match[0]; - var index = re.lastIndex; - - if (index - value.length > lastIndex) { - var skipped = line.substring(lastIndex, index - value.length); - if (token.type == type) { - token.value += skipped; - } else { - if (token.type) - tokens.push(token); - token = {type: type, value: skipped}; - } - } - - for (var i = 0; i < match.length-2; i++) { - if (match[i + 1] === undefined) - continue; - - rule = state[mapping[i]]; - - if (rule.onMatch) - type = rule.onMatch(value, currentState, stack, line); - else - type = rule.token; - - if (rule.next) { - if (typeof rule.next == "string") { - currentState = rule.next; - } else { - currentState = rule.next(currentState, stack); - } - - state = this.states[currentState]; - if (!state) { - this.reportError("state doesn't exist", currentState); - currentState = "start"; - state = this.states[currentState]; - } - mapping = this.matchMappings[currentState]; - lastIndex = index; - re = this.regExps[currentState]; - re.lastIndex = index; - } - if (rule.consumeLineEnd) - lastIndex = index; - break; - } - - if (value) { - if (typeof type === "string") { - if ((!rule || rule.merge !== false) && token.type === type) { - token.value += value; - } else { - if (token.type) - tokens.push(token); - token = {type: type, value: value}; - } - } else if (type) { - if (token.type) - tokens.push(token); - token = {type: null, value: ""}; - for (var i = 0; i < type.length; i++) - tokens.push(type[i]); - } - } - - if (lastIndex == line.length) - break; - - lastIndex = index; - - if (matchAttempts++ > MAX_TOKEN_COUNT) { - if (matchAttempts > 2 * line.length) { - this.reportError("infinite loop with in ace tokenizer", { - startState: startState, - line: line - }); - } - while (lastIndex < line.length) { - if (token.type) - tokens.push(token); - token = { - value: line.substring(lastIndex, lastIndex += 2000), - type: "overflow" - }; - } - currentState = "start"; - stack = []; - break; - } - } - - if (token.type) - tokens.push(token); - - if (stack.length > 1) { - if (stack[0] !== currentState) - stack.unshift("#tmp", currentState); - } - return { - tokens : tokens, - state : stack.length ? stack : currentState - }; - }; - - this.reportError = config.reportError; - - }).call(Tokenizer.prototype); - - exports.Tokenizer = Tokenizer; - }); - - ace.define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/lang"], function(acequire, exports, module) { - "use strict"; - - var lang = acequire("../lib/lang"); - - var TextHighlightRules = function() { - - this.$rules = { - "start" : [{ - token : "empty_line", - regex : '^$' - }, { - defaultToken : "text" - }] - }; - }; - - (function() { - - this.addRules = function(rules, prefix) { - if (!prefix) { - for (var key in rules) - this.$rules[key] = rules[key]; - return; - } - for (var key in rules) { - var state = rules[key]; - for (var i = 0; i < state.length; i++) { - var rule = state[i]; - if (rule.next || rule.onMatch) { - if (typeof rule.next == "string") { - if (rule.next.indexOf(prefix) !== 0) - rule.next = prefix + rule.next; - } - if (rule.nextState && rule.nextState.indexOf(prefix) !== 0) - rule.nextState = prefix + rule.nextState; - } - } - this.$rules[prefix + key] = state; - } - }; - - this.getRules = function() { - return this.$rules; - }; - - this.embedRules = function (HighlightRules, prefix, escapeRules, states, append) { - var embedRules = typeof HighlightRules == "function" - ? new HighlightRules().getRules() - : HighlightRules; - if (states) { - for (var i = 0; i < states.length; i++) - states[i] = prefix + states[i]; - } else { - states = []; - for (var key in embedRules) - states.push(prefix + key); - } - - this.addRules(embedRules, prefix); - - if (escapeRules) { - var addRules = Array.prototype[append ? "push" : "unshift"]; - for (var i = 0; i < states.length; i++) - addRules.apply(this.$rules[states[i]], lang.deepCopy(escapeRules)); - } - - if (!this.$embeds) - this.$embeds = []; - this.$embeds.push(prefix); - }; - - this.getEmbeds = function() { - return this.$embeds; - }; - - var pushState = function(currentState, stack) { - if (currentState != "start" || stack.length) - stack.unshift(this.nextState, currentState); - return this.nextState; - }; - var popState = function(currentState, stack) { - stack.shift(); - return stack.shift() || "start"; - }; - - this.normalizeRules = function() { - var id = 0; - var rules = this.$rules; - function processState(key) { - var state = rules[key]; - state.processed = true; - for (var i = 0; i < state.length; i++) { - var rule = state[i]; - var toInsert = null; - if (Array.isArray(rule)) { - toInsert = rule; - rule = {}; - } - if (!rule.regex && rule.start) { - rule.regex = rule.start; - if (!rule.next) - rule.next = []; - rule.next.push({ - defaultToken: rule.token - }, { - token: rule.token + ".end", - regex: rule.end || rule.start, - next: "pop" - }); - rule.token = rule.token + ".start"; - rule.push = true; - } - var next = rule.next || rule.push; - if (next && Array.isArray(next)) { - var stateName = rule.stateName; - if (!stateName) { - stateName = rule.token; - if (typeof stateName != "string") - stateName = stateName[0] || ""; - if (rules[stateName]) - stateName += id++; - } - rules[stateName] = next; - rule.next = stateName; - processState(stateName); - } else if (next == "pop") { - rule.next = popState; - } - - if (rule.push) { - rule.nextState = rule.next || rule.push; - rule.next = pushState; - delete rule.push; - } - - if (rule.rules) { - for (var r in rule.rules) { - if (rules[r]) { - if (rules[r].push) - rules[r].push.apply(rules[r], rule.rules[r]); - } else { - rules[r] = rule.rules[r]; - } - } - } - var includeName = typeof rule == "string" ? rule : rule.include; - if (includeName) { - if (Array.isArray(includeName)) - toInsert = includeName.map(function(x) { return rules[x]; }); - else - toInsert = rules[includeName]; - } - - if (toInsert) { - var args = [i, 1].concat(toInsert); - if (rule.noEscape) - args = args.filter(function(x) {return !x.next;}); - state.splice.apply(state, args); - i--; - } - - if (rule.keywordMap) { - rule.token = this.createKeywordMapper( - rule.keywordMap, rule.defaultToken || "text", rule.caseInsensitive - ); - delete rule.defaultToken; - } - } - } - Object.keys(rules).forEach(processState, this); - }; - - this.createKeywordMapper = function(map, defaultToken, ignoreCase, splitChar) { - var keywords = Object.create(null); - Object.keys(map).forEach(function(className) { - var a = map[className]; - if (ignoreCase) - a = a.toLowerCase(); - var list = a.split(splitChar || "|"); - for (var i = list.length; i--; ) - keywords[list[i]] = className; - }); - if (Object.getPrototypeOf(keywords)) { - keywords.__proto__ = null; - } - this.$keywordList = Object.keys(keywords); - map = null; - return ignoreCase - ? function(value) {return keywords[value.toLowerCase()] || defaultToken; } - : function(value) {return keywords[value] || defaultToken; }; - }; - - this.getKeywords = function() { - return this.$keywords; - }; - - }).call(TextHighlightRules.prototype); - - exports.TextHighlightRules = TextHighlightRules; - }); - - ace.define("ace/mode/behaviour",["require","exports","module"], function(acequire, exports, module) { - "use strict"; - - var Behaviour = function() { - this.$behaviours = {}; - }; - - (function () { - - this.add = function (name, action, callback) { - switch (undefined) { - case this.$behaviours: - this.$behaviours = {}; - case this.$behaviours[name]: - this.$behaviours[name] = {}; - } - this.$behaviours[name][action] = callback; - }; - - this.addBehaviours = function (behaviours) { - for (var key in behaviours) { - for (var action in behaviours[key]) { - this.add(key, action, behaviours[key][action]); - } - } - }; - - this.remove = function (name) { - if (this.$behaviours && this.$behaviours[name]) { - delete this.$behaviours[name]; - } - }; - - this.inherit = function (mode, filter) { - if (typeof mode === "function") { - var behaviours = new mode().getBehaviours(filter); - } else { - var behaviours = mode.getBehaviours(filter); - } - this.addBehaviours(behaviours); - }; - - this.getBehaviours = function (filter) { - if (!filter) { - return this.$behaviours; - } else { - var ret = {}; - for (var i = 0; i < filter.length; i++) { - if (this.$behaviours[filter[i]]) { - ret[filter[i]] = this.$behaviours[filter[i]]; - } - } - return ret; - } - }; - - }).call(Behaviour.prototype); - - exports.Behaviour = Behaviour; - }); - - ace.define("ace/token_iterator",["require","exports","module","ace/range"], function(acequire, exports, module) { - "use strict"; - - var Range = acequire("./range").Range; - var TokenIterator = function(session, initialRow, initialColumn) { - this.$session = session; - this.$row = initialRow; - this.$rowTokens = session.getTokens(initialRow); - - var token = session.getTokenAt(initialRow, initialColumn); - this.$tokenIndex = token ? token.index : -1; - }; - - (function() { - this.stepBackward = function() { - this.$tokenIndex -= 1; - - while (this.$tokenIndex < 0) { - this.$row -= 1; - if (this.$row < 0) { - this.$row = 0; - return null; - } - - this.$rowTokens = this.$session.getTokens(this.$row); - this.$tokenIndex = this.$rowTokens.length - 1; - } - - return this.$rowTokens[this.$tokenIndex]; - }; - this.stepForward = function() { - this.$tokenIndex += 1; - var rowCount; - while (this.$tokenIndex >= this.$rowTokens.length) { - this.$row += 1; - if (!rowCount) - rowCount = this.$session.getLength(); - if (this.$row >= rowCount) { - this.$row = rowCount - 1; - return null; - } - - this.$rowTokens = this.$session.getTokens(this.$row); - this.$tokenIndex = 0; - } - - return this.$rowTokens[this.$tokenIndex]; - }; - this.getCurrentToken = function () { - return this.$rowTokens[this.$tokenIndex]; - }; - this.getCurrentTokenRow = function () { - return this.$row; - }; - this.getCurrentTokenColumn = function() { - var rowTokens = this.$rowTokens; - var tokenIndex = this.$tokenIndex; - var column = rowTokens[tokenIndex].start; - if (column !== undefined) - return column; - - column = 0; - while (tokenIndex > 0) { - tokenIndex -= 1; - column += rowTokens[tokenIndex].value.length; - } - - return column; - }; - this.getCurrentTokenPosition = function() { - return {row: this.$row, column: this.getCurrentTokenColumn()}; - }; - this.getCurrentTokenRange = function() { - var token = this.$rowTokens[this.$tokenIndex]; - var column = this.getCurrentTokenColumn(); - return new Range(this.$row, column, this.$row, column + token.value.length); - }; - - }).call(TokenIterator.prototype); - - exports.TokenIterator = TokenIterator; - }); - - ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("../../lib/oop"); - var Behaviour = acequire("../behaviour").Behaviour; - var TokenIterator = acequire("../../token_iterator").TokenIterator; - var lang = acequire("../../lib/lang"); - - var SAFE_INSERT_IN_TOKENS = - ["text", "paren.rparen", "punctuation.operator"]; - var SAFE_INSERT_BEFORE_TOKENS = - ["text", "paren.rparen", "punctuation.operator", "comment"]; - - var context; - var contextCache = {}; - var defaultQuotes = {'"' : '"', "'" : "'"}; - - var initContext = function(editor) { - var id = -1; - if (editor.multiSelect) { - id = editor.selection.index; - if (contextCache.rangeCount != editor.multiSelect.rangeCount) - contextCache = {rangeCount: editor.multiSelect.rangeCount}; - } - if (contextCache[id]) - return context = contextCache[id]; - context = contextCache[id] = { - autoInsertedBrackets: 0, - autoInsertedRow: -1, - autoInsertedLineEnd: "", - maybeInsertedBrackets: 0, - maybeInsertedRow: -1, - maybeInsertedLineStart: "", - maybeInsertedLineEnd: "" - }; - }; - - var getWrapped = function(selection, selected, opening, closing) { - var rowDiff = selection.end.row - selection.start.row; - return { - text: opening + selected + closing, - selection: [ - 0, - selection.start.column + 1, - rowDiff, - selection.end.column + (rowDiff ? 0 : 1) - ] - }; - }; - - var CstyleBehaviour = function(options) { - this.add("braces", "insertion", function(state, action, editor, session, text) { - var cursor = editor.getCursorPosition(); - var line = session.doc.getLine(cursor.row); - if (text == '{') { - initContext(editor); - var selection = editor.getSelectionRange(); - var selected = session.doc.getTextRange(selection); - if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) { - return getWrapped(selection, selected, '{', '}'); - } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { - if (/[\]\}\)]/.test(line[cursor.column]) || editor.inMultiSelectMode || options && options.braces) { - CstyleBehaviour.recordAutoInsert(editor, session, "}"); - return { - text: '{}', - selection: [1, 1] - }; - } else { - CstyleBehaviour.recordMaybeInsert(editor, session, "{"); - return { - text: '{', - selection: [1, 1] - }; - } - } - } else if (text == '}') { - initContext(editor); - var rightChar = line.substring(cursor.column, cursor.column + 1); - if (rightChar == '}') { - var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); - if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { - CstyleBehaviour.popAutoInsertedClosing(); - return { - text: '', - selection: [1, 1] - }; - } - } - } else if (text == "\n" || text == "\r\n") { - initContext(editor); - var closing = ""; - if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) { - closing = lang.stringRepeat("}", context.maybeInsertedBrackets); - CstyleBehaviour.clearMaybeInsertedClosing(); - } - var rightChar = line.substring(cursor.column, cursor.column + 1); - if (rightChar === '}') { - var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column+1}, '}'); - if (!openBracePos) - return null; - var next_indent = this.$getIndent(session.getLine(openBracePos.row)); - } else if (closing) { - var next_indent = this.$getIndent(line); - } else { - CstyleBehaviour.clearMaybeInsertedClosing(); - return; - } - var indent = next_indent + session.getTabString(); - - return { - text: '\n' + indent + '\n' + next_indent + closing, - selection: [1, indent.length, 1, indent.length] - }; - } else { - CstyleBehaviour.clearMaybeInsertedClosing(); - } - }); - - this.add("braces", "deletion", function(state, action, editor, session, range) { - var selected = session.doc.getTextRange(range); - if (!range.isMultiLine() && selected == '{') { - initContext(editor); - var line = session.doc.getLine(range.start.row); - var rightChar = line.substring(range.end.column, range.end.column + 1); - if (rightChar == '}') { - range.end.column++; - return range; - } else { - context.maybeInsertedBrackets--; - } - } - }); - - this.add("parens", "insertion", function(state, action, editor, session, text) { - if (text == '(') { - initContext(editor); - var selection = editor.getSelectionRange(); - var selected = session.doc.getTextRange(selection); - if (selected !== "" && editor.getWrapBehavioursEnabled()) { - return getWrapped(selection, selected, '(', ')'); - } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { - CstyleBehaviour.recordAutoInsert(editor, session, ")"); - return { - text: '()', - selection: [1, 1] - }; - } - } else if (text == ')') { - initContext(editor); - var cursor = editor.getCursorPosition(); - var line = session.doc.getLine(cursor.row); - var rightChar = line.substring(cursor.column, cursor.column + 1); - if (rightChar == ')') { - var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row}); - if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { - CstyleBehaviour.popAutoInsertedClosing(); - return { - text: '', - selection: [1, 1] - }; - } - } - } - }); - - this.add("parens", "deletion", function(state, action, editor, session, range) { - var selected = session.doc.getTextRange(range); - if (!range.isMultiLine() && selected == '(') { - initContext(editor); - var line = session.doc.getLine(range.start.row); - var rightChar = line.substring(range.start.column + 1, range.start.column + 2); - if (rightChar == ')') { - range.end.column++; - return range; - } - } - }); - - this.add("brackets", "insertion", function(state, action, editor, session, text) { - if (text == '[') { - initContext(editor); - var selection = editor.getSelectionRange(); - var selected = session.doc.getTextRange(selection); - if (selected !== "" && editor.getWrapBehavioursEnabled()) { - return getWrapped(selection, selected, '[', ']'); - } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { - CstyleBehaviour.recordAutoInsert(editor, session, "]"); - return { - text: '[]', - selection: [1, 1] - }; - } - } else if (text == ']') { - initContext(editor); - var cursor = editor.getCursorPosition(); - var line = session.doc.getLine(cursor.row); - var rightChar = line.substring(cursor.column, cursor.column + 1); - if (rightChar == ']') { - var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row}); - if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { - CstyleBehaviour.popAutoInsertedClosing(); - return { - text: '', - selection: [1, 1] - }; - } - } - } - }); - - this.add("brackets", "deletion", function(state, action, editor, session, range) { - var selected = session.doc.getTextRange(range); - if (!range.isMultiLine() && selected == '[') { - initContext(editor); - var line = session.doc.getLine(range.start.row); - var rightChar = line.substring(range.start.column + 1, range.start.column + 2); - if (rightChar == ']') { - range.end.column++; - return range; - } - } - }); - - this.add("string_dquotes", "insertion", function(state, action, editor, session, text) { - var quotes = session.$mode.$quotes || defaultQuotes; - if (text.length == 1 && quotes[text]) { - if (this.lineCommentStart && this.lineCommentStart.indexOf(text) != -1) - return; - initContext(editor); - var quote = text; - var selection = editor.getSelectionRange(); - var selected = session.doc.getTextRange(selection); - if (selected !== "" && (selected.length != 1 || !quotes[selected]) && editor.getWrapBehavioursEnabled()) { - return getWrapped(selection, selected, quote, quote); - } else if (!selected) { - var cursor = editor.getCursorPosition(); - var line = session.doc.getLine(cursor.row); - var leftChar = line.substring(cursor.column-1, cursor.column); - var rightChar = line.substring(cursor.column, cursor.column + 1); - - var token = session.getTokenAt(cursor.row, cursor.column); - var rightToken = session.getTokenAt(cursor.row, cursor.column + 1); - if (leftChar == "\\" && token && /escape/.test(token.type)) - return null; - - var stringBefore = token && /string|escape/.test(token.type); - var stringAfter = !rightToken || /string|escape/.test(rightToken.type); - - var pair; - if (rightChar == quote) { - pair = stringBefore !== stringAfter; - if (pair && /string\.end/.test(rightToken.type)) - pair = false; - } else { - if (stringBefore && !stringAfter) - return null; // wrap string with different quote - if (stringBefore && stringAfter) - return null; // do not pair quotes inside strings - var wordRe = session.$mode.tokenRe; - wordRe.lastIndex = 0; - var isWordBefore = wordRe.test(leftChar); - wordRe.lastIndex = 0; - var isWordAfter = wordRe.test(leftChar); - if (isWordBefore || isWordAfter) - return null; // before or after alphanumeric - if (rightChar && !/[\s;,.})\]\\]/.test(rightChar)) - return null; // there is rightChar and it isn't closing - pair = true; - } - return { - text: pair ? quote + quote : "", - selection: [1,1] - }; - } - } - }); - - this.add("string_dquotes", "deletion", function(state, action, editor, session, range) { - var selected = session.doc.getTextRange(range); - if (!range.isMultiLine() && (selected == '"' || selected == "'")) { - initContext(editor); - var line = session.doc.getLine(range.start.row); - var rightChar = line.substring(range.start.column + 1, range.start.column + 2); - if (rightChar == selected) { - range.end.column++; - return range; - } - } - }); - - }; - - - CstyleBehaviour.isSaneInsertion = function(editor, session) { - var cursor = editor.getCursorPosition(); - var iterator = new TokenIterator(session, cursor.row, cursor.column); - if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { - var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1); - if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) - return false; - } - iterator.stepForward(); - return iterator.getCurrentTokenRow() !== cursor.row || - this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS); - }; - - CstyleBehaviour.$matchTokenType = function(token, types) { - return types.indexOf(token.type || token) > -1; - }; - - CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) { - var cursor = editor.getCursorPosition(); - var line = session.doc.getLine(cursor.row); - if (!this.isAutoInsertedClosing(cursor, line, context.autoInsertedLineEnd[0])) - context.autoInsertedBrackets = 0; - context.autoInsertedRow = cursor.row; - context.autoInsertedLineEnd = bracket + line.substr(cursor.column); - context.autoInsertedBrackets++; - }; - - CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) { - var cursor = editor.getCursorPosition(); - var line = session.doc.getLine(cursor.row); - if (!this.isMaybeInsertedClosing(cursor, line)) - context.maybeInsertedBrackets = 0; - context.maybeInsertedRow = cursor.row; - context.maybeInsertedLineStart = line.substr(0, cursor.column) + bracket; - context.maybeInsertedLineEnd = line.substr(cursor.column); - context.maybeInsertedBrackets++; - }; - - CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) { - return context.autoInsertedBrackets > 0 && - cursor.row === context.autoInsertedRow && - bracket === context.autoInsertedLineEnd[0] && - line.substr(cursor.column) === context.autoInsertedLineEnd; - }; - - CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) { - return context.maybeInsertedBrackets > 0 && - cursor.row === context.maybeInsertedRow && - line.substr(cursor.column) === context.maybeInsertedLineEnd && - line.substr(0, cursor.column) == context.maybeInsertedLineStart; - }; - - CstyleBehaviour.popAutoInsertedClosing = function() { - context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1); - context.autoInsertedBrackets--; - }; - - CstyleBehaviour.clearMaybeInsertedClosing = function() { - if (context) { - context.maybeInsertedBrackets = 0; - context.maybeInsertedRow = -1; - } - }; - - - - oop.inherits(CstyleBehaviour, Behaviour); - - exports.CstyleBehaviour = CstyleBehaviour; - }); - - ace.define("ace/unicode",["require","exports","module"], function(acequire, exports, module) { - "use strict"; - exports.packages = {}; - - addUnicodePackage({ - L: "0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", - Ll: "0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A", - Lu: "0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A", - Lt: "01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC", - Lm: "02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F", - Lo: "01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", - M: "0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26", - Mn: "0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26", - Mc: "0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC", - Me: "0488048906DE20DD-20E020E2-20E4A670-A672", - N: "0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19", - Nd: "0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19", - Nl: "16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF", - No: "00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835", - P: "0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65", - Pd: "002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D", - Ps: "0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62", - Pe: "0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63", - Pi: "00AB2018201B201C201F20392E022E042E092E0C2E1C2E20", - Pf: "00BB2019201D203A2E032E052E0A2E0D2E1D2E21", - Pc: "005F203F20402054FE33FE34FE4D-FE4FFF3F", - Po: "0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65", - S: "0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD", - Sm: "002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC", - Sc: "002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6", - Sk: "005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3", - So: "00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD", - Z: "002000A01680180E2000-200A20282029202F205F3000", - Zs: "002000A01680180E2000-200A202F205F3000", - Zl: "2028", - Zp: "2029", - C: "0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF", - Cc: "0000-001F007F-009F", - Cf: "00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB", - Co: "E000-F8FF", - Cs: "D800-DFFF", - Cn: "03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF" - }); - - function addUnicodePackage (pack) { - var codePoint = /\w{4}/g; - for (var name in pack) - exports.packages[name] = pack[name].replace(codePoint, "\\u$&"); - } - - }); - - ace.define("ace/mode/text",["require","exports","module","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/behaviour/cstyle","ace/unicode","ace/lib/lang","ace/token_iterator","ace/range"], function(acequire, exports, module) { - "use strict"; - - var Tokenizer = acequire("../tokenizer").Tokenizer; - var TextHighlightRules = acequire("./text_highlight_rules").TextHighlightRules; - var CstyleBehaviour = acequire("./behaviour/cstyle").CstyleBehaviour; - var unicode = acequire("../unicode"); - var lang = acequire("../lib/lang"); - var TokenIterator = acequire("../token_iterator").TokenIterator; - var Range = acequire("../range").Range; - - var Mode = function() { - this.HighlightRules = TextHighlightRules; - }; - - (function() { - this.$defaultBehaviour = new CstyleBehaviour(); - - this.tokenRe = new RegExp("^[" - + unicode.packages.L - + unicode.packages.Mn + unicode.packages.Mc - + unicode.packages.Nd - + unicode.packages.Pc + "\\$_]+", "g" - ); - - this.nonTokenRe = new RegExp("^(?:[^" - + unicode.packages.L - + unicode.packages.Mn + unicode.packages.Mc - + unicode.packages.Nd - + unicode.packages.Pc + "\\$_]|\\s])+", "g" - ); - - this.getTokenizer = function() { - if (!this.$tokenizer) { - this.$highlightRules = this.$highlightRules || new this.HighlightRules(this.$highlightRuleConfig); - this.$tokenizer = new Tokenizer(this.$highlightRules.getRules()); - } - return this.$tokenizer; - }; - - this.lineCommentStart = ""; - this.blockComment = ""; - - this.toggleCommentLines = function(state, session, startRow, endRow) { - var doc = session.doc; - - var ignoreBlankLines = true; - var shouldRemove = true; - var minIndent = Infinity; - var tabSize = session.getTabSize(); - var insertAtTabStop = false; - - if (!this.lineCommentStart) { - if (!this.blockComment) - return false; - var lineCommentStart = this.blockComment.start; - var lineCommentEnd = this.blockComment.end; - var regexpStart = new RegExp("^(\\s*)(?:" + lang.escapeRegExp(lineCommentStart) + ")"); - var regexpEnd = new RegExp("(?:" + lang.escapeRegExp(lineCommentEnd) + ")\\s*$"); - - var comment = function(line, i) { - if (testRemove(line, i)) - return; - if (!ignoreBlankLines || /\S/.test(line)) { - doc.insertInLine({row: i, column: line.length}, lineCommentEnd); - doc.insertInLine({row: i, column: minIndent}, lineCommentStart); - } - }; - - var uncomment = function(line, i) { - var m; - if (m = line.match(regexpEnd)) - doc.removeInLine(i, line.length - m[0].length, line.length); - if (m = line.match(regexpStart)) - doc.removeInLine(i, m[1].length, m[0].length); - }; - - var testRemove = function(line, row) { - if (regexpStart.test(line)) - return true; - var tokens = session.getTokens(row); - for (var i = 0; i < tokens.length; i++) { - if (tokens[i].type === "comment") - return true; - } - }; - } else { - if (Array.isArray(this.lineCommentStart)) { - var regexpStart = this.lineCommentStart.map(lang.escapeRegExp).join("|"); - var lineCommentStart = this.lineCommentStart[0]; - } else { - var regexpStart = lang.escapeRegExp(this.lineCommentStart); - var lineCommentStart = this.lineCommentStart; - } - regexpStart = new RegExp("^(\\s*)(?:" + regexpStart + ") ?"); - - insertAtTabStop = session.getUseSoftTabs(); - - var uncomment = function(line, i) { - var m = line.match(regexpStart); - if (!m) return; - var start = m[1].length, end = m[0].length; - if (!shouldInsertSpace(line, start, end) && m[0][end - 1] == " ") - end--; - doc.removeInLine(i, start, end); - }; - var commentWithSpace = lineCommentStart + " "; - var comment = function(line, i) { - if (!ignoreBlankLines || /\S/.test(line)) { - if (shouldInsertSpace(line, minIndent, minIndent)) - doc.insertInLine({row: i, column: minIndent}, commentWithSpace); - else - doc.insertInLine({row: i, column: minIndent}, lineCommentStart); - } - }; - var testRemove = function(line, i) { - return regexpStart.test(line); - }; - - var shouldInsertSpace = function(line, before, after) { - var spaces = 0; - while (before-- && line.charAt(before) == " ") - spaces++; - if (spaces % tabSize != 0) - return false; - var spaces = 0; - while (line.charAt(after++) == " ") - spaces++; - if (tabSize > 2) - return spaces % tabSize != tabSize - 1; - else - return spaces % tabSize == 0; - return true; - }; - } - - function iter(fun) { - for (var i = startRow; i <= endRow; i++) - fun(doc.getLine(i), i); - } - - - var minEmptyLength = Infinity; - iter(function(line, i) { - var indent = line.search(/\S/); - if (indent !== -1) { - if (indent < minIndent) - minIndent = indent; - if (shouldRemove && !testRemove(line, i)) - shouldRemove = false; - } else if (minEmptyLength > line.length) { - minEmptyLength = line.length; - } - }); - - if (minIndent == Infinity) { - minIndent = minEmptyLength; - ignoreBlankLines = false; - shouldRemove = false; - } - - if (insertAtTabStop && minIndent % tabSize != 0) - minIndent = Math.floor(minIndent / tabSize) * tabSize; - - iter(shouldRemove ? uncomment : comment); - }; - - this.toggleBlockComment = function(state, session, range, cursor) { - var comment = this.blockComment; - if (!comment) - return; - if (!comment.start && comment[0]) - comment = comment[0]; - - var iterator = new TokenIterator(session, cursor.row, cursor.column); - var token = iterator.getCurrentToken(); - - var sel = session.selection; - var initialRange = session.selection.toOrientedRange(); - var startRow, colDiff; - - if (token && /comment/.test(token.type)) { - var startRange, endRange; - while (token && /comment/.test(token.type)) { - var i = token.value.indexOf(comment.start); - if (i != -1) { - var row = iterator.getCurrentTokenRow(); - var column = iterator.getCurrentTokenColumn() + i; - startRange = new Range(row, column, row, column + comment.start.length); - break; - } - token = iterator.stepBackward(); - } - - var iterator = new TokenIterator(session, cursor.row, cursor.column); - var token = iterator.getCurrentToken(); - while (token && /comment/.test(token.type)) { - var i = token.value.indexOf(comment.end); - if (i != -1) { - var row = iterator.getCurrentTokenRow(); - var column = iterator.getCurrentTokenColumn() + i; - endRange = new Range(row, column, row, column + comment.end.length); - break; - } - token = iterator.stepForward(); - } - if (endRange) - session.remove(endRange); - if (startRange) { - session.remove(startRange); - startRow = startRange.start.row; - colDiff = -comment.start.length; - } - } else { - colDiff = comment.start.length; - startRow = range.start.row; - session.insert(range.end, comment.end); - session.insert(range.start, comment.start); - } - if (initialRange.start.row == startRow) - initialRange.start.column += colDiff; - if (initialRange.end.row == startRow) - initialRange.end.column += colDiff; - session.selection.fromOrientedRange(initialRange); - }; - - this.getNextLineIndent = function(state, line, tab) { - return this.$getIndent(line); - }; - - this.checkOutdent = function(state, line, input) { - return false; - }; - - this.autoOutdent = function(state, doc, row) { - }; - - this.$getIndent = function(line) { - return line.match(/^\s*/)[0]; - }; - - this.createWorker = function(session) { - return null; - }; - - this.createModeDelegates = function (mapping) { - this.$embeds = []; - this.$modes = {}; - for (var i in mapping) { - if (mapping[i]) { - this.$embeds.push(i); - this.$modes[i] = new mapping[i](); - } - } - - var delegations = ["toggleBlockComment", "toggleCommentLines", "getNextLineIndent", - "checkOutdent", "autoOutdent", "transformAction", "getCompletions"]; - - for (var i = 0; i < delegations.length; i++) { - (function(scope) { - var functionName = delegations[i]; - var defaultHandler = scope[functionName]; - scope[delegations[i]] = function() { - return this.$delegator(functionName, arguments, defaultHandler); - }; - }(this)); - } - }; - - this.$delegator = function(method, args, defaultHandler) { - var state = args[0]; - if (typeof state != "string") - state = state[0]; - for (var i = 0; i < this.$embeds.length; i++) { - if (!this.$modes[this.$embeds[i]]) continue; - - var split = state.split(this.$embeds[i]); - if (!split[0] && split[1]) { - args[0] = split[1]; - var mode = this.$modes[this.$embeds[i]]; - return mode[method].apply(mode, args); - } - } - var ret = defaultHandler.apply(this, args); - return defaultHandler ? ret : undefined; - }; - - this.transformAction = function(state, action, editor, session, param) { - if (this.$behaviour) { - var behaviours = this.$behaviour.getBehaviours(); - for (var key in behaviours) { - if (behaviours[key][action]) { - var ret = behaviours[key][action].apply(this, arguments); - if (ret) { - return ret; - } - } - } - } - }; - - this.getKeywords = function(append) { - if (!this.completionKeywords) { - var rules = this.$tokenizer.rules; - var completionKeywords = []; - for (var rule in rules) { - var ruleItr = rules[rule]; - for (var r = 0, l = ruleItr.length; r < l; r++) { - if (typeof ruleItr[r].token === "string") { - if (/keyword|support|storage/.test(ruleItr[r].token)) - completionKeywords.push(ruleItr[r].regex); - } - else if (typeof ruleItr[r].token === "object") { - for (var a = 0, aLength = ruleItr[r].token.length; a < aLength; a++) { - if (/keyword|support|storage/.test(ruleItr[r].token[a])) { - var rule = ruleItr[r].regex.match(/\(.+?\)/g)[a]; - completionKeywords.push(rule.substr(1, rule.length - 2)); - } - } - } - } - } - this.completionKeywords = completionKeywords; - } - if (!append) - return this.$keywordList; - return completionKeywords.concat(this.$keywordList || []); - }; - - this.$createKeywordList = function() { - if (!this.$highlightRules) - this.getTokenizer(); - return this.$keywordList = this.$highlightRules.$keywordList || []; - }; - - this.getCompletions = function(state, session, pos, prefix) { - var keywords = this.$keywordList || this.$createKeywordList(); - return keywords.map(function(word) { - return { - name: word, - value: word, - score: 0, - meta: "keyword" - }; - }); - }; - - this.$id = "ace/mode/text"; - }).call(Mode.prototype); - - exports.Mode = Mode; - }); - - ace.define("ace/apply_delta",["require","exports","module"], function(acequire, exports, module) { - "use strict"; - - function throwDeltaError(delta, errorText){ - console.log("Invalid Delta:", delta); - throw "Invalid Delta: " + errorText; - } - - function positionInDocument(docLines, position) { - return position.row >= 0 && position.row < docLines.length && - position.column >= 0 && position.column <= docLines[position.row].length; - } - - function validateDelta(docLines, delta) { - if (delta.action != "insert" && delta.action != "remove") - throwDeltaError(delta, "delta.action must be 'insert' or 'remove'"); - if (!(delta.lines instanceof Array)) - throwDeltaError(delta, "delta.lines must be an Array"); - if (!delta.start || !delta.end) - throwDeltaError(delta, "delta.start/end must be an present"); - var start = delta.start; - if (!positionInDocument(docLines, delta.start)) - throwDeltaError(delta, "delta.start must be contained in document"); - var end = delta.end; - if (delta.action == "remove" && !positionInDocument(docLines, end)) - throwDeltaError(delta, "delta.end must contained in document for 'remove' actions"); - var numRangeRows = end.row - start.row; - var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0)); - if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars) - throwDeltaError(delta, "delta.range must match delta lines"); - } - - exports.applyDelta = function(docLines, delta, doNotValidate) { - - var row = delta.start.row; - var startColumn = delta.start.column; - var line = docLines[row] || ""; - switch (delta.action) { - case "insert": - var lines = delta.lines; - if (lines.length === 1) { - docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); - } else { - var args = [row, 1].concat(delta.lines); - docLines.splice.apply(docLines, args); - docLines[row] = line.substring(0, startColumn) + docLines[row]; - docLines[row + delta.lines.length - 1] += line.substring(startColumn); - } - break; - case "remove": - var endColumn = delta.end.column; - var endRow = delta.end.row; - if (row === endRow) { - docLines[row] = line.substring(0, startColumn) + line.substring(endColumn); - } else { - docLines.splice( - row, endRow - row + 1, - line.substring(0, startColumn) + docLines[endRow].substring(endColumn) - ); - } - break; - } - }; - }); - - ace.define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("./lib/oop"); - var EventEmitter = acequire("./lib/event_emitter").EventEmitter; - - var Anchor = exports.Anchor = function(doc, row, column) { - this.$onChange = this.onChange.bind(this); - this.attach(doc); - - if (typeof column == "undefined") - this.setPosition(row.row, row.column); - else - this.setPosition(row, column); - }; - - (function() { - - oop.implement(this, EventEmitter); - this.getPosition = function() { - return this.$clipPositionToDocument(this.row, this.column); - }; - this.getDocument = function() { - return this.document; - }; - this.$insertRight = false; - this.onChange = function(delta) { - if (delta.start.row == delta.end.row && delta.start.row != this.row) - return; - - if (delta.start.row > this.row) - return; - - var point = $getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight); - this.setPosition(point.row, point.column, true); - }; - - function $pointsInOrder(point1, point2, equalPointsInOrder) { - var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column; - return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter); - } - - function $getTransformedPoint(delta, point, moveIfEqual) { - var deltaIsInsert = delta.action == "insert"; - var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row); - var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column); - var deltaStart = delta.start; - var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range. - if ($pointsInOrder(point, deltaStart, moveIfEqual)) { - return { - row: point.row, - column: point.column - }; - } - if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) { - return { - row: point.row + deltaRowShift, - column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0) - }; - } - - return { - row: deltaStart.row, - column: deltaStart.column - }; - } - this.setPosition = function(row, column, noClip) { - var pos; - if (noClip) { - pos = { - row: row, - column: column - }; - } else { - pos = this.$clipPositionToDocument(row, column); - } - - if (this.row == pos.row && this.column == pos.column) - return; - - var old = { - row: this.row, - column: this.column - }; - - this.row = pos.row; - this.column = pos.column; - this._signal("change", { - old: old, - value: pos - }); - }; - this.detach = function() { - this.document.removeEventListener("change", this.$onChange); - }; - this.attach = function(doc) { - this.document = doc || this.document; - this.document.on("change", this.$onChange); - }; - this.$clipPositionToDocument = function(row, column) { - var pos = {}; - - if (row >= this.document.getLength()) { - pos.row = Math.max(0, this.document.getLength() - 1); - pos.column = this.document.getLine(pos.row).length; - } - else if (row < 0) { - pos.row = 0; - pos.column = 0; - } - else { - pos.row = row; - pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); - } - - if (column < 0) - pos.column = 0; - - return pos; - }; - - }).call(Anchor.prototype); - - }); - - ace.define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("./lib/oop"); - var applyDelta = acequire("./apply_delta").applyDelta; - var EventEmitter = acequire("./lib/event_emitter").EventEmitter; - var Range = acequire("./range").Range; - var Anchor = acequire("./anchor").Anchor; - - var Document = function(textOrLines) { - this.$lines = [""]; - if (textOrLines.length === 0) { - this.$lines = [""]; - } else if (Array.isArray(textOrLines)) { - this.insertMergedLines({row: 0, column: 0}, textOrLines); - } else { - this.insert({row: 0, column:0}, textOrLines); - } - }; - - (function() { - - oop.implement(this, EventEmitter); - this.setValue = function(text) { - var len = this.getLength() - 1; - this.remove(new Range(0, 0, len, this.getLine(len).length)); - this.insert({row: 0, column: 0}, text); - }; - this.getValue = function() { - return this.getAllLines().join(this.getNewLineCharacter()); - }; - this.createAnchor = function(row, column) { - return new Anchor(this, row, column); - }; - if ("aaa".split(/a/).length === 0) { - this.$split = function(text) { - return text.replace(/\r\n|\r/g, "\n").split("\n"); - }; - } else { - this.$split = function(text) { - return text.split(/\r\n|\r|\n/); - }; - } - - - this.$detectNewLine = function(text) { - var match = text.match(/^.*?(\r\n|\r|\n)/m); - this.$autoNewLine = match ? match[1] : "\n"; - this._signal("changeNewLineMode"); - }; - this.getNewLineCharacter = function() { - switch (this.$newLineMode) { - case "windows": - return "\r\n"; - case "unix": - return "\n"; - default: - return this.$autoNewLine || "\n"; - } - }; - - this.$autoNewLine = ""; - this.$newLineMode = "auto"; - this.setNewLineMode = function(newLineMode) { - if (this.$newLineMode === newLineMode) - return; - - this.$newLineMode = newLineMode; - this._signal("changeNewLineMode"); - }; - this.getNewLineMode = function() { - return this.$newLineMode; - }; - this.isNewLine = function(text) { - return (text == "\r\n" || text == "\r" || text == "\n"); - }; - this.getLine = function(row) { - return this.$lines[row] || ""; - }; - this.getLines = function(firstRow, lastRow) { - return this.$lines.slice(firstRow, lastRow + 1); - }; - this.getAllLines = function() { - return this.getLines(0, this.getLength()); - }; - this.getLength = function() { - return this.$lines.length; - }; - this.getTextRange = function(range) { - return this.getLinesForRange(range).join(this.getNewLineCharacter()); - }; - this.getLinesForRange = function(range) { - var lines; - if (range.start.row === range.end.row) { - lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)]; - } else { - lines = this.getLines(range.start.row, range.end.row); - lines[0] = (lines[0] || "").substring(range.start.column); - var l = lines.length - 1; - if (range.end.row - range.start.row == l) - lines[l] = lines[l].substring(0, range.end.column); - } - return lines; - }; - this.insertLines = function(row, lines) { - console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."); - return this.insertFullLines(row, lines); - }; - this.removeLines = function(firstRow, lastRow) { - console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."); - return this.removeFullLines(firstRow, lastRow); - }; - this.insertNewLine = function(position) { - console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."); - return this.insertMergedLines(position, ["", ""]); - }; - this.insert = function(position, text) { - if (this.getLength() <= 1) - this.$detectNewLine(text); - - return this.insertMergedLines(position, this.$split(text)); - }; - this.insertInLine = function(position, text) { - var start = this.clippedPos(position.row, position.column); - var end = this.pos(position.row, position.column + text.length); - - this.applyDelta({ - start: start, - end: end, - action: "insert", - lines: [text] - }, true); - - return this.clonePos(end); - }; - - this.clippedPos = function(row, column) { - var length = this.getLength(); - if (row === undefined) { - row = length; - } else if (row < 0) { - row = 0; - } else if (row >= length) { - row = length - 1; - column = undefined; - } - var line = this.getLine(row); - if (column == undefined) - column = line.length; - column = Math.min(Math.max(column, 0), line.length); - return {row: row, column: column}; - }; - - this.clonePos = function(pos) { - return {row: pos.row, column: pos.column}; - }; - - this.pos = function(row, column) { - return {row: row, column: column}; - }; - - this.$clipPosition = function(position) { - var length = this.getLength(); - if (position.row >= length) { - position.row = Math.max(0, length - 1); - position.column = this.getLine(length - 1).length; - } else { - position.row = Math.max(0, position.row); - position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length); - } - return position; - }; - this.insertFullLines = function(row, lines) { - row = Math.min(Math.max(row, 0), this.getLength()); - var column = 0; - if (row < this.getLength()) { - lines = lines.concat([""]); - column = 0; - } else { - lines = [""].concat(lines); - row--; - column = this.$lines[row].length; - } - this.insertMergedLines({row: row, column: column}, lines); - }; - this.insertMergedLines = function(position, lines) { - var start = this.clippedPos(position.row, position.column); - var end = { - row: start.row + lines.length - 1, - column: (lines.length == 1 ? start.column : 0) + lines[lines.length - 1].length - }; - - this.applyDelta({ - start: start, - end: end, - action: "insert", - lines: lines - }); - - return this.clonePos(end); - }; - this.remove = function(range) { - var start = this.clippedPos(range.start.row, range.start.column); - var end = this.clippedPos(range.end.row, range.end.column); - this.applyDelta({ - start: start, - end: end, - action: "remove", - lines: this.getLinesForRange({start: start, end: end}) - }); - return this.clonePos(start); - }; - this.removeInLine = function(row, startColumn, endColumn) { - var start = this.clippedPos(row, startColumn); - var end = this.clippedPos(row, endColumn); - - this.applyDelta({ - start: start, - end: end, - action: "remove", - lines: this.getLinesForRange({start: start, end: end}) - }, true); - - return this.clonePos(start); - }; - this.removeFullLines = function(firstRow, lastRow) { - firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1); - lastRow = Math.min(Math.max(0, lastRow ), this.getLength() - 1); - var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0; - var deleteLastNewLine = lastRow < this.getLength() - 1; - var startRow = ( deleteFirstNewLine ? firstRow - 1 : firstRow ); - var startCol = ( deleteFirstNewLine ? this.getLine(startRow).length : 0 ); - var endRow = ( deleteLastNewLine ? lastRow + 1 : lastRow ); - var endCol = ( deleteLastNewLine ? 0 : this.getLine(endRow).length ); - var range = new Range(startRow, startCol, endRow, endCol); - var deletedLines = this.$lines.slice(firstRow, lastRow + 1); - - this.applyDelta({ - start: range.start, - end: range.end, - action: "remove", - lines: this.getLinesForRange(range) - }); - return deletedLines; - }; - this.removeNewLine = function(row) { - if (row < this.getLength() - 1 && row >= 0) { - this.applyDelta({ - start: this.pos(row, this.getLine(row).length), - end: this.pos(row + 1, 0), - action: "remove", - lines: ["", ""] - }); - } - }; - this.replace = function(range, text) { - if (!(range instanceof Range)) - range = Range.fromPoints(range.start, range.end); - if (text.length === 0 && range.isEmpty()) - return range.start; - if (text == this.getTextRange(range)) - return range.end; - - this.remove(range); - var end; - if (text) { - end = this.insert(range.start, text); - } - else { - end = range.start; - } - - return end; - }; - this.applyDeltas = function(deltas) { - for (var i=0; i=0; i--) { - this.revertDelta(deltas[i]); - } - }; - this.applyDelta = function(delta, doNotValidate) { - var isInsert = delta.action == "insert"; - if (isInsert ? delta.lines.length <= 1 && !delta.lines[0] - : !Range.comparePoints(delta.start, delta.end)) { - return; - } - - if (isInsert && delta.lines.length > 20000) - this.$splitAndapplyLargeDelta(delta, 20000); - applyDelta(this.$lines, delta, doNotValidate); - this._signal("change", delta); - }; - - this.$splitAndapplyLargeDelta = function(delta, MAX) { - var lines = delta.lines; - var l = lines.length; - var row = delta.start.row; - var column = delta.start.column; - var from = 0, to = 0; - do { - from = to; - to += MAX - 1; - var chunk = lines.slice(from, to); - if (to > l) { - delta.lines = chunk; - delta.start.row = row + from; - delta.start.column = column; - break; - } - chunk.push(""); - this.applyDelta({ - start: this.pos(row + from, column), - end: this.pos(row + to, column = 0), - action: delta.action, - lines: chunk - }, true); - } while(true); - }; - this.revertDelta = function(delta) { - this.applyDelta({ - start: this.clonePos(delta.start), - end: this.clonePos(delta.end), - action: (delta.action == "insert" ? "remove" : "insert"), - lines: delta.lines.slice() - }); - }; - this.indexToPosition = function(index, startRow) { - var lines = this.$lines || this.getAllLines(); - var newlineLength = this.getNewLineCharacter().length; - for (var i = startRow || 0, l = lines.length; i < l; i++) { - index -= lines[i].length + newlineLength; - if (index < 0) - return {row: i, column: index + lines[i].length + newlineLength}; - } - return {row: l-1, column: lines[l-1].length}; - }; - this.positionToIndex = function(pos, startRow) { - var lines = this.$lines || this.getAllLines(); - var newlineLength = this.getNewLineCharacter().length; - var index = 0; - var row = Math.min(pos.row, lines.length); - for (var i = startRow || 0; i < row; ++i) - index += lines[i].length + newlineLength; - - return index + pos.column; - }; - - }).call(Document.prototype); - - exports.Document = Document; - }); - - ace.define("ace/background_tokenizer",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("./lib/oop"); - var EventEmitter = acequire("./lib/event_emitter").EventEmitter; - - var BackgroundTokenizer = function(tokenizer, editor) { - this.running = false; - this.lines = []; - this.states = []; - this.currentLine = 0; - this.tokenizer = tokenizer; - - var self = this; - - this.$worker = function() { - if (!self.running) { return; } - - var workerStart = new Date(); - var currentLine = self.currentLine; - var endLine = -1; - var doc = self.doc; - - var startLine = currentLine; - while (self.lines[currentLine]) - currentLine++; - - var len = doc.getLength(); - var processedLines = 0; - self.running = false; - while (currentLine < len) { - self.$tokenizeRow(currentLine); - endLine = currentLine; - do { - currentLine++; - } while (self.lines[currentLine]); - processedLines ++; - if ((processedLines % 5 === 0) && (new Date() - workerStart) > 20) { - self.running = setTimeout(self.$worker, 20); - break; - } - } - self.currentLine = currentLine; - - if (endLine == -1) - endLine = currentLine; - - if (startLine <= endLine) - self.fireUpdateEvent(startLine, endLine); - }; - }; - - (function(){ - - oop.implement(this, EventEmitter); - this.setTokenizer = function(tokenizer) { - this.tokenizer = tokenizer; - this.lines = []; - this.states = []; - - this.start(0); - }; - this.setDocument = function(doc) { - this.doc = doc; - this.lines = []; - this.states = []; - - this.stop(); - }; - this.fireUpdateEvent = function(firstRow, lastRow) { - var data = { - first: firstRow, - last: lastRow - }; - this._signal("update", {data: data}); - }; - this.start = function(startRow) { - this.currentLine = Math.min(startRow || 0, this.currentLine, this.doc.getLength()); - this.lines.splice(this.currentLine, this.lines.length); - this.states.splice(this.currentLine, this.states.length); - - this.stop(); - this.running = setTimeout(this.$worker, 700); - }; - - this.scheduleStart = function() { - if (!this.running) - this.running = setTimeout(this.$worker, 700); - }; - - this.$updateOnChange = function(delta) { - var startRow = delta.start.row; - var len = delta.end.row - startRow; - - if (len === 0) { - this.lines[startRow] = null; - } else if (delta.action == "remove") { - this.lines.splice(startRow, len + 1, null); - this.states.splice(startRow, len + 1, null); - } else { - var args = Array(len + 1); - args.unshift(startRow, 1); - this.lines.splice.apply(this.lines, args); - this.states.splice.apply(this.states, args); - } - - this.currentLine = Math.min(startRow, this.currentLine, this.doc.getLength()); - - this.stop(); - }; - this.stop = function() { - if (this.running) - clearTimeout(this.running); - this.running = false; - }; - this.getTokens = function(row) { - return this.lines[row] || this.$tokenizeRow(row); - }; - this.getState = function(row) { - if (this.currentLine == row) - this.$tokenizeRow(row); - return this.states[row] || "start"; - }; - - this.$tokenizeRow = function(row) { - var line = this.doc.getLine(row); - var state = this.states[row - 1]; - - var data = this.tokenizer.getLineTokens(line, state, row); - - if (this.states[row] + "" !== data.state + "") { - this.states[row] = data.state; - this.lines[row + 1] = null; - if (this.currentLine > row + 1) - this.currentLine = row + 1; - } else if (this.currentLine == row) { - this.currentLine = row + 1; - } - - return this.lines[row] = data.tokens; - }; - - }).call(BackgroundTokenizer.prototype); - - exports.BackgroundTokenizer = BackgroundTokenizer; - }); - - ace.define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"], function(acequire, exports, module) { - "use strict"; - - var lang = acequire("./lib/lang"); - var oop = acequire("./lib/oop"); - var Range = acequire("./range").Range; - - var SearchHighlight = function(regExp, clazz, type) { - this.setRegexp(regExp); - this.clazz = clazz; - this.type = type || "text"; - }; - - (function() { - this.MAX_RANGES = 500; - - this.setRegexp = function(regExp) { - if (this.regExp+"" == regExp+"") - return; - this.regExp = regExp; - this.cache = []; - }; - - this.update = function(html, markerLayer, session, config) { - if (!this.regExp) - return; - var start = config.firstRow, end = config.lastRow; - - for (var i = start; i <= end; i++) { - var ranges = this.cache[i]; - if (ranges == null) { - ranges = lang.getMatchOffsets(session.getLine(i), this.regExp); - if (ranges.length > this.MAX_RANGES) - ranges = ranges.slice(0, this.MAX_RANGES); - ranges = ranges.map(function(match) { - return new Range(i, match.offset, i, match.offset + match.length); - }); - this.cache[i] = ranges.length ? ranges : ""; - } - - for (var j = ranges.length; j --; ) { - markerLayer.drawSingleLineMarker( - html, ranges[j].toScreenRange(session), this.clazz, config); - } - } - }; - - }).call(SearchHighlight.prototype); - - exports.SearchHighlight = SearchHighlight; - }); - - ace.define("ace/edit_session/fold_line",["require","exports","module","ace/range"], function(acequire, exports, module) { - "use strict"; - - var Range = acequire("../range").Range; - function FoldLine(foldData, folds) { - this.foldData = foldData; - if (Array.isArray(folds)) { - this.folds = folds; - } else { - folds = this.folds = [ folds ]; - } - - var last = folds[folds.length - 1]; - this.range = new Range(folds[0].start.row, folds[0].start.column, - last.end.row, last.end.column); - this.start = this.range.start; - this.end = this.range.end; - - this.folds.forEach(function(fold) { - fold.setFoldLine(this); - }, this); - } - - (function() { - this.shiftRow = function(shift) { - this.start.row += shift; - this.end.row += shift; - this.folds.forEach(function(fold) { - fold.start.row += shift; - fold.end.row += shift; - }); - }; - - this.addFold = function(fold) { - if (fold.sameRow) { - if (fold.start.row < this.startRow || fold.endRow > this.endRow) { - throw new Error("Can't add a fold to this FoldLine as it has no connection"); - } - this.folds.push(fold); - this.folds.sort(function(a, b) { - return -a.range.compareEnd(b.start.row, b.start.column); - }); - if (this.range.compareEnd(fold.start.row, fold.start.column) > 0) { - this.end.row = fold.end.row; - this.end.column = fold.end.column; - } else if (this.range.compareStart(fold.end.row, fold.end.column) < 0) { - this.start.row = fold.start.row; - this.start.column = fold.start.column; - } - } else if (fold.start.row == this.end.row) { - this.folds.push(fold); - this.end.row = fold.end.row; - this.end.column = fold.end.column; - } else if (fold.end.row == this.start.row) { - this.folds.unshift(fold); - this.start.row = fold.start.row; - this.start.column = fold.start.column; - } else { - throw new Error("Trying to add fold to FoldRow that doesn't have a matching row"); - } - fold.foldLine = this; - }; - - this.containsRow = function(row) { - return row >= this.start.row && row <= this.end.row; - }; - - this.walk = function(callback, endRow, endColumn) { - var lastEnd = 0, - folds = this.folds, - fold, - cmp, stop, isNewRow = true; - - if (endRow == null) { - endRow = this.end.row; - endColumn = this.end.column; - } - - for (var i = 0; i < folds.length; i++) { - fold = folds[i]; - - cmp = fold.range.compareStart(endRow, endColumn); - if (cmp == -1) { - callback(null, endRow, endColumn, lastEnd, isNewRow); - return; - } - - stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow); - stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd); - if (stop || cmp === 0) { - return; - } - isNewRow = !fold.sameRow; - lastEnd = fold.end.column; - } - callback(null, endRow, endColumn, lastEnd, isNewRow); - }; - - this.getNextFoldTo = function(row, column) { - var fold, cmp; - for (var i = 0; i < this.folds.length; i++) { - fold = this.folds[i]; - cmp = fold.range.compareEnd(row, column); - if (cmp == -1) { - return { - fold: fold, - kind: "after" - }; - } else if (cmp === 0) { - return { - fold: fold, - kind: "inside" - }; - } - } - return null; - }; - - this.addRemoveChars = function(row, column, len) { - var ret = this.getNextFoldTo(row, column), - fold, folds; - if (ret) { - fold = ret.fold; - if (ret.kind == "inside" - && fold.start.column != column - && fold.start.row != row) - { - window.console && window.console.log(row, column, fold); - } else if (fold.start.row == row) { - folds = this.folds; - var i = folds.indexOf(fold); - if (i === 0) { - this.start.column += len; - } - for (i; i < folds.length; i++) { - fold = folds[i]; - fold.start.column += len; - if (!fold.sameRow) { - return; - } - fold.end.column += len; - } - this.end.column += len; - } - } - }; - - this.split = function(row, column) { - var pos = this.getNextFoldTo(row, column); - - if (!pos || pos.kind == "inside") - return null; - - var fold = pos.fold; - var folds = this.folds; - var foldData = this.foldData; - - var i = folds.indexOf(fold); - var foldBefore = folds[i - 1]; - this.end.row = foldBefore.end.row; - this.end.column = foldBefore.end.column; - folds = folds.splice(i, folds.length - i); - - var newFoldLine = new FoldLine(foldData, folds); - foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine); - return newFoldLine; - }; - - this.merge = function(foldLineNext) { - var folds = foldLineNext.folds; - for (var i = 0; i < folds.length; i++) { - this.addFold(folds[i]); - } - var foldData = this.foldData; - foldData.splice(foldData.indexOf(foldLineNext), 1); - }; - - this.toString = function() { - var ret = [this.range.toString() + ": [" ]; - - this.folds.forEach(function(fold) { - ret.push(" " + fold.toString()); - }); - ret.push("]"); - return ret.join("\n"); - }; - - this.idxToPosition = function(idx) { - var lastFoldEndColumn = 0; - - for (var i = 0; i < this.folds.length; i++) { - var fold = this.folds[i]; - - idx -= fold.start.column - lastFoldEndColumn; - if (idx < 0) { - return { - row: fold.start.row, - column: fold.start.column + idx - }; - } - - idx -= fold.placeholder.length; - if (idx < 0) { - return fold.start; - } - - lastFoldEndColumn = fold.end.column; - } - - return { - row: this.end.row, - column: this.end.column + idx - }; - }; - }).call(FoldLine.prototype); - - exports.FoldLine = FoldLine; - }); - - ace.define("ace/range_list",["require","exports","module","ace/range"], function(acequire, exports, module) { - "use strict"; - var Range = acequire("./range").Range; - var comparePoints = Range.comparePoints; - - var RangeList = function() { - this.ranges = []; - }; - - (function() { - this.comparePoints = comparePoints; - - this.pointIndex = function(pos, excludeEdges, startIndex) { - var list = this.ranges; - - for (var i = startIndex || 0; i < list.length; i++) { - var range = list[i]; - var cmpEnd = comparePoints(pos, range.end); - if (cmpEnd > 0) - continue; - var cmpStart = comparePoints(pos, range.start); - if (cmpEnd === 0) - return excludeEdges && cmpStart !== 0 ? -i-2 : i; - if (cmpStart > 0 || (cmpStart === 0 && !excludeEdges)) - return i; - - return -i-1; - } - return -i - 1; - }; - - this.add = function(range) { - var excludeEdges = !range.isEmpty(); - var startIndex = this.pointIndex(range.start, excludeEdges); - if (startIndex < 0) - startIndex = -startIndex - 1; - - var endIndex = this.pointIndex(range.end, excludeEdges, startIndex); - - if (endIndex < 0) - endIndex = -endIndex - 1; - else - endIndex++; - return this.ranges.splice(startIndex, endIndex - startIndex, range); - }; - - this.addList = function(list) { - var removed = []; - for (var i = list.length; i--; ) { - removed.push.apply(removed, this.add(list[i])); - } - return removed; - }; - - this.substractPoint = function(pos) { - var i = this.pointIndex(pos); - - if (i >= 0) - return this.ranges.splice(i, 1); - }; - this.merge = function() { - var removed = []; - var list = this.ranges; - - list = list.sort(function(a, b) { - return comparePoints(a.start, b.start); - }); - - var next = list[0], range; - for (var i = 1; i < list.length; i++) { - range = next; - next = list[i]; - var cmp = comparePoints(range.end, next.start); - if (cmp < 0) - continue; - - if (cmp == 0 && !range.isEmpty() && !next.isEmpty()) - continue; - - if (comparePoints(range.end, next.end) < 0) { - range.end.row = next.end.row; - range.end.column = next.end.column; - } - - list.splice(i, 1); - removed.push(next); - next = range; - i--; - } - - this.ranges = list; - - return removed; - }; - - this.contains = function(row, column) { - return this.pointIndex({row: row, column: column}) >= 0; - }; - - this.containsPoint = function(pos) { - return this.pointIndex(pos) >= 0; - }; - - this.rangeAtPoint = function(pos) { - var i = this.pointIndex(pos); - if (i >= 0) - return this.ranges[i]; - }; - - - this.clipRows = function(startRow, endRow) { - var list = this.ranges; - if (list[0].start.row > endRow || list[list.length - 1].start.row < startRow) - return []; - - var startIndex = this.pointIndex({row: startRow, column: 0}); - if (startIndex < 0) - startIndex = -startIndex - 1; - var endIndex = this.pointIndex({row: endRow, column: 0}, startIndex); - if (endIndex < 0) - endIndex = -endIndex - 1; - - var clipped = []; - for (var i = startIndex; i < endIndex; i++) { - clipped.push(list[i]); - } - return clipped; - }; - - this.removeAll = function() { - return this.ranges.splice(0, this.ranges.length); - }; - - this.attach = function(session) { - if (this.session) - this.detach(); - - this.session = session; - this.onChange = this.$onChange.bind(this); - - this.session.on('change', this.onChange); - }; - - this.detach = function() { - if (!this.session) - return; - this.session.removeListener('change', this.onChange); - this.session = null; - }; - - this.$onChange = function(delta) { - if (delta.action == "insert"){ - var start = delta.start; - var end = delta.end; - } else { - var end = delta.start; - var start = delta.end; - } - var startRow = start.row; - var endRow = end.row; - var lineDif = endRow - startRow; - - var colDiff = -start.column + end.column; - var ranges = this.ranges; - - for (var i = 0, n = ranges.length; i < n; i++) { - var r = ranges[i]; - if (r.end.row < startRow) - continue; - if (r.start.row > startRow) - break; - - if (r.start.row == startRow && r.start.column >= start.column ) { - if (r.start.column == start.column && this.$insertRight) { - } else { - r.start.column += colDiff; - r.start.row += lineDif; - } - } - if (r.end.row == startRow && r.end.column >= start.column) { - if (r.end.column == start.column && this.$insertRight) { - continue; - } - if (r.end.column == start.column && colDiff > 0 && i < n - 1) { - if (r.end.column > r.start.column && r.end.column == ranges[i+1].start.column) - r.end.column -= colDiff; - } - r.end.column += colDiff; - r.end.row += lineDif; - } - } - - if (lineDif != 0 && i < n) { - for (; i < n; i++) { - var r = ranges[i]; - r.start.row += lineDif; - r.end.row += lineDif; - } - } - }; - - }).call(RangeList.prototype); - - exports.RangeList = RangeList; - }); - - ace.define("ace/edit_session/fold",["require","exports","module","ace/range","ace/range_list","ace/lib/oop"], function(acequire, exports, module) { - "use strict"; - - var Range = acequire("../range").Range; - var RangeList = acequire("../range_list").RangeList; - var oop = acequire("../lib/oop"); - var Fold = exports.Fold = function(range, placeholder) { - this.foldLine = null; - this.placeholder = placeholder; - this.range = range; - this.start = range.start; - this.end = range.end; - - this.sameRow = range.start.row == range.end.row; - this.subFolds = this.ranges = []; - }; - - oop.inherits(Fold, RangeList); - - (function() { - - this.toString = function() { - return '"' + this.placeholder + '" ' + this.range.toString(); - }; - - this.setFoldLine = function(foldLine) { - this.foldLine = foldLine; - this.subFolds.forEach(function(fold) { - fold.setFoldLine(foldLine); - }); - }; - - this.clone = function() { - var range = this.range.clone(); - var fold = new Fold(range, this.placeholder); - this.subFolds.forEach(function(subFold) { - fold.subFolds.push(subFold.clone()); - }); - fold.collapseChildren = this.collapseChildren; - return fold; - }; - - this.addSubFold = function(fold) { - if (this.range.isEqual(fold)) - return; - - if (!this.range.containsRange(fold)) - throw new Error("A fold can't intersect already existing fold" + fold.range + this.range); - consumeRange(fold, this.start); - - var row = fold.start.row, column = fold.start.column; - for (var i = 0, cmp = -1; i < this.subFolds.length; i++) { - cmp = this.subFolds[i].range.compare(row, column); - if (cmp != 1) - break; - } - var afterStart = this.subFolds[i]; - - if (cmp == 0) - return afterStart.addSubFold(fold); - var row = fold.range.end.row, column = fold.range.end.column; - for (var j = i, cmp = -1; j < this.subFolds.length; j++) { - cmp = this.subFolds[j].range.compare(row, column); - if (cmp != 1) - break; - } - var afterEnd = this.subFolds[j]; - - if (cmp == 0) - throw new Error("A fold can't intersect already existing fold" + fold.range + this.range); - - var consumedFolds = this.subFolds.splice(i, j - i, fold); - fold.setFoldLine(this.foldLine); - - return fold; - }; - - this.restoreRange = function(range) { - return restoreRange(range, this.start); - }; - - }).call(Fold.prototype); - - function consumePoint(point, anchor) { - point.row -= anchor.row; - if (point.row == 0) - point.column -= anchor.column; - } - function consumeRange(range, anchor) { - consumePoint(range.start, anchor); - consumePoint(range.end, anchor); - } - function restorePoint(point, anchor) { - if (point.row == 0) - point.column += anchor.column; - point.row += anchor.row; - } - function restoreRange(range, anchor) { - restorePoint(range.start, anchor); - restorePoint(range.end, anchor); - } - - }); - - ace.define("ace/edit_session/folding",["require","exports","module","ace/range","ace/edit_session/fold_line","ace/edit_session/fold","ace/token_iterator"], function(acequire, exports, module) { - "use strict"; - - var Range = acequire("../range").Range; - var FoldLine = acequire("./fold_line").FoldLine; - var Fold = acequire("./fold").Fold; - var TokenIterator = acequire("../token_iterator").TokenIterator; - - function Folding() { - this.getFoldAt = function(row, column, side) { - var foldLine = this.getFoldLine(row); - if (!foldLine) - return null; - - var folds = foldLine.folds; - for (var i = 0; i < folds.length; i++) { - var fold = folds[i]; - if (fold.range.contains(row, column)) { - if (side == 1 && fold.range.isEnd(row, column)) { - continue; - } else if (side == -1 && fold.range.isStart(row, column)) { - continue; - } - return fold; - } - } - }; - this.getFoldsInRange = function(range) { - var start = range.start; - var end = range.end; - var foldLines = this.$foldData; - var foundFolds = []; - - start.column += 1; - end.column -= 1; - - for (var i = 0; i < foldLines.length; i++) { - var cmp = foldLines[i].range.compareRange(range); - if (cmp == 2) { - continue; - } - else if (cmp == -2) { - break; - } - - var folds = foldLines[i].folds; - for (var j = 0; j < folds.length; j++) { - var fold = folds[j]; - cmp = fold.range.compareRange(range); - if (cmp == -2) { - break; - } else if (cmp == 2) { - continue; - } else - if (cmp == 42) { - break; - } - foundFolds.push(fold); - } - } - start.column -= 1; - end.column += 1; - - return foundFolds; - }; - - this.getFoldsInRangeList = function(ranges) { - if (Array.isArray(ranges)) { - var folds = []; - ranges.forEach(function(range) { - folds = folds.concat(this.getFoldsInRange(range)); - }, this); - } else { - var folds = this.getFoldsInRange(ranges); - } - return folds; - }; - this.getAllFolds = function() { - var folds = []; - var foldLines = this.$foldData; - - for (var i = 0; i < foldLines.length; i++) - for (var j = 0; j < foldLines[i].folds.length; j++) - folds.push(foldLines[i].folds[j]); - - return folds; - }; - this.getFoldStringAt = function(row, column, trim, foldLine) { - foldLine = foldLine || this.getFoldLine(row); - if (!foldLine) - return null; - - var lastFold = { - end: { column: 0 } - }; - var str, fold; - for (var i = 0; i < foldLine.folds.length; i++) { - fold = foldLine.folds[i]; - var cmp = fold.range.compareEnd(row, column); - if (cmp == -1) { - str = this - .getLine(fold.start.row) - .substring(lastFold.end.column, fold.start.column); - break; - } - else if (cmp === 0) { - return null; - } - lastFold = fold; - } - if (!str) - str = this.getLine(fold.start.row).substring(lastFold.end.column); - - if (trim == -1) - return str.substring(0, column - lastFold.end.column); - else if (trim == 1) - return str.substring(column - lastFold.end.column); - else - return str; - }; - - this.getFoldLine = function(docRow, startFoldLine) { - var foldData = this.$foldData; - var i = 0; - if (startFoldLine) - i = foldData.indexOf(startFoldLine); - if (i == -1) - i = 0; - for (i; i < foldData.length; i++) { - var foldLine = foldData[i]; - if (foldLine.start.row <= docRow && foldLine.end.row >= docRow) { - return foldLine; - } else if (foldLine.end.row > docRow) { - return null; - } - } - return null; - }; - this.getNextFoldLine = function(docRow, startFoldLine) { - var foldData = this.$foldData; - var i = 0; - if (startFoldLine) - i = foldData.indexOf(startFoldLine); - if (i == -1) - i = 0; - for (i; i < foldData.length; i++) { - var foldLine = foldData[i]; - if (foldLine.end.row >= docRow) { - return foldLine; - } - } - return null; - }; - - this.getFoldedRowCount = function(first, last) { - var foldData = this.$foldData, rowCount = last-first+1; - for (var i = 0; i < foldData.length; i++) { - var foldLine = foldData[i], - end = foldLine.end.row, - start = foldLine.start.row; - if (end >= last) { - if (start < last) { - if (start >= first) - rowCount -= last-start; - else - rowCount = 0; // in one fold - } - break; - } else if (end >= first){ - if (start >= first) // fold inside range - rowCount -= end-start; - else - rowCount -= end-first+1; - } - } - return rowCount; - }; - - this.$addFoldLine = function(foldLine) { - this.$foldData.push(foldLine); - this.$foldData.sort(function(a, b) { - return a.start.row - b.start.row; - }); - return foldLine; - }; - this.addFold = function(placeholder, range) { - var foldData = this.$foldData; - var added = false; - var fold; - - if (placeholder instanceof Fold) - fold = placeholder; - else { - fold = new Fold(range, placeholder); - fold.collapseChildren = range.collapseChildren; - } - this.$clipRangeToDocument(fold.range); - - var startRow = fold.start.row; - var startColumn = fold.start.column; - var endRow = fold.end.row; - var endColumn = fold.end.column; - if (!(startRow < endRow || - startRow == endRow && startColumn <= endColumn - 2)) - throw new Error("The range has to be at least 2 characters width"); - - var startFold = this.getFoldAt(startRow, startColumn, 1); - var endFold = this.getFoldAt(endRow, endColumn, -1); - if (startFold && endFold == startFold) - return startFold.addSubFold(fold); - - if (startFold && !startFold.range.isStart(startRow, startColumn)) - this.removeFold(startFold); - - if (endFold && !endFold.range.isEnd(endRow, endColumn)) - this.removeFold(endFold); - var folds = this.getFoldsInRange(fold.range); - if (folds.length > 0) { - this.removeFolds(folds); - folds.forEach(function(subFold) { - fold.addSubFold(subFold); - }); - } - - for (var i = 0; i < foldData.length; i++) { - var foldLine = foldData[i]; - if (endRow == foldLine.start.row) { - foldLine.addFold(fold); - added = true; - break; - } else if (startRow == foldLine.end.row) { - foldLine.addFold(fold); - added = true; - if (!fold.sameRow) { - var foldLineNext = foldData[i + 1]; - if (foldLineNext && foldLineNext.start.row == endRow) { - foldLine.merge(foldLineNext); - break; - } - } - break; - } else if (endRow <= foldLine.start.row) { - break; - } - } - - if (!added) - foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold)); - - if (this.$useWrapMode) - this.$updateWrapData(foldLine.start.row, foldLine.start.row); - else - this.$updateRowLengthCache(foldLine.start.row, foldLine.start.row); - this.$modified = true; - this._signal("changeFold", { data: fold, action: "add" }); - - return fold; - }; - - this.addFolds = function(folds) { - folds.forEach(function(fold) { - this.addFold(fold); - }, this); - }; - - this.removeFold = function(fold) { - var foldLine = fold.foldLine; - var startRow = foldLine.start.row; - var endRow = foldLine.end.row; - - var foldLines = this.$foldData; - var folds = foldLine.folds; - if (folds.length == 1) { - foldLines.splice(foldLines.indexOf(foldLine), 1); - } else - if (foldLine.range.isEnd(fold.end.row, fold.end.column)) { - folds.pop(); - foldLine.end.row = folds[folds.length - 1].end.row; - foldLine.end.column = folds[folds.length - 1].end.column; - } else - if (foldLine.range.isStart(fold.start.row, fold.start.column)) { - folds.shift(); - foldLine.start.row = folds[0].start.row; - foldLine.start.column = folds[0].start.column; - } else - if (fold.sameRow) { - folds.splice(folds.indexOf(fold), 1); - } else - { - var newFoldLine = foldLine.split(fold.start.row, fold.start.column); - folds = newFoldLine.folds; - folds.shift(); - newFoldLine.start.row = folds[0].start.row; - newFoldLine.start.column = folds[0].start.column; - } - - if (!this.$updating) { - if (this.$useWrapMode) - this.$updateWrapData(startRow, endRow); - else - this.$updateRowLengthCache(startRow, endRow); - } - this.$modified = true; - this._signal("changeFold", { data: fold, action: "remove" }); - }; - - this.removeFolds = function(folds) { - var cloneFolds = []; - for (var i = 0; i < folds.length; i++) { - cloneFolds.push(folds[i]); - } - - cloneFolds.forEach(function(fold) { - this.removeFold(fold); - }, this); - this.$modified = true; - }; - - this.expandFold = function(fold) { - this.removeFold(fold); - fold.subFolds.forEach(function(subFold) { - fold.restoreRange(subFold); - this.addFold(subFold); - }, this); - if (fold.collapseChildren > 0) { - this.foldAll(fold.start.row+1, fold.end.row, fold.collapseChildren-1); - } - fold.subFolds = []; - }; - - this.expandFolds = function(folds) { - folds.forEach(function(fold) { - this.expandFold(fold); - }, this); - }; - - this.unfold = function(location, expandInner) { - var range, folds; - if (location == null) { - range = new Range(0, 0, this.getLength(), 0); - expandInner = true; - } else if (typeof location == "number") - range = new Range(location, 0, location, this.getLine(location).length); - else if ("row" in location) - range = Range.fromPoints(location, location); - else - range = location; - - folds = this.getFoldsInRangeList(range); - if (expandInner) { - this.removeFolds(folds); - } else { - var subFolds = folds; - while (subFolds.length) { - this.expandFolds(subFolds); - subFolds = this.getFoldsInRangeList(range); - } - } - if (folds.length) - return folds; - }; - this.isRowFolded = function(docRow, startFoldRow) { - return !!this.getFoldLine(docRow, startFoldRow); - }; - - this.getRowFoldEnd = function(docRow, startFoldRow) { - var foldLine = this.getFoldLine(docRow, startFoldRow); - return foldLine ? foldLine.end.row : docRow; - }; - - this.getRowFoldStart = function(docRow, startFoldRow) { - var foldLine = this.getFoldLine(docRow, startFoldRow); - return foldLine ? foldLine.start.row : docRow; - }; - - this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) { - if (startRow == null) - startRow = foldLine.start.row; - if (startColumn == null) - startColumn = 0; - if (endRow == null) - endRow = foldLine.end.row; - if (endColumn == null) - endColumn = this.getLine(endRow).length; - var doc = this.doc; - var textLine = ""; - - foldLine.walk(function(placeholder, row, column, lastColumn) { - if (row < startRow) - return; - if (row == startRow) { - if (column < startColumn) - return; - lastColumn = Math.max(startColumn, lastColumn); - } - - if (placeholder != null) { - textLine += placeholder; - } else { - textLine += doc.getLine(row).substring(lastColumn, column); - } - }, endRow, endColumn); - return textLine; - }; - - this.getDisplayLine = function(row, endColumn, startRow, startColumn) { - var foldLine = this.getFoldLine(row); - - if (!foldLine) { - var line; - line = this.doc.getLine(row); - return line.substring(startColumn || 0, endColumn || line.length); - } else { - return this.getFoldDisplayLine( - foldLine, row, endColumn, startRow, startColumn); - } - }; - - this.$cloneFoldData = function() { - var fd = []; - fd = this.$foldData.map(function(foldLine) { - var folds = foldLine.folds.map(function(fold) { - return fold.clone(); - }); - return new FoldLine(fd, folds); - }); - - return fd; - }; - - this.toggleFold = function(tryToUnfold) { - var selection = this.selection; - var range = selection.getRange(); - var fold; - var bracketPos; - - if (range.isEmpty()) { - var cursor = range.start; - fold = this.getFoldAt(cursor.row, cursor.column); - - if (fold) { - this.expandFold(fold); - return; - } else if (bracketPos = this.findMatchingBracket(cursor)) { - if (range.comparePoint(bracketPos) == 1) { - range.end = bracketPos; - } else { - range.start = bracketPos; - range.start.column++; - range.end.column--; - } - } else if (bracketPos = this.findMatchingBracket({row: cursor.row, column: cursor.column + 1})) { - if (range.comparePoint(bracketPos) == 1) - range.end = bracketPos; - else - range.start = bracketPos; - - range.start.column++; - } else { - range = this.getCommentFoldRange(cursor.row, cursor.column) || range; - } - } else { - var folds = this.getFoldsInRange(range); - if (tryToUnfold && folds.length) { - this.expandFolds(folds); - return; - } else if (folds.length == 1 ) { - fold = folds[0]; - } - } - - if (!fold) - fold = this.getFoldAt(range.start.row, range.start.column); - - if (fold && fold.range.toString() == range.toString()) { - this.expandFold(fold); - return; - } - - var placeholder = "..."; - if (!range.isMultiLine()) { - placeholder = this.getTextRange(range); - if (placeholder.length < 4) - return; - placeholder = placeholder.trim().substring(0, 2) + ".."; - } - - this.addFold(placeholder, range); - }; - - this.getCommentFoldRange = function(row, column, dir) { - var iterator = new TokenIterator(this, row, column); - var token = iterator.getCurrentToken(); - var type = token.type; - if (token && /^comment|string/.test(type)) { - type = type.match(/comment|string/)[0]; - if (type == "comment") - type += "|doc-start"; - var re = new RegExp(type); - var range = new Range(); - if (dir != 1) { - do { - token = iterator.stepBackward(); - } while (token && re.test(token.type)); - iterator.stepForward(); - } - - range.start.row = iterator.getCurrentTokenRow(); - range.start.column = iterator.getCurrentTokenColumn() + 2; - - iterator = new TokenIterator(this, row, column); - - if (dir != -1) { - var lastRow = -1; - do { - token = iterator.stepForward(); - if (lastRow == -1) { - var state = this.getState(iterator.$row); - if (!re.test(state)) - lastRow = iterator.$row; - } else if (iterator.$row > lastRow) { - break; - } - } while (token && re.test(token.type)); - token = iterator.stepBackward(); - } else - token = iterator.getCurrentToken(); - - range.end.row = iterator.getCurrentTokenRow(); - range.end.column = iterator.getCurrentTokenColumn() + token.value.length - 2; - return range; - } - }; - - this.foldAll = function(startRow, endRow, depth) { - if (depth == undefined) - depth = 100000; // JSON.stringify doesn't hanle Infinity - var foldWidgets = this.foldWidgets; - if (!foldWidgets) - return; // mode doesn't support folding - endRow = endRow || this.getLength(); - startRow = startRow || 0; - for (var row = startRow; row < endRow; row++) { - if (foldWidgets[row] == null) - foldWidgets[row] = this.getFoldWidget(row); - if (foldWidgets[row] != "start") - continue; - - var range = this.getFoldWidgetRange(row); - if (range && range.isMultiLine() - && range.end.row <= endRow - && range.start.row >= startRow - ) { - row = range.end.row; - try { - var fold = this.addFold("...", range); - if (fold) - fold.collapseChildren = depth; - } catch(e) {} - } - } - }; - this.$foldStyles = { - "manual": 1, - "markbegin": 1, - "markbeginend": 1 - }; - this.$foldStyle = "markbegin"; - this.setFoldStyle = function(style) { - if (!this.$foldStyles[style]) - throw new Error("invalid fold style: " + style + "[" + Object.keys(this.$foldStyles).join(", ") + "]"); - - if (this.$foldStyle == style) - return; - - this.$foldStyle = style; - - if (style == "manual") - this.unfold(); - var mode = this.$foldMode; - this.$setFolding(null); - this.$setFolding(mode); - }; - - this.$setFolding = function(foldMode) { - if (this.$foldMode == foldMode) - return; - - this.$foldMode = foldMode; - - this.off('change', this.$updateFoldWidgets); - this.off('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets); - this._signal("changeAnnotation"); - - if (!foldMode || this.$foldStyle == "manual") { - this.foldWidgets = null; - return; - } - - this.foldWidgets = []; - this.getFoldWidget = foldMode.getFoldWidget.bind(foldMode, this, this.$foldStyle); - this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(foldMode, this, this.$foldStyle); - - this.$updateFoldWidgets = this.updateFoldWidgets.bind(this); - this.$tokenizerUpdateFoldWidgets = this.tokenizerUpdateFoldWidgets.bind(this); - this.on('change', this.$updateFoldWidgets); - this.on('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets); - }; - - this.getParentFoldRangeData = function (row, ignoreCurrent) { - var fw = this.foldWidgets; - if (!fw || (ignoreCurrent && fw[row])) - return {}; - - var i = row - 1, firstRange; - while (i >= 0) { - var c = fw[i]; - if (c == null) - c = fw[i] = this.getFoldWidget(i); - - if (c == "start") { - var range = this.getFoldWidgetRange(i); - if (!firstRange) - firstRange = range; - if (range && range.end.row >= row) - break; - } - i--; - } - - return { - range: i !== -1 && range, - firstRange: firstRange - }; - }; - - this.onFoldWidgetClick = function(row, e) { - e = e.domEvent; - var options = { - children: e.shiftKey, - all: e.ctrlKey || e.metaKey, - siblings: e.altKey - }; - - var range = this.$toggleFoldWidget(row, options); - if (!range) { - var el = (e.target || e.srcElement); - if (el && /ace_fold-widget/.test(el.className)) - el.className += " ace_invalid"; - } - }; - - this.$toggleFoldWidget = function(row, options) { - if (!this.getFoldWidget) - return; - var type = this.getFoldWidget(row); - var line = this.getLine(row); - - var dir = type === "end" ? -1 : 1; - var fold = this.getFoldAt(row, dir === -1 ? 0 : line.length, dir); - - if (fold) { - if (options.children || options.all) - this.removeFold(fold); - else - this.expandFold(fold); - return fold; - } - - var range = this.getFoldWidgetRange(row, true); - if (range && !range.isMultiLine()) { - fold = this.getFoldAt(range.start.row, range.start.column, 1); - if (fold && range.isEqual(fold.range)) { - this.removeFold(fold); - return fold; - } - } - - if (options.siblings) { - var data = this.getParentFoldRangeData(row); - if (data.range) { - var startRow = data.range.start.row + 1; - var endRow = data.range.end.row; - } - this.foldAll(startRow, endRow, options.all ? 10000 : 0); - } else if (options.children) { - endRow = range ? range.end.row : this.getLength(); - this.foldAll(row + 1, endRow, options.all ? 10000 : 0); - } else if (range) { - if (options.all) - range.collapseChildren = 10000; - this.addFold("...", range); - } - - return range; - }; - - - - this.toggleFoldWidget = function(toggleParent) { - var row = this.selection.getCursor().row; - row = this.getRowFoldStart(row); - var range = this.$toggleFoldWidget(row, {}); - - if (range) - return; - var data = this.getParentFoldRangeData(row, true); - range = data.range || data.firstRange; - - if (range) { - row = range.start.row; - var fold = this.getFoldAt(row, this.getLine(row).length, 1); - - if (fold) { - this.removeFold(fold); - } else { - this.addFold("...", range); - } - } - }; - - this.updateFoldWidgets = function(delta) { - var firstRow = delta.start.row; - var len = delta.end.row - firstRow; - - if (len === 0) { - this.foldWidgets[firstRow] = null; - } else if (delta.action == 'remove') { - this.foldWidgets.splice(firstRow, len + 1, null); - } else { - var args = Array(len + 1); - args.unshift(firstRow, 1); - this.foldWidgets.splice.apply(this.foldWidgets, args); - } - }; - this.tokenizerUpdateFoldWidgets = function(e) { - var rows = e.data; - if (rows.first != rows.last) { - if (this.foldWidgets.length > rows.first) - this.foldWidgets.splice(rows.first, this.foldWidgets.length); - } - }; - } - - exports.Folding = Folding; - - }); - - ace.define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"], function(acequire, exports, module) { - "use strict"; - - var TokenIterator = acequire("../token_iterator").TokenIterator; - var Range = acequire("../range").Range; - - - function BracketMatch() { - - this.findMatchingBracket = function(position, chr) { - if (position.column == 0) return null; - - var charBeforeCursor = chr || this.getLine(position.row).charAt(position.column-1); - if (charBeforeCursor == "") return null; - - var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/); - if (!match) - return null; - - if (match[1]) - return this.$findClosingBracket(match[1], position); - else - return this.$findOpeningBracket(match[2], position); - }; - - this.getBracketRange = function(pos) { - var line = this.getLine(pos.row); - var before = true, range; - - var chr = line.charAt(pos.column-1); - var match = chr && chr.match(/([\(\[\{])|([\)\]\}])/); - if (!match) { - chr = line.charAt(pos.column); - pos = {row: pos.row, column: pos.column + 1}; - match = chr && chr.match(/([\(\[\{])|([\)\]\}])/); - before = false; - } - if (!match) - return null; - - if (match[1]) { - var bracketPos = this.$findClosingBracket(match[1], pos); - if (!bracketPos) - return null; - range = Range.fromPoints(pos, bracketPos); - if (!before) { - range.end.column++; - range.start.column--; - } - range.cursor = range.end; - } else { - var bracketPos = this.$findOpeningBracket(match[2], pos); - if (!bracketPos) - return null; - range = Range.fromPoints(bracketPos, pos); - if (!before) { - range.start.column++; - range.end.column--; - } - range.cursor = range.start; - } - - return range; - }; - - this.$brackets = { - ")": "(", - "(": ")", - "]": "[", - "[": "]", - "{": "}", - "}": "{" - }; - - this.$findOpeningBracket = function(bracket, position, typeRe) { - var openBracket = this.$brackets[bracket]; - var depth = 1; - - var iterator = new TokenIterator(this, position.row, position.column); - var token = iterator.getCurrentToken(); - if (!token) - token = iterator.stepForward(); - if (!token) - return; - - if (!typeRe){ - typeRe = new RegExp( - "(\\.?" + - token.type.replace(".", "\\.").replace("rparen", ".paren") - .replace(/\b(?:end)\b/, "(?:start|begin|end)") - + ")+" - ); - } - var valueIndex = position.column - iterator.getCurrentTokenColumn() - 2; - var value = token.value; - - while (true) { - - while (valueIndex >= 0) { - var chr = value.charAt(valueIndex); - if (chr == openBracket) { - depth -= 1; - if (depth == 0) { - return {row: iterator.getCurrentTokenRow(), - column: valueIndex + iterator.getCurrentTokenColumn()}; - } - } - else if (chr == bracket) { - depth += 1; - } - valueIndex -= 1; - } - do { - token = iterator.stepBackward(); - } while (token && !typeRe.test(token.type)); - - if (token == null) - break; - - value = token.value; - valueIndex = value.length - 1; - } - - return null; - }; - - this.$findClosingBracket = function(bracket, position, typeRe) { - var closingBracket = this.$brackets[bracket]; - var depth = 1; - - var iterator = new TokenIterator(this, position.row, position.column); - var token = iterator.getCurrentToken(); - if (!token) - token = iterator.stepForward(); - if (!token) - return; - - if (!typeRe){ - typeRe = new RegExp( - "(\\.?" + - token.type.replace(".", "\\.").replace("lparen", ".paren") - .replace(/\b(?:start|begin)\b/, "(?:start|begin|end)") - + ")+" - ); - } - var valueIndex = position.column - iterator.getCurrentTokenColumn(); - - while (true) { - - var value = token.value; - var valueLength = value.length; - while (valueIndex < valueLength) { - var chr = value.charAt(valueIndex); - if (chr == closingBracket) { - depth -= 1; - if (depth == 0) { - return {row: iterator.getCurrentTokenRow(), - column: valueIndex + iterator.getCurrentTokenColumn()}; - } - } - else if (chr == bracket) { - depth += 1; - } - valueIndex += 1; - } - do { - token = iterator.stepForward(); - } while (token && !typeRe.test(token.type)); - - if (token == null) - break; - - valueIndex = 0; - } - - return null; - }; - } - exports.BracketMatch = BracketMatch; - - }); - - ace.define("ace/edit_session",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/bidihandler","ace/config","ace/lib/event_emitter","ace/selection","ace/mode/text","ace/range","ace/document","ace/background_tokenizer","ace/search_highlight","ace/edit_session/folding","ace/edit_session/bracket_match"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("./lib/oop"); - var lang = acequire("./lib/lang"); - var BidiHandler = acequire("./bidihandler").BidiHandler; - var config = acequire("./config"); - var EventEmitter = acequire("./lib/event_emitter").EventEmitter; - var Selection = acequire("./selection").Selection; - var TextMode = acequire("./mode/text").Mode; - var Range = acequire("./range").Range; - var Document = acequire("./document").Document; - var BackgroundTokenizer = acequire("./background_tokenizer").BackgroundTokenizer; - var SearchHighlight = acequire("./search_highlight").SearchHighlight; - - var EditSession = function(text, mode) { - this.$breakpoints = []; - this.$decorations = []; - this.$frontMarkers = {}; - this.$backMarkers = {}; - this.$markerId = 1; - this.$undoSelect = true; - - this.$foldData = []; - this.id = "session" + (++EditSession.$uid); - this.$foldData.toString = function() { - return this.join("\n"); - }; - this.on("changeFold", this.onChangeFold.bind(this)); - this.$onChange = this.onChange.bind(this); - - if (typeof text != "object" || !text.getLine) - text = new Document(text); - - this.$bidiHandler = new BidiHandler(this); - this.setDocument(text); - this.selection = new Selection(this); - - config.resetOptions(this); - this.setMode(mode); - config._signal("session", this); - }; - - - EditSession.$uid = 0; - - (function() { - - oop.implement(this, EventEmitter); - this.setDocument = function(doc) { - if (this.doc) - this.doc.removeListener("change", this.$onChange); - - this.doc = doc; - doc.on("change", this.$onChange); - - if (this.bgTokenizer) - this.bgTokenizer.setDocument(this.getDocument()); - - this.resetCaches(); - }; - this.getDocument = function() { - return this.doc; - }; - this.$resetRowCache = function(docRow) { - if (!docRow) { - this.$docRowCache = []; - this.$screenRowCache = []; - return; - } - var l = this.$docRowCache.length; - var i = this.$getRowCacheIndex(this.$docRowCache, docRow) + 1; - if (l > i) { - this.$docRowCache.splice(i, l); - this.$screenRowCache.splice(i, l); - } - }; - - this.$getRowCacheIndex = function(cacheArray, val) { - var low = 0; - var hi = cacheArray.length - 1; - - while (low <= hi) { - var mid = (low + hi) >> 1; - var c = cacheArray[mid]; - - if (val > c) - low = mid + 1; - else if (val < c) - hi = mid - 1; - else - return mid; - } - - return low -1; - }; - - this.resetCaches = function() { - this.$modified = true; - this.$wrapData = []; - this.$rowLengthCache = []; - this.$resetRowCache(0); - if (this.bgTokenizer) - this.bgTokenizer.start(0); - }; - - this.onChangeFold = function(e) { - var fold = e.data; - this.$resetRowCache(fold.start.row); - }; - - this.onChange = function(delta) { - this.$modified = true; - this.$bidiHandler.onChange(delta); - this.$resetRowCache(delta.start.row); - - var removedFolds = this.$updateInternalDataOnChange(delta); - if (!this.$fromUndo && this.$undoManager && !delta.ignore) { - this.$deltasDoc.push(delta); - if (removedFolds && removedFolds.length != 0) { - this.$deltasFold.push({ - action: "removeFolds", - folds: removedFolds - }); - } - - this.$informUndoManager.schedule(); - } - - this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta); - this._signal("change", delta); - }; - this.setValue = function(text) { - this.doc.setValue(text); - this.selection.moveTo(0, 0); - - this.$resetRowCache(0); - this.$deltas = []; - this.$deltasDoc = []; - this.$deltasFold = []; - this.setUndoManager(this.$undoManager); - this.getUndoManager().reset(); - }; - this.getValue = - this.toString = function() { - return this.doc.getValue(); - }; - this.getSelection = function() { - return this.selection; - }; - this.getState = function(row) { - return this.bgTokenizer.getState(row); - }; - this.getTokens = function(row) { - return this.bgTokenizer.getTokens(row); - }; - this.getTokenAt = function(row, column) { - var tokens = this.bgTokenizer.getTokens(row); - var token, c = 0; - if (column == null) { - var i = tokens.length - 1; - c = this.getLine(row).length; - } else { - for (var i = 0; i < tokens.length; i++) { - c += tokens[i].value.length; - if (c >= column) - break; - } - } - token = tokens[i]; - if (!token) - return null; - token.index = i; - token.start = c - token.value.length; - return token; - }; - this.setUndoManager = function(undoManager) { - this.$undoManager = undoManager; - this.$deltas = []; - this.$deltasDoc = []; - this.$deltasFold = []; - - if (this.$informUndoManager) - this.$informUndoManager.cancel(); - - if (undoManager) { - var self = this; - - this.$syncInformUndoManager = function() { - self.$informUndoManager.cancel(); - - if (self.$deltasFold.length) { - self.$deltas.push({ - group: "fold", - deltas: self.$deltasFold - }); - self.$deltasFold = []; - } - - if (self.$deltasDoc.length) { - self.$deltas.push({ - group: "doc", - deltas: self.$deltasDoc - }); - self.$deltasDoc = []; - } - - if (self.$deltas.length > 0) { - undoManager.execute({ - action: "aceupdate", - args: [self.$deltas, self], - merge: self.mergeUndoDeltas - }); - } - self.mergeUndoDeltas = false; - self.$deltas = []; - }; - this.$informUndoManager = lang.delayedCall(this.$syncInformUndoManager); - } - }; - this.markUndoGroup = function() { - if (this.$syncInformUndoManager) - this.$syncInformUndoManager(); - }; - - this.$defaultUndoManager = { - undo: function() {}, - redo: function() {}, - reset: function() {} - }; - this.getUndoManager = function() { - return this.$undoManager || this.$defaultUndoManager; - }; - this.getTabString = function() { - if (this.getUseSoftTabs()) { - return lang.stringRepeat(" ", this.getTabSize()); - } else { - return "\t"; - } - }; - this.setUseSoftTabs = function(val) { - this.setOption("useSoftTabs", val); - }; - this.getUseSoftTabs = function() { - return this.$useSoftTabs && !this.$mode.$indentWithTabs; - }; - this.setTabSize = function(tabSize) { - this.setOption("tabSize", tabSize); - }; - this.getTabSize = function() { - return this.$tabSize; - }; - this.isTabStop = function(position) { - return this.$useSoftTabs && (position.column % this.$tabSize === 0); - }; - this.setNavigateWithinSoftTabs = function (navigateWithinSoftTabs) { - this.setOption("navigateWithinSoftTabs", navigateWithinSoftTabs); - }; - this.getNavigateWithinSoftTabs = function() { - return this.$navigateWithinSoftTabs; - }; - - this.$overwrite = false; - this.setOverwrite = function(overwrite) { - this.setOption("overwrite", overwrite); - }; - this.getOverwrite = function() { - return this.$overwrite; - }; - this.toggleOverwrite = function() { - this.setOverwrite(!this.$overwrite); - }; - this.addGutterDecoration = function(row, className) { - if (!this.$decorations[row]) - this.$decorations[row] = ""; - this.$decorations[row] += " " + className; - this._signal("changeBreakpoint", {}); - }; - this.removeGutterDecoration = function(row, className) { - this.$decorations[row] = (this.$decorations[row] || "").replace(" " + className, ""); - this._signal("changeBreakpoint", {}); - }; - this.getBreakpoints = function() { - return this.$breakpoints; - }; - this.setBreakpoints = function(rows) { - this.$breakpoints = []; - for (var i=0; i 0) - inToken = !!line.charAt(column - 1).match(this.tokenRe); - - if (!inToken) - inToken = !!line.charAt(column).match(this.tokenRe); - - if (inToken) - var re = this.tokenRe; - else if (/^\s+$/.test(line.slice(column-1, column+1))) - var re = /\s/; - else - var re = this.nonTokenRe; - - var start = column; - if (start > 0) { - do { - start--; - } - while (start >= 0 && line.charAt(start).match(re)); - start++; - } - - var end = column; - while (end < line.length && line.charAt(end).match(re)) { - end++; - } - - return new Range(row, start, row, end); - }; - this.getAWordRange = function(row, column) { - var wordRange = this.getWordRange(row, column); - var line = this.getLine(wordRange.end.row); - - while (line.charAt(wordRange.end.column).match(/[ \t]/)) { - wordRange.end.column += 1; - } - return wordRange; - }; - this.setNewLineMode = function(newLineMode) { - this.doc.setNewLineMode(newLineMode); - }; - this.getNewLineMode = function() { - return this.doc.getNewLineMode(); - }; - this.setUseWorker = function(useWorker) { this.setOption("useWorker", useWorker); }; - this.getUseWorker = function() { return this.$useWorker; }; - this.onReloadTokenizer = function(e) { - var rows = e.data; - this.bgTokenizer.start(rows.first); - this._signal("tokenizerUpdate", e); - }; - - this.$modes = {}; - this.$mode = null; - this.$modeId = null; - this.setMode = function(mode, cb) { - if (mode && typeof mode === "object") { - if (mode.getTokenizer) - return this.$onChangeMode(mode); - var options = mode; - var path = options.path; - } else { - path = mode || "ace/mode/text"; - } - if (!this.$modes["ace/mode/text"]) - this.$modes["ace/mode/text"] = new TextMode(); - - if (this.$modes[path] && !options) { - this.$onChangeMode(this.$modes[path]); - cb && cb(); - return; - } - this.$modeId = path; - config.loadModule(["mode", path], function(m) { - if (this.$modeId !== path) - return cb && cb(); - if (this.$modes[path] && !options) { - this.$onChangeMode(this.$modes[path]); - } else if (m && m.Mode) { - m = new m.Mode(options); - if (!options) { - this.$modes[path] = m; - m.$id = path; - } - this.$onChangeMode(m); - } - cb && cb(); - }.bind(this)); - if (!this.$mode) - this.$onChangeMode(this.$modes["ace/mode/text"], true); - }; - - this.$onChangeMode = function(mode, $isPlaceholder) { - if (!$isPlaceholder) - this.$modeId = mode.$id; - if (this.$mode === mode) - return; - - this.$mode = mode; - - this.$stopWorker(); - - if (this.$useWorker) - this.$startWorker(); - - var tokenizer = mode.getTokenizer(); - - if(tokenizer.addEventListener !== undefined) { - var onReloadTokenizer = this.onReloadTokenizer.bind(this); - tokenizer.addEventListener("update", onReloadTokenizer); - } - - if (!this.bgTokenizer) { - this.bgTokenizer = new BackgroundTokenizer(tokenizer); - var _self = this; - this.bgTokenizer.addEventListener("update", function(e) { - _self._signal("tokenizerUpdate", e); - }); - } else { - this.bgTokenizer.setTokenizer(tokenizer); - } - - this.bgTokenizer.setDocument(this.getDocument()); - - this.tokenRe = mode.tokenRe; - this.nonTokenRe = mode.nonTokenRe; - - - if (!$isPlaceholder) { - if (mode.attachToSession) - mode.attachToSession(this); - this.$options.wrapMethod.set.call(this, this.$wrapMethod); - this.$setFolding(mode.foldingRules); - this.bgTokenizer.start(0); - this._emit("changeMode"); - } - }; - - this.$stopWorker = function() { - if (this.$worker) { - this.$worker.terminate(); - this.$worker = null; - } - }; - - this.$startWorker = function() { - try { - this.$worker = this.$mode.createWorker(this); - } catch (e) { - config.warn("Could not load worker", e); - this.$worker = null; - } - }; - this.getMode = function() { - return this.$mode; - }; - - this.$scrollTop = 0; - this.setScrollTop = function(scrollTop) { - if (this.$scrollTop === scrollTop || isNaN(scrollTop)) - return; - - this.$scrollTop = scrollTop; - this._signal("changeScrollTop", scrollTop); - }; - this.getScrollTop = function() { - return this.$scrollTop; - }; - - this.$scrollLeft = 0; - this.setScrollLeft = function(scrollLeft) { - if (this.$scrollLeft === scrollLeft || isNaN(scrollLeft)) - return; - - this.$scrollLeft = scrollLeft; - this._signal("changeScrollLeft", scrollLeft); - }; - this.getScrollLeft = function() { - return this.$scrollLeft; - }; - this.getScreenWidth = function() { - this.$computeWidth(); - if (this.lineWidgets) - return Math.max(this.getLineWidgetMaxWidth(), this.screenWidth); - return this.screenWidth; - }; - - this.getLineWidgetMaxWidth = function() { - if (this.lineWidgetsWidth != null) return this.lineWidgetsWidth; - var width = 0; - this.lineWidgets.forEach(function(w) { - if (w && w.screenWidth > width) - width = w.screenWidth; - }); - return this.lineWidgetWidth = width; - }; - - this.$computeWidth = function(force) { - if (this.$modified || force) { - this.$modified = false; - - if (this.$useWrapMode) - return this.screenWidth = this.$wrapLimit; - - var lines = this.doc.getAllLines(); - var cache = this.$rowLengthCache; - var longestScreenLine = 0; - var foldIndex = 0; - var foldLine = this.$foldData[foldIndex]; - var foldStart = foldLine ? foldLine.start.row : Infinity; - var len = lines.length; - - for (var i = 0; i < len; i++) { - if (i > foldStart) { - i = foldLine.end.row + 1; - if (i >= len) - break; - foldLine = this.$foldData[foldIndex++]; - foldStart = foldLine ? foldLine.start.row : Infinity; - } - - if (cache[i] == null) - cache[i] = this.$getStringScreenWidth(lines[i])[0]; - - if (cache[i] > longestScreenLine) - longestScreenLine = cache[i]; - } - this.screenWidth = longestScreenLine; - } - }; - this.getLine = function(row) { - return this.doc.getLine(row); - }; - this.getLines = function(firstRow, lastRow) { - return this.doc.getLines(firstRow, lastRow); - }; - this.getLength = function() { - return this.doc.getLength(); - }; - this.getTextRange = function(range) { - return this.doc.getTextRange(range || this.selection.getRange()); - }; - this.insert = function(position, text) { - return this.doc.insert(position, text); - }; - this.remove = function(range) { - return this.doc.remove(range); - }; - this.removeFullLines = function(firstRow, lastRow){ - return this.doc.removeFullLines(firstRow, lastRow); - }; - this.undoChanges = function(deltas, dontSelect) { - if (!deltas.length) - return; - - this.$fromUndo = true; - var lastUndoRange = null; - for (var i = deltas.length - 1; i != -1; i--) { - var delta = deltas[i]; - if (delta.group == "doc") { - this.doc.revertDeltas(delta.deltas); - lastUndoRange = - this.$getUndoSelection(delta.deltas, true, lastUndoRange); - } else { - delta.deltas.forEach(function(foldDelta) { - this.addFolds(foldDelta.folds); - }, this); - } - } - this.$fromUndo = false; - lastUndoRange && - this.$undoSelect && - !dontSelect && - this.selection.setSelectionRange(lastUndoRange); - return lastUndoRange; - }; - this.redoChanges = function(deltas, dontSelect) { - if (!deltas.length) - return; - - this.$fromUndo = true; - var lastUndoRange = null; - for (var i = 0; i < deltas.length; i++) { - var delta = deltas[i]; - if (delta.group == "doc") { - this.doc.applyDeltas(delta.deltas); - lastUndoRange = - this.$getUndoSelection(delta.deltas, false, lastUndoRange); - } - } - this.$fromUndo = false; - lastUndoRange && - this.$undoSelect && - !dontSelect && - this.selection.setSelectionRange(lastUndoRange); - return lastUndoRange; - }; - this.setUndoSelect = function(enable) { - this.$undoSelect = enable; - }; - - this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) { - function isInsert(delta) { - return isUndo ? delta.action !== "insert" : delta.action === "insert"; - } - - var delta = deltas[0]; - var range, point; - var lastDeltaIsInsert = false; - if (isInsert(delta)) { - range = Range.fromPoints(delta.start, delta.end); - lastDeltaIsInsert = true; - } else { - range = Range.fromPoints(delta.start, delta.start); - lastDeltaIsInsert = false; - } - - for (var i = 1; i < deltas.length; i++) { - delta = deltas[i]; - if (isInsert(delta)) { - point = delta.start; - if (range.compare(point.row, point.column) == -1) { - range.setStart(point); - } - point = delta.end; - if (range.compare(point.row, point.column) == 1) { - range.setEnd(point); - } - lastDeltaIsInsert = true; - } else { - point = delta.start; - if (range.compare(point.row, point.column) == -1) { - range = Range.fromPoints(delta.start, delta.start); - } - lastDeltaIsInsert = false; - } - } - if (lastUndoRange != null) { - if (Range.comparePoints(lastUndoRange.start, range.start) === 0) { - lastUndoRange.start.column += range.end.column - range.start.column; - lastUndoRange.end.column += range.end.column - range.start.column; - } - - var cmp = lastUndoRange.compareRange(range); - if (cmp == 1) { - range.setStart(lastUndoRange.start); - } else if (cmp == -1) { - range.setEnd(lastUndoRange.end); - } - } - - return range; - }; - this.replace = function(range, text) { - return this.doc.replace(range, text); - }; - this.moveText = function(fromRange, toPosition, copy) { - var text = this.getTextRange(fromRange); - var folds = this.getFoldsInRange(fromRange); - - var toRange = Range.fromPoints(toPosition, toPosition); - if (!copy) { - this.remove(fromRange); - var rowDiff = fromRange.start.row - fromRange.end.row; - var collDiff = rowDiff ? -fromRange.end.column : fromRange.start.column - fromRange.end.column; - if (collDiff) { - if (toRange.start.row == fromRange.end.row && toRange.start.column > fromRange.end.column) - toRange.start.column += collDiff; - if (toRange.end.row == fromRange.end.row && toRange.end.column > fromRange.end.column) - toRange.end.column += collDiff; - } - if (rowDiff && toRange.start.row >= fromRange.end.row) { - toRange.start.row += rowDiff; - toRange.end.row += rowDiff; - } - } - - toRange.end = this.insert(toRange.start, text); - if (folds.length) { - var oldStart = fromRange.start; - var newStart = toRange.start; - var rowDiff = newStart.row - oldStart.row; - var collDiff = newStart.column - oldStart.column; - this.addFolds(folds.map(function(x) { - x = x.clone(); - if (x.start.row == oldStart.row) - x.start.column += collDiff; - if (x.end.row == oldStart.row) - x.end.column += collDiff; - x.start.row += rowDiff; - x.end.row += rowDiff; - return x; - })); - } - - return toRange; - }; - this.indentRows = function(startRow, endRow, indentString) { - indentString = indentString.replace(/\t/g, this.getTabString()); - for (var row=startRow; row<=endRow; row++) - this.doc.insertInLine({row: row, column: 0}, indentString); - }; - this.outdentRows = function (range) { - var rowRange = range.collapseRows(); - var deleteRange = new Range(0, 0, 0, 0); - var size = this.getTabSize(); - - for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) { - var line = this.getLine(i); - - deleteRange.start.row = i; - deleteRange.end.row = i; - for (var j = 0; j < size; ++j) - if (line.charAt(j) != ' ') - break; - if (j < size && line.charAt(j) == '\t') { - deleteRange.start.column = j; - deleteRange.end.column = j + 1; - } else { - deleteRange.start.column = 0; - deleteRange.end.column = j; - } - this.remove(deleteRange); - } - }; - - this.$moveLines = function(firstRow, lastRow, dir) { - firstRow = this.getRowFoldStart(firstRow); - lastRow = this.getRowFoldEnd(lastRow); - if (dir < 0) { - var row = this.getRowFoldStart(firstRow + dir); - if (row < 0) return 0; - var diff = row-firstRow; - } else if (dir > 0) { - var row = this.getRowFoldEnd(lastRow + dir); - if (row > this.doc.getLength()-1) return 0; - var diff = row-lastRow; - } else { - firstRow = this.$clipRowToDocument(firstRow); - lastRow = this.$clipRowToDocument(lastRow); - var diff = lastRow - firstRow + 1; - } - - var range = new Range(firstRow, 0, lastRow, Number.MAX_VALUE); - var folds = this.getFoldsInRange(range).map(function(x){ - x = x.clone(); - x.start.row += diff; - x.end.row += diff; - return x; - }); - - var lines = dir == 0 - ? this.doc.getLines(firstRow, lastRow) - : this.doc.removeFullLines(firstRow, lastRow); - this.doc.insertFullLines(firstRow+diff, lines); - folds.length && this.addFolds(folds); - return diff; - }; - this.moveLinesUp = function(firstRow, lastRow) { - return this.$moveLines(firstRow, lastRow, -1); - }; - this.moveLinesDown = function(firstRow, lastRow) { - return this.$moveLines(firstRow, lastRow, 1); - }; - this.duplicateLines = function(firstRow, lastRow) { - return this.$moveLines(firstRow, lastRow, 0); - }; - - - this.$clipRowToDocument = function(row) { - return Math.max(0, Math.min(row, this.doc.getLength()-1)); - }; - - this.$clipColumnToRow = function(row, column) { - if (column < 0) - return 0; - return Math.min(this.doc.getLine(row).length, column); - }; - - - this.$clipPositionToDocument = function(row, column) { - column = Math.max(0, column); - - if (row < 0) { - row = 0; - column = 0; - } else { - var len = this.doc.getLength(); - if (row >= len) { - row = len - 1; - column = this.doc.getLine(len-1).length; - } else { - column = Math.min(this.doc.getLine(row).length, column); - } - } - - return { - row: row, - column: column - }; - }; - - this.$clipRangeToDocument = function(range) { - if (range.start.row < 0) { - range.start.row = 0; - range.start.column = 0; - } else { - range.start.column = this.$clipColumnToRow( - range.start.row, - range.start.column - ); - } - - var len = this.doc.getLength() - 1; - if (range.end.row > len) { - range.end.row = len; - range.end.column = this.doc.getLine(len).length; - } else { - range.end.column = this.$clipColumnToRow( - range.end.row, - range.end.column - ); - } - return range; - }; - this.$wrapLimit = 80; - this.$useWrapMode = false; - this.$wrapLimitRange = { - min : null, - max : null - }; - this.setUseWrapMode = function(useWrapMode) { - if (useWrapMode != this.$useWrapMode) { - this.$useWrapMode = useWrapMode; - this.$modified = true; - this.$resetRowCache(0); - if (useWrapMode) { - var len = this.getLength(); - this.$wrapData = Array(len); - this.$updateWrapData(0, len - 1); - } - - this._signal("changeWrapMode"); - } - }; - this.getUseWrapMode = function() { - return this.$useWrapMode; - }; - this.setWrapLimitRange = function(min, max) { - if (this.$wrapLimitRange.min !== min || this.$wrapLimitRange.max !== max) { - this.$wrapLimitRange = { min: min, max: max }; - this.$modified = true; - this.$bidiHandler.markAsDirty(); - if (this.$useWrapMode) - this._signal("changeWrapMode"); - } - }; - this.adjustWrapLimit = function(desiredLimit, $printMargin) { - var limits = this.$wrapLimitRange; - if (limits.max < 0) - limits = {min: $printMargin, max: $printMargin}; - var wrapLimit = this.$constrainWrapLimit(desiredLimit, limits.min, limits.max); - if (wrapLimit != this.$wrapLimit && wrapLimit > 1) { - this.$wrapLimit = wrapLimit; - this.$modified = true; - if (this.$useWrapMode) { - this.$updateWrapData(0, this.getLength() - 1); - this.$resetRowCache(0); - this._signal("changeWrapLimit"); - } - return true; - } - return false; - }; - - this.$constrainWrapLimit = function(wrapLimit, min, max) { - if (min) - wrapLimit = Math.max(min, wrapLimit); - - if (max) - wrapLimit = Math.min(max, wrapLimit); - - return wrapLimit; - }; - this.getWrapLimit = function() { - return this.$wrapLimit; - }; - this.setWrapLimit = function (limit) { - this.setWrapLimitRange(limit, limit); - }; - this.getWrapLimitRange = function() { - return { - min : this.$wrapLimitRange.min, - max : this.$wrapLimitRange.max - }; - }; - - this.$updateInternalDataOnChange = function(delta) { - var useWrapMode = this.$useWrapMode; - var action = delta.action; - var start = delta.start; - var end = delta.end; - var firstRow = start.row; - var lastRow = end.row; - var len = lastRow - firstRow; - var removedFolds = null; - - this.$updating = true; - if (len != 0) { - if (action === "remove") { - this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len); - - var foldLines = this.$foldData; - removedFolds = this.getFoldsInRange(delta); - this.removeFolds(removedFolds); - - var foldLine = this.getFoldLine(end.row); - var idx = 0; - if (foldLine) { - foldLine.addRemoveChars(end.row, end.column, start.column - end.column); - foldLine.shiftRow(-len); - - var foldLineBefore = this.getFoldLine(firstRow); - if (foldLineBefore && foldLineBefore !== foldLine) { - foldLineBefore.merge(foldLine); - foldLine = foldLineBefore; - } - idx = foldLines.indexOf(foldLine) + 1; - } - - for (idx; idx < foldLines.length; idx++) { - var foldLine = foldLines[idx]; - if (foldLine.start.row >= end.row) { - foldLine.shiftRow(-len); - } - } - - lastRow = firstRow; - } else { - var args = Array(len); - args.unshift(firstRow, 0); - var arr = useWrapMode ? this.$wrapData : this.$rowLengthCache; - arr.splice.apply(arr, args); - var foldLines = this.$foldData; - var foldLine = this.getFoldLine(firstRow); - var idx = 0; - if (foldLine) { - var cmp = foldLine.range.compareInside(start.row, start.column); - if (cmp == 0) { - foldLine = foldLine.split(start.row, start.column); - if (foldLine) { - foldLine.shiftRow(len); - foldLine.addRemoveChars(lastRow, 0, end.column - start.column); - } - } else - if (cmp == -1) { - foldLine.addRemoveChars(firstRow, 0, end.column - start.column); - foldLine.shiftRow(len); - } - idx = foldLines.indexOf(foldLine) + 1; - } - - for (idx; idx < foldLines.length; idx++) { - var foldLine = foldLines[idx]; - if (foldLine.start.row >= firstRow) { - foldLine.shiftRow(len); - } - } - } - } else { - len = Math.abs(delta.start.column - delta.end.column); - if (action === "remove") { - removedFolds = this.getFoldsInRange(delta); - this.removeFolds(removedFolds); - - len = -len; - } - var foldLine = this.getFoldLine(firstRow); - if (foldLine) { - foldLine.addRemoveChars(firstRow, start.column, len); - } - } - - if (useWrapMode && this.$wrapData.length != this.doc.getLength()) { - console.error("doc.getLength() and $wrapData.length have to be the same!"); - } - this.$updating = false; - - if (useWrapMode) - this.$updateWrapData(firstRow, lastRow); - else - this.$updateRowLengthCache(firstRow, lastRow); - - return removedFolds; - }; - - this.$updateRowLengthCache = function(firstRow, lastRow, b) { - this.$rowLengthCache[firstRow] = null; - this.$rowLengthCache[lastRow] = null; - }; - - this.$updateWrapData = function(firstRow, lastRow) { - var lines = this.doc.getAllLines(); - var tabSize = this.getTabSize(); - var wrapData = this.$wrapData; - var wrapLimit = this.$wrapLimit; - var tokens; - var foldLine; - - var row = firstRow; - lastRow = Math.min(lastRow, lines.length - 1); - while (row <= lastRow) { - foldLine = this.getFoldLine(row, foldLine); - if (!foldLine) { - tokens = this.$getDisplayTokens(lines[row]); - wrapData[row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize); - row ++; - } else { - tokens = []; - foldLine.walk(function(placeholder, row, column, lastColumn) { - var walkTokens; - if (placeholder != null) { - walkTokens = this.$getDisplayTokens( - placeholder, tokens.length); - walkTokens[0] = PLACEHOLDER_START; - for (var i = 1; i < walkTokens.length; i++) { - walkTokens[i] = PLACEHOLDER_BODY; - } - } else { - walkTokens = this.$getDisplayTokens( - lines[row].substring(lastColumn, column), - tokens.length); - } - tokens = tokens.concat(walkTokens); - }.bind(this), - foldLine.end.row, - lines[foldLine.end.row].length + 1 - ); - - wrapData[foldLine.start.row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize); - row = foldLine.end.row + 1; - } - } - }; - var CHAR = 1, - CHAR_EXT = 2, - PLACEHOLDER_START = 3, - PLACEHOLDER_BODY = 4, - PUNCTUATION = 9, - SPACE = 10, - TAB = 11, - TAB_SPACE = 12; - - - this.$computeWrapSplits = function(tokens, wrapLimit, tabSize) { - if (tokens.length == 0) { - return []; - } - - var splits = []; - var displayLength = tokens.length; - var lastSplit = 0, lastDocSplit = 0; - - var isCode = this.$wrapAsCode; - - var indentedSoftWrap = this.$indentedSoftWrap; - var maxIndent = wrapLimit <= Math.max(2 * tabSize, 8) - || indentedSoftWrap === false ? 0 : Math.floor(wrapLimit / 2); - - function getWrapIndent() { - var indentation = 0; - if (maxIndent === 0) - return indentation; - if (indentedSoftWrap) { - for (var i = 0; i < tokens.length; i++) { - var token = tokens[i]; - if (token == SPACE) - indentation += 1; - else if (token == TAB) - indentation += tabSize; - else if (token == TAB_SPACE) - continue; - else - break; - } - } - if (isCode && indentedSoftWrap !== false) - indentation += tabSize; - return Math.min(indentation, maxIndent); - } - function addSplit(screenPos) { - var displayed = tokens.slice(lastSplit, screenPos); - var len = displayed.length; - displayed.join("") - .replace(/12/g, function() { - len -= 1; - }) - .replace(/2/g, function() { - len -= 1; - }); - - if (!splits.length) { - indent = getWrapIndent(); - splits.indent = indent; - } - lastDocSplit += len; - splits.push(lastDocSplit); - lastSplit = screenPos; - } - var indent = 0; - while (displayLength - lastSplit > wrapLimit - indent) { - var split = lastSplit + wrapLimit - indent; - if (tokens[split - 1] >= SPACE && tokens[split] >= SPACE) { - addSplit(split); - continue; - } - if (tokens[split] == PLACEHOLDER_START || tokens[split] == PLACEHOLDER_BODY) { - for (split; split != lastSplit - 1; split--) { - if (tokens[split] == PLACEHOLDER_START) { - break; - } - } - if (split > lastSplit) { - addSplit(split); - continue; - } - split = lastSplit + wrapLimit; - for (split; split < tokens.length; split++) { - if (tokens[split] != PLACEHOLDER_BODY) { - break; - } - } - if (split == tokens.length) { - break; // Breaks the while-loop. - } - addSplit(split); - continue; - } - var minSplit = Math.max(split - (wrapLimit -(wrapLimit>>2)), lastSplit - 1); - while (split > minSplit && tokens[split] < PLACEHOLDER_START) { - split --; - } - if (isCode) { - while (split > minSplit && tokens[split] < PLACEHOLDER_START) { - split --; - } - while (split > minSplit && tokens[split] == PUNCTUATION) { - split --; - } - } else { - while (split > minSplit && tokens[split] < SPACE) { - split --; - } - } - if (split > minSplit) { - addSplit(++split); - continue; - } - split = lastSplit + wrapLimit; - if (tokens[split] == CHAR_EXT) - split--; - addSplit(split - indent); - } - return splits; - }; - this.$getDisplayTokens = function(str, offset) { - var arr = []; - var tabSize; - offset = offset || 0; - - for (var i = 0; i < str.length; i++) { - var c = str.charCodeAt(i); - if (c == 9) { - tabSize = this.getScreenTabSize(arr.length + offset); - arr.push(TAB); - for (var n = 1; n < tabSize; n++) { - arr.push(TAB_SPACE); - } - } - else if (c == 32) { - arr.push(SPACE); - } else if((c > 39 && c < 48) || (c > 57 && c < 64)) { - arr.push(PUNCTUATION); - } - else if (c >= 0x1100 && isFullWidth(c)) { - arr.push(CHAR, CHAR_EXT); - } else { - arr.push(CHAR); - } - } - return arr; - }; - this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) { - if (maxScreenColumn == 0) - return [0, 0]; - if (maxScreenColumn == null) - maxScreenColumn = Infinity; - screenColumn = screenColumn || 0; - - var c, column; - for (column = 0; column < str.length; column++) { - c = str.charCodeAt(column); - if (c == 9) { - screenColumn += this.getScreenTabSize(screenColumn); - } - else if (c >= 0x1100 && isFullWidth(c)) { - screenColumn += 2; - } else { - screenColumn += 1; - } - if (screenColumn > maxScreenColumn) { - break; - } - } - - return [screenColumn, column]; - }; - - this.lineWidgets = null; - this.getRowLength = function(row) { - if (this.lineWidgets) - var h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0; - else - h = 0; - if (!this.$useWrapMode || !this.$wrapData[row]) { - return 1 + h; - } else { - return this.$wrapData[row].length + 1 + h; - } - }; - this.getRowLineCount = function(row) { - if (!this.$useWrapMode || !this.$wrapData[row]) { - return 1; - } else { - return this.$wrapData[row].length + 1; - } - }; - - this.getRowWrapIndent = function(screenRow) { - if (this.$useWrapMode) { - var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE); - var splits = this.$wrapData[pos.row]; - return splits.length && splits[0] < pos.column ? splits.indent : 0; - } else { - return 0; - } - }; - this.getScreenLastRowColumn = function(screenRow) { - var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE); - return this.documentToScreenColumn(pos.row, pos.column); - }; - this.getDocumentLastRowColumn = function(docRow, docColumn) { - var screenRow = this.documentToScreenRow(docRow, docColumn); - return this.getScreenLastRowColumn(screenRow); - }; - this.getDocumentLastRowColumnPosition = function(docRow, docColumn) { - var screenRow = this.documentToScreenRow(docRow, docColumn); - return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10); - }; - this.getRowSplitData = function(row) { - if (!this.$useWrapMode) { - return undefined; - } else { - return this.$wrapData[row]; - } - }; - this.getScreenTabSize = function(screenColumn) { - return this.$tabSize - screenColumn % this.$tabSize; - }; - - - this.screenToDocumentRow = function(screenRow, screenColumn) { - return this.screenToDocumentPosition(screenRow, screenColumn).row; - }; - - - this.screenToDocumentColumn = function(screenRow, screenColumn) { - return this.screenToDocumentPosition(screenRow, screenColumn).column; - }; - this.screenToDocumentPosition = function(screenRow, screenColumn, offsetX) { - if (screenRow < 0) - return {row: 0, column: 0}; - - var line; - var docRow = 0; - var docColumn = 0; - var column; - var row = 0; - var rowLength = 0; - - var rowCache = this.$screenRowCache; - var i = this.$getRowCacheIndex(rowCache, screenRow); - var l = rowCache.length; - if (l && i >= 0) { - var row = rowCache[i]; - var docRow = this.$docRowCache[i]; - var doCache = screenRow > rowCache[l - 1]; - } else { - var doCache = !l; - } - - var maxRow = this.getLength() - 1; - var foldLine = this.getNextFoldLine(docRow); - var foldStart = foldLine ? foldLine.start.row : Infinity; - - while (row <= screenRow) { - rowLength = this.getRowLength(docRow); - if (row + rowLength > screenRow || docRow >= maxRow) { - break; - } else { - row += rowLength; - docRow++; - if (docRow > foldStart) { - docRow = foldLine.end.row+1; - foldLine = this.getNextFoldLine(docRow, foldLine); - foldStart = foldLine ? foldLine.start.row : Infinity; - } - } - - if (doCache) { - this.$docRowCache.push(docRow); - this.$screenRowCache.push(row); - } - } - - if (foldLine && foldLine.start.row <= docRow) { - line = this.getFoldDisplayLine(foldLine); - docRow = foldLine.start.row; - } else if (row + rowLength <= screenRow || docRow > maxRow) { - return { - row: maxRow, - column: this.getLine(maxRow).length - }; - } else { - line = this.getLine(docRow); - foldLine = null; - } - var wrapIndent = 0, splitIndex = Math.floor(screenRow - row); - if (this.$useWrapMode) { - var splits = this.$wrapData[docRow]; - if (splits) { - column = splits[splitIndex]; - if(splitIndex > 0 && splits.length) { - wrapIndent = splits.indent; - docColumn = splits[splitIndex - 1] || splits[splits.length - 1]; - line = line.substring(docColumn); - } - } - } - - if (offsetX !== undefined && this.$bidiHandler.isBidiRow(row + splitIndex, docRow, splitIndex)) - screenColumn = this.$bidiHandler.offsetToCol(offsetX); - - docColumn += this.$getStringScreenWidth(line, screenColumn - wrapIndent)[1]; - if (this.$useWrapMode && docColumn >= column) - docColumn = column - 1; - - if (foldLine) - return foldLine.idxToPosition(docColumn); - - return {row: docRow, column: docColumn}; - }; - this.documentToScreenPosition = function(docRow, docColumn) { - if (typeof docColumn === "undefined") - var pos = this.$clipPositionToDocument(docRow.row, docRow.column); - else - pos = this.$clipPositionToDocument(docRow, docColumn); - - docRow = pos.row; - docColumn = pos.column; - - var screenRow = 0; - var foldStartRow = null; - var fold = null; - fold = this.getFoldAt(docRow, docColumn, 1); - if (fold) { - docRow = fold.start.row; - docColumn = fold.start.column; - } - - var rowEnd, row = 0; - - - var rowCache = this.$docRowCache; - var i = this.$getRowCacheIndex(rowCache, docRow); - var l = rowCache.length; - if (l && i >= 0) { - var row = rowCache[i]; - var screenRow = this.$screenRowCache[i]; - var doCache = docRow > rowCache[l - 1]; - } else { - var doCache = !l; - } - - var foldLine = this.getNextFoldLine(row); - var foldStart = foldLine ?foldLine.start.row :Infinity; - - while (row < docRow) { - if (row >= foldStart) { - rowEnd = foldLine.end.row + 1; - if (rowEnd > docRow) - break; - foldLine = this.getNextFoldLine(rowEnd, foldLine); - foldStart = foldLine ?foldLine.start.row :Infinity; - } - else { - rowEnd = row + 1; - } - - screenRow += this.getRowLength(row); - row = rowEnd; - - if (doCache) { - this.$docRowCache.push(row); - this.$screenRowCache.push(screenRow); - } - } - var textLine = ""; - if (foldLine && row >= foldStart) { - textLine = this.getFoldDisplayLine(foldLine, docRow, docColumn); - foldStartRow = foldLine.start.row; - } else { - textLine = this.getLine(docRow).substring(0, docColumn); - foldStartRow = docRow; - } - var wrapIndent = 0; - if (this.$useWrapMode) { - var wrapRow = this.$wrapData[foldStartRow]; - if (wrapRow) { - var screenRowOffset = 0; - while (textLine.length >= wrapRow[screenRowOffset]) { - screenRow ++; - screenRowOffset++; - } - textLine = textLine.substring( - wrapRow[screenRowOffset - 1] || 0, textLine.length - ); - wrapIndent = screenRowOffset > 0 ? wrapRow.indent : 0; - } - } - - return { - row: screenRow, - column: wrapIndent + this.$getStringScreenWidth(textLine)[0] - }; - }; - this.documentToScreenColumn = function(row, docColumn) { - return this.documentToScreenPosition(row, docColumn).column; - }; - this.documentToScreenRow = function(docRow, docColumn) { - return this.documentToScreenPosition(docRow, docColumn).row; - }; - this.getScreenLength = function() { - var screenRows = 0; - var fold = null; - if (!this.$useWrapMode) { - screenRows = this.getLength(); - var foldData = this.$foldData; - for (var i = 0; i < foldData.length; i++) { - fold = foldData[i]; - screenRows -= fold.end.row - fold.start.row; - } - } else { - var lastRow = this.$wrapData.length; - var row = 0, i = 0; - var fold = this.$foldData[i++]; - var foldStart = fold ? fold.start.row :Infinity; - - while (row < lastRow) { - var splits = this.$wrapData[row]; - screenRows += splits ? splits.length + 1 : 1; - row ++; - if (row > foldStart) { - row = fold.end.row+1; - fold = this.$foldData[i++]; - foldStart = fold ?fold.start.row :Infinity; - } - } - } - if (this.lineWidgets) - screenRows += this.$getWidgetScreenLength(); - - return screenRows; - }; - this.$setFontMetrics = function(fm) { - if (!this.$enableVarChar) return; - this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) { - if (maxScreenColumn === 0) - return [0, 0]; - if (!maxScreenColumn) - maxScreenColumn = Infinity; - screenColumn = screenColumn || 0; - - var c, column; - for (column = 0; column < str.length; column++) { - c = str.charAt(column); - if (c === "\t") { - screenColumn += this.getScreenTabSize(screenColumn); - } else { - screenColumn += fm.getCharacterWidth(c); - } - if (screenColumn > maxScreenColumn) { - break; - } - } - - return [screenColumn, column]; - }; - }; - - this.destroy = function() { - if (this.bgTokenizer) { - this.bgTokenizer.setDocument(null); - this.bgTokenizer = null; - } - this.$stopWorker(); - }; - - this.isFullWidth = isFullWidth; - function isFullWidth(c) { - if (c < 0x1100) - return false; - return c >= 0x1100 && c <= 0x115F || - c >= 0x11A3 && c <= 0x11A7 || - c >= 0x11FA && c <= 0x11FF || - c >= 0x2329 && c <= 0x232A || - c >= 0x2E80 && c <= 0x2E99 || - c >= 0x2E9B && c <= 0x2EF3 || - c >= 0x2F00 && c <= 0x2FD5 || - c >= 0x2FF0 && c <= 0x2FFB || - c >= 0x3000 && c <= 0x303E || - c >= 0x3041 && c <= 0x3096 || - c >= 0x3099 && c <= 0x30FF || - c >= 0x3105 && c <= 0x312D || - c >= 0x3131 && c <= 0x318E || - c >= 0x3190 && c <= 0x31BA || - c >= 0x31C0 && c <= 0x31E3 || - c >= 0x31F0 && c <= 0x321E || - c >= 0x3220 && c <= 0x3247 || - c >= 0x3250 && c <= 0x32FE || - c >= 0x3300 && c <= 0x4DBF || - c >= 0x4E00 && c <= 0xA48C || - c >= 0xA490 && c <= 0xA4C6 || - c >= 0xA960 && c <= 0xA97C || - c >= 0xAC00 && c <= 0xD7A3 || - c >= 0xD7B0 && c <= 0xD7C6 || - c >= 0xD7CB && c <= 0xD7FB || - c >= 0xF900 && c <= 0xFAFF || - c >= 0xFE10 && c <= 0xFE19 || - c >= 0xFE30 && c <= 0xFE52 || - c >= 0xFE54 && c <= 0xFE66 || - c >= 0xFE68 && c <= 0xFE6B || - c >= 0xFF01 && c <= 0xFF60 || - c >= 0xFFE0 && c <= 0xFFE6; - } - - }).call(EditSession.prototype); - - acequire("./edit_session/folding").Folding.call(EditSession.prototype); - acequire("./edit_session/bracket_match").BracketMatch.call(EditSession.prototype); - - - config.defineOptions(EditSession.prototype, "session", { - wrap: { - set: function(value) { - if (!value || value == "off") - value = false; - else if (value == "free") - value = true; - else if (value == "printMargin") - value = -1; - else if (typeof value == "string") - value = parseInt(value, 10) || false; - - if (this.$wrap == value) - return; - this.$wrap = value; - if (!value) { - this.setUseWrapMode(false); - } else { - var col = typeof value == "number" ? value : null; - this.setWrapLimitRange(col, col); - this.setUseWrapMode(true); - } - }, - get: function() { - if (this.getUseWrapMode()) { - if (this.$wrap == -1) - return "printMargin"; - if (!this.getWrapLimitRange().min) - return "free"; - return this.$wrap; - } - return "off"; - }, - handlesSet: true - }, - wrapMethod: { - set: function(val) { - val = val == "auto" - ? this.$mode.type != "text" - : val != "text"; - if (val != this.$wrapAsCode) { - this.$wrapAsCode = val; - if (this.$useWrapMode) { - this.$modified = true; - this.$resetRowCache(0); - this.$updateWrapData(0, this.getLength() - 1); - } - } - }, - initialValue: "auto" - }, - indentedSoftWrap: { initialValue: true }, - firstLineNumber: { - set: function() {this._signal("changeBreakpoint");}, - initialValue: 1 - }, - useWorker: { - set: function(useWorker) { - this.$useWorker = useWorker; - - this.$stopWorker(); - if (useWorker) - this.$startWorker(); - }, - initialValue: true - }, - useSoftTabs: {initialValue: true}, - tabSize: { - set: function(tabSize) { - if (isNaN(tabSize) || this.$tabSize === tabSize) return; - - this.$modified = true; - this.$rowLengthCache = []; - this.$tabSize = tabSize; - this._signal("changeTabSize"); - }, - initialValue: 4, - handlesSet: true - }, - navigateWithinSoftTabs: {initialValue: false}, - overwrite: { - set: function(val) {this._signal("changeOverwrite");}, - initialValue: false - }, - newLineMode: { - set: function(val) {this.doc.setNewLineMode(val);}, - get: function() {return this.doc.getNewLineMode();}, - handlesSet: true - }, - mode: { - set: function(val) { this.setMode(val); }, - get: function() { return this.$modeId; } - } - }); - - exports.EditSession = EditSession; - }); - - ace.define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"], function(acequire, exports, module) { - "use strict"; - - var lang = acequire("./lib/lang"); - var oop = acequire("./lib/oop"); - var Range = acequire("./range").Range; - - var Search = function() { - this.$options = {}; - }; - - (function() { - this.set = function(options) { - oop.mixin(this.$options, options); - return this; - }; - this.getOptions = function() { - return lang.copyObject(this.$options); - }; - this.setOptions = function(options) { - this.$options = options; - }; - this.find = function(session) { - var options = this.$options; - var iterator = this.$matchIterator(session, options); - if (!iterator) - return false; - - var firstRange = null; - iterator.forEach(function(sr, sc, er, ec) { - firstRange = new Range(sr, sc, er, ec); - if (sc == ec && options.start && options.start.start - && options.skipCurrent != false && firstRange.isEqual(options.start) - ) { - firstRange = null; - return false; - } - - return true; - }); - - return firstRange; - }; - this.findAll = function(session) { - var options = this.$options; - if (!options.needle) - return []; - this.$assembleRegExp(options); - - var range = options.range; - var lines = range - ? session.getLines(range.start.row, range.end.row) - : session.doc.getAllLines(); - - var ranges = []; - var re = options.re; - if (options.$isMultiLine) { - var len = re.length; - var maxRow = lines.length - len; - var prevRange; - outer: for (var row = re.offset || 0; row <= maxRow; row++) { - for (var j = 0; j < len; j++) - if (lines[row + j].search(re[j]) == -1) - continue outer; - - var startLine = lines[row]; - var line = lines[row + len - 1]; - var startIndex = startLine.length - startLine.match(re[0])[0].length; - var endIndex = line.match(re[len - 1])[0].length; - - if (prevRange && prevRange.end.row === row && - prevRange.end.column > startIndex - ) { - continue; - } - ranges.push(prevRange = new Range( - row, startIndex, row + len - 1, endIndex - )); - if (len > 2) - row = row + len - 2; - } - } else { - for (var i = 0; i < lines.length; i++) { - var matches = lang.getMatchOffsets(lines[i], re); - for (var j = 0; j < matches.length; j++) { - var match = matches[j]; - ranges.push(new Range(i, match.offset, i, match.offset + match.length)); - } - } - } - - if (range) { - var startColumn = range.start.column; - var endColumn = range.start.column; - var i = 0, j = ranges.length - 1; - while (i < j && ranges[i].start.column < startColumn && ranges[i].start.row == range.start.row) - i++; - - while (i < j && ranges[j].end.column > endColumn && ranges[j].end.row == range.end.row) - j--; - - ranges = ranges.slice(i, j + 1); - for (i = 0, j = ranges.length; i < j; i++) { - ranges[i].start.row += range.start.row; - ranges[i].end.row += range.start.row; - } - } - - return ranges; - }; - this.replace = function(input, replacement) { - var options = this.$options; - - var re = this.$assembleRegExp(options); - if (options.$isMultiLine) - return replacement; - - if (!re) - return; - - var match = re.exec(input); - if (!match || match[0].length != input.length) - return null; - - replacement = input.replace(re, replacement); - if (options.preserveCase) { - replacement = replacement.split(""); - for (var i = Math.min(input.length, input.length); i--; ) { - var ch = input[i]; - if (ch && ch.toLowerCase() != ch) - replacement[i] = replacement[i].toUpperCase(); - else - replacement[i] = replacement[i].toLowerCase(); - } - replacement = replacement.join(""); - } - - return replacement; - }; - - this.$assembleRegExp = function(options, $disableFakeMultiline) { - if (options.needle instanceof RegExp) - return options.re = options.needle; - - var needle = options.needle; - - if (!options.needle) - return options.re = false; - - if (!options.regExp) - needle = lang.escapeRegExp(needle); - - if (options.wholeWord) - needle = addWordBoundary(needle, options); - - var modifier = options.caseSensitive ? "gm" : "gmi"; - - options.$isMultiLine = !$disableFakeMultiline && /[\n\r]/.test(needle); - if (options.$isMultiLine) - return options.re = this.$assembleMultilineRegExp(needle, modifier); - - try { - var re = new RegExp(needle, modifier); - } catch(e) { - re = false; - } - return options.re = re; - }; - - this.$assembleMultilineRegExp = function(needle, modifier) { - var parts = needle.replace(/\r\n|\r|\n/g, "$\n^").split("\n"); - var re = []; - for (var i = 0; i < parts.length; i++) try { - re.push(new RegExp(parts[i], modifier)); - } catch(e) { - return false; - } - return re; - }; - - this.$matchIterator = function(session, options) { - var re = this.$assembleRegExp(options); - if (!re) - return false; - var backwards = options.backwards == true; - var skipCurrent = options.skipCurrent != false; - - var range = options.range; - var start = options.start; - if (!start) - start = range ? range[backwards ? "end" : "start"] : session.selection.getRange(); - - if (start.start) - start = start[skipCurrent != backwards ? "end" : "start"]; - - var firstRow = range ? range.start.row : 0; - var lastRow = range ? range.end.row : session.getLength() - 1; - - if (backwards) { - var forEach = function(callback) { - var row = start.row; - if (forEachInLine(row, start.column, callback)) - return; - for (row--; row >= firstRow; row--) - if (forEachInLine(row, Number.MAX_VALUE, callback)) - return; - if (options.wrap == false) - return; - for (row = lastRow, firstRow = start.row; row >= firstRow; row--) - if (forEachInLine(row, Number.MAX_VALUE, callback)) - return; - }; - } - else { - var forEach = function(callback) { - var row = start.row; - if (forEachInLine(row, start.column, callback)) - return; - for (row = row + 1; row <= lastRow; row++) - if (forEachInLine(row, 0, callback)) - return; - if (options.wrap == false) - return; - for (row = firstRow, lastRow = start.row; row <= lastRow; row++) - if (forEachInLine(row, 0, callback)) - return; - }; - } - - if (options.$isMultiLine) { - var len = re.length; - var forEachInLine = function(row, offset, callback) { - var startRow = backwards ? row - len + 1 : row; - if (startRow < 0) return; - var line = session.getLine(startRow); - var startIndex = line.search(re[0]); - if (!backwards && startIndex < offset || startIndex === -1) return; - for (var i = 1; i < len; i++) { - line = session.getLine(startRow + i); - if (line.search(re[i]) == -1) - return; - } - var endIndex = line.match(re[len - 1])[0].length; - if (backwards && endIndex > offset) return; - if (callback(startRow, startIndex, startRow + len - 1, endIndex)) - return true; - }; - } - else if (backwards) { - var forEachInLine = function(row, endIndex, callback) { - var line = session.getLine(row); - var matches = []; - var m, last = 0; - re.lastIndex = 0; - while((m = re.exec(line))) { - var length = m[0].length; - last = m.index; - if (!length) { - if (last >= line.length) break; - re.lastIndex = last += 1; - } - if (m.index + length > endIndex) - break; - matches.push(m.index, length); - } - for (var i = matches.length - 1; i >= 0; i -= 2) { - var column = matches[i - 1]; - var length = matches[i]; - if (callback(row, column, row, column + length)) - return true; - } - }; - } - else { - var forEachInLine = function(row, startIndex, callback) { - var line = session.getLine(row); - var m; - var last = startIndex; - re.lastIndex = startIndex; - while((m = re.exec(line))) { - var length = m[0].length; - last = m.index; - if (callback(row, last, row,last + length)) - return true; - if (!length) { - re.lastIndex = last += 1; - if (last >= line.length) return false; - } - } - }; - } - return {forEach: forEach}; - }; - - }).call(Search.prototype); - - function addWordBoundary(needle, options) { - function wordBoundary(c) { - if (/\w/.test(c) || options.regExp) return "\\b"; - return ""; - } - return wordBoundary(needle[0]) + needle - + wordBoundary(needle[needle.length - 1]); - } - - exports.Search = Search; - }); - - ace.define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys","ace/lib/useragent"], function(acequire, exports, module) { - "use strict"; - - var keyUtil = acequire("../lib/keys"); - var useragent = acequire("../lib/useragent"); - var KEY_MODS = keyUtil.KEY_MODS; - - function HashHandler(config, platform) { - this.platform = platform || (useragent.isMac ? "mac" : "win"); - this.commands = {}; - this.commandKeyBinding = {}; - this.addCommands(config); - this.$singleCommand = true; - } - - function MultiHashHandler(config, platform) { - HashHandler.call(this, config, platform); - this.$singleCommand = false; - } - - MultiHashHandler.prototype = HashHandler.prototype; - - (function() { - - - this.addCommand = function(command) { - if (this.commands[command.name]) - this.removeCommand(command); - - this.commands[command.name] = command; - - if (command.bindKey) - this._buildKeyHash(command); - }; - - this.removeCommand = function(command, keepCommand) { - var name = command && (typeof command === 'string' ? command : command.name); - command = this.commands[name]; - if (!keepCommand) - delete this.commands[name]; - var ckb = this.commandKeyBinding; - for (var keyId in ckb) { - var cmdGroup = ckb[keyId]; - if (cmdGroup == command) { - delete ckb[keyId]; - } else if (Array.isArray(cmdGroup)) { - var i = cmdGroup.indexOf(command); - if (i != -1) { - cmdGroup.splice(i, 1); - if (cmdGroup.length == 1) - ckb[keyId] = cmdGroup[0]; - } - } - } - }; - - this.bindKey = function(key, command, position) { - if (typeof key == "object" && key) { - if (position == undefined) - position = key.position; - key = key[this.platform]; - } - if (!key) - return; - if (typeof command == "function") - return this.addCommand({exec: command, bindKey: key, name: command.name || key}); - - key.split("|").forEach(function(keyPart) { - var chain = ""; - if (keyPart.indexOf(" ") != -1) { - var parts = keyPart.split(/\s+/); - keyPart = parts.pop(); - parts.forEach(function(keyPart) { - var binding = this.parseKeys(keyPart); - var id = KEY_MODS[binding.hashId] + binding.key; - chain += (chain ? " " : "") + id; - this._addCommandToBinding(chain, "chainKeys"); - }, this); - chain += " "; - } - var binding = this.parseKeys(keyPart); - var id = KEY_MODS[binding.hashId] + binding.key; - this._addCommandToBinding(chain + id, command, position); - }, this); - }; - - function getPosition(command) { - return typeof command == "object" && command.bindKey - && command.bindKey.position - || (command.isDefault ? -100 : 0); - } - this._addCommandToBinding = function(keyId, command, position) { - var ckb = this.commandKeyBinding, i; - if (!command) { - delete ckb[keyId]; - } else if (!ckb[keyId] || this.$singleCommand) { - ckb[keyId] = command; - } else { - if (!Array.isArray(ckb[keyId])) { - ckb[keyId] = [ckb[keyId]]; - } else if ((i = ckb[keyId].indexOf(command)) != -1) { - ckb[keyId].splice(i, 1); - } - - if (typeof position != "number") { - position = getPosition(command); - } - - var commands = ckb[keyId]; - for (i = 0; i < commands.length; i++) { - var other = commands[i]; - var otherPos = getPosition(other); - if (otherPos > position) - break; - } - commands.splice(i, 0, command); - } - }; - - this.addCommands = function(commands) { - commands && Object.keys(commands).forEach(function(name) { - var command = commands[name]; - if (!command) - return; - - if (typeof command === "string") - return this.bindKey(command, name); - - if (typeof command === "function") - command = { exec: command }; - - if (typeof command !== "object") - return; - - if (!command.name) - command.name = name; - - this.addCommand(command); - }, this); - }; - - this.removeCommands = function(commands) { - Object.keys(commands).forEach(function(name) { - this.removeCommand(commands[name]); - }, this); - }; - - this.bindKeys = function(keyList) { - Object.keys(keyList).forEach(function(key) { - this.bindKey(key, keyList[key]); - }, this); - }; - - this._buildKeyHash = function(command) { - this.bindKey(command.bindKey, command); - }; - this.parseKeys = function(keys) { - var parts = keys.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(x){return x;}); - var key = parts.pop(); - - var keyCode = keyUtil[key]; - if (keyUtil.FUNCTION_KEYS[keyCode]) - key = keyUtil.FUNCTION_KEYS[keyCode].toLowerCase(); - else if (!parts.length) - return {key: key, hashId: -1}; - else if (parts.length == 1 && parts[0] == "shift") - return {key: key.toUpperCase(), hashId: -1}; - - var hashId = 0; - for (var i = parts.length; i--;) { - var modifier = keyUtil.KEY_MODS[parts[i]]; - if (modifier == null) { - if (typeof console != "undefined") - console.error("invalid modifier " + parts[i] + " in " + keys); - return false; - } - hashId |= modifier; - } - return {key: key, hashId: hashId}; - }; - - this.findKeyCommand = function findKeyCommand(hashId, keyString) { - var key = KEY_MODS[hashId] + keyString; - return this.commandKeyBinding[key]; - }; - - this.handleKeyboard = function(data, hashId, keyString, keyCode) { - if (keyCode < 0) return; - var key = KEY_MODS[hashId] + keyString; - var command = this.commandKeyBinding[key]; - if (data.$keyChain) { - data.$keyChain += " " + key; - command = this.commandKeyBinding[data.$keyChain] || command; - } - - if (command) { - if (command == "chainKeys" || command[command.length - 1] == "chainKeys") { - data.$keyChain = data.$keyChain || key; - return {command: "null"}; - } - } - - if (data.$keyChain) { - if ((!hashId || hashId == 4) && keyString.length == 1) - data.$keyChain = data.$keyChain.slice(0, -key.length - 1); // wait for input - else if (hashId == -1 || keyCode > 0) - data.$keyChain = ""; // reset keyChain - } - return {command: command}; - }; - - this.getStatusText = function(editor, data) { - return data.$keyChain || ""; - }; - - }).call(HashHandler.prototype); - - exports.HashHandler = HashHandler; - exports.MultiHashHandler = MultiHashHandler; - }); - - ace.define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("../lib/oop"); - var MultiHashHandler = acequire("../keyboard/hash_handler").MultiHashHandler; - var EventEmitter = acequire("../lib/event_emitter").EventEmitter; - - var CommandManager = function(platform, commands) { - MultiHashHandler.call(this, commands, platform); - this.byName = this.commands; - this.setDefaultHandler("exec", function(e) { - return e.command.exec(e.editor, e.args || {}); - }); - }; - - oop.inherits(CommandManager, MultiHashHandler); - - (function() { - - oop.implement(this, EventEmitter); - - this.exec = function(command, editor, args) { - if (Array.isArray(command)) { - for (var i = command.length; i--; ) { - if (this.exec(command[i], editor, args)) return true; - } - return false; - } - - if (typeof command === "string") - command = this.commands[command]; - - if (!command) - return false; - - if (editor && editor.$readOnly && !command.readOnly) - return false; - - if (command.isAvailable && !command.isAvailable(editor)) - return false; - - var e = {editor: editor, command: command, args: args}; - e.returnValue = this._emit("exec", e); - this._signal("afterExec", e); - - return e.returnValue === false ? false : true; - }; - - this.toggleRecording = function(editor) { - if (this.$inReplay) - return; - - editor && editor._emit("changeStatus"); - if (this.recording) { - this.macro.pop(); - this.removeEventListener("exec", this.$addCommandToMacro); - - if (!this.macro.length) - this.macro = this.oldMacro; - - return this.recording = false; - } - if (!this.$addCommandToMacro) { - this.$addCommandToMacro = function(e) { - this.macro.push([e.command, e.args]); - }.bind(this); - } - - this.oldMacro = this.macro; - this.macro = []; - this.on("exec", this.$addCommandToMacro); - return this.recording = true; - }; - - this.replay = function(editor) { - if (this.$inReplay || !this.macro) - return; - - if (this.recording) - return this.toggleRecording(editor); - - try { - this.$inReplay = true; - this.macro.forEach(function(x) { - if (typeof x == "string") - this.exec(x, editor); - else - this.exec(x[0], editor, x[1]); - }, this); - } finally { - this.$inReplay = false; - } - }; - - this.trimMacro = function(m) { - return m.map(function(x){ - if (typeof x[0] != "string") - x[0] = x[0].name; - if (!x[1]) - x = x[0]; - return x; - }); - }; - - }).call(CommandManager.prototype); - - exports.CommandManager = CommandManager; - - }); - - ace.define("ace/commands/default_commands",["require","exports","module","ace/lib/lang","ace/config","ace/range"], function(acequire, exports, module) { - "use strict"; - - var lang = acequire("../lib/lang"); - var config = acequire("../config"); - var Range = acequire("../range").Range; - - function bindKey(win, mac) { - return {win: win, mac: mac}; - } - exports.commands = [{ - name: "showSettingsMenu", - bindKey: bindKey("Ctrl-,", "Command-,"), - exec: function(editor) { - config.loadModule("ace/ext/settings_menu", function(module) { - module.init(editor); - editor.showSettingsMenu(); - }); - }, - readOnly: true - }, { - name: "goToNextError", - bindKey: bindKey("Alt-E", "F4"), - exec: function(editor) { - config.loadModule("ace/ext/error_marker", function(module) { - module.showErrorMarker(editor, 1); - }); - }, - scrollIntoView: "animate", - readOnly: true - }, { - name: "goToPreviousError", - bindKey: bindKey("Alt-Shift-E", "Shift-F4"), - exec: function(editor) { - config.loadModule("ace/ext/error_marker", function(module) { - module.showErrorMarker(editor, -1); - }); - }, - scrollIntoView: "animate", - readOnly: true - }, { - name: "selectall", - bindKey: bindKey("Ctrl-A", "Command-A"), - exec: function(editor) { editor.selectAll(); }, - readOnly: true - }, { - name: "centerselection", - bindKey: bindKey(null, "Ctrl-L"), - exec: function(editor) { editor.centerSelection(); }, - readOnly: true - }, { - name: "gotoline", - bindKey: bindKey("Ctrl-L", "Command-L"), - exec: function(editor) { - var line = parseInt(prompt("Enter line number:"), 10); - if (!isNaN(line)) { - editor.gotoLine(line); - } - }, - readOnly: true - }, { - name: "fold", - bindKey: bindKey("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"), - exec: function(editor) { editor.session.toggleFold(false); }, - multiSelectAction: "forEach", - scrollIntoView: "center", - readOnly: true - }, { - name: "unfold", - bindKey: bindKey("Alt-Shift-L|Ctrl-Shift-F1", "Command-Alt-Shift-L|Command-Shift-F1"), - exec: function(editor) { editor.session.toggleFold(true); }, - multiSelectAction: "forEach", - scrollIntoView: "center", - readOnly: true - }, { - name: "toggleFoldWidget", - bindKey: bindKey("F2", "F2"), - exec: function(editor) { editor.session.toggleFoldWidget(); }, - multiSelectAction: "forEach", - scrollIntoView: "center", - readOnly: true - }, { - name: "toggleParentFoldWidget", - bindKey: bindKey("Alt-F2", "Alt-F2"), - exec: function(editor) { editor.session.toggleFoldWidget(true); }, - multiSelectAction: "forEach", - scrollIntoView: "center", - readOnly: true - }, { - name: "foldall", - bindKey: bindKey(null, "Ctrl-Command-Option-0"), - exec: function(editor) { editor.session.foldAll(); }, - scrollIntoView: "center", - readOnly: true - }, { - name: "foldOther", - bindKey: bindKey("Alt-0", "Command-Option-0"), - exec: function(editor) { - editor.session.foldAll(); - editor.session.unfold(editor.selection.getAllRanges()); - }, - scrollIntoView: "center", - readOnly: true - }, { - name: "unfoldall", - bindKey: bindKey("Alt-Shift-0", "Command-Option-Shift-0"), - exec: function(editor) { editor.session.unfold(); }, - scrollIntoView: "center", - readOnly: true - }, { - name: "findnext", - bindKey: bindKey("Ctrl-K", "Command-G"), - exec: function(editor) { editor.findNext(); }, - multiSelectAction: "forEach", - scrollIntoView: "center", - readOnly: true - }, { - name: "findprevious", - bindKey: bindKey("Ctrl-Shift-K", "Command-Shift-G"), - exec: function(editor) { editor.findPrevious(); }, - multiSelectAction: "forEach", - scrollIntoView: "center", - readOnly: true - }, { - name: "selectOrFindNext", - bindKey: bindKey("Alt-K", "Ctrl-G"), - exec: function(editor) { - if (editor.selection.isEmpty()) - editor.selection.selectWord(); - else - editor.findNext(); - }, - readOnly: true - }, { - name: "selectOrFindPrevious", - bindKey: bindKey("Alt-Shift-K", "Ctrl-Shift-G"), - exec: function(editor) { - if (editor.selection.isEmpty()) - editor.selection.selectWord(); - else - editor.findPrevious(); - }, - readOnly: true - }, { - name: "find", - bindKey: bindKey("Ctrl-F", "Command-F"), - exec: function(editor) { - config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor);}); - }, - readOnly: true - }, { - name: "overwrite", - bindKey: "Insert", - exec: function(editor) { editor.toggleOverwrite(); }, - readOnly: true - }, { - name: "selecttostart", - bindKey: bindKey("Ctrl-Shift-Home", "Command-Shift-Home|Command-Shift-Up"), - exec: function(editor) { editor.getSelection().selectFileStart(); }, - multiSelectAction: "forEach", - readOnly: true, - scrollIntoView: "animate", - aceCommandGroup: "fileJump" - }, { - name: "gotostart", - bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"), - exec: function(editor) { editor.navigateFileStart(); }, - multiSelectAction: "forEach", - readOnly: true, - scrollIntoView: "animate", - aceCommandGroup: "fileJump" - }, { - name: "selectup", - bindKey: bindKey("Shift-Up", "Shift-Up|Ctrl-Shift-P"), - exec: function(editor) { editor.getSelection().selectUp(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "golineup", - bindKey: bindKey("Up", "Up|Ctrl-P"), - exec: function(editor, args) { editor.navigateUp(args.times); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "selecttoend", - bindKey: bindKey("Ctrl-Shift-End", "Command-Shift-End|Command-Shift-Down"), - exec: function(editor) { editor.getSelection().selectFileEnd(); }, - multiSelectAction: "forEach", - readOnly: true, - scrollIntoView: "animate", - aceCommandGroup: "fileJump" - }, { - name: "gotoend", - bindKey: bindKey("Ctrl-End", "Command-End|Command-Down"), - exec: function(editor) { editor.navigateFileEnd(); }, - multiSelectAction: "forEach", - readOnly: true, - scrollIntoView: "animate", - aceCommandGroup: "fileJump" - }, { - name: "selectdown", - bindKey: bindKey("Shift-Down", "Shift-Down|Ctrl-Shift-N"), - exec: function(editor) { editor.getSelection().selectDown(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "golinedown", - bindKey: bindKey("Down", "Down|Ctrl-N"), - exec: function(editor, args) { editor.navigateDown(args.times); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "selectwordleft", - bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"), - exec: function(editor) { editor.getSelection().selectWordLeft(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "gotowordleft", - bindKey: bindKey("Ctrl-Left", "Option-Left"), - exec: function(editor) { editor.navigateWordLeft(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "selecttolinestart", - bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left|Ctrl-Shift-A"), - exec: function(editor) { editor.getSelection().selectLineStart(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "gotolinestart", - bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"), - exec: function(editor) { editor.navigateLineStart(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "selectleft", - bindKey: bindKey("Shift-Left", "Shift-Left|Ctrl-Shift-B"), - exec: function(editor) { editor.getSelection().selectLeft(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "gotoleft", - bindKey: bindKey("Left", "Left|Ctrl-B"), - exec: function(editor, args) { editor.navigateLeft(args.times); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "selectwordright", - bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"), - exec: function(editor) { editor.getSelection().selectWordRight(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "gotowordright", - bindKey: bindKey("Ctrl-Right", "Option-Right"), - exec: function(editor) { editor.navigateWordRight(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "selecttolineend", - bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right|Shift-End|Ctrl-Shift-E"), - exec: function(editor) { editor.getSelection().selectLineEnd(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "gotolineend", - bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"), - exec: function(editor) { editor.navigateLineEnd(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "selectright", - bindKey: bindKey("Shift-Right", "Shift-Right"), - exec: function(editor) { editor.getSelection().selectRight(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "gotoright", - bindKey: bindKey("Right", "Right|Ctrl-F"), - exec: function(editor, args) { editor.navigateRight(args.times); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "selectpagedown", - bindKey: "Shift-PageDown", - exec: function(editor) { editor.selectPageDown(); }, - readOnly: true - }, { - name: "pagedown", - bindKey: bindKey(null, "Option-PageDown"), - exec: function(editor) { editor.scrollPageDown(); }, - readOnly: true - }, { - name: "gotopagedown", - bindKey: bindKey("PageDown", "PageDown|Ctrl-V"), - exec: function(editor) { editor.gotoPageDown(); }, - readOnly: true - }, { - name: "selectpageup", - bindKey: "Shift-PageUp", - exec: function(editor) { editor.selectPageUp(); }, - readOnly: true - }, { - name: "pageup", - bindKey: bindKey(null, "Option-PageUp"), - exec: function(editor) { editor.scrollPageUp(); }, - readOnly: true - }, { - name: "gotopageup", - bindKey: "PageUp", - exec: function(editor) { editor.gotoPageUp(); }, - readOnly: true - }, { - name: "scrollup", - bindKey: bindKey("Ctrl-Up", null), - exec: function(e) { e.renderer.scrollBy(0, -2 * e.renderer.layerConfig.lineHeight); }, - readOnly: true - }, { - name: "scrolldown", - bindKey: bindKey("Ctrl-Down", null), - exec: function(e) { e.renderer.scrollBy(0, 2 * e.renderer.layerConfig.lineHeight); }, - readOnly: true - }, { - name: "selectlinestart", - bindKey: "Shift-Home", - exec: function(editor) { editor.getSelection().selectLineStart(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "selectlineend", - bindKey: "Shift-End", - exec: function(editor) { editor.getSelection().selectLineEnd(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "togglerecording", - bindKey: bindKey("Ctrl-Alt-E", "Command-Option-E"), - exec: function(editor) { editor.commands.toggleRecording(editor); }, - readOnly: true - }, { - name: "replaymacro", - bindKey: bindKey("Ctrl-Shift-E", "Command-Shift-E"), - exec: function(editor) { editor.commands.replay(editor); }, - readOnly: true - }, { - name: "jumptomatching", - bindKey: bindKey("Ctrl-P", "Ctrl-P"), - exec: function(editor) { editor.jumpToMatching(); }, - multiSelectAction: "forEach", - scrollIntoView: "animate", - readOnly: true - }, { - name: "selecttomatching", - bindKey: bindKey("Ctrl-Shift-P", "Ctrl-Shift-P"), - exec: function(editor) { editor.jumpToMatching(true); }, - multiSelectAction: "forEach", - scrollIntoView: "animate", - readOnly: true - }, { - name: "expandToMatching", - bindKey: bindKey("Ctrl-Shift-M", "Ctrl-Shift-M"), - exec: function(editor) { editor.jumpToMatching(true, true); }, - multiSelectAction: "forEach", - scrollIntoView: "animate", - readOnly: true - }, { - name: "passKeysToBrowser", - bindKey: bindKey(null, null), - exec: function() {}, - passEvent: true, - readOnly: true - }, { - name: "copy", - exec: function(editor) { - }, - readOnly: true - }, - { - name: "cut", - exec: function(editor) { - var range = editor.getSelectionRange(); - editor._emit("cut", range); - - if (!editor.selection.isEmpty()) { - editor.session.remove(range); - editor.clearSelection(); - } - }, - scrollIntoView: "cursor", - multiSelectAction: "forEach" - }, { - name: "paste", - exec: function(editor, args) { - editor.$handlePaste(args); - }, - scrollIntoView: "cursor" - }, { - name: "removeline", - bindKey: bindKey("Ctrl-D", "Command-D"), - exec: function(editor) { editor.removeLines(); }, - scrollIntoView: "cursor", - multiSelectAction: "forEachLine" - }, { - name: "duplicateSelection", - bindKey: bindKey("Ctrl-Shift-D", "Command-Shift-D"), - exec: function(editor) { editor.duplicateSelection(); }, - scrollIntoView: "cursor", - multiSelectAction: "forEach" - }, { - name: "sortlines", - bindKey: bindKey("Ctrl-Alt-S", "Command-Alt-S"), - exec: function(editor) { editor.sortLines(); }, - scrollIntoView: "selection", - multiSelectAction: "forEachLine" - }, { - name: "togglecomment", - bindKey: bindKey("Ctrl-/", "Command-/"), - exec: function(editor) { editor.toggleCommentLines(); }, - multiSelectAction: "forEachLine", - scrollIntoView: "selectionPart" - }, { - name: "toggleBlockComment", - bindKey: bindKey("Ctrl-Shift-/", "Command-Shift-/"), - exec: function(editor) { editor.toggleBlockComment(); }, - multiSelectAction: "forEach", - scrollIntoView: "selectionPart" - }, { - name: "modifyNumberUp", - bindKey: bindKey("Ctrl-Shift-Up", "Alt-Shift-Up"), - exec: function(editor) { editor.modifyNumber(1); }, - scrollIntoView: "cursor", - multiSelectAction: "forEach" - }, { - name: "modifyNumberDown", - bindKey: bindKey("Ctrl-Shift-Down", "Alt-Shift-Down"), - exec: function(editor) { editor.modifyNumber(-1); }, - scrollIntoView: "cursor", - multiSelectAction: "forEach" - }, { - name: "replace", - bindKey: bindKey("Ctrl-H", "Command-Option-F"), - exec: function(editor) { - config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor, true);}); - } - }, { - name: "undo", - bindKey: bindKey("Ctrl-Z", "Command-Z"), - exec: function(editor) { editor.undo(); } - }, { - name: "redo", - bindKey: bindKey("Ctrl-Shift-Z|Ctrl-Y", "Command-Shift-Z|Command-Y"), - exec: function(editor) { editor.redo(); } - }, { - name: "copylinesup", - bindKey: bindKey("Alt-Shift-Up", "Command-Option-Up"), - exec: function(editor) { editor.copyLinesUp(); }, - scrollIntoView: "cursor" - }, { - name: "movelinesup", - bindKey: bindKey("Alt-Up", "Option-Up"), - exec: function(editor) { editor.moveLinesUp(); }, - scrollIntoView: "cursor" - }, { - name: "copylinesdown", - bindKey: bindKey("Alt-Shift-Down", "Command-Option-Down"), - exec: function(editor) { editor.copyLinesDown(); }, - scrollIntoView: "cursor" - }, { - name: "movelinesdown", - bindKey: bindKey("Alt-Down", "Option-Down"), - exec: function(editor) { editor.moveLinesDown(); }, - scrollIntoView: "cursor" - }, { - name: "del", - bindKey: bindKey("Delete", "Delete|Ctrl-D|Shift-Delete"), - exec: function(editor) { editor.remove("right"); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" - }, { - name: "backspace", - bindKey: bindKey( - "Shift-Backspace|Backspace", - "Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H" - ), - exec: function(editor) { editor.remove("left"); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" - }, { - name: "cut_or_delete", - bindKey: bindKey("Shift-Delete", null), - exec: function(editor) { - if (editor.selection.isEmpty()) { - editor.remove("left"); - } else { - return false; - } - }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" - }, { - name: "removetolinestart", - bindKey: bindKey("Alt-Backspace", "Command-Backspace"), - exec: function(editor) { editor.removeToLineStart(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" - }, { - name: "removetolineend", - bindKey: bindKey("Alt-Delete", "Ctrl-K|Command-Delete"), - exec: function(editor) { editor.removeToLineEnd(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" - }, { - name: "removetolinestarthard", - bindKey: bindKey("Ctrl-Shift-Backspace", null), - exec: function(editor) { - var range = editor.selection.getRange(); - range.start.column = 0; - editor.session.remove(range); - }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" - }, { - name: "removetolineendhard", - bindKey: bindKey("Ctrl-Shift-Delete", null), - exec: function(editor) { - var range = editor.selection.getRange(); - range.end.column = Number.MAX_VALUE; - editor.session.remove(range); - }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" - }, { - name: "removewordleft", - bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"), - exec: function(editor) { editor.removeWordLeft(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" - }, { - name: "removewordright", - bindKey: bindKey("Ctrl-Delete", "Alt-Delete"), - exec: function(editor) { editor.removeWordRight(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" - }, { - name: "outdent", - bindKey: bindKey("Shift-Tab", "Shift-Tab"), - exec: function(editor) { editor.blockOutdent(); }, - multiSelectAction: "forEach", - scrollIntoView: "selectionPart" - }, { - name: "indent", - bindKey: bindKey("Tab", "Tab"), - exec: function(editor) { editor.indent(); }, - multiSelectAction: "forEach", - scrollIntoView: "selectionPart" - }, { - name: "blockoutdent", - bindKey: bindKey("Ctrl-[", "Ctrl-["), - exec: function(editor) { editor.blockOutdent(); }, - multiSelectAction: "forEachLine", - scrollIntoView: "selectionPart" - }, { - name: "blockindent", - bindKey: bindKey("Ctrl-]", "Ctrl-]"), - exec: function(editor) { editor.blockIndent(); }, - multiSelectAction: "forEachLine", - scrollIntoView: "selectionPart" - }, { - name: "insertstring", - exec: function(editor, str) { editor.insert(str); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" - }, { - name: "inserttext", - exec: function(editor, args) { - editor.insert(lang.stringRepeat(args.text || "", args.times || 1)); - }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" - }, { - name: "splitline", - bindKey: bindKey(null, "Ctrl-O"), - exec: function(editor) { editor.splitLine(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" - }, { - name: "transposeletters", - bindKey: bindKey("Alt-Shift-X", "Ctrl-T"), - exec: function(editor) { editor.transposeLetters(); }, - multiSelectAction: function(editor) {editor.transposeSelections(1); }, - scrollIntoView: "cursor" - }, { - name: "touppercase", - bindKey: bindKey("Ctrl-U", "Ctrl-U"), - exec: function(editor) { editor.toUpperCase(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" - }, { - name: "tolowercase", - bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"), - exec: function(editor) { editor.toLowerCase(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" - }, { - name: "expandtoline", - bindKey: bindKey("Ctrl-Shift-L", "Command-Shift-L"), - exec: function(editor) { - var range = editor.selection.getRange(); - - range.start.column = range.end.column = 0; - range.end.row++; - editor.selection.setRange(range, false); - }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true - }, { - name: "joinlines", - bindKey: bindKey(null, null), - exec: function(editor) { - var isBackwards = editor.selection.isBackwards(); - var selectionStart = isBackwards ? editor.selection.getSelectionLead() : editor.selection.getSelectionAnchor(); - var selectionEnd = isBackwards ? editor.selection.getSelectionAnchor() : editor.selection.getSelectionLead(); - var firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length; - var selectedText = editor.session.doc.getTextRange(editor.selection.getRange()); - var selectedCount = selectedText.replace(/\n\s*/, " ").length; - var insertLine = editor.session.doc.getLine(selectionStart.row); - - for (var i = selectionStart.row + 1; i <= selectionEnd.row + 1; i++) { - var curLine = lang.stringTrimLeft(lang.stringTrimRight(editor.session.doc.getLine(i))); - if (curLine.length !== 0) { - curLine = " " + curLine; - } - insertLine += curLine; - } - - if (selectionEnd.row + 1 < (editor.session.doc.getLength() - 1)) { - insertLine += editor.session.doc.getNewLineCharacter(); - } - - editor.clearSelection(); - editor.session.doc.replace(new Range(selectionStart.row, 0, selectionEnd.row + 2, 0), insertLine); - - if (selectedCount > 0) { - editor.selection.moveCursorTo(selectionStart.row, selectionStart.column); - editor.selection.selectTo(selectionStart.row, selectionStart.column + selectedCount); - } else { - firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length > firstLineEndCol ? (firstLineEndCol + 1) : firstLineEndCol; - editor.selection.moveCursorTo(selectionStart.row, firstLineEndCol); - } - }, - multiSelectAction: "forEach", - readOnly: true - }, { - name: "invertSelection", - bindKey: bindKey(null, null), - exec: function(editor) { - var endRow = editor.session.doc.getLength() - 1; - var endCol = editor.session.doc.getLine(endRow).length; - var ranges = editor.selection.rangeList.ranges; - var newRanges = []; - if (ranges.length < 1) { - ranges = [editor.selection.getRange()]; - } - - for (var i = 0; i < ranges.length; i++) { - if (i == (ranges.length - 1)) { - if (!(ranges[i].end.row === endRow && ranges[i].end.column === endCol)) { - newRanges.push(new Range(ranges[i].end.row, ranges[i].end.column, endRow, endCol)); - } - } - - if (i === 0) { - if (!(ranges[i].start.row === 0 && ranges[i].start.column === 0)) { - newRanges.push(new Range(0, 0, ranges[i].start.row, ranges[i].start.column)); - } - } else { - newRanges.push(new Range(ranges[i-1].end.row, ranges[i-1].end.column, ranges[i].start.row, ranges[i].start.column)); - } - } - - editor.exitMultiSelectMode(); - editor.clearSelection(); - - for(var i = 0; i < newRanges.length; i++) { - editor.selection.addRange(newRanges[i], false); - } - }, - readOnly: true, - scrollIntoView: "none" - }]; - - }); - - ace.define("ace/editor",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/keyboard/textinput","ace/mouse/mouse_handler","ace/mouse/fold_handler","ace/keyboard/keybinding","ace/edit_session","ace/search","ace/range","ace/lib/event_emitter","ace/commands/command_manager","ace/commands/default_commands","ace/config","ace/token_iterator"], function(acequire, exports, module) { - "use strict"; - - acequire("./lib/fixoldbrowsers"); - - var oop = acequire("./lib/oop"); - var dom = acequire("./lib/dom"); - var lang = acequire("./lib/lang"); - var useragent = acequire("./lib/useragent"); - var TextInput = acequire("./keyboard/textinput").TextInput; - var MouseHandler = acequire("./mouse/mouse_handler").MouseHandler; - var FoldHandler = acequire("./mouse/fold_handler").FoldHandler; - var KeyBinding = acequire("./keyboard/keybinding").KeyBinding; - var EditSession = acequire("./edit_session").EditSession; - var Search = acequire("./search").Search; - var Range = acequire("./range").Range; - var EventEmitter = acequire("./lib/event_emitter").EventEmitter; - var CommandManager = acequire("./commands/command_manager").CommandManager; - var defaultCommands = acequire("./commands/default_commands").commands; - var config = acequire("./config"); - var TokenIterator = acequire("./token_iterator").TokenIterator; - var Editor = function(renderer, session) { - var container = renderer.getContainerElement(); - this.container = container; - this.renderer = renderer; - this.id = "editor" + (++Editor.$uid); - - this.commands = new CommandManager(useragent.isMac ? "mac" : "win", defaultCommands); - if (typeof document == "object") { - this.textInput = new TextInput(renderer.getTextAreaContainer(), this); - this.renderer.textarea = this.textInput.getElement(); - this.$mouseHandler = new MouseHandler(this); - new FoldHandler(this); - } - - this.keyBinding = new KeyBinding(this); - - this.$blockScrolling = 0; - this.$search = new Search().set({ - wrap: true - }); - - this.$historyTracker = this.$historyTracker.bind(this); - this.commands.on("exec", this.$historyTracker); - - this.$initOperationListeners(); - - this._$emitInputEvent = lang.delayedCall(function() { - this._signal("input", {}); - if (this.session && this.session.bgTokenizer) - this.session.bgTokenizer.scheduleStart(); - }.bind(this)); - - this.on("change", function(_, _self) { - _self._$emitInputEvent.schedule(31); - }); - - this.setSession(session || new EditSession("")); - config.resetOptions(this); - config._signal("editor", this); - }; - - Editor.$uid = 0; - - (function(){ - - oop.implement(this, EventEmitter); - - this.$initOperationListeners = function() { - function last(a) {return a[a.length - 1];} - - this.selections = []; - this.commands.on("exec", this.startOperation.bind(this), true); - this.commands.on("afterExec", this.endOperation.bind(this), true); - - this.$opResetTimer = lang.delayedCall(this.endOperation.bind(this)); - - this.on("change", function() { - this.curOp || this.startOperation(); - this.curOp.docChanged = true; - }.bind(this), true); - - this.on("changeSelection", function() { - this.curOp || this.startOperation(); - this.curOp.selectionChanged = true; - }.bind(this), true); - }; - - this.curOp = null; - this.prevOp = {}; - this.startOperation = function(commadEvent) { - if (this.curOp) { - if (!commadEvent || this.curOp.command) - return; - this.prevOp = this.curOp; - } - if (!commadEvent) { - this.previousCommand = null; - commadEvent = {}; - } - - this.$opResetTimer.schedule(); - this.curOp = { - command: commadEvent.command || {}, - args: commadEvent.args, - scrollTop: this.renderer.scrollTop - }; - if (this.curOp.command.name && this.curOp.command.scrollIntoView !== undefined) - this.$blockScrolling++; - }; - - this.endOperation = function(e) { - if (this.curOp) { - if (e && e.returnValue === false) - return this.curOp = null; - this._signal("beforeEndOperation"); - var command = this.curOp.command; - if (command.name && this.$blockScrolling > 0) - this.$blockScrolling--; - var scrollIntoView = command && command.scrollIntoView; - if (scrollIntoView) { - switch (scrollIntoView) { - case "center-animate": - scrollIntoView = "animate"; - case "center": - this.renderer.scrollCursorIntoView(null, 0.5); - break; - case "animate": - case "cursor": - this.renderer.scrollCursorIntoView(); - break; - case "selectionPart": - var range = this.selection.getRange(); - var config = this.renderer.layerConfig; - if (range.start.row >= config.lastRow || range.end.row <= config.firstRow) { - this.renderer.scrollSelectionIntoView(this.selection.anchor, this.selection.lead); - } - break; - default: - break; - } - if (scrollIntoView == "animate") - this.renderer.animateScrolling(this.curOp.scrollTop); - } - - this.prevOp = this.curOp; - this.curOp = null; - } - }; - this.$mergeableCommands = ["backspace", "del", "insertstring"]; - this.$historyTracker = function(e) { - if (!this.$mergeUndoDeltas) - return; - - var prev = this.prevOp; - var mergeableCommands = this.$mergeableCommands; - var shouldMerge = prev.command && (e.command.name == prev.command.name); - if (e.command.name == "insertstring") { - var text = e.args; - if (this.mergeNextCommand === undefined) - this.mergeNextCommand = true; - - shouldMerge = shouldMerge - && this.mergeNextCommand // previous command allows to coalesce with - && (!/\s/.test(text) || /\s/.test(prev.args)); // previous insertion was of same type - - this.mergeNextCommand = true; - } else { - shouldMerge = shouldMerge - && mergeableCommands.indexOf(e.command.name) !== -1; // the command is mergeable - } - - if ( - this.$mergeUndoDeltas != "always" - && Date.now() - this.sequenceStartTime > 2000 - ) { - shouldMerge = false; // the sequence is too long - } - - if (shouldMerge) - this.session.mergeUndoDeltas = true; - else if (mergeableCommands.indexOf(e.command.name) !== -1) - this.sequenceStartTime = Date.now(); - }; - this.setKeyboardHandler = function(keyboardHandler, cb) { - if (keyboardHandler && typeof keyboardHandler === "string") { - this.$keybindingId = keyboardHandler; - var _self = this; - config.loadModule(["keybinding", keyboardHandler], function(module) { - if (_self.$keybindingId == keyboardHandler) - _self.keyBinding.setKeyboardHandler(module && module.handler); - cb && cb(); - }); - } else { - this.$keybindingId = null; - this.keyBinding.setKeyboardHandler(keyboardHandler); - cb && cb(); - } - }; - this.getKeyboardHandler = function() { - return this.keyBinding.getKeyboardHandler(); - }; - this.setSession = function(session) { - if (this.session == session) - return; - if (this.curOp) this.endOperation(); - this.curOp = {}; - - var oldSession = this.session; - if (oldSession) { - this.session.off("change", this.$onDocumentChange); - this.session.off("changeMode", this.$onChangeMode); - this.session.off("tokenizerUpdate", this.$onTokenizerUpdate); - this.session.off("changeTabSize", this.$onChangeTabSize); - this.session.off("changeWrapLimit", this.$onChangeWrapLimit); - this.session.off("changeWrapMode", this.$onChangeWrapMode); - this.session.off("changeFold", this.$onChangeFold); - this.session.off("changeFrontMarker", this.$onChangeFrontMarker); - this.session.off("changeBackMarker", this.$onChangeBackMarker); - this.session.off("changeBreakpoint", this.$onChangeBreakpoint); - this.session.off("changeAnnotation", this.$onChangeAnnotation); - this.session.off("changeOverwrite", this.$onCursorChange); - this.session.off("changeScrollTop", this.$onScrollTopChange); - this.session.off("changeScrollLeft", this.$onScrollLeftChange); - - var selection = this.session.getSelection(); - selection.off("changeCursor", this.$onCursorChange); - selection.off("changeSelection", this.$onSelectionChange); - } - - this.session = session; - if (session) { - this.$onDocumentChange = this.onDocumentChange.bind(this); - session.on("change", this.$onDocumentChange); - this.renderer.setSession(session); - - this.$onChangeMode = this.onChangeMode.bind(this); - session.on("changeMode", this.$onChangeMode); - - this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this); - session.on("tokenizerUpdate", this.$onTokenizerUpdate); - - this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer); - session.on("changeTabSize", this.$onChangeTabSize); - - this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this); - session.on("changeWrapLimit", this.$onChangeWrapLimit); - - this.$onChangeWrapMode = this.onChangeWrapMode.bind(this); - session.on("changeWrapMode", this.$onChangeWrapMode); - - this.$onChangeFold = this.onChangeFold.bind(this); - session.on("changeFold", this.$onChangeFold); - - this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this); - this.session.on("changeFrontMarker", this.$onChangeFrontMarker); - - this.$onChangeBackMarker = this.onChangeBackMarker.bind(this); - this.session.on("changeBackMarker", this.$onChangeBackMarker); - - this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this); - this.session.on("changeBreakpoint", this.$onChangeBreakpoint); - - this.$onChangeAnnotation = this.onChangeAnnotation.bind(this); - this.session.on("changeAnnotation", this.$onChangeAnnotation); - - this.$onCursorChange = this.onCursorChange.bind(this); - this.session.on("changeOverwrite", this.$onCursorChange); - - this.$onScrollTopChange = this.onScrollTopChange.bind(this); - this.session.on("changeScrollTop", this.$onScrollTopChange); - - this.$onScrollLeftChange = this.onScrollLeftChange.bind(this); - this.session.on("changeScrollLeft", this.$onScrollLeftChange); - - this.selection = session.getSelection(); - this.selection.on("changeCursor", this.$onCursorChange); - - this.$onSelectionChange = this.onSelectionChange.bind(this); - this.selection.on("changeSelection", this.$onSelectionChange); - - this.onChangeMode(); - - this.$blockScrolling += 1; - this.onCursorChange(); - this.$blockScrolling -= 1; - - this.onScrollTopChange(); - this.onScrollLeftChange(); - this.onSelectionChange(); - this.onChangeFrontMarker(); - this.onChangeBackMarker(); - this.onChangeBreakpoint(); - this.onChangeAnnotation(); - this.session.getUseWrapMode() && this.renderer.adjustWrapLimit(); - this.renderer.updateFull(); - } else { - this.selection = null; - this.renderer.setSession(session); - } - - this._signal("changeSession", { - session: session, - oldSession: oldSession - }); - - this.curOp = null; - - oldSession && oldSession._signal("changeEditor", {oldEditor: this}); - session && session._signal("changeEditor", {editor: this}); - - if (session && session.bgTokenizer) - session.bgTokenizer.scheduleStart(); - }; - this.getSession = function() { - return this.session; - }; - this.setValue = function(val, cursorPos) { - this.session.doc.setValue(val); - - if (!cursorPos) - this.selectAll(); - else if (cursorPos == 1) - this.navigateFileEnd(); - else if (cursorPos == -1) - this.navigateFileStart(); - - return val; - }; - this.getValue = function() { - return this.session.getValue(); - }; - this.getSelection = function() { - return this.selection; - }; - this.resize = function(force) { - this.renderer.onResize(force); - }; - this.setTheme = function(theme, cb) { - this.renderer.setTheme(theme, cb); - }; - this.getTheme = function() { - return this.renderer.getTheme(); - }; - this.setStyle = function(style) { - this.renderer.setStyle(style); - }; - this.unsetStyle = function(style) { - this.renderer.unsetStyle(style); - }; - this.getFontSize = function () { - return this.getOption("fontSize") || - dom.computedStyle(this.container, "fontSize"); - }; - this.setFontSize = function(size) { - this.setOption("fontSize", size); - }; - - this.$highlightBrackets = function() { - if (this.session.$bracketHighlight) { - this.session.removeMarker(this.session.$bracketHighlight); - this.session.$bracketHighlight = null; - } - - if (this.$highlightPending) { - return; - } - var self = this; - this.$highlightPending = true; - setTimeout(function() { - self.$highlightPending = false; - var session = self.session; - if (!session || !session.bgTokenizer) return; - var pos = session.findMatchingBracket(self.getCursorPosition()); - if (pos) { - var range = new Range(pos.row, pos.column, pos.row, pos.column + 1); - } else if (session.$mode.getMatching) { - var range = session.$mode.getMatching(self.session); - } - if (range) - session.$bracketHighlight = session.addMarker(range, "ace_bracket", "text"); - }, 50); - }; - this.$highlightTags = function() { - if (this.$highlightTagPending) - return; - var self = this; - this.$highlightTagPending = true; - setTimeout(function() { - self.$highlightTagPending = false; - - var session = self.session; - if (!session || !session.bgTokenizer) return; - - var pos = self.getCursorPosition(); - var iterator = new TokenIterator(self.session, pos.row, pos.column); - var token = iterator.getCurrentToken(); - - if (!token || !/\b(?:tag-open|tag-name)/.test(token.type)) { - session.removeMarker(session.$tagHighlight); - session.$tagHighlight = null; - return; - } - - if (token.type.indexOf("tag-open") != -1) { - token = iterator.stepForward(); - if (!token) - return; - } - - var tag = token.value; - var depth = 0; - var prevToken = iterator.stepBackward(); - - if (prevToken.value == '<'){ - do { - prevToken = token; - token = iterator.stepForward(); - - if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) { - if (prevToken.value === '<'){ - depth++; - } else if (prevToken.value === '= 0); - } else { - do { - token = prevToken; - prevToken = iterator.stepBackward(); - - if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) { - if (prevToken.value === '<') { - depth++; - } else if (prevToken.value === ' 1)) - highlight = false; - } - - if (session.$highlightLineMarker && !highlight) { - session.removeMarker(session.$highlightLineMarker.id); - session.$highlightLineMarker = null; - } else if (!session.$highlightLineMarker && highlight) { - var range = new Range(highlight.row, highlight.column, highlight.row, Infinity); - range.id = session.addMarker(range, "ace_active-line", "screenLine"); - session.$highlightLineMarker = range; - } else if (highlight) { - session.$highlightLineMarker.start.row = highlight.row; - session.$highlightLineMarker.end.row = highlight.row; - session.$highlightLineMarker.start.column = highlight.column; - session._signal("changeBackMarker"); - } - }; - - this.onSelectionChange = function(e) { - var session = this.session; - - if (session.$selectionMarker) { - session.removeMarker(session.$selectionMarker); - } - session.$selectionMarker = null; - - if (!this.selection.isEmpty()) { - var range = this.selection.getRange(); - var style = this.getSelectionStyle(); - session.$selectionMarker = session.addMarker(range, "ace_selection", style); - } else { - this.$updateHighlightActiveLine(); - } - - var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp(); - this.session.highlight(re); - - this._signal("changeSelection"); - }; - - this.$getSelectionHighLightRegexp = function() { - var session = this.session; - - var selection = this.getSelectionRange(); - if (selection.isEmpty() || selection.isMultiLine()) - return; - - var startOuter = selection.start.column - 1; - var endOuter = selection.end.column + 1; - var line = session.getLine(selection.start.row); - var lineCols = line.length; - var needle = line.substring(Math.max(startOuter, 0), - Math.min(endOuter, lineCols)); - if ((startOuter >= 0 && /^[\w\d]/.test(needle)) || - (endOuter <= lineCols && /[\w\d]$/.test(needle))) - return; - - needle = line.substring(selection.start.column, selection.end.column); - if (!/^[\w\d]+$/.test(needle)) - return; - - var re = this.$search.$assembleRegExp({ - wholeWord: true, - caseSensitive: true, - needle: needle - }); - - return re; - }; - - - this.onChangeFrontMarker = function() { - this.renderer.updateFrontMarkers(); - }; - - this.onChangeBackMarker = function() { - this.renderer.updateBackMarkers(); - }; - - - this.onChangeBreakpoint = function() { - this.renderer.updateBreakpoints(); - }; - - this.onChangeAnnotation = function() { - this.renderer.setAnnotations(this.session.getAnnotations()); - }; - - - this.onChangeMode = function(e) { - this.renderer.updateText(); - this._emit("changeMode", e); - }; - - - this.onChangeWrapLimit = function() { - this.renderer.updateFull(); - }; - - this.onChangeWrapMode = function() { - this.renderer.onResize(true); - }; - - - this.onChangeFold = function() { - this.$updateHighlightActiveLine(); - this.renderer.updateFull(); - }; - this.getSelectedText = function() { - return this.session.getTextRange(this.getSelectionRange()); - }; - this.getCopyText = function() { - var text = this.getSelectedText(); - this._signal("copy", text); - return text; - }; - this.onCopy = function() { - this.commands.exec("copy", this); - }; - this.onCut = function() { - this.commands.exec("cut", this); - }; - this.onPaste = function(text, event) { - var e = {text: text, event: event}; - this.commands.exec("paste", this, e); - }; - - this.$handlePaste = function(e) { - if (typeof e == "string") - e = {text: e}; - this._signal("paste", e); - var text = e.text; - if (!this.inMultiSelectMode || this.inVirtualSelectionMode) { - this.insert(text); - } else { - var lines = text.split(/\r\n|\r|\n/); - var ranges = this.selection.rangeList.ranges; - - if (lines.length > ranges.length || lines.length < 2 || !lines[1]) - return this.commands.exec("insertstring", this, text); - - for (var i = ranges.length; i--;) { - var range = ranges[i]; - if (!range.isEmpty()) - this.session.remove(range); - - this.session.insert(range.start, lines[i]); - } - } - }; - - this.execCommand = function(command, args) { - return this.commands.exec(command, this, args); - }; - this.insert = function(text, pasted) { - var session = this.session; - var mode = session.getMode(); - var cursor = this.getCursorPosition(); - - if (this.getBehavioursEnabled() && !pasted) { - var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text); - if (transform) { - if (text !== transform.text) { - this.session.mergeUndoDeltas = false; - this.$mergeNextCommand = false; - } - text = transform.text; - - } - } - - if (text == "\t") - text = this.session.getTabString(); - if (!this.selection.isEmpty()) { - var range = this.getSelectionRange(); - cursor = this.session.remove(range); - this.clearSelection(); - } - else if (this.session.getOverwrite() && text.indexOf("\n") == -1) { - var range = new Range.fromPoints(cursor, cursor); - range.end.column += text.length; - this.session.remove(range); - } - - if (text == "\n" || text == "\r\n") { - var line = session.getLine(cursor.row); - if (cursor.column > line.search(/\S|$/)) { - var d = line.substr(cursor.column).search(/\S|$/); - session.doc.removeInLine(cursor.row, cursor.column, cursor.column + d); - } - } - this.clearSelection(); - - var start = cursor.column; - var lineState = session.getState(cursor.row); - var line = session.getLine(cursor.row); - var shouldOutdent = mode.checkOutdent(lineState, line, text); - var end = session.insert(cursor, text); - - if (transform && transform.selection) { - if (transform.selection.length == 2) { // Transform relative to the current column - this.selection.setSelectionRange( - new Range(cursor.row, start + transform.selection[0], - cursor.row, start + transform.selection[1])); - } else { // Transform relative to the current row. - this.selection.setSelectionRange( - new Range(cursor.row + transform.selection[0], - transform.selection[1], - cursor.row + transform.selection[2], - transform.selection[3])); - } - } - - if (session.getDocument().isNewLine(text)) { - var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString()); - - session.insert({row: cursor.row+1, column: 0}, lineIndent); - } - if (shouldOutdent) - mode.autoOutdent(lineState, session, cursor.row); - }; - - this.onTextInput = function(text) { - this.keyBinding.onTextInput(text); - }; - - this.onCommandKey = function(e, hashId, keyCode) { - this.keyBinding.onCommandKey(e, hashId, keyCode); - }; - this.setOverwrite = function(overwrite) { - this.session.setOverwrite(overwrite); - }; - this.getOverwrite = function() { - return this.session.getOverwrite(); - }; - this.toggleOverwrite = function() { - this.session.toggleOverwrite(); - }; - this.setScrollSpeed = function(speed) { - this.setOption("scrollSpeed", speed); - }; - this.getScrollSpeed = function() { - return this.getOption("scrollSpeed"); - }; - this.setDragDelay = function(dragDelay) { - this.setOption("dragDelay", dragDelay); - }; - this.getDragDelay = function() { - return this.getOption("dragDelay"); - }; - this.setSelectionStyle = function(val) { - this.setOption("selectionStyle", val); - }; - this.getSelectionStyle = function() { - return this.getOption("selectionStyle"); - }; - this.setHighlightActiveLine = function(shouldHighlight) { - this.setOption("highlightActiveLine", shouldHighlight); - }; - this.getHighlightActiveLine = function() { - return this.getOption("highlightActiveLine"); - }; - this.setHighlightGutterLine = function(shouldHighlight) { - this.setOption("highlightGutterLine", shouldHighlight); - }; - - this.getHighlightGutterLine = function() { - return this.getOption("highlightGutterLine"); - }; - this.setHighlightSelectedWord = function(shouldHighlight) { - this.setOption("highlightSelectedWord", shouldHighlight); - }; - this.getHighlightSelectedWord = function() { - return this.$highlightSelectedWord; - }; - - this.setAnimatedScroll = function(shouldAnimate){ - this.renderer.setAnimatedScroll(shouldAnimate); - }; - - this.getAnimatedScroll = function(){ - return this.renderer.getAnimatedScroll(); - }; - this.setShowInvisibles = function(showInvisibles) { - this.renderer.setShowInvisibles(showInvisibles); - }; - this.getShowInvisibles = function() { - return this.renderer.getShowInvisibles(); - }; - - this.setDisplayIndentGuides = function(display) { - this.renderer.setDisplayIndentGuides(display); - }; - - this.getDisplayIndentGuides = function() { - return this.renderer.getDisplayIndentGuides(); - }; - this.setShowPrintMargin = function(showPrintMargin) { - this.renderer.setShowPrintMargin(showPrintMargin); - }; - this.getShowPrintMargin = function() { - return this.renderer.getShowPrintMargin(); - }; - this.setPrintMarginColumn = function(showPrintMargin) { - this.renderer.setPrintMarginColumn(showPrintMargin); - }; - this.getPrintMarginColumn = function() { - return this.renderer.getPrintMarginColumn(); - }; - this.setReadOnly = function(readOnly) { - this.setOption("readOnly", readOnly); - }; - this.getReadOnly = function() { - return this.getOption("readOnly"); - }; - this.setBehavioursEnabled = function (enabled) { - this.setOption("behavioursEnabled", enabled); - }; - this.getBehavioursEnabled = function () { - return this.getOption("behavioursEnabled"); - }; - this.setWrapBehavioursEnabled = function (enabled) { - this.setOption("wrapBehavioursEnabled", enabled); - }; - this.getWrapBehavioursEnabled = function () { - return this.getOption("wrapBehavioursEnabled"); - }; - this.setShowFoldWidgets = function(show) { - this.setOption("showFoldWidgets", show); - - }; - this.getShowFoldWidgets = function() { - return this.getOption("showFoldWidgets"); - }; - - this.setFadeFoldWidgets = function(fade) { - this.setOption("fadeFoldWidgets", fade); - }; - - this.getFadeFoldWidgets = function() { - return this.getOption("fadeFoldWidgets"); - }; - this.remove = function(dir) { - if (this.selection.isEmpty()){ - if (dir == "left") - this.selection.selectLeft(); - else - this.selection.selectRight(); - } - - var range = this.getSelectionRange(); - if (this.getBehavioursEnabled()) { - var session = this.session; - var state = session.getState(range.start.row); - var new_range = session.getMode().transformAction(state, 'deletion', this, session, range); - - if (range.end.column === 0) { - var text = session.getTextRange(range); - if (text[text.length - 1] == "\n") { - var line = session.getLine(range.end.row); - if (/^\s+$/.test(line)) { - range.end.column = line.length; - } - } - } - if (new_range) - range = new_range; - } - - this.session.remove(range); - this.clearSelection(); - }; - this.removeWordRight = function() { - if (this.selection.isEmpty()) - this.selection.selectWordRight(); - - this.session.remove(this.getSelectionRange()); - this.clearSelection(); - }; - this.removeWordLeft = function() { - if (this.selection.isEmpty()) - this.selection.selectWordLeft(); - - this.session.remove(this.getSelectionRange()); - this.clearSelection(); - }; - this.removeToLineStart = function() { - if (this.selection.isEmpty()) - this.selection.selectLineStart(); - - this.session.remove(this.getSelectionRange()); - this.clearSelection(); - }; - this.removeToLineEnd = function() { - if (this.selection.isEmpty()) - this.selection.selectLineEnd(); - - var range = this.getSelectionRange(); - if (range.start.column == range.end.column && range.start.row == range.end.row) { - range.end.column = 0; - range.end.row++; - } - - this.session.remove(range); - this.clearSelection(); - }; - this.splitLine = function() { - if (!this.selection.isEmpty()) { - this.session.remove(this.getSelectionRange()); - this.clearSelection(); - } - - var cursor = this.getCursorPosition(); - this.insert("\n"); - this.moveCursorToPosition(cursor); - }; - this.transposeLetters = function() { - if (!this.selection.isEmpty()) { - return; - } - - var cursor = this.getCursorPosition(); - var column = cursor.column; - if (column === 0) - return; - - var line = this.session.getLine(cursor.row); - var swap, range; - if (column < line.length) { - swap = line.charAt(column) + line.charAt(column-1); - range = new Range(cursor.row, column-1, cursor.row, column+1); - } - else { - swap = line.charAt(column-1) + line.charAt(column-2); - range = new Range(cursor.row, column-2, cursor.row, column); - } - this.session.replace(range, swap); - this.session.selection.moveToPosition(range.end); - }; - this.toLowerCase = function() { - var originalRange = this.getSelectionRange(); - if (this.selection.isEmpty()) { - this.selection.selectWord(); - } - - var range = this.getSelectionRange(); - var text = this.session.getTextRange(range); - this.session.replace(range, text.toLowerCase()); - this.selection.setSelectionRange(originalRange); - }; - this.toUpperCase = function() { - var originalRange = this.getSelectionRange(); - if (this.selection.isEmpty()) { - this.selection.selectWord(); - } - - var range = this.getSelectionRange(); - var text = this.session.getTextRange(range); - this.session.replace(range, text.toUpperCase()); - this.selection.setSelectionRange(originalRange); - }; - this.indent = function() { - var session = this.session; - var range = this.getSelectionRange(); - - if (range.start.row < range.end.row) { - var rows = this.$getSelectedRows(); - session.indentRows(rows.first, rows.last, "\t"); - return; - } else if (range.start.column < range.end.column) { - var text = session.getTextRange(range); - if (!/^\s+$/.test(text)) { - var rows = this.$getSelectedRows(); - session.indentRows(rows.first, rows.last, "\t"); - return; - } - } - - var line = session.getLine(range.start.row); - var position = range.start; - var size = session.getTabSize(); - var column = session.documentToScreenColumn(position.row, position.column); - - if (this.session.getUseSoftTabs()) { - var count = (size - column % size); - var indentString = lang.stringRepeat(" ", count); - } else { - var count = column % size; - while (line[range.start.column - 1] == " " && count) { - range.start.column--; - count--; - } - this.selection.setSelectionRange(range); - indentString = "\t"; - } - return this.insert(indentString); - }; - this.blockIndent = function() { - var rows = this.$getSelectedRows(); - this.session.indentRows(rows.first, rows.last, "\t"); - }; - this.blockOutdent = function() { - var selection = this.session.getSelection(); - this.session.outdentRows(selection.getRange()); - }; - this.sortLines = function() { - var rows = this.$getSelectedRows(); - var session = this.session; - - var lines = []; - for (var i = rows.first; i <= rows.last; i++) - lines.push(session.getLine(i)); - - lines.sort(function(a, b) { - if (a.toLowerCase() < b.toLowerCase()) return -1; - if (a.toLowerCase() > b.toLowerCase()) return 1; - return 0; - }); - - var deleteRange = new Range(0, 0, 0, 0); - for (var i = rows.first; i <= rows.last; i++) { - var line = session.getLine(i); - deleteRange.start.row = i; - deleteRange.end.row = i; - deleteRange.end.column = line.length; - session.replace(deleteRange, lines[i-rows.first]); - } - }; - this.toggleCommentLines = function() { - var state = this.session.getState(this.getCursorPosition().row); - var rows = this.$getSelectedRows(); - this.session.getMode().toggleCommentLines(state, this.session, rows.first, rows.last); - }; - - this.toggleBlockComment = function() { - var cursor = this.getCursorPosition(); - var state = this.session.getState(cursor.row); - var range = this.getSelectionRange(); - this.session.getMode().toggleBlockComment(state, this.session, range, cursor); - }; - this.getNumberAt = function(row, column) { - var _numberRx = /[\-]?[0-9]+(?:\.[0-9]+)?/g; - _numberRx.lastIndex = 0; - - var s = this.session.getLine(row); - while (_numberRx.lastIndex < column) { - var m = _numberRx.exec(s); - if(m.index <= column && m.index+m[0].length >= column){ - var number = { - value: m[0], - start: m.index, - end: m.index+m[0].length - }; - return number; - } - } - return null; - }; - this.modifyNumber = function(amount) { - var row = this.selection.getCursor().row; - var column = this.selection.getCursor().column; - var charRange = new Range(row, column-1, row, column); - - var c = this.session.getTextRange(charRange); - if (!isNaN(parseFloat(c)) && isFinite(c)) { - var nr = this.getNumberAt(row, column); - if (nr) { - var fp = nr.value.indexOf(".") >= 0 ? nr.start + nr.value.indexOf(".") + 1 : nr.end; - var decimals = nr.start + nr.value.length - fp; - - var t = parseFloat(nr.value); - t *= Math.pow(10, decimals); - - - if(fp !== nr.end && column < fp){ - amount *= Math.pow(10, nr.end - column - 1); - } else { - amount *= Math.pow(10, nr.end - column); - } - - t += amount; - t /= Math.pow(10, decimals); - var nnr = t.toFixed(decimals); - var replaceRange = new Range(row, nr.start, row, nr.end); - this.session.replace(replaceRange, nnr); - this.moveCursorTo(row, Math.max(nr.start +1, column + nnr.length - nr.value.length)); - - } - } - }; - this.removeLines = function() { - var rows = this.$getSelectedRows(); - this.session.removeFullLines(rows.first, rows.last); - this.clearSelection(); - }; - - this.duplicateSelection = function() { - var sel = this.selection; - var doc = this.session; - var range = sel.getRange(); - var reverse = sel.isBackwards(); - if (range.isEmpty()) { - var row = range.start.row; - doc.duplicateLines(row, row); - } else { - var point = reverse ? range.start : range.end; - var endPoint = doc.insert(point, doc.getTextRange(range), false); - range.start = point; - range.end = endPoint; - - sel.setSelectionRange(range, reverse); - } - }; - this.moveLinesDown = function() { - this.$moveLines(1, false); - }; - this.moveLinesUp = function() { - this.$moveLines(-1, false); - }; - this.moveText = function(range, toPosition, copy) { - return this.session.moveText(range, toPosition, copy); - }; - this.copyLinesUp = function() { - this.$moveLines(-1, true); - }; - this.copyLinesDown = function() { - this.$moveLines(1, true); - }; - this.$moveLines = function(dir, copy) { - var rows, moved; - var selection = this.selection; - if (!selection.inMultiSelectMode || this.inVirtualSelectionMode) { - var range = selection.toOrientedRange(); - rows = this.$getSelectedRows(range); - moved = this.session.$moveLines(rows.first, rows.last, copy ? 0 : dir); - if (copy && dir == -1) moved = 0; - range.moveBy(moved, 0); - selection.fromOrientedRange(range); - } else { - var ranges = selection.rangeList.ranges; - selection.rangeList.detach(this.session); - this.inVirtualSelectionMode = true; - - var diff = 0; - var totalDiff = 0; - var l = ranges.length; - for (var i = 0; i < l; i++) { - var rangeIndex = i; - ranges[i].moveBy(diff, 0); - rows = this.$getSelectedRows(ranges[i]); - var first = rows.first; - var last = rows.last; - while (++i < l) { - if (totalDiff) ranges[i].moveBy(totalDiff, 0); - var subRows = this.$getSelectedRows(ranges[i]); - if (copy && subRows.first != last) - break; - else if (!copy && subRows.first > last + 1) - break; - last = subRows.last; - } - i--; - diff = this.session.$moveLines(first, last, copy ? 0 : dir); - if (copy && dir == -1) rangeIndex = i + 1; - while (rangeIndex <= i) { - ranges[rangeIndex].moveBy(diff, 0); - rangeIndex++; - } - if (!copy) diff = 0; - totalDiff += diff; - } - - selection.fromOrientedRange(selection.ranges[0]); - selection.rangeList.attach(this.session); - this.inVirtualSelectionMode = false; - } - }; - this.$getSelectedRows = function(range) { - range = (range || this.getSelectionRange()).collapseRows(); - - return { - first: this.session.getRowFoldStart(range.start.row), - last: this.session.getRowFoldEnd(range.end.row) - }; - }; - - this.onCompositionStart = function(text) { - this.renderer.showComposition(this.getCursorPosition()); - }; - - this.onCompositionUpdate = function(text) { - this.renderer.setCompositionText(text); - }; - - this.onCompositionEnd = function() { - this.renderer.hideComposition(); - }; - this.getFirstVisibleRow = function() { - return this.renderer.getFirstVisibleRow(); - }; - this.getLastVisibleRow = function() { - return this.renderer.getLastVisibleRow(); - }; - this.isRowVisible = function(row) { - return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow()); - }; - this.isRowFullyVisible = function(row) { - return (row >= this.renderer.getFirstFullyVisibleRow() && row <= this.renderer.getLastFullyVisibleRow()); - }; - this.$getVisibleRowCount = function() { - return this.renderer.getScrollBottomRow() - this.renderer.getScrollTopRow() + 1; - }; - - this.$moveByPage = function(dir, select) { - var renderer = this.renderer; - var config = this.renderer.layerConfig; - var rows = dir * Math.floor(config.height / config.lineHeight); - - this.$blockScrolling++; - if (select === true) { - this.selection.$moveSelection(function(){ - this.moveCursorBy(rows, 0); - }); - } else if (select === false) { - this.selection.moveCursorBy(rows, 0); - this.selection.clearSelection(); - } - this.$blockScrolling--; - - var scrollTop = renderer.scrollTop; - - renderer.scrollBy(0, rows * config.lineHeight); - if (select != null) - renderer.scrollCursorIntoView(null, 0.5); - - renderer.animateScrolling(scrollTop); - }; - this.selectPageDown = function() { - this.$moveByPage(1, true); - }; - this.selectPageUp = function() { - this.$moveByPage(-1, true); - }; - this.gotoPageDown = function() { - this.$moveByPage(1, false); - }; - this.gotoPageUp = function() { - this.$moveByPage(-1, false); - }; - this.scrollPageDown = function() { - this.$moveByPage(1); - }; - this.scrollPageUp = function() { - this.$moveByPage(-1); - }; - this.scrollToRow = function(row) { - this.renderer.scrollToRow(row); - }; - this.scrollToLine = function(line, center, animate, callback) { - this.renderer.scrollToLine(line, center, animate, callback); - }; - this.centerSelection = function() { - var range = this.getSelectionRange(); - var pos = { - row: Math.floor(range.start.row + (range.end.row - range.start.row) / 2), - column: Math.floor(range.start.column + (range.end.column - range.start.column) / 2) - }; - this.renderer.alignCursor(pos, 0.5); - }; - this.getCursorPosition = function() { - return this.selection.getCursor(); - }; - this.getCursorPositionScreen = function() { - return this.session.documentToScreenPosition(this.getCursorPosition()); - }; - this.getSelectionRange = function() { - return this.selection.getRange(); - }; - this.selectAll = function() { - this.$blockScrolling += 1; - this.selection.selectAll(); - this.$blockScrolling -= 1; - }; - this.clearSelection = function() { - this.selection.clearSelection(); - }; - this.moveCursorTo = function(row, column) { - this.selection.moveCursorTo(row, column); - }; - this.moveCursorToPosition = function(pos) { - this.selection.moveCursorToPosition(pos); - }; - this.jumpToMatching = function(select, expand) { - var cursor = this.getCursorPosition(); - var iterator = new TokenIterator(this.session, cursor.row, cursor.column); - var prevToken = iterator.getCurrentToken(); - var token = prevToken || iterator.stepForward(); - - if (!token) return; - var matchType; - var found = false; - var depth = {}; - var i = cursor.column - token.start; - var bracketType; - var brackets = { - ")": "(", - "(": "(", - "]": "[", - "[": "[", - "{": "{", - "}": "{" - }; - - do { - if (token.value.match(/[{}()\[\]]/g)) { - for (; i < token.value.length && !found; i++) { - if (!brackets[token.value[i]]) { - continue; - } - - bracketType = brackets[token.value[i]] + '.' + token.type.replace("rparen", "lparen"); - - if (isNaN(depth[bracketType])) { - depth[bracketType] = 0; - } - - switch (token.value[i]) { - case '(': - case '[': - case '{': - depth[bracketType]++; - break; - case ')': - case ']': - case '}': - depth[bracketType]--; - - if (depth[bracketType] === -1) { - matchType = 'bracket'; - found = true; - } - break; - } - } - } - else if (token && token.type.indexOf('tag-name') !== -1) { - if (isNaN(depth[token.value])) { - depth[token.value] = 0; - } - - if (prevToken.value === '<') { - depth[token.value]++; - } - else if (prevToken.value === '= 0; --i) { - if(this.$tryReplace(ranges[i], replacement)) { - replaced++; - } - } - - this.selection.setSelectionRange(selection); - this.$blockScrolling -= 1; - - return replaced; - }; - - this.$tryReplace = function(range, replacement) { - var input = this.session.getTextRange(range); - replacement = this.$search.replace(input, replacement); - if (replacement !== null) { - range.end = this.session.replace(range, replacement); - return range; - } else { - return null; - } - }; - this.getLastSearchOptions = function() { - return this.$search.getOptions(); - }; - this.find = function(needle, options, animate) { - if (!options) - options = {}; - - if (typeof needle == "string" || needle instanceof RegExp) - options.needle = needle; - else if (typeof needle == "object") - oop.mixin(options, needle); - - var range = this.selection.getRange(); - if (options.needle == null) { - needle = this.session.getTextRange(range) - || this.$search.$options.needle; - if (!needle) { - range = this.session.getWordRange(range.start.row, range.start.column); - needle = this.session.getTextRange(range); - } - this.$search.set({needle: needle}); - } - - this.$search.set(options); - if (!options.start) - this.$search.set({start: range}); - - var newRange = this.$search.find(this.session); - if (options.preventScroll) - return newRange; - if (newRange) { - this.revealRange(newRange, animate); - return newRange; - } - if (options.backwards) - range.start = range.end; - else - range.end = range.start; - this.selection.setRange(range); - }; - this.findNext = function(options, animate) { - this.find({skipCurrent: true, backwards: false}, options, animate); - }; - this.findPrevious = function(options, animate) { - this.find(options, {skipCurrent: true, backwards: true}, animate); - }; - - this.revealRange = function(range, animate) { - this.$blockScrolling += 1; - this.session.unfold(range); - this.selection.setSelectionRange(range); - this.$blockScrolling -= 1; - - var scrollTop = this.renderer.scrollTop; - this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5); - if (animate !== false) - this.renderer.animateScrolling(scrollTop); - }; - this.undo = function() { - this.$blockScrolling++; - this.session.getUndoManager().undo(); - this.$blockScrolling--; - this.renderer.scrollCursorIntoView(null, 0.5); - }; - this.redo = function() { - this.$blockScrolling++; - this.session.getUndoManager().redo(); - this.$blockScrolling--; - this.renderer.scrollCursorIntoView(null, 0.5); - }; - this.destroy = function() { - this.renderer.destroy(); - this._signal("destroy", this); - if (this.session) { - this.session.destroy(); - } - }; - this.setAutoScrollEditorIntoView = function(enable) { - if (!enable) - return; - var rect; - var self = this; - var shouldScroll = false; - if (!this.$scrollAnchor) - this.$scrollAnchor = document.createElement("div"); - var scrollAnchor = this.$scrollAnchor; - scrollAnchor.style.cssText = "position:absolute"; - this.container.insertBefore(scrollAnchor, this.container.firstChild); - var onChangeSelection = this.on("changeSelection", function() { - shouldScroll = true; - }); - var onBeforeRender = this.renderer.on("beforeRender", function() { - if (shouldScroll) - rect = self.renderer.container.getBoundingClientRect(); - }); - var onAfterRender = this.renderer.on("afterRender", function() { - if (shouldScroll && rect && (self.isFocused() - || self.searchBox && self.searchBox.isFocused()) - ) { - var renderer = self.renderer; - var pos = renderer.$cursorLayer.$pixelPos; - var config = renderer.layerConfig; - var top = pos.top - config.offset; - if (pos.top >= 0 && top + rect.top < 0) { - shouldScroll = true; - } else if (pos.top < config.height && - pos.top + rect.top + config.lineHeight > window.innerHeight) { - shouldScroll = false; - } else { - shouldScroll = null; - } - if (shouldScroll != null) { - scrollAnchor.style.top = top + "px"; - scrollAnchor.style.left = pos.left + "px"; - scrollAnchor.style.height = config.lineHeight + "px"; - scrollAnchor.scrollIntoView(shouldScroll); - } - shouldScroll = rect = null; - } - }); - this.setAutoScrollEditorIntoView = function(enable) { - if (enable) - return; - delete this.setAutoScrollEditorIntoView; - this.off("changeSelection", onChangeSelection); - this.renderer.off("afterRender", onAfterRender); - this.renderer.off("beforeRender", onBeforeRender); - }; - }; - - - this.$resetCursorStyle = function() { - var style = this.$cursorStyle || "ace"; - var cursorLayer = this.renderer.$cursorLayer; - if (!cursorLayer) - return; - cursorLayer.setSmoothBlinking(/smooth/.test(style)); - cursorLayer.isBlinking = !this.$readOnly && style != "wide"; - dom.setCssClass(cursorLayer.element, "ace_slim-cursors", /slim/.test(style)); - }; - - }).call(Editor.prototype); - - - - config.defineOptions(Editor.prototype, "editor", { - selectionStyle: { - set: function(style) { - this.onSelectionChange(); - this._signal("changeSelectionStyle", {data: style}); - }, - initialValue: "line" - }, - highlightActiveLine: { - set: function() {this.$updateHighlightActiveLine();}, - initialValue: true - }, - highlightSelectedWord: { - set: function(shouldHighlight) {this.$onSelectionChange();}, - initialValue: true - }, - readOnly: { - set: function(readOnly) { - this.$resetCursorStyle(); - }, - initialValue: false - }, - cursorStyle: { - set: function(val) { this.$resetCursorStyle(); }, - values: ["ace", "slim", "smooth", "wide"], - initialValue: "ace" - }, - mergeUndoDeltas: { - values: [false, true, "always"], - initialValue: true - }, - behavioursEnabled: {initialValue: true}, - wrapBehavioursEnabled: {initialValue: true}, - autoScrollEditorIntoView: { - set: function(val) {this.setAutoScrollEditorIntoView(val);} - }, - keyboardHandler: { - set: function(val) { this.setKeyboardHandler(val); }, - get: function() { return this.keybindingId; }, - handlesSet: true - }, - - hScrollBarAlwaysVisible: "renderer", - vScrollBarAlwaysVisible: "renderer", - highlightGutterLine: "renderer", - animatedScroll: "renderer", - showInvisibles: "renderer", - showPrintMargin: "renderer", - printMarginColumn: "renderer", - printMargin: "renderer", - fadeFoldWidgets: "renderer", - showFoldWidgets: "renderer", - showLineNumbers: "renderer", - showGutter: "renderer", - displayIndentGuides: "renderer", - fontSize: "renderer", - fontFamily: "renderer", - maxLines: "renderer", - minLines: "renderer", - scrollPastEnd: "renderer", - fixedWidthGutter: "renderer", - theme: "renderer", - - scrollSpeed: "$mouseHandler", - dragDelay: "$mouseHandler", - dragEnabled: "$mouseHandler", - focusTimout: "$mouseHandler", - tooltipFollowsMouse: "$mouseHandler", - - firstLineNumber: "session", - overwrite: "session", - newLineMode: "session", - useWorker: "session", - useSoftTabs: "session", - tabSize: "session", - wrap: "session", - indentedSoftWrap: "session", - foldStyle: "session", - mode: "session" - }); - - exports.Editor = Editor; - }); - - ace.define("ace/undomanager",["require","exports","module"], function(acequire, exports, module) { - "use strict"; - var UndoManager = function() { - this.reset(); - }; - - (function() { - this.execute = function(options) { - var deltaSets = options.args[0]; - this.$doc = options.args[1]; - if (options.merge && this.hasUndo()){ - this.dirtyCounter--; - deltaSets = this.$undoStack.pop().concat(deltaSets); - } - this.$undoStack.push(deltaSets); - this.$redoStack = []; - if (this.dirtyCounter < 0) { - this.dirtyCounter = NaN; - } - this.dirtyCounter++; - }; - this.undo = function(dontSelect) { - var deltaSets = this.$undoStack.pop(); - var undoSelectionRange = null; - if (deltaSets) { - undoSelectionRange = this.$doc.undoChanges(deltaSets, dontSelect); - this.$redoStack.push(deltaSets); - this.dirtyCounter--; - } - - return undoSelectionRange; - }; - this.redo = function(dontSelect) { - var deltaSets = this.$redoStack.pop(); - var redoSelectionRange = null; - if (deltaSets) { - redoSelectionRange = - this.$doc.redoChanges(this.$deserializeDeltas(deltaSets), dontSelect); - this.$undoStack.push(deltaSets); - this.dirtyCounter++; - } - return redoSelectionRange; - }; - this.reset = function() { - this.$undoStack = []; - this.$redoStack = []; - this.dirtyCounter = 0; - }; - this.hasUndo = function() { - return this.$undoStack.length > 0; - }; - this.hasRedo = function() { - return this.$redoStack.length > 0; - }; - this.markClean = function() { - this.dirtyCounter = 0; - }; - this.isClean = function() { - return this.dirtyCounter === 0; - }; - this.$serializeDeltas = function(deltaSets) { - return cloneDeltaSetsObj(deltaSets, $serializeDelta); - }; - this.$deserializeDeltas = function(deltaSets) { - return cloneDeltaSetsObj(deltaSets, $deserializeDelta); - }; - - function $serializeDelta(delta){ - return { - action: delta.action, - start: delta.start, - end: delta.end, - lines: delta.lines.length == 1 ? null : delta.lines, - text: delta.lines.length == 1 ? delta.lines[0] : null - }; - } - - function $deserializeDelta(delta) { - return { - action: delta.action, - start: delta.start, - end: delta.end, - lines: delta.lines || [delta.text] - }; - } - - function cloneDeltaSetsObj(deltaSets_old, fnGetModifiedDelta) { - var deltaSets_new = new Array(deltaSets_old.length); - for (var i = 0; i < deltaSets_old.length; i++) { - var deltaSet_old = deltaSets_old[i]; - var deltaSet_new = { group: deltaSet_old.group, deltas: new Array(deltaSet_old.length)}; - - for (var j = 0; j < deltaSet_old.deltas.length; j++) { - var delta_old = deltaSet_old.deltas[j]; - deltaSet_new.deltas[j] = fnGetModifiedDelta(delta_old); - } - - deltaSets_new[i] = deltaSet_new; - } - return deltaSets_new; - } - - }).call(UndoManager.prototype); - - exports.UndoManager = UndoManager; - }); - - ace.define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter"], function(acequire, exports, module) { - "use strict"; - - var dom = acequire("../lib/dom"); - var oop = acequire("../lib/oop"); - var lang = acequire("../lib/lang"); - var EventEmitter = acequire("../lib/event_emitter").EventEmitter; - - var Gutter = function(parentEl) { - this.element = dom.createElement("div"); - this.element.className = "ace_layer ace_gutter-layer"; - parentEl.appendChild(this.element); - this.setShowFoldWidgets(this.$showFoldWidgets); - - this.gutterWidth = 0; - - this.$annotations = []; - this.$updateAnnotations = this.$updateAnnotations.bind(this); - - this.$cells = []; - }; - - (function() { - - oop.implement(this, EventEmitter); - - this.setSession = function(session) { - if (this.session) - this.session.removeEventListener("change", this.$updateAnnotations); - this.session = session; - if (session) - session.on("change", this.$updateAnnotations); - }; - - this.addGutterDecoration = function(row, className){ - if (window.console) - console.warn && console.warn("deprecated use session.addGutterDecoration"); - this.session.addGutterDecoration(row, className); - }; - - this.removeGutterDecoration = function(row, className){ - if (window.console) - console.warn && console.warn("deprecated use session.removeGutterDecoration"); - this.session.removeGutterDecoration(row, className); - }; - - this.setAnnotations = function(annotations) { - this.$annotations = []; - for (var i = 0; i < annotations.length; i++) { - var annotation = annotations[i]; - var row = annotation.row; - var rowInfo = this.$annotations[row]; - if (!rowInfo) - rowInfo = this.$annotations[row] = {text: []}; - - var annoText = annotation.text; - annoText = annoText ? lang.escapeHTML(annoText) : annotation.html || ""; - - if (rowInfo.text.indexOf(annoText) === -1) - rowInfo.text.push(annoText); - - var type = annotation.type; - if (type == "error") - rowInfo.className = " ace_error"; - else if (type == "warning" && rowInfo.className != " ace_error") - rowInfo.className = " ace_warning"; - else if (type == "info" && (!rowInfo.className)) - rowInfo.className = " ace_info"; - } - }; - - this.$updateAnnotations = function (delta) { - if (!this.$annotations.length) - return; - var firstRow = delta.start.row; - var len = delta.end.row - firstRow; - if (len === 0) { - } else if (delta.action == 'remove') { - this.$annotations.splice(firstRow, len + 1, null); - } else { - var args = new Array(len + 1); - args.unshift(firstRow, 1); - this.$annotations.splice.apply(this.$annotations, args); - } - }; - - this.update = function(config) { - var session = this.session; - var firstRow = config.firstRow; - var lastRow = Math.min(config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar - session.getLength() - 1); - var fold = session.getNextFoldLine(firstRow); - var foldStart = fold ? fold.start.row : Infinity; - var foldWidgets = this.$showFoldWidgets && session.foldWidgets; - var breakpoints = session.$breakpoints; - var decorations = session.$decorations; - var firstLineNumber = session.$firstLineNumber; - var lastLineNumber = 0; - - var gutterRenderer = session.gutterRenderer || this.$renderer; - - var cell = null; - var index = -1; - var row = firstRow; - while (true) { - if (row > foldStart) { - row = fold.end.row + 1; - fold = session.getNextFoldLine(row, fold); - foldStart = fold ? fold.start.row : Infinity; - } - if (row > lastRow) { - while (this.$cells.length > index + 1) { - cell = this.$cells.pop(); - this.element.removeChild(cell.element); - } - break; - } - - cell = this.$cells[++index]; - if (!cell) { - cell = {element: null, textNode: null, foldWidget: null}; - cell.element = dom.createElement("div"); - cell.textNode = document.createTextNode(''); - cell.element.appendChild(cell.textNode); - this.element.appendChild(cell.element); - this.$cells[index] = cell; - } - - var className = "ace_gutter-cell "; - if (breakpoints[row]) - className += breakpoints[row]; - if (decorations[row]) - className += decorations[row]; - if (this.$annotations[row]) - className += this.$annotations[row].className; - if (cell.element.className != className) - cell.element.className = className; - - var height = session.getRowLength(row) * config.lineHeight + "px"; - if (height != cell.element.style.height) - cell.element.style.height = height; - - if (foldWidgets) { - var c = foldWidgets[row]; - if (c == null) - c = foldWidgets[row] = session.getFoldWidget(row); - } - - if (c) { - if (!cell.foldWidget) { - cell.foldWidget = dom.createElement("span"); - cell.element.appendChild(cell.foldWidget); - } - var className = "ace_fold-widget ace_" + c; - if (c == "start" && row == foldStart && row < fold.end.row) - className += " ace_closed"; - else - className += " ace_open"; - if (cell.foldWidget.className != className) - cell.foldWidget.className = className; - - var height = config.lineHeight + "px"; - if (cell.foldWidget.style.height != height) - cell.foldWidget.style.height = height; - } else { - if (cell.foldWidget) { - cell.element.removeChild(cell.foldWidget); - cell.foldWidget = null; - } - } - - var text = lastLineNumber = gutterRenderer - ? gutterRenderer.getText(session, row) - : row + firstLineNumber; - if (text !== cell.textNode.data) - cell.textNode.data = text; - - row++; - } - - this.element.style.height = config.minHeight + "px"; - - if (this.$fixedWidth || session.$useWrapMode) - lastLineNumber = session.getLength() + firstLineNumber; - - var gutterWidth = gutterRenderer - ? gutterRenderer.getWidth(session, lastLineNumber, config) - : lastLineNumber.toString().length * config.characterWidth; - - var padding = this.$padding || this.$computePadding(); - gutterWidth += padding.left + padding.right; - if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) { - this.gutterWidth = gutterWidth; - this.element.style.width = Math.ceil(this.gutterWidth) + "px"; - this._emit("changeGutterWidth", gutterWidth); - } - }; - - this.$fixedWidth = false; - - this.$showLineNumbers = true; - this.$renderer = ""; - this.setShowLineNumbers = function(show) { - this.$renderer = !show && { - getWidth: function() {return "";}, - getText: function() {return "";} - }; - }; - - this.getShowLineNumbers = function() { - return this.$showLineNumbers; - }; - - this.$showFoldWidgets = true; - this.setShowFoldWidgets = function(show) { - if (show) - dom.addCssClass(this.element, "ace_folding-enabled"); - else - dom.removeCssClass(this.element, "ace_folding-enabled"); - - this.$showFoldWidgets = show; - this.$padding = null; - }; - - this.getShowFoldWidgets = function() { - return this.$showFoldWidgets; - }; - - this.$computePadding = function() { - if (!this.element.firstChild) - return {left: 0, right: 0}; - var style = dom.computedStyle(this.element.firstChild); - this.$padding = {}; - this.$padding.left = parseInt(style.paddingLeft) + 1 || 0; - this.$padding.right = parseInt(style.paddingRight) || 0; - return this.$padding; - }; - - this.getRegion = function(point) { - var padding = this.$padding || this.$computePadding(); - var rect = this.element.getBoundingClientRect(); - if (point.x < padding.left + rect.left) - return "markers"; - if (this.$showFoldWidgets && point.x > rect.right - padding.right) - return "foldWidgets"; - }; - - }).call(Gutter.prototype); - - exports.Gutter = Gutter; - - }); - - ace.define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"], function(acequire, exports, module) { - "use strict"; - - var Range = acequire("../range").Range; - var dom = acequire("../lib/dom"); - - var Marker = function(parentEl) { - this.element = dom.createElement("div"); - this.element.className = "ace_layer ace_marker-layer"; - parentEl.appendChild(this.element); - }; - - (function() { - - this.$padding = 0; - - this.setPadding = function(padding) { - this.$padding = padding; - }; - this.setSession = function(session) { - this.session = session; - }; - - this.setMarkers = function(markers) { - this.markers = markers; - }; - - this.update = function(config) { - if (!config) return; - - this.config = config; - - - var html = []; - for (var key in this.markers) { - var marker = this.markers[key]; - - if (!marker.range) { - marker.update(html, this, this.session, config); - continue; - } - - var range = marker.range.clipRows(config.firstRow, config.lastRow); - if (range.isEmpty()) continue; - - range = range.toScreenRange(this.session); - if (marker.renderer) { - var top = this.$getTop(range.start.row, config); - var left = this.$padding + (this.session.$bidiHandler.isBidiRow(range.start.row) - ? this.session.$bidiHandler.getPosLeft(range.start.column) - : range.start.column * config.characterWidth); - marker.renderer(html, range, left, top, config); - } else if (marker.type == "fullLine") { - this.drawFullLineMarker(html, range, marker.clazz, config); - } else if (marker.type == "screenLine") { - this.drawScreenLineMarker(html, range, marker.clazz, config); - } else if (range.isMultiLine()) { - if (marker.type == "text") - this.drawTextMarker(html, range, marker.clazz, config); - else - this.drawMultiLineMarker(html, range, marker.clazz, config); - } else { - if (this.session.$bidiHandler.isBidiRow(range.start.row)) { - this.drawBidiSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config); - } else { - this.drawSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config); - } - } - } - this.element.innerHTML = html.join(""); - }; - - this.$getTop = function(row, layerConfig) { - return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight; - }; - - function getBorderClass(tl, tr, br, bl) { - return (tl ? 1 : 0) | (tr ? 2 : 0) | (br ? 4 : 0) | (bl ? 8 : 0); - } - this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig, extraStyle) { - var session = this.session; - var start = range.start.row; - var end = range.end.row; - var row = start; - var prev = 0; - var curr = 0; - var next = session.getScreenLastRowColumn(row); - var clazzModified = null; - var lineRange = new Range(row, range.start.column, row, curr); - for (; row <= end; row++) { - lineRange.start.row = lineRange.end.row = row; - lineRange.start.column = row == start ? range.start.column : session.getRowWrapIndent(row); - lineRange.end.column = next; - prev = curr; - curr = next; - next = row + 1 < end ? session.getScreenLastRowColumn(row + 1) : row == end ? 0 : range.end.column; - clazzModified = clazz + (row == start ? " ace_start" : "") + " ace_br" - + getBorderClass(row == start || row == start + 1 && range.start.column, prev < curr, curr > next, row == end); - - if (this.session.$bidiHandler.isBidiRow(row)) { - this.drawBidiSingleLineMarker(stringBuilder, lineRange, clazzModified, - layerConfig, row == end ? 0 : 1, extraStyle); - } else { - this.drawSingleLineMarker(stringBuilder, lineRange, clazzModified, - layerConfig, row == end ? 0 : 1, extraStyle); - } - } - }; - this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { - var padding = this.$padding; - var height, top, left; - extraStyle = extraStyle || ""; - if (this.session.$bidiHandler.isBidiRow(range.start.row)) { - var range1 = range.clone(); - range1.end.row = range1.start.row; - range1.end.column = this.session.getLine(range1.start.row).length; - this.drawBidiSingleLineMarker(stringBuilder, range1, clazz + " ace_br1 ace_start", config, null, extraStyle); - } else { - height = config.lineHeight; - top = this.$getTop(range.start.row, config); - left = padding + range.start.column * config.characterWidth; - stringBuilder.push( - "
" - ); - } - if (this.session.$bidiHandler.isBidiRow(range.end.row)) { - var range1 = range.clone(); - range1.start.row = range1.end.row; - range1.start.column = 0; - this.drawBidiSingleLineMarker(stringBuilder, range1, clazz + " ace_br12", config, null, extraStyle); - } else { - var width = range.end.column * config.characterWidth; - height = config.lineHeight; - top = this.$getTop(range.end.row, config); - stringBuilder.push( - "
" - ); - } - height = (range.end.row - range.start.row - 1) * config.lineHeight; - if (height <= 0) - return; - top = this.$getTop(range.start.row + 1, config); - - var radiusClass = (range.start.column ? 1 : 0) | (range.end.column ? 0 : 8); - - stringBuilder.push( - "
" - ); - }; - this.drawSingleLineMarker = function(stringBuilder, range, clazz, config, extraLength, extraStyle) { - var height = config.lineHeight; - var width = (range.end.column + (extraLength || 0) - range.start.column) * config.characterWidth; - - var top = this.$getTop(range.start.row, config); - var left = this.$padding + range.start.column * config.characterWidth; - - stringBuilder.push( - "
" - ); - }; - this.drawBidiSingleLineMarker = function(stringBuilder, range, clazz, config, extraLength, extraStyle) { - var height = config.lineHeight, top = this.$getTop(range.start.row, config), padding = this.$padding; - var selections = this.session.$bidiHandler.getSelections(range.start.column, range.end.column); - - selections.forEach(function(selection) { - stringBuilder.push( - "
" - ); - }); - }; - - this.drawFullLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { - var top = this.$getTop(range.start.row, config); - var height = config.lineHeight; - if (range.start.row != range.end.row) - height += this.$getTop(range.end.row, config) - top; - - stringBuilder.push( - "
" - ); - }; - - this.drawScreenLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { - var top = this.$getTop(range.start.row, config); - var height = config.lineHeight; - - stringBuilder.push( - "
" - ); - }; - - }).call(Marker.prototype); - - exports.Marker = Marker; - - }); - - ace.define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("../lib/oop"); - var dom = acequire("../lib/dom"); - var lang = acequire("../lib/lang"); - var useragent = acequire("../lib/useragent"); - var EventEmitter = acequire("../lib/event_emitter").EventEmitter; - - var Text = function(parentEl) { - this.element = dom.createElement("div"); - this.element.className = "ace_layer ace_text-layer"; - parentEl.appendChild(this.element); - this.$updateEolChar = this.$updateEolChar.bind(this); - }; - - (function() { - - oop.implement(this, EventEmitter); - - this.EOF_CHAR = "\xB6"; - this.EOL_CHAR_LF = "\xAC"; - this.EOL_CHAR_CRLF = "\xa4"; - this.EOL_CHAR = this.EOL_CHAR_LF; - this.TAB_CHAR = "\u2014"; //"\u21E5"; - this.SPACE_CHAR = "\xB7"; - this.$padding = 0; - - this.$updateEolChar = function() { - var EOL_CHAR = this.session.doc.getNewLineCharacter() == "\n" - ? this.EOL_CHAR_LF - : this.EOL_CHAR_CRLF; - if (this.EOL_CHAR != EOL_CHAR) { - this.EOL_CHAR = EOL_CHAR; - return true; - } - }; - - this.setPadding = function(padding) { - this.$padding = padding; - this.element.style.padding = "0 " + padding + "px"; - }; - - this.getLineHeight = function() { - return this.$fontMetrics.$characterSize.height || 0; - }; - - this.getCharacterWidth = function() { - return this.$fontMetrics.$characterSize.width || 0; - }; - - this.$setFontMetrics = function(measure) { - this.$fontMetrics = measure; - this.$fontMetrics.on("changeCharacterSize", function(e) { - this._signal("changeCharacterSize", e); - }.bind(this)); - this.$pollSizeChanges(); - }; - - this.checkForSizeChanges = function() { - this.$fontMetrics.checkForSizeChanges(); - }; - this.$pollSizeChanges = function() { - return this.$pollSizeChangesTimer = this.$fontMetrics.$pollSizeChanges(); - }; - this.setSession = function(session) { - this.session = session; - if (session) - this.$computeTabString(); - }; - - this.showInvisibles = false; - this.setShowInvisibles = function(showInvisibles) { - if (this.showInvisibles == showInvisibles) - return false; - - this.showInvisibles = showInvisibles; - this.$computeTabString(); - return true; - }; - - this.displayIndentGuides = true; - this.setDisplayIndentGuides = function(display) { - if (this.displayIndentGuides == display) - return false; - - this.displayIndentGuides = display; - this.$computeTabString(); - return true; - }; - - this.$tabStrings = []; - this.onChangeTabSize = - this.$computeTabString = function() { - var tabSize = this.session.getTabSize(); - this.tabSize = tabSize; - var tabStr = this.$tabStrings = [0]; - for (var i = 1; i < tabSize + 1; i++) { - if (this.showInvisibles) { - tabStr.push("" - + lang.stringRepeat(this.TAB_CHAR, i) - + ""); - } else { - tabStr.push(lang.stringRepeat(" ", i)); - } - } - if (this.displayIndentGuides) { - this.$indentGuideRe = /\s\S| \t|\t |\s$/; - var className = "ace_indent-guide"; - var spaceClass = ""; - var tabClass = ""; - if (this.showInvisibles) { - className += " ace_invisible"; - spaceClass = " ace_invisible_space"; - tabClass = " ace_invisible_tab"; - var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize); - var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize); - } else{ - var spaceContent = lang.stringRepeat(" ", this.tabSize); - var tabContent = spaceContent; - } - - this.$tabStrings[" "] = "" + spaceContent + ""; - this.$tabStrings["\t"] = "" + tabContent + ""; - } - }; - - this.updateLines = function(config, firstRow, lastRow) { - if (this.config.lastRow != config.lastRow || - this.config.firstRow != config.firstRow) { - this.scrollLines(config); - } - this.config = config; - - var first = Math.max(firstRow, config.firstRow); - var last = Math.min(lastRow, config.lastRow); - - var lineElements = this.element.childNodes; - var lineElementsIdx = 0; - - for (var row = config.firstRow; row < first; row++) { - var foldLine = this.session.getFoldLine(row); - if (foldLine) { - if (foldLine.containsRow(first)) { - first = foldLine.start.row; - break; - } else { - row = foldLine.end.row; - } - } - lineElementsIdx ++; - } - - var row = first; - var foldLine = this.session.getNextFoldLine(row); - var foldStart = foldLine ? foldLine.start.row : Infinity; - - while (true) { - if (row > foldStart) { - row = foldLine.end.row+1; - foldLine = this.session.getNextFoldLine(row, foldLine); - foldStart = foldLine ? foldLine.start.row :Infinity; - } - if (row > last) - break; - - var lineElement = lineElements[lineElementsIdx++]; - if (lineElement) { - var html = []; - this.$renderLine( - html, row, !this.$useLineGroups(), row == foldStart ? foldLine : false - ); - lineElement.style.height = config.lineHeight * this.session.getRowLength(row) + "px"; - lineElement.innerHTML = html.join(""); - } - row++; - } - }; - - this.scrollLines = function(config) { - var oldConfig = this.config; - this.config = config; - - if (!oldConfig || oldConfig.lastRow < config.firstRow) - return this.update(config); - - if (config.lastRow < oldConfig.firstRow) - return this.update(config); - - var el = this.element; - if (oldConfig.firstRow < config.firstRow) - for (var row=this.session.getFoldedRowCount(oldConfig.firstRow, config.firstRow - 1); row>0; row--) - el.removeChild(el.firstChild); - - if (oldConfig.lastRow > config.lastRow) - for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--) - el.removeChild(el.lastChild); - - if (config.firstRow < oldConfig.firstRow) { - var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1); - if (el.firstChild) - el.insertBefore(fragment, el.firstChild); - else - el.appendChild(fragment); - } - - if (config.lastRow > oldConfig.lastRow) { - var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow); - el.appendChild(fragment); - } - }; - - this.$renderLinesFragment = function(config, firstRow, lastRow) { - var fragment = this.element.ownerDocument.createDocumentFragment(); - var row = firstRow; - var foldLine = this.session.getNextFoldLine(row); - var foldStart = foldLine ? foldLine.start.row : Infinity; - - while (true) { - if (row > foldStart) { - row = foldLine.end.row+1; - foldLine = this.session.getNextFoldLine(row, foldLine); - foldStart = foldLine ? foldLine.start.row : Infinity; - } - if (row > lastRow) - break; - - var container = dom.createElement("div"); - - var html = []; - this.$renderLine(html, row, false, row == foldStart ? foldLine : false); - container.innerHTML = html.join(""); - if (this.$useLineGroups()) { - container.className = 'ace_line_group'; - fragment.appendChild(container); - container.style.height = config.lineHeight * this.session.getRowLength(row) + "px"; - - } else { - while(container.firstChild) - fragment.appendChild(container.firstChild); - } - - row++; - } - return fragment; - }; - - this.update = function(config) { - this.config = config; - - var html = []; - var firstRow = config.firstRow, lastRow = config.lastRow; - - var row = firstRow; - var foldLine = this.session.getNextFoldLine(row); - var foldStart = foldLine ? foldLine.start.row : Infinity; - - while (true) { - if (row > foldStart) { - row = foldLine.end.row+1; - foldLine = this.session.getNextFoldLine(row, foldLine); - foldStart = foldLine ? foldLine.start.row :Infinity; - } - if (row > lastRow) - break; - - if (this.$useLineGroups()) - html.push("
"); - - this.$renderLine(html, row, false, row == foldStart ? foldLine : false); - - if (this.$useLineGroups()) - html.push("
"); // end the line group - - row++; - } - this.element.innerHTML = html.join(""); - }; - - this.$textToken = { - "text": true, - "rparen": true, - "lparen": true - }; - - this.$renderToken = function(stringBuilder, screenColumn, token, value) { - var self = this; - var replaceReg = /\t|&|<|>|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF\uFFF9-\uFFFC])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g; - var replaceFunc = function(c, a, b, tabIdx, idx4) { - if (a) { - return self.showInvisibles - ? "" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "" - : c; - } else if (c == "&") { - return "&"; - } else if (c == "<") { - return "<"; - } else if (c == ">") { - return ">"; - } else if (c == "\t") { - var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx); - screenColumn += tabSize - 1; - return self.$tabStrings[tabSize]; - } else if (c == "\u3000") { - var classToUse = self.showInvisibles ? "ace_cjk ace_invisible ace_invisible_space" : "ace_cjk"; - var space = self.showInvisibles ? self.SPACE_CHAR : ""; - screenColumn += 1; - return "" + space + ""; - } else if (b) { - return "" + self.SPACE_CHAR + ""; - } else { - screenColumn += 1; - return "" + c + ""; - } - }; - - var output = value.replace(replaceReg, replaceFunc); - - if (!this.$textToken[token.type]) { - var classes = "ace_" + token.type.replace(/\./g, " ace_"); - var style = ""; - if (token.type == "fold") - style = " style='width:" + (token.value.length * this.config.characterWidth) + "px;' "; - stringBuilder.push("", output, ""); - } - else { - stringBuilder.push(output); - } - return screenColumn + value.length; - }; - - this.renderIndentGuide = function(stringBuilder, value, max) { - var cols = value.search(this.$indentGuideRe); - if (cols <= 0 || cols >= max) - return value; - if (value[0] == " ") { - cols -= cols % this.tabSize; - stringBuilder.push(lang.stringRepeat(this.$tabStrings[" "], cols/this.tabSize)); - return value.substr(cols); - } else if (value[0] == "\t") { - stringBuilder.push(lang.stringRepeat(this.$tabStrings["\t"], cols)); - return value.substr(cols); - } - return value; - }; - - this.$renderWrappedLine = function(stringBuilder, tokens, splits, onlyContents) { - var chars = 0; - var split = 0; - var splitChars = splits[0]; - var screenColumn = 0; - - for (var i = 0; i < tokens.length; i++) { - var token = tokens[i]; - var value = token.value; - if (i == 0 && this.displayIndentGuides) { - chars = value.length; - value = this.renderIndentGuide(stringBuilder, value, splitChars); - if (!value) - continue; - chars -= value.length; - } - - if (chars + value.length < splitChars) { - screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); - chars += value.length; - } else { - while (chars + value.length >= splitChars) { - screenColumn = this.$renderToken( - stringBuilder, screenColumn, - token, value.substring(0, splitChars - chars) - ); - value = value.substring(splitChars - chars); - chars = splitChars; - - if (!onlyContents) { - stringBuilder.push("", - "
" - ); - } - - stringBuilder.push(lang.stringRepeat("\xa0", splits.indent)); - - split ++; - screenColumn = 0; - splitChars = splits[split] || Number.MAX_VALUE; - } - if (value.length != 0) { - chars += value.length; - screenColumn = this.$renderToken( - stringBuilder, screenColumn, token, value - ); - } - } - } - }; - - this.$renderSimpleLine = function(stringBuilder, tokens) { - var screenColumn = 0; - var token = tokens[0]; - var value = token.value; - if (this.displayIndentGuides) - value = this.renderIndentGuide(stringBuilder, value); - if (value) - screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); - for (var i = 1; i < tokens.length; i++) { - token = tokens[i]; - value = token.value; - screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); - } - }; - this.$renderLine = function(stringBuilder, row, onlyContents, foldLine) { - if (!foldLine && foldLine != false) - foldLine = this.session.getFoldLine(row); - - if (foldLine) - var tokens = this.$getFoldLineTokens(row, foldLine); - else - var tokens = this.session.getTokens(row); - - - if (!onlyContents) { - stringBuilder.push( - "
" - ); - } - - if (tokens.length) { - var splits = this.session.getRowSplitData(row); - if (splits && splits.length) - this.$renderWrappedLine(stringBuilder, tokens, splits, onlyContents); - else - this.$renderSimpleLine(stringBuilder, tokens); - } - - if (this.showInvisibles) { - if (foldLine) - row = foldLine.end.row; - - stringBuilder.push( - "", - row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR, - "" - ); - } - if (!onlyContents) - stringBuilder.push("
"); - }; - - this.$getFoldLineTokens = function(row, foldLine) { - var session = this.session; - var renderTokens = []; - - function addTokens(tokens, from, to) { - var idx = 0, col = 0; - while ((col + tokens[idx].value.length) < from) { - col += tokens[idx].value.length; - idx++; - - if (idx == tokens.length) - return; - } - if (col != from) { - var value = tokens[idx].value.substring(from - col); - if (value.length > (to - from)) - value = value.substring(0, to - from); - - renderTokens.push({ - type: tokens[idx].type, - value: value - }); - - col = from + value.length; - idx += 1; - } - - while (col < to && idx < tokens.length) { - var value = tokens[idx].value; - if (value.length + col > to) { - renderTokens.push({ - type: tokens[idx].type, - value: value.substring(0, to - col) - }); - } else - renderTokens.push(tokens[idx]); - col += value.length; - idx += 1; - } - } - - var tokens = session.getTokens(row); - foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) { - if (placeholder != null) { - renderTokens.push({ - type: "fold", - value: placeholder - }); - } else { - if (isNewRow) - tokens = session.getTokens(row); - - if (tokens.length) - addTokens(tokens, lastColumn, column); - } - }, foldLine.end.row, this.session.getLine(foldLine.end.row).length); - - return renderTokens; - }; - - this.$useLineGroups = function() { - return this.session.getUseWrapMode(); - }; - - this.destroy = function() { - clearInterval(this.$pollSizeChangesTimer); - if (this.$measureNode) - this.$measureNode.parentNode.removeChild(this.$measureNode); - delete this.$measureNode; - }; - - }).call(Text.prototype); - - exports.Text = Text; - - }); - - ace.define("ace/layer/cursor",["require","exports","module","ace/lib/dom"], function(acequire, exports, module) { - "use strict"; - - var dom = acequire("../lib/dom"); - var isIE8; - - var Cursor = function(parentEl) { - this.element = dom.createElement("div"); - this.element.className = "ace_layer ace_cursor-layer"; - parentEl.appendChild(this.element); - - if (isIE8 === undefined) - isIE8 = !("opacity" in this.element.style); - - this.isVisible = false; - this.isBlinking = true; - this.blinkInterval = 1000; - this.smoothBlinking = false; - - this.cursors = []; - this.cursor = this.addCursor(); - dom.addCssClass(this.element, "ace_hidden-cursors"); - this.$updateCursors = (isIE8 - ? this.$updateVisibility - : this.$updateOpacity).bind(this); - }; - - (function() { - - this.$updateVisibility = function(val) { - var cursors = this.cursors; - for (var i = cursors.length; i--; ) - cursors[i].style.visibility = val ? "" : "hidden"; - }; - this.$updateOpacity = function(val) { - var cursors = this.cursors; - for (var i = cursors.length; i--; ) - cursors[i].style.opacity = val ? "" : "0"; - }; - - - this.$padding = 0; - this.setPadding = function(padding) { - this.$padding = padding; - }; - - this.setSession = function(session) { - this.session = session; - }; - - this.setBlinking = function(blinking) { - if (blinking != this.isBlinking){ - this.isBlinking = blinking; - this.restartTimer(); - } - }; - - this.setBlinkInterval = function(blinkInterval) { - if (blinkInterval != this.blinkInterval){ - this.blinkInterval = blinkInterval; - this.restartTimer(); - } - }; - - this.setSmoothBlinking = function(smoothBlinking) { - if (smoothBlinking != this.smoothBlinking && !isIE8) { - this.smoothBlinking = smoothBlinking; - dom.setCssClass(this.element, "ace_smooth-blinking", smoothBlinking); - this.$updateCursors(true); - this.$updateCursors = (this.$updateOpacity).bind(this); - this.restartTimer(); - } - }; - - this.addCursor = function() { - var el = dom.createElement("div"); - el.className = "ace_cursor"; - this.element.appendChild(el); - this.cursors.push(el); - return el; - }; - - this.removeCursor = function() { - if (this.cursors.length > 1) { - var el = this.cursors.pop(); - el.parentNode.removeChild(el); - return el; - } - }; - - this.hideCursor = function() { - this.isVisible = false; - dom.addCssClass(this.element, "ace_hidden-cursors"); - this.restartTimer(); - }; - - this.showCursor = function() { - this.isVisible = true; - dom.removeCssClass(this.element, "ace_hidden-cursors"); - this.restartTimer(); - }; - - this.restartTimer = function() { - var update = this.$updateCursors; - clearInterval(this.intervalId); - clearTimeout(this.timeoutId); - if (this.smoothBlinking) { - dom.removeCssClass(this.element, "ace_smooth-blinking"); - } - - update(true); - - if (!this.isBlinking || !this.blinkInterval || !this.isVisible) - return; - - if (this.smoothBlinking) { - setTimeout(function(){ - dom.addCssClass(this.element, "ace_smooth-blinking"); - }.bind(this)); - } - - var blink = function(){ - this.timeoutId = setTimeout(function() { - update(false); - }, 0.6 * this.blinkInterval); - }.bind(this); - - this.intervalId = setInterval(function() { - update(true); - blink(); - }, this.blinkInterval); - - blink(); - }; - - this.getPixelPosition = function(position, onScreen) { - if (!this.config || !this.session) - return {left : 0, top : 0}; - - if (!position) - position = this.session.selection.getCursor(); - var pos = this.session.documentToScreenPosition(position); - var cursorLeft = this.$padding + (this.session.$bidiHandler.isBidiRow(pos.row, position.row) - ? this.session.$bidiHandler.getPosLeft(pos.column) - : pos.column * this.config.characterWidth); - - var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) * - this.config.lineHeight; - - return {left : cursorLeft, top : cursorTop}; - }; - - this.update = function(config) { - this.config = config; - - var selections = this.session.$selectionMarkers; - var i = 0, cursorIndex = 0; - - if (selections === undefined || selections.length === 0){ - selections = [{cursor: null}]; - } - - for (var i = 0, n = selections.length; i < n; i++) { - var pixelPos = this.getPixelPosition(selections[i].cursor, true); - if ((pixelPos.top > config.height + config.offset || - pixelPos.top < 0) && i > 1) { - continue; - } - - var style = (this.cursors[cursorIndex++] || this.addCursor()).style; - - if (!this.drawCursor) { - style.left = pixelPos.left + "px"; - style.top = pixelPos.top + "px"; - style.width = config.characterWidth + "px"; - style.height = config.lineHeight + "px"; - } else { - this.drawCursor(style, pixelPos, config, selections[i], this.session); - } - } - while (this.cursors.length > cursorIndex) - this.removeCursor(); - - var overwrite = this.session.getOverwrite(); - this.$setOverwrite(overwrite); - this.$pixelPos = pixelPos; - this.restartTimer(); - }; - - this.drawCursor = null; - - this.$setOverwrite = function(overwrite) { - if (overwrite != this.overwrite) { - this.overwrite = overwrite; - if (overwrite) - dom.addCssClass(this.element, "ace_overwrite-cursors"); - else - dom.removeCssClass(this.element, "ace_overwrite-cursors"); - } - }; - - this.destroy = function() { - clearInterval(this.intervalId); - clearTimeout(this.timeoutId); - }; - - }).call(Cursor.prototype); - - exports.Cursor = Cursor; - - }); - - ace.define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("./lib/oop"); - var dom = acequire("./lib/dom"); - var event = acequire("./lib/event"); - var EventEmitter = acequire("./lib/event_emitter").EventEmitter; - var MAX_SCROLL_H = 0x8000; - var ScrollBar = function(parent) { - this.element = dom.createElement("div"); - this.element.className = "ace_scrollbar ace_scrollbar" + this.classSuffix; - - this.inner = dom.createElement("div"); - this.inner.className = "ace_scrollbar-inner"; - this.element.appendChild(this.inner); - - parent.appendChild(this.element); - - this.setVisible(false); - this.skipEvent = false; - - event.addListener(this.element, "scroll", this.onScroll.bind(this)); - event.addListener(this.element, "mousedown", event.preventDefault); - }; - - (function() { - oop.implement(this, EventEmitter); - - this.setVisible = function(isVisible) { - this.element.style.display = isVisible ? "" : "none"; - this.isVisible = isVisible; - this.coeff = 1; - }; - }).call(ScrollBar.prototype); - var VScrollBar = function(parent, renderer) { - ScrollBar.call(this, parent); - this.scrollTop = 0; - this.scrollHeight = 0; - renderer.$scrollbarWidth = - this.width = dom.scrollbarWidth(parent.ownerDocument); - this.inner.style.width = - this.element.style.width = (this.width || 15) + 5 + "px"; - this.$minWidth = 0; - }; - - oop.inherits(VScrollBar, ScrollBar); - - (function() { - - this.classSuffix = '-v'; - this.onScroll = function() { - if (!this.skipEvent) { - this.scrollTop = this.element.scrollTop; - if (this.coeff != 1) { - var h = this.element.clientHeight / this.scrollHeight; - this.scrollTop = this.scrollTop * (1 - h) / (this.coeff - h); - } - this._emit("scroll", {data: this.scrollTop}); - } - this.skipEvent = false; - }; - this.getWidth = function() { - return Math.max(this.isVisible ? this.width : 0, this.$minWidth || 0); - }; - this.setHeight = function(height) { - this.element.style.height = height + "px"; - }; - this.setInnerHeight = - this.setScrollHeight = function(height) { - this.scrollHeight = height; - if (height > MAX_SCROLL_H) { - this.coeff = MAX_SCROLL_H / height; - height = MAX_SCROLL_H; - } else if (this.coeff != 1) { - this.coeff = 1; - } - this.inner.style.height = height + "px"; - }; - this.setScrollTop = function(scrollTop) { - if (this.scrollTop != scrollTop) { - this.skipEvent = true; - this.scrollTop = scrollTop; - this.element.scrollTop = scrollTop * this.coeff; - } - }; - - }).call(VScrollBar.prototype); - var HScrollBar = function(parent, renderer) { - ScrollBar.call(this, parent); - this.scrollLeft = 0; - this.height = renderer.$scrollbarWidth; - this.inner.style.height = - this.element.style.height = (this.height || 15) + 5 + "px"; - }; - - oop.inherits(HScrollBar, ScrollBar); - - (function() { - - this.classSuffix = '-h'; - this.onScroll = function() { - if (!this.skipEvent) { - this.scrollLeft = this.element.scrollLeft; - this._emit("scroll", {data: this.scrollLeft}); - } - this.skipEvent = false; - }; - this.getHeight = function() { - return this.isVisible ? this.height : 0; - }; - this.setWidth = function(width) { - this.element.style.width = width + "px"; - }; - this.setInnerWidth = function(width) { - this.inner.style.width = width + "px"; - }; - this.setScrollWidth = function(width) { - this.inner.style.width = width + "px"; - }; - this.setScrollLeft = function(scrollLeft) { - if (this.scrollLeft != scrollLeft) { - this.skipEvent = true; - this.scrollLeft = this.element.scrollLeft = scrollLeft; - } - }; - - }).call(HScrollBar.prototype); - - - exports.ScrollBar = VScrollBar; // backward compatibility - exports.ScrollBarV = VScrollBar; // backward compatibility - exports.ScrollBarH = HScrollBar; // backward compatibility - - exports.VScrollBar = VScrollBar; - exports.HScrollBar = HScrollBar; - }); - - ace.define("ace/renderloop",["require","exports","module","ace/lib/event"], function(acequire, exports, module) { - "use strict"; - - var event = acequire("./lib/event"); - - - var RenderLoop = function(onRender, win) { - this.onRender = onRender; - this.pending = false; - this.changes = 0; - this.window = win || window; - }; - - (function() { - - - this.schedule = function(change) { - this.changes = this.changes | change; - if (!this.pending && this.changes) { - this.pending = true; - var _self = this; - event.nextFrame(function() { - _self.pending = false; - var changes; - while (changes = _self.changes) { - _self.changes = 0; - _self.onRender(changes); - } - }, this.window); - } - }; - - }).call(RenderLoop.prototype); - - exports.RenderLoop = RenderLoop; - }); - - ace.define("ace/layer/font_metrics",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"], function(acequire, exports, module) { - - var oop = acequire("../lib/oop"); - var dom = acequire("../lib/dom"); - var lang = acequire("../lib/lang"); - var useragent = acequire("../lib/useragent"); - var EventEmitter = acequire("../lib/event_emitter").EventEmitter; - - var CHAR_COUNT = 0; - - var FontMetrics = exports.FontMetrics = function(parentEl) { - this.el = dom.createElement("div"); - this.$setMeasureNodeStyles(this.el.style, true); - - this.$main = dom.createElement("div"); - this.$setMeasureNodeStyles(this.$main.style); - - this.$measureNode = dom.createElement("div"); - this.$setMeasureNodeStyles(this.$measureNode.style); - - - this.el.appendChild(this.$main); - this.el.appendChild(this.$measureNode); - parentEl.appendChild(this.el); - - if (!CHAR_COUNT) - this.$testFractionalRect(); - this.$measureNode.innerHTML = lang.stringRepeat("X", CHAR_COUNT); - - this.$characterSize = {width: 0, height: 0}; - this.checkForSizeChanges(); - }; - - (function() { - - oop.implement(this, EventEmitter); - - this.$characterSize = {width: 0, height: 0}; - - this.$testFractionalRect = function() { - var el = dom.createElement("div"); - this.$setMeasureNodeStyles(el.style); - el.style.width = "0.2px"; - document.documentElement.appendChild(el); - var w = el.getBoundingClientRect().width; - if (w > 0 && w < 1) - CHAR_COUNT = 50; - else - CHAR_COUNT = 100; - el.parentNode.removeChild(el); - }; - - this.$setMeasureNodeStyles = function(style, isRoot) { - style.width = style.height = "auto"; - style.left = style.top = "0px"; - style.visibility = "hidden"; - style.position = "absolute"; - style.whiteSpace = "pre"; - - if (useragent.isIE < 8) { - style["font-family"] = "inherit"; - } else { - style.font = "inherit"; - } - style.overflow = isRoot ? "hidden" : "visible"; - }; - - this.checkForSizeChanges = function() { - var size = this.$measureSizes(); - if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) { - this.$measureNode.style.fontWeight = "bold"; - var boldSize = this.$measureSizes(); - this.$measureNode.style.fontWeight = ""; - this.$characterSize = size; - this.charSizes = Object.create(null); - this.allowBoldFonts = boldSize && boldSize.width === size.width && boldSize.height === size.height; - this._emit("changeCharacterSize", {data: size}); - } - }; - - this.$pollSizeChanges = function() { - if (this.$pollSizeChangesTimer) - return this.$pollSizeChangesTimer; - var self = this; - return this.$pollSizeChangesTimer = setInterval(function() { - self.checkForSizeChanges(); - }, 500); - }; - - this.setPolling = function(val) { - if (val) { - this.$pollSizeChanges(); - } else if (this.$pollSizeChangesTimer) { - clearInterval(this.$pollSizeChangesTimer); - this.$pollSizeChangesTimer = 0; - } - }; - - this.$measureSizes = function() { - if (CHAR_COUNT === 50) { - var rect = null; - try { - rect = this.$measureNode.getBoundingClientRect(); - } catch(e) { - rect = {width: 0, height:0 }; - } - var size = { - height: rect.height, - width: rect.width / CHAR_COUNT - }; - } else { - var size = { - height: this.$measureNode.clientHeight, - width: this.$measureNode.clientWidth / CHAR_COUNT - }; - } - if (size.width === 0 || size.height === 0) - return null; - return size; - }; - - this.$measureCharWidth = function(ch) { - this.$main.innerHTML = lang.stringRepeat(ch, CHAR_COUNT); - var rect = this.$main.getBoundingClientRect(); - return rect.width / CHAR_COUNT; - }; - - this.getCharacterWidth = function(ch) { - var w = this.charSizes[ch]; - if (w === undefined) { - w = this.charSizes[ch] = this.$measureCharWidth(ch) / this.$characterSize.width; - } - return w; - }; - - this.destroy = function() { - clearInterval(this.$pollSizeChangesTimer); - if (this.el && this.el.parentNode) - this.el.parentNode.removeChild(this.el); - }; - - }).call(FontMetrics.prototype); - - }); - - ace.define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/config","ace/lib/useragent","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/scrollbar","ace/renderloop","ace/layer/font_metrics","ace/lib/event_emitter"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("./lib/oop"); - var dom = acequire("./lib/dom"); - var config = acequire("./config"); - var useragent = acequire("./lib/useragent"); - var GutterLayer = acequire("./layer/gutter").Gutter; - var MarkerLayer = acequire("./layer/marker").Marker; - var TextLayer = acequire("./layer/text").Text; - var CursorLayer = acequire("./layer/cursor").Cursor; - var HScrollBar = acequire("./scrollbar").HScrollBar; - var VScrollBar = acequire("./scrollbar").VScrollBar; - var RenderLoop = acequire("./renderloop").RenderLoop; - var FontMetrics = acequire("./layer/font_metrics").FontMetrics; - var EventEmitter = acequire("./lib/event_emitter").EventEmitter; - var editorCss = ".ace_editor {\ - position: relative;\ - overflow: hidden;\ - font: 12px/normal 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;\ - direction: ltr;\ - text-align: left;\ - -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\ - }\ - .ace_scroller {\ - position: absolute;\ - overflow: hidden;\ - top: 0;\ - bottom: 0;\ - background-color: inherit;\ - -ms-user-select: none;\ - -moz-user-select: none;\ - -webkit-user-select: none;\ - user-select: none;\ - cursor: text;\ - }\ - .ace_content {\ - position: absolute;\ - -moz-box-sizing: border-box;\ - -webkit-box-sizing: border-box;\ - box-sizing: border-box;\ - min-width: 100%;\ - }\ - .ace_dragging .ace_scroller:before{\ - position: absolute;\ - top: 0;\ - left: 0;\ - right: 0;\ - bottom: 0;\ - content: '';\ - background: rgba(250, 250, 250, 0.01);\ - z-index: 1000;\ - }\ - .ace_dragging.ace_dark .ace_scroller:before{\ - background: rgba(0, 0, 0, 0.01);\ - }\ - .ace_selecting, .ace_selecting * {\ - cursor: text !important;\ - }\ - .ace_gutter {\ - position: absolute;\ - overflow : hidden;\ - width: auto;\ - top: 0;\ - bottom: 0;\ - left: 0;\ - cursor: default;\ - z-index: 4;\ - -ms-user-select: none;\ - -moz-user-select: none;\ - -webkit-user-select: none;\ - user-select: none;\ - }\ - .ace_gutter-active-line {\ - position: absolute;\ - left: 0;\ - right: 0;\ - }\ - .ace_scroller.ace_scroll-left {\ - box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;\ - }\ - .ace_gutter-cell {\ - padding-left: 19px;\ - padding-right: 6px;\ - background-repeat: no-repeat;\ - }\ - .ace_gutter-cell.ace_error {\ - background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==\");\ - background-repeat: no-repeat;\ - background-position: 2px center;\ - }\ - .ace_gutter-cell.ace_warning {\ - background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==\");\ - background-position: 2px center;\ - }\ - .ace_gutter-cell.ace_info {\ - background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=\");\ - background-position: 2px center;\ - }\ - .ace_dark .ace_gutter-cell.ace_info {\ - background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC\");\ - }\ - .ace_scrollbar {\ - position: absolute;\ - right: 0;\ - bottom: 0;\ - z-index: 6;\ - }\ - .ace_scrollbar-inner {\ - position: absolute;\ - cursor: text;\ - left: 0;\ - top: 0;\ - }\ - .ace_scrollbar-v{\ - overflow-x: hidden;\ - overflow-y: scroll;\ - top: 0;\ - }\ - .ace_scrollbar-h {\ - overflow-x: scroll;\ - overflow-y: hidden;\ - left: 0;\ - }\ - .ace_print-margin {\ - position: absolute;\ - height: 100%;\ - }\ - .ace_text-input {\ - position: absolute;\ - z-index: 0;\ - width: 0.5em;\ - height: 1em;\ - opacity: 0;\ - background: transparent;\ - -moz-appearance: none;\ - appearance: none;\ - border: none;\ - resize: none;\ - outline: none;\ - overflow: hidden;\ - font: inherit;\ - padding: 0 1px;\ - margin: 0 -1px;\ - text-indent: -1em;\ - -ms-user-select: text;\ - -moz-user-select: text;\ - -webkit-user-select: text;\ - user-select: text;\ - white-space: pre!important;\ - }\ - .ace_text-input.ace_composition {\ - background: inherit;\ - color: inherit;\ - z-index: 1000;\ - opacity: 1;\ - text-indent: 0;\ - }\ - .ace_layer {\ - z-index: 1;\ - position: absolute;\ - overflow: hidden;\ - word-wrap: normal;\ - white-space: pre;\ - height: 100%;\ - width: 100%;\ - -moz-box-sizing: border-box;\ - -webkit-box-sizing: border-box;\ - box-sizing: border-box;\ - pointer-events: none;\ - }\ - .ace_gutter-layer {\ - position: relative;\ - width: auto;\ - text-align: right;\ - pointer-events: auto;\ - }\ - .ace_text-layer {\ - font: inherit !important;\ - }\ - .ace_cjk {\ - display: inline-block;\ - text-align: center;\ - }\ - .ace_cursor-layer {\ - z-index: 4;\ - }\ - .ace_cursor {\ - z-index: 4;\ - position: absolute;\ - -moz-box-sizing: border-box;\ - -webkit-box-sizing: border-box;\ - box-sizing: border-box;\ - border-left: 2px solid;\ - transform: translatez(0);\ - }\ - .ace_multiselect .ace_cursor {\ - border-left-width: 1px;\ - }\ - .ace_slim-cursors .ace_cursor {\ - border-left-width: 1px;\ - }\ - .ace_overwrite-cursors .ace_cursor {\ - border-left-width: 0;\ - border-bottom: 1px solid;\ - }\ - .ace_hidden-cursors .ace_cursor {\ - opacity: 0.2;\ - }\ - .ace_smooth-blinking .ace_cursor {\ - -webkit-transition: opacity 0.18s;\ - transition: opacity 0.18s;\ - }\ - .ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {\ - position: absolute;\ - z-index: 3;\ - }\ - .ace_marker-layer .ace_selection {\ - position: absolute;\ - z-index: 5;\ - }\ - .ace_marker-layer .ace_bracket {\ - position: absolute;\ - z-index: 6;\ - }\ - .ace_marker-layer .ace_active-line {\ - position: absolute;\ - z-index: 2;\ - }\ - .ace_marker-layer .ace_selected-word {\ - position: absolute;\ - z-index: 4;\ - -moz-box-sizing: border-box;\ - -webkit-box-sizing: border-box;\ - box-sizing: border-box;\ - }\ - .ace_line .ace_fold {\ - -moz-box-sizing: border-box;\ - -webkit-box-sizing: border-box;\ - box-sizing: border-box;\ - display: inline-block;\ - height: 11px;\ - margin-top: -2px;\ - vertical-align: middle;\ - background-image:\ - url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),\ - url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=\");\ - background-repeat: no-repeat, repeat-x;\ - background-position: center center, top left;\ - color: transparent;\ - border: 1px solid black;\ - border-radius: 2px;\ - cursor: pointer;\ - pointer-events: auto;\ - }\ - .ace_dark .ace_fold {\ - }\ - .ace_fold:hover{\ - background-image:\ - url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),\ - url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC\");\ - }\ - .ace_tooltip {\ - background-color: #FFF;\ - background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1));\ - background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));\ - border: 1px solid gray;\ - border-radius: 1px;\ - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);\ - color: black;\ - max-width: 100%;\ - padding: 3px 4px;\ - position: fixed;\ - z-index: 999999;\ - -moz-box-sizing: border-box;\ - -webkit-box-sizing: border-box;\ - box-sizing: border-box;\ - cursor: default;\ - white-space: pre;\ - word-wrap: break-word;\ - line-height: normal;\ - font-style: normal;\ - font-weight: normal;\ - letter-spacing: normal;\ - pointer-events: none;\ - }\ - .ace_folding-enabled > .ace_gutter-cell {\ - padding-right: 13px;\ - }\ - .ace_fold-widget {\ - -moz-box-sizing: border-box;\ - -webkit-box-sizing: border-box;\ - box-sizing: border-box;\ - margin: 0 -12px 0 1px;\ - display: none;\ - width: 11px;\ - vertical-align: top;\ - background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==\");\ - background-repeat: no-repeat;\ - background-position: center;\ - border-radius: 3px;\ - border: 1px solid transparent;\ - cursor: pointer;\ - }\ - .ace_folding-enabled .ace_fold-widget {\ - display: inline-block; \ - }\ - .ace_fold-widget.ace_end {\ - background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==\");\ - }\ - .ace_fold-widget.ace_closed {\ - background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==\");\ - }\ - .ace_fold-widget:hover {\ - border: 1px solid rgba(0, 0, 0, 0.3);\ - background-color: rgba(255, 255, 255, 0.2);\ - box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\ - }\ - .ace_fold-widget:active {\ - border: 1px solid rgba(0, 0, 0, 0.4);\ - background-color: rgba(0, 0, 0, 0.05);\ - box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\ - }\ - .ace_dark .ace_fold-widget {\ - background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\");\ - }\ - .ace_dark .ace_fold-widget.ace_end {\ - background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\");\ - }\ - .ace_dark .ace_fold-widget.ace_closed {\ - background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\");\ - }\ - .ace_dark .ace_fold-widget:hover {\ - box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\ - background-color: rgba(255, 255, 255, 0.1);\ - }\ - .ace_dark .ace_fold-widget:active {\ - box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\ - }\ - .ace_fold-widget.ace_invalid {\ - background-color: #FFB4B4;\ - border-color: #DE5555;\ - }\ - .ace_fade-fold-widgets .ace_fold-widget {\ - -webkit-transition: opacity 0.4s ease 0.05s;\ - transition: opacity 0.4s ease 0.05s;\ - opacity: 0;\ - }\ - .ace_fade-fold-widgets:hover .ace_fold-widget {\ - -webkit-transition: opacity 0.05s ease 0.05s;\ - transition: opacity 0.05s ease 0.05s;\ - opacity:1;\ - }\ - .ace_underline {\ - text-decoration: underline;\ - }\ - .ace_bold {\ - font-weight: bold;\ - }\ - .ace_nobold .ace_bold {\ - font-weight: normal;\ - }\ - .ace_italic {\ - font-style: italic;\ - }\ - .ace_error-marker {\ - background-color: rgba(255, 0, 0,0.2);\ - position: absolute;\ - z-index: 9;\ - }\ - .ace_highlight-marker {\ - background-color: rgba(255, 255, 0,0.2);\ - position: absolute;\ - z-index: 8;\ - }\ - .ace_br1 {border-top-left-radius : 3px;}\ - .ace_br2 {border-top-right-radius : 3px;}\ - .ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;}\ - .ace_br4 {border-bottom-right-radius: 3px;}\ - .ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;}\ - .ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;}\ - .ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;}\ - .ace_br8 {border-bottom-left-radius : 3px;}\ - .ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;}\ - .ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;}\ - .ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;}\ - .ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\ - .ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\ - .ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\ - .ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\ - .ace_text-input-ios {\ - position: absolute !important;\ - top: -100000px !important;\ - left: -100000px !important;\ - }\ - "; - - dom.importCssString(editorCss, "ace_editor.css"); - - var VirtualRenderer = function(container, theme) { - var _self = this; - - this.container = container || dom.createElement("div"); - this.$keepTextAreaAtCursor = !useragent.isOldIE; - - dom.addCssClass(this.container, "ace_editor"); - - this.setTheme(theme); - - this.$gutter = dom.createElement("div"); - this.$gutter.className = "ace_gutter"; - this.container.appendChild(this.$gutter); - this.$gutter.setAttribute("aria-hidden", true); - - this.scroller = dom.createElement("div"); - this.scroller.className = "ace_scroller"; - this.container.appendChild(this.scroller); - - this.content = dom.createElement("div"); - this.content.className = "ace_content"; - this.scroller.appendChild(this.content); - - this.$gutterLayer = new GutterLayer(this.$gutter); - this.$gutterLayer.on("changeGutterWidth", this.onGutterResize.bind(this)); - - this.$markerBack = new MarkerLayer(this.content); - - var textLayer = this.$textLayer = new TextLayer(this.content); - this.canvas = textLayer.element; - - this.$markerFront = new MarkerLayer(this.content); - - this.$cursorLayer = new CursorLayer(this.content); - this.$horizScroll = false; - this.$vScroll = false; - - this.scrollBar = - this.scrollBarV = new VScrollBar(this.container, this); - this.scrollBarH = new HScrollBar(this.container, this); - this.scrollBarV.addEventListener("scroll", function(e) { - if (!_self.$scrollAnimation) - _self.session.setScrollTop(e.data - _self.scrollMargin.top); - }); - this.scrollBarH.addEventListener("scroll", function(e) { - if (!_self.$scrollAnimation) - _self.session.setScrollLeft(e.data - _self.scrollMargin.left); - }); - - this.scrollTop = 0; - this.scrollLeft = 0; - - this.cursorPos = { - row : 0, - column : 0 - }; - - this.$fontMetrics = new FontMetrics(this.container); - this.$textLayer.$setFontMetrics(this.$fontMetrics); - this.$textLayer.addEventListener("changeCharacterSize", function(e) { - _self.updateCharacterSize(); - _self.onResize(true, _self.gutterWidth, _self.$size.width, _self.$size.height); - _self._signal("changeCharacterSize", e); - }); - - this.$size = { - width: 0, - height: 0, - scrollerHeight: 0, - scrollerWidth: 0, - $dirty: true - }; - - this.layerConfig = { - width : 1, - padding : 0, - firstRow : 0, - firstRowScreen: 0, - lastRow : 0, - lineHeight : 0, - characterWidth : 0, - minHeight : 1, - maxHeight : 1, - offset : 0, - height : 1, - gutterOffset: 1 - }; - - this.scrollMargin = { - left: 0, - right: 0, - top: 0, - bottom: 0, - v: 0, - h: 0 - }; - - this.$loop = new RenderLoop( - this.$renderChanges.bind(this), - this.container.ownerDocument.defaultView - ); - this.$loop.schedule(this.CHANGE_FULL); - - this.updateCharacterSize(); - this.setPadding(4); - config.resetOptions(this); - config._emit("renderer", this); - }; - - (function() { - - this.CHANGE_CURSOR = 1; - this.CHANGE_MARKER = 2; - this.CHANGE_GUTTER = 4; - this.CHANGE_SCROLL = 8; - this.CHANGE_LINES = 16; - this.CHANGE_TEXT = 32; - this.CHANGE_SIZE = 64; - this.CHANGE_MARKER_BACK = 128; - this.CHANGE_MARKER_FRONT = 256; - this.CHANGE_FULL = 512; - this.CHANGE_H_SCROLL = 1024; - - oop.implement(this, EventEmitter); - - this.updateCharacterSize = function() { - if (this.$textLayer.allowBoldFonts != this.$allowBoldFonts) { - this.$allowBoldFonts = this.$textLayer.allowBoldFonts; - this.setStyle("ace_nobold", !this.$allowBoldFonts); - } - - this.layerConfig.characterWidth = - this.characterWidth = this.$textLayer.getCharacterWidth(); - this.layerConfig.lineHeight = - this.lineHeight = this.$textLayer.getLineHeight(); - this.$updatePrintMargin(); - }; - this.setSession = function(session) { - if (this.session) - this.session.doc.off("changeNewLineMode", this.onChangeNewLineMode); - - this.session = session; - if (session && this.scrollMargin.top && session.getScrollTop() <= 0) - session.setScrollTop(-this.scrollMargin.top); - - this.$cursorLayer.setSession(session); - this.$markerBack.setSession(session); - this.$markerFront.setSession(session); - this.$gutterLayer.setSession(session); - this.$textLayer.setSession(session); - if (!session) - return; - - this.$loop.schedule(this.CHANGE_FULL); - this.session.$setFontMetrics(this.$fontMetrics); - this.scrollBarH.scrollLeft = this.scrollBarV.scrollTop = null; - - this.onChangeNewLineMode = this.onChangeNewLineMode.bind(this); - this.onChangeNewLineMode(); - this.session.doc.on("changeNewLineMode", this.onChangeNewLineMode); - }; - this.updateLines = function(firstRow, lastRow, force) { - if (lastRow === undefined) - lastRow = Infinity; - - if (!this.$changedLines) { - this.$changedLines = { - firstRow: firstRow, - lastRow: lastRow - }; - } - else { - if (this.$changedLines.firstRow > firstRow) - this.$changedLines.firstRow = firstRow; - - if (this.$changedLines.lastRow < lastRow) - this.$changedLines.lastRow = lastRow; - } - if (this.$changedLines.lastRow < this.layerConfig.firstRow) { - if (force) - this.$changedLines.lastRow = this.layerConfig.lastRow; - else - return; - } - if (this.$changedLines.firstRow > this.layerConfig.lastRow) - return; - this.$loop.schedule(this.CHANGE_LINES); - }; - - this.onChangeNewLineMode = function() { - this.$loop.schedule(this.CHANGE_TEXT); - this.$textLayer.$updateEolChar(); - this.session.$bidiHandler.setEolChar(this.$textLayer.EOL_CHAR); - }; - - this.onChangeTabSize = function() { - this.$loop.schedule(this.CHANGE_TEXT | this.CHANGE_MARKER); - this.$textLayer.onChangeTabSize(); - }; - this.updateText = function() { - this.$loop.schedule(this.CHANGE_TEXT); - }; - this.updateFull = function(force) { - if (force) - this.$renderChanges(this.CHANGE_FULL, true); - else - this.$loop.schedule(this.CHANGE_FULL); - }; - this.updateFontSize = function() { - this.$textLayer.checkForSizeChanges(); - }; - - this.$changes = 0; - this.$updateSizeAsync = function() { - if (this.$loop.pending) - this.$size.$dirty = true; - else - this.onResize(); - }; - this.onResize = function(force, gutterWidth, width, height) { - if (this.resizing > 2) - return; - else if (this.resizing > 0) - this.resizing++; - else - this.resizing = force ? 1 : 0; - var el = this.container; - if (!height) - height = el.clientHeight || el.scrollHeight; - if (!width) - width = el.clientWidth || el.scrollWidth; - var changes = this.$updateCachedSize(force, gutterWidth, width, height); - - - if (!this.$size.scrollerHeight || (!width && !height)) - return this.resizing = 0; - - if (force) - this.$gutterLayer.$padding = null; - - if (force) - this.$renderChanges(changes | this.$changes, true); - else - this.$loop.schedule(changes | this.$changes); - - if (this.resizing) - this.resizing = 0; - this.scrollBarV.scrollLeft = this.scrollBarV.scrollTop = null; - }; - - this.$updateCachedSize = function(force, gutterWidth, width, height) { - height -= (this.$extraHeight || 0); - var changes = 0; - var size = this.$size; - var oldSize = { - width: size.width, - height: size.height, - scrollerHeight: size.scrollerHeight, - scrollerWidth: size.scrollerWidth - }; - if (height && (force || size.height != height)) { - size.height = height; - changes |= this.CHANGE_SIZE; - - size.scrollerHeight = size.height; - if (this.$horizScroll) - size.scrollerHeight -= this.scrollBarH.getHeight(); - this.scrollBarV.element.style.bottom = this.scrollBarH.getHeight() + "px"; - - changes = changes | this.CHANGE_SCROLL; - } - - if (width && (force || size.width != width)) { - changes |= this.CHANGE_SIZE; - size.width = width; - - if (gutterWidth == null) - gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0; - - this.gutterWidth = gutterWidth; - - this.scrollBarH.element.style.left = - this.scroller.style.left = gutterWidth + "px"; - size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth()); - - this.scrollBarH.element.style.right = - this.scroller.style.right = this.scrollBarV.getWidth() + "px"; - this.scroller.style.bottom = this.scrollBarH.getHeight() + "px"; - - if (this.session && this.session.getUseWrapMode() && this.adjustWrapLimit() || force) - changes |= this.CHANGE_FULL; - } - - size.$dirty = !width || !height; - - if (changes) - this._signal("resize", oldSize); - - return changes; - }; - - this.onGutterResize = function() { - var gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0; - if (gutterWidth != this.gutterWidth) - this.$changes |= this.$updateCachedSize(true, gutterWidth, this.$size.width, this.$size.height); - - if (this.session.getUseWrapMode() && this.adjustWrapLimit()) { - this.$loop.schedule(this.CHANGE_FULL); - } else if (this.$size.$dirty) { - this.$loop.schedule(this.CHANGE_FULL); - } else { - this.$computeLayerConfig(); - this.$loop.schedule(this.CHANGE_MARKER); - } - }; - this.adjustWrapLimit = function() { - var availableWidth = this.$size.scrollerWidth - this.$padding * 2; - var limit = Math.floor(availableWidth / this.characterWidth); - return this.session.adjustWrapLimit(limit, this.$showPrintMargin && this.$printMarginColumn); - }; - this.setAnimatedScroll = function(shouldAnimate){ - this.setOption("animatedScroll", shouldAnimate); - }; - this.getAnimatedScroll = function() { - return this.$animatedScroll; - }; - this.setShowInvisibles = function(showInvisibles) { - this.setOption("showInvisibles", showInvisibles); - this.session.$bidiHandler.setShowInvisibles(showInvisibles); - }; - this.getShowInvisibles = function() { - return this.getOption("showInvisibles"); - }; - this.getDisplayIndentGuides = function() { - return this.getOption("displayIndentGuides"); - }; - - this.setDisplayIndentGuides = function(display) { - this.setOption("displayIndentGuides", display); - }; - this.setShowPrintMargin = function(showPrintMargin) { - this.setOption("showPrintMargin", showPrintMargin); - }; - this.getShowPrintMargin = function() { - return this.getOption("showPrintMargin"); - }; - this.setPrintMarginColumn = function(showPrintMargin) { - this.setOption("printMarginColumn", showPrintMargin); - }; - this.getPrintMarginColumn = function() { - return this.getOption("printMarginColumn"); - }; - this.getShowGutter = function(){ - return this.getOption("showGutter"); - }; - this.setShowGutter = function(show){ - return this.setOption("showGutter", show); - }; - - this.getFadeFoldWidgets = function(){ - return this.getOption("fadeFoldWidgets"); - }; - - this.setFadeFoldWidgets = function(show) { - this.setOption("fadeFoldWidgets", show); - }; - - this.setHighlightGutterLine = function(shouldHighlight) { - this.setOption("highlightGutterLine", shouldHighlight); - }; - - this.getHighlightGutterLine = function() { - return this.getOption("highlightGutterLine"); - }; - - this.$updateGutterLineHighlight = function() { - var pos = this.$cursorLayer.$pixelPos; - var height = this.layerConfig.lineHeight; - if (this.session.getUseWrapMode()) { - var cursor = this.session.selection.getCursor(); - cursor.column = 0; - pos = this.$cursorLayer.getPixelPosition(cursor, true); - height *= this.session.getRowLength(cursor.row); - } - this.$gutterLineHighlight.style.top = pos.top - this.layerConfig.offset + "px"; - this.$gutterLineHighlight.style.height = height + "px"; - }; - - this.$updatePrintMargin = function() { - if (!this.$showPrintMargin && !this.$printMarginEl) - return; - - if (!this.$printMarginEl) { - var containerEl = dom.createElement("div"); - containerEl.className = "ace_layer ace_print-margin-layer"; - this.$printMarginEl = dom.createElement("div"); - this.$printMarginEl.className = "ace_print-margin"; - containerEl.appendChild(this.$printMarginEl); - this.content.insertBefore(containerEl, this.content.firstChild); - } - - var style = this.$printMarginEl.style; - style.left = ((this.characterWidth * this.$printMarginColumn) + this.$padding) + "px"; - style.visibility = this.$showPrintMargin ? "visible" : "hidden"; - - if (this.session && this.session.$wrap == -1) - this.adjustWrapLimit(); - }; - this.getContainerElement = function() { - return this.container; - }; - this.getMouseEventTarget = function() { - return this.scroller; - }; - this.getTextAreaContainer = function() { - return this.container; - }; - this.$moveTextAreaToCursor = function() { - if (!this.$keepTextAreaAtCursor) - return; - var config = this.layerConfig; - var posTop = this.$cursorLayer.$pixelPos.top; - var posLeft = this.$cursorLayer.$pixelPos.left; - posTop -= config.offset; - - var style = this.textarea.style; - var h = this.lineHeight; - if (posTop < 0 || posTop > config.height - h) { - style.top = style.left = "0"; - return; - } - - var w = this.characterWidth; - if (this.$composition) { - var val = this.textarea.value.replace(/^\x01+/, ""); - w *= (this.session.$getStringScreenWidth(val)[0]+2); - h += 2; - } - posLeft -= this.scrollLeft; - if (posLeft > this.$size.scrollerWidth - w) - posLeft = this.$size.scrollerWidth - w; - - posLeft += this.gutterWidth; - style.height = h + "px"; - style.width = w + "px"; - style.left = Math.min(posLeft, this.$size.scrollerWidth - w) + "px"; - style.top = Math.min(posTop, this.$size.height - h) + "px"; - }; - this.getFirstVisibleRow = function() { - return this.layerConfig.firstRow; - }; - this.getFirstFullyVisibleRow = function() { - return this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1); - }; - this.getLastFullyVisibleRow = function() { - var config = this.layerConfig; - var lastRow = config.lastRow; - var top = this.session.documentToScreenRow(lastRow, 0) * config.lineHeight; - if (top - this.session.getScrollTop() > config.height - config.lineHeight) - return lastRow - 1; - return lastRow; - }; - this.getLastVisibleRow = function() { - return this.layerConfig.lastRow; - }; - - this.$padding = null; - this.setPadding = function(padding) { - this.$padding = padding; - this.$textLayer.setPadding(padding); - this.$cursorLayer.setPadding(padding); - this.$markerFront.setPadding(padding); - this.$markerBack.setPadding(padding); - this.$loop.schedule(this.CHANGE_FULL); - this.$updatePrintMargin(); - }; - - this.setScrollMargin = function(top, bottom, left, right) { - var sm = this.scrollMargin; - sm.top = top|0; - sm.bottom = bottom|0; - sm.right = right|0; - sm.left = left|0; - sm.v = sm.top + sm.bottom; - sm.h = sm.left + sm.right; - if (sm.top && this.scrollTop <= 0 && this.session) - this.session.setScrollTop(-sm.top); - this.updateFull(); - }; - this.getHScrollBarAlwaysVisible = function() { - return this.$hScrollBarAlwaysVisible; - }; - this.setHScrollBarAlwaysVisible = function(alwaysVisible) { - this.setOption("hScrollBarAlwaysVisible", alwaysVisible); - }; - this.getVScrollBarAlwaysVisible = function() { - return this.$vScrollBarAlwaysVisible; - }; - this.setVScrollBarAlwaysVisible = function(alwaysVisible) { - this.setOption("vScrollBarAlwaysVisible", alwaysVisible); - }; - - this.$updateScrollBarV = function() { - var scrollHeight = this.layerConfig.maxHeight; - var scrollerHeight = this.$size.scrollerHeight; - if (!this.$maxLines && this.$scrollPastEnd) { - scrollHeight -= (scrollerHeight - this.lineHeight) * this.$scrollPastEnd; - if (this.scrollTop > scrollHeight - scrollerHeight) { - scrollHeight = this.scrollTop + scrollerHeight; - this.scrollBarV.scrollTop = null; - } - } - this.scrollBarV.setScrollHeight(scrollHeight + this.scrollMargin.v); - this.scrollBarV.setScrollTop(this.scrollTop + this.scrollMargin.top); - }; - this.$updateScrollBarH = function() { - this.scrollBarH.setScrollWidth(this.layerConfig.width + 2 * this.$padding + this.scrollMargin.h); - this.scrollBarH.setScrollLeft(this.scrollLeft + this.scrollMargin.left); - }; - - this.$frozen = false; - this.freeze = function() { - this.$frozen = true; - }; - - this.unfreeze = function() { - this.$frozen = false; - }; - - this.$renderChanges = function(changes, force) { - if (this.$changes) { - changes |= this.$changes; - this.$changes = 0; - } - if ((!this.session || !this.container.offsetWidth || this.$frozen) || (!changes && !force)) { - this.$changes |= changes; - return; - } - if (this.$size.$dirty) { - this.$changes |= changes; - return this.onResize(true); - } - if (!this.lineHeight) { - this.$textLayer.checkForSizeChanges(); - } - - this._signal("beforeRender"); - - if (this.session && this.session.$bidiHandler) - this.session.$bidiHandler.updateCharacterWidths(this.$fontMetrics); - - var config = this.layerConfig; - if (changes & this.CHANGE_FULL || - changes & this.CHANGE_SIZE || - changes & this.CHANGE_TEXT || - changes & this.CHANGE_LINES || - changes & this.CHANGE_SCROLL || - changes & this.CHANGE_H_SCROLL - ) { - changes |= this.$computeLayerConfig(); - if (config.firstRow != this.layerConfig.firstRow && config.firstRowScreen == this.layerConfig.firstRowScreen) { - var st = this.scrollTop + (config.firstRow - this.layerConfig.firstRow) * this.lineHeight; - if (st > 0) { - this.scrollTop = st; - changes = changes | this.CHANGE_SCROLL; - changes |= this.$computeLayerConfig(); - } - } - config = this.layerConfig; - this.$updateScrollBarV(); - if (changes & this.CHANGE_H_SCROLL) - this.$updateScrollBarH(); - this.$gutterLayer.element.style.marginTop = (-config.offset) + "px"; - this.content.style.marginTop = (-config.offset) + "px"; - this.content.style.width = config.width + 2 * this.$padding + "px"; - this.content.style.height = config.minHeight + "px"; - } - if (changes & this.CHANGE_H_SCROLL) { - this.content.style.marginLeft = -this.scrollLeft + "px"; - this.scroller.className = this.scrollLeft <= 0 ? "ace_scroller" : "ace_scroller ace_scroll-left"; - } - if (changes & this.CHANGE_FULL) { - this.$textLayer.update(config); - if (this.$showGutter) - this.$gutterLayer.update(config); - this.$markerBack.update(config); - this.$markerFront.update(config); - this.$cursorLayer.update(config); - this.$moveTextAreaToCursor(); - this.$highlightGutterLine && this.$updateGutterLineHighlight(); - this._signal("afterRender"); - return; - } - if (changes & this.CHANGE_SCROLL) { - if (changes & this.CHANGE_TEXT || changes & this.CHANGE_LINES) - this.$textLayer.update(config); - else - this.$textLayer.scrollLines(config); - - if (this.$showGutter) - this.$gutterLayer.update(config); - this.$markerBack.update(config); - this.$markerFront.update(config); - this.$cursorLayer.update(config); - this.$highlightGutterLine && this.$updateGutterLineHighlight(); - this.$moveTextAreaToCursor(); - this._signal("afterRender"); - return; - } - - if (changes & this.CHANGE_TEXT) { - this.$textLayer.update(config); - if (this.$showGutter) - this.$gutterLayer.update(config); - } - else if (changes & this.CHANGE_LINES) { - if (this.$updateLines() || (changes & this.CHANGE_GUTTER) && this.$showGutter) - this.$gutterLayer.update(config); - } - else if (changes & this.CHANGE_TEXT || changes & this.CHANGE_GUTTER) { - if (this.$showGutter) - this.$gutterLayer.update(config); - } - - if (changes & this.CHANGE_CURSOR) { - this.$cursorLayer.update(config); - this.$moveTextAreaToCursor(); - this.$highlightGutterLine && this.$updateGutterLineHighlight(); - } - - if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) { - this.$markerFront.update(config); - } - - if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_BACK)) { - this.$markerBack.update(config); - } - - this._signal("afterRender"); - }; - - - this.$autosize = function() { - var height = this.session.getScreenLength() * this.lineHeight; - var maxHeight = this.$maxLines * this.lineHeight; - var desiredHeight = Math.min(maxHeight, - Math.max((this.$minLines || 1) * this.lineHeight, height) - ) + this.scrollMargin.v + (this.$extraHeight || 0); - if (this.$horizScroll) - desiredHeight += this.scrollBarH.getHeight(); - if (this.$maxPixelHeight && desiredHeight > this.$maxPixelHeight) - desiredHeight = this.$maxPixelHeight; - var vScroll = height > maxHeight; - - if (desiredHeight != this.desiredHeight || - this.$size.height != this.desiredHeight || vScroll != this.$vScroll) { - if (vScroll != this.$vScroll) { - this.$vScroll = vScroll; - this.scrollBarV.setVisible(vScroll); - } - - var w = this.container.clientWidth; - this.container.style.height = desiredHeight + "px"; - this.$updateCachedSize(true, this.$gutterWidth, w, desiredHeight); - this.desiredHeight = desiredHeight; - - this._signal("autosize"); - } - }; - - this.$computeLayerConfig = function() { - var session = this.session; - var size = this.$size; - - var hideScrollbars = size.height <= 2 * this.lineHeight; - var screenLines = this.session.getScreenLength(); - var maxHeight = screenLines * this.lineHeight; - - var longestLine = this.$getLongestLine(); - - var horizScroll = !hideScrollbars && (this.$hScrollBarAlwaysVisible || - size.scrollerWidth - longestLine - 2 * this.$padding < 0); - - var hScrollChanged = this.$horizScroll !== horizScroll; - if (hScrollChanged) { - this.$horizScroll = horizScroll; - this.scrollBarH.setVisible(horizScroll); - } - var vScrollBefore = this.$vScroll; // autosize can change vscroll value in which case we need to update longestLine - if (this.$maxLines && this.lineHeight > 1) - this.$autosize(); - - var offset = this.scrollTop % this.lineHeight; - var minHeight = size.scrollerHeight + this.lineHeight; - - var scrollPastEnd = !this.$maxLines && this.$scrollPastEnd - ? (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd - : 0; - maxHeight += scrollPastEnd; - - var sm = this.scrollMargin; - this.session.setScrollTop(Math.max(-sm.top, - Math.min(this.scrollTop, maxHeight - size.scrollerHeight + sm.bottom))); - - this.session.setScrollLeft(Math.max(-sm.left, Math.min(this.scrollLeft, - longestLine + 2 * this.$padding - size.scrollerWidth + sm.right))); - - var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible || - size.scrollerHeight - maxHeight + scrollPastEnd < 0 || this.scrollTop > sm.top); - var vScrollChanged = vScrollBefore !== vScroll; - if (vScrollChanged) { - this.$vScroll = vScroll; - this.scrollBarV.setVisible(vScroll); - } - - var lineCount = Math.ceil(minHeight / this.lineHeight) - 1; - var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight)); - var lastRow = firstRow + lineCount; - var firstRowScreen, firstRowHeight; - var lineHeight = this.lineHeight; - firstRow = session.screenToDocumentRow(firstRow, 0); - var foldLine = session.getFoldLine(firstRow); - if (foldLine) { - firstRow = foldLine.start.row; - } - - firstRowScreen = session.documentToScreenRow(firstRow, 0); - firstRowHeight = session.getRowLength(firstRow) * lineHeight; - - lastRow = Math.min(session.screenToDocumentRow(lastRow, 0), session.getLength() - 1); - minHeight = size.scrollerHeight + session.getRowLength(lastRow) * lineHeight + - firstRowHeight; - - offset = this.scrollTop - firstRowScreen * lineHeight; - - var changes = 0; - if (this.layerConfig.width != longestLine) - changes = this.CHANGE_H_SCROLL; - if (hScrollChanged || vScrollChanged) { - changes = this.$updateCachedSize(true, this.gutterWidth, size.width, size.height); - this._signal("scrollbarVisibilityChanged"); - if (vScrollChanged) - longestLine = this.$getLongestLine(); - } - - this.layerConfig = { - width : longestLine, - padding : this.$padding, - firstRow : firstRow, - firstRowScreen: firstRowScreen, - lastRow : lastRow, - lineHeight : lineHeight, - characterWidth : this.characterWidth, - minHeight : minHeight, - maxHeight : maxHeight, - offset : offset, - gutterOffset : lineHeight ? Math.max(0, Math.ceil((offset + size.height - size.scrollerHeight) / lineHeight)) : 0, - height : this.$size.scrollerHeight - }; - - return changes; - }; - - this.$updateLines = function() { - if (!this.$changedLines) return; - var firstRow = this.$changedLines.firstRow; - var lastRow = this.$changedLines.lastRow; - this.$changedLines = null; - - var layerConfig = this.layerConfig; - - if (firstRow > layerConfig.lastRow + 1) { return; } - if (lastRow < layerConfig.firstRow) { return; } - if (lastRow === Infinity) { - if (this.$showGutter) - this.$gutterLayer.update(layerConfig); - this.$textLayer.update(layerConfig); - return; - } - this.$textLayer.updateLines(layerConfig, firstRow, lastRow); - return true; - }; - - this.$getLongestLine = function() { - var charCount = this.session.getScreenWidth(); - if (this.showInvisibles && !this.session.$useWrapMode) - charCount += 1; - - return Math.max(this.$size.scrollerWidth - 2 * this.$padding, Math.round(charCount * this.characterWidth)); - }; - this.updateFrontMarkers = function() { - this.$markerFront.setMarkers(this.session.getMarkers(true)); - this.$loop.schedule(this.CHANGE_MARKER_FRONT); - }; - this.updateBackMarkers = function() { - this.$markerBack.setMarkers(this.session.getMarkers()); - this.$loop.schedule(this.CHANGE_MARKER_BACK); - }; - this.addGutterDecoration = function(row, className){ - this.$gutterLayer.addGutterDecoration(row, className); - }; - this.removeGutterDecoration = function(row, className){ - this.$gutterLayer.removeGutterDecoration(row, className); - }; - this.updateBreakpoints = function(rows) { - this.$loop.schedule(this.CHANGE_GUTTER); - }; - this.setAnnotations = function(annotations) { - this.$gutterLayer.setAnnotations(annotations); - this.$loop.schedule(this.CHANGE_GUTTER); - }; - this.updateCursor = function() { - this.$loop.schedule(this.CHANGE_CURSOR); - }; - this.hideCursor = function() { - this.$cursorLayer.hideCursor(); - }; - this.showCursor = function() { - this.$cursorLayer.showCursor(); - }; - - this.scrollSelectionIntoView = function(anchor, lead, offset) { - this.scrollCursorIntoView(anchor, offset); - this.scrollCursorIntoView(lead, offset); - }; - this.scrollCursorIntoView = function(cursor, offset, $viewMargin) { - if (this.$size.scrollerHeight === 0) - return; - - var pos = this.$cursorLayer.getPixelPosition(cursor); - - var left = pos.left; - var top = pos.top; - - var topMargin = $viewMargin && $viewMargin.top || 0; - var bottomMargin = $viewMargin && $viewMargin.bottom || 0; - - var scrollTop = this.$scrollAnimation ? this.session.getScrollTop() : this.scrollTop; - - if (scrollTop + topMargin > top) { - if (offset && scrollTop + topMargin > top + this.lineHeight) - top -= offset * this.$size.scrollerHeight; - if (top === 0) - top = -this.scrollMargin.top; - this.session.setScrollTop(top); - } else if (scrollTop + this.$size.scrollerHeight - bottomMargin < top + this.lineHeight) { - if (offset && scrollTop + this.$size.scrollerHeight - bottomMargin < top - this.lineHeight) - top += offset * this.$size.scrollerHeight; - this.session.setScrollTop(top + this.lineHeight - this.$size.scrollerHeight); - } - - var scrollLeft = this.scrollLeft; - - if (scrollLeft > left) { - if (left < this.$padding + 2 * this.layerConfig.characterWidth) - left = -this.scrollMargin.left; - this.session.setScrollLeft(left); - } else if (scrollLeft + this.$size.scrollerWidth < left + this.characterWidth) { - this.session.setScrollLeft(Math.round(left + this.characterWidth - this.$size.scrollerWidth)); - } else if (scrollLeft <= this.$padding && left - scrollLeft < this.characterWidth) { - this.session.setScrollLeft(0); - } - }; - this.getScrollTop = function() { - return this.session.getScrollTop(); - }; - this.getScrollLeft = function() { - return this.session.getScrollLeft(); - }; - this.getScrollTopRow = function() { - return this.scrollTop / this.lineHeight; - }; - this.getScrollBottomRow = function() { - return Math.max(0, Math.floor((this.scrollTop + this.$size.scrollerHeight) / this.lineHeight) - 1); - }; - this.scrollToRow = function(row) { - this.session.setScrollTop(row * this.lineHeight); - }; - - this.alignCursor = function(cursor, alignment) { - if (typeof cursor == "number") - cursor = {row: cursor, column: 0}; - - var pos = this.$cursorLayer.getPixelPosition(cursor); - var h = this.$size.scrollerHeight - this.lineHeight; - var offset = pos.top - h * (alignment || 0); - - this.session.setScrollTop(offset); - return offset; - }; - - this.STEPS = 8; - this.$calcSteps = function(fromValue, toValue){ - var i = 0; - var l = this.STEPS; - var steps = []; - - var func = function(t, x_min, dx) { - return dx * (Math.pow(t - 1, 3) + 1) + x_min; - }; - - for (i = 0; i < l; ++i) - steps.push(func(i / this.STEPS, fromValue, toValue - fromValue)); - - return steps; - }; - this.scrollToLine = function(line, center, animate, callback) { - var pos = this.$cursorLayer.getPixelPosition({row: line, column: 0}); - var offset = pos.top; - if (center) - offset -= this.$size.scrollerHeight / 2; - - var initialScroll = this.scrollTop; - this.session.setScrollTop(offset); - if (animate !== false) - this.animateScrolling(initialScroll, callback); - }; - - this.animateScrolling = function(fromValue, callback) { - var toValue = this.scrollTop; - if (!this.$animatedScroll) - return; - var _self = this; - - if (fromValue == toValue) - return; - - if (this.$scrollAnimation) { - var oldSteps = this.$scrollAnimation.steps; - if (oldSteps.length) { - fromValue = oldSteps[0]; - if (fromValue == toValue) - return; - } - } - - var steps = _self.$calcSteps(fromValue, toValue); - this.$scrollAnimation = {from: fromValue, to: toValue, steps: steps}; - - clearInterval(this.$timer); - - _self.session.setScrollTop(steps.shift()); - _self.session.$scrollTop = toValue; - this.$timer = setInterval(function() { - if (steps.length) { - _self.session.setScrollTop(steps.shift()); - _self.session.$scrollTop = toValue; - } else if (toValue != null) { - _self.session.$scrollTop = -1; - _self.session.setScrollTop(toValue); - toValue = null; - } else { - _self.$timer = clearInterval(_self.$timer); - _self.$scrollAnimation = null; - callback && callback(); - } - }, 10); - }; - this.scrollToY = function(scrollTop) { - if (this.scrollTop !== scrollTop) { - this.$loop.schedule(this.CHANGE_SCROLL); - this.scrollTop = scrollTop; - } - }; - this.scrollToX = function(scrollLeft) { - if (this.scrollLeft !== scrollLeft) - this.scrollLeft = scrollLeft; - this.$loop.schedule(this.CHANGE_H_SCROLL); - }; - this.scrollTo = function(x, y) { - this.session.setScrollTop(y); - this.session.setScrollLeft(y); - }; - this.scrollBy = function(deltaX, deltaY) { - deltaY && this.session.setScrollTop(this.session.getScrollTop() + deltaY); - deltaX && this.session.setScrollLeft(this.session.getScrollLeft() + deltaX); - }; - this.isScrollableBy = function(deltaX, deltaY) { - if (deltaY < 0 && this.session.getScrollTop() >= 1 - this.scrollMargin.top) - return true; - if (deltaY > 0 && this.session.getScrollTop() + this.$size.scrollerHeight - - this.layerConfig.maxHeight < -1 + this.scrollMargin.bottom) - return true; - if (deltaX < 0 && this.session.getScrollLeft() >= 1 - this.scrollMargin.left) - return true; - if (deltaX > 0 && this.session.getScrollLeft() + this.$size.scrollerWidth - - this.layerConfig.width < -1 + this.scrollMargin.right) - return true; - }; - - this.pixelToScreenCoordinates = function(x, y) { - var canvasPos = this.scroller.getBoundingClientRect(); - - var offsetX = x + this.scrollLeft - canvasPos.left - this.$padding; - var offset = offsetX / this.characterWidth; - var row = Math.floor((y + this.scrollTop - canvasPos.top) / this.lineHeight); - var col = Math.round(offset); - - return {row: row, column: col, side: offset - col > 0 ? 1 : -1, offsetX: offsetX}; - }; - - this.screenToTextCoordinates = function(x, y) { - var canvasPos = this.scroller.getBoundingClientRect(); - var offsetX = x + this.scrollLeft - canvasPos.left - this.$padding; - - var col = Math.round(offsetX / this.characterWidth); - - var row = (y + this.scrollTop - canvasPos.top) / this.lineHeight; - - return this.session.screenToDocumentPosition(row, Math.max(col, 0), offsetX); - }; - this.textToScreenCoordinates = function(row, column) { - var canvasPos = this.scroller.getBoundingClientRect(); - var pos = this.session.documentToScreenPosition(row, column); - - var x = this.$padding + (this.session.$bidiHandler.isBidiRow(pos.row, row) - ? this.session.$bidiHandler.getPosLeft(pos.column) - : Math.round(pos.column * this.characterWidth)); - - var y = pos.row * this.lineHeight; - - return { - pageX: canvasPos.left + x - this.scrollLeft, - pageY: canvasPos.top + y - this.scrollTop - }; - }; - this.visualizeFocus = function() { - dom.addCssClass(this.container, "ace_focus"); - }; - this.visualizeBlur = function() { - dom.removeCssClass(this.container, "ace_focus"); - }; - this.showComposition = function(position) { - if (!this.$composition) - this.$composition = { - keepTextAreaAtCursor: this.$keepTextAreaAtCursor, - cssText: this.textarea.style.cssText - }; - - this.$keepTextAreaAtCursor = true; - dom.addCssClass(this.textarea, "ace_composition"); - this.textarea.style.cssText = ""; - this.$moveTextAreaToCursor(); - }; - this.setCompositionText = function(text) { - this.$moveTextAreaToCursor(); - }; - this.hideComposition = function() { - if (!this.$composition) - return; - - dom.removeCssClass(this.textarea, "ace_composition"); - this.$keepTextAreaAtCursor = this.$composition.keepTextAreaAtCursor; - this.textarea.style.cssText = this.$composition.cssText; - this.$composition = null; - }; - this.setTheme = function(theme, cb) { - var _self = this; - this.$themeId = theme; - _self._dispatchEvent('themeChange',{theme:theme}); - - if (!theme || typeof theme == "string") { - var moduleName = theme || this.$options.theme.initialValue; - config.loadModule(["theme", moduleName], afterLoad); - } else { - afterLoad(theme); - } - - function afterLoad(module) { - if (_self.$themeId != theme) - return cb && cb(); - if (!module || !module.cssClass) - throw new Error("couldn't load module " + theme + " or it didn't call define"); - dom.importCssString( - module.cssText, - module.cssClass, - _self.container.ownerDocument - ); - - if (_self.theme) - dom.removeCssClass(_self.container, _self.theme.cssClass); - - var padding = "padding" in module ? module.padding - : "padding" in (_self.theme || {}) ? 4 : _self.$padding; - if (_self.$padding && padding != _self.$padding) - _self.setPadding(padding); - _self.$theme = module.cssClass; - - _self.theme = module; - dom.addCssClass(_self.container, module.cssClass); - dom.setCssClass(_self.container, "ace_dark", module.isDark); - if (_self.$size) { - _self.$size.width = 0; - _self.$updateSizeAsync(); - } - - _self._dispatchEvent('themeLoaded', {theme:module}); - cb && cb(); - } - }; - this.getTheme = function() { - return this.$themeId; - }; - this.setStyle = function(style, include) { - dom.setCssClass(this.container, style, include !== false); - }; - this.unsetStyle = function(style) { - dom.removeCssClass(this.container, style); - }; - - this.setCursorStyle = function(style) { - if (this.scroller.style.cursor != style) - this.scroller.style.cursor = style; - }; - this.setMouseCursor = function(cursorStyle) { - this.scroller.style.cursor = cursorStyle; - }; - this.destroy = function() { - this.$textLayer.destroy(); - this.$cursorLayer.destroy(); - }; - - }).call(VirtualRenderer.prototype); - - - config.defineOptions(VirtualRenderer.prototype, "renderer", { - animatedScroll: {initialValue: false}, - showInvisibles: { - set: function(value) { - if (this.$textLayer.setShowInvisibles(value)) - this.$loop.schedule(this.CHANGE_TEXT); - }, - initialValue: false - }, - showPrintMargin: { - set: function() { this.$updatePrintMargin(); }, - initialValue: true - }, - printMarginColumn: { - set: function() { this.$updatePrintMargin(); }, - initialValue: 80 - }, - printMargin: { - set: function(val) { - if (typeof val == "number") - this.$printMarginColumn = val; - this.$showPrintMargin = !!val; - this.$updatePrintMargin(); - }, - get: function() { - return this.$showPrintMargin && this.$printMarginColumn; - } - }, - showGutter: { - set: function(show){ - this.$gutter.style.display = show ? "block" : "none"; - this.$loop.schedule(this.CHANGE_FULL); - this.onGutterResize(); - }, - initialValue: true - }, - fadeFoldWidgets: { - set: function(show) { - dom.setCssClass(this.$gutter, "ace_fade-fold-widgets", show); - }, - initialValue: false - }, - showFoldWidgets: { - set: function(show) {this.$gutterLayer.setShowFoldWidgets(show);}, - initialValue: true - }, - showLineNumbers: { - set: function(show) { - this.$gutterLayer.setShowLineNumbers(show); - this.$loop.schedule(this.CHANGE_GUTTER); - }, - initialValue: true - }, - displayIndentGuides: { - set: function(show) { - if (this.$textLayer.setDisplayIndentGuides(show)) - this.$loop.schedule(this.CHANGE_TEXT); - }, - initialValue: true - }, - highlightGutterLine: { - set: function(shouldHighlight) { - if (!this.$gutterLineHighlight) { - this.$gutterLineHighlight = dom.createElement("div"); - this.$gutterLineHighlight.className = "ace_gutter-active-line"; - this.$gutter.appendChild(this.$gutterLineHighlight); - return; - } - - this.$gutterLineHighlight.style.display = shouldHighlight ? "" : "none"; - if (this.$cursorLayer.$pixelPos) - this.$updateGutterLineHighlight(); - }, - initialValue: false, - value: true - }, - hScrollBarAlwaysVisible: { - set: function(val) { - if (!this.$hScrollBarAlwaysVisible || !this.$horizScroll) - this.$loop.schedule(this.CHANGE_SCROLL); - }, - initialValue: false - }, - vScrollBarAlwaysVisible: { - set: function(val) { - if (!this.$vScrollBarAlwaysVisible || !this.$vScroll) - this.$loop.schedule(this.CHANGE_SCROLL); - }, - initialValue: false - }, - fontSize: { - set: function(size) { - if (typeof size == "number") - size = size + "px"; - this.container.style.fontSize = size; - this.updateFontSize(); - }, - initialValue: 12 - }, - fontFamily: { - set: function(name) { - this.container.style.fontFamily = name; - this.updateFontSize(); - } - }, - maxLines: { - set: function(val) { - this.updateFull(); - } - }, - minLines: { - set: function(val) { - this.updateFull(); - } - }, - maxPixelHeight: { - set: function(val) { - this.updateFull(); - }, - initialValue: 0 - }, - scrollPastEnd: { - set: function(val) { - val = +val || 0; - if (this.$scrollPastEnd == val) - return; - this.$scrollPastEnd = val; - this.$loop.schedule(this.CHANGE_SCROLL); - }, - initialValue: 0, - handlesSet: true - }, - fixedWidthGutter: { - set: function(val) { - this.$gutterLayer.$fixedWidth = !!val; - this.$loop.schedule(this.CHANGE_GUTTER); - } - }, - theme: { - set: function(val) { this.setTheme(val); }, - get: function() { return this.$themeId || this.theme; }, - initialValue: "./theme/textmate", - handlesSet: true - } - }); - - exports.VirtualRenderer = VirtualRenderer; - }); - - ace.define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/net","ace/lib/event_emitter","ace/config"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("../lib/oop"); - var net = acequire("../lib/net"); - var EventEmitter = acequire("../lib/event_emitter").EventEmitter; - var config = acequire("../config"); - - function $workerBlob(workerUrl, mod) { - var script = mod.src;"importScripts('" + net.qualifyURL(workerUrl) + "');"; - try { - return new Blob([script], {"type": "application/javascript"}); - } catch (e) { // Backwards-compatibility - var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder; - var blobBuilder = new BlobBuilder(); - blobBuilder.append(script); - return blobBuilder.getBlob("application/javascript"); - } - } - - function createWorker(workerUrl, mod) { - var blob = $workerBlob(workerUrl, mod); - var URL = window.URL || window.webkitURL; - var blobURL = URL.createObjectURL(blob); - return new Worker(blobURL); - } - - var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl, importScripts) { - this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this); - this.changeListener = this.changeListener.bind(this); - this.onMessage = this.onMessage.bind(this); - if (acequire.nameToUrl && !acequire.toUrl) - acequire.toUrl = acequire.nameToUrl; - - if (config.get("packaged") || !acequire.toUrl) { - workerUrl = workerUrl || config.moduleUrl(mod.id, "worker"); - } else { - var normalizePath = this.$normalizePath; - workerUrl = workerUrl || normalizePath(acequire.toUrl("ace/worker/worker.js", null, "_")); - - var tlns = {}; - topLevelNamespaces.forEach(function(ns) { - tlns[ns] = normalizePath(acequire.toUrl(ns, null, "_").replace(/(\.js)?(\?.*)?$/, "")); - }); - } - - this.$worker = createWorker(workerUrl, mod); - if (importScripts) { - this.send("importScripts", importScripts); - } - this.$worker.postMessage({ - init : true, - tlns : tlns, - module : mod.id, - classname : classname - }); - - this.callbackId = 1; - this.callbacks = {}; - - this.$worker.onmessage = this.onMessage; - }; - - (function(){ - - oop.implement(this, EventEmitter); - - this.onMessage = function(e) { - var msg = e.data; - switch (msg.type) { - case "event": - this._signal(msg.name, {data: msg.data}); - break; - case "call": - var callback = this.callbacks[msg.id]; - if (callback) { - callback(msg.data); - delete this.callbacks[msg.id]; - } - break; - case "error": - this.reportError(msg.data); - break; - case "log": - window.console && console.log && console.log.apply(console, msg.data); - break; - } - }; - - this.reportError = function(err) { - window.console && console.error && console.error(err); - }; - - this.$normalizePath = function(path) { - return net.qualifyURL(path); - }; - - this.terminate = function() { - this._signal("terminate", {}); - this.deltaQueue = null; - this.$worker.terminate(); - this.$worker = null; - if (this.$doc) - this.$doc.off("change", this.changeListener); - this.$doc = null; - }; - - this.send = function(cmd, args) { - this.$worker.postMessage({command: cmd, args: args}); - }; - - this.call = function(cmd, args, callback) { - if (callback) { - var id = this.callbackId++; - this.callbacks[id] = callback; - args.push(id); - } - this.send(cmd, args); - }; - - this.emit = function(event, data) { - try { - this.$worker.postMessage({event: event, data: {data: data.data}}); - } - catch(ex) { - console.error(ex.stack); - } - }; - - this.attachToDocument = function(doc) { - if (this.$doc) - this.terminate(); - - this.$doc = doc; - this.call("setValue", [doc.getValue()]); - doc.on("change", this.changeListener); - }; - - this.changeListener = function(delta) { - if (!this.deltaQueue) { - this.deltaQueue = []; - setTimeout(this.$sendDeltaQueue, 0); - } - if (delta.action == "insert") - this.deltaQueue.push(delta.start, delta.lines); - else - this.deltaQueue.push(delta.start, delta.end); - }; - - this.$sendDeltaQueue = function() { - var q = this.deltaQueue; - if (!q) return; - this.deltaQueue = null; - if (q.length > 50 && q.length > this.$doc.getLength() >> 1) { - this.call("setValue", [this.$doc.getValue()]); - } else - this.emit("change", {data: q}); - }; - - }).call(WorkerClient.prototype); - - - var UIWorkerClient = function(topLevelNamespaces, mod, classname) { - this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this); - this.changeListener = this.changeListener.bind(this); - this.callbackId = 1; - this.callbacks = {}; - this.messageBuffer = []; - - var main = null; - var emitSync = false; - var sender = Object.create(EventEmitter); - var _self = this; - - this.$worker = {}; - this.$worker.terminate = function() {}; - this.$worker.postMessage = function(e) { - _self.messageBuffer.push(e); - if (main) { - if (emitSync) - setTimeout(processNext); - else - processNext(); - } - }; - this.setEmitSync = function(val) { emitSync = val; }; - - var processNext = function() { - var msg = _self.messageBuffer.shift(); - if (msg.command) - main[msg.command].apply(main, msg.args); - else if (msg.event) - sender._signal(msg.event, msg.data); - }; - - sender.postMessage = function(msg) { - _self.onMessage({data: msg}); - }; - sender.callback = function(data, callbackId) { - this.postMessage({type: "call", id: callbackId, data: data}); - }; - sender.emit = function(name, data) { - this.postMessage({type: "event", name: name, data: data}); - }; - - config.loadModule(["worker", mod], function(Main) { - main = new Main[classname](sender); - while (_self.messageBuffer.length) - processNext(); - }); - }; - - UIWorkerClient.prototype = WorkerClient.prototype; - - exports.UIWorkerClient = UIWorkerClient; - exports.WorkerClient = WorkerClient; - exports.createWorker = createWorker; - - - }); - - ace.define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"], function(acequire, exports, module) { - "use strict"; - - var Range = acequire("./range").Range; - var EventEmitter = acequire("./lib/event_emitter").EventEmitter; - var oop = acequire("./lib/oop"); - - var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) { - var _self = this; - this.length = length; - this.session = session; - this.doc = session.getDocument(); - this.mainClass = mainClass; - this.othersClass = othersClass; - this.$onUpdate = this.onUpdate.bind(this); - this.doc.on("change", this.$onUpdate); - this.$others = others; - - this.$onCursorChange = function() { - setTimeout(function() { - _self.onCursorChange(); - }); - }; - - this.$pos = pos; - var undoStack = session.getUndoManager().$undoStack || session.getUndoManager().$undostack || {length: -1}; - this.$undoStackDepth = undoStack.length; - this.setup(); - - session.selection.on("changeCursor", this.$onCursorChange); - }; - - (function() { - - oop.implement(this, EventEmitter); - this.setup = function() { - var _self = this; - var doc = this.doc; - var session = this.session; - - this.selectionBefore = session.selection.toJSON(); - if (session.selection.inMultiSelectMode) - session.selection.toSingleRange(); - - this.pos = doc.createAnchor(this.$pos.row, this.$pos.column); - var pos = this.pos; - pos.$insertRight = true; - pos.detach(); - pos.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column + this.length), this.mainClass, null, false); - this.others = []; - this.$others.forEach(function(other) { - var anchor = doc.createAnchor(other.row, other.column); - anchor.$insertRight = true; - anchor.detach(); - _self.others.push(anchor); - }); - session.setUndoSelect(false); - }; - this.showOtherMarkers = function() { - if (this.othersActive) return; - var session = this.session; - var _self = this; - this.othersActive = true; - this.others.forEach(function(anchor) { - anchor.markerId = session.addMarker(new Range(anchor.row, anchor.column, anchor.row, anchor.column+_self.length), _self.othersClass, null, false); - }); - }; - this.hideOtherMarkers = function() { - if (!this.othersActive) return; - this.othersActive = false; - for (var i = 0; i < this.others.length; i++) { - this.session.removeMarker(this.others[i].markerId); - } - }; - this.onUpdate = function(delta) { - if (this.$updating) - return this.updateAnchors(delta); - - var range = delta; - if (range.start.row !== range.end.row) return; - if (range.start.row !== this.pos.row) return; - this.$updating = true; - var lengthDiff = delta.action === "insert" ? range.end.column - range.start.column : range.start.column - range.end.column; - var inMainRange = range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1; - var distanceFromStart = range.start.column - this.pos.column; - - this.updateAnchors(delta); - - if (inMainRange) - this.length += lengthDiff; - - if (inMainRange && !this.session.$fromUndo) { - if (delta.action === 'insert') { - for (var i = this.others.length - 1; i >= 0; i--) { - var otherPos = this.others[i]; - var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; - this.doc.insertMergedLines(newPos, delta.lines); - } - } else if (delta.action === 'remove') { - for (var i = this.others.length - 1; i >= 0; i--) { - var otherPos = this.others[i]; - var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; - this.doc.remove(new Range(newPos.row, newPos.column, newPos.row, newPos.column - lengthDiff)); - } - } - } - - this.$updating = false; - this.updateMarkers(); - }; - - this.updateAnchors = function(delta) { - this.pos.onChange(delta); - for (var i = this.others.length; i--;) - this.others[i].onChange(delta); - this.updateMarkers(); - }; - - this.updateMarkers = function() { - if (this.$updating) - return; - var _self = this; - var session = this.session; - var updateMarker = function(pos, className) { - session.removeMarker(pos.markerId); - pos.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column+_self.length), className, null, false); - }; - updateMarker(this.pos, this.mainClass); - for (var i = this.others.length; i--;) - updateMarker(this.others[i], this.othersClass); - }; - - this.onCursorChange = function(event) { - if (this.$updating || !this.session) return; - var pos = this.session.selection.getCursor(); - if (pos.row === this.pos.row && pos.column >= this.pos.column && pos.column <= this.pos.column + this.length) { - this.showOtherMarkers(); - this._emit("cursorEnter", event); - } else { - this.hideOtherMarkers(); - this._emit("cursorLeave", event); - } - }; - this.detach = function() { - this.session.removeMarker(this.pos && this.pos.markerId); - this.hideOtherMarkers(); - this.doc.removeEventListener("change", this.$onUpdate); - this.session.selection.removeEventListener("changeCursor", this.$onCursorChange); - this.session.setUndoSelect(true); - this.session = null; - }; - this.cancel = function() { - if (this.$undoStackDepth === -1) - return; - var undoManager = this.session.getUndoManager(); - var undosRequired = (undoManager.$undoStack || undoManager.$undostack).length - this.$undoStackDepth; - for (var i = 0; i < undosRequired; i++) { - undoManager.undo(true); - } - if (this.selectionBefore) - this.session.selection.fromJSON(this.selectionBefore); - }; - }).call(PlaceHolder.prototype); - - - exports.PlaceHolder = PlaceHolder; - }); - - ace.define("ace/mouse/multi_select_handler",["require","exports","module","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) { - - var event = acequire("../lib/event"); - var useragent = acequire("../lib/useragent"); - function isSamePoint(p1, p2) { - return p1.row == p2.row && p1.column == p2.column; - } - - function onMouseDown(e) { - var ev = e.domEvent; - var alt = ev.altKey; - var shift = ev.shiftKey; - var ctrl = ev.ctrlKey; - var accel = e.getAccelKey(); - var button = e.getButton(); - - if (ctrl && useragent.isMac) - button = ev.button; - - if (e.editor.inMultiSelectMode && button == 2) { - e.editor.textInput.onContextMenu(e.domEvent); - return; - } - - if (!ctrl && !alt && !accel) { - if (button === 0 && e.editor.inMultiSelectMode) - e.editor.exitMultiSelectMode(); - return; - } - - if (button !== 0) - return; - - var editor = e.editor; - var selection = editor.selection; - var isMultiSelect = editor.inMultiSelectMode; - var pos = e.getDocumentPosition(); - var cursor = selection.getCursor(); - var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor)); - - var mouseX = e.x, mouseY = e.y; - var onMouseSelection = function(e) { - mouseX = e.clientX; - mouseY = e.clientY; - }; - - var session = editor.session; - var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY); - var screenCursor = screenAnchor; - - var selectionMode; - if (editor.$mouseHandler.$enableJumpToDef) { - if (ctrl && alt || accel && alt) - selectionMode = shift ? "block" : "add"; - else if (alt && editor.$blockSelectEnabled) - selectionMode = "block"; - } else { - if (accel && !alt) { - selectionMode = "add"; - if (!isMultiSelect && shift) - return; - } else if (alt && editor.$blockSelectEnabled) { - selectionMode = "block"; - } - } - - if (selectionMode && useragent.isMac && ev.ctrlKey) { - editor.$mouseHandler.cancelContextMenu(); - } - - if (selectionMode == "add") { - if (!isMultiSelect && inSelection) - return; // dragging - - if (!isMultiSelect) { - var range = selection.toOrientedRange(); - editor.addSelectionMarker(range); - } - - var oldRange = selection.rangeList.rangeAtPoint(pos); - - - editor.$blockScrolling++; - editor.inVirtualSelectionMode = true; - - if (shift) { - oldRange = null; - range = selection.ranges[0] || range; - editor.removeSelectionMarker(range); - } - editor.once("mouseup", function() { - var tmpSel = selection.toOrientedRange(); - - if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor)) - selection.substractPoint(tmpSel.cursor); - else { - if (shift) { - selection.substractPoint(range.cursor); - } else if (range) { - editor.removeSelectionMarker(range); - selection.addRange(range); - } - selection.addRange(tmpSel); - } - editor.$blockScrolling--; - editor.inVirtualSelectionMode = false; - }); - - } else if (selectionMode == "block") { - e.stop(); - editor.inVirtualSelectionMode = true; - var initialRange; - var rectSel = []; - var blockSelect = function() { - var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY); - var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column, newCursor.offsetX); - - if (isSamePoint(screenCursor, newCursor) && isSamePoint(cursor, selection.lead)) - return; - screenCursor = newCursor; - - editor.$blockScrolling++; - editor.selection.moveToPosition(cursor); - editor.renderer.scrollCursorIntoView(); - - editor.removeSelectionMarkers(rectSel); - rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor); - if (editor.$mouseHandler.$clickSelection && rectSel.length == 1 && rectSel[0].isEmpty()) - rectSel[0] = editor.$mouseHandler.$clickSelection.clone(); - rectSel.forEach(editor.addSelectionMarker, editor); - editor.updateSelectionMarkers(); - editor.$blockScrolling--; - }; - editor.$blockScrolling++; - if (isMultiSelect && !accel) { - selection.toSingleRange(); - } else if (!isMultiSelect && accel) { - initialRange = selection.toOrientedRange(); - editor.addSelectionMarker(initialRange); - } - - if (shift) - screenAnchor = session.documentToScreenPosition(selection.lead); - else - selection.moveToPosition(pos); - editor.$blockScrolling--; - - screenCursor = {row: -1, column: -1}; - - var onMouseSelectionEnd = function(e) { - clearInterval(timerId); - editor.removeSelectionMarkers(rectSel); - if (!rectSel.length) - rectSel = [selection.toOrientedRange()]; - editor.$blockScrolling++; - if (initialRange) { - editor.removeSelectionMarker(initialRange); - selection.toSingleRange(initialRange); - } - for (var i = 0; i < rectSel.length; i++) - selection.addRange(rectSel[i]); - editor.inVirtualSelectionMode = false; - editor.$mouseHandler.$clickSelection = null; - editor.$blockScrolling--; - }; - - var onSelectionInterval = blockSelect; - - event.capture(editor.container, onMouseSelection, onMouseSelectionEnd); - var timerId = setInterval(function() {onSelectionInterval();}, 20); - - return e.preventDefault(); - } - } - - - exports.onMouseDown = onMouseDown; - - }); - - ace.define("ace/commands/multi_select_commands",["require","exports","module","ace/keyboard/hash_handler"], function(acequire, exports, module) { - exports.defaultCommands = [{ - name: "addCursorAbove", - exec: function(editor) { editor.selectMoreLines(-1); }, - bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"}, - scrollIntoView: "cursor", - readOnly: true - }, { - name: "addCursorBelow", - exec: function(editor) { editor.selectMoreLines(1); }, - bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"}, - scrollIntoView: "cursor", - readOnly: true - }, { - name: "addCursorAboveSkipCurrent", - exec: function(editor) { editor.selectMoreLines(-1, true); }, - bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"}, - scrollIntoView: "cursor", - readOnly: true - }, { - name: "addCursorBelowSkipCurrent", - exec: function(editor) { editor.selectMoreLines(1, true); }, - bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"}, - scrollIntoView: "cursor", - readOnly: true - }, { - name: "selectMoreBefore", - exec: function(editor) { editor.selectMore(-1); }, - bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"}, - scrollIntoView: "cursor", - readOnly: true - }, { - name: "selectMoreAfter", - exec: function(editor) { editor.selectMore(1); }, - bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"}, - scrollIntoView: "cursor", - readOnly: true - }, { - name: "selectNextBefore", - exec: function(editor) { editor.selectMore(-1, true); }, - bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"}, - scrollIntoView: "cursor", - readOnly: true - }, { - name: "selectNextAfter", - exec: function(editor) { editor.selectMore(1, true); }, - bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"}, - scrollIntoView: "cursor", - readOnly: true - }, { - name: "splitIntoLines", - exec: function(editor) { editor.multiSelect.splitIntoLines(); }, - bindKey: {win: "Ctrl-Alt-L", mac: "Ctrl-Alt-L"}, - readOnly: true - }, { - name: "alignCursors", - exec: function(editor) { editor.alignCursors(); }, - bindKey: {win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A"}, - scrollIntoView: "cursor" - }, { - name: "findAll", - exec: function(editor) { editor.findAll(); }, - bindKey: {win: "Ctrl-Alt-K", mac: "Ctrl-Alt-G"}, - scrollIntoView: "cursor", - readOnly: true - }]; - exports.multiSelectCommands = [{ - name: "singleSelection", - bindKey: "esc", - exec: function(editor) { editor.exitMultiSelectMode(); }, - scrollIntoView: "cursor", - readOnly: true, - isAvailable: function(editor) {return editor && editor.inMultiSelectMode;} - }]; - - var HashHandler = acequire("../keyboard/hash_handler").HashHandler; - exports.keyboardHandler = new HashHandler(exports.multiSelectCommands); - - }); - - ace.define("ace/multi_select",["require","exports","module","ace/range_list","ace/range","ace/selection","ace/mouse/multi_select_handler","ace/lib/event","ace/lib/lang","ace/commands/multi_select_commands","ace/search","ace/edit_session","ace/editor","ace/config"], function(acequire, exports, module) { - - var RangeList = acequire("./range_list").RangeList; - var Range = acequire("./range").Range; - var Selection = acequire("./selection").Selection; - var onMouseDown = acequire("./mouse/multi_select_handler").onMouseDown; - var event = acequire("./lib/event"); - var lang = acequire("./lib/lang"); - var commands = acequire("./commands/multi_select_commands"); - exports.commands = commands.defaultCommands.concat(commands.multiSelectCommands); - var Search = acequire("./search").Search; - var search = new Search(); - - function find(session, needle, dir) { - search.$options.wrap = true; - search.$options.needle = needle; - search.$options.backwards = dir == -1; - return search.find(session); - } - var EditSession = acequire("./edit_session").EditSession; - (function() { - this.getSelectionMarkers = function() { - return this.$selectionMarkers; - }; - }).call(EditSession.prototype); - (function() { - this.ranges = null; - this.rangeList = null; - this.addRange = function(range, $blockChangeEvents) { - if (!range) - return; - - if (!this.inMultiSelectMode && this.rangeCount === 0) { - var oldRange = this.toOrientedRange(); - this.rangeList.add(oldRange); - this.rangeList.add(range); - if (this.rangeList.ranges.length != 2) { - this.rangeList.removeAll(); - return $blockChangeEvents || this.fromOrientedRange(range); - } - this.rangeList.removeAll(); - this.rangeList.add(oldRange); - this.$onAddRange(oldRange); - } - - if (!range.cursor) - range.cursor = range.end; - - var removed = this.rangeList.add(range); - - this.$onAddRange(range); - - if (removed.length) - this.$onRemoveRange(removed); - - if (this.rangeCount > 1 && !this.inMultiSelectMode) { - this._signal("multiSelect"); - this.inMultiSelectMode = true; - this.session.$undoSelect = false; - this.rangeList.attach(this.session); - } - - return $blockChangeEvents || this.fromOrientedRange(range); - }; - - this.toSingleRange = function(range) { - range = range || this.ranges[0]; - var removed = this.rangeList.removeAll(); - if (removed.length) - this.$onRemoveRange(removed); - - range && this.fromOrientedRange(range); - }; - this.substractPoint = function(pos) { - var removed = this.rangeList.substractPoint(pos); - if (removed) { - this.$onRemoveRange(removed); - return removed[0]; - } - }; - this.mergeOverlappingRanges = function() { - var removed = this.rangeList.merge(); - if (removed.length) - this.$onRemoveRange(removed); - else if(this.ranges[0]) - this.fromOrientedRange(this.ranges[0]); - }; - - this.$onAddRange = function(range) { - this.rangeCount = this.rangeList.ranges.length; - this.ranges.unshift(range); - this._signal("addRange", {range: range}); - }; - - this.$onRemoveRange = function(removed) { - this.rangeCount = this.rangeList.ranges.length; - if (this.rangeCount == 1 && this.inMultiSelectMode) { - var lastRange = this.rangeList.ranges.pop(); - removed.push(lastRange); - this.rangeCount = 0; - } - - for (var i = removed.length; i--; ) { - var index = this.ranges.indexOf(removed[i]); - this.ranges.splice(index, 1); - } - - this._signal("removeRange", {ranges: removed}); - - if (this.rangeCount === 0 && this.inMultiSelectMode) { - this.inMultiSelectMode = false; - this._signal("singleSelect"); - this.session.$undoSelect = true; - this.rangeList.detach(this.session); - } - - lastRange = lastRange || this.ranges[0]; - if (lastRange && !lastRange.isEqual(this.getRange())) - this.fromOrientedRange(lastRange); - }; - this.$initRangeList = function() { - if (this.rangeList) - return; - - this.rangeList = new RangeList(); - this.ranges = []; - this.rangeCount = 0; - }; - this.getAllRanges = function() { - return this.rangeCount ? this.rangeList.ranges.concat() : [this.getRange()]; - }; - - this.splitIntoLines = function () { - if (this.rangeCount > 1) { - var ranges = this.rangeList.ranges; - var lastRange = ranges[ranges.length - 1]; - var range = Range.fromPoints(ranges[0].start, lastRange.end); - - this.toSingleRange(); - this.setSelectionRange(range, lastRange.cursor == lastRange.start); - } else { - var range = this.getRange(); - var isBackwards = this.isBackwards(); - var startRow = range.start.row; - var endRow = range.end.row; - if (startRow == endRow) { - if (isBackwards) - var start = range.end, end = range.start; - else - var start = range.start, end = range.end; - - this.addRange(Range.fromPoints(end, end)); - this.addRange(Range.fromPoints(start, start)); - return; - } - - var rectSel = []; - var r = this.getLineRange(startRow, true); - r.start.column = range.start.column; - rectSel.push(r); - - for (var i = startRow + 1; i < endRow; i++) - rectSel.push(this.getLineRange(i, true)); - - r = this.getLineRange(endRow, true); - r.end.column = range.end.column; - rectSel.push(r); - - rectSel.forEach(this.addRange, this); - } - }; - this.toggleBlockSelection = function () { - if (this.rangeCount > 1) { - var ranges = this.rangeList.ranges; - var lastRange = ranges[ranges.length - 1]; - var range = Range.fromPoints(ranges[0].start, lastRange.end); - - this.toSingleRange(); - this.setSelectionRange(range, lastRange.cursor == lastRange.start); - } else { - var cursor = this.session.documentToScreenPosition(this.selectionLead); - var anchor = this.session.documentToScreenPosition(this.selectionAnchor); - - var rectSel = this.rectangularRangeBlock(cursor, anchor); - rectSel.forEach(this.addRange, this); - } - }; - this.rectangularRangeBlock = function(screenCursor, screenAnchor, includeEmptyLines) { - var rectSel = []; - - var xBackwards = screenCursor.column < screenAnchor.column; - if (xBackwards) { - var startColumn = screenCursor.column; - var endColumn = screenAnchor.column; - var startOffsetX = screenCursor.offsetX; - var endOffsetX = screenAnchor.offsetX; - } else { - var startColumn = screenAnchor.column; - var endColumn = screenCursor.column; - var startOffsetX = screenAnchor.offsetX; - var endOffsetX = screenCursor.offsetX; - } - - var yBackwards = screenCursor.row < screenAnchor.row; - if (yBackwards) { - var startRow = screenCursor.row; - var endRow = screenAnchor.row; - } else { - var startRow = screenAnchor.row; - var endRow = screenCursor.row; - } - - if (startColumn < 0) - startColumn = 0; - if (startRow < 0) - startRow = 0; - - if (startRow == endRow) - includeEmptyLines = true; - - for (var row = startRow; row <= endRow; row++) { - var range = Range.fromPoints( - this.session.screenToDocumentPosition(row, startColumn, startOffsetX), - this.session.screenToDocumentPosition(row, endColumn, endOffsetX) - ); - if (range.isEmpty()) { - if (docEnd && isSamePoint(range.end, docEnd)) - break; - var docEnd = range.end; - } - range.cursor = xBackwards ? range.start : range.end; - rectSel.push(range); - } - - if (yBackwards) - rectSel.reverse(); - - if (!includeEmptyLines) { - var end = rectSel.length - 1; - while (rectSel[end].isEmpty() && end > 0) - end--; - if (end > 0) { - var start = 0; - while (rectSel[start].isEmpty()) - start++; - } - for (var i = end; i >= start; i--) { - if (rectSel[i].isEmpty()) - rectSel.splice(i, 1); - } - } - - return rectSel; - }; - }).call(Selection.prototype); - var Editor = acequire("./editor").Editor; - (function() { - this.updateSelectionMarkers = function() { - this.renderer.updateCursor(); - this.renderer.updateBackMarkers(); - }; - this.addSelectionMarker = function(orientedRange) { - if (!orientedRange.cursor) - orientedRange.cursor = orientedRange.end; - - var style = this.getSelectionStyle(); - orientedRange.marker = this.session.addMarker(orientedRange, "ace_selection", style); - - this.session.$selectionMarkers.push(orientedRange); - this.session.selectionMarkerCount = this.session.$selectionMarkers.length; - return orientedRange; - }; - this.removeSelectionMarker = function(range) { - if (!range.marker) - return; - this.session.removeMarker(range.marker); - var index = this.session.$selectionMarkers.indexOf(range); - if (index != -1) - this.session.$selectionMarkers.splice(index, 1); - this.session.selectionMarkerCount = this.session.$selectionMarkers.length; - }; - - this.removeSelectionMarkers = function(ranges) { - var markerList = this.session.$selectionMarkers; - for (var i = ranges.length; i--; ) { - var range = ranges[i]; - if (!range.marker) - continue; - this.session.removeMarker(range.marker); - var index = markerList.indexOf(range); - if (index != -1) - markerList.splice(index, 1); - } - this.session.selectionMarkerCount = markerList.length; - }; - - this.$onAddRange = function(e) { - this.addSelectionMarker(e.range); - this.renderer.updateCursor(); - this.renderer.updateBackMarkers(); - }; - - this.$onRemoveRange = function(e) { - this.removeSelectionMarkers(e.ranges); - this.renderer.updateCursor(); - this.renderer.updateBackMarkers(); - }; - - this.$onMultiSelect = function(e) { - if (this.inMultiSelectMode) - return; - this.inMultiSelectMode = true; - - this.setStyle("ace_multiselect"); - this.keyBinding.addKeyboardHandler(commands.keyboardHandler); - this.commands.setDefaultHandler("exec", this.$onMultiSelectExec); - - this.renderer.updateCursor(); - this.renderer.updateBackMarkers(); - }; - - this.$onSingleSelect = function(e) { - if (this.session.multiSelect.inVirtualMode) - return; - this.inMultiSelectMode = false; - - this.unsetStyle("ace_multiselect"); - this.keyBinding.removeKeyboardHandler(commands.keyboardHandler); - - this.commands.removeDefaultHandler("exec", this.$onMultiSelectExec); - this.renderer.updateCursor(); - this.renderer.updateBackMarkers(); - this._emit("changeSelection"); - }; - - this.$onMultiSelectExec = function(e) { - var command = e.command; - var editor = e.editor; - if (!editor.multiSelect) - return; - if (!command.multiSelectAction) { - var result = command.exec(editor, e.args || {}); - editor.multiSelect.addRange(editor.multiSelect.toOrientedRange()); - editor.multiSelect.mergeOverlappingRanges(); - } else if (command.multiSelectAction == "forEach") { - result = editor.forEachSelection(command, e.args); - } else if (command.multiSelectAction == "forEachLine") { - result = editor.forEachSelection(command, e.args, true); - } else if (command.multiSelectAction == "single") { - editor.exitMultiSelectMode(); - result = command.exec(editor, e.args || {}); - } else { - result = command.multiSelectAction(editor, e.args || {}); - } - return result; - }; - this.forEachSelection = function(cmd, args, options) { - if (this.inVirtualSelectionMode) - return; - var keepOrder = options && options.keepOrder; - var $byLines = options == true || options && options.$byLines; - var session = this.session; - var selection = this.selection; - var rangeList = selection.rangeList; - var ranges = (keepOrder ? selection : rangeList).ranges; - var result; - - if (!ranges.length) - return cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {}); - - var reg = selection._eventRegistry; - selection._eventRegistry = {}; - - var tmpSel = new Selection(session); - this.inVirtualSelectionMode = true; - for (var i = ranges.length; i--;) { - if ($byLines) { - while (i > 0 && ranges[i].start.row == ranges[i - 1].end.row) - i--; - } - tmpSel.fromOrientedRange(ranges[i]); - tmpSel.index = i; - this.selection = session.selection = tmpSel; - var cmdResult = cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {}); - if (!result && cmdResult !== undefined) - result = cmdResult; - tmpSel.toOrientedRange(ranges[i]); - } - tmpSel.detach(); - - this.selection = session.selection = selection; - this.inVirtualSelectionMode = false; - selection._eventRegistry = reg; - selection.mergeOverlappingRanges(); - - var anim = this.renderer.$scrollAnimation; - this.onCursorChange(); - this.onSelectionChange(); - if (anim && anim.from == anim.to) - this.renderer.animateScrolling(anim.from); - - return result; - }; - this.exitMultiSelectMode = function() { - if (!this.inMultiSelectMode || this.inVirtualSelectionMode) - return; - this.multiSelect.toSingleRange(); - }; - - this.getSelectedText = function() { - var text = ""; - if (this.inMultiSelectMode && !this.inVirtualSelectionMode) { - var ranges = this.multiSelect.rangeList.ranges; - var buf = []; - for (var i = 0; i < ranges.length; i++) { - buf.push(this.session.getTextRange(ranges[i])); - } - var nl = this.session.getDocument().getNewLineCharacter(); - text = buf.join(nl); - if (text.length == (buf.length - 1) * nl.length) - text = ""; - } else if (!this.selection.isEmpty()) { - text = this.session.getTextRange(this.getSelectionRange()); - } - return text; - }; - - this.$checkMultiselectChange = function(e, anchor) { - if (this.inMultiSelectMode && !this.inVirtualSelectionMode) { - var range = this.multiSelect.ranges[0]; - if (this.multiSelect.isEmpty() && anchor == this.multiSelect.anchor) - return; - var pos = anchor == this.multiSelect.anchor - ? range.cursor == range.start ? range.end : range.start - : range.cursor; - if (pos.row != anchor.row - || this.session.$clipPositionToDocument(pos.row, pos.column).column != anchor.column) - this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange()); - } - }; - this.findAll = function(needle, options, additive) { - options = options || {}; - options.needle = needle || options.needle; - if (options.needle == undefined) { - var range = this.selection.isEmpty() - ? this.selection.getWordRange() - : this.selection.getRange(); - options.needle = this.session.getTextRange(range); - } - this.$search.set(options); - - var ranges = this.$search.findAll(this.session); - if (!ranges.length) - return 0; - - this.$blockScrolling += 1; - var selection = this.multiSelect; - - if (!additive) - selection.toSingleRange(ranges[0]); - - for (var i = ranges.length; i--; ) - selection.addRange(ranges[i], true); - if (range && selection.rangeList.rangeAtPoint(range.start)) - selection.addRange(range, true); - - this.$blockScrolling -= 1; - - return ranges.length; - }; - this.selectMoreLines = function(dir, skip) { - var range = this.selection.toOrientedRange(); - var isBackwards = range.cursor == range.end; - - var screenLead = this.session.documentToScreenPosition(range.cursor); - if (this.selection.$desiredColumn) - screenLead.column = this.selection.$desiredColumn; - - var lead = this.session.screenToDocumentPosition(screenLead.row + dir, screenLead.column); - - if (!range.isEmpty()) { - var screenAnchor = this.session.documentToScreenPosition(isBackwards ? range.end : range.start); - var anchor = this.session.screenToDocumentPosition(screenAnchor.row + dir, screenAnchor.column); - } else { - var anchor = lead; - } - - if (isBackwards) { - var newRange = Range.fromPoints(lead, anchor); - newRange.cursor = newRange.start; - } else { - var newRange = Range.fromPoints(anchor, lead); - newRange.cursor = newRange.end; - } - - newRange.desiredColumn = screenLead.column; - if (!this.selection.inMultiSelectMode) { - this.selection.addRange(range); - } else { - if (skip) - var toRemove = range.cursor; - } - - this.selection.addRange(newRange); - if (toRemove) - this.selection.substractPoint(toRemove); - }; - this.transposeSelections = function(dir) { - var session = this.session; - var sel = session.multiSelect; - var all = sel.ranges; - - for (var i = all.length; i--; ) { - var range = all[i]; - if (range.isEmpty()) { - var tmp = session.getWordRange(range.start.row, range.start.column); - range.start.row = tmp.start.row; - range.start.column = tmp.start.column; - range.end.row = tmp.end.row; - range.end.column = tmp.end.column; - } - } - sel.mergeOverlappingRanges(); - - var words = []; - for (var i = all.length; i--; ) { - var range = all[i]; - words.unshift(session.getTextRange(range)); - } - - if (dir < 0) - words.unshift(words.pop()); - else - words.push(words.shift()); - - for (var i = all.length; i--; ) { - var range = all[i]; - var tmp = range.clone(); - session.replace(range, words[i]); - range.start.row = tmp.start.row; - range.start.column = tmp.start.column; - } - }; - this.selectMore = function(dir, skip, stopAtFirst) { - var session = this.session; - var sel = session.multiSelect; - - var range = sel.toOrientedRange(); - if (range.isEmpty()) { - range = session.getWordRange(range.start.row, range.start.column); - range.cursor = dir == -1 ? range.start : range.end; - this.multiSelect.addRange(range); - if (stopAtFirst) - return; - } - var needle = session.getTextRange(range); - - var newRange = find(session, needle, dir); - if (newRange) { - newRange.cursor = dir == -1 ? newRange.start : newRange.end; - this.$blockScrolling += 1; - this.session.unfold(newRange); - this.multiSelect.addRange(newRange); - this.$blockScrolling -= 1; - this.renderer.scrollCursorIntoView(null, 0.5); - } - if (skip) - this.multiSelect.substractPoint(range.cursor); - }; - this.alignCursors = function() { - var session = this.session; - var sel = session.multiSelect; - var ranges = sel.ranges; - var row = -1; - var sameRowRanges = ranges.filter(function(r) { - if (r.cursor.row == row) - return true; - row = r.cursor.row; - }); - - if (!ranges.length || sameRowRanges.length == ranges.length - 1) { - var range = this.selection.getRange(); - var fr = range.start.row, lr = range.end.row; - var guessRange = fr == lr; - if (guessRange) { - var max = this.session.getLength(); - var line; - do { - line = this.session.getLine(lr); - } while (/[=:]/.test(line) && ++lr < max); - do { - line = this.session.getLine(fr); - } while (/[=:]/.test(line) && --fr > 0); - - if (fr < 0) fr = 0; - if (lr >= max) lr = max - 1; - } - var lines = this.session.removeFullLines(fr, lr); - lines = this.$reAlignText(lines, guessRange); - this.session.insert({row: fr, column: 0}, lines.join("\n") + "\n"); - if (!guessRange) { - range.start.column = 0; - range.end.column = lines[lines.length - 1].length; - } - this.selection.setRange(range); - } else { - sameRowRanges.forEach(function(r) { - sel.substractPoint(r.cursor); - }); - - var maxCol = 0; - var minSpace = Infinity; - var spaceOffsets = ranges.map(function(r) { - var p = r.cursor; - var line = session.getLine(p.row); - var spaceOffset = line.substr(p.column).search(/\S/g); - if (spaceOffset == -1) - spaceOffset = 0; - - if (p.column > maxCol) - maxCol = p.column; - if (spaceOffset < minSpace) - minSpace = spaceOffset; - return spaceOffset; - }); - ranges.forEach(function(r, i) { - var p = r.cursor; - var l = maxCol - p.column; - var d = spaceOffsets[i] - minSpace; - if (l > d) - session.insert(p, lang.stringRepeat(" ", l - d)); - else - session.remove(new Range(p.row, p.column, p.row, p.column - l + d)); - - r.start.column = r.end.column = maxCol; - r.start.row = r.end.row = p.row; - r.cursor = r.end; - }); - sel.fromOrientedRange(ranges[0]); - this.renderer.updateCursor(); - this.renderer.updateBackMarkers(); - } - }; - - this.$reAlignText = function(lines, forceLeft) { - var isLeftAligned = true, isRightAligned = true; - var startW, textW, endW; - - return lines.map(function(line) { - var m = line.match(/(\s*)(.*?)(\s*)([=:].*)/); - if (!m) - return [line]; - - if (startW == null) { - startW = m[1].length; - textW = m[2].length; - endW = m[3].length; - return m; - } - - if (startW + textW + endW != m[1].length + m[2].length + m[3].length) - isRightAligned = false; - if (startW != m[1].length) - isLeftAligned = false; - - if (startW > m[1].length) - startW = m[1].length; - if (textW < m[2].length) - textW = m[2].length; - if (endW > m[3].length) - endW = m[3].length; - - return m; - }).map(forceLeft ? alignLeft : - isLeftAligned ? isRightAligned ? alignRight : alignLeft : unAlign); - - function spaces(n) { - return lang.stringRepeat(" ", n); - } - - function alignLeft(m) { - return !m[2] ? m[0] : spaces(startW) + m[2] - + spaces(textW - m[2].length + endW) - + m[4].replace(/^([=:])\s+/, "$1 "); - } - function alignRight(m) { - return !m[2] ? m[0] : spaces(startW + textW - m[2].length) + m[2] - + spaces(endW, " ") - + m[4].replace(/^([=:])\s+/, "$1 "); - } - function unAlign(m) { - return !m[2] ? m[0] : spaces(startW) + m[2] - + spaces(endW) - + m[4].replace(/^([=:])\s+/, "$1 "); - } - }; - }).call(Editor.prototype); - - - function isSamePoint(p1, p2) { - return p1.row == p2.row && p1.column == p2.column; - } - exports.onSessionChange = function(e) { - var session = e.session; - if (session && !session.multiSelect) { - session.$selectionMarkers = []; - session.selection.$initRangeList(); - session.multiSelect = session.selection; - } - this.multiSelect = session && session.multiSelect; - - var oldSession = e.oldSession; - if (oldSession) { - oldSession.multiSelect.off("addRange", this.$onAddRange); - oldSession.multiSelect.off("removeRange", this.$onRemoveRange); - oldSession.multiSelect.off("multiSelect", this.$onMultiSelect); - oldSession.multiSelect.off("singleSelect", this.$onSingleSelect); - oldSession.multiSelect.lead.off("change", this.$checkMultiselectChange); - oldSession.multiSelect.anchor.off("change", this.$checkMultiselectChange); - } - - if (session) { - session.multiSelect.on("addRange", this.$onAddRange); - session.multiSelect.on("removeRange", this.$onRemoveRange); - session.multiSelect.on("multiSelect", this.$onMultiSelect); - session.multiSelect.on("singleSelect", this.$onSingleSelect); - session.multiSelect.lead.on("change", this.$checkMultiselectChange); - session.multiSelect.anchor.on("change", this.$checkMultiselectChange); - } - - if (session && this.inMultiSelectMode != session.selection.inMultiSelectMode) { - if (session.selection.inMultiSelectMode) - this.$onMultiSelect(); - else - this.$onSingleSelect(); - } - }; - function MultiSelect(editor) { - if (editor.$multiselectOnSessionChange) - return; - editor.$onAddRange = editor.$onAddRange.bind(editor); - editor.$onRemoveRange = editor.$onRemoveRange.bind(editor); - editor.$onMultiSelect = editor.$onMultiSelect.bind(editor); - editor.$onSingleSelect = editor.$onSingleSelect.bind(editor); - editor.$multiselectOnSessionChange = exports.onSessionChange.bind(editor); - editor.$checkMultiselectChange = editor.$checkMultiselectChange.bind(editor); - - editor.$multiselectOnSessionChange(editor); - editor.on("changeSession", editor.$multiselectOnSessionChange); - - editor.on("mousedown", onMouseDown); - editor.commands.addCommands(commands.defaultCommands); - - addAltCursorListeners(editor); - } - - function addAltCursorListeners(editor){ - var el = editor.textInput.getElement(); - var altCursor = false; - event.addListener(el, "keydown", function(e) { - var altDown = e.keyCode == 18 && !(e.ctrlKey || e.shiftKey || e.metaKey); - if (editor.$blockSelectEnabled && altDown) { - if (!altCursor) { - editor.renderer.setMouseCursor("crosshair"); - altCursor = true; - } - } else if (altCursor) { - reset(); - } - }); - - event.addListener(el, "keyup", reset); - event.addListener(el, "blur", reset); - function reset(e) { - if (altCursor) { - editor.renderer.setMouseCursor(""); - altCursor = false; - } - } - } - - exports.MultiSelect = MultiSelect; - - - acequire("./config").defineOptions(Editor.prototype, "editor", { - enableMultiselect: { - set: function(val) { - MultiSelect(this); - if (val) { - this.on("changeSession", this.$multiselectOnSessionChange); - this.on("mousedown", onMouseDown); - } else { - this.off("changeSession", this.$multiselectOnSessionChange); - this.off("mousedown", onMouseDown); - } - }, - value: true - }, - enableBlockSelect: { - set: function(val) { - this.$blockSelectEnabled = val; - }, - value: true - } - }); - - - - }); - - ace.define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"], function(acequire, exports, module) { - "use strict"; - - var Range = acequire("../../range").Range; - - var FoldMode = exports.FoldMode = function() {}; - - (function() { - - this.foldingStartMarker = null; - this.foldingStopMarker = null; - this.getFoldWidget = function(session, foldStyle, row) { - var line = session.getLine(row); - if (this.foldingStartMarker.test(line)) - return "start"; - if (foldStyle == "markbeginend" - && this.foldingStopMarker - && this.foldingStopMarker.test(line)) - return "end"; - return ""; - }; - - this.getFoldWidgetRange = function(session, foldStyle, row) { - return null; - }; - - this.indentationBlock = function(session, row, column) { - var re = /\S/; - var line = session.getLine(row); - var startLevel = line.search(re); - if (startLevel == -1) - return; - - var startColumn = column || line.length; - var maxRow = session.getLength(); - var startRow = row; - var endRow = row; - - while (++row < maxRow) { - var level = session.getLine(row).search(re); - - if (level == -1) - continue; - - if (level <= startLevel) - break; - - endRow = row; - } - - if (endRow > startRow) { - var endColumn = session.getLine(endRow).length; - return new Range(startRow, startColumn, endRow, endColumn); - } - }; - - this.openingBracketBlock = function(session, bracket, row, column, typeRe) { - var start = {row: row, column: column + 1}; - var end = session.$findClosingBracket(bracket, start, typeRe); - if (!end) - return; - - var fw = session.foldWidgets[end.row]; - if (fw == null) - fw = session.getFoldWidget(end.row); - - if (fw == "start" && end.row > start.row) { - end.row --; - end.column = session.getLine(end.row).length; - } - return Range.fromPoints(start, end); - }; - - this.closingBracketBlock = function(session, bracket, row, column, typeRe) { - var end = {row: row, column: column}; - var start = session.$findOpeningBracket(bracket, end); - - if (!start) - return; - - start.column++; - end.column--; - - return Range.fromPoints(start, end); - }; - }).call(FoldMode.prototype); - - }); - - ace.define("ace/theme/textmate",["require","exports","module","ace/lib/dom"], function(acequire, exports, module) { - "use strict"; - - exports.isDark = false; - exports.cssClass = "ace-tm"; - exports.cssText = ".ace-tm .ace_gutter {\ - background: #f0f0f0;\ - color: #333;\ - }\ - .ace-tm .ace_print-margin {\ - width: 1px;\ - background: #e8e8e8;\ - }\ - .ace-tm .ace_fold {\ - background-color: #6B72E6;\ - }\ - .ace-tm {\ - background-color: #FFFFFF;\ - color: black;\ - }\ - .ace-tm .ace_cursor {\ - color: black;\ - }\ - .ace-tm .ace_invisible {\ - color: rgb(191, 191, 191);\ - }\ - .ace-tm .ace_storage,\ - .ace-tm .ace_keyword {\ - color: blue;\ - }\ - .ace-tm .ace_constant {\ - color: rgb(197, 6, 11);\ - }\ - .ace-tm .ace_constant.ace_buildin {\ - color: rgb(88, 72, 246);\ - }\ - .ace-tm .ace_constant.ace_language {\ - color: rgb(88, 92, 246);\ - }\ - .ace-tm .ace_constant.ace_library {\ - color: rgb(6, 150, 14);\ - }\ - .ace-tm .ace_invalid {\ - background-color: rgba(255, 0, 0, 0.1);\ - color: red;\ - }\ - .ace-tm .ace_support.ace_function {\ - color: rgb(60, 76, 114);\ - }\ - .ace-tm .ace_support.ace_constant {\ - color: rgb(6, 150, 14);\ - }\ - .ace-tm .ace_support.ace_type,\ - .ace-tm .ace_support.ace_class {\ - color: rgb(109, 121, 222);\ - }\ - .ace-tm .ace_keyword.ace_operator {\ - color: rgb(104, 118, 135);\ - }\ - .ace-tm .ace_string {\ - color: rgb(3, 106, 7);\ - }\ - .ace-tm .ace_comment {\ - color: rgb(76, 136, 107);\ - }\ - .ace-tm .ace_comment.ace_doc {\ - color: rgb(0, 102, 255);\ - }\ - .ace-tm .ace_comment.ace_doc.ace_tag {\ - color: rgb(128, 159, 191);\ - }\ - .ace-tm .ace_constant.ace_numeric {\ - color: rgb(0, 0, 205);\ - }\ - .ace-tm .ace_variable {\ - color: rgb(49, 132, 149);\ - }\ - .ace-tm .ace_xml-pe {\ - color: rgb(104, 104, 91);\ - }\ - .ace-tm .ace_entity.ace_name.ace_function {\ - color: #0000A2;\ - }\ - .ace-tm .ace_heading {\ - color: rgb(12, 7, 255);\ - }\ - .ace-tm .ace_list {\ - color:rgb(185, 6, 144);\ - }\ - .ace-tm .ace_meta.ace_tag {\ - color:rgb(0, 22, 142);\ - }\ - .ace-tm .ace_string.ace_regex {\ - color: rgb(255, 0, 0)\ - }\ - .ace-tm .ace_marker-layer .ace_selection {\ - background: rgb(181, 213, 255);\ - }\ - .ace-tm.ace_multiselect .ace_selection.ace_start {\ - box-shadow: 0 0 3px 0px white;\ - }\ - .ace-tm .ace_marker-layer .ace_step {\ - background: rgb(252, 255, 0);\ - }\ - .ace-tm .ace_marker-layer .ace_stack {\ - background: rgb(164, 229, 101);\ - }\ - .ace-tm .ace_marker-layer .ace_bracket {\ - margin: -1px 0 0 -1px;\ - border: 1px solid rgb(192, 192, 192);\ - }\ - .ace-tm .ace_marker-layer .ace_active-line {\ - background: rgba(0, 0, 0, 0.07);\ - }\ - .ace-tm .ace_gutter-active-line {\ - background-color : #dcdcdc;\ - }\ - .ace-tm .ace_marker-layer .ace_selected-word {\ - background: rgb(250, 250, 255);\ - border: 1px solid rgb(200, 200, 250);\ - }\ - .ace-tm .ace_indent-guide {\ - background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\ - }\ - "; - - var dom = acequire("../lib/dom"); - dom.importCssString(exports.cssText, exports.cssClass); - }); - - ace.define("ace/line_widgets",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/range"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("./lib/oop"); - var dom = acequire("./lib/dom"); - var Range = acequire("./range").Range; - - - function LineWidgets(session) { - this.session = session; - this.session.widgetManager = this; - this.session.getRowLength = this.getRowLength; - this.session.$getWidgetScreenLength = this.$getWidgetScreenLength; - this.updateOnChange = this.updateOnChange.bind(this); - this.renderWidgets = this.renderWidgets.bind(this); - this.measureWidgets = this.measureWidgets.bind(this); - this.session._changedWidgets = []; - this.$onChangeEditor = this.$onChangeEditor.bind(this); - - this.session.on("change", this.updateOnChange); - this.session.on("changeFold", this.updateOnFold); - this.session.on("changeEditor", this.$onChangeEditor); - } - - (function() { - this.getRowLength = function(row) { - var h; - if (this.lineWidgets) - h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0; - else - h = 0; - if (!this.$useWrapMode || !this.$wrapData[row]) { - return 1 + h; - } else { - return this.$wrapData[row].length + 1 + h; - } - }; - - this.$getWidgetScreenLength = function() { - var screenRows = 0; - this.lineWidgets.forEach(function(w){ - if (w && w.rowCount && !w.hidden) - screenRows += w.rowCount; - }); - return screenRows; - }; - - this.$onChangeEditor = function(e) { - this.attach(e.editor); - }; - - this.attach = function(editor) { - if (editor && editor.widgetManager && editor.widgetManager != this) - editor.widgetManager.detach(); - - if (this.editor == editor) - return; - - this.detach(); - this.editor = editor; - - if (editor) { - editor.widgetManager = this; - editor.renderer.on("beforeRender", this.measureWidgets); - editor.renderer.on("afterRender", this.renderWidgets); - } - }; - this.detach = function(e) { - var editor = this.editor; - if (!editor) - return; - - this.editor = null; - editor.widgetManager = null; - - editor.renderer.off("beforeRender", this.measureWidgets); - editor.renderer.off("afterRender", this.renderWidgets); - var lineWidgets = this.session.lineWidgets; - lineWidgets && lineWidgets.forEach(function(w) { - if (w && w.el && w.el.parentNode) { - w._inDocument = false; - w.el.parentNode.removeChild(w.el); - } - }); - }; - - this.updateOnFold = function(e, session) { - var lineWidgets = session.lineWidgets; - if (!lineWidgets || !e.action) - return; - var fold = e.data; - var start = fold.start.row; - var end = fold.end.row; - var hide = e.action == "add"; - for (var i = start + 1; i < end; i++) { - if (lineWidgets[i]) - lineWidgets[i].hidden = hide; - } - if (lineWidgets[end]) { - if (hide) { - if (!lineWidgets[start]) - lineWidgets[start] = lineWidgets[end]; - else - lineWidgets[end].hidden = hide; - } else { - if (lineWidgets[start] == lineWidgets[end]) - lineWidgets[start] = undefined; - lineWidgets[end].hidden = hide; - } - } - }; - - this.updateOnChange = function(delta) { - var lineWidgets = this.session.lineWidgets; - if (!lineWidgets) return; - - var startRow = delta.start.row; - var len = delta.end.row - startRow; - - if (len === 0) { - } else if (delta.action == 'remove') { - var removed = lineWidgets.splice(startRow + 1, len); - removed.forEach(function(w) { - w && this.removeLineWidget(w); - }, this); - this.$updateRows(); - } else { - var args = new Array(len); - args.unshift(startRow, 0); - lineWidgets.splice.apply(lineWidgets, args); - this.$updateRows(); - } - }; - - this.$updateRows = function() { - var lineWidgets = this.session.lineWidgets; - if (!lineWidgets) return; - var noWidgets = true; - lineWidgets.forEach(function(w, i) { - if (w) { - noWidgets = false; - w.row = i; - while (w.$oldWidget) { - w.$oldWidget.row = i; - w = w.$oldWidget; - } - } - }); - if (noWidgets) - this.session.lineWidgets = null; - }; - - this.addLineWidget = function(w) { - if (!this.session.lineWidgets) - this.session.lineWidgets = new Array(this.session.getLength()); - - var old = this.session.lineWidgets[w.row]; - if (old) { - w.$oldWidget = old; - if (old.el && old.el.parentNode) { - old.el.parentNode.removeChild(old.el); - old._inDocument = false; - } - } - - this.session.lineWidgets[w.row] = w; - - w.session = this.session; - - var renderer = this.editor.renderer; - if (w.html && !w.el) { - w.el = dom.createElement("div"); - w.el.innerHTML = w.html; - } - if (w.el) { - dom.addCssClass(w.el, "ace_lineWidgetContainer"); - w.el.style.position = "absolute"; - w.el.style.zIndex = 5; - renderer.container.appendChild(w.el); - w._inDocument = true; - } - - if (!w.coverGutter) { - w.el.style.zIndex = 3; - } - if (w.pixelHeight == null) { - w.pixelHeight = w.el.offsetHeight; - } - if (w.rowCount == null) { - w.rowCount = w.pixelHeight / renderer.layerConfig.lineHeight; - } - - var fold = this.session.getFoldAt(w.row, 0); - w.$fold = fold; - if (fold) { - var lineWidgets = this.session.lineWidgets; - if (w.row == fold.end.row && !lineWidgets[fold.start.row]) - lineWidgets[fold.start.row] = w; - else - w.hidden = true; - } - - this.session._emit("changeFold", {data:{start:{row: w.row}}}); - - this.$updateRows(); - this.renderWidgets(null, renderer); - this.onWidgetChanged(w); - return w; - }; - - this.removeLineWidget = function(w) { - w._inDocument = false; - w.session = null; - if (w.el && w.el.parentNode) - w.el.parentNode.removeChild(w.el); - if (w.editor && w.editor.destroy) try { - w.editor.destroy(); - } catch(e){} - if (this.session.lineWidgets) { - var w1 = this.session.lineWidgets[w.row]; - if (w1 == w) { - this.session.lineWidgets[w.row] = w.$oldWidget; - if (w.$oldWidget) - this.onWidgetChanged(w.$oldWidget); - } else { - while (w1) { - if (w1.$oldWidget == w) { - w1.$oldWidget = w.$oldWidget; - break; - } - w1 = w1.$oldWidget; - } - } - } - this.session._emit("changeFold", {data:{start:{row: w.row}}}); - this.$updateRows(); - }; - - this.getWidgetsAtRow = function(row) { - var lineWidgets = this.session.lineWidgets; - var w = lineWidgets && lineWidgets[row]; - var list = []; - while (w) { - list.push(w); - w = w.$oldWidget; - } - return list; - }; - - this.onWidgetChanged = function(w) { - this.session._changedWidgets.push(w); - this.editor && this.editor.renderer.updateFull(); - }; - - this.measureWidgets = function(e, renderer) { - var changedWidgets = this.session._changedWidgets; - var config = renderer.layerConfig; - - if (!changedWidgets || !changedWidgets.length) return; - var min = Infinity; - for (var i = 0; i < changedWidgets.length; i++) { - var w = changedWidgets[i]; - if (!w || !w.el) continue; - if (w.session != this.session) continue; - if (!w._inDocument) { - if (this.session.lineWidgets[w.row] != w) - continue; - w._inDocument = true; - renderer.container.appendChild(w.el); - } - - w.h = w.el.offsetHeight; - - if (!w.fixedWidth) { - w.w = w.el.offsetWidth; - w.screenWidth = Math.ceil(w.w / config.characterWidth); - } - - var rowCount = w.h / config.lineHeight; - if (w.coverLine) { - rowCount -= this.session.getRowLineCount(w.row); - if (rowCount < 0) - rowCount = 0; - } - if (w.rowCount != rowCount) { - w.rowCount = rowCount; - if (w.row < min) - min = w.row; - } - } - if (min != Infinity) { - this.session._emit("changeFold", {data:{start:{row: min}}}); - this.session.lineWidgetWidth = null; - } - this.session._changedWidgets = []; - }; - - this.renderWidgets = function(e, renderer) { - var config = renderer.layerConfig; - var lineWidgets = this.session.lineWidgets; - if (!lineWidgets) - return; - var first = Math.min(this.firstRow, config.firstRow); - var last = Math.max(this.lastRow, config.lastRow, lineWidgets.length); - - while (first > 0 && !lineWidgets[first]) - first--; - - this.firstRow = config.firstRow; - this.lastRow = config.lastRow; - - renderer.$cursorLayer.config = config; - for (var i = first; i <= last; i++) { - var w = lineWidgets[i]; - if (!w || !w.el) continue; - if (w.hidden) { - w.el.style.top = -100 - (w.pixelHeight || 0) + "px"; - continue; - } - if (!w._inDocument) { - w._inDocument = true; - renderer.container.appendChild(w.el); - } - var top = renderer.$cursorLayer.getPixelPosition({row: i, column:0}, true).top; - if (!w.coverLine) - top += config.lineHeight * this.session.getRowLineCount(w.row); - w.el.style.top = top - config.offset + "px"; - - var left = w.coverGutter ? 0 : renderer.gutterWidth; - if (!w.fixedWidth) - left -= renderer.scrollLeft; - w.el.style.left = left + "px"; - - if (w.fullWidth && w.screenWidth) { - w.el.style.minWidth = config.width + 2 * config.padding + "px"; - } - - if (w.fixedWidth) { - w.el.style.right = renderer.scrollBar.getWidth() + "px"; - } else { - w.el.style.right = ""; - } - } - }; - - }).call(LineWidgets.prototype); - - - exports.LineWidgets = LineWidgets; - - }); - - ace.define("ace/ext/error_marker",["require","exports","module","ace/line_widgets","ace/lib/dom","ace/range"], function(acequire, exports, module) { - "use strict"; - var LineWidgets = acequire("../line_widgets").LineWidgets; - var dom = acequire("../lib/dom"); - var Range = acequire("../range").Range; - - function binarySearch(array, needle, comparator) { - var first = 0; - var last = array.length - 1; - - while (first <= last) { - var mid = (first + last) >> 1; - var c = comparator(needle, array[mid]); - if (c > 0) - first = mid + 1; - else if (c < 0) - last = mid - 1; - else - return mid; - } - return -(first + 1); - } - - function findAnnotations(session, row, dir) { - var annotations = session.getAnnotations().sort(Range.comparePoints); - if (!annotations.length) - return; - - var i = binarySearch(annotations, {row: row, column: -1}, Range.comparePoints); - if (i < 0) - i = -i - 1; - - if (i >= annotations.length) - i = dir > 0 ? 0 : annotations.length - 1; - else if (i === 0 && dir < 0) - i = annotations.length - 1; - - var annotation = annotations[i]; - if (!annotation || !dir) - return; - - if (annotation.row === row) { - do { - annotation = annotations[i += dir]; - } while (annotation && annotation.row === row); - if (!annotation) - return annotations.slice(); - } - - - var matched = []; - row = annotation.row; - do { - matched[dir < 0 ? "unshift" : "push"](annotation); - annotation = annotations[i += dir]; - } while (annotation && annotation.row == row); - return matched.length && matched; - } - - exports.showErrorMarker = function(editor, dir) { - var session = editor.session; - if (!session.widgetManager) { - session.widgetManager = new LineWidgets(session); - session.widgetManager.attach(editor); - } - - var pos = editor.getCursorPosition(); - var row = pos.row; - var oldWidget = session.widgetManager.getWidgetsAtRow(row).filter(function(w) { - return w.type == "errorMarker"; - })[0]; - if (oldWidget) { - oldWidget.destroy(); - } else { - row -= dir; - } - var annotations = findAnnotations(session, row, dir); - var gutterAnno; - if (annotations) { - var annotation = annotations[0]; - pos.column = (annotation.pos && typeof annotation.column != "number" - ? annotation.pos.sc - : annotation.column) || 0; - pos.row = annotation.row; - gutterAnno = editor.renderer.$gutterLayer.$annotations[pos.row]; - } else if (oldWidget) { - return; - } else { - gutterAnno = { - text: ["Looks good!"], - className: "ace_ok" - }; - } - editor.session.unfold(pos.row); - editor.selection.moveToPosition(pos); - - var w = { - row: pos.row, - fixedWidth: true, - coverGutter: true, - el: dom.createElement("div"), - type: "errorMarker" - }; - var el = w.el.appendChild(dom.createElement("div")); - var arrow = w.el.appendChild(dom.createElement("div")); - arrow.className = "error_widget_arrow " + gutterAnno.className; - - var left = editor.renderer.$cursorLayer - .getPixelPosition(pos).left; - arrow.style.left = left + editor.renderer.gutterWidth - 5 + "px"; - - w.el.className = "error_widget_wrapper"; - el.className = "error_widget " + gutterAnno.className; - el.innerHTML = gutterAnno.text.join("
"); - - el.appendChild(dom.createElement("div")); - - var kb = function(_, hashId, keyString) { - if (hashId === 0 && (keyString === "esc" || keyString === "return")) { - w.destroy(); - return {command: "null"}; - } - }; - - w.destroy = function() { - if (editor.$mouseHandler.isMousePressed) - return; - editor.keyBinding.removeKeyboardHandler(kb); - session.widgetManager.removeLineWidget(w); - editor.off("changeSelection", w.destroy); - editor.off("changeSession", w.destroy); - editor.off("mouseup", w.destroy); - editor.off("change", w.destroy); - }; - - editor.keyBinding.addKeyboardHandler(kb); - editor.on("changeSelection", w.destroy); - editor.on("changeSession", w.destroy); - editor.on("mouseup", w.destroy); - editor.on("change", w.destroy); - - editor.session.widgetManager.addLineWidget(w); - - w.el.onmousedown = editor.focus.bind(editor); - - editor.renderer.scrollCursorIntoView(null, 0.5, {bottom: w.el.offsetHeight}); - }; - - - dom.importCssString("\ - .error_widget_wrapper {\ - background: inherit;\ - color: inherit;\ - border:none\ - }\ - .error_widget {\ - border-top: solid 2px;\ - border-bottom: solid 2px;\ - margin: 5px 0;\ - padding: 10px 40px;\ - white-space: pre-wrap;\ - }\ - .error_widget.ace_error, .error_widget_arrow.ace_error{\ - border-color: #ff5a5a\ - }\ - .error_widget.ace_warning, .error_widget_arrow.ace_warning{\ - border-color: #F1D817\ - }\ - .error_widget.ace_info, .error_widget_arrow.ace_info{\ - border-color: #5a5a5a\ - }\ - .error_widget.ace_ok, .error_widget_arrow.ace_ok{\ - border-color: #5aaa5a\ - }\ - .error_widget_arrow {\ - position: absolute;\ - border: solid 5px;\ - border-top-color: transparent!important;\ - border-right-color: transparent!important;\ - border-left-color: transparent!important;\ - top: -5px;\ - }\ - ", ""); - - }); - - ace.define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config"], function(acequire, exports, module) { - "use strict"; - - acequire("./lib/fixoldbrowsers"); - - var dom = acequire("./lib/dom"); - var event = acequire("./lib/event"); - - var Editor = acequire("./editor").Editor; - var EditSession = acequire("./edit_session").EditSession; - var UndoManager = acequire("./undomanager").UndoManager; - var Renderer = acequire("./virtual_renderer").VirtualRenderer; - acequire("./worker/worker_client"); - acequire("./keyboard/hash_handler"); - acequire("./placeholder"); - acequire("./multi_select"); - acequire("./mode/folding/fold_mode"); - acequire("./theme/textmate"); - acequire("./ext/error_marker"); - - exports.config = acequire("./config"); - exports.acequire = acequire; - - if (true) - exports.define = __webpack_require__(67); - exports.edit = function(el) { - if (typeof el == "string") { - var _id = el; - el = document.getElementById(_id); - if (!el) - throw new Error("ace.edit can't find div #" + _id); - } - - if (el && el.env && el.env.editor instanceof Editor) - return el.env.editor; - - var value = ""; - if (el && /input|textarea/i.test(el.tagName)) { - var oldNode = el; - value = oldNode.value; - el = dom.createElement("pre"); - oldNode.parentNode.replaceChild(el, oldNode); - } else if (el) { - value = dom.getInnerText(el); - el.innerHTML = ""; - } - - var doc = exports.createEditSession(value); - - var editor = new Editor(new Renderer(el)); - editor.setSession(doc); - - var env = { - document: doc, - editor: editor, - onResize: editor.resize.bind(editor, null) - }; - if (oldNode) env.textarea = oldNode; - event.addListener(window, "resize", env.onResize); - editor.on("destroy", function() { - event.removeListener(window, "resize", env.onResize); - env.editor.container.env = null; // prevent memory leak on old ie - }); - editor.container.env = editor.env = env; - return editor; - }; - exports.createEditSession = function(text, mode) { - var doc = new EditSession(text, mode); - doc.setUndoManager(new UndoManager()); - return doc; - }; - exports.EditSession = EditSession; - exports.UndoManager = UndoManager; - exports.version = "1.2.9"; - }); - (function() { - ace.acequire(["ace/ace"], function(a) { - if (a) { - a.config.init(true); - a.define = ace.define; - } - if (!window.ace) - window.ace = a; - for (var key in a) if (a.hasOwnProperty(key)) - window.ace[key] = a[key]; - }); - })(); - - module.exports = window.ace.acequire("ace/ace"); - -/***/ }, -/* 67 */ -/***/ function(module, exports) { - - module.exports = function() { throw new Error("define cannot be used indirect"); }; - - -/***/ }, -/* 68 */ -/***/ function(module, exports, __webpack_require__) { - - ace.define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("../lib/oop"); - var TextHighlightRules = acequire("./text_highlight_rules").TextHighlightRules; - - var JsonHighlightRules = function() { - this.$rules = { - "start" : [ - { - token : "variable", // single line - regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)' - }, { - token : "string", // single line - regex : '"', - next : "string" - }, { - token : "constant.numeric", // hex - regex : "0[xX][0-9a-fA-F]+\\b" - }, { - token : "constant.numeric", // float - regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b" - }, { - token : "constant.language.boolean", - regex : "(?:true|false)\\b" - }, { - token : "text", // single quoted strings are not allowed - regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" - }, { - token : "comment", // comments are not allowed, but who cares? - regex : "\\/\\/.*$" - }, { - token : "comment.start", // comments are not allowed, but who cares? - regex : "\\/\\*", - next : "comment" - }, { - token : "paren.lparen", - regex : "[[({]" - }, { - token : "paren.rparen", - regex : "[\\])}]" - }, { - token : "text", - regex : "\\s+" - } - ], - "string" : [ - { - token : "constant.language.escape", - regex : /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/ - }, { - token : "string", - regex : '"|$', - next : "start" - }, { - defaultToken : "string" - } - ], - "comment" : [ - { - token : "comment.end", // comments are not allowed, but who cares? - regex : "\\*\\/", - next : "start" - }, { - defaultToken: "comment" - } - ] - }; - - }; - - oop.inherits(JsonHighlightRules, TextHighlightRules); - - exports.JsonHighlightRules = JsonHighlightRules; - }); - - ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(acequire, exports, module) { - "use strict"; - - var Range = acequire("../range").Range; - - var MatchingBraceOutdent = function() {}; - - (function() { - - this.checkOutdent = function(line, input) { - if (! /^\s+$/.test(line)) - return false; - - return /^\s*\}/.test(input); - }; - - this.autoOutdent = function(doc, row) { - var line = doc.getLine(row); - var match = line.match(/^(\s*\})/); - - if (!match) return 0; - - var column = match[1].length; - var openBracePos = doc.findMatchingBracket({row: row, column: column}); - - if (!openBracePos || openBracePos.row == row) return 0; - - var indent = this.$getIndent(doc.getLine(openBracePos.row)); - doc.replace(new Range(row, 0, row, column-1), indent); - }; - - this.$getIndent = function(line) { - return line.match(/^\s*/)[0]; - }; - - }).call(MatchingBraceOutdent.prototype); - - exports.MatchingBraceOutdent = MatchingBraceOutdent; - }); - - ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("../../lib/oop"); - var Range = acequire("../../range").Range; - var BaseFoldMode = acequire("./fold_mode").FoldMode; - - var FoldMode = exports.FoldMode = function(commentRegex) { - if (commentRegex) { - this.foldingStartMarker = new RegExp( - this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start) - ); - this.foldingStopMarker = new RegExp( - this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end) - ); - } - }; - oop.inherits(FoldMode, BaseFoldMode); - - (function() { - - this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/; - this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/; - this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/; - this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/; - this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/; - this._getFoldWidgetBase = this.getFoldWidget; - this.getFoldWidget = function(session, foldStyle, row) { - var line = session.getLine(row); - - if (this.singleLineBlockCommentRe.test(line)) { - if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line)) - return ""; - } - - var fw = this._getFoldWidgetBase(session, foldStyle, row); - - if (!fw && this.startRegionRe.test(line)) - return "start"; // lineCommentRegionStart - - return fw; - }; - - this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) { - var line = session.getLine(row); - - if (this.startRegionRe.test(line)) - return this.getCommentRegionBlock(session, line, row); - - var match = line.match(this.foldingStartMarker); - if (match) { - var i = match.index; - - if (match[1]) - return this.openingBracketBlock(session, match[1], row, i); - - var range = session.getCommentFoldRange(row, i + match[0].length, 1); - - if (range && !range.isMultiLine()) { - if (forceMultiline) { - range = this.getSectionRange(session, row); - } else if (foldStyle != "all") - range = null; - } - - return range; - } - - if (foldStyle === "markbegin") - return; - - var match = line.match(this.foldingStopMarker); - if (match) { - var i = match.index + match[0].length; - - if (match[1]) - return this.closingBracketBlock(session, match[1], row, i); - - return session.getCommentFoldRange(row, i, -1); - } - }; - - this.getSectionRange = function(session, row) { - var line = session.getLine(row); - var startIndent = line.search(/\S/); - var startRow = row; - var startColumn = line.length; - row = row + 1; - var endRow = row; - var maxRow = session.getLength(); - while (++row < maxRow) { - line = session.getLine(row); - var indent = line.search(/\S/); - if (indent === -1) - continue; - if (startIndent > indent) - break; - var subRange = this.getFoldWidgetRange(session, "all", row); - - if (subRange) { - if (subRange.start.row <= startRow) { - break; - } else if (subRange.isMultiLine()) { - row = subRange.end.row; - } else if (startIndent == indent) { - break; - } - } - endRow = row; - } - - return new Range(startRow, startColumn, endRow, session.getLine(endRow).length); - }; - this.getCommentRegionBlock = function(session, line, row) { - var startColumn = line.search(/\s*$/); - var maxRow = session.getLength(); - var startRow = row; - - var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/; - var depth = 1; - while (++row < maxRow) { - line = session.getLine(row); - var m = re.exec(line); - if (!m) continue; - if (m[1]) depth--; - else depth++; - - if (!depth) break; - } - - var endRow = row; - if (endRow > startRow) { - return new Range(startRow, startColumn, endRow, line.length); - } - }; - - }).call(FoldMode.prototype); - - }); - - ace.define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"], function(acequire, exports, module) { - "use strict"; - - var oop = acequire("../lib/oop"); - var TextMode = acequire("./text").Mode; - var HighlightRules = acequire("./json_highlight_rules").JsonHighlightRules; - var MatchingBraceOutdent = acequire("./matching_brace_outdent").MatchingBraceOutdent; - var CstyleBehaviour = acequire("./behaviour/cstyle").CstyleBehaviour; - var CStyleFoldMode = acequire("./folding/cstyle").FoldMode; - var WorkerClient = acequire("../worker/worker_client").WorkerClient; - - var Mode = function() { - this.HighlightRules = HighlightRules; - this.$outdent = new MatchingBraceOutdent(); - this.$behaviour = new CstyleBehaviour(); - this.foldingRules = new CStyleFoldMode(); - }; - oop.inherits(Mode, TextMode); - - (function() { - - this.getNextLineIndent = function(state, line, tab) { - var indent = this.$getIndent(line); - - if (state == "start") { - var match = line.match(/^.*[\{\(\[]\s*$/); - if (match) { - indent += tab; - } - } - - return indent; - }; - - this.checkOutdent = function(state, line, input) { - return this.$outdent.checkOutdent(line, input); - }; - - this.autoOutdent = function(state, doc, row) { - this.$outdent.autoOutdent(doc, row); - }; - - this.createWorker = function(session) { - var worker = new WorkerClient(["ace"], __webpack_require__(69), "JsonWorker"); - worker.attachToDocument(session.getDocument()); - - worker.on("annotate", function(e) { - session.setAnnotations(e.data); - }); - - worker.on("terminate", function() { - session.clearAnnotations(); - }); - - return worker; - }; - - - this.$id = "ace/mode/json"; - }).call(Mode.prototype); - - exports.Mode = Mode; - }); - - -/***/ }, -/* 69 */ -/***/ function(module, exports) { - - module.exports.id = 'ace/mode/json_worker'; - module.exports.src = "\"no use strict\";!function(window){function resolveModuleId(id,paths){for(var testPath=id,tail=\"\";testPath;){var alias=paths[testPath];if(\"string\"==typeof alias)return alias+tail;if(alias)return alias.location.replace(/\\/*$/,\"/\")+(tail||alias.main||alias.name);if(alias===!1)return\"\";var i=testPath.lastIndexOf(\"/\");if(-1===i)break;tail=testPath.substr(i)+tail,testPath=testPath.slice(0,i)}return id}if(!(void 0!==window.window&&window.document||window.acequire&&window.define)){window.console||(window.console=function(){var msgs=Array.prototype.slice.call(arguments,0);postMessage({type:\"log\",data:msgs})},window.console.error=window.console.warn=window.console.log=window.console.trace=window.console),window.window=window,window.ace=window,window.onerror=function(message,file,line,col,err){postMessage({type:\"error\",data:{message:message,data:err.data,file:file,line:line,col:col,stack:err.stack}})},window.normalizeModule=function(parentId,moduleName){if(-1!==moduleName.indexOf(\"!\")){var chunks=moduleName.split(\"!\");return window.normalizeModule(parentId,chunks[0])+\"!\"+window.normalizeModule(parentId,chunks[1])}if(\".\"==moduleName.charAt(0)){var base=parentId.split(\"/\").slice(0,-1).join(\"/\");for(moduleName=(base?base+\"/\":\"\")+moduleName;-1!==moduleName.indexOf(\".\")&&previous!=moduleName;){var previous=moduleName;moduleName=moduleName.replace(/^\\.\\//,\"\").replace(/\\/\\.\\//,\"/\").replace(/[^\\/]+\\/\\.\\.\\//,\"\")}}return moduleName},window.acequire=function acequire(parentId,id){if(id||(id=parentId,parentId=null),!id.charAt)throw Error(\"worker.js acequire() accepts only (parentId, id) as arguments\");id=window.normalizeModule(parentId,id);var module=window.acequire.modules[id];if(module)return module.initialized||(module.initialized=!0,module.exports=module.factory().exports),module.exports;if(!window.acequire.tlns)return console.log(\"unable to load \"+id);var path=resolveModuleId(id,window.acequire.tlns);return\".js\"!=path.slice(-3)&&(path+=\".js\"),window.acequire.id=id,window.acequire.modules[id]={},importScripts(path),window.acequire(parentId,id)},window.acequire.modules={},window.acequire.tlns={},window.define=function(id,deps,factory){if(2==arguments.length?(factory=deps,\"string\"!=typeof id&&(deps=id,id=window.acequire.id)):1==arguments.length&&(factory=id,deps=[],id=window.acequire.id),\"function\"!=typeof factory)return window.acequire.modules[id]={exports:factory,initialized:!0},void 0;deps.length||(deps=[\"require\",\"exports\",\"module\"]);var req=function(childId){return window.acequire(id,childId)};window.acequire.modules[id]={exports:{},factory:function(){var module=this,returnExports=factory.apply(this,deps.map(function(dep){switch(dep){case\"require\":return req;case\"exports\":return module.exports;case\"module\":return module;default:return req(dep)}}));return returnExports&&(module.exports=returnExports),module}}},window.define.amd={},acequire.tlns={},window.initBaseUrls=function(topLevelNamespaces){for(var i in topLevelNamespaces)acequire.tlns[i]=topLevelNamespaces[i]},window.initSender=function(){var EventEmitter=window.acequire(\"ace/lib/event_emitter\").EventEmitter,oop=window.acequire(\"ace/lib/oop\"),Sender=function(){};return function(){oop.implement(this,EventEmitter),this.callback=function(data,callbackId){postMessage({type:\"call\",id:callbackId,data:data})},this.emit=function(name,data){postMessage({type:\"event\",name:name,data:data})}}.call(Sender.prototype),new Sender};var main=window.main=null,sender=window.sender=null;window.onmessage=function(e){var msg=e.data;if(msg.event&&sender)sender._signal(msg.event,msg.data);else if(msg.command)if(main[msg.command])main[msg.command].apply(main,msg.args);else{if(!window[msg.command])throw Error(\"Unknown command:\"+msg.command);window[msg.command].apply(window,msg.args)}else if(msg.init){window.initBaseUrls(msg.tlns),acequire(\"ace/lib/es5-shim\"),sender=window.sender=window.initSender();var clazz=acequire(msg.module)[msg.classname];main=window.main=new clazz(sender)}}}}(this),ace.define(\"ace/lib/oop\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";exports.inherits=function(ctor,superCtor){ctor.super_=superCtor,ctor.prototype=Object.create(superCtor.prototype,{constructor:{value:ctor,enumerable:!1,writable:!0,configurable:!0}})},exports.mixin=function(obj,mixin){for(var key in mixin)obj[key]=mixin[key];return obj},exports.implement=function(proto,mixin){exports.mixin(proto,mixin)}}),ace.define(\"ace/range\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";var comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},Range=function(startRow,startColumn,endRow,endColumn){this.start={row:startRow,column:startColumn},this.end={row:endRow,column:endColumn}};(function(){this.isEqual=function(range){return this.start.row===range.start.row&&this.end.row===range.end.row&&this.start.column===range.start.column&&this.end.column===range.end.column},this.toString=function(){return\"Range: [\"+this.start.row+\"/\"+this.start.column+\"] -> [\"+this.end.row+\"/\"+this.end.column+\"]\"},this.contains=function(row,column){return 0==this.compare(row,column)},this.compareRange=function(range){var cmp,end=range.end,start=range.start;return cmp=this.compare(end.row,end.column),1==cmp?(cmp=this.compare(start.row,start.column),1==cmp?2:0==cmp?1:0):-1==cmp?-2:(cmp=this.compare(start.row,start.column),-1==cmp?-1:1==cmp?42:0)},this.comparePoint=function(p){return this.compare(p.row,p.column)},this.containsRange=function(range){return 0==this.comparePoint(range.start)&&0==this.comparePoint(range.end)},this.intersects=function(range){var cmp=this.compareRange(range);return-1==cmp||0==cmp||1==cmp},this.isEnd=function(row,column){return this.end.row==row&&this.end.column==column},this.isStart=function(row,column){return this.start.row==row&&this.start.column==column},this.setStart=function(row,column){\"object\"==typeof row?(this.start.column=row.column,this.start.row=row.row):(this.start.row=row,this.start.column=column)},this.setEnd=function(row,column){\"object\"==typeof row?(this.end.column=row.column,this.end.row=row.row):(this.end.row=row,this.end.column=column)},this.inside=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)||this.isStart(row,column)?!1:!0:!1},this.insideStart=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)?!1:!0:!1},this.insideEnd=function(row,column){return 0==this.compare(row,column)?this.isStart(row,column)?!1:!0:!1},this.compare=function(row,column){return this.isMultiLine()||row!==this.start.row?this.start.row>row?-1:row>this.end.row?1:this.start.row===row?column>=this.start.column?0:-1:this.end.row===row?this.end.column>=column?0:1:0:this.start.column>column?-1:column>this.end.column?1:0},this.compareStart=function(row,column){return this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.compareEnd=function(row,column){return this.end.row==row&&this.end.column==column?1:this.compare(row,column)},this.compareInside=function(row,column){return this.end.row==row&&this.end.column==column?1:this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.clipRows=function(firstRow,lastRow){if(this.end.row>lastRow)var end={row:lastRow+1,column:0};else if(firstRow>this.end.row)var end={row:firstRow,column:0};if(this.start.row>lastRow)var start={row:lastRow+1,column:0};else if(firstRow>this.start.row)var start={row:firstRow,column:0};return Range.fromPoints(start||this.start,end||this.end)},this.extend=function(row,column){var cmp=this.compare(row,column);if(0==cmp)return this;if(-1==cmp)var start={row:row,column:column};else var end={row:row,column:column};return Range.fromPoints(start||this.start,end||this.end)},this.isEmpty=function(){return this.start.row===this.end.row&&this.start.column===this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return Range.fromPoints(this.start,this.end)},this.collapseRows=function(){return 0==this.end.column?new Range(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new Range(this.start.row,0,this.end.row,0)},this.toScreenRange=function(session){var screenPosStart=session.documentToScreenPosition(this.start),screenPosEnd=session.documentToScreenPosition(this.end);return new Range(screenPosStart.row,screenPosStart.column,screenPosEnd.row,screenPosEnd.column)},this.moveBy=function(row,column){this.start.row+=row,this.start.column+=column,this.end.row+=row,this.end.column+=column}}).call(Range.prototype),Range.fromPoints=function(start,end){return new Range(start.row,start.column,end.row,end.column)},Range.comparePoints=comparePoints,Range.comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},exports.Range=Range}),ace.define(\"ace/apply_delta\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";exports.applyDelta=function(docLines,delta){var row=delta.start.row,startColumn=delta.start.column,line=docLines[row]||\"\";switch(delta.action){case\"insert\":var lines=delta.lines;if(1===lines.length)docLines[row]=line.substring(0,startColumn)+delta.lines[0]+line.substring(startColumn);else{var args=[row,1].concat(delta.lines);docLines.splice.apply(docLines,args),docLines[row]=line.substring(0,startColumn)+docLines[row],docLines[row+delta.lines.length-1]+=line.substring(startColumn)}break;case\"remove\":var endColumn=delta.end.column,endRow=delta.end.row;row===endRow?docLines[row]=line.substring(0,startColumn)+line.substring(endColumn):docLines.splice(row,endRow-row+1,line.substring(0,startColumn)+docLines[endRow].substring(endColumn))}}}),ace.define(\"ace/lib/event_emitter\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";var EventEmitter={},stopPropagation=function(){this.propagationStopped=!0},preventDefault=function(){this.defaultPrevented=!0};EventEmitter._emit=EventEmitter._dispatchEvent=function(eventName,e){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var listeners=this._eventRegistry[eventName]||[],defaultHandler=this._defaultHandlers[eventName];if(listeners.length||defaultHandler){\"object\"==typeof e&&e||(e={}),e.type||(e.type=eventName),e.stopPropagation||(e.stopPropagation=stopPropagation),e.preventDefault||(e.preventDefault=preventDefault),listeners=listeners.slice();for(var i=0;listeners.length>i&&(listeners[i](e,this),!e.propagationStopped);i++);return defaultHandler&&!e.defaultPrevented?defaultHandler(e,this):void 0}},EventEmitter._signal=function(eventName,e){var listeners=(this._eventRegistry||{})[eventName];if(listeners){listeners=listeners.slice();for(var i=0;listeners.length>i;i++)listeners[i](e,this)}},EventEmitter.once=function(eventName,callback){var _self=this;callback&&this.addEventListener(eventName,function newCallback(){_self.removeEventListener(eventName,newCallback),callback.apply(null,arguments)})},EventEmitter.setDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers||(handlers=this._defaultHandlers={_disabled_:{}}),handlers[eventName]){var old=handlers[eventName],disabled=handlers._disabled_[eventName];disabled||(handlers._disabled_[eventName]=disabled=[]),disabled.push(old);var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}handlers[eventName]=callback},EventEmitter.removeDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers){var disabled=handlers._disabled_[eventName];if(handlers[eventName]==callback)handlers[eventName],disabled&&this.setDefaultHandler(eventName,disabled.pop());else if(disabled){var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}}},EventEmitter.on=EventEmitter.addEventListener=function(eventName,callback,capturing){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];return listeners||(listeners=this._eventRegistry[eventName]=[]),-1==listeners.indexOf(callback)&&listeners[capturing?\"unshift\":\"push\"](callback),callback},EventEmitter.off=EventEmitter.removeListener=EventEmitter.removeEventListener=function(eventName,callback){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];if(listeners){var index=listeners.indexOf(callback);-1!==index&&listeners.splice(index,1)}},EventEmitter.removeAllListeners=function(eventName){this._eventRegistry&&(this._eventRegistry[eventName]=[])},exports.EventEmitter=EventEmitter}),ace.define(\"ace/anchor\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(acequire,exports){\"use strict\";var oop=acequire(\"./lib/oop\"),EventEmitter=acequire(\"./lib/event_emitter\").EventEmitter,Anchor=exports.Anchor=function(doc,row,column){this.$onChange=this.onChange.bind(this),this.attach(doc),column===void 0?this.setPosition(row.row,row.column):this.setPosition(row,column)};(function(){function $pointsInOrder(point1,point2,equalPointsInOrder){var bColIsAfter=equalPointsInOrder?point1.column<=point2.column:point1.columnthis.row)){var point=$getTransformedPoint(delta,{row:this.row,column:this.column},this.$insertRight);this.setPosition(point.row,point.column,!0)}},this.setPosition=function(row,column,noClip){var pos;if(pos=noClip?{row:row,column:column}:this.$clipPositionToDocument(row,column),this.row!=pos.row||this.column!=pos.column){var old={row:this.row,column:this.column};this.row=pos.row,this.column=pos.column,this._signal(\"change\",{old:old,value:pos})}},this.detach=function(){this.document.removeEventListener(\"change\",this.$onChange)},this.attach=function(doc){this.document=doc||this.document,this.document.on(\"change\",this.$onChange)},this.$clipPositionToDocument=function(row,column){var pos={};return row>=this.document.getLength()?(pos.row=Math.max(0,this.document.getLength()-1),pos.column=this.document.getLine(pos.row).length):0>row?(pos.row=0,pos.column=0):(pos.row=row,pos.column=Math.min(this.document.getLine(pos.row).length,Math.max(0,column))),0>column&&(pos.column=0),pos}}).call(Anchor.prototype)}),ace.define(\"ace/document\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/apply_delta\",\"ace/lib/event_emitter\",\"ace/range\",\"ace/anchor\"],function(acequire,exports){\"use strict\";var oop=acequire(\"./lib/oop\"),applyDelta=acequire(\"./apply_delta\").applyDelta,EventEmitter=acequire(\"./lib/event_emitter\").EventEmitter,Range=acequire(\"./range\").Range,Anchor=acequire(\"./anchor\").Anchor,Document=function(textOrLines){this.$lines=[\"\"],0===textOrLines.length?this.$lines=[\"\"]:Array.isArray(textOrLines)?this.insertMergedLines({row:0,column:0},textOrLines):this.insert({row:0,column:0},textOrLines)};(function(){oop.implement(this,EventEmitter),this.setValue=function(text){var len=this.getLength()-1;this.remove(new Range(0,0,len,this.getLine(len).length)),this.insert({row:0,column:0},text)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(row,column){return new Anchor(this,row,column)},this.$split=0===\"aaa\".split(/a/).length?function(text){return text.replace(/\\r\\n|\\r/g,\"\\n\").split(\"\\n\")}:function(text){return text.split(/\\r\\n|\\r|\\n/)},this.$detectNewLine=function(text){var match=text.match(/^.*?(\\r\\n|\\r|\\n)/m);this.$autoNewLine=match?match[1]:\"\\n\",this._signal(\"changeNewLineMode\")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case\"windows\":return\"\\r\\n\";case\"unix\":return\"\\n\";default:return this.$autoNewLine||\"\\n\"}},this.$autoNewLine=\"\",this.$newLineMode=\"auto\",this.setNewLineMode=function(newLineMode){this.$newLineMode!==newLineMode&&(this.$newLineMode=newLineMode,this._signal(\"changeNewLineMode\"))},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(text){return\"\\r\\n\"==text||\"\\r\"==text||\"\\n\"==text},this.getLine=function(row){return this.$lines[row]||\"\"},this.getLines=function(firstRow,lastRow){return this.$lines.slice(firstRow,lastRow+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(range){return this.getLinesForRange(range).join(this.getNewLineCharacter())},this.getLinesForRange=function(range){var lines;if(range.start.row===range.end.row)lines=[this.getLine(range.start.row).substring(range.start.column,range.end.column)];else{lines=this.getLines(range.start.row,range.end.row),lines[0]=(lines[0]||\"\").substring(range.start.column);var l=lines.length-1;range.end.row-range.start.row==l&&(lines[l]=lines[l].substring(0,range.end.column))}return lines},this.insertLines=function(row,lines){return console.warn(\"Use of document.insertLines is deprecated. Use the insertFullLines method instead.\"),this.insertFullLines(row,lines)},this.removeLines=function(firstRow,lastRow){return console.warn(\"Use of document.removeLines is deprecated. Use the removeFullLines method instead.\"),this.removeFullLines(firstRow,lastRow)},this.insertNewLine=function(position){return console.warn(\"Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead.\"),this.insertMergedLines(position,[\"\",\"\"])},this.insert=function(position,text){return 1>=this.getLength()&&this.$detectNewLine(text),this.insertMergedLines(position,this.$split(text))},this.insertInLine=function(position,text){var start=this.clippedPos(position.row,position.column),end=this.pos(position.row,position.column+text.length);return this.applyDelta({start:start,end:end,action:\"insert\",lines:[text]},!0),this.clonePos(end)},this.clippedPos=function(row,column){var length=this.getLength();void 0===row?row=length:0>row?row=0:row>=length&&(row=length-1,column=void 0);var line=this.getLine(row);return void 0==column&&(column=line.length),column=Math.min(Math.max(column,0),line.length),{row:row,column:column}},this.clonePos=function(pos){return{row:pos.row,column:pos.column}},this.pos=function(row,column){return{row:row,column:column}},this.$clipPosition=function(position){var length=this.getLength();return position.row>=length?(position.row=Math.max(0,length-1),position.column=this.getLine(length-1).length):(position.row=Math.max(0,position.row),position.column=Math.min(Math.max(position.column,0),this.getLine(position.row).length)),position},this.insertFullLines=function(row,lines){row=Math.min(Math.max(row,0),this.getLength());var column=0;this.getLength()>row?(lines=lines.concat([\"\"]),column=0):(lines=[\"\"].concat(lines),row--,column=this.$lines[row].length),this.insertMergedLines({row:row,column:column},lines)},this.insertMergedLines=function(position,lines){var start=this.clippedPos(position.row,position.column),end={row:start.row+lines.length-1,column:(1==lines.length?start.column:0)+lines[lines.length-1].length};return this.applyDelta({start:start,end:end,action:\"insert\",lines:lines}),this.clonePos(end)},this.remove=function(range){var start=this.clippedPos(range.start.row,range.start.column),end=this.clippedPos(range.end.row,range.end.column);return this.applyDelta({start:start,end:end,action:\"remove\",lines:this.getLinesForRange({start:start,end:end})}),this.clonePos(start)},this.removeInLine=function(row,startColumn,endColumn){var start=this.clippedPos(row,startColumn),end=this.clippedPos(row,endColumn);return this.applyDelta({start:start,end:end,action:\"remove\",lines:this.getLinesForRange({start:start,end:end})},!0),this.clonePos(start)},this.removeFullLines=function(firstRow,lastRow){firstRow=Math.min(Math.max(0,firstRow),this.getLength()-1),lastRow=Math.min(Math.max(0,lastRow),this.getLength()-1);var deleteFirstNewLine=lastRow==this.getLength()-1&&firstRow>0,deleteLastNewLine=this.getLength()-1>lastRow,startRow=deleteFirstNewLine?firstRow-1:firstRow,startCol=deleteFirstNewLine?this.getLine(startRow).length:0,endRow=deleteLastNewLine?lastRow+1:lastRow,endCol=deleteLastNewLine?0:this.getLine(endRow).length,range=new Range(startRow,startCol,endRow,endCol),deletedLines=this.$lines.slice(firstRow,lastRow+1);return this.applyDelta({start:range.start,end:range.end,action:\"remove\",lines:this.getLinesForRange(range)}),deletedLines},this.removeNewLine=function(row){this.getLength()-1>row&&row>=0&&this.applyDelta({start:this.pos(row,this.getLine(row).length),end:this.pos(row+1,0),action:\"remove\",lines:[\"\",\"\"]})},this.replace=function(range,text){if(range instanceof Range||(range=Range.fromPoints(range.start,range.end)),0===text.length&&range.isEmpty())return range.start;if(text==this.getTextRange(range))return range.end;this.remove(range);var end;return end=text?this.insert(range.start,text):range.start},this.applyDeltas=function(deltas){for(var i=0;deltas.length>i;i++)this.applyDelta(deltas[i])},this.revertDeltas=function(deltas){for(var i=deltas.length-1;i>=0;i--)this.revertDelta(deltas[i])},this.applyDelta=function(delta,doNotValidate){var isInsert=\"insert\"==delta.action;(isInsert?1>=delta.lines.length&&!delta.lines[0]:!Range.comparePoints(delta.start,delta.end))||(isInsert&&delta.lines.length>2e4&&this.$splitAndapplyLargeDelta(delta,2e4),applyDelta(this.$lines,delta,doNotValidate),this._signal(\"change\",delta))},this.$splitAndapplyLargeDelta=function(delta,MAX){for(var lines=delta.lines,l=lines.length,row=delta.start.row,column=delta.start.column,from=0,to=0;;){from=to,to+=MAX-1;var chunk=lines.slice(from,to);if(to>l){delta.lines=chunk,delta.start.row=row+from,delta.start.column=column;break}chunk.push(\"\"),this.applyDelta({start:this.pos(row+from,column),end:this.pos(row+to,column=0),action:delta.action,lines:chunk},!0)}},this.revertDelta=function(delta){this.applyDelta({start:this.clonePos(delta.start),end:this.clonePos(delta.end),action:\"insert\"==delta.action?\"remove\":\"insert\",lines:delta.lines.slice()})},this.indexToPosition=function(index,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,i=startRow||0,l=lines.length;l>i;i++)if(index-=lines[i].length+newlineLength,0>index)return{row:i,column:index+lines[i].length+newlineLength};return{row:l-1,column:lines[l-1].length}},this.positionToIndex=function(pos,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,index=0,row=Math.min(pos.row,lines.length),i=startRow||0;row>i;++i)index+=lines[i].length+newlineLength;return index+pos.column}}).call(Document.prototype),exports.Document=Document}),ace.define(\"ace/lib/lang\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";exports.last=function(a){return a[a.length-1]},exports.stringReverse=function(string){return string.split(\"\").reverse().join(\"\")},exports.stringRepeat=function(string,count){for(var result=\"\";count>0;)1&count&&(result+=string),(count>>=1)&&(string+=string);return result};var trimBeginRegexp=/^\\s\\s*/,trimEndRegexp=/\\s\\s*$/;exports.stringTrimLeft=function(string){return string.replace(trimBeginRegexp,\"\")},exports.stringTrimRight=function(string){return string.replace(trimEndRegexp,\"\")},exports.copyObject=function(obj){var copy={};for(var key in obj)copy[key]=obj[key];return copy},exports.copyArray=function(array){for(var copy=[],i=0,l=array.length;l>i;i++)copy[i]=array[i]&&\"object\"==typeof array[i]?this.copyObject(array[i]):array[i];return copy},exports.deepCopy=function deepCopy(obj){if(\"object\"!=typeof obj||!obj)return obj;var copy;if(Array.isArray(obj)){copy=[];for(var key=0;obj.length>key;key++)copy[key]=deepCopy(obj[key]);return copy}if(\"[object Object]\"!==Object.prototype.toString.call(obj))return obj;copy={};for(var key in obj)copy[key]=deepCopy(obj[key]);return copy},exports.arrayToMap=function(arr){for(var map={},i=0;arr.length>i;i++)map[arr[i]]=1;return map},exports.createMap=function(props){var map=Object.create(null);for(var i in props)map[i]=props[i];return map},exports.arrayRemove=function(array,value){for(var i=0;array.length>=i;i++)value===array[i]&&array.splice(i,1)},exports.escapeRegExp=function(str){return str.replace(/([.*+?^${}()|[\\]\\/\\\\])/g,\"\\\\$1\")},exports.escapeHTML=function(str){return str.replace(/&/g,\"&\").replace(/\"/g,\""\").replace(/'/g,\"'\").replace(/i;i+=2){if(Array.isArray(data[i+1]))var d={action:\"insert\",start:data[i],lines:data[i+1]};else var d={action:\"remove\",start:data[i],end:data[i+1]};doc.applyDelta(d,!0)}return _self.$timeout?deferredUpdate.schedule(_self.$timeout):(_self.onUpdate(),void 0)})};(function(){this.$timeout=500,this.setTimeout=function(timeout){this.$timeout=timeout},this.setValue=function(value){this.doc.setValue(value),this.deferredUpdate.schedule(this.$timeout)},this.getValue=function(callbackId){this.sender.callback(this.doc.getValue(),callbackId)},this.onUpdate=function(){},this.isPending=function(){return this.deferredUpdate.isPending()}}).call(Mirror.prototype)}),ace.define(\"ace/mode/json/json_parse\",[\"require\",\"exports\",\"module\"],function(){\"use strict\";var at,ch,text,value,escapee={'\"':'\"',\"\\\\\":\"\\\\\",\"/\":\"/\",b:\"\\b\",f:\"\\f\",n:\"\\n\",r:\"\\r\",t:\"\t\"},error=function(m){throw{name:\"SyntaxError\",message:m,at:at,text:text}},next=function(c){return c&&c!==ch&&error(\"Expected '\"+c+\"' instead of '\"+ch+\"'\"),ch=text.charAt(at),at+=1,ch},number=function(){var number,string=\"\";for(\"-\"===ch&&(string=\"-\",next(\"-\"));ch>=\"0\"&&\"9\">=ch;)string+=ch,next();if(\".\"===ch)for(string+=\".\";next()&&ch>=\"0\"&&\"9\">=ch;)string+=ch;if(\"e\"===ch||\"E\"===ch)for(string+=ch,next(),(\"-\"===ch||\"+\"===ch)&&(string+=ch,next());ch>=\"0\"&&\"9\">=ch;)string+=ch,next();return number=+string,isNaN(number)?(error(\"Bad number\"),void 0):number},string=function(){var hex,i,uffff,string=\"\";if('\"'===ch)for(;next();){if('\"'===ch)return next(),string;if(\"\\\\\"===ch)if(next(),\"u\"===ch){for(uffff=0,i=0;4>i&&(hex=parseInt(next(),16),isFinite(hex));i+=1)uffff=16*uffff+hex;string+=String.fromCharCode(uffff)}else{if(\"string\"!=typeof escapee[ch])break;string+=escapee[ch]}else string+=ch}error(\"Bad string\")},white=function(){for(;ch&&\" \">=ch;)next()},word=function(){switch(ch){case\"t\":return next(\"t\"),next(\"r\"),next(\"u\"),next(\"e\"),!0;case\"f\":return next(\"f\"),next(\"a\"),next(\"l\"),next(\"s\"),next(\"e\"),!1;case\"n\":return next(\"n\"),next(\"u\"),next(\"l\"),next(\"l\"),null}error(\"Unexpected '\"+ch+\"'\")},array=function(){var array=[];if(\"[\"===ch){if(next(\"[\"),white(),\"]\"===ch)return next(\"]\"),array;for(;ch;){if(array.push(value()),white(),\"]\"===ch)return next(\"]\"),array;next(\",\"),white()}}error(\"Bad array\")},object=function(){var key,object={};if(\"{\"===ch){if(next(\"{\"),white(),\"}\"===ch)return next(\"}\"),object;for(;ch;){if(key=string(),white(),next(\":\"),Object.hasOwnProperty.call(object,key)&&error('Duplicate key \"'+key+'\"'),object[key]=value(),white(),\"}\"===ch)return next(\"}\"),object;next(\",\"),white()}}error(\"Bad object\")};return value=function(){switch(white(),ch){case\"{\":return object();case\"[\":return array();case'\"':return string();case\"-\":return number();default:return ch>=\"0\"&&\"9\">=ch?number():word()}},function(source,reviver){var result;return text=source,at=0,ch=\" \",result=value(),white(),ch&&error(\"Syntax error\"),\"function\"==typeof reviver?function walk(holder,key){var k,v,value=holder[key];if(value&&\"object\"==typeof value)for(k in value)Object.hasOwnProperty.call(value,k)&&(v=walk(value,k),void 0!==v?value[k]=v:delete value[k]);return reviver.call(holder,key,value)}({\"\":result},\"\"):result}}),ace.define(\"ace/mode/json_worker\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/worker/mirror\",\"ace/mode/json/json_parse\"],function(acequire,exports){\"use strict\";var oop=acequire(\"../lib/oop\"),Mirror=acequire(\"../worker/mirror\").Mirror,parse=acequire(\"./json/json_parse\"),JsonWorker=exports.JsonWorker=function(sender){Mirror.call(this,sender),this.setTimeout(200)};oop.inherits(JsonWorker,Mirror),function(){this.onUpdate=function(){var value=this.doc.getValue(),errors=[];try{value&&parse(value)}catch(e){var pos=this.doc.indexToPosition(e.at-1);errors.push({row:pos.row,column:pos.column,text:e.message,type:\"error\"})}this.sender.emit(\"annotate\",errors)}}.call(JsonWorker.prototype)}),ace.define(\"ace/lib/es5-shim\",[\"require\",\"exports\",\"module\"],function(){function Empty(){}function doesDefinePropertyWork(object){try{return Object.defineProperty(object,\"sentinel\",{}),\"sentinel\"in object}catch(exception){}}function toInteger(n){return n=+n,n!==n?n=0:0!==n&&n!==1/0&&n!==-(1/0)&&(n=(n>0||-1)*Math.floor(Math.abs(n))),n}Function.prototype.bind||(Function.prototype.bind=function(that){var target=this;if(\"function\"!=typeof target)throw new TypeError(\"Function.prototype.bind called on incompatible \"+target);var args=slice.call(arguments,1),bound=function(){if(this instanceof bound){var result=target.apply(this,args.concat(slice.call(arguments)));return Object(result)===result?result:this}return target.apply(that,args.concat(slice.call(arguments)))};return target.prototype&&(Empty.prototype=target.prototype,bound.prototype=new Empty,Empty.prototype=null),bound});var defineGetter,defineSetter,lookupGetter,lookupSetter,supportsAccessors,call=Function.prototype.call,prototypeOfArray=Array.prototype,prototypeOfObject=Object.prototype,slice=prototypeOfArray.slice,_toString=call.bind(prototypeOfObject.toString),owns=call.bind(prototypeOfObject.hasOwnProperty);if((supportsAccessors=owns(prototypeOfObject,\"__defineGetter__\"))&&(defineGetter=call.bind(prototypeOfObject.__defineGetter__),defineSetter=call.bind(prototypeOfObject.__defineSetter__),lookupGetter=call.bind(prototypeOfObject.__lookupGetter__),lookupSetter=call.bind(prototypeOfObject.__lookupSetter__)),2!=[1,2].splice(0).length)if(function(){function makeArray(l){var a=Array(l+2);return a[0]=a[1]=0,a}var lengthBefore,array=[];return array.splice.apply(array,makeArray(20)),array.splice.apply(array,makeArray(26)),lengthBefore=array.length,array.splice(5,0,\"XXX\"),lengthBefore+1==array.length,lengthBefore+1==array.length?!0:void 0\n}()){var array_splice=Array.prototype.splice;Array.prototype.splice=function(start,deleteCount){return arguments.length?array_splice.apply(this,[void 0===start?0:start,void 0===deleteCount?this.length-start:deleteCount].concat(slice.call(arguments,2))):[]}}else Array.prototype.splice=function(pos,removeCount){var length=this.length;pos>0?pos>length&&(pos=length):void 0==pos?pos=0:0>pos&&(pos=Math.max(length+pos,0)),length>pos+removeCount||(removeCount=length-pos);var removed=this.slice(pos,pos+removeCount),insert=slice.call(arguments,2),add=insert.length;if(pos===length)add&&this.push.apply(this,insert);else{var remove=Math.min(removeCount,length-pos),tailOldPos=pos+remove,tailNewPos=tailOldPos+add-remove,tailCount=length-tailOldPos,lengthAfterRemove=length-remove;if(tailOldPos>tailNewPos)for(var i=0;tailCount>i;++i)this[tailNewPos+i]=this[tailOldPos+i];else if(tailNewPos>tailOldPos)for(i=tailCount;i--;)this[tailNewPos+i]=this[tailOldPos+i];if(add&&pos===lengthAfterRemove)this.length=lengthAfterRemove,this.push.apply(this,insert);else for(this.length=lengthAfterRemove+add,i=0;add>i;++i)this[pos+i]=insert[i]}return removed};Array.isArray||(Array.isArray=function(obj){return\"[object Array]\"==_toString(obj)});var boxedString=Object(\"a\"),splitString=\"a\"!=boxedString[0]||!(0 in boxedString);if(Array.prototype.forEach||(Array.prototype.forEach=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,thisp=arguments[1],i=-1,length=self.length>>>0;if(\"[object Function]\"!=_toString(fun))throw new TypeError;for(;length>++i;)i in self&&fun.call(thisp,self[i],i,object)}),Array.prototype.map||(Array.prototype.map=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,result=Array(length),thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)i in self&&(result[i]=fun.call(thisp,self[i],i,object));return result}),Array.prototype.filter||(Array.prototype.filter=function(fun){var value,object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,result=[],thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)i in self&&(value=self[i],fun.call(thisp,value,i,object)&&result.push(value));return result}),Array.prototype.every||(Array.prototype.every=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)if(i in self&&!fun.call(thisp,self[i],i,object))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)if(i in self&&fun.call(thisp,self[i],i,object))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0;if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");if(!length&&1==arguments.length)throw new TypeError(\"reduce of empty array with no initial value\");var result,i=0;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i++];break}if(++i>=length)throw new TypeError(\"reduce of empty array with no initial value\")}for(;length>i;i++)i in self&&(result=fun.call(void 0,result,self[i],i,object));return result}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0;if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");if(!length&&1==arguments.length)throw new TypeError(\"reduceRight of empty array with no initial value\");var result,i=length-1;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i--];break}if(0>--i)throw new TypeError(\"reduceRight of empty array with no initial value\")}do i in this&&(result=fun.call(void 0,result,self[i],i,object));while(i--);return result}),Array.prototype.indexOf&&-1==[0,1].indexOf(1,2)||(Array.prototype.indexOf=function(sought){var self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):toObject(this),length=self.length>>>0;if(!length)return-1;var i=0;for(arguments.length>1&&(i=toInteger(arguments[1])),i=i>=0?i:Math.max(0,length+i);length>i;i++)if(i in self&&self[i]===sought)return i;return-1}),Array.prototype.lastIndexOf&&-1==[0,1].lastIndexOf(0,-3)||(Array.prototype.lastIndexOf=function(sought){var self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):toObject(this),length=self.length>>>0;if(!length)return-1;var i=length-1;for(arguments.length>1&&(i=Math.min(i,toInteger(arguments[1]))),i=i>=0?i:length-Math.abs(i);i>=0;i--)if(i in self&&sought===self[i])return i;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(object){return object.__proto__||(object.constructor?object.constructor.prototype:prototypeOfObject)}),!Object.getOwnPropertyDescriptor){var ERR_NON_OBJECT=\"Object.getOwnPropertyDescriptor called on a non-object: \";Object.getOwnPropertyDescriptor=function(object,property){if(\"object\"!=typeof object&&\"function\"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT+object);if(owns(object,property)){var descriptor,getter,setter;if(descriptor={enumerable:!0,configurable:!0},supportsAccessors){var prototype=object.__proto__;object.__proto__=prototypeOfObject;var getter=lookupGetter(object,property),setter=lookupSetter(object,property);if(object.__proto__=prototype,getter||setter)return getter&&(descriptor.get=getter),setter&&(descriptor.set=setter),descriptor}return descriptor.value=object[property],descriptor}}}if(Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(object){return Object.keys(object)}),!Object.create){var createEmpty;createEmpty=null===Object.prototype.__proto__?function(){return{__proto__:null}}:function(){var empty={};for(var i in empty)empty[i]=null;return empty.constructor=empty.hasOwnProperty=empty.propertyIsEnumerable=empty.isPrototypeOf=empty.toLocaleString=empty.toString=empty.valueOf=empty.__proto__=null,empty},Object.create=function(prototype,properties){var object;if(null===prototype)object=createEmpty();else{if(\"object\"!=typeof prototype)throw new TypeError(\"typeof prototype[\"+typeof prototype+\"] != 'object'\");var Type=function(){};Type.prototype=prototype,object=new Type,object.__proto__=prototype}return void 0!==properties&&Object.defineProperties(object,properties),object}}if(Object.defineProperty){var definePropertyWorksOnObject=doesDefinePropertyWork({}),definePropertyWorksOnDom=\"undefined\"==typeof document||doesDefinePropertyWork(document.createElement(\"div\"));if(!definePropertyWorksOnObject||!definePropertyWorksOnDom)var definePropertyFallback=Object.defineProperty}if(!Object.defineProperty||definePropertyFallback){var ERR_NON_OBJECT_DESCRIPTOR=\"Property description must be an object: \",ERR_NON_OBJECT_TARGET=\"Object.defineProperty called on non-object: \",ERR_ACCESSORS_NOT_SUPPORTED=\"getters & setters can not be defined on this javascript engine\";Object.defineProperty=function(object,property,descriptor){if(\"object\"!=typeof object&&\"function\"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT_TARGET+object);if(\"object\"!=typeof descriptor&&\"function\"!=typeof descriptor||null===descriptor)throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR+descriptor);if(definePropertyFallback)try{return definePropertyFallback.call(Object,object,property,descriptor)}catch(exception){}if(owns(descriptor,\"value\"))if(supportsAccessors&&(lookupGetter(object,property)||lookupSetter(object,property))){var prototype=object.__proto__;object.__proto__=prototypeOfObject,delete object[property],object[property]=descriptor.value,object.__proto__=prototype}else object[property]=descriptor.value;else{if(!supportsAccessors)throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);owns(descriptor,\"get\")&&defineGetter(object,property,descriptor.get),owns(descriptor,\"set\")&&defineSetter(object,property,descriptor.set)}return object}}Object.defineProperties||(Object.defineProperties=function(object,properties){for(var property in properties)owns(properties,property)&&Object.defineProperty(object,property,properties[property]);return object}),Object.seal||(Object.seal=function(object){return object}),Object.freeze||(Object.freeze=function(object){return object});try{Object.freeze(function(){})}catch(exception){Object.freeze=function(freezeObject){return function(object){return\"function\"==typeof object?object:freezeObject(object)}}(Object.freeze)}if(Object.preventExtensions||(Object.preventExtensions=function(object){return object}),Object.isSealed||(Object.isSealed=function(){return!1}),Object.isFrozen||(Object.isFrozen=function(){return!1}),Object.isExtensible||(Object.isExtensible=function(object){if(Object(object)===object)throw new TypeError;for(var name=\"\";owns(object,name);)name+=\"?\";object[name]=!0;var returnValue=owns(object,name);return delete object[name],returnValue}),!Object.keys){var hasDontEnumBug=!0,dontEnums=[\"toString\",\"toLocaleString\",\"valueOf\",\"hasOwnProperty\",\"isPrototypeOf\",\"propertyIsEnumerable\",\"constructor\"],dontEnumsLength=dontEnums.length;for(var key in{toString:null})hasDontEnumBug=!1;Object.keys=function(object){if(\"object\"!=typeof object&&\"function\"!=typeof object||null===object)throw new TypeError(\"Object.keys called on a non-object\");var keys=[];for(var name in object)owns(object,name)&&keys.push(name);if(hasDontEnumBug)for(var i=0,ii=dontEnumsLength;ii>i;i++){var dontEnum=dontEnums[i];owns(object,dontEnum)&&keys.push(dontEnum)}return keys}}Date.now||(Date.now=function(){return(new Date).getTime()});var ws=\"\t\\n\u000b\\f\\r   ᠎              \\u2028\\u2029\";if(!String.prototype.trim||ws.trim()){ws=\"[\"+ws+\"]\";var trimBeginRegexp=RegExp(\"^\"+ws+ws+\"*\"),trimEndRegexp=RegExp(ws+ws+\"*$\");String.prototype.trim=function(){return(this+\"\").replace(trimBeginRegexp,\"\").replace(trimEndRegexp,\"\")}}var toObject=function(o){if(null==o)throw new TypeError(\"can't convert \"+o+\" to object\");return Object(o)}});"; - -/***/ }, -/* 70 */ -/***/ function(module, exports) { - - ace.define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"], function(acequire, exports, module) { - "use strict"; - - var dom = acequire("../lib/dom"); - var lang = acequire("../lib/lang"); - var event = acequire("../lib/event"); - var searchboxCss = "\ - .ace_search {\ - background-color: #ddd;\ - color: #666;\ - border: 1px solid #cbcbcb;\ - border-top: 0 none;\ - overflow: hidden;\ - margin: 0;\ - padding: 4px 6px 0 4px;\ - position: absolute;\ - top: 0;\ - z-index: 99;\ - white-space: normal;\ - }\ - .ace_search.left {\ - border-left: 0 none;\ - border-radius: 0px 0px 5px 0px;\ - left: 0;\ - }\ - .ace_search.right {\ - border-radius: 0px 0px 0px 5px;\ - border-right: 0 none;\ - right: 0;\ - }\ - .ace_search_form, .ace_replace_form {\ - margin: 0 20px 4px 0;\ - overflow: hidden;\ - line-height: 1.9;\ - }\ - .ace_replace_form {\ - margin-right: 0;\ - }\ - .ace_search_form.ace_nomatch {\ - outline: 1px solid red;\ - }\ - .ace_search_field {\ - border-radius: 3px 0 0 3px;\ - background-color: white;\ - color: black;\ - border: 1px solid #cbcbcb;\ - border-right: 0 none;\ - box-sizing: border-box!important;\ - outline: 0;\ - padding: 0;\ - font-size: inherit;\ - margin: 0;\ - line-height: inherit;\ - padding: 0 6px;\ - min-width: 17em;\ - vertical-align: top;\ - }\ - .ace_searchbtn {\ - border: 1px solid #cbcbcb;\ - line-height: inherit;\ - display: inline-block;\ - padding: 0 6px;\ - background: #fff;\ - border-right: 0 none;\ - border-left: 1px solid #dcdcdc;\ - cursor: pointer;\ - margin: 0;\ - position: relative;\ - box-sizing: content-box!important;\ - color: #666;\ - }\ - .ace_searchbtn:last-child {\ - border-radius: 0 3px 3px 0;\ - border-right: 1px solid #cbcbcb;\ - }\ - .ace_searchbtn:disabled {\ - background: none;\ - cursor: default;\ - }\ - .ace_searchbtn:hover {\ - background-color: #eef1f6;\ - }\ - .ace_searchbtn.prev, .ace_searchbtn.next {\ - padding: 0px 0.7em\ - }\ - .ace_searchbtn.prev:after, .ace_searchbtn.next:after {\ - content: \"\";\ - border: solid 2px #888;\ - width: 0.5em;\ - height: 0.5em;\ - border-width: 2px 0 0 2px;\ - display:inline-block;\ - transform: rotate(-45deg);\ - }\ - .ace_searchbtn.next:after {\ - border-width: 0 2px 2px 0 ;\ - }\ - .ace_searchbtn_close {\ - background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;\ - border-radius: 50%;\ - border: 0 none;\ - color: #656565;\ - cursor: pointer;\ - font: 16px/16px Arial;\ - padding: 0;\ - height: 14px;\ - width: 14px;\ - top: 9px;\ - right: 7px;\ - position: absolute;\ - }\ - .ace_searchbtn_close:hover {\ - background-color: #656565;\ - background-position: 50% 100%;\ - color: white;\ - }\ - .ace_button {\ - margin-left: 2px;\ - cursor: pointer;\ - -webkit-user-select: none;\ - -moz-user-select: none;\ - -o-user-select: none;\ - -ms-user-select: none;\ - user-select: none;\ - overflow: hidden;\ - opacity: 0.7;\ - border: 1px solid rgba(100,100,100,0.23);\ - padding: 1px;\ - box-sizing: border-box!important;\ - color: black;\ - }\ - .ace_button:hover {\ - background-color: #eee;\ - opacity:1;\ - }\ - .ace_button:active {\ - background-color: #ddd;\ - }\ - .ace_button.checked {\ - border-color: #3399ff;\ - opacity:1;\ - }\ - .ace_search_options{\ - margin-bottom: 3px;\ - text-align: right;\ - -webkit-user-select: none;\ - -moz-user-select: none;\ - -o-user-select: none;\ - -ms-user-select: none;\ - user-select: none;\ - clear: both;\ - }\ - .ace_search_counter {\ - float: left;\ - font-family: arial;\ - padding: 0 8px;\ - }"; - var HashHandler = acequire("../keyboard/hash_handler").HashHandler; - var keyUtil = acequire("../lib/keys"); - - var MAX_COUNT = 999; - - dom.importCssString(searchboxCss, "ace_searchbox"); - - var html = ''.replace(/> +/g, ">"); - - var SearchBox = function(editor, range, showReplaceForm) { - var div = dom.createElement("div"); - div.innerHTML = html; - this.element = div.firstChild; - - this.setSession = this.setSession.bind(this); - - this.$init(); - this.setEditor(editor); - }; - - (function() { - this.setEditor = function(editor) { - editor.searchBox = this; - editor.renderer.scroller.appendChild(this.element); - this.editor = editor; - }; - - this.setSession = function(e) { - this.searchRange = null; - this.$syncOptions(true); - }; - - this.$initElements = function(sb) { - this.searchBox = sb.querySelector(".ace_search_form"); - this.replaceBox = sb.querySelector(".ace_replace_form"); - this.searchOption = sb.querySelector("[action=searchInSelection]"); - this.replaceOption = sb.querySelector("[action=toggleReplace]"); - this.regExpOption = sb.querySelector("[action=toggleRegexpMode]"); - this.caseSensitiveOption = sb.querySelector("[action=toggleCaseSensitive]"); - this.wholeWordOption = sb.querySelector("[action=toggleWholeWords]"); - this.searchInput = this.searchBox.querySelector(".ace_search_field"); - this.replaceInput = this.replaceBox.querySelector(".ace_search_field"); - this.searchCounter = sb.querySelector(".ace_search_counter"); - }; - - this.$init = function() { - var sb = this.element; - - this.$initElements(sb); - - var _this = this; - event.addListener(sb, "mousedown", function(e) { - setTimeout(function(){ - _this.activeInput.focus(); - }, 0); - event.stopPropagation(e); - }); - event.addListener(sb, "click", function(e) { - var t = e.target || e.srcElement; - var action = t.getAttribute("action"); - if (action && _this[action]) - _this[action](); - else if (_this.$searchBarKb.commands[action]) - _this.$searchBarKb.commands[action].exec(_this); - event.stopPropagation(e); - }); - - event.addCommandKeyListener(sb, function(e, hashId, keyCode) { - var keyString = keyUtil.keyCodeToString(keyCode); - var command = _this.$searchBarKb.findKeyCommand(hashId, keyString); - if (command && command.exec) { - command.exec(_this); - event.stopEvent(e); - } - }); - - this.$onChange = lang.delayedCall(function() { - _this.find(false, false); - }); - - event.addListener(this.searchInput, "input", function() { - _this.$onChange.schedule(20); - }); - event.addListener(this.searchInput, "focus", function() { - _this.activeInput = _this.searchInput; - _this.searchInput.value && _this.highlight(); - }); - event.addListener(this.replaceInput, "focus", function() { - _this.activeInput = _this.replaceInput; - _this.searchInput.value && _this.highlight(); - }); - }; - this.$closeSearchBarKb = new HashHandler([{ - bindKey: "Esc", - name: "closeSearchBar", - exec: function(editor) { - editor.searchBox.hide(); - } - }]); - this.$searchBarKb = new HashHandler(); - this.$searchBarKb.bindKeys({ - "Ctrl-f|Command-f": function(sb) { - var isReplace = sb.isReplace = !sb.isReplace; - sb.replaceBox.style.display = isReplace ? "" : "none"; - sb.replaceOption.checked = false; - sb.$syncOptions(); - sb.searchInput.focus(); - }, - "Ctrl-H|Command-Option-F": function(sb) { - sb.replaceOption.checked = true; - sb.$syncOptions(); - sb.replaceInput.focus(); - }, - "Ctrl-G|Command-G": function(sb) { - sb.findNext(); - }, - "Ctrl-Shift-G|Command-Shift-G": function(sb) { - sb.findPrev(); - }, - "esc": function(sb) { - setTimeout(function() { sb.hide();}); - }, - "Return": function(sb) { - if (sb.activeInput == sb.replaceInput) - sb.replace(); - sb.findNext(); - }, - "Shift-Return": function(sb) { - if (sb.activeInput == sb.replaceInput) - sb.replace(); - sb.findPrev(); - }, - "Alt-Return": function(sb) { - if (sb.activeInput == sb.replaceInput) - sb.replaceAll(); - sb.findAll(); - }, - "Tab": function(sb) { - (sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus(); - } - }); - - this.$searchBarKb.addCommands([{ - name: "toggleRegexpMode", - bindKey: {win: "Alt-R|Alt-/", mac: "Ctrl-Alt-R|Ctrl-Alt-/"}, - exec: function(sb) { - sb.regExpOption.checked = !sb.regExpOption.checked; - sb.$syncOptions(); - } - }, { - name: "toggleCaseSensitive", - bindKey: {win: "Alt-C|Alt-I", mac: "Ctrl-Alt-R|Ctrl-Alt-I"}, - exec: function(sb) { - sb.caseSensitiveOption.checked = !sb.caseSensitiveOption.checked; - sb.$syncOptions(); - } - }, { - name: "toggleWholeWords", - bindKey: {win: "Alt-B|Alt-W", mac: "Ctrl-Alt-B|Ctrl-Alt-W"}, - exec: function(sb) { - sb.wholeWordOption.checked = !sb.wholeWordOption.checked; - sb.$syncOptions(); - } - }, { - name: "toggleReplace", - exec: function(sb) { - sb.replaceOption.checked = !sb.replaceOption.checked; - sb.$syncOptions(); - } - }, { - name: "searchInSelection", - exec: function(sb) { - sb.searchOption.checked = !sb.searchRange; - sb.setSearchRange(sb.searchOption.checked && sb.editor.getSelectionRange()); - sb.$syncOptions(); - } - }]); - - this.setSearchRange = function(range) { - this.searchRange = range; - if (range) { - this.searchRangeMarker = this.editor.session.addMarker(range, "ace_active-line"); - } else if (this.searchRangeMarker) { - this.editor.session.removeMarker(this.searchRangeMarker); - this.searchRangeMarker = null; - } - }; - - this.$syncOptions = function(preventScroll) { - dom.setCssClass(this.replaceOption, "checked", this.searchRange); - dom.setCssClass(this.searchOption, "checked", this.searchOption.checked); - this.replaceOption.textContent = this.replaceOption.checked ? "-" : "+"; - dom.setCssClass(this.regExpOption, "checked", this.regExpOption.checked); - dom.setCssClass(this.wholeWordOption, "checked", this.wholeWordOption.checked); - dom.setCssClass(this.caseSensitiveOption, "checked", this.caseSensitiveOption.checked); - this.replaceBox.style.display = this.replaceOption.checked ? "" : "none"; - this.find(false, false, preventScroll); - }; - - this.highlight = function(re) { - this.editor.session.highlight(re || this.editor.$search.$options.re); - this.editor.renderer.updateBackMarkers(); - }; - this.find = function(skipCurrent, backwards, preventScroll) { - var range = this.editor.find(this.searchInput.value, { - skipCurrent: skipCurrent, - backwards: backwards, - wrap: true, - regExp: this.regExpOption.checked, - caseSensitive: this.caseSensitiveOption.checked, - wholeWord: this.wholeWordOption.checked, - preventScroll: preventScroll, - range: this.searchRange - }); - var noMatch = !range && this.searchInput.value; - dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); - this.editor._emit("findSearchBox", { match: !noMatch }); - this.highlight(); - this.updateCounter(); - }; - this.updateCounter = function() { - var editor = this.editor; - var regex = editor.$search.$options.re; - var all = 0; - var before = 0; - if (regex) { - var value = this.searchRange - ? editor.session.getTextRange(this.searchRange) - : editor.getValue(); - - var offset = editor.session.doc.positionToIndex(editor.selection.anchor); - if (this.searchRange) - offset -= editor.session.doc.positionToIndex(this.searchRange.start); - - var last = regex.lastIndex = 0; - var m; - while ((m = regex.exec(value))) { - all++; - last = m.index; - if (last <= offset) - before++; - if (all > MAX_COUNT) - break; - if (!m[0]) { - regex.lastIndex = last += 1; - if (last >= value.length) - break; - } - } - } - this.searchCounter.textContent = before + " of " + (all > MAX_COUNT ? MAX_COUNT + "+" : all); - }; - this.findNext = function() { - this.find(true, false); - }; - this.findPrev = function() { - this.find(true, true); - }; - this.findAll = function(){ - var range = this.editor.findAll(this.searchInput.value, { - regExp: this.regExpOption.checked, - caseSensitive: this.caseSensitiveOption.checked, - wholeWord: this.wholeWordOption.checked - }); - var noMatch = !range && this.searchInput.value; - dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); - this.editor._emit("findSearchBox", { match: !noMatch }); - this.highlight(); - this.hide(); - }; - this.replace = function() { - if (!this.editor.getReadOnly()) - this.editor.replace(this.replaceInput.value); - }; - this.replaceAndFindNext = function() { - if (!this.editor.getReadOnly()) { - this.editor.replace(this.replaceInput.value); - this.findNext(); - } - }; - this.replaceAll = function() { - if (!this.editor.getReadOnly()) - this.editor.replaceAll(this.replaceInput.value); - }; - - this.hide = function() { - this.active = false; - this.setSearchRange(null); - this.editor.off("changeSession", this.setSession); - - this.element.style.display = "none"; - this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb); - this.editor.focus(); - }; - this.show = function(value, isReplace) { - this.active = true; - this.editor.on("changeSession", this.setSession); - this.element.style.display = ""; - this.replaceOption.checked = isReplace; - - if (value) - this.searchInput.value = value; - - this.searchInput.focus(); - this.searchInput.select(); - - this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb); - - this.$syncOptions(true); - }; - - this.isFocused = function() { - var el = document.activeElement; - return el == this.searchInput || el == this.replaceInput; - }; - }).call(SearchBox.prototype); - - exports.SearchBox = SearchBox; - - exports.Search = function(editor, isReplace) { - var sb = editor.searchBox || new SearchBox(editor); - sb.show(editor.session.getTextRange(), isReplace); - }; - - }); - (function() { - ace.acequire(["ace/ext/searchbox"], function() {}); - })(); - - -/***/ }, -/* 71 */ -/***/ function(module, exports) { - - /* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2010, Ajax.org B.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Ajax.org B.V. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ - - ace.define('ace/theme/jsoneditor', ['require', 'exports', 'module', 'ace/lib/dom'], function(acequire, exports, module) { - - exports.isDark = false; - exports.cssClass = "ace-jsoneditor"; - exports.cssText = ".ace-jsoneditor .ace_gutter {\ - background: #ebebeb;\ - color: #333\ - }\ - \ - .ace-jsoneditor.ace_editor {\ - font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif;\ - line-height: 1.3;\ - background-color: #fff;\ - }\ - .ace-jsoneditor .ace_print-margin {\ - width: 1px;\ - background: #e8e8e8\ - }\ - .ace-jsoneditor .ace_scroller {\ - background-color: #FFFFFF\ - }\ - .ace-jsoneditor .ace_text-layer {\ - color: gray\ - }\ - .ace-jsoneditor .ace_variable {\ - color: #1a1a1a\ - }\ - .ace-jsoneditor .ace_cursor {\ - border-left: 2px solid #000000\ - }\ - .ace-jsoneditor .ace_overwrite-cursors .ace_cursor {\ - border-left: 0px;\ - border-bottom: 1px solid #000000\ - }\ - .ace-jsoneditor .ace_marker-layer .ace_selection {\ - background: lightgray\ - }\ - .ace-jsoneditor.ace_multiselect .ace_selection.ace_start {\ - box-shadow: 0 0 3px 0px #FFFFFF;\ - border-radius: 2px\ - }\ - .ace-jsoneditor .ace_marker-layer .ace_step {\ - background: rgb(255, 255, 0)\ - }\ - .ace-jsoneditor .ace_marker-layer .ace_bracket {\ - margin: -1px 0 0 -1px;\ - border: 1px solid #BFBFBF\ - }\ - .ace-jsoneditor .ace_marker-layer .ace_active-line {\ - background: #FFFBD1\ - }\ - .ace-jsoneditor .ace_gutter-active-line {\ - background-color : #dcdcdc\ - }\ - .ace-jsoneditor .ace_marker-layer .ace_selected-word {\ - border: 1px solid lightgray\ - }\ - .ace-jsoneditor .ace_invisible {\ - color: #BFBFBF\ - }\ - .ace-jsoneditor .ace_keyword,\ - .ace-jsoneditor .ace_meta,\ - .ace-jsoneditor .ace_support.ace_constant.ace_property-value {\ - color: #AF956F\ - }\ - .ace-jsoneditor .ace_keyword.ace_operator {\ - color: #484848\ - }\ - .ace-jsoneditor .ace_keyword.ace_other.ace_unit {\ - color: #96DC5F\ - }\ - .ace-jsoneditor .ace_constant.ace_language {\ - color: darkorange\ - }\ - .ace-jsoneditor .ace_constant.ace_numeric {\ - color: red\ - }\ - .ace-jsoneditor .ace_constant.ace_character.ace_entity {\ - color: #BF78CC\ - }\ - .ace-jsoneditor .ace_invalid {\ - color: #FFFFFF;\ - background-color: #FF002A;\ - }\ - .ace-jsoneditor .ace_fold {\ - background-color: #AF956F;\ - border-color: #000000\ - }\ - .ace-jsoneditor .ace_storage,\ - .ace-jsoneditor .ace_support.ace_class,\ - .ace-jsoneditor .ace_support.ace_function,\ - .ace-jsoneditor .ace_support.ace_other,\ - .ace-jsoneditor .ace_support.ace_type {\ - color: #C52727\ - }\ - .ace-jsoneditor .ace_string {\ - color: green\ - }\ - .ace-jsoneditor .ace_comment {\ - color: #BCC8BA\ - }\ - .ace-jsoneditor .ace_entity.ace_name.ace_tag,\ - .ace-jsoneditor .ace_entity.ace_other.ace_attribute-name {\ - color: #606060\ - }\ - .ace-jsoneditor .ace_markup.ace_underline {\ - text-decoration: underline\ - }\ - .ace-jsoneditor .ace_indent-guide {\ - background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y\ - }"; - - var dom = acequire("../lib/dom"); - dom.importCssString(exports.cssText, exports.cssClass); - }); - - -/***/ } -/******/ ]) -}); -; \ No newline at end of file diff --git a/main/webapp/modules/core/langs/translation-en.json b/main/webapp/modules/core/langs/translation-en.json index 481d1fba0..30294f66d 100644 --- a/main/webapp/modules/core/langs/translation-en.json +++ b/main/webapp/modules/core/langs/translation-en.json @@ -75,7 +75,6 @@ "core-index-import/warning-data-file": "You must specify a data file to import.", "core-index-import/uploading-data": "Uploading data ...", "core-index-import/web-address": "Web Addresses (URLs)", - "core-index-import/data-package": "Data Package (JSON URL)", "core-index-import/warning-web-address": "You must specify a web address (URL) to import.", "core-index-import/downloading-data": "Downloading data ...", "core-index-import/clipboard": "Clipboard", diff --git a/main/webapp/modules/core/scripts/index/default-importing-controller/file-selection-panel.js b/main/webapp/modules/core/scripts/index/default-importing-controller/file-selection-panel.js index ef52445d4..90c63b722 100644 --- a/main/webapp/modules/core/scripts/index/default-importing-controller/file-selection-panel.js +++ b/main/webapp/modules/core/scripts/index/default-importing-controller/file-selection-panel.js @@ -158,9 +158,7 @@ Refine.DefaultImportingController.prototype._renderFileSelectionPanelFileTable = } self._updateFileSelectionSummary(); }); - if (fileRecord.metaDataFormat) { - checkbox.removeAttr("checked").attr("disabled", "disabled"); - } else if (fileRecord.selected) { + if (fileRecord.selected) { // Initial selection determined on server side. checkbox.attr("checked", "checked"); self._selectedMap[fileRecord.location] = fileRecord; diff --git a/main/webapp/modules/core/scripts/index/default-importing-sources/import-from-data-package-form.html b/main/webapp/modules/core/scripts/index/default-importing-sources/import-from-data-package-form.html deleted file mode 100644 index 638e0cd84..000000000 --- a/main/webapp/modules/core/scripts/index/default-importing-sources/import-from-data-package-form.html +++ /dev/null @@ -1,7 +0,0 @@ -
- - - - - -
\ No newline at end of file diff --git a/main/webapp/modules/core/scripts/index/default-importing-sources/sources.js b/main/webapp/modules/core/scripts/index/default-importing-sources/sources.js index 1a6e5e18b..f46468d38 100644 --- a/main/webapp/modules/core/scripts/index/default-importing-sources/sources.js +++ b/main/webapp/modules/core/scripts/index/default-importing-sources/sources.js @@ -130,35 +130,3 @@ ClipboardImportingSourceUI.prototype.focus = function() { this._elmts.textInput.focus(); }; -// data package source: -function DataPackageImportingSourceUI(controller) { - this._controller = controller; - } - Refine.DefaultImportingController.sources.push({ - "label": $.i18n('core-index-import/data-package'), - "id": "data-package", - "uiClass": DataPackageImportingSourceUI - }); - - DataPackageImportingSourceUI.prototype.attachUI = function(bodyDiv) { - var self = this; - - bodyDiv.html(DOM.loadHTML("core", "scripts/index/default-importing-sources/import-from-data-package-form.html")); - - this._elmts = DOM.bind(bodyDiv); - - $('#or-import-enterurl').text($.i18n('core-index-import/enter-url')); - this._elmts.nextButton.html($.i18n('core-buttons/next')); - - this._elmts.nextButton.click(function(evt) { - if ($.trim(self._elmts.urlInput[0].value).length === 0) { - window.alert($.i18n('core-index-import/warning-web-address')); - } else { - self._controller.startImportJob(self._elmts.form, $.i18n('core-index-import/data-package')); - } - }); - }; - - DataPackageImportingSourceUI.prototype.focus = function() { - this._elmts.urlInput.focus(); - }; diff --git a/main/webapp/modules/core/scripts/index/edit-metadata-dialog.js b/main/webapp/modules/core/scripts/index/edit-metadata-dialog.js index 6fd584c11..96d2e1eb1 100644 --- a/main/webapp/modules/core/scripts/index/edit-metadata-dialog.js +++ b/main/webapp/modules/core/scripts/index/edit-metadata-dialog.js @@ -12,23 +12,24 @@ function EditMetadataDialog(metaData, targetRowElem) { } var td0 = tr.insertCell(0); + + var keyLable = $.i18n._('core-index')[key] || key; + $(td0).text(keyLable); var td1 = tr.insertCell(1); - var keyLable = $.i18n('core-index/'+key) || key; - $(td1).text(keyLable); + $(td1).text((value !== null) ? value : ""); var td2 = tr.insertCell(2); - $(td2).text((value !== null) ? value : ""); if(key==="tags"){ - $('