kirill-stepanishin commented on code in PR #3307: URL: https://github.com/apache/tinkerpop/pull/3307#discussion_r2819461100
########## gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/gremlin-lang.ts: ########## @@ -0,0 +1,183 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import { P, TextP, EnumValue } from './traversal.js'; +import { OptionsStrategy, TraversalStrategy } from './traversal-strategy.js'; +import { Long } from '../utils.js'; +import { Vertex } from '../structure/graph.js'; + +export default class GremlinLang { + private gremlin: string = ''; + private optionsStrategies: OptionsStrategy[] = []; + private parameters: Map<string, any> = new Map(); + + constructor(toClone?: GremlinLang) { + if (toClone) { + this.gremlin = toClone.gremlin; + this.optionsStrategies = [...toClone.optionsStrategies]; + this.parameters = new Map(toClone.parameters); + } + } + + getOptionsStrategies(): OptionsStrategy[] { + return this.optionsStrategies; + } + + addG(g: string): void { + this.parameters.set('g', g); + } + + getParameters(): Map<string, any> { + return this.parameters; + } + + private _predicateAsString(p: P | TextP): string { + if (p.operator === 'and' || p.operator === 'or') { + return `${this._predicateAsString(p.value)}.${p.operator}(${this._predicateAsString(p.other)})`; + } + + let result = p.operator + '('; + if (Array.isArray(p.value)) { + result += '[' + p.value.map(v => this._argAsString(v)).join(',') + ']'; + } else { + result += this._argAsString(p.value); + if (p.other !== undefined && p.other !== null) { + result += ',' + this._argAsString(p.other); + } + } + result += ')'; + return result; + } + + private _argAsString(arg: any): string { + if (arg === null || arg === undefined) return 'null'; + if (typeof arg === 'boolean') return arg ? 'true' : 'false'; + if (arg instanceof Long) { + return String(arg.value); + } + if (arg instanceof Date) { + const iso = arg.toISOString().replace('.000Z', 'Z'); + return `datetime("${iso}")`; + } + if (typeof arg === 'number') { + if (Number.isNaN(arg)) return 'NaN'; + if (arg === Infinity) return '+Infinity'; + if (arg === -Infinity) return '-Infinity'; + return String(arg); + } + if (typeof arg === 'string') { + const escaped = JSON.stringify(arg).slice(1, -1).replace(/'/g, "\\'"); Review Comment: `JSON.stringify()` escapes all special characters in one call, but wraps the result in double quotes and doesn't escape single quotes. So `.slice(1, -1)` to strip the double quotes, `.replace()` to escape single quotes, then wrap in single quotes for Gremlin. I think it also could either be done by nesting `.replace()` for every case or with a single `.replace()` + regex + replacer function, but it'd be more verbose and require manually maintaining the escape mapping. I'll add comment to clarify. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
