Skip to content

Commit 07e23ae

Browse files
rahulvudutalaMarkLogic Builder
authored andcommitted
DHFPROD-3581: Adding hub entity services library and tests
1 parent 13c343d commit 07e23ae

File tree

4 files changed

+311
-0
lines changed

4 files changed

+311
-0
lines changed
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/**
2+
Copyright 2012-2019 MarkLogic Corporation
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
'use strict';
18+
const sem = require("/MarkLogic/semantics.xqy");
19+
20+
function getPropertyRangePath(entityIRI, propertyPath) {
21+
let properties = propertyPath.split("/");
22+
let finalPath = "//*:instance";
23+
for(let property of properties) {
24+
let model = getEntityDefinitionFromIRI(entityIRI);
25+
let entityInfo = getEntityInfoFromIRI(entityIRI);
26+
let prop = model.definitions[entityInfo.entityName].properties[property];
27+
if(!prop) {
28+
throw Error('The property ' + property + ' do not exist');
29+
}
30+
finalPath += "/" + entityInfo.entityName + "/" + property;
31+
entityIRI = getRefEntityIdentifiers(entityIRI, entityInfo, prop).entityIRI;
32+
}
33+
return finalPath;
34+
}
35+
36+
function getPropertyReferenceType(entityIRI, propertyPath) {
37+
let properties = propertyPath.split("/");
38+
let model = null;
39+
40+
for(let property of properties) {
41+
try {
42+
model = getEntityDefinitionFromIRI(entityIRI);
43+
} catch(err) {
44+
throw Error('The property ' + property + ' is either not indexed or do not exist');
45+
}
46+
let entityInfo = getEntityInfoFromIRI(entityIRI);
47+
48+
let prop = model.definitions[entityInfo.entityName].rangeIndex;
49+
if(prop && prop.includes(property)) {
50+
return "path";
51+
}
52+
53+
prop = model.definitions[entityInfo.entityName].elementRangeIndex;
54+
if(prop && prop.includes(property)) {
55+
return "element";
56+
}
57+
58+
prop = model.definitions[entityInfo.entityName].properties[property];
59+
if(!prop) {
60+
throw Error('The property ' + property + ' do not exist');
61+
}
62+
entityIRI = getRefEntityIdentifiers(entityIRI, entityInfo, prop).entityIRI;
63+
}
64+
}
65+
66+
function getEntityDefinitionFromIRI(entityIRI) {
67+
let model = fn.head(cts.search(
68+
cts.tripleRangeQuery(sem.iri(entityIRI), sem.iri('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), sem.iri('http://marklogic.com/entity-services#EntityType'), '=')
69+
));
70+
if(!model) {
71+
throw Error('The entity model ' + entityIRI + ' does not exist');
72+
}
73+
return model.toObject();
74+
}
75+
76+
function getEntityInfoFromIRI(entityIRI) {
77+
let entityInfo = {
78+
"baseUri": null,
79+
"modelName": null,
80+
"version": null,
81+
"entityName": null
82+
};
83+
84+
let entityIRIArr = entityIRI.split("/");
85+
let modelInfo = entityIRIArr[entityIRIArr.length-2].split("-");
86+
87+
entityInfo.modelName = modelInfo[0];
88+
entityInfo.version = modelInfo[1];
89+
entityInfo.baseUri = entityIRI.split(entityIRIArr[entityIRIArr.length-2])[0];
90+
entityInfo.entityName = entityIRIArr[entityIRIArr.length-1];
91+
92+
return entityInfo;
93+
}
94+
95+
function getRefEntityIdentifiers(entityIRI, entityInfo, prop) {
96+
let refEntityId = {
97+
"entityIRI": null,
98+
"entityName": null
99+
};
100+
let ref = null;
101+
let refArr = null;
102+
103+
if(prop["$ref"]) {
104+
ref = prop["$ref"];
105+
refArr = ref.split("/");
106+
}
107+
108+
if(prop.items && prop.items["$ref"]) {
109+
ref = prop.items["$ref"];
110+
refArr = ref.split("/");
111+
}
112+
113+
if(refArr) {
114+
refEntityId.entityName = refArr[refArr.length - 1];
115+
if(ref.startsWith("#/definitions")) {
116+
refEntityId.entityIRI = entityInfo.baseUri + entityInfo.modelName + "-" + entityInfo.version + "/" + refEntityId.entityName;
117+
} else {
118+
refEntityId.entityIRI = ref;
119+
}
120+
}
121+
return refEntityId;
122+
}
123+
124+
module.exports = {
125+
getPropertyRangePath: getPropertyRangePath,
126+
getPropertyReferenceType: getPropertyReferenceType,
127+
getEntityDefinitionFromIRI: getEntityDefinitionFromIRI
128+
};
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
const test = require("/test/test-helper.xqy");
2+
const lib = require('/data-hub/5/impl/hub-es.sjs');
3+
let result = [];
4+
5+
function testGetPropertyRangePath(entityIRI, propertyPath, expRes) {
6+
const path = lib.getPropertyRangePath(entityIRI, propertyPath);
7+
test.assertEqual(expRes, path);
8+
}
9+
10+
result
11+
// getPropertyRangePath for two level nested property
12+
.concat(testGetPropertyRangePath("http://marklogic.com/EntitiesSearchEntity-0.0.1/EntitiesSearchEntity",
13+
"numStrEntityProp/numEntProp/intProp",
14+
"//*:instance/EntitiesSearchEntity/numStrEntityProp/NumStringEntity/numEntProp/NumericEntity/intProp"))
15+
// getPropertyRangePath for one level nested property
16+
.concat(testGetPropertyRangePath("http://marklogic.com/EntitiesSearchEntity-0.0.1/EntitiesSearchEntity",
17+
"numStrEntityProp/strCityProp",
18+
"//*:instance/EntitiesSearchEntity/numStrEntityProp/NumStringEntity/strCityProp"))
19+
// getPropertyRangePath for one level nested property
20+
.concat(testGetPropertyRangePath("http://marklogic.com/EntitiesSearchEntity-0.0.1/NumStringEntity",
21+
"numEntProp/intProp",
22+
"//*:instance/NumStringEntity/numEntProp/NumericEntity/intProp"))
23+
// getPropertyRangePath for root level property
24+
.concat(testGetPropertyRangePath("http://marklogic.com/EntitiesSearchEntity-0.0.1/NumStringEntity",
25+
"intProp", "//*:instance/NumStringEntity/intProp"));
26+
27+
28+
function testRangePathPropertyReferenceType(entityIRI, propertyPath) {
29+
const refType = lib.getPropertyReferenceType(entityIRI, propertyPath);
30+
test.assertEqual("path", refType);
31+
}
32+
33+
result
34+
// getPropertyReferenceType for two level nested property
35+
.concat(testRangePathPropertyReferenceType("http://marklogic.com/EntitiesSearchEntity-0.0.1/EntitiesSearchEntity",
36+
"numStrEntityProp/numEntProp/intProp"))
37+
// getPropertyReferenceType for one level nested property
38+
.concat(testRangePathPropertyReferenceType("http://marklogic.com/EntitiesSearchEntity-0.0.1/EntitiesSearchEntity",
39+
"numStrEntityProp/strCityProp"))
40+
// getPropertyReferenceType for one level nested property
41+
.concat(testRangePathPropertyReferenceType("http://marklogic.com/EntitiesSearchEntity-0.0.1/NumStringEntity",
42+
"numEntProp/intProp"))
43+
// getPropertyReferenceType for root level nested property
44+
.concat(testRangePathPropertyReferenceType("http://marklogic.com/EntitiesSearchEntity-0.0.1/NumStringEntity",
45+
"intProp"));
46+
47+
function testRangeElementPropertyReferenceType(entityIRI, propertyPath) {
48+
const refType = lib.getPropertyReferenceType(entityIRI, propertyPath);
49+
test.assertEqual("element", refType);
50+
}
51+
52+
result
53+
// getPropertyReferenceType for two level nested property
54+
.concat(testRangeElementPropertyReferenceType("http://marklogic.com/EntitiesSearchEntity-0.0.1/EntitiesSearchEntity",
55+
"numStrEntityProp/numEntProp/floatProp"))
56+
// getPropertyReferenceType for one level nested property
57+
.concat(testRangeElementPropertyReferenceType("http://marklogic.com/EntitiesSearchEntity-0.0.1/EntitiesSearchEntity",
58+
"numStrEntityProp/strNameProp"))
59+
// getPropertyReferenceType for one level nested property
60+
.concat(testRangeElementPropertyReferenceType("http://marklogic.com/EntitiesSearchEntity-0.0.1/NumStringEntity",
61+
"numEntProp/floatProp"))
62+
// getPropertyReferenceType for root level nested property
63+
.concat(testRangeElementPropertyReferenceType("http://marklogic.com/EntitiesSearchEntity-0.0.1/NumStringEntity",
64+
"strNameProp"));
65+
66+
function testGetEntityDefinitionFromIRI(entityIRI, expRes) {
67+
const result = lib.getEntityDefinitionFromIRI(entityIRI);
68+
test.assertTrue(result.definitions[expRes] !== null);
69+
}
70+
71+
result
72+
// Exisiting IRI
73+
.concat(testGetEntityDefinitionFromIRI("http://marklogic.com/EntitiesSearchEntity-0.0.1/EntitiesSearchEntity",
74+
"EntitiesSearchEntity"))
75+
// fetching nested objectType from IRI
76+
.concat(testGetEntityDefinitionFromIRI("http://marklogic.com/EntitiesSearchEntity-0.0.1/NumStringEntity",
77+
"NumStringEntity"));
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
declareUpdate();
2+
3+
// Nested ObjectType entity model
4+
xdmp.documentInsert("/entities/EntitiesSearchEntity.entity.json",
5+
{
6+
"info": {
7+
"title": "EntitiesSearchEntity",
8+
"version": "0.0.1",
9+
"baseUri": "http://marklogic.com/"
10+
},
11+
"definitions": {
12+
"EntitiesSearchEntity": {
13+
"required": [],
14+
"pii": [],
15+
"elementRangeIndex": [
16+
"srchEntyProp1"
17+
],
18+
"rangeIndex": [
19+
"srchEntyProp2"
20+
],
21+
"wordLexicon": [],
22+
"properties": {
23+
"srchEntyProp1": {
24+
"datatype": "string",
25+
"collation": "http://marklogic.com/collation/codepoint"
26+
},
27+
"srchEntyProp2": {
28+
"datatype": "string",
29+
"collation": "http://marklogic.com/collation/codepoint"
30+
},
31+
"numStrEntityProp": {
32+
"datatype": "array",
33+
"items": {
34+
"$ref": "#/definitions/NumStringEntity"
35+
}
36+
}
37+
}
38+
},
39+
"NumericEntity": {
40+
"required": [],
41+
"pii": [],
42+
"elementRangeIndex": [
43+
"decimalProp",
44+
"floatProp",
45+
"doubleProp"
46+
],
47+
"rangeIndex": [
48+
"intProp",
49+
"longProp"
50+
],
51+
"wordLexicon": [],
52+
"properties": {
53+
"intProp": {
54+
"datatype": "int"
55+
},
56+
"longProp": {
57+
"datatype": "long"
58+
},
59+
"decimalProp": {
60+
"datatype": "decimal"
61+
},
62+
"floatProp": {
63+
"datatype": "float"
64+
},
65+
"doubleProp": {
66+
"datatype": "double"
67+
}
68+
}
69+
},
70+
"NumStringEntity": {
71+
"required": [],
72+
"pii": [],
73+
"elementRangeIndex": [
74+
"strNameProp"
75+
],
76+
"rangeIndex": [
77+
"strCityProp",
78+
"intProp"
79+
],
80+
"wordLexicon": [],
81+
"properties": {
82+
"strNameProp": {
83+
"datatype": "string",
84+
"collation": "http://marklogic.com/collation/codepoint"
85+
},
86+
"strCityProp": {
87+
"datatype": "string",
88+
"collation": "http://marklogic.com/collation/codepoint"
89+
},
90+
"intProp": {
91+
"datatype": "int"
92+
},
93+
"numEntProp": {
94+
"$ref": "#/definitions/NumericEntity"
95+
}
96+
}
97+
}
98+
}
99+
},
100+
{
101+
permissions: xdmp.defaultPermissions(),
102+
collections: "http://marklogic.com/entity-services/models"
103+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
declareUpdate();
2+
3+
xdmp.documentDelete('/entities/EntitiesSearchEntity.entity.json');

0 commit comments

Comments
 (0)