def parseQueryString()

in backend/app/model/frontend/Chip.scala [60:105]


  def parseQueryString(q: String): ParsedChips = {
    val parsedQ = Json.parse(q)
    // workspace_folder chips need to be handled separately from the rest.
    // Instead of transforming the chips to a query string, we need to use
    // workspace and folder IDs to find a list of blob so filter for. Look for
    // those IDs here, then skip workspace_folder when building the query.
    val workspaceFolder = parsedQ match {
      case JsArray(value) => value.collectFirst {
        case JsObject(o) if o.get("t").map(_.validate[String].get).get == "workspace_folder" => 
            WorkspaceSearchContextParams(o.get("workspaceId").map(_.validate[String].get).get, o.get("folderId").map(_.validate[String].get).get)
      }
      case _ => None
    }

    val query = parsedQ match {
      case JsArray(v) => v.toList.filter {
        // remove workspace_folder chips
        case JsObject(o) if o.get("t").map(_.validate[String].get).get == "workspace_folder" => false
        case _ => true
      }.map {
        // When typing a new chip, we end up with a dangling + which is illegal in the ES query syntax.
        // This doesn't matter if you start a chip before an existing term or in between two existing.
        // In that case it will be parsed as the boolean operator attached to the subsequent term.
        // Weirdly this seems to work even if it's just whitespace after the plus so no need to trim
        case JsString(s) if s.endsWith("+") || s.endsWith("-") =>
          s.substring(0, s.length - 1)
        case JsString(s) =>
          s
        case JsObject(o) =>
          val name: String = o.get("n").map(_.validate[String].get).get
          val value: String = o.get("v").map(_.validate[String].get).get
          val op: String = o.get("op").map(_.validate[String].get).get

          val template: String = all.find(suggestion => suggestion.name == name).map(_.template).get

          // The query syntax will fail to parse with text() so we convert to text("") if no value is set
          // which happens when you've inserted the chip but haven't typed into it yet
          val sanitisedValue = if(value.isEmpty) { "\"\"" } else  { value }

          op + template.replace("_word_", sanitisedValue)
        case _ => throw new UnsupportedOperationException("Invalid json type in query array")
      }.mkString(" ")
      case _ => throw new UnsupportedOperationException("Outer json type must be an array")
    }
    ParsedChips(query, workspaceFolder)
  }