init
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
import static java.math.MathContext.DECIMAL128
|
||||
|
||||
BigDecimal RES = 0
|
||||
int i = 0
|
||||
ROWS.each { row ->
|
||||
COLUMNS.each { column ->
|
||||
def value = row.value(column)
|
||||
if (value instanceof Number) {
|
||||
RES = RES.add(value, DECIMAL128)
|
||||
i++
|
||||
}
|
||||
else if (value.toString().isBigDecimal()) {
|
||||
RES = RES.add(value.toString().toBigDecimal(), DECIMAL128)
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i > 0) {
|
||||
RES = RES.divide(i, DECIMAL128)
|
||||
OUT.append(RES.toString())
|
||||
}
|
||||
else {
|
||||
OUT.append("Not enough values")
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
import static java.math.MathContext.DECIMAL128
|
||||
|
||||
def toBigDecimal = { value ->
|
||||
value instanceof Number ? value as BigDecimal :
|
||||
value.toString().isBigDecimal() ? value.toString() as BigDecimal :
|
||||
null
|
||||
}
|
||||
|
||||
def values = []
|
||||
|
||||
ROWS.each { row ->
|
||||
COLUMNS.each { column ->
|
||||
def bigDecimal = toBigDecimal(row.value(column))
|
||||
if (bigDecimal != null) {
|
||||
values.add(bigDecimal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (values.isEmpty()) {
|
||||
OUT.append("Not enough values")
|
||||
return
|
||||
}
|
||||
|
||||
def sum = BigDecimal.ZERO
|
||||
values.forEach { value ->
|
||||
sum = sum.add(value, DECIMAL128)
|
||||
}
|
||||
def avg = sum.divide(values.size(), DECIMAL128)
|
||||
def sumSquaredDiff = BigDecimal.ZERO
|
||||
values.each { value ->
|
||||
BigDecimal diff = value.subtract(avg, DECIMAL128)
|
||||
sumSquaredDiff = sumSquaredDiff.add(diff.multiply(diff, DECIMAL128), DECIMAL128)
|
||||
}
|
||||
|
||||
def variance = sumSquaredDiff.divide(values.size(), DECIMAL128)
|
||||
def standardDeviation = variance.sqrt(DECIMAL128)
|
||||
def cv = standardDeviation.divide(avg, DECIMAL128)
|
||||
OUT.append((cv * 100).round(2) + "%")
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
OUT.append(COLUMNS.size().toString())
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
def RES = 0G
|
||||
ROWS.each { row ->
|
||||
COLUMNS.each { column ->
|
||||
RES += 1
|
||||
}
|
||||
}
|
||||
OUT.append(RES.toString())
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
def RES = 0G
|
||||
ROWS.each { row ->
|
||||
COLUMNS.each { column ->
|
||||
def value = row.value(column)
|
||||
if (value instanceof Number) {
|
||||
RES += 1
|
||||
}
|
||||
else if (value.toString().isBigDecimal()) {
|
||||
RES += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
OUT.append(RES.toString())
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
|
||||
values = new ArrayList<BigDecimal>()
|
||||
ROWS.each { row ->
|
||||
COLUMNS.each { column ->
|
||||
def value = row.value(column)
|
||||
if (value instanceof Number) {
|
||||
values.add(value as BigDecimal)
|
||||
}
|
||||
else if (value.toString().isBigDecimal()) {
|
||||
values.add(value.toString() as BigDecimal)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (values.size() == 0) {
|
||||
OUT.append("Not enough values")
|
||||
return
|
||||
}
|
||||
OUT.append(Collections.max(values).toString())
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
import static java.math.MathContext.DECIMAL128
|
||||
|
||||
def toBigDecimal = { value ->
|
||||
value instanceof Number ? value as BigDecimal :
|
||||
value.toString().isBigDecimal() ? value.toString() as BigDecimal :
|
||||
null
|
||||
}
|
||||
|
||||
def values = []
|
||||
|
||||
ROWS.each { row ->
|
||||
COLUMNS.each { column ->
|
||||
def bigDecimal = toBigDecimal(row.value(column))
|
||||
if (bigDecimal != null) {
|
||||
values.add(bigDecimal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (values.isEmpty()) {
|
||||
OUT.append("Not enough values")
|
||||
return
|
||||
}
|
||||
elementsNumber = values.size()
|
||||
Collections.sort(values)
|
||||
mid = (int)elementsNumber / 2
|
||||
RES = elementsNumber % 2 != 0 ? values[mid] : values[mid].add(values[mid - 1], DECIMAL128).divide(2, DECIMAL128)
|
||||
OUT.append(RES.toString())
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
values = new ArrayList<BigDecimal>()
|
||||
ROWS.each { row ->
|
||||
COLUMNS.each { column ->
|
||||
def value = row.value(column)
|
||||
if (value instanceof Number) {
|
||||
values.add(value as BigDecimal)
|
||||
}
|
||||
else if (value.toString().isBigDecimal()) {
|
||||
values.add(value.toString() as BigDecimal)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (values.size() == 0) {
|
||||
OUT.append("Not enough values")
|
||||
return
|
||||
}
|
||||
OUT.append(Collections.min(values).toString())
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
OUT.append(ROWS.size().toString())
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
import static java.math.MathContext.DECIMAL128
|
||||
|
||||
BigDecimal RES = 0
|
||||
ROWS.each { row ->
|
||||
COLUMNS.each { column ->
|
||||
def value = row.value(column)
|
||||
if (value instanceof Number) {
|
||||
RES = RES.add(value, DECIMAL128)
|
||||
}
|
||||
else if (value.toString().isBigDecimal()) {
|
||||
RES = RES.add(value.toString().toBigDecimal(), DECIMAL128)
|
||||
}
|
||||
}
|
||||
}
|
||||
OUT.append(RES.toString())
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
SEPARATOR = ","
|
||||
QUOTE = "\""
|
||||
NEWLINE = System.getProperty("line.separator")
|
||||
|
||||
def printRow = { values, valueToString ->
|
||||
values.eachWithIndex { value, idx ->
|
||||
def str = valueToString(value)
|
||||
def q = str.contains(SEPARATOR) || str.contains(QUOTE) || str.contains(NEWLINE)
|
||||
OUT.append(q ? QUOTE : "")
|
||||
.append(str.replace(QUOTE, QUOTE + QUOTE))
|
||||
.append(q ? QUOTE : "")
|
||||
.append(idx != values.size() - 1 ? SEPARATOR : NEWLINE)
|
||||
}
|
||||
}
|
||||
|
||||
if (!TRANSPOSED) {
|
||||
ROWS.each { row -> printRow(COLUMNS, { FORMATTER.format(row, it) }) }
|
||||
}
|
||||
else {
|
||||
def values = COLUMNS.collect { new ArrayList<String>() }
|
||||
ROWS.each { row -> COLUMNS.eachWithIndex { col, i -> values[i].add(FORMATTER.format(row, col)) } }
|
||||
values.each { printRow(it, { it }) }
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
import static com.intellij.openapi.util.text.StringUtil.escapeXmlEntities
|
||||
|
||||
NEWLINE = System.getProperty("line.separator")
|
||||
|
||||
def HTML_PATTERN = ~"<.+>"
|
||||
|
||||
def printRow = { values, tag, valueToString ->
|
||||
OUT.append("$NEWLINE<tr>$NEWLINE")
|
||||
values.each {
|
||||
def str = valueToString(it)
|
||||
def escaped = str ==~ HTML_PATTERN
|
||||
? str
|
||||
: escapeXmlEntities((str as String).replaceAll("\\t|\\b|\\f", "")).replaceAll("\\r|\\n|\\r\\n", "<br/>")
|
||||
OUT.append(" <$tag>$escaped</$tag>$NEWLINE")
|
||||
}
|
||||
OUT.append("</tr>")
|
||||
}
|
||||
|
||||
OUT.append(
|
||||
"""<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<table border="1" style="border-collapse:collapse">""")
|
||||
|
||||
if (!TRANSPOSED) {
|
||||
printRow(COLUMNS, "th") { it.name() }
|
||||
ROWS.each { row -> printRow(COLUMNS, "td") { FORMATTER.format(row, it) } }
|
||||
}
|
||||
else {
|
||||
def values = COLUMNS.collect { new ArrayList<String>( [it.name()] ) }
|
||||
ROWS.each { row -> COLUMNS.eachWithIndex { col, i -> values[i].add(FORMATTER.format(row, col)) } }
|
||||
values.each { printRow(it, "td", { it }) }
|
||||
}
|
||||
|
||||
OUT.append("""
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
""")
|
||||
@@ -0,0 +1,49 @@
|
||||
function eachWithIdx(iterable, f) { var i = iterable.iterator(); var idx = 0; while (i.hasNext()) f(i.next(), idx++); }
|
||||
function mapEach(iterable, f) { var vs = []; eachWithIdx(iterable, function (i) { vs.push(f(i));}); return vs; }
|
||||
function escape(str) {
|
||||
str = str.replace(/\t|\b|\f/g, "");
|
||||
str = com.intellij.openapi.util.text.StringUtil.escapeXml(str);
|
||||
str = str.replace(/\r|\n|\r\n/g, "<br/>");
|
||||
return str;
|
||||
}
|
||||
var isHTML = RegExp.prototype.test.bind(/^<.+>$/);
|
||||
|
||||
var NEWLINE = "\n";
|
||||
|
||||
function output() { for (var i = 0; i < arguments.length; i++) { OUT.append(arguments[i]); } }
|
||||
function outputRow(items, tag) {
|
||||
output("<tr>");
|
||||
for (var i = 0; i < items.length; i++)
|
||||
output("<", tag, ">", isHTML(items[i]) ? items[i] : escape(items[i]), "</", tag, ">");
|
||||
output("</tr>", NEWLINE);
|
||||
}
|
||||
|
||||
|
||||
output("<!DOCTYPE html>", NEWLINE,
|
||||
"<html>", NEWLINE,
|
||||
"<head>", NEWLINE,
|
||||
"<title></title>", NEWLINE,
|
||||
"<meta charset=\"UTF-8\">", NEWLINE,
|
||||
"</head>", NEWLINE,
|
||||
"<body>", NEWLINE,
|
||||
"<table border=\"1\" style=\"border-collapse:collapse\">", NEWLINE);
|
||||
|
||||
if (TRANSPOSED) {
|
||||
var values = mapEach(COLUMNS, function(col) { return [col.name()]; });
|
||||
eachWithIdx(ROWS, function (row) {
|
||||
eachWithIdx(COLUMNS, function (col, i) {
|
||||
values[i].push(FORMATTER.format(row, col));
|
||||
});
|
||||
});
|
||||
eachWithIdx(COLUMNS, function (_, i) { outputRow(values[i], "td"); });
|
||||
}
|
||||
else {
|
||||
outputRow(mapEach(COLUMNS, function (col) { return col.name(); }), "th");
|
||||
eachWithIdx(ROWS, function (row) {
|
||||
outputRow(mapEach(COLUMNS, function (col) { return FORMATTER.format(row, col); }), "td")
|
||||
});
|
||||
}
|
||||
|
||||
output("</table>", NEWLINE,
|
||||
"</body>", NEWLINE,
|
||||
"</html>", NEWLINE);
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
|
||||
import static com.intellij.openapi.util.text.StringUtil.escapeStringCharacters as escapeStr
|
||||
|
||||
NEWLINE = System.getProperty("line.separator")
|
||||
INDENT = " "
|
||||
|
||||
def printJSON(level, col, o) {
|
||||
switch (o) {
|
||||
case null: OUT.append("null"); break
|
||||
case Tuple: printJSON(level, o[0], o[1]); break
|
||||
case Map:
|
||||
OUT.append("{")
|
||||
o.entrySet().eachWithIndex { entry, i ->
|
||||
OUT.append("${i > 0 ? "," : ""}$NEWLINE${INDENT * (level + 1)}")
|
||||
OUT.append("\"${escapeStr(entry.getKey().toString())}\"")
|
||||
OUT.append(": ")
|
||||
printJSON(level + 1, col, entry.getValue())
|
||||
}
|
||||
OUT.append("$NEWLINE${INDENT * level}}")
|
||||
break
|
||||
case Object[]:
|
||||
case Iterable:
|
||||
OUT.append("[")
|
||||
def plain = true
|
||||
o.eachWithIndex { item, i ->
|
||||
plain = item == null || item instanceof Number || item instanceof Boolean || item instanceof String
|
||||
if (plain) {
|
||||
OUT.append(i > 0 ? ", " : "")
|
||||
}
|
||||
else {
|
||||
OUT.append("${i > 0 ? "," : ""}$NEWLINE${INDENT * (level + 1)}")
|
||||
}
|
||||
printJSON(level + 1, col, item)
|
||||
}
|
||||
if (plain) OUT.append("]") else OUT.append("$NEWLINE${INDENT * level}]")
|
||||
break
|
||||
case Boolean: OUT.append("$o"); break
|
||||
default:
|
||||
def str = FORMATTER.formatValue(o, col)
|
||||
def typeName = FORMATTER.getTypeName(o, col)
|
||||
def shouldQuote = FORMATTER.isStringLiteral(o, col) && !(typeName.equalsIgnoreCase("json") || typeName.equalsIgnoreCase("jsonb"))
|
||||
OUT.append(shouldQuote ? "\"${escapeStr(str)}\"" : str);
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
printJSON(0, null, ROWS.transform { row ->
|
||||
def map = new LinkedHashMap<String, Object>()
|
||||
COLUMNS.each { col ->
|
||||
if (row.hasValue(col)) {
|
||||
def val = row.value(col)
|
||||
map.put(col.name(), new Tuple(col, val))
|
||||
}
|
||||
}
|
||||
map
|
||||
})
|
||||
@@ -0,0 +1,65 @@
|
||||
package extensions.data.extractors
|
||||
|
||||
NEWLINE = System.getProperty("line.separator")
|
||||
SEPARATOR = "|"
|
||||
BACKSLASH = "\\"
|
||||
BACKQUOTE = "`"
|
||||
LTAG = "<"
|
||||
RTAG = ">"
|
||||
ASTERISK = "*"
|
||||
UNDERSCORE = "_"
|
||||
LPARENTH = "("
|
||||
RPARENTH = ")"
|
||||
LBRACKET = "["
|
||||
RBRACKET = "]"
|
||||
TILDE = "~"
|
||||
|
||||
def printRow = { values, firstBold = false, valueToString ->
|
||||
values.eachWithIndex { value, idx ->
|
||||
def str = valueToString(value)
|
||||
.replace(BACKSLASH, BACKSLASH + BACKSLASH)
|
||||
.replace(SEPARATOR, BACKSLASH + SEPARATOR)
|
||||
.replace(BACKQUOTE, BACKSLASH + BACKQUOTE)
|
||||
.replace(ASTERISK, BACKSLASH + ASTERISK)
|
||||
.replace(UNDERSCORE, BACKSLASH + UNDERSCORE)
|
||||
.replace(LPARENTH, BACKSLASH + LPARENTH)
|
||||
.replace(RPARENTH, BACKSLASH + RPARENTH)
|
||||
.replace(LBRACKET, BACKSLASH + LBRACKET)
|
||||
.replace(RBRACKET, BACKSLASH + RBRACKET)
|
||||
.replace(TILDE, BACKSLASH + TILDE)
|
||||
.replace(LTAG, "<")
|
||||
.replace(RTAG, ">")
|
||||
.replaceAll("\r\n|\r|\n", "<br/>")
|
||||
.replaceAll("\t|\b|\f", "")
|
||||
|
||||
OUT.append("| ")
|
||||
.append(firstBold && idx == 0 ? "**" : "")
|
||||
.append(str)
|
||||
.append(firstBold && idx == 0 ? "**" : "")
|
||||
.append(idx != values.size() - 1 ? " " : " |" + NEWLINE)
|
||||
}
|
||||
}
|
||||
|
||||
if (TRANSPOSED) {
|
||||
def values = COLUMNS.collect { new ArrayList<String>([it.name()]) }
|
||||
def rowCount = 0
|
||||
ROWS.forEach { row ->
|
||||
COLUMNS.eachWithIndex { col, i -> values[i].add(FORMATTER.format(row, col)) }
|
||||
rowCount++
|
||||
}
|
||||
for (int i = 0; i <= rowCount; i++) {
|
||||
OUT.append("| ")
|
||||
}
|
||||
OUT.append("|" + NEWLINE)
|
||||
for (int i = 0; i <= rowCount; i++) {
|
||||
OUT.append("| :- ")
|
||||
}
|
||||
OUT.append("|" + NEWLINE)
|
||||
values.each { printRow(it, true) { it } }
|
||||
}
|
||||
else {
|
||||
printRow(COLUMNS) { it.name() }
|
||||
COLUMNS.each { OUT.append("| :--- ") }
|
||||
OUT.append("|" + NEWLINE)
|
||||
ROWS.each { row -> printRow(COLUMNS) { FORMATTER.format(row, it) } }
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
SEPARATOR = ", "
|
||||
QUOTE = "'"
|
||||
STRING_PREFIX = DIALECT.getDbms().isMicrosoft() ? "N" : ""
|
||||
KEYWORDS_LOWERCASE = com.intellij.database.util.DbSqlUtil.areKeywordsLowerCase(PROJECT)
|
||||
KW_NULL = KEYWORDS_LOWERCASE ? "null" : "NULL"
|
||||
|
||||
first = true
|
||||
ROWS.each { row ->
|
||||
COLUMNS.each { column ->
|
||||
def value = row.value(column)
|
||||
def stringValue = value == null ? KW_NULL : FORMATTER.formatValue(value, column)
|
||||
def isStringLiteral = value != null && FORMATTER.isStringLiteral(value, column)
|
||||
if (isStringLiteral && DIALECT.getDbms().isMysql()) stringValue = stringValue.replace("\\", "\\\\")
|
||||
OUT.append(first ? "" : SEPARATOR)
|
||||
.append(isStringLiteral ? (STRING_PREFIX + QUOTE) : "")
|
||||
.append(stringValue ? stringValue.replace(QUOTE, QUOTE + QUOTE) : stringValue)
|
||||
.append(isStringLiteral ? QUOTE : "")
|
||||
first = false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
|
||||
WIDTH_BASED_ON_CONTENT = -1
|
||||
|
||||
PIPE = "|"
|
||||
SPACE = " "
|
||||
CROSS = "+"
|
||||
MINUS = "-"
|
||||
ROW_SEPARATORS = false
|
||||
COLUMN_WIDTH = WIDTH_BASED_ON_CONTENT
|
||||
NEWLINE = System.getProperty("line.separator")
|
||||
|
||||
static def splitByLines(values, size) {
|
||||
def splitValues = new ArrayList<>()
|
||||
def maxLines = 0
|
||||
for (int i = 0; i < size; i++) {
|
||||
def splitValue = StringUtil.splitByLines(values(i))
|
||||
splitValues.add(splitValue)
|
||||
maxLines = Math.max(maxLines, splitValue.size())
|
||||
}
|
||||
|
||||
def byLines = new ArrayList<>(maxLines)
|
||||
for (int i = 0; i < maxLines; i++) {
|
||||
def lineValues = new ArrayList<>()
|
||||
byLines.add(lineValues)
|
||||
for (int j = 0; j < splitValues.size(); j++) {
|
||||
def splitValue = splitValues[j]
|
||||
lineValues.add(splitValue.size() <= i ? null : splitValue[i])
|
||||
}
|
||||
}
|
||||
return byLines
|
||||
}
|
||||
|
||||
def printRow(values, size, width = { COLUMN_WIDTH }, padding = SPACE, separator = { PIPE }) {
|
||||
def byLines = splitByLines(values, size)
|
||||
byLines.each { line ->
|
||||
def lineSize = line.size()
|
||||
if (lineSize > 0) OUT.append(separator(-1))
|
||||
for (int i = 0; i < lineSize; i++) {
|
||||
def value = line[i] == null ? "" : line.get(i)
|
||||
def curWidth = width(i)
|
||||
OUT.append(value.padRight(curWidth, padding))
|
||||
OUT.append(separator(i))
|
||||
}
|
||||
OUT.append(NEWLINE)
|
||||
}
|
||||
}
|
||||
|
||||
def printRows() {
|
||||
def colNames = COLUMNS.collect { it.name() }
|
||||
def calcWidth = COLUMN_WIDTH == WIDTH_BASED_ON_CONTENT
|
||||
def rows
|
||||
def width
|
||||
def rowFormatter
|
||||
if (calcWidth) {
|
||||
rows = new ArrayList<>()
|
||||
def widths = new int[COLUMNS.size()]
|
||||
COLUMNS.eachWithIndex { column, idx -> widths[idx] = column.name().length() }
|
||||
ROWS.each { row ->
|
||||
def rowValues = COLUMNS.withIndex().collect { col, idx ->
|
||||
def value = FORMATTER.format(row, col)
|
||||
widths[idx] = Math.max(widths[idx], value.length())
|
||||
value
|
||||
}
|
||||
rows.add(rowValues)
|
||||
}
|
||||
width = { widths[it] }
|
||||
rowFormatter = { it }
|
||||
}
|
||||
else {
|
||||
rows = ROWS
|
||||
width = { COLUMN_WIDTH }
|
||||
rowFormatter = { COLUMNS.collect { col -> FORMATTER.format(it, col) } }
|
||||
}
|
||||
|
||||
printRow({""}, COLUMNS.size(), { width(it) }, MINUS) { CROSS }
|
||||
printRow( { colNames[it] }, COLUMNS.size()) { width(it) }
|
||||
|
||||
def first = true
|
||||
rows.each { row ->
|
||||
def rowValues = rowFormatter(row)
|
||||
if (first || ROW_SEPARATORS) printRow({""}, COLUMNS.size(), { width(it) }, MINUS) { first ? CROSS : MINUS }
|
||||
printRow({ rowValues[it] }, rowValues.size()) { width(it) }
|
||||
first = false
|
||||
}
|
||||
printRow({""}, COLUMNS.size(), { width(it) }, MINUS) { CROSS }
|
||||
}
|
||||
|
||||
def printRowsTransposed() {
|
||||
def calcWidth = COLUMN_WIDTH == WIDTH_BASED_ON_CONTENT
|
||||
if (calcWidth) {
|
||||
COLUMN_WIDTHS = new ArrayList<Integer>()
|
||||
COLUMN_WIDTHS.add(0)
|
||||
}
|
||||
def valuesByRow = COLUMNS.collect { col ->
|
||||
if (calcWidth) COLUMN_WIDTHS.set(0, Math.max(COLUMN_WIDTHS[0], col.name().length()))
|
||||
new ArrayList<String>([col.name()])
|
||||
}
|
||||
def rowCount = 1
|
||||
ROWS.each { row ->
|
||||
rowCount++
|
||||
COLUMNS.eachWithIndex { col, i ->
|
||||
def formattedValue = FORMATTER.format(row, col)
|
||||
valuesByRow[i].add(formattedValue)
|
||||
def widthIdx = rowCount - 1
|
||||
def length = formattedValue.length()
|
||||
if (calcWidth) {
|
||||
if (COLUMN_WIDTHS.size() == widthIdx) COLUMN_WIDTHS.add(length)
|
||||
COLUMN_WIDTHS.set(widthIdx, Math.max(COLUMN_WIDTHS[widthIdx], length))
|
||||
}
|
||||
}
|
||||
}
|
||||
valuesByRow.each { row ->
|
||||
printRow({ "" }, rowCount, { calcWidth ? COLUMN_WIDTHS[it] : COLUMN_WIDTH }, MINUS) {
|
||||
it <= 0 ? CROSS : it == rowCount - 1 ? CROSS : MINUS
|
||||
}
|
||||
printRow({ row[it] }, row.size()) { calcWidth ? COLUMN_WIDTHS[it] : COLUMN_WIDTH }
|
||||
}
|
||||
printRow({ "" }, rowCount, { calcWidth ? COLUMN_WIDTHS[it] : COLUMN_WIDTH }, MINUS) {
|
||||
it <= 0 ? CROSS : it == rowCount - 1 ? CROSS : MINUS
|
||||
}
|
||||
}
|
||||
|
||||
if (TRANSPOSED) {
|
||||
printRowsTransposed()
|
||||
}
|
||||
else {
|
||||
printRows()
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
SEP = ", "
|
||||
QUOTE = "\'"
|
||||
STRING_PREFIX = DIALECT.getDbms().isMicrosoft() ? "N" : ""
|
||||
NEWLINE = System.getProperty("line.separator")
|
||||
|
||||
KEYWORDS_LOWERCASE = com.intellij.database.util.DbSqlUtil.areKeywordsLowerCase(PROJECT)
|
||||
KW_INSERT_INTO = KEYWORDS_LOWERCASE ? "insert into " : "INSERT INTO "
|
||||
KW_VALUES = KEYWORDS_LOWERCASE ? "values" : "VALUES"
|
||||
KW_NULL = KEYWORDS_LOWERCASE ? "null" : "NULL"
|
||||
|
||||
begin = true
|
||||
|
||||
def record(columns, dataRow) {
|
||||
|
||||
if (begin) {
|
||||
OUT.append(KW_INSERT_INTO)
|
||||
if (TABLE == null) OUT.append("MY_TABLE")
|
||||
else OUT.append(TABLE.getParent().getName()).append(".").append(TABLE.getName())
|
||||
OUT.append(" (")
|
||||
|
||||
columns.eachWithIndex { column, idx ->
|
||||
OUT.append(column.name()).append(idx != columns.size() - 1 ? SEP : "")
|
||||
}
|
||||
|
||||
OUT.append(")").append(NEWLINE)
|
||||
OUT.append(KW_VALUES).append(" (")
|
||||
begin = false
|
||||
}
|
||||
else {
|
||||
OUT.append(",").append(NEWLINE)
|
||||
OUT.append(" (")
|
||||
}
|
||||
|
||||
columns.eachWithIndex { column, idx ->
|
||||
def value = dataRow.value(column)
|
||||
def stringValue = value == null ? KW_NULL : FORMATTER.formatValue(value, column)
|
||||
def isStringLiteral = value != null && FORMATTER.isStringLiteral(value, column)
|
||||
if (isStringLiteral && DIALECT.getDbms().isMysql()) stringValue = stringValue.replace("\\", "\\\\")
|
||||
OUT.append(isStringLiteral ? (STRING_PREFIX + QUOTE) : "")
|
||||
.append(stringValue ? stringValue.replace(QUOTE, QUOTE + QUOTE) : stringValue)
|
||||
.append(isStringLiteral ? QUOTE : "")
|
||||
.append(idx != columns.size() - 1 ? SEP : "")
|
||||
}
|
||||
OUT.append(")")
|
||||
}
|
||||
|
||||
ROWS.each { row -> record(COLUMNS, row) }
|
||||
OUT.append(";")
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
SEP = ", "
|
||||
QUOTE = "\'"
|
||||
STRING_PREFIX = DIALECT.getDbms().isMicrosoft() ? "N" : ""
|
||||
NEWLINE = System.getProperty("line.separator")
|
||||
|
||||
KEYWORDS_LOWERCASE = com.intellij.database.util.DbSqlUtil.areKeywordsLowerCase(PROJECT)
|
||||
KW_INSERT_INTO = KEYWORDS_LOWERCASE ? "insert into " : "INSERT INTO "
|
||||
KW_VALUES = KEYWORDS_LOWERCASE ? ") values (" : ") VALUES ("
|
||||
KW_NULL = KEYWORDS_LOWERCASE ? "null" : "NULL"
|
||||
|
||||
def record(columns, dataRow) {
|
||||
OUT.append(KW_INSERT_INTO)
|
||||
if (TABLE == null) OUT.append("MY_TABLE")
|
||||
else OUT.append(TABLE.getParent().getName()).append(".").append(TABLE.getName())
|
||||
OUT.append(" (")
|
||||
|
||||
columns.eachWithIndex { column, idx ->
|
||||
OUT.append(column.name()).append(idx != columns.size() - 1 ? SEP : "")
|
||||
}
|
||||
|
||||
OUT.append(KW_VALUES)
|
||||
columns.eachWithIndex { column, idx ->
|
||||
def value = dataRow.value(column)
|
||||
def stringValue = value == null ? KW_NULL : FORMATTER.formatValue(value, column)
|
||||
def isStringLiteral = value != null && FORMATTER.isStringLiteral(value, column)
|
||||
if (isStringLiteral && DIALECT.getDbms().isMysql()) stringValue = stringValue.replace("\\", "\\\\")
|
||||
OUT.append(isStringLiteral ? (STRING_PREFIX + QUOTE) : "")
|
||||
.append(isStringLiteral ? stringValue.replace(QUOTE, QUOTE + QUOTE) : stringValue)
|
||||
.append(isStringLiteral ? QUOTE : "")
|
||||
.append(idx != columns.size() - 1 ? SEP : "")
|
||||
}
|
||||
OUT.append(");").append(NEWLINE)
|
||||
}
|
||||
|
||||
ROWS.each { row -> record(COLUMNS, row) }
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Available context bindings:
|
||||
* COLUMNS List<DataColumn>
|
||||
* ROWS Iterable<DataRow>
|
||||
* OUT { append() }
|
||||
* FORMATTER { format(row, col); formatValue(Object, col); getTypeName(Object, col); isStringLiteral(Object, col); }
|
||||
* TRANSPOSED Boolean
|
||||
* plus ALL_COLUMNS, TABLE, DIALECT
|
||||
*
|
||||
* where:
|
||||
* DataRow { rowNumber(); first(); last(); data(): List<Object>; value(column): Object }
|
||||
* DataColumn { columnNumber(), name() }
|
||||
*/
|
||||
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
NEWLINE = System.getProperty("line.separator")
|
||||
|
||||
pattern = Pattern.compile("[^\\w\\d]")
|
||||
def escapeTag(name) {
|
||||
name = pattern.matcher(name).replaceAll("_")
|
||||
return name.isEmpty() || !Character.isLetter(name.charAt(0)) ? "_$name" : name
|
||||
}
|
||||
def printRow(level, rowTag, values) {
|
||||
def prefix = "$NEWLINE${StringUtil.repeat(" ", level)}"
|
||||
OUT.append("$prefix<$rowTag>")
|
||||
values.each { name, col, valuesName, value ->
|
||||
switch (value) {
|
||||
case Map:
|
||||
def mapValues = new ArrayList<Tuple>()
|
||||
value.each { key, v -> mapValues.add(new Tuple(escapeTag(key.toString()), col, key.toString(), v)) }
|
||||
printRow(level + 1, name, mapValues)
|
||||
break
|
||||
case Object[]:
|
||||
case Iterable:
|
||||
def listItems = new ArrayList<Tuple>()
|
||||
def itemName = valuesName != null ? escapeTag(StringUtil.unpluralize(valuesName) ?: "item") : "item"
|
||||
value.collect { v -> listItems.add(new Tuple(itemName, col, null, v)) }
|
||||
printRow(level + 1, name, listItems)
|
||||
break
|
||||
default:
|
||||
OUT.append("$prefix <$name>")
|
||||
if (value == null) OUT.append("null")
|
||||
else {
|
||||
def formattedValue = FORMATTER.formatValue(value, col)
|
||||
if (isXmlString(formattedValue)) OUT.append(formattedValue)
|
||||
else OUT.append(StringUtil.escapeXmlEntities(formattedValue))
|
||||
}
|
||||
OUT.append("</$name>")
|
||||
}
|
||||
}
|
||||
OUT.append("$prefix</$rowTag>")
|
||||
}
|
||||
|
||||
def isXmlString(string) {
|
||||
return string.startsWith("<") && string.endsWith(">") && (string.contains("</") || string.contains("/>"))
|
||||
}
|
||||
|
||||
OUT.append(
|
||||
"""<?xml version="1.0" encoding="UTF-8"?>
|
||||
<data>""")
|
||||
|
||||
if (!TRANSPOSED) {
|
||||
ROWS.each { row ->
|
||||
def values = COLUMNS
|
||||
.findAll { col -> row.hasValue(col) }
|
||||
.collect { col ->
|
||||
new Tuple(escapeTag(col.name()), col, col.name(), row.value(col))
|
||||
}
|
||||
printRow(0, "row", values)
|
||||
}
|
||||
}
|
||||
else {
|
||||
def values = COLUMNS.collect { new ArrayList<Tuple>() }
|
||||
ROWS.eachWithIndex { row, rowIdx ->
|
||||
COLUMNS.eachWithIndex { col, colIdx ->
|
||||
if (row.hasValue(col)) {
|
||||
def value = row.value(col)
|
||||
values[colIdx].add(new Tuple("row${rowIdx + 1}", col, col.name(), value))
|
||||
}
|
||||
}
|
||||
}
|
||||
values.eachWithIndex { it, index ->
|
||||
printRow(0, escapeTag(COLUMNS[index].name()), it)
|
||||
}
|
||||
}
|
||||
|
||||
OUT.append("""
|
||||
</data>
|
||||
""")
|
||||
Reference in New Issue
Block a user