diff --git a/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala b/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala index 99949e9938..5c5f1f8ec7 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala @@ -2326,7 +2326,7 @@ class StringFormatter private ( errorFun: => Nothing ): IRI = { val ontologyIri = xmlImportNamespaceToInternalOntologyIriV1(namespace, errorFun) - ontologyIri + "#" + elementLabel + ontologyIri.toString + "#" + elementLabel } /** diff --git a/webapi/src/main/scala/org/knora/webapi/messages/util/PermissionUtilADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/util/PermissionUtilADM.scala index f7ef75a422..2c5ff06a48 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/util/PermissionUtilADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/util/PermissionUtilADM.scala @@ -441,7 +441,8 @@ object PermissionUtilADM extends LazyLogging { throw InconsistentRepositoryDataException(s"invalid permission literal: $permissionLiteral") } ): Map[EntityPermission, Set[IRI]] = { - val permissions: Seq[String] = permissionLiteral.split(OntologyConstants.KnoraBase.PermissionListDelimiter) + val permissions: Seq[String] = + permissionLiteral.split(OntologyConstants.KnoraBase.PermissionListDelimiter).toIndexedSeq permissions.map { permission => val splitPermission: Array[String] = permission.split(' ') @@ -481,7 +482,7 @@ object PermissionUtilADM extends LazyLogging { { val cleanedPermissionListStr = permissionListStr.replaceAll("[<>]", "") val permissions: Seq[String] = - cleanedPermissionListStr.split(OntologyConstants.KnoraBase.PermissionListDelimiter) + cleanedPermissionListStr.split(OntologyConstants.KnoraBase.PermissionListDelimiter).toIndexedSeq logger.debug(s"PermissionUtil.parsePermissionsWithType - split permissions: $permissions") permissions.flatMap { permission => val splitPermission = permission.split(' ') diff --git a/webapi/src/main/scala/org/knora/webapi/messages/util/search/gravsearch/prequery/GravsearchQueryOptimisationFactory.scala b/webapi/src/main/scala/org/knora/webapi/messages/util/search/gravsearch/prequery/GravsearchQueryOptimisationFactory.scala index 01f7f3f215..1ae0df0fed 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/util/search/gravsearch/prequery/GravsearchQueryOptimisationFactory.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/util/search/gravsearch/prequery/GravsearchQueryOptimisationFactory.scala @@ -6,15 +6,14 @@ package org.knora.webapi.messages.util.search.gravsearch.prequery import org.knora.webapi.ApiV2Schema -import org.knora.webapi.exceptions.AssertionException import org.knora.webapi.feature.{Feature, FeatureFactory, FeatureFactoryConfig} -import org.knora.webapi.messages.{OntologyConstants, SmartIri} import org.knora.webapi.messages.util.search._ import org.knora.webapi.messages.util.search.gravsearch.types.{ GravsearchTypeInspectionResult, GravsearchTypeInspectionUtil, TypeableEntity } +import org.knora.webapi.messages.{OntologyConstants, SmartIri} import scalax.collection.Graph import scalax.collection.GraphEdge.DiHyperEdge @@ -256,9 +255,10 @@ class ReorderPatternsByDependencyOptimisationFeature( private def createAndSortGraph(statementPatterns: Seq[StatementPattern]): Seq[QueryPattern] = { @scala.annotation.tailrec def makeGraphWithoutCycles(graphComponents: Seq[(String, String)]): Graph[String, DiHyperEdge] = { - val graph = graphComponents.foldLeft(Graph.empty[String, DiHyperEdge]) { (graph, edgeDef) => - val edge = DiHyperEdge(edgeDef._1, edgeDef._2) - graph + edge // add nodes and edges to graph + val graph: Graph[String, DiHyperEdge] = graphComponents.foldLeft(Graph.empty[String, DiHyperEdge]) { + (graph, edgeDef) => + val edge: DiHyperEdge[String] = DiHyperEdge(edgeDef._1, edgeDef._2) + graph ++ Vector(edge) // add nodes and edges to graph } if (graph.isCyclic) { diff --git a/webapi/src/main/scala/org/knora/webapi/messages/util/standoff/StandoffTagUtilV2.scala b/webapi/src/main/scala/org/knora/webapi/messages/util/standoff/StandoffTagUtilV2.scala index a2cabc87eb..1e4bc3926b 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/util/standoff/StandoffTagUtilV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/util/standoff/StandoffTagUtilV2.scala @@ -5,9 +5,6 @@ package org.knora.webapi.messages.util.standoff -import java.time.Instant -import java.util.UUID - import akka.actor.ActorRef import akka.event.LoggingAdapter import akka.pattern.ask @@ -30,6 +27,8 @@ import org.knora.webapi.messages.v2.responder.standoffmessages._ import org.knora.webapi.messages.{OntologyConstants, SmartIri, StringFormatter} import org.knora.webapi.settings.KnoraSettingsImpl +import java.time.Instant +import java.util.UUID import scala.concurrent.{ExecutionContext, Future} object StandoffTagUtilV2 { @@ -1308,7 +1307,7 @@ object StandoffTagUtilV2 { conventionalAttributes ) :+ StandoffTagAttribute( key = dataTypeAttrName, - value = StandoffTagUtilV2.internalLinkMarker + internalRefTarget, + value = StandoffTagUtilV2.internalLinkMarker.toString + internalRefTarget, xmlNamespace = None ) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/OntologyMessagesV2.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/OntologyMessagesV2.scala index 2c04607c83..0cc740420d 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/OntologyMessagesV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/OntologyMessagesV2.scala @@ -2839,7 +2839,7 @@ case class ReadClassInfoV2( propertyIri }.sortBy { case (_, cardinalityInfo: KnoraCardinalityInfo) => cardinalityInfo.guiOrder - }.map { case (propertyIri: SmartIri, cardinalityInfo: KnoraCardinalityInfo) => + }.toIndexedSeq.map { case (propertyIri: SmartIri, cardinalityInfo: KnoraCardinalityInfo) => val prop2card: (IRI, JsonLDInt) = cardinalityInfo.cardinality match { case Cardinality.MayHaveMany => OntologyConstants.Owl.MinCardinality -> JsonLDInt(0) case Cardinality.MayHaveOne => OntologyConstants.Owl.MaxCardinality -> JsonLDInt(1) @@ -2904,7 +2904,7 @@ case class ReadClassInfoV2( } ++ owlCardinalities val jsonSubClassOfStatement: Option[(IRI, JsonLDArray)] = if (jsonSubClassOf.nonEmpty) { - Some(OntologyConstants.Rdfs.SubClassOf -> JsonLDArray(jsonSubClassOf)) + Some(OntologyConstants.Rdfs.SubClassOf -> JsonLDArray(jsonSubClassOf.toIndexedSeq)) } else { None } @@ -3063,7 +3063,7 @@ case class ReadPropertyInfoV2( case objs if objs.nonEmpty => Some( OntologyConstants.SalsahGuiApiV2WithValueObjects.GuiAttribute -> JsonLDArray( - objs.toArray.sorted.map(JsonLDString) + objs.toArray.sorted.map(JsonLDString).toIndexedSeq ) ) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v1/CkanResponderV1.scala b/webapi/src/main/scala/org/knora/webapi/responders/v1/CkanResponderV1.scala index 3a1efb8ab9..4b58f08718 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v1/CkanResponderV1.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v1/CkanResponderV1.scala @@ -170,7 +170,7 @@ class CkanResponderV1(responderData: ResponderData) extends Responder(responderD val propsMap = flattenProps(props) CkanProjectDatasetV1( ckan_title = propsMap.getOrElse("Description", ""), - ckan_tags = propsMap.getOrElse("Title", "").split("/").map(_.trim), + ckan_tags = propsMap.getOrElse("Title", "").split("/").toIndexedSeq.map(_.trim), files = Vector( CkanProjectDatasetFileV1( ckan_title = propsMap.getOrElse("preview_loc_origname", ""), diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v1/ResourcesResponderV1.scala b/webapi/src/main/scala/org/knora/webapi/responders/v1/ResourcesResponderV1.scala index 78c98c1623..679cc5ac4f 100755 --- a/webapi/src/main/scala/org/knora/webapi/responders/v1/ResourcesResponderV1.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v1/ResourcesResponderV1.scala @@ -1399,8 +1399,12 @@ class ResourcesResponderV1(responderData: ResponderData) extends Responder(respo } // create a list of three tuples, sort it by guiOrder and valueOrder and return only string values - val values: Seq[String] = - (valueStrings, guiOrders, valueOrders).zipped.toVector.sortBy(row => (row._2, row._3)).map(_._1) + val values: Seq[String] = valueStrings + .lazyZip(guiOrders) + .lazyZip(valueOrders) + .toVector + .sortBy(row => (row._2, row._3)) + .map(_._1) // ?values is given: it is one string to be split by separator val propValues = values.foldLeft(Vector(firstProp)) { case (acc, prop: String) => @@ -3372,7 +3376,7 @@ class ResourcesResponderV1(responderData: ResponderData) extends Responder(respo private def convertPropertyV1toPropertyGetV1(propertyV1: PropertyV1): PropertyGetV1 = { val valueObjects: Seq[PropertyGetValueV1] = - (propertyV1.value_ids, propertyV1.values, propertyV1.comments).zipped.map { + propertyV1.value_ids.lazyZip(propertyV1.values).lazyZip(propertyV1.comments).map { case (id: IRI, value: ApiValueV1, comment: Option[String]) => PropertyGetValueV1( id = id, diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v1/SearchResponderV1.scala b/webapi/src/main/scala/org/knora/webapi/responders/v1/SearchResponderV1.scala index e30299315b..89cca1a3be 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v1/SearchResponderV1.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v1/SearchResponderV1.scala @@ -360,205 +360,206 @@ class SearchResponderV1(responderData: ResponderData) extends Responder(responde * * http://stackoverflow.com/questions/1157564/zipwith-mapping-over-multiple-seq-in-scala */ - searchCriteria: Seq[SearchCriterion] = ( - searchGetRequest.propertyIri, - searchGetRequest.compareProps, - searchGetRequest.searchValue - ).zipped.map { (prop, compop, searchval) => - val propertyEntityInfo = propertyInfo.propertyInfoMap(prop) - - // If the property is a linking property, we pretend its knora-base:objectClassConstraint is knora-base:Resource, so validTypeCompopCombos will work. - val propertyObjectClassConstraint: IRI = if (propertyEntityInfo.isLinkProp) { - OntologyConstants.KnoraBase.Resource - } else { - propertyEntityInfo - .getPredicateObject(OntologyConstants.KnoraBase.ObjectClassConstraint) - .getOrElse( - throw InconsistentRepositoryDataException(s"Property $prop has no knora-base:objectClassConstraint") - ) - } + searchCriteria: Seq[SearchCriterion] = + searchGetRequest.propertyIri.lazyZip(searchGetRequest.compareProps).lazyZip(searchGetRequest.searchValue).map { + (prop, compop, searchval) => + val propertyEntityInfo = propertyInfo.propertyInfoMap(prop) + + // If the property is a linking property, we pretend its knora-base:objectClassConstraint is knora-base:Resource, so validTypeCompopCombos will work. + val propertyObjectClassConstraint: IRI = if (propertyEntityInfo.isLinkProp) { + OntologyConstants.KnoraBase.Resource + } else { + propertyEntityInfo + .getPredicateObject(OntologyConstants.KnoraBase.ObjectClassConstraint) + .getOrElse( + throw InconsistentRepositoryDataException(s"Property $prop has no knora-base:objectClassConstraint") + ) + } + + // Ensure that the property's objectClassConstraint is valid, and that the specified operator can be + // used with it. + validTypeCompopCombos.get(propertyObjectClassConstraint) match { + case Some(validOps) => + if (!validOps.contains(compop)) { + // The class specified in the property's objectClassConstraint can't be used with the specified operator. + throw BadRequestException(s"Operator $compop cannot be used with property $prop") + } - // Ensure that the property's objectClassConstraint is valid, and that the specified operator can be - // used with it. - validTypeCompopCombos.get(propertyObjectClassConstraint) match { - case Some(validOps) => - if (!validOps.contains(compop)) { - // The class specified in the property's objectClassConstraint can't be used with the specified operator. - throw BadRequestException(s"Operator $compop cannot be used with property $prop") + case None => + // The class specified in the property's objectClassConstraint is invalid. + throw BadRequestException( + s"Property $prop has an invalid knora-base:objectClassConstraint: $propertyObjectClassConstraint" + ) } - case None => - // The class specified in the property's objectClassConstraint is invalid. - throw BadRequestException( - s"Property $prop has an invalid knora-base:objectClassConstraint: $propertyObjectClassConstraint" + val searchParamWithoutValue = SearchCriterion( + propertyIri = prop, + comparisonOperator = compop, + valueType = propertyObjectClassConstraint ) - } - val searchParamWithoutValue = SearchCriterion( - propertyIri = prop, - comparisonOperator = compop, - valueType = propertyObjectClassConstraint - ) - - // check and convert the searchval if necessary (e.g. check if a given string is numeric or convert a date string to a date) + // check and convert the searchval if necessary (e.g. check if a given string is numeric or convert a date string to a date) - if (compop == SearchComparisonOperatorV1.EXISTS) { - // EXISTS doesn't need the searchval at all. - searchParamWithoutValue - } else { - propertyObjectClassConstraint match { - case OntologyConstants.KnoraBase.DateValue => - // - // It is a date, parse and convert it to JD - // + if (compop == SearchComparisonOperatorV1.EXISTS) { + // EXISTS doesn't need the searchval at all. + searchParamWithoutValue + } else { + propertyObjectClassConstraint match { + case OntologyConstants.KnoraBase.DateValue => + // + // It is a date, parse and convert it to JD + // - val datestring = - stringFormatter.validateDate(searchval, throw BadRequestException(s"Invalid date format: $searchval")) + val datestring = + stringFormatter + .validateDate(searchval, throw BadRequestException(s"Invalid date format: $searchval")) - // parse date: Calendar:YYYY-MM-DD[:YYYY-MM-DD] - val parsedDate = datestring.split(StringFormatter.CalendarSeparator) - val calendar = KnoraCalendarV1.lookup(parsedDate(0)) + // parse date: Calendar:YYYY-MM-DD[:YYYY-MM-DD] + val parsedDate = datestring.split(StringFormatter.CalendarSeparator) + val calendar = KnoraCalendarV1.lookup(parsedDate(0)) - // val daysInMonth = Calendar.DAY_OF_MONTH // will be used to determine the number of days in the given month - // val monthsInYear = Calendar.MONTH // will be used to determine the number of months in the given year (generic for other calendars) + // val daysInMonth = Calendar.DAY_OF_MONTH // will be used to determine the number of days in the given month + // val monthsInYear = Calendar.MONTH // will be used to determine the number of months in the given year (generic for other calendars) - val (dateStart, dateEnd) = if (parsedDate.length > 2) { - // it is a period: 0 : cal | 1 : start | 2 : end + val (dateStart, dateEnd) = if (parsedDate.length > 2) { + // it is a period: 0 : cal | 1 : start | 2 : end - val periodStart = DateUtilV1.dateString2DateRange(parsedDate(1), calendar).start - val periodEnd = DateUtilV1.dateString2DateRange(parsedDate(2), calendar).end + val periodStart = DateUtilV1.dateString2DateRange(parsedDate(1), calendar).start + val periodEnd = DateUtilV1.dateString2DateRange(parsedDate(2), calendar).end - val start = DateUtilV1.convertDateToJulianDayNumber(periodStart) - val end = DateUtilV1.convertDateToJulianDayNumber(periodEnd) + val start = DateUtilV1.convertDateToJulianDayNumber(periodStart) + val end = DateUtilV1.convertDateToJulianDayNumber(periodEnd) - // check if end is bigger than start (the user could have submitted a period where start is bigger than end) - if (start > end) - throw BadRequestException(s"Invalid input for period: start is bigger than end: $searchval") + // check if end is bigger than start (the user could have submitted a period where start is bigger than end) + if (start > end) + throw BadRequestException(s"Invalid input for period: start is bigger than end: $searchval") - (start, end) - } else { - // no period: 0 : cal | 1 : start + (start, end) + } else { + // no period: 0 : cal | 1 : start - val dateRange = DateUtilV1.dateString2DateRange(parsedDate(1), calendar) + val dateRange = DateUtilV1.dateString2DateRange(parsedDate(1), calendar) - val start = DateUtilV1.convertDateToJulianDayNumber(dateRange.start) - val end = DateUtilV1.convertDateToJulianDayNumber(dateRange.end) + val start = DateUtilV1.convertDateToJulianDayNumber(dateRange.start) + val end = DateUtilV1.convertDateToJulianDayNumber(dateRange.end) - (start, end) - } + (start, end) + } - searchParamWithoutValue.copy( - dateStart = Some(dateStart), - dateEnd = Some(dateEnd) - ) + searchParamWithoutValue.copy( + dateStart = Some(dateStart), + dateEnd = Some(dateEnd) + ) - case OntologyConstants.KnoraBase.TextValue => - // http://www.morelab.deusto.es/code_injection/ - // http://stackoverflow.com/questions/29601839/prevent-sparql-injection-generic-solution-triplestore-independent - val searchString = stringFormatter - .toSparqlEncodedString(searchval, throw BadRequestException(s"Invalid search string: '$searchval'")) - - val (matchBooleanPositiveTerms, matchBooleanNegativeTerms) = - if (compop == SearchComparisonOperatorV1.MATCH_BOOLEAN) { - val terms = searchString.asInstanceOf[String].split("\\s+").toSet - val negativeTerms = terms.filter(_.startsWith("-")) - val positiveTerms = terms -- negativeTerms - val negativeTermsWithoutPrefixes = negativeTerms.map(_.stripPrefix("-")) - val positiveTermsWithoutPrefixes = positiveTerms.map(_.stripPrefix("+")) - (positiveTermsWithoutPrefixes, negativeTermsWithoutPrefixes) - } else { - (Set.empty[String], Set.empty[String]) - } + case OntologyConstants.KnoraBase.TextValue => + // http://www.morelab.deusto.es/code_injection/ + // http://stackoverflow.com/questions/29601839/prevent-sparql-injection-generic-solution-triplestore-independent + val searchString = stringFormatter + .toSparqlEncodedString(searchval, throw BadRequestException(s"Invalid search string: '$searchval'")) + + val (matchBooleanPositiveTerms, matchBooleanNegativeTerms) = + if (compop == SearchComparisonOperatorV1.MATCH_BOOLEAN) { + val terms = searchString.asInstanceOf[String].split("\\s+").toSet + val negativeTerms = terms.filter(_.startsWith("-")) + val positiveTerms = terms -- negativeTerms + val negativeTermsWithoutPrefixes = negativeTerms.map(_.stripPrefix("-")) + val positiveTermsWithoutPrefixes = positiveTerms.map(_.stripPrefix("+")) + (positiveTermsWithoutPrefixes, negativeTermsWithoutPrefixes) + } else { + (Set.empty[String], Set.empty[String]) + } - searchParamWithoutValue.copy( - searchValue = Some(searchString), - matchBooleanPositiveTerms = matchBooleanPositiveTerms, - matchBooleanNegativeTerms = matchBooleanNegativeTerms - ) + searchParamWithoutValue.copy( + searchValue = Some(searchString), + matchBooleanPositiveTerms = matchBooleanPositiveTerms, + matchBooleanNegativeTerms = matchBooleanNegativeTerms + ) - case OntologyConstants.KnoraBase.IntValue => - // check if string is an integer - val searchString = stringFormatter - .validateInt(searchval, throw BadRequestException(s"Given searchval is not an integer: $searchval")) - .toString - searchParamWithoutValue.copy(searchValue = Some(searchString)) - - case OntologyConstants.KnoraBase.DecimalValue => - // check if string is a decimal number - val searchString = stringFormatter - .validateBigDecimal( - searchval, - throw BadRequestException(s"Given searchval is not a decimal number: $searchval") - ) - .toString - searchParamWithoutValue.copy(searchValue = Some(searchString)) - - case OntologyConstants.KnoraBase.TimeValue => - // check if string is an integer - val searchString = stringFormatter - .xsdDateTimeStampToInstant( - searchval, - throw BadRequestException(s"Given searchval is not a timestamp: $searchval") - ) - .toString - searchParamWithoutValue.copy(searchValue = Some(searchString)) - - case OntologyConstants.KnoraBase.Resource => - // check if string is a valid IRI - val searchString = stringFormatter.validateAndEscapeIri( - searchval, - throw BadRequestException(s"Given searchval is not a valid IRI: $searchval") - ) - searchParamWithoutValue.copy(searchValue = Some(searchString)) - - case OntologyConstants.KnoraBase.ColorValue => - // check if string is a hexadecimal RGB-color value - val searchString = - stringFormatter.validateColor(searchval, throw BadRequestException(s"Invalid color format: $searchval")) - searchParamWithoutValue.copy(searchValue = Some(searchString)) - - case OntologyConstants.KnoraBase.GeomValue => - // this only will be used with compop EXISTS - searchParamWithoutValue.copy(searchValue = Some("")) - - case OntologyConstants.KnoraBase.GeonameValue => - // sanitize Geoname search string - val searchString = stringFormatter - .toSparqlEncodedString( - searchval, - throw BadRequestException(s"Invalid Geoname search string: '$searchval'") - ) + case OntologyConstants.KnoraBase.IntValue => + // check if string is an integer + val searchString = stringFormatter + .validateInt(searchval, throw BadRequestException(s"Given searchval is not an integer: $searchval")) + .toString + searchParamWithoutValue.copy(searchValue = Some(searchString)) + + case OntologyConstants.KnoraBase.DecimalValue => + // check if string is a decimal number + val searchString = stringFormatter + .validateBigDecimal( + searchval, + throw BadRequestException(s"Given searchval is not a decimal number: $searchval") + ) + .toString + searchParamWithoutValue.copy(searchValue = Some(searchString)) + + case OntologyConstants.KnoraBase.TimeValue => + // check if string is an integer + val searchString = stringFormatter + .xsdDateTimeStampToInstant( + searchval, + throw BadRequestException(s"Given searchval is not a timestamp: $searchval") + ) + .toString + searchParamWithoutValue.copy(searchValue = Some(searchString)) + + case OntologyConstants.KnoraBase.Resource => + // check if string is a valid IRI + val searchString = stringFormatter.validateAndEscapeIri( + searchval, + throw BadRequestException(s"Given searchval is not a valid IRI: $searchval") + ) + searchParamWithoutValue.copy(searchValue = Some(searchString)) + + case OntologyConstants.KnoraBase.ColorValue => + // check if string is a hexadecimal RGB-color value + val searchString = + stringFormatter + .validateColor(searchval, throw BadRequestException(s"Invalid color format: $searchval")) + searchParamWithoutValue.copy(searchValue = Some(searchString)) + + case OntologyConstants.KnoraBase.GeomValue => + // this only will be used with compop EXISTS + searchParamWithoutValue.copy(searchValue = Some("")) + + case OntologyConstants.KnoraBase.GeonameValue => + // sanitize Geoname search string + val searchString = stringFormatter + .toSparqlEncodedString( + searchval, + throw BadRequestException(s"Invalid Geoname search string: '$searchval'") + ) - searchParamWithoutValue.copy(searchValue = Some(searchString)) + searchParamWithoutValue.copy(searchValue = Some(searchString)) - case OntologyConstants.KnoraBase.UriValue => - // validate URI - val searchString = - stringFormatter.validateAndEscapeIri(searchval, throw BadRequestException(s"Invalid URI: $searchval")) - searchParamWithoutValue.copy(searchValue = Some(searchString)) + case OntologyConstants.KnoraBase.UriValue => + // validate URI + val searchString = + stringFormatter + .validateAndEscapeIri(searchval, throw BadRequestException(s"Invalid URI: $searchval")) + searchParamWithoutValue.copy(searchValue = Some(searchString)) - case OntologyConstants.KnoraBase.ListValue => - // check if string represents a node in a list - val searchString = stringFormatter.validateAndEscapeIri( - searchval, - throw BadRequestException(s"Given searchval is not a formally valid IRI $searchval") - ) - searchParamWithoutValue.copy(searchValue = Some(searchString)) - - case OntologyConstants.KnoraBase.BooleanValue => - // check if searchVal is a Boolan value - val searchString = stringFormatter - .validateBoolean( - searchval, - throw BadRequestException(s"Given searchval is not a valid Boolean value: $searchval") - ) - .toString - searchParamWithoutValue.copy(searchValue = Some(searchString)) + case OntologyConstants.KnoraBase.ListValue => + // check if string represents a node in a list + val searchString = stringFormatter.validateAndEscapeIri( + searchval, + throw BadRequestException(s"Given searchval is not a formally valid IRI $searchval") + ) + searchParamWithoutValue.copy(searchValue = Some(searchString)) + + case OntologyConstants.KnoraBase.BooleanValue => + // check if searchVal is a Boolan value + val searchString = stringFormatter + .validateBoolean( + searchval, + throw BadRequestException(s"Given searchval is not a valid Boolean value: $searchval") + ) + .toString + searchParamWithoutValue.copy(searchValue = Some(searchString)) - case other => throw BadRequestException(s"The value type for the given property $prop is unknown.") - } + case other => throw BadRequestException(s"The value type for the given property $prop is unknown.") + } + } } - } // Get the search results. searchSparql = org.knora.webapi.messages.twirl.queries.sparql.v1.txt diff --git a/webapi/src/test/scala/org/knora/webapi/messages/util/standoff/StandoffTagUtilV2Spec.scala b/webapi/src/test/scala/org/knora/webapi/messages/util/standoff/StandoffTagUtilV2Spec.scala index 72011dfef1..ad94e3a4e3 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/util/standoff/StandoffTagUtilV2Spec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/util/standoff/StandoffTagUtilV2Spec.scala @@ -5,8 +5,6 @@ package org.knora.webapi.util.standoff -import java.util.UUID - import akka.util.Timeout import org.knora.webapi.CoreSpec import org.knora.webapi.messages.IriConversions._ @@ -15,6 +13,7 @@ import org.knora.webapi.messages.util.standoff.StandoffTagUtilV2 import org.knora.webapi.messages.v2.responder.standoffmessages._ import org.knora.webapi.sharedtestdata.SharedTestDataADM +import java.util.UUID import scala.concurrent.Await import scala.concurrent.duration._ diff --git a/webapi/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala b/webapi/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala index f5c5660ba6..ba9f03a656 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala @@ -3272,6 +3272,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { val guiElementTypeFromMessage = predicateInfo.objects.head.asInstanceOf[SmartIriLiteralV2] val guiElementTypeInternal = guiElementTypeFromMessage.toOntologySchema(InternalSchema) guiElementTypeFromMessage should equal(guiElementTypeInternal) + case None => () } // Check that the salsah-gui:guiElement from the message is as expected diff --git a/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/CacheSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/CacheSpec.scala index 0d8d02aa21..15955e0a89 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/CacheSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/CacheSpec.scala @@ -7,32 +7,24 @@ package org.knora.webapi.responders.v2.ontology import akka.actor.Props import org.knora.webapi.feature.{FeatureFactoryConfig, KnoraSettingsFeatureFactoryConfig} -import org.knora.webapi.messages.{OntologyConstants, SmartIri, StringFormatter} -import org.knora.webapi.messages.store.triplestoremessages.{ - IriLiteralV2, - RdfDataObject, - SmartIriLiteralV2, - StringLiteralV2 -} +import org.knora.webapi.messages.store.triplestoremessages.{RdfDataObject, SmartIriLiteralV2, StringLiteralV2} import org.knora.webapi.messages.util.KnoraSystemInstances -import org.knora.webapi.messages.v2.responder.SuccessResponseV2 import org.knora.webapi.messages.v2.responder.ontologymessages.{ PredicateInfoV2, PropertyInfoContentV2, ReadOntologyV2, ReadPropertyInfoV2 } +import org.knora.webapi.messages.{OntologyConstants, SmartIri, StringFormatter} import org.knora.webapi.settings.KnoraDispatchers -import org.knora.webapi.sharedtestdata.SharedOntologyTestDataADM import org.knora.webapi.store.triplestore.http.HttpTriplestoreConnector import org.knora.webapi.util.cache.CacheUtil import org.knora.webapi.{IntegrationSpec, InternalSchema, TestContainerFuseki} import java.time.Instant -import scala.concurrent.{Await, Future} import scala.concurrent.duration._ +import scala.concurrent.{Await, Future} import scala.language.postfixOps -import scala.util.{Failure, Success} /** * This spec is used to test [[org.knora.webapi.responders.v2.ontology.Cache]]. @@ -84,11 +76,12 @@ class CacheSpec extends IntegrationSpec(TestContainerFuseki.PortConfig) { res.size should equal(13) } } - } "Updating the ontology cache," when { + val CACHE_NOT_AVAILABLE_ERROR = "Cache not available" + "removing a property from an ontology," should { "remove the property from the cache." in { @@ -100,7 +93,7 @@ class CacheSpec extends IntegrationSpec(TestContainerFuseki.PortConfig) { val previousBooksMaybe = previousCacheData.ontologies.get(iri) previousBooksMaybe match { - case Some(previousBooks) => { + case Some(previousBooks) => // copy books-onto but remove :hasTitle property val newBooks = previousBooks.copy( ontologyMetadata = previousBooks.ontologyMetadata.copy( @@ -124,17 +117,19 @@ class CacheSpec extends IntegrationSpec(TestContainerFuseki.PortConfig) { // ensure that the cache updated correctly val newCachedBooksMaybe = newCachedCacheData.ontologies.get(iri) newCachedBooksMaybe match { - case Some(newCachedBooks) => { + case Some(newCachedBooks) => // check length assert(newCachedBooks.properties.size != previousBooks.properties.size) assert(newCachedBooks.properties.size == newBooks.properties.size) // check actual property - previousBooks.properties should contain key (hasTitlePropertyIri) + previousBooks.properties should contain key hasTitlePropertyIri newCachedBooks.properties should not contain key(hasTitlePropertyIri) - } + + case None => fail(message = CACHE_NOT_AVAILABLE_ERROR) } - } + + case None => fail(message = CACHE_NOT_AVAILABLE_ERROR) } } } @@ -151,7 +146,7 @@ class CacheSpec extends IntegrationSpec(TestContainerFuseki.PortConfig) { val previousBooksMaybe = previousCacheData.ontologies.get(iri) previousBooksMaybe match { - case Some(previousBooks) => { + case Some(previousBooks) => // copy books-onto but add :hasDescription property val descriptionProp = ReadPropertyInfoV2( entityInfoContent = PropertyInfoContentV2( @@ -217,19 +212,20 @@ class CacheSpec extends IntegrationSpec(TestContainerFuseki.PortConfig) { // ensure that the cache updated correctly val newCachedBooksMaybe = newCachedCacheData.ontologies.get(iri) newCachedBooksMaybe match { - case Some(newCachedBooks) => { + case Some(newCachedBooks) => // check length assert(newCachedBooks.properties.size != previousBooks.properties.size) assert(newCachedBooks.properties.size == newBooks.properties.size) // check actual property previousBooks.properties should not contain key(hasDescriptionPropertyIri) - newCachedBooks.properties should contain key (hasDescriptionPropertyIri) - } + newCachedBooks.properties should contain key hasDescriptionPropertyIri + + case None => fail(message = CACHE_NOT_AVAILABLE_ERROR) } - } - } + case None => fail(message = CACHE_NOT_AVAILABLE_ERROR) + } } "add a link property and a link value property to the cache." in { @@ -243,7 +239,7 @@ class CacheSpec extends IntegrationSpec(TestContainerFuseki.PortConfig) { val previousCacheData = Await.result(Cache.getCacheData, 2 seconds) previousCacheData.ontologies.get(ontologyIri) match { - case Some(previousBooks) => { + case Some(previousBooks) => // copy books-ontology but add link from book to page val linkPropertyInfoContent = PropertyInfoContentV2( propertyIri = hasPagePropertyIri, @@ -308,7 +304,7 @@ class CacheSpec extends IntegrationSpec(TestContainerFuseki.PortConfig) { // ensure that the cache updated correctly newCachedCacheData.ontologies.get(ontologyIri) match { - case Some(newCachedBooks) => { + case Some(newCachedBooks) => // check length assert(newCachedBooks.properties.size != previousBooks.properties.size) assert(newCachedBooks.properties.size == newBooks.properties.size) @@ -323,20 +319,21 @@ class CacheSpec extends IntegrationSpec(TestContainerFuseki.PortConfig) { val newHasPageValuePropertyMaybe = newCachedBooks.properties.get(hasPageValuePropertyIri) newHasPageValuePropertyMaybe should not equal (None) newHasPageValuePropertyMaybe match { - case Some(newHasPageValueProperty) => { + case Some(newHasPageValueProperty) => assert(newHasPageValueProperty.isEditable) assert(newHasPageValueProperty.isLinkValueProp) - } + + case None => fail(message = CACHE_NOT_AVAILABLE_ERROR) } newCachedBooks should equal(newBooks) - } + + case None => fail(message = CACHE_NOT_AVAILABLE_ERROR) } - } - } + case None => fail(message = CACHE_NOT_AVAILABLE_ERROR) + } } } - } }