Skip to content

Implemented map function for Record. #494

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 107 additions & 4 deletions src/graph-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,23 @@
* limitations under the License.
*/

const IDENTIFIER_PROPERTY_ATTRIBUTES = {
value: true,
enumerable: false,
configurable: false,
writable: false
}

const NODE_IDENTIFIER_PROPERTY = '__isNode__'
const RELATIONSHIP_IDENTIFIER_PROPERTY = '__isRelationship__'
const UNBOUND_RELATIONSHIP_IDENTIFIER_PROPERTY = '__isUnboundRelationship__'
const PATH_IDENTIFIER_PROPERTY = '__isPath__'
const PATH_SEGMENT_IDENTIFIER_PROPERTY = '__isPathSegment__'

function hasIdentifierProperty (obj, property) {
return (obj && obj[property]) === true
}

/**
* Class for Node Type.
*/
Expand Down Expand Up @@ -54,7 +71,7 @@ class Node {
for (let i = 0; i < this.labels.length; i++) {
s += ':' + this.labels[i]
}
let keys = Object.keys(this.properties)
const keys = Object.keys(this.properties)
if (keys.length > 0) {
s += ' {'
for (let i = 0; i < keys.length; i++) {
Expand All @@ -68,6 +85,21 @@ class Node {
}
}

Object.defineProperty(
Node.prototype,
NODE_IDENTIFIER_PROPERTY,
IDENTIFIER_PROPERTY_ATTRIBUTES
)

/**
* Test if given object is an instance of {@link Node} class.
* @param {Object} obj the object to test.
* @return {boolean} `true` if given object is a {@link Node}, `false` otherwise.
*/
function isNode (obj) {
return hasIdentifierProperty(obj, NODE_IDENTIFIER_PROPERTY)
}

/**
* Class for Relationship Type.
*/
Expand Down Expand Up @@ -114,7 +146,7 @@ class Relationship {
*/
toString () {
let s = '(' + this.start + ')-[:' + this.type
let keys = Object.keys(this.properties)
const keys = Object.keys(this.properties)
if (keys.length > 0) {
s += ' {'
for (let i = 0; i < keys.length; i++) {
Expand All @@ -128,6 +160,21 @@ class Relationship {
}
}

Object.defineProperty(
Relationship.prototype,
RELATIONSHIP_IDENTIFIER_PROPERTY,
IDENTIFIER_PROPERTY_ATTRIBUTES
)

/**
* Test if given object is an instance of {@link Relationship} class.
* @param {Object} obj the object to test.
* @return {boolean} `true` if given object is a {@link Relationship}, `false` otherwise.
*/
function isRelationship (obj) {
return hasIdentifierProperty(obj, RELATIONSHIP_IDENTIFIER_PROPERTY)
}

/**
* Class for UnboundRelationship Type.
* @access private
Expand Down Expand Up @@ -181,7 +228,7 @@ class UnboundRelationship {
*/
toString () {
let s = '-[:' + this.type
let keys = Object.keys(this.properties)
const keys = Object.keys(this.properties)
if (keys.length > 0) {
s += ' {'
for (let i = 0; i < keys.length; i++) {
Expand All @@ -195,6 +242,21 @@ class UnboundRelationship {
}
}

Object.defineProperty(
UnboundRelationship.prototype,
UNBOUND_RELATIONSHIP_IDENTIFIER_PROPERTY,
IDENTIFIER_PROPERTY_ATTRIBUTES
)

/**
* Test if given object is an instance of {@link UnboundRelationship} class.
* @param {Object} obj the object to test.
* @return {boolean} `true` if given object is a {@link UnboundRelationship}, `false` otherwise.
*/
function isUnboundRelationship (obj) {
return hasIdentifierProperty(obj, UNBOUNT_RELATIONSHIP_IDENTIFIER_PROPERTY)
}

/**
* Class for PathSegment Type.
*/
Expand Down Expand Up @@ -225,6 +287,21 @@ class PathSegment {
}
}

Object.defineProperty(
PathSegment.prototype,
PATH_SEGMENT_IDENTIFIER_PROPERTY,
IDENTIFIER_PROPERTY_ATTRIBUTES
)

/**
* Test if given object is an instance of {@link PathSegment} class.
* @param {Object} obj the object to test.
* @return {boolean} `true` if given object is a {@link PathSegment}, `false` otherwise.
*/
function isPathSegment (obj) {
return hasIdentifierProperty(obj, PATH_SEGMENT_IDENTIFIER_PROPERTY)
}

/**
* Class for Path Type.
*/
Expand Down Expand Up @@ -260,4 +337,30 @@ class Path {
}
}

export { Node, Relationship, UnboundRelationship, Path, PathSegment }
Object.defineProperty(
Path.prototype,
PATH_IDENTIFIER_PROPERTY,
IDENTIFIER_PROPERTY_ATTRIBUTES
)

/**
* Test if given object is an instance of {@link Path} class.
* @param {Object} obj the object to test.
* @return {boolean} `true` if given object is a {@link Path}, `false` otherwise.
*/
function isPath (obj) {
return hasIdentifierProperty(obj, PATH_IDENTIFIER_PROPERTY)
}

export {
Node,
isNode,
Relationship,
isRelationship,
UnboundRelationship,
isUnboundRelationship,
Path,
isPath,
PathSegment,
isPathSegment
}
22 changes: 21 additions & 1 deletion src/record.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import { newError } from './error'

function generateFieldLookup (keys) {
let lookup = {}
const lookup = {}
keys.forEach((name, idx) => {
lookup[name] = idx
})
Expand Down Expand Up @@ -85,6 +85,26 @@ class Record {
}
}

/**
* Run the given function for each field in this record. The function
* will get three arguments - the value, the key and this record, in that
* order.
*
* @param {function(value: Object, key: string, record: Record)} visitor the function to apply on each field
* and return a value that is saved to the returned Array.
*
* @returns {Array}
*/
map (visitor) {
const resultArray = []

for (let i = 0; i < this.keys.length; i++) {
resultArray.push(visitor(this._fields[i], this.keys[i], this))
}

return resultArray
}

/**
* Generates an object out of the current Record
*
Expand Down
11 changes: 6 additions & 5 deletions src/spatial-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ export class Point {
toString () {
return this.z || this.z === 0
? `Point{srid=${formatAsFloat(this.srid)}, x=${formatAsFloat(
this.x
)}, y=${formatAsFloat(this.y)}, z=${formatAsFloat(this.z)}}`
this.x
)}, y=${formatAsFloat(this.y)}, z=${formatAsFloat(this.z)}}`
: `Point{srid=${formatAsFloat(this.srid)}, x=${formatAsFloat(
this.x
)}, y=${formatAsFloat(this.y)}}`
this.x
)}, y=${formatAsFloat(this.y)}}`
}
}

Expand All @@ -77,7 +77,8 @@ function formatAsFloat (number) {
Object.defineProperty(Point.prototype, POINT_IDENTIFIER_PROPERTY, {
value: true,
enumerable: false,
configurable: false
configurable: false,
writable: false
})

/**
Expand Down
3 changes: 2 additions & 1 deletion src/temporal-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import { newError } from './error'
const IDENTIFIER_PROPERTY_ATTRIBUTES = {
value: true,
enumerable: false,
configurable: false
configurable: false,
writable: false
}

const DURATION_IDENTIFIER_PROPERTY = '__isDuration__'
Expand Down
13 changes: 13 additions & 0 deletions test/record.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,17 @@ describe('#unit Record', () => {
// Then
expect(result).toEqual([['Bob', 'name', record], [45, 'age', record]])
})

it('should allow map function for the record', () => {
// Given
const record = new Record(['name', 'age'], ['Bob', 45])

// When
const result = record.map((value, key, rec) => {
return [value, key, rec]
})

// Then
expect(result).toEqual([['Bob', 'name', record], [45, 'age', record]])
})
})
12 changes: 11 additions & 1 deletion test/types/graph-types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ import {
Path,
PathSegment,
Relationship,
UnboundRelationship
UnboundRelationship,
isNode,
isPath,
isPathSegment,
isRelationship,
isUnboundRelationship
} from '../../types/graph-types'
import Integer, { int } from '../../types/integer'

Expand All @@ -32,6 +37,7 @@ const node1Id: Integer = node1.identity
const node1Labels: string[] = node1.labels
const node1Props: object = node1.properties
const isNode1: boolean = node1 instanceof Node
const isNode1B: boolean = isNode(node1)

const node2: Node<number> = new Node(2, ['Person', 'Employee'], {
name: 'Alice'
Expand All @@ -48,6 +54,7 @@ const rel1End: Integer = rel1.end
const rel1Type: string = rel1.type
const rel1Props: object = rel1.properties
const isRel1: boolean = rel1 instanceof Relationship
const isRel1B: boolean = isRelationship(rel1)

const rel2: UnboundRelationship = new UnboundRelationship(int(1), 'KNOWS', {
since: 12345
Expand All @@ -58,6 +65,7 @@ const rel2Id: Integer = rel2.identity
const rel2Type: string = rel2.type
const rel2Props: object = rel2.properties
const isRel2: boolean = rel2 instanceof UnboundRelationship
const isRel2B: boolean = isUnboundRelationship(rel2)

const rel4: Relationship<number> = new Relationship(2, 3, 4, 'KNOWS', {
since: 12345
Expand All @@ -82,6 +90,7 @@ const pathSegment1Start: Node = pathSegment1.start
const pathSegment1Rel: Relationship = pathSegment1.relationship
const pathSegment1End: Node = pathSegment1.end
const isPathSegment1: boolean = pathSegment1 instanceof PathSegment
const isPathSegment1B: boolean = isPathSegment(pathSegment1)

const pathSegment2: PathSegment<number> = new PathSegment(node2, rel4, node2)
const pathSegment2Start: Node<number> = pathSegment2.start
Expand All @@ -94,6 +103,7 @@ const path1End: Node = path1.end
const path1Segments: PathSegment[] = path1.segments
const path1Length: number = path1.length
const isPath1: boolean = path1 instanceof Path
const isPath1B: boolean = isPath(path1)

const path2: Path<number> = new Path(node2, node2, [pathSegment2])
const path2Start: Node<number> = path2.start
Expand Down
15 changes: 15 additions & 0 deletions types/graph-types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,27 @@ declare class Path<T extends NumberOrInteger = Integer> {
constructor(start: Node<T>, end: Node<T>, segments: PathSegment<T>[])
}

declare function isNode(obj: object): boolean

declare function isRelationship(obj: object): boolean

declare function isUnboundRelationship(obj: object): boolean

declare function isPath(obj: object): boolean

declare function isPathSegment(obj: object): boolean

export {
Node,
Relationship,
UnboundRelationship,
Path,
PathSegment,
isNode,
isRelationship,
isUnboundRelationship,
isPath,
isPathSegment,
NumberOrInteger,
StandardDate
}
4 changes: 4 additions & 0 deletions types/record.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

declare type Visitor = (value: any, key: string, record: Record) => void

declare type MapVisitor<T> = (value: any, key: string, record: Record) => T

declare class Record {
keys: string[]
length: number
Expand All @@ -31,6 +33,8 @@ declare class Record {

forEach(visitor: Visitor): void

map<T>(visitor: MapVisitor<T>): T[]

toObject(): object

get(key: string | number): any
Expand Down