Skip to content

Commit

Permalink
Delete SPARQL query generation from widgets
Browse files Browse the repository at this point in the history
  • Loading branch information
tfrancart committed Jul 13, 2024
1 parent a7a5c43 commit 270ddb2
Show file tree
Hide file tree
Showing 12 changed files with 27 additions and 457 deletions.
39 changes: 0 additions & 39 deletions src/sparnatural/components/widgets/AbstractWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@ export abstract class AbstractWidget extends HTMLComponent {
return this
}

// Must be implemented by the developper of the widget
abstract getRdfJsPattern(): Pattern[];
// Is used to parse the inputs from the ISparnaturalJson e.g "preloaded" queries
abstract parseInput(value:WidgetValue["value"]):WidgetValue

Expand Down Expand Up @@ -149,41 +147,4 @@ export abstract class AbstractWidget extends HTMLComponent {
if(message != null) this.spinner.renderMessage(message)
}

isBlockingStart() {
return this.blockStartTriple
}
isBlockingObjectProp() {
return this.blockObjectPropTriple
}
isBlockingEnd() {
return this.blockEndTriple
}

/**
* Translates an IRI, Literal or BNode into the corresponding SPARQL query term
* to be inserted in a SPARQL query.
* @returns
*/
rdfTermToSparqlQuery(rdfTerm:RDFTerm): IriTerm | BlankTerm | LiteralTerm {
if(rdfTerm.type == "uri") {
return factory.namedNode(rdfTerm.value);
} else if(rdfTerm.type == "literal") {
if(rdfTerm["xml:lang"]) {
return factory.literal(rdfTerm.value, rdfTerm["xml:lang"]);
} else if(rdfTerm.datatype) {
// if the second parameter is a NamedNode, then it is considered a datatype, otherwise it is
// considered like a language
// so we make the datatype a NamedNode
let namedNodeDatatype = factory.namedNode(rdfTerm.datatype);
return factory.literal(rdfTerm.value, namedNodeDatatype);
} else {
return factory.literal(rdfTerm.value);
}
} else if(rdfTerm.type == "bnode") {
// we don't know what to do with this, but don't trigger an error
return factory.blankNode(rdfTerm.value);
} else {
throw new Error("Unexpected rdfTerm type "+rdfTerm.type)
}
}
}
50 changes: 0 additions & 50 deletions src/sparnatural/components/widgets/AutoCompleteWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,54 +133,4 @@ export class AutoCompleteWidget extends AbstractWidget {

parseInput(input: RdfTermValue["value"]): RdfTermValue {return new RdfTermValue(input)}

/**
* @returns true if the number of values is 1, in which case the widget will handle the generation of the triple itself,
* not using a VALUES clause; returns false otherwise.
*/
isBlockingObjectProp() {
return (
this.widgetValues.length == 1
&&
!((this.ParentComponent.ParentComponent.ParentComponent as EndClassGroup).isVarSelected())
);
}

/**
* @returns true if at least one value is selected, in which case we don't need to insert an rdf:type constraint
* on the end class
*/
isBlockingEnd(): boolean {
return (this.widgetValues.length > 0);
}


getRdfJsPattern(): Pattern[] {
if(this.isBlockingObjectProp()) {
let singleTriple: Triple = SparqlFactory.buildTriple(
factory.variable(this.startClassVal.variable),
factory.namedNode(this.objectPropVal.type),
this.rdfTermToSparqlQuery((this.widgetValues[0] as RdfTermValue).value.rdfTerm)
);

let ptrn: BgpPattern = {
type: "bgp",
triples: [singleTriple],
};


return [ptrn];
} else {
let vals = (this.widgetValues as RdfTermValue[]).map((v) => {
let vl: ValuePatternRow = {};
vl["?"+this.endClassVal.variable] = this.rdfTermToSparqlQuery(v.value.rdfTerm);
return vl;
});
let valuePattern: ValuesPattern = {
type: "values",
values: vals,
};
return [valuePattern];
}
}

}
48 changes: 0 additions & 48 deletions src/sparnatural/components/widgets/BooleanWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,52 +78,4 @@ export class BooleanWidget extends AbstractWidget {
return new BooleanWidgetValue(input);
}

/**
* Blocks if a value is selected and this is not the "all" special value
* @returns true
*/
isBlockingObjectProp() {
return (
this.widgetValues.length == 1
&&
!(this.widgetValues[0] instanceof SelectAllValue)
&&
!((this.ParentComponent.ParentComponent.ParentComponent as EndClassGroup).isVarSelected())
);
}

getRdfJsPattern(): Pattern[] {
// if we are blocking the object prop, we create it directly here with the value as the object
if(this.isBlockingObjectProp()) {
let ptrn: BgpPattern = {
type: "bgp",
triples: [
{
subject: factory.variable(this.startClassVal.variable),
predicate: factory.namedNode(this.objectPropVal.type),
object: factory.literal(
this.widgetValues[0].value.boolean.toString(),
factory.namedNode("http://www.w3.org/2001/XMLSchema#boolean")
),
},
],
};
return [ptrn];
} else {
// otherwise the object prop is created and we create a VALUES clause with the actual boolean
let vals = (this.widgetValues as BooleanWidgetValue[]).map((v) => {
let vl: ValuePatternRow = {};
vl["?"+this.endClassVal.variable] = factory.literal(
this.widgetValues[0].value.boolean.toString(),
factory.namedNode("http://www.w3.org/2001/XMLSchema#boolean")
);
return vl;
});
let valuePattern: ValuesPattern = {
type: "values",
values: vals,
};
return [valuePattern];
}
}
}
3 changes: 0 additions & 3 deletions src/sparnatural/components/widgets/DatesWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,4 @@ export class DatesWidget extends AbstractWidget {
return lbl;
};

getRdfJsPattern(): Pattern[] {
throw new Error("Method not implemented.");
}
}
54 changes: 0 additions & 54 deletions src/sparnatural/components/widgets/ListWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,59 +169,5 @@ export class ListWidget extends AbstractWidget {

parseInput(input:RdfTermValue["value"]): WidgetValue { return new RdfTermValue(input) }

/**
* @returns true if the number of values is 1, in which case the widget will handle the generation of the triple itself,
* not using a VALUES clause; returns false otherwise.
*/
isBlockingObjectProp() {
return (
this.widgetValues.length == 1
&&
!((this.ParentComponent.ParentComponent.ParentComponent as EndClassGroup).isVarSelected())
);
}

/**
* @returns true if at least one value is selected, in which case we don't need to insert an rdf:type constraint
* on the end class
*/
isBlockingEnd(): boolean {
return (
this.widgetValues.length > 0
);
}


getRdfJsPattern(): Pattern[] {
if(this.isBlockingObjectProp()) {
let singleTriple: Triple = SparqlFactory.buildTriple(
factory.variable(this.startClassVal.variable),
factory.namedNode(this.objectPropVal.type),
this.rdfTermToSparqlQuery((this.widgetValues[0] as RdfTermValue).value.rdfTerm)
);

let ptrn: BgpPattern = {
type: "bgp",
triples: [singleTriple],
};


return [ptrn];
} else {
let vals = (this.widgetValues as RdfTermValue[]).map((v) => {
let vl: ValuePatternRow = {};
vl["?"+this.endClassVal.variable] = this.rdfTermToSparqlQuery(v.value.rdfTerm);
return vl;
});
let valuePattern: ValuesPattern = {
type: "values",
values: vals,
};
return [valuePattern];
}
}




}
36 changes: 0 additions & 36 deletions src/sparnatural/components/widgets/MapWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,42 +395,6 @@ export default class MapWidget extends AbstractWidget {
).render();
}

// reference: https://graphdb.ontotext.com/documentation/standard/geosparql-support.html
getRdfJsPattern(): Pattern[] {

// the property between the subject and its position expressed as wkt value, e.g. http://www.w3.org/2003/01/geo/wgs84_pos#geometry

let filterPtrn: FilterPattern = {
type: "filter",
expression: <FunctionCallExpression><unknown>{
type: "functionCall",
function: GEOFUNCTIONS.WITHIN,
args: [
factory.variable(this.endClassVal.variable),
this.#buildPolygon(this.widgetValues[0].value.coordinates[0])
],
},
};

return [filterPtrn];

}

#buildPolygon(coordinates: LatLng[]) {
let polygon = "";
coordinates.forEach((coordinat) => {
polygon = `${polygon}${coordinat.lng} ${coordinat.lat}, `;
});
// polygon must be closed with the starting point
let startPt = coordinates[0]
let literal: LiteralTerm = factory.literal(
`Polygon((${polygon}${startPt.lng} ${startPt.lat}))`,
GEOSPARQL.WKT_LITERAL
)

return literal;
}

#getSvgSelection(coordinates: LatLng[][]) {

let bounds = L.latLngBounds(coordinates[0]) ;
Expand Down
4 changes: 1 addition & 3 deletions src/sparnatural/components/widgets/NoWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,5 @@ export class NoWidget extends AbstractWidget {
render() {
return this;
}
getRdfJsPattern(): Pattern[] {
throw new Error("Method not implemented.");
}

}
22 changes: 0 additions & 22 deletions src/sparnatural/components/widgets/NumberWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,26 +157,4 @@ export class NumberWidget extends AbstractWidget {
return new NumberWidgetValue(input);
}

/**
* @returns false
*/
isBlockingObjectProp() {
return false;
}

getRdfJsPattern(): Pattern[] {
return [
SparqlFactory.buildFilterRangeDateOrNumber(
(this.widgetValues[0].value.min != undefined)?factory.literal(
this.widgetValues[0].value.min.toString(),
factory.namedNode("http://www.w3.org/2001/XMLSchema#decimal")
):null,
(this.widgetValues[0].value.max != undefined)?factory.literal(
this.widgetValues[0].value.max.toString(),
factory.namedNode("http://www.w3.org/2001/XMLSchema#decimal")
):null,
factory.variable(this.endClassVal.variable)
)
];
}
}
82 changes: 0 additions & 82 deletions src/sparnatural/components/widgets/SearchRegexWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,86 +101,4 @@ export class SearchRegexWidget extends AbstractWidget {
return new SearchRegexWidgetValue(input);
}

isBlockingObjectProp() {
// TODO : customize depending on widget type, e.g. Virtuoso, Jena, etc.
return super.isBlockingObjectProp();
}


isBlockingEnd(): boolean {
// TODO : customize depending on widget type, e.g. Virtuoso, Jena, etc.
return super.isBlockingEnd();
}

getRdfJsPattern(): Pattern[] {
switch(this.configuration.widgetType) {
case Config.STRING_EQUALS_PROPERTY: {
// builds a FILTER(lcase(...) = lcase(...))
return [SparqlFactory.buildFilterStringEquals(
factory.literal(
`${this.widgetValues[0].value.regex}`
),
factory.variable(this.endClassVal.variable)
)];
}
case Config.SEARCH_PROPERTY: {
// builds a FILTER(regex(...,...,"i"))
return [SparqlFactory.buildFilterRegex(
factory.literal(
`${this.widgetValues[0].value.regex}`
),
factory.variable(this.endClassVal.variable)
)];
}
case Config.GRAPHDB_SEARCH_PROPERTY: {
// builds a GraphDB-specific search pattern
let ptrn: BgpPattern = {
type: "bgp",
triples: [
{
subject: factory.variable(this.startClassVal.variable),
predicate: factory.namedNode(
"http://www.ontotext.com/connectors/lucene#query"
),
object: factory.literal(
`text:${this.widgetValues[0].value.regex}`
),
},
{
subject: factory.variable(this.startClassVal.variable),
predicate: factory.namedNode(
"http://www.ontotext.com/connectors/lucene#entities"
),
object: factory.variable(this.endClassVal.variable),
},
],
};
return [ptrn];
}
case Config.VIRTUOSO_SEARCH_PROPERTY: {
let bif_query = this.widgetValues[0].value.label
.replace(/[\"']/g, " ")
.split(" ")
.map((e) => `'${e}'`)
.join(" and ");
console.log(bif_query);
let ptrn: BgpPattern = {
type: "bgp",
triples: [
{
subject: factory.variable(this.endClassVal.variable),
predicate: factory.namedNode(
"http://www.openlinksw.com/schemas/bif#contains"
),
object: factory.literal(`${bif_query}`),
},
],
};
return [ptrn];
}
case Config.JENA_SEARCH_PROPERTY: {
throw new Error("Not implemented yet")
}
}
}
}
Loading

0 comments on commit 270ddb2

Please sign in to comment.