<commit_before>/*
 * Copyright 2012 SFB 632.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package annis.sqlgen;

import annis.service.objects.SaltURIGroupSet;
import annis.CommonHelper;
import annis.model.QueryNode;
import annis.ql.parser.QueryData;
import annis.service.objects.SaltURIGroup;
import java.net.URI;
import java.util.List;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.StringUtils;

import static annis.sqlgen.AbstractSqlGenerator.TABSTOP;
import static annis.sqlgen.TableAccessStrategy.CORPUS_TABLE;
import static annis.sqlgen.TableAccessStrategy.NODE_TABLE;

import static annis.sqlgen.SqlConstraints.sqlString;
import annis.sqlgen.extensions.AnnotateQueryData;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Map;

/**
 * Generates a WITH clause sql statement for a list of salt ids.
 *
 * Salt ids are simple URI and are defined like this:
 *
 * <p>{@code salt:/corp1/corp2/doc1}</p>.
 *
 * The leading / of the URI is a must, // would cause an error, because
 * authorities are currently not supported.
 *
 * @author <NAME> <<EMAIL>>
 * @author <NAME> <<EMAIL>>
 */
public class GraphWithClauseGenerator extends CommonAnnotateWithClauseGenerator
{
  
  private String selectForNode(
    TableAccessStrategy tas, AnnotateQueryData annotateQueryData,
    int match,
    int nodeNr, 
    String indent)
  {
    StringBuilder sb = new StringBuilder();

    
    sb.append(match).append(" AS n, ");
    sb.append(nodeNr).append(" AS nodeNr,\n").append(indent);
    
    sb.append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".")
      .append(tas.columnName(NODE_TABLE, "id")).append(" AS ")
      .append("id, ");

    sb.append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".")
      .append(tas.columnName(NODE_TABLE, "text_ref")).append(" AS ")
      .append("text, ");

    sb.append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".")
      .append(tas.columnName(NODE_TABLE, "left_token"));

    if (annotateQueryData.getSegmentationLayer() == null)
    {
      sb.append(" - ").append(annotateQueryData.getLeft());
    }
    sb.append(" AS ").append("min, ");

    sb.append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".")
      .append(tas.columnName(NODE_TABLE, "right_token"));
    if (annotateQueryData.getSegmentationLayer() == null)
    {
      sb.append(" + ").append(annotateQueryData.getRight());
    }
    sb.append(" AS ").append("max, ");

    sb.append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".")
      .append(tas.columnName(NODE_TABLE, "corpus_ref"))
      .append(" AS ").append("corpus, ");

    sb.append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".")
      .append(tas.columnName(NODE_TABLE, "node_name"))
      .append(" AS ").append("name");

    return sb.toString();
  }
  
  private String fromForNode(
    TableAccessStrategy tas, String indent,
      int nodeNr)
  {
    StringBuilder sb = new StringBuilder();
    sb.append(indent)
        .append(tas.tableName(NODE_TABLE)).append(" AS ")
        .append(tas.tableName(NODE_TABLE)).append(nodeNr).append(", ")
        .append(tas.tableName(CORPUS_TABLE)).append(" AS ")
        .append(tas.tableName(CORPUS_TABLE)).append(nodeNr);
    
    return sb.toString();
  }
  
  private String whereForNode(URI uri,
    TableAccessStrategy tas, List<Long> corpusList, String indent,
      int nodeNr)
  {
    StringBuilder sb = new StringBuilder();
    // check for corpus/document by it's path
      sb.append(indent)
        .append(tas.tableName(CORPUS_TABLE)).append(nodeNr).append(".path_name = ")
        .append(generatePathName(uri)).append(" AND\n");

      // join the found corpus/document to the facts table
      sb.append(indent)
        .append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".corpus_ref = ")
        .append(tas.tableName(CORPUS_TABLE)).append(nodeNr).append(".id AND\n");

      // filter the node with the right name
      sb.append(indent)
        .append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".node_name = ")
        .append("'").append(uri.getFragment()).append("'").append(" AND\n");

      // use the toplevel partioning
      sb.append(indent)
        .append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".toplevel_corpus IN ( ")
        .append(StringUtils.join(corpusList, ",")).append(") ");
      return sb.toString();
  }
  
  
  private String subselectForMatch(int match, int nodeNr, URI uri, 
    TableAccessStrategy tas, AnnotateQueryData annoQueryData, List<Long> corpusList, 
    String indent)
  {
    StringBuilder sb = new StringBuilder();
    
    sb.append(indent).append("SELECT ").append(
      selectForNode(tas, annoQueryData, match, nodeNr, indent+TABSTOP)).append("\n");
    sb.append(indent).append("FROM ").append(fromForNode(tas, indent, nodeNr)).append("\n");
    sb.append(indent).append("WHERE ").append(whereForNode(uri, tas, corpusList , indent+TABSTOP, nodeNr)).append("\n");
    sb.append(indent).append("LIMIT 1\n");
  
    return sb.toString();
  }
  
  

  @Override
  protected List<String> getMatchesWithClause(QueryData queryData,
    List<QueryNode> alternative, String indent)
  {
    TableAccessStrategy tas = createTableAccessStrategy();
    
    List<AnnotateQueryData> extensions =
      queryData.getExtensions(AnnotateQueryData.class);
    AnnotateQueryData annotateQueryData = extensions.isEmpty()
      ? new AnnotateQueryData(5, 5) : extensions.get(0);
    List<SaltURIGroupSet> listOfSaltURIs = queryData.getExtensions(SaltURIGroupSet.class);
    // only work with the first element
    Validate.isTrue(!listOfSaltURIs.isEmpty());
    
    List<String> subselects = new LinkedList<String>();
    
    
    String indent2 = indent + TABSTOP;
    
    SaltURIGroupSet groupSet = listOfSaltURIs.get(0);
    int matchNr = 1;
    for(Map.Entry<Integer, SaltURIGroup> match : groupSet.getGroups().entrySet())
    {
      List<URI> uriList = match.getValue().getUris();<commit_msg>better formatting<commit_after>/*
 * Copyright 2012 SFB 632.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package annis.sqlgen;

import annis.service.objects.SaltURIGroupSet;
import annis.CommonHelper;
import annis.model.QueryNode;
import annis.ql.parser.QueryData;
import annis.service.objects.SaltURIGroup;
import java.net.URI;
import java.util.List;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.StringUtils;

import static annis.sqlgen.AbstractSqlGenerator.TABSTOP;
import static annis.sqlgen.TableAccessStrategy.CORPUS_TABLE;
import static annis.sqlgen.TableAccessStrategy.NODE_TABLE;

import static annis.sqlgen.SqlConstraints.sqlString;
import annis.sqlgen.extensions.AnnotateQueryData;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Map;

/**
 * Generates a WITH clause sql statement for a list of salt ids.
 *
 * Salt ids are simple URI and are defined like this:
 *
 * <p>{@code salt:/corp1/corp2/doc1}</p>.
 *
 * The leading / of the URI is a must, // would cause an error, because
 * authorities are currently not supported.
 *
 * @author <NAME> <<EMAIL>>
 * @author <NAME> <<EMAIL>>
 */
public class GraphWithClauseGenerator extends CommonAnnotateWithClauseGenerator
{
  
  private String selectForNode(
    TableAccessStrategy tas, AnnotateQueryData annotateQueryData,
    int match,
    int nodeNr, 
    String indent)
  {
    StringBuilder sb = new StringBuilder();

    
    sb.append(match).append(" AS n, ");
    sb.append(nodeNr).append(" AS nodeNr,\n").append(indent);
    
    sb.append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".")
      .append(tas.columnName(NODE_TABLE, "id")).append(" AS ")
      .append("id, ");

    sb.append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".")
      .append(tas.columnName(NODE_TABLE, "text_ref")).append(" AS ")
      .append("text, ");

    sb.append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".")
      .append(tas.columnName(NODE_TABLE, "left_token"));

    if (annotateQueryData.getSegmentationLayer() == null)
    {
      sb.append(" - ").append(annotateQueryData.getLeft());
    }
    sb.append(" AS ").append("min, ");

    sb.append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".")
      .append(tas.columnName(NODE_TABLE, "right_token"));
    if (annotateQueryData.getSegmentationLayer() == null)
    {
      sb.append(" + ").append(annotateQueryData.getRight());
    }
    sb.append(" AS ").append("max, ");

    sb.append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".")
      .append(tas.columnName(NODE_TABLE, "corpus_ref"))
      .append(" AS ").append("corpus, ");

    sb.append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".")
      .append(tas.columnName(NODE_TABLE, "node_name"))
      .append(" AS ").append("name");

    return sb.toString();
  }
  
  private String fromForNode(
    TableAccessStrategy tas, String indent,
      int nodeNr)
  {
    StringBuilder sb = new StringBuilder();
    sb.append(indent)
        .append(tas.tableName(NODE_TABLE)).append(" AS ")
        .append(tas.tableName(NODE_TABLE)).append(nodeNr).append(", ")
        .append(tas.tableName(CORPUS_TABLE)).append(" AS ")
        .append(tas.tableName(CORPUS_TABLE)).append(nodeNr);
    
    return sb.toString();
  }
  
  private String whereForNode(URI uri,
    TableAccessStrategy tas, List<Long> corpusList, String indent,
      int nodeNr)
  {
    StringBuilder sb = new StringBuilder();
    // check for corpus/document by it's path
      sb.append(indent)
        .append(tas.tableName(CORPUS_TABLE)).append(nodeNr).append(".path_name = ")
        .append(generatePathName(uri)).append(" AND\n");

      // join the found corpus/document to the facts table
      sb.append(indent)
        .append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".corpus_ref = ")
        .append(tas.tableName(CORPUS_TABLE)).append(nodeNr).append(".id AND\n");

      // filter the node with the right name
      sb.append(indent)
        .append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".node_name = ")
        .append("'").append(uri.getFragment()).append("'").append(" AND\n");

      // use the toplevel partioning
      sb.append(indent)
        .append(tas.tableName(NODE_TABLE)).append(nodeNr).append(".toplevel_corpus IN ( ")
        .append(StringUtils.join(corpusList, ",")).append(") ");
      return sb.toString();
  }
  
  
  private String subselectForMatch(int match, int nodeNr, URI uri, 
    TableAccessStrategy tas, AnnotateQueryData annoQueryData, List<Long> corpusList, 
    String indent)
  {
    StringBuilder sb = new StringBuilder();
    
    sb.append(indent).append("SELECT ").append(
      selectForNode(tas, annoQueryData, match, nodeNr, indent+TABSTOP)).append("\n");
    sb.append(indent).append("FROM\n").append(fromForNode(tas, indent+TABSTOP, nodeNr)).append("\n");
    sb.append(indent).append("WHERE\n").append(whereForNode(uri, tas, corpusList , indent+TABSTOP, nodeNr)).append("\n");
    sb.append(indent).append("LIMIT 1\n");
  
    return sb.toString();
  }
  
  

  @Override
  protected List<String> getMatchesWithClause(QueryData queryData,
    List<QueryNode> alternative, String indent)
  {
    TableAccessStrategy tas = createTableAccessStrategy();
    
    List<AnnotateQueryData> extensions =
      queryData.getExtensions(AnnotateQueryData.class);
    AnnotateQueryData annotateQueryData = extensions.isEmpty()
      ? new AnnotateQueryData(5, 5) : extensions.get(0);
    List<SaltURIGroupSet> listOfSaltURIs = queryData.getExtensions(SaltURIGroupSet.class);
    // only work with the first element
    Validate.isTrue(!listOfSaltURIs.isEmpty());
    
    List<String> subselects = new LinkedList<String>();
    
    
    String indent2 = indent + TABSTOP;
    
    SaltURIGroupSet groupSet = listOfSaltURIs.get(0);
    int matchNr = 1;
    for(Map.Entry<Integer, SaltURIGroup> match : groupSet.getGroups().entrySet())
    {
      List<URI> uriList = match.getValue().getUris();
{'fraction_non_alphanumeric': 0.13860557162429593, 'fraction_numerical': 0.0035012939564621707, 'mean_word_length': 3.7917578409919765, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7250907', 'n_tokens_mistral': 4222, 'n_tokens_neox': 4134, 'n_words': 848}