This is an automated email from the ASF dual-hosted git repository.
joshinnis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-age.git
The following commit(s) were added to refs/heads/master by this push:
new 50fce50 fix: (driver/nodejs) fix problems that occur when an object
is empty or nested. (#104)
50fce50 is described below
commit 50fce50480ff7beabf72aadf8386c10dbd6402dd
Author: Alex Kwak <[email protected]>
AuthorDate: Wed Dec 1 05:21:59 2021 +0900
fix: (driver/nodejs) fix problems that occur when an object is empty or
nested. (#104)
---
drivers/nodejs/src/antlr4/CustomAgTypeListener.ts | 219 ++++++++++++++--------
drivers/nodejs/test/Agtype.test.ts | 36 +++-
2 files changed, 173 insertions(+), 82 deletions(-)
diff --git a/drivers/nodejs/src/antlr4/CustomAgTypeListener.ts
b/drivers/nodejs/src/antlr4/CustomAgTypeListener.ts
index 0319f5c..e2e662c 100644
--- a/drivers/nodejs/src/antlr4/CustomAgTypeListener.ts
+++ b/drivers/nodejs/src/antlr4/CustomAgTypeListener.ts
@@ -30,102 +30,159 @@ import { ParseTreeListener } from
'antlr4ts/tree/ParseTreeListener'
type MapOrArray = Map<string, any> | any[];
class CustomAgTypeListener implements AgtypeListener, ParseTreeListener {
- rootObject?: MapOrArray;
- objectInsider: MapOrArray[] = [];
- lastValue: any = null;
-
- exitStringValue (ctx: StringValueContext): void {
- this.lastValue = this.stripQuotes(ctx.text)
+ rootObject?: MapOrArray;
+ objectInsider: MapOrArray[] = [];
+ prevObject?: MapOrArray;
+ lastObject?: MapOrArray;
+ lastValue: any = undefined;
+
+ mergeArrayOrObject (key: string) {
+ if (this.prevObject instanceof Array) {
+ this.mergeArray()
+ } else {
+ this.mergeObject(key)
+ }
+ }
+
+ mergeArray () {
+ if (this.prevObject !== undefined && this.lastObject !== undefined &&
this.prevObject instanceof Array) {
+ this.prevObject.push(this.lastObject)
+ this.lastObject = this.prevObject
+ this.objectInsider.shift()
+ this.prevObject = this.objectInsider[1]
+ }
+ }
+
+ mergeObject (key: string) {
+ if (this.prevObject !== undefined && this.lastObject !== undefined &&
this.prevObject instanceof Map) {
+ this.prevObject.set(key, this.lastObject)
+ this.lastObject = this.prevObject
+ this.objectInsider.shift()
+ this.prevObject = this.objectInsider[1]
}
-
- exitIntegerValue (ctx: IntegerValueContext): void {
- this.lastValue = parseInt(ctx.text)
+ }
+
+ createNewObject () {
+ const newObject = new Map()
+ this.objectInsider.unshift(newObject)
+ this.prevObject = this.lastObject
+ this.lastObject = newObject
+ }
+
+ createNewArray () {
+ const newObject: any[] = []
+ this.objectInsider.unshift(newObject)
+ this.prevObject = this.lastObject
+ this.lastObject = newObject
+ }
+
+ pushIfArray (value: any) {
+ if (this.lastObject instanceof Array) {
+ this.lastObject.push(value)
+ return true
}
+ return false
+ }
+
+ exitStringValue (ctx: StringValueContext): void {
+ const value = this.stripQuotes(ctx.text)
+ if (!this.pushIfArray(value)) {
+ this.lastValue = value
+ }
+ }
+
+ exitIntegerValue (ctx: IntegerValueContext): void {
+ const value = parseInt(ctx.text)
+ if (!this.pushIfArray(value)) {
+ this.lastValue = value
+ }
+ }
+
+ exitFloatValue (ctx: FloatValueContext): void {
+ const value = parseFloat(ctx.text)
+ if (!this.pushIfArray(value)) {
+ this.lastValue = value
+ }
+ }
+
+ exitTrueBoolean (): void {
+ const value = true
+ if (!this.pushIfArray(value)) {
+ this.lastValue = value
+ }
+ }
+
+ exitFalseBoolean (): void {
+ const value = false
+ if (!this.pushIfArray(value)) {
+ this.lastValue = value
+ }
+ }
+
+ exitNullValue (): void {
+ const value = null
+ if (!this.pushIfArray(value)) {
+ this.lastValue = value
+ }
+ }
+
+ exitFloatLiteral (ctx: FloatLiteralContext): void {
+ const value = ctx.text
+ if (!this.pushIfArray(value)) {
+ this.lastValue = value
+ }
+ }
- exitFloatValue (ctx: FloatValueContext): void {
- this.lastValue = parseFloat(ctx.text)
- }
+ enterObjectValue (): void {
+ this.createNewObject()
+ }
- exitTrueBoolean (): void {
- this.lastValue = true
- }
+ enterArrayValue (): void {
+ this.createNewArray()
+ }
- exitFalseBoolean (): void {
- this.lastValue = false
- }
+ exitObjectValue (): void {
+ this.mergeArray()
+ }
- exitNullValue (): void {
- this.lastValue = null
- }
+ exitPair (ctx: PairContext): void {
+ const name = this.stripQuotes(ctx.STRING().text)
- enterObjectValue (): void {
- this.objectInsider.unshift(new Map())
- this.lastValue = this.objectInsider[0]
+ if (this.lastValue !== undefined) {
+ (this.lastObject as Map<string, any>).set(name, this.lastValue)
+ this.lastValue = undefined
+ } else {
+ this.mergeArrayOrObject(name)
}
+ }
- exitObjectValue (): void {
- if (this.objectInsider.length >= 2 && this.objectInsider[1] instanceof
Array) {
- const currentObject = this.objectInsider.shift()!;
- (this.objectInsider[0]! as any[]).push(currentObject)
- }
- }
+ exitAgType (): void {
+ this.rootObject = this.objectInsider.shift()
+ }
- enterArrayValue (): void {
- this.objectInsider.unshift([])
- this.lastValue = this.objectInsider[0]
- }
+ stripQuotes (quotesString: string) {
+ return JSON.parse(quotesString)
+ }
- exitArrayValue (): void {
- if (this.objectInsider.length >= 2 && this.objectInsider[1] instanceof
Array) {
- // if objectInsider == Object then is pair or root
- const currentObject = this.objectInsider.shift();
- (this.objectInsider[0]! as any[]).push(currentObject)
- }
- }
+ getResult () {
+ this.objectInsider = []
+ this.prevObject = undefined
+ this.lastObject = undefined
+ this.lastValue = undefined
+ return this.rootObject
+ }
- exitPair (ctx: PairContext): void {
- const name = this.stripQuotes(ctx.STRING().text)
-
- if (this.lastValue !== undefined) {
- (this.objectInsider[0] as Map<string, any>).set(name, this.lastValue)
- this.lastValue = undefined
- } else {
- const lastValue = this.objectInsider.shift()
- if (this.objectInsider[0] instanceof Array) {
- this.objectInsider[0].push(lastValue)
- } else {
- (this.objectInsider[0] as Map<string, any>).set(name, lastValue)
- }
- }
- }
+ enterEveryRule (): void {
+ }
- exitFloatLiteral (ctx: FloatLiteralContext): void {
- this.lastValue = ctx.text
- }
+ exitEveryRule (): void {
+ }
- exitAgType (): void {
- this.rootObject = this.objectInsider.shift()
- }
+ visitErrorNode (): void {
+ }
- stripQuotes (quotesString: string) {
- return JSON.parse(quotesString)
- }
-
- getResult () {
- return this.rootObject
- }
-
- enterEveryRule (): void {
- }
-
- exitEveryRule (): void {
- }
-
- visitErrorNode (): void {
- }
-
- visitTerminal (): void {
- }
+ visitTerminal (): void {
+ }
}
export default CustomAgTypeListener
diff --git a/drivers/nodejs/test/Agtype.test.ts
b/drivers/nodejs/test/Agtype.test.ts
index e19a21d..27f5f4e 100644
--- a/drivers/nodejs/test/Agtype.test.ts
+++ b/drivers/nodejs/test/Agtype.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { AGTypeParse } from '../dist'
+import { AGTypeParse } from '../src'
describe('Parsing', () => {
it('Vertex', async () => {
@@ -33,6 +33,7 @@ describe('Parsing', () => {
}))
})))
})
+
it('Edge', async () => {
expect(
AGTypeParse('{"id": 1125899906842625, "label": "used_by", "end_id":
844424930131970, "start_id": 844424930131969, "properties": {"quantity":
1}}::edge')
@@ -44,6 +45,7 @@ describe('Parsing', () => {
properties: new Map(Object.entries({ quantity: 1 }))
})))
})
+
it('Path', async () => {
expect(
AGTypeParse('[{"id": 844424930131969, "label": "Part", "properties":
{"part_num": "123"}}::vertex, {"id": 1125899906842625, "label": "used_by",
"end_id": 844424930131970, "start_id": 844424930131969, "properties":
{"quantity": 1}}::edge, {"id": 844424930131970, "label": "Part", "properties":
{"part_num": "345"}}::vertex]::path')
@@ -67,4 +69,36 @@ describe('Parsing', () => {
}))
])
})
+
+ it('Null Properties', async () => {
+ expect(
+ AGTypeParse('{"id": 1688849860263937, "label": "car", "properties":
{}}::vertex')
+ ).toStrictEqual(new Map<string, any>(Object.entries({
+ id: 1688849860263937,
+ label: 'car',
+ properties: new Map(Object.entries({}))
+ })))
+ })
+
+ it('Nested Agtype', () => {
+ expect(
+ AGTypeParse('{"id": 1688849860263937, "label": "car", "properties":
{"a": {"b":{"c":{"d":[1, 2, "A"]}}}}}::vertex')
+ ).toStrictEqual(new Map<string, any>(Object.entries({
+ id: 1688849860263937,
+ label: 'car',
+ properties: new Map<string, any>(Object.entries({
+ a: new Map<string, any>(Object.entries({
+ b: new Map<string, any>(Object.entries({
+ c: new Map<string, any>(Object.entries({
+ d: [
+ 1,
+ 2,
+ 'A'
+ ]
+ }))
+ }))
+ }))
+ }))
+ })))
+ })
})