/**
   * Returns the result of replacing each column reference c in the inverse expression with : - the
   * quoted and escaped data value of column c in r, if c is a referenced column in the term map -
   * the column name of column c, otherwise
   *
   * @param stringTemplate
   * @param dbValues
   * @param columnReferences
   * @param dbTypes
   * @return
   * @throws R2RMLDataError
   * @throws SQLException
   * @throws UnsupportedEncodingException
   * @throws MalformedURLException
   */
  public static String extractColumnValueFromInverseExpression(
      String inverseExpression,
      Map<ColumnIdentifier, byte[]> dbValues,
      Set<ColumnIdentifier> columnReferences)
      throws R2RMLDataError, SQLException, UnsupportedEncodingException {
    // Let result be the template string
    String result = inverseExpression;
    if (dbValues == null) return null;

    for (ColumnIdentifier column : dbValues.keySet()) {
      // A quoted and escaped data value is any SQL
      // string that matches the <literal> or <null specification>
      // productions of [SQL2].
      // This string can be used in a SQL query to specify a SQL data
      // value.
      String value = null;
      if (dbValues.get(column) == null) value = "NULL";
      else {
        // Extract db value
        byte[] byteValue = dbValues.get(column);
        // Apply cast to string to the SQL data value
        value = new String(byteValue, "UTF-8");
      }
      result = column.replaceAll(result, "'" + value + "'");
      // Test backslashes result =
      /*
       * result.replaceAll("\\{\\\"" + column + "\\\"\\}", "'" + result +
       * "'"); result = result.replaceAll("\\{\\'" + column + "\\'\\}",
       * "'" + result + "'"); result = result.replaceAll("\\{\\`" + column
       * + "\\`\\}", "'" + result + "'");
       */
    }
    // Replace curly braces of not referenced column references
    for (ColumnIdentifier column : columnReferences) {
      if (!dbValues.keySet().contains(column)) {
        result = column.replaceAll(result, column.toString());
        //				result = result.replaceAll("\\{\\'" + columnStr + "\\'\\}", columnStr);
        //				result = result.replaceAll("\\{\\`" + columnStr + "\\`\\}", columnStr);
      }
    }
    // Curly braces that do not enclose column names MUST be
    // escaped by a backslash character (“\”).
    result = result.replaceAll("\\\\\\{", "{");
    result = result.replaceAll("\\\\\\}", "}");
    return result;
  }
  /**
   * The template value of the term map for a given logical table row is determined as follows.
   *
   * @param stringTemplate
   * @param dbValues
   * @param dbTypes
   * @return
   * @throws R2RMLDataError
   * @throws SQLException
   * @throws UnsupportedEncodingException
   * @throws MalformedURLException
   */
  public static String extractColumnValueFromStringTemplate(
      String stringTemplate, Map<ColumnIdentifier, byte[]> dbValues, ResultSetMetaData dbTypes)
      throws R2RMLDataError, SQLException, UnsupportedEncodingException {
    // Let result be the template string

    String result = stringTemplate;
    if (dbValues == null) return null;
    for (ColumnIdentifier dbValue : dbValues.keySet()) {
      // For each pair of unescaped curly braces in result: if value is
      // NULL, then return NULL
      if (dbValues.get(dbValue) == null) return null;
    }
    for (ColumnIdentifier column : dbValues.keySet()) {
      // Extract db value
      byte[] byteValue = dbValues.get(column);
      // Extract RDF Natural form
      SQLType sqlType = column.getSqlType();
      // Apply cast to string to the SQL data value
      String value;
      if (sqlType != null) {
        XSDType xsdType = SQLToXMLS.getEquivalentType(sqlType);
        value = XSDLexicalTransformation.extractNaturalRDFFormFrom(xsdType, byteValue);
      } else {
        value = new String(byteValue, "UTF-8");
      }
      result = column.replaceAll(result, getIRISafeVersion(value));
      // Test backslashes result =
      /*
       * result.replaceAll("\\{\\\"" + column + "\\\"\\}",
       * getIRISafeVersion(result)); result = result.replaceAll("\\{\\'" +
       * column + "\\'\\}", getIRISafeVersion(result)); result =
       * result.replaceAll("\\{\\`" + column + "\\`\\}",
       * getIRISafeVersion(result));
       */

    }
    // Curly braces that do not enclose column names MUST be
    // escaped by a backslash character (“\”).
    result = result.replaceAll("\\\\\\{", "{");
    result = result.replaceAll("\\\\\\}", "}");

    return result;
  }