Skip to content

Commit 5d3af46

Browse files
Benjamin Geersubotic
andauthored
feat(gravsearch): Remove deprecated functions (#1660)
* feat(gravsearch): Remove deprecated functions. * test(gravsearch): Fix tests. Co-authored-by: Ivan Subotic <400790+subotic@users.noreply.github.com>
1 parent e4fd02c commit 5d3af46

6 files changed

Lines changed: 3 additions & 254 deletions

File tree

‎docs/src/paradox/03-apis/api-v2/query-language.md‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -382,10 +382,6 @@ For example, to search for titles that contain the words 'Zeitglöcklein' and
382382
FILTER knora-api:matchText(?title, "Zeitglöcklein Lebens")
383383
```
384384

385-
Note: the `knora-api:match` function has been deprecated, and will no longer work in
386-
a future release of Knora. Please change your Gravsearch queries to use `knora-api:matchText`
387-
instead. Attention: the first argument is different.
388-
389385
#### Filtering Text by Language
390386

391387
To filter a text value by language in the simple schema, use the SPARQL `lang` function
@@ -465,10 +461,6 @@ CONSTRUCT {
465461
Here we are looking for letters containing the words "Grund" and "Richtigkeit"
466462
within a single paragraph.
467463

468-
Note: the `knora-api:matchInStandoff` function has been deprecated, and will no longer
469-
work in a future release of Knora. Please change your Gravsearch queries to use
470-
`knora-api:matchTextInStandoff` instead. Attention: the first argument is different.
471-
472464
#### Matching Standoff Links
473465

474466
If you are only interested in specifying that a resource has some text

‎webapi/src/main/scala/org/knora/webapi/OntologyConstants.scala‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -334,10 +334,6 @@ object OntologyConstants {
334334

335335
val IsMainResource: IRI = KnoraBasePrefixExpansion + "isMainResource"
336336

337-
// A deprecated virtual property, used by the deprecated Gravsearch functions knora-api:match and
338-
// knora-api:matchInStandoff. Replaced during processing by a triplestore-specific property.
339-
val MatchesTextIndex: IRI = KnoraBasePrefixExpansion + "matchesTextIndex"
340-
341337
/* Resource creator */
342338
val AttachedToUser: IRI = KnoraBasePrefixExpansion + "attachedToUser"
343339

@@ -925,9 +921,7 @@ object OntologyConstants {
925921

926922
val IsMainResource: IRI = KnoraApiV2PrefixExpansion + "isMainResource"
927923
val ToSimpleDateFunction: IRI = KnoraApiV2PrefixExpansion + "toSimpleDate"
928-
val MatchFunction: IRI = KnoraApiV2PrefixExpansion + "match"
929924
val MatchTextFunction: IRI = KnoraApiV2PrefixExpansion + "matchText"
930-
val MatchInStandoffFunction: IRI = KnoraApiV2PrefixExpansion + "matchInStandoff"
931925
val MatchTextInStandoffFunction: IRI = KnoraApiV2PrefixExpansion + "matchTextInStandoff"
932926
val MatchLabelFunction: IRI = KnoraApiV2PrefixExpansion + "matchLabel"
933927
val StandoffLinkFunction: IRI = KnoraApiV2PrefixExpansion + "standoffLink"
@@ -966,8 +960,6 @@ object OntologyConstants {
966960
val ObjectType: IRI = KnoraApiV2PrefixExpansion + "objectType"
967961

968962
val IsMainResource: IRI = KnoraApiV2PrefixExpansion + "isMainResource"
969-
val MatchesTextIndex: IRI = KnoraApiV2PrefixExpansion + "matchesTextIndex" // virtual property to be replaced by a triplestore-specific one
970-
val MatchFunction: IRI = KnoraApiV2PrefixExpansion + "match"
971963
val MatchTextFunction: IRI = KnoraApiV2PrefixExpansion + "matchText"
972964
val MatchLabelFunction: IRI = KnoraApiV2PrefixExpansion + "matchLabel"
973965

‎webapi/src/main/scala/org/knora/webapi/responders/v2/search/SparqlTransformer.scala‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,7 @@ object SparqlTransformer {
300300

301301
val transformedPattern = statement.copy(
302302
// Replace the deprecated property knora-base:matchesTextIndex with a GraphDB-specific one.
303-
pred = statement.pred match {
304-
case iri: IriRef if iri.iri == OntologyConstants.KnoraBase.MatchesTextIndex.toSmartIri => IriRef(OntologyConstants.Ontotext.LuceneFulltext.toSmartIri) // convert to special Lucene property
305-
case other => other // no conversion needed
306-
},
303+
pred = statement.pred,
307304
namedGraph = statement.namedGraph match {
308305
case Some(IriRef(SmartIri(OntologyConstants.NamedGraphs.KnoraExplicitNamedGraph), _)) => Some(IriRef(OntologyConstants.NamedGraphs.GraphDBExplicitNamedGraph.toSmartIri))
309306
case Some(IriRef(_, _)) => throw AssertionException(s"Named graphs other than ${OntologyConstants.NamedGraphs.KnoraExplicitNamedGraph} cannot occur in non-triplestore-specific generated search query SPARQL")

‎webapi/src/main/scala/org/knora/webapi/responders/v2/search/gravsearch/prequery/AbstractPrequeryGenerator.scala‎

Lines changed: 0 additions & 215 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,74 +1119,6 @@ abstract class AbstractPrequeryGenerator(constructClause: ConstructClause,
11191119
}
11201120
}
11211121

1122-
/**
1123-
* Handles the deprecated function `knora-api:match` in the simple schema.
1124-
*
1125-
* @param functionCallExpression the function call to be handled.
1126-
* @param typeInspectionResult the type inspection results.
1127-
* @param isTopLevel if `true`, this is the top-level expression in the `FILTER`.
1128-
* @return a [[TransformedFilterPattern]].
1129-
*/
1130-
private def handleMatchFunctionInSimpleSchema(functionCallExpression: FunctionCallExpression, typeInspectionResult: GravsearchTypeInspectionResult, isTopLevel: Boolean): TransformedFilterPattern = {
1131-
val functionIri: SmartIri = functionCallExpression.functionIri.iri
1132-
1133-
if (querySchema == ApiV2Complex) {
1134-
throw GravsearchException(s"Function ${functionIri.toSparql} cannot be used in a Gravsearch query written in the complex schema; use ${OntologyConstants.KnoraApiV2Complex.MatchFunction.toSmartIri.toSparql} instead")
1135-
}
1136-
1137-
// The match function must be the top-level expression, otherwise boolean logic won't work properly.
1138-
if (!isTopLevel) {
1139-
throw GravsearchException(s"Function ${functionIri.toSparql} must be the top-level expression in a FILTER")
1140-
}
1141-
1142-
// two arguments are expected: the first must be a variable representing a string value,
1143-
// the second must be a string literal
1144-
1145-
if (functionCallExpression.args.size != 2) throw GravsearchException(s"Two arguments are expected for ${functionIri.toSparql}")
1146-
1147-
// a QueryVariable expected to represent a text value
1148-
val textValueVar: QueryVariable = functionCallExpression.getArgAsQueryVar(pos = 0)
1149-
1150-
typeInspectionResult.getTypeOfEntity(textValueVar) match {
1151-
case Some(nonPropInfo: NonPropertyTypeInfo) =>
1152-
1153-
nonPropInfo.typeIri.toString match {
1154-
1155-
case OntologyConstants.Xsd.String => () // xsd:string is expected, TODO: should also xsd:anyUri be allowed?
1156-
1157-
case _ => throw GravsearchException(s"${textValueVar.toSparql} must be an xsd:string")
1158-
}
1159-
1160-
case _ => throw GravsearchException(s"${textValueVar.toSparql} must be an xsd:string")
1161-
}
1162-
1163-
val textValHasString: QueryVariable = SparqlTransformer.createUniqueVariableNameFromEntityAndProperty(base = textValueVar, propertyIri = OntologyConstants.KnoraBase.ValueHasString)
1164-
1165-
// Add a statement to assign the literal to a variable, which we'll use in the transformed FILTER expression,
1166-
// if that statement hasn't been added already.
1167-
val valueHasStringStatement = if (addGeneratedVariableForValueLiteral(textValueVar, textValHasString)) {
1168-
Seq(StatementPattern.makeExplicit(subj = textValueVar, pred = IriRef(OntologyConstants.KnoraBase.ValueHasString.toSmartIri), textValHasString))
1169-
} else {
1170-
Seq.empty[StatementPattern]
1171-
}
1172-
1173-
val searchTerm: XsdLiteral = functionCallExpression.getArgAsLiteral(1, xsdDatatype = OntologyConstants.Xsd.String.toSmartIri)
1174-
1175-
val searchTerms: LuceneQueryString = LuceneQueryString(searchTerm.value)
1176-
1177-
// Replace the filter with a statement using the deprecated knora-base:matchesTextIndex property.
1178-
TransformedFilterPattern(
1179-
None, // FILTER has been replaced by statements
1180-
valueHasStringStatement ++ Seq(
1181-
StatementPattern.makeExplicit(
1182-
subj = textValHasString,
1183-
pred = IriRef(OntologyConstants.KnoraBase.MatchesTextIndex.toSmartIri),
1184-
obj = XsdLiteral(searchTerms.getQueryString, OntologyConstants.Xsd.String.toSmartIri)
1185-
)
1186-
)
1187-
)
1188-
}
1189-
11901122
/**
11911123
* Handles the function `knora-api:matchText` in the simple schema.
11921124
*
@@ -1253,51 +1185,6 @@ abstract class AbstractPrequeryGenerator(constructClause: ConstructClause,
12531185
)
12541186
}
12551187

1256-
/**
1257-
* Handles the deprecated function `knora-api:match` in the complex schema.
1258-
*
1259-
* @param functionCallExpression the function call to be handled.
1260-
* @param typeInspectionResult the type inspection results.
1261-
* @param isTopLevel if `true`, this is the top-level expression in the `FILTER`.
1262-
* @return a [[TransformedFilterPattern]].
1263-
*/
1264-
private def handleMatchFunctionInComplexSchema(functionCallExpression: FunctionCallExpression, typeInspectionResult: GravsearchTypeInspectionResult, isTopLevel: Boolean): TransformedFilterPattern = {
1265-
val functionIri: SmartIri = functionCallExpression.functionIri.iri
1266-
1267-
if (querySchema == ApiV2Simple) {
1268-
throw GravsearchException(s"Function ${functionIri.toSparql} cannot be used in a Gravsearch query written in the simple schema; use ${OntologyConstants.KnoraApiV2Simple.MatchFunction.toSmartIri.toSparql} instead")
1269-
}
1270-
1271-
// The match function must be the top-level expression, otherwise boolean logic won't work properly.
1272-
if (!isTopLevel) {
1273-
throw GravsearchException(s"Function ${functionIri.toSparql} must be the top-level expression in a FILTER")
1274-
}
1275-
1276-
// two arguments are expected: the first must be a variable representing a string value,
1277-
// the second must be a string literal
1278-
1279-
if (functionCallExpression.args.size != 2) throw GravsearchException(s"Two arguments are expected for ${functionIri.toSparql}")
1280-
1281-
// a QueryVariable expected to represent a string
1282-
val stringVar: QueryVariable = functionCallExpression.getArgAsQueryVar(pos = 0)
1283-
1284-
val searchTermStr: XsdLiteral = functionCallExpression.getArgAsLiteral(1, xsdDatatype = OntologyConstants.Xsd.String.toSmartIri)
1285-
1286-
val searchTerms: LuceneQueryString = LuceneQueryString(searchTermStr.value)
1287-
1288-
// Replace the filter with a statement using the deprecated knora-base:matchesTextIndex property.
1289-
TransformedFilterPattern(
1290-
None, // FILTER has been replaced by statements
1291-
Seq(
1292-
StatementPattern.makeExplicit(
1293-
subj = stringVar,
1294-
pred = IriRef(OntologyConstants.KnoraBase.MatchesTextIndex.toSmartIri),
1295-
XsdLiteral(searchTerms.getQueryString, OntologyConstants.Xsd.String.toSmartIri)
1296-
)
1297-
)
1298-
)
1299-
}
1300-
13011188
/**
13021189
* Handles the function `knora-api:matchText` in the complex schema.
13031190
*
@@ -1364,105 +1251,6 @@ abstract class AbstractPrequeryGenerator(constructClause: ConstructClause,
13641251
)
13651252
}
13661253

1367-
/**
1368-
* Handles the deprecated function `knora-api:matchInStandoff`.
1369-
*
1370-
* @param functionCallExpression the function call to be handled.
1371-
* @param typeInspectionResult the type inspection results.
1372-
* @param isTopLevel if `true`, this is the top-level expression in the `FILTER`.
1373-
* @return a [[TransformedFilterPattern]].
1374-
*/
1375-
private def handleMatchInStandoffFunction(functionCallExpression: FunctionCallExpression, typeInspectionResult: GravsearchTypeInspectionResult, isTopLevel: Boolean): TransformedFilterPattern = {
1376-
val functionIri: SmartIri = functionCallExpression.functionIri.iri
1377-
1378-
if (querySchema == ApiV2Simple) {
1379-
throw GravsearchException(s"Function ${functionIri.toSparql} cannot be used in a Gravsearch query written in the simple schema")
1380-
}
1381-
1382-
if (!isTopLevel) {
1383-
throw GravsearchException(s"Function ${functionIri.toSparql} must be the top-level expression in a FILTER")
1384-
}
1385-
1386-
// Three arguments are expected:
1387-
// 1. a variable representing the string literal value of the text value
1388-
// 2. a variable representing the standoff tag
1389-
// 3. a string literal containing space-separated search terms
1390-
1391-
if (functionCallExpression.args.size != 3) throw GravsearchException(s"Three arguments are expected for ${functionIri.toSparql}")
1392-
1393-
// A variable representing the object of the text value's valueHasString.
1394-
val textValueStringLiteralVar: QueryVariable = functionCallExpression.getArgAsQueryVar(pos = 0)
1395-
1396-
// A variable representing the standoff tag.
1397-
val standoffTagVar: QueryVariable = functionCallExpression.getArgAsQueryVar(pos = 1)
1398-
1399-
// A string literal representing the search terms.
1400-
val searchTermStr: XsdLiteral = functionCallExpression.getArgAsLiteral(pos = 2, xsdDatatype = OntologyConstants.Xsd.String.toSmartIri)
1401-
1402-
val searchTerms: LuceneQueryString = LuceneQueryString(searchTermStr.value)
1403-
1404-
// Generate a statement to search the full-text search index, using the deprecated virtual predicate
1405-
// knora-base:matchesTextIndex, to assert that text value contains the search terms.
1406-
val fullTextSearchStatement: Seq[StatementPattern] = Seq(
1407-
StatementPattern.makeInferred(
1408-
subj = textValueStringLiteralVar,
1409-
pred = IriRef(OntologyConstants.KnoraBase.MatchesTextIndex.toSmartIri),
1410-
XsdLiteral(searchTerms.getQueryString, OntologyConstants.Xsd.String.toSmartIri)
1411-
)
1412-
)
1413-
1414-
// Generate query patterns to assign the text in the standoff tag to a variable, if we
1415-
// haven't done so already.
1416-
1417-
val startVariable = QueryVariable(standoffTagVar.variableName + "__start")
1418-
val endVariable = QueryVariable(standoffTagVar.variableName + "__end")
1419-
1420-
val markedUpPatternsToAdd: Seq[QueryPattern] = if (!standoffMarkedUpVariables.contains(startVariable)) {
1421-
standoffMarkedUpVariables += startVariable
1422-
1423-
Seq(
1424-
// ?standoffTag knora-base:standoffTagHasStart ?standoffTag__start .
1425-
StatementPattern.makeExplicit(standoffTagVar, IriRef(OntologyConstants.KnoraBase.StandoffTagHasStart.toSmartIri), startVariable),
1426-
// ?standoffTag knora-base:standoffTagHasEnd ?standoffTag__end .
1427-
StatementPattern.makeExplicit(standoffTagVar, IriRef(OntologyConstants.KnoraBase.StandoffTagHasEnd.toSmartIri), endVariable)
1428-
)
1429-
} else {
1430-
Seq.empty[QueryPattern]
1431-
}
1432-
1433-
// Generate a FILTER pattern for each search term, using the regex function to assert that the text in the
1434-
// standoff tag contains the term:
1435-
// FILTER REGEX(SUBSTR(?textValueStr, ?standoffTag__start + 1, ?standoffTag__end - ?standoffTag__start), 'term', "i")
1436-
// TODO: handle the differences between regex syntax and Lucene syntax.
1437-
val regexFilters: Seq[FilterPattern] = searchTerms.getSingleTerms.map {
1438-
term: String =>
1439-
FilterPattern(
1440-
expression = RegexFunction(
1441-
textExpr = SubStrFunction(
1442-
textLiteralVar = textValueStringLiteralVar,
1443-
startExpression = ArithmeticExpression(
1444-
leftArg = startVariable,
1445-
operator = PlusOperator,
1446-
rightArg = IntegerLiteral(1)
1447-
),
1448-
lengthExpression = ArithmeticExpression(
1449-
leftArg = endVariable,
1450-
operator = MinusOperator,
1451-
rightArg = startVariable
1452-
)
1453-
),
1454-
pattern = term, // TODO: Ignore Lucene operators
1455-
modifier = Some("i")
1456-
)
1457-
)
1458-
}
1459-
1460-
TransformedFilterPattern(
1461-
expression = None, // The expression has been replaced by additional patterns.
1462-
additionalPatterns = fullTextSearchStatement ++ markedUpPatternsToAdd ++ regexFilters
1463-
)
1464-
}
1465-
14661254
/**
14671255
* Handles the function `knora-api:matchTextInStandoff`.
14681256
*
@@ -1779,9 +1567,6 @@ abstract class AbstractPrequeryGenerator(constructClause: ConstructClause,
17791567

17801568
// Get a Scala function that implements the Gravsearch function.
17811569
val functionFunction: (FunctionCallExpression, GravsearchTypeInspectionResult, Boolean) => TransformedFilterPattern = functionIri.toString match {
1782-
case OntologyConstants.KnoraApiV2Simple.MatchFunction => handleMatchFunctionInSimpleSchema // deprecated
1783-
case OntologyConstants.KnoraApiV2Complex.MatchFunction => handleMatchFunctionInComplexSchema // deprecated
1784-
case OntologyConstants.KnoraApiV2Complex.MatchInStandoffFunction => handleMatchInStandoffFunction // deprecated
17851570
case OntologyConstants.KnoraApiV2Simple.MatchTextFunction => handleMatchTextFunctionInSimpleSchema
17861571
case OntologyConstants.KnoraApiV2Complex.MatchTextFunction => handleMatchTextFunctionInComplexSchema
17871572
case OntologyConstants.KnoraApiV2Simple.MatchLabelFunction => handleMatchLabelFunctionInSimpleSchema

‎webapi/src/main/scala/org/knora/webapi/responders/v2/search/gravsearch/types/InferringGravsearchTypeInspector.scala‎

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -982,9 +982,7 @@ class InferringGravsearchTypeInspector(nextInspector: Option[GravsearchTypeInspe
982982
// the function.
983983

984984
functionCallExpression.functionIri.iri.toString match {
985-
case OntologyConstants.KnoraApiV2Simple.MatchFunction |
986-
OntologyConstants.KnoraApiV2Simple.MatchTextFunction |
987-
OntologyConstants.KnoraApiV2Complex.MatchFunction =>
985+
case OntologyConstants.KnoraApiV2Simple.MatchTextFunction =>
988986
// The first argument is a variable representing a string.
989987
val textVar = TypeableVariable(functionCallExpression.getArgAsQueryVar(0).variableName)
990988
val currentTextVarTypesFromFilters: Set[SmartIri] = acc.typedEntitiesInFilters.getOrElse(textVar, Set.empty[SmartIri])
@@ -1024,21 +1022,6 @@ class InferringGravsearchTypeInspector(nextInspector: Option[GravsearchTypeInspe
10241022
(resourceVar -> (currentResourceVarTypesFromFilters + OntologyConstants.KnoraApiV2Complex.Resource.toSmartIri))
10251023
)
10261024

1027-
case OntologyConstants.KnoraApiV2Complex.MatchInStandoffFunction =>
1028-
// The first argument is a variable representing a string.
1029-
val textVar = TypeableVariable(functionCallExpression.getArgAsQueryVar(0).variableName)
1030-
val currentTextVarTypesFromFilters: Set[SmartIri] = acc.typedEntitiesInFilters.getOrElse(textVar, Set.empty[SmartIri])
1031-
1032-
// The second argument is a variable representing a standoff tag.
1033-
val standoffTagVar = TypeableVariable(functionCallExpression.getArgAsQueryVar(1).variableName)
1034-
val currentStandoffVarTypesFromFilters: Set[SmartIri] = acc.typedEntitiesInFilters.getOrElse(standoffTagVar, Set.empty[SmartIri])
1035-
1036-
acc.copy(
1037-
typedEntitiesInFilters = acc.typedEntitiesInFilters +
1038-
(textVar -> (currentTextVarTypesFromFilters + OntologyConstants.Xsd.String.toSmartIri)) +
1039-
(standoffTagVar -> (currentStandoffVarTypesFromFilters + OntologyConstants.KnoraApiV2Complex.StandoffTag.toSmartIri))
1040-
)
1041-
10421025
case OntologyConstants.KnoraApiV2Complex.MatchTextInStandoffFunction =>
10431026
// The first argument is a variable representing a text value.
10441027
val textVar = TypeableVariable(functionCallExpression.getArgAsQueryVar(0).variableName)

‎webapi/src/test/scala/org/knora/webapi/responders/v2/search/gravsearch/types/GravsearchTypeInspectorSpec.scala‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ class GravsearchTypeInspectorSpec extends CoreSpec() with ImplicitSender {
302302
|
303303
| ?mainRes ?titleProp ?propVal0 .
304304
|
305-
| FILTER knora-api:match(?propVal0, "Zeitglöcklein")
305+
| FILTER knora-api:matchText(?propVal0, "Zeitglöcklein")
306306
|
307307
| }
308308
""".stripMargin

0 commit comments

Comments
 (0)