package webCAPPCombd;

import comHttp.RequisitorHttp;
import combd.TabelaDeResultado;
import infoUsinagem.Ferramenta;
import infoUsinagem.FerramentaTorneamentoExterno;
import infoUsinagem.FerramentaTorneamentoInterno;
import infoUsinagem.FerramentaSangramentoExterno;
import infoUsinagem.FerramentaSangramentoInterno;
import infoUsinagem.FerramentaRosqueamentoExterno;
import infoUsinagem.FerramentaRosqueamentoInterno;
import infoUsinagem.FerramentaUtilizada;

import java.util.LinkedList;

/**
 * Fornece métodos para a busca de ferramentas no banco de dados. Cada
 * ferramenta é escolhida de acordo com a geometria a ser usinada.
 *
 * @author Marcos V. S. Godinho
 * @version 1.0
 */
public class DeterminadorDeFerramenta{

  private static final String URI_DO_SERVLET = ":8080/combdServlet/combdservlet";

  //Contantes das tabelas.
  private static final String TAB_SUPORTE_TGI = "suporte_TGI";
  private static final String TAB_SUPORTE_TGE = "suporte_TGE";
  private static final String TAB_SUPORTE_SANGRAMENTO = "suporte_sangramento";
  private static final String TAB_SUPORTE_ROSQUEAMENTO = "suporte_rosqueamento";
  private static final String TAB_PASTILHA_TG = "pastilha_TG";
  private static final String TAB_PASTILHA_SANGRAMENTO = "pastilha_sangramento";
  private static final String TAB_PASTILHA_ROSQUEAMENTO = "pastilha_rosqueamento";

  //Contantes gerais codigos de todas as ferramentas.
  private static final String COL_ID_PASTILHA = "id_pastilha";
  private static final String COL_ID_SUPORTE = "id_suporte";
  private static final String COL_COD_SUPORTE = "codigo_suporte";//é necessário a TAB tambem.
  private static final String COL_COD_PASTILHA = "codigo_pastilha";//é necessário a TAB tambem.
  private static final String COL_CLASSE = "classe";

  //Contantes das variaveis das ferramentas de TG, sangramento e rosqueamento.
  private static final String COL_DIRECAO_AVANCO = "direcao_avanco";//é necessário a TAB tambem.

  //Contantes das variaveis das ferramentas de TG e sangramento.
  private static final String COL_RAIO_PONTA  = "raio_ponta";
  private static final String COL_MIN_AP = "min_ap";
  private static final String COL_MAX_AP = "max_ap";
  private static final String COL_MIN_FN = "min_fn";
  private static final String COL_MAX_FN = "max_fn";

  //para ferramenta de TG.
  private static final String COL_ANG_PONTA = "angulo_ponta";
  private static final String COL_ESP_PASTILHA = "espessura_pastilha";
  private static final String COL_COMP_ARESTA_CORTE = "comp_aresta_corte";
  private static final String COL_CUT_IN = "cut_in";
  private static final String COL_CUT_OUT = "cut_out";
  private static final String COL_COMP_SUPORTE = "comprimento_suporte";

  //para torneamento geral externo.
  private static final String COL_LARGURA_SUPORTE = "largura_suporte";

  //para sangramento externo e rosqueamento externo. Área da secção do suporte em mm²
  private static final String COL_SECCAO_BARRA = "dimensao_b_l1 * dimensao_h_f1";

  //para torneamento geral interno, sangramento interno e rosqueamento interno.
  private static final String COL_DIAMETRO_MIN_DA_BARRA = "diametro_min_barra";
  private static final String COL_DIAMETRO_BARRA = "diametro_barra";

  //para sangramento.
  private static final String COL_ANG_FRONTAL = "angulo_frontal";
  private static final String COL_LARGURA_PASTILHA = "largura_pastilha";
  private static final String COL_MAX_PROFUNDIDADE_CORTE = "limitacoes_usinagem";
  private static final String COL_TIPO_SUPORTE = "tipo_suporte";
  private static final String COL_ANG_SUPORTE = "angulo_suporte";
  private static final String COL_MIN_FNX = "min_fnx";
  private static final String COL_MAX_FNX = "max_fnx";

  //para rosqueamento.
  private static final String COL_PERFIL_ROSCA = "perfil_rosca";
  private static final String COL_PASSO= "passo";
  private static final String COL_TIPO_FERRAMENTA = "tipo_ferramenta";

  //Colunas usadas no INNER JOIN em torneamento geral.
  private static final String COL_FORMATO_PASTILHA = "formato_pastilha";//é necessário a TAB tambem.
  private static final String COL_COMP_ARESTA = "comp_aresta_corte";//é necessário a TAB tambem.

  //Coluna usada no INNER JOIN em sangramento.
  private static final String COL_TAM_ASSENTO_PASTILHA = "tamanho_assento_pastilha";//é necessário a TAB tambem.

  //Coluna usada no INNER JOIN em rosqueamento.
  private static final String COL_TAMANHO_PASTILHA = "tamanho_pastilha";//é necessário a TAB tambem.

  //separadores.
  private static final String SEP = ", ";
  private static final String DOT = ".";
  //Colunas comuns em TG.
  private static final String COLUNAS_TG =
      COL_ID_PASTILHA + SEP +
      COL_ID_SUPORTE + SEP +
      COL_CLASSE + SEP +
      TAB_PASTILHA_TG+DOT+COL_FORMATO_PASTILHA + SEP +
      COL_DIRECAO_AVANCO + SEP +
      COL_ANG_PONTA + SEP +
      COL_RAIO_PONTA + SEP +
      COL_ESP_PASTILHA + SEP +
      TAB_PASTILHA_TG +DOT+ COL_COMP_ARESTA_CORTE + SEP +
      COL_CUT_IN + SEP +
      COL_CUT_OUT + SEP +
      COL_COMP_SUPORTE + SEP +
      COL_MIN_AP + SEP +
      COL_MAX_AP + SEP +
      COL_MIN_FN + SEP +
      COL_MAX_FN + SEP +
      COL_COMP_SUPORTE;

  //Colunas comuns em sangramento.
  private static final String COLUNAS_SANGRAMENTO =
      TAB_PASTILHA_SANGRAMENTO +DOT+ COL_COD_PASTILHA + SEP +
      TAB_SUPORTE_SANGRAMENTO +DOT+ COL_COD_SUPORTE + SEP +
      COL_ID_PASTILHA + SEP +
      COL_ID_SUPORTE + SEP +
      COL_CLASSE + SEP +
      TAB_SUPORTE_SANGRAMENTO +DOT+ COL_DIRECAO_AVANCO + SEP +
      COL_ANG_FRONTAL + SEP +
      COL_RAIO_PONTA + SEP +
      COL_LARGURA_PASTILHA + SEP +
      COL_MAX_PROFUNDIDADE_CORTE + SEP +
      COL_TIPO_SUPORTE + SEP +
      TAB_PASTILHA_SANGRAMENTO +DOT+ COL_TAM_ASSENTO_PASTILHA + SEP +
      COL_ANG_SUPORTE + SEP +
      COL_MIN_AP + SEP +
      COL_MAX_AP + SEP +
      COL_MIN_FN + SEP +
      COL_MAX_FN + SEP +
      COL_MIN_FNX + SEP +
      COL_MAX_FNX;

  //Colunas comuns em rosqueamento.
  private static final String COLUNAS_ROSQUEAMENTO =
      TAB_PASTILHA_ROSQUEAMENTO +DOT+ COL_COD_PASTILHA + SEP +
      TAB_SUPORTE_ROSQUEAMENTO +DOT+ COL_COD_SUPORTE + SEP +
      COL_ID_PASTILHA + SEP +
      COL_ID_SUPORTE + SEP +
      COL_CLASSE + SEP +
      TAB_SUPORTE_ROSQUEAMENTO +DOT+ COL_DIRECAO_AVANCO + SEP +
      COL_PERFIL_ROSCA + SEP +
      COL_PASSO + SEP +
      COL_TIPO_FERRAMENTA + SEP +
      TAB_PASTILHA_ROSQUEAMENTO +DOT+ COL_TAMANHO_PASTILHA;




  //Parametros de filtragem.
  private static final String CONDICAO_CUT_IN = " cut_in >= ? ";
  private static final String CONDICAO_CUT_OUT = " cut_out >= ? ";
  private static final String CONDICAO_DIAMETRO = " diametro_barra < ? ";
  private static final String CONDICAO_LARGURA = " largura_pastilha <= ? ";
  private static final String CONDICAO_PROFUNDIDADE = " limitacoes_usinagem >= ? ";
  private static final String CONDICAO_ANG_SUPORTE = " angulo_suporte = ? ";
  private static final String CONDICAO_PERFIL_ROSCA = " perfil_rosca = ? ";
  private static final String CONDICAO_PASSO = " passo = ? ";

  //Ordenação das ferramentas.
  private static final String ORDER_BY = " ORDER BY " +
      COL_DIRECAO_AVANCO;
  private static final String ORDER_BY_DESBASTE = ORDER_BY  + SEP  +
      COL_ANG_PONTA + " DESC" + SEP +
      COL_RAIO_PONTA + " DESC" + SEP +
      COL_ESP_PASTILHA + " DESC" + SEP +
      TAB_PASTILHA_TG +DOT+ COL_COMP_ARESTA_CORTE + " DESC" + SEP;
  private static final String ORDER_BY_ACABAMENTO = ORDER_BY  + SEP  +
      COL_ANG_PONTA + SEP +
      COL_RAIO_PONTA + " DESC" + SEP +
      COL_ESP_PASTILHA + SEP +
      TAB_PASTILHA_TG +DOT+ COL_COMP_ARESTA_CORTE + SEP;
  private static final String ORDER_BY_SANGRAMENTO = ORDER_BY  + SEP +
      COL_LARGURA_PASTILHA + " DESC" + SEP +
      COL_MAX_PROFUNDIDADE_CORTE;




  //Query de busca de ferramenta montada.
  private static final String QUERY_FERRAMENTA_UTILIZADA  =
      "SELECT num_magazine, num_compensacao FROM ferramenta_montada" +
      " WHERE id_pastilha = ? AND id_suporte = ?";
  private static final String COL_NUM_MAGAZINE = "num_magazine";
  private static final String COL_NUM_COMPENSACAO = "num_compensacao";

  /**
   * Indica que uma condição de busca não é aplicável.
   */
  public static final int NAO_SE_APLICA = -3267;

  private RequisitorHttp requisitor;
  //"http://localhost:8080/combdServlet/combdservlet";

  /**
   * Cria um instância do determinador de ferramenta.
   *
   * @param urlDoServidor a URL do servidor onde está o servlet.
   */
  public DeterminadorDeFerramenta(String urlDoServidor){

    requisitor =  new RequisitorHttp(urlDoServidor + URI_DO_SERVLET);
  }


  //Se a ferramenta estiver montada, busca seus dados da torre.
  private Ferramenta verificaSeEstaNaTorre(Object id_pastilha, Object id_suporte, Ferramenta ferramenta){

    TabelaDeResultado dadosTorre = (TabelaDeResultado)requisitor.requisitaQuery(
      QUERY_FERRAMENTA_UTILIZADA,
      new Object[]{//Parametros de busca.
      id_pastilha, id_suporte});

    if(dadosTorre.existeDados()){

      int numMagazine = Integer.parseInt(dadosTorre.getDado(COL_NUM_MAGAZINE,0).toString());
      int numCompensacao = Integer.parseInt(dadosTorre.getDado(COL_NUM_COMPENSACAO,0).toString());

      return new FerramentaUtilizada(ferramenta, numMagazine,
                                     numCompensacao, "teste");
    }

    return ferramenta;
  }//verificaSeEstaNaTorre


  //Coloca as ferramentas utilizadas como preferencia e devolve o array reordenado.
  private Ferramenta[] preferenciaDasUtilizadas(Ferramenta[] arrayTemp){

    Ferramenta[] ferramentas = new Ferramenta[arrayTemp.length];
    int k=0;
    for(int j=0; j < ferramentas.length; j++){

      if(arrayTemp[j] instanceof FerramentaUtilizada){

        ferramentas[k++] = arrayTemp[j];
        arrayTemp[j] = null;
      }
    }
    for(int j=0; j < ferramentas.length; j++){

      if(arrayTemp[j] == null) continue;

        ferramentas[k++] = arrayTemp[j];
    }

    return ferramentas;
  }//preferenciaDasUtilizadas


  private Ferramenta[] determinaFerramentaTG(String orderBy,
      double cutIn, double cutOut, double diametro){

    String qry = "SELECT " + TAB_PASTILHA_TG+DOT+COL_COD_PASTILHA + SEP;
    //Define se o suporte é de torneamento interno ou externo.
    String tabelaSuporte = (diametro == NAO_SE_APLICA ?
                            TAB_SUPORTE_TGE : TAB_SUPORTE_TGI);
    //Inclui tabela do codigo do suporte.
    qry += tabelaSuporte+DOT+COL_COD_SUPORTE + SEP;
    //Inclui variáveis comuns.
    qry += COLUNAS_TG + SEP;
    //Inclui variáveis particulares.
    if(diametro == NAO_SE_APLICA){

      qry += COL_LARGURA_SUPORTE;
    }
    else{

      qry += COL_DIAMETRO_MIN_DA_BARRA + SEP + COL_DIAMETRO_BARRA;
    }
    //Inclui tabelas a serem buscadas.
    qry += " FROM " + TAB_PASTILHA_TG + " INNER JOIN " + tabelaSuporte +
        " ON " + tabelaSuporte+DOT+COL_FORMATO_PASTILHA  + "=" + TAB_PASTILHA_TG+DOT+COL_FORMATO_PASTILHA +
        " AND " + tabelaSuporte+DOT+COL_COMP_ARESTA  + "=" + TAB_PASTILHA_TG+DOT+COL_COMP_ARESTA + " ";
    //Inclui condições.
    if(cutIn != NAO_SE_APLICA ||
       cutOut != NAO_SE_APLICA ||
       diametro != NAO_SE_APLICA)  qry += "WHERE ";

    //Define os parametros de entrada.
    LinkedList parametros = new LinkedList();

    if(cutIn != NAO_SE_APLICA){

      qry += CONDICAO_CUT_IN;
      parametros.addLast( new Double(cutIn) );
    }

    if(cutOut != NAO_SE_APLICA){

      qry += (parametros.size() > 0 ? " AND " : "") +CONDICAO_CUT_OUT;
      parametros.addLast( new Double(cutOut) );
    }

    if(diametro != NAO_SE_APLICA){

      qry += (parametros.size() > 0 ? " AND " : "") +CONDICAO_DIAMETRO;
      parametros.addLast( new Double(diametro) );
    }

    //Inclui ordenação.
    qry += orderBy +
      (diametro == NAO_SE_APLICA ?
                      COL_LARGURA_SUPORTE : COL_DIAMETRO_MIN_DA_BARRA)
      + " DESC" + SEP +
      COL_COMP_SUPORTE;

  System.out.println(qry);

    TabelaDeResultado resposta = (TabelaDeResultado)requisitor.requisitaQuery(
        qry, parametros.toArray());

    Ferramenta[] arrayTemp = new Ferramenta[resposta.getNumLinhas()];
    Ferramenta temp = null;

    for(int i=0; i < arrayTemp.length; i++){

      if(diametro == NAO_SE_APLICA){

        temp = new FerramentaTorneamentoExterno(
                      resposta.getDado(COL_COD_PASTILHA, i),
                      resposta.getDado(COL_COD_SUPORTE, i),
                      resposta.getDado(COL_CLASSE, i),
                      resposta.getDado(COL_FORMATO_PASTILHA, i),
                      resposta.getDado(COL_DIRECAO_AVANCO, i),
                      resposta.getDado(COL_ANG_PONTA, i),
                      resposta.getDado(COL_RAIO_PONTA, i),
                      resposta.getDado(COL_ESP_PASTILHA, i),
                      resposta.getDado(COL_COMP_ARESTA_CORTE, i),
                      resposta.getDado(COL_CUT_IN, i),
                      resposta.getDado(COL_CUT_OUT, i),
                      resposta.getDado(COL_COMP_SUPORTE, i),
                      resposta.getDado(COL_LARGURA_SUPORTE, i),
                      resposta.getDado(COL_MIN_AP, i),
                      resposta.getDado(COL_MAX_AP, i),
                      resposta.getDado(COL_MIN_FN, i),
                      resposta.getDado(COL_MAX_FN, i) );
      }
      else{

        temp = new FerramentaTorneamentoInterno(
                      resposta.getDado(COL_COD_PASTILHA, i),
                      resposta.getDado(COL_COD_SUPORTE, i),
                      resposta.getDado(COL_CLASSE, i),
                      resposta.getDado(TAB_PASTILHA_TG+DOT+COL_FORMATO_PASTILHA, i),
                      resposta.getDado(COL_DIRECAO_AVANCO, i),
                      resposta.getDado(COL_ANG_PONTA, i),
                      resposta.getDado(COL_RAIO_PONTA, i),
                      resposta.getDado(COL_ESP_PASTILHA, i),
                      resposta.getDado(COL_COMP_ARESTA_CORTE, i),
                      resposta.getDado(COL_CUT_IN, i),
                      resposta.getDado(COL_CUT_OUT, i),
                      resposta.getDado(COL_COMP_SUPORTE, i),
                      resposta.getDado(COL_DIAMETRO_MIN_DA_BARRA, i),
                      resposta.getDado(COL_DIAMETRO_BARRA, i),
                      resposta.getDado(COL_MIN_AP, i),
                      resposta.getDado(COL_MAX_AP, i),
                      resposta.getDado(COL_MIN_FN, i),
                      resposta.getDado(COL_MAX_FN, i) );

      }

      //Se a ferramenta estiver montada, busca seus dados da torre.
      arrayTemp[i] = verificaSeEstaNaTorre(resposta.getDado(COL_ID_PASTILHA, i),
        resposta.getDado(COL_ID_SUPORTE, i), temp);
    }//for

    //Coloca as ferramentas utilizadas como preferencia.
    return preferenciaDasUtilizadas(arrayTemp);
  }//determinaFerramentaTG


  /**
   * Determina as ferramentas de desbaste interno ou externo que estão aptas
   * a realizar a usinagem na geometria especificada.
   *
   * @param cutIn o maior angulo de entrada da peça a ser usinada. Usar a
   *   constante dessa classe NAO_SE_APLICA se for o caso.
   * @param cutOut o maior angulo de saida da peça a ser usinada. Usar a
   *   constante dessa classe NAO_SE_APLICA se for o caso.
   * @param diametro o menor diametro de um torneamento interno. Usar a
   *   constante dessa classe NAO_SE_APLICA se a operação for externa.
   * @return um array com todas as opções de ferramentas para esse desbaste.
   */
  public Ferramenta[] determinaFerramentaDesbaste(
      double cutIn, double cutOut, double diametro){

      return determinaFerramentaTG(ORDER_BY_DESBASTE, cutIn, cutOut, diametro);
  }//determinaFerramentaDesbaste


  /**
   * Determina as ferramentas de acabamento interno ou externo que estão aptas
   * a realizar a usinagem na geometria especificada.
   *
   * @param cutIn o maior angulo de entrada da peça a ser usinada. Usar a
   *   constante dessa classe NAO_SE_APLICA se for o caso.
   * @param cutOut o maior angulo de saida da peça a ser usinada. Usar a
   *   constante dessa classe NAO_SE_APLICA se for o caso.
   * @param diametro o menor diametro de um torneamento interno. Usar a
   *   constante dessa classe NAO_SE_APLICA se a operação for externa.
   * @return um array com todas as opções de ferramentas para esse acabamento.
   */
  public Ferramenta[] determinaFerramentaAcabamento(
      double cutIn, double cutOut, double diametro){

      return determinaFerramentaTG(ORDER_BY_ACABAMENTO, cutIn, cutOut, diametro);
  }//determinaFerramentaAcabamento


  /**
   * Determina as ferramentas de sangramento interno ou externo especificadas
   * por dados da geometria da feature e do ângulo de suporte desejado.
   *
   * @param largura a largura do sangramento a ser efetuado. Usar a
   *   constante dessa classe NAO_SE_APLICA se for o caso.
   * @param profundidade a profundidade do sangramento a ser efetuado. Usar a
   *   constante dessa classe NAO_SE_APLICA se for o caso.
   * @param angSuporte a angulação do suporte desejado para a operação de sangramento.
   *   Usar a constante dessa classe NAO_SE_APLICA se for o caso.
   * @param diametro o menor diametro de um torneamento interno. Usar a
   *   constante dessa classe NAO_SE_APLICA se a operação for externa.
   * @return um array com todas as opções de ferramentas para esse sangramento.
   */
  public Ferramenta[] determinaFerramentaSangramento( double largura, double profundidade,
      double angSuporte, double diametro){

    String qry = "SELECT " + COLUNAS_SANGRAMENTO + SEP;
    //Inclui variáveis particulares.
    if(diametro == NAO_SE_APLICA){

      qry += COL_SECCAO_BARRA;
    }
    else{

      qry += COL_DIAMETRO_MIN_DA_BARRA + SEP + COL_DIAMETRO_BARRA;
    }

    //Inclui tabelas a serem buscadas.
    qry += " FROM " + TAB_PASTILHA_SANGRAMENTO + " INNER JOIN " + TAB_SUPORTE_SANGRAMENTO +
        " ON " + TAB_PASTILHA_SANGRAMENTO+DOT+COL_TAM_ASSENTO_PASTILHA  +
        "=" + TAB_SUPORTE_SANGRAMENTO+DOT+COL_TAM_ASSENTO_PASTILHA + " ";
    //Inclui condições.
    if(largura != NAO_SE_APLICA ||
       profundidade != NAO_SE_APLICA ||
       angSuporte != NAO_SE_APLICA ||
       diametro != NAO_SE_APLICA)  qry += "WHERE ";

    //Define os parametros de entrada.
    LinkedList parametros = new LinkedList();

    if(largura != NAO_SE_APLICA){

      qry += CONDICAO_LARGURA;
      parametros.addLast( new Double(largura) );
    }

    if(profundidade != NAO_SE_APLICA){

      qry += (parametros.size() > 0 ? " AND " : "") +CONDICAO_PROFUNDIDADE;
      parametros.addLast( new Double(profundidade) );
    }

    if(angSuporte != NAO_SE_APLICA){

      qry += (parametros.size() > 0 ? " AND " : "") +CONDICAO_ANG_SUPORTE;
      parametros.addLast( new Double(angSuporte) );
    }

    if(diametro != NAO_SE_APLICA){

      qry += (parametros.size() > 0 ? " AND " : "") +CONDICAO_DIAMETRO;
      parametros.addLast( new Double(diametro) );
    }

    //inclui ordenação
    qry += ORDER_BY_SANGRAMENTO;

    System.out.println(qry);

    TabelaDeResultado resposta = (TabelaDeResultado)requisitor.requisitaQuery(
        qry, parametros.toArray());

    Ferramenta[] arrayTemp = new Ferramenta[resposta.getNumLinhas()];
    Ferramenta temp = null;

    for(int i=0; i < arrayTemp.length; i++){

      if(diametro == NAO_SE_APLICA){

        temp = new FerramentaSangramentoExterno(
                      resposta.getDado(COL_COD_PASTILHA, i),
                      resposta.getDado(COL_COD_SUPORTE, i),
                      resposta.getDado(COL_CLASSE, i),
                      resposta.getDado(COL_DIRECAO_AVANCO, i),
                      resposta.getDado(COL_ANG_FRONTAL, i),
                      resposta.getDado(COL_RAIO_PONTA, i),
                      resposta.getDado(COL_LARGURA_PASTILHA, i),
                      resposta.getDado(COL_MAX_PROFUNDIDADE_CORTE, i),
                      resposta.getDado(COL_TIPO_SUPORTE, i),
                      resposta.getDado(COL_TAM_ASSENTO_PASTILHA, i),
                      resposta.getDado(COL_ANG_SUPORTE, i),
                      resposta.getDado(COL_SECCAO_BARRA, i),
                      resposta.getDado(COL_MIN_AP, i),
                      resposta.getDado(COL_MAX_AP, i),
                      resposta.getDado(COL_MIN_FN, i),
                      resposta.getDado(COL_MAX_FN, i),
                      resposta.getDado(COL_MIN_FNX, i),
                      resposta.getDado(COL_MAX_FNX, i) );
      }
      else{

        temp = new FerramentaSangramentoInterno(
                      resposta.getDado(COL_COD_PASTILHA, i),
                      resposta.getDado(COL_COD_SUPORTE, i),
                      resposta.getDado(COL_CLASSE, i),
                      resposta.getDado(COL_DIRECAO_AVANCO, i),
                      resposta.getDado(COL_ANG_FRONTAL, i),
                      resposta.getDado(COL_RAIO_PONTA, i),
                      resposta.getDado(COL_LARGURA_PASTILHA, i),
                      resposta.getDado(COL_MAX_PROFUNDIDADE_CORTE, i),
                      resposta.getDado(COL_TIPO_SUPORTE, i),
                      resposta.getDado(COL_TAM_ASSENTO_PASTILHA, i),
                      resposta.getDado(COL_ANG_SUPORTE, i),
                      resposta.getDado(COL_DIAMETRO_MIN_DA_BARRA, i),
                      resposta.getDado(COL_DIAMETRO_BARRA, i),
                      resposta.getDado(COL_MIN_AP, i),
                      resposta.getDado(COL_MAX_AP, i),
                      resposta.getDado(COL_MIN_FN, i),
                      resposta.getDado(COL_MAX_FN, i),
                      resposta.getDado(COL_MIN_FNX, i),
                      resposta.getDado(COL_MAX_FNX, i) );
      }

      //Se a ferramenta estiver montada, busca seus dados da torre.
      arrayTemp[i] = verificaSeEstaNaTorre(resposta.getDado(COL_ID_PASTILHA, i),
                                           resposta.getDado(COL_ID_SUPORTE, i), temp);
    }//for

    //Coloca as ferramentas utilizadas como preferencia.
    return preferenciaDasUtilizadas(arrayTemp);
 }//determinaFerramentaSangramento


 //Constantes dos perfis de rosca.
  /** Rosca Métrica 60°
   * @see #determinaFerramentaRosqueamento
   */
  public static final String ROSCA_MM0 = "MM0";
  /** Rosca Perfil V 60°
   * @see #determinaFerramentaRosqueamento
   */
  public static final String ROSCA_VM0 = "VM0";

 /**
  * Determina as ferramentas de rosqueamento interno ou externo que estão aptas
  * a realizar o rosqueamento desejado.
  *
  * @param perfilRosca código (manual da SANDIVIK) que indica o perfil da rosca.
  *   Usar as contantes de perfil de rosca inseridas nessa classe, caso contrário
  *   poderá ocorrer erros na determinação das ferramentas.
  * @param passo o passo da rosca em milímetros. Usar a
  *   constante dessa classe NAO_SE_APLICA se for o caso.
  * @param diametro o menor diametro de um torneamento interno. Usar a
  *   constante dessa classe NAO_SE_APLICA se a operação for externa.
  * @return um array com todas as opções de ferramentas para esse rosqueamento.
  */
 public Ferramenta[] determinaFerramentaRosqueamento(String perfilRosca, double passo, double diametro){

   String qry = "SELECT " + COLUNAS_ROSQUEAMENTO + SEP;
   //Inclui variáveis particulares.
    if(diametro == NAO_SE_APLICA){

      qry += COL_SECCAO_BARRA;
    }
    else{

      qry += COL_DIAMETRO_MIN_DA_BARRA + SEP + COL_DIAMETRO_BARRA;
    }

    //Inclui tabelas a serem buscadas.
    qry += " FROM " + TAB_PASTILHA_ROSQUEAMENTO + " INNER JOIN " + TAB_SUPORTE_ROSQUEAMENTO +
        " ON " + TAB_PASTILHA_ROSQUEAMENTO+DOT+COL_TAMANHO_PASTILHA  +
        "=" + TAB_SUPORTE_ROSQUEAMENTO+DOT+COL_TAMANHO_PASTILHA + " ";

    //Inclui condições.
    if(perfilRosca != null ||
       passo != NAO_SE_APLICA ||
       diametro != NAO_SE_APLICA)  qry += "WHERE ";

    //Define os parametros de entrada.
    LinkedList parametros = new LinkedList();

    if(perfilRosca != null){

      qry += CONDICAO_PERFIL_ROSCA;
      parametros.addLast( perfilRosca );
    }

    if(passo != NAO_SE_APLICA){

      qry += (parametros.size() > 0 ? " AND " : "") +CONDICAO_PASSO;
      parametros.addLast( new Double(passo) );
    }

    if(diametro != NAO_SE_APLICA){

      qry += (parametros.size() > 0 ? " AND " : "") +CONDICAO_DIAMETRO;
      parametros.addLast( new Double(diametro) );
    }

    //inclui ordenação comum.
    qry += ORDER_BY;

    System.out.println(qry);

    TabelaDeResultado resposta = (TabelaDeResultado)requisitor.requisitaQuery(
        qry, parametros.toArray());

    Ferramenta[] arrayTemp = new Ferramenta[resposta.getNumLinhas()];
    Ferramenta temp = null;

    for(int i=0; i < arrayTemp.length; i++){

      if(diametro == NAO_SE_APLICA){

        temp = new FerramentaRosqueamentoExterno(
                      resposta.getDado(COL_COD_PASTILHA, i),
                      resposta.getDado(COL_COD_SUPORTE, i),
                      resposta.getDado(COL_CLASSE, i),
                      resposta.getDado(COL_DIRECAO_AVANCO, i),
                      resposta.getDado(COL_PERFIL_ROSCA, i),
                      resposta.getDado(COL_PASSO, i),
                      resposta.getDado(COL_TIPO_FERRAMENTA, i),
                      resposta.getDado(COL_TAMANHO_PASTILHA, i),
                      resposta.getDado(COL_SECCAO_BARRA, i) );
      }
      else{

        temp = new FerramentaRosqueamentoInterno(
                      resposta.getDado(COL_COD_PASTILHA, i),
                      resposta.getDado(COL_COD_SUPORTE, i),
                      resposta.getDado(COL_CLASSE, i),
                      resposta.getDado(COL_DIRECAO_AVANCO, i),
                      resposta.getDado(COL_PERFIL_ROSCA, i),
                      resposta.getDado(COL_PASSO, i),
                      resposta.getDado(COL_TIPO_FERRAMENTA, i),
                      resposta.getDado(COL_TAMANHO_PASTILHA, i),
                      resposta.getDado(COL_DIAMETRO_MIN_DA_BARRA, i),
                      resposta.getDado(COL_DIAMETRO_BARRA, i) );
      }

      //Se a ferramenta estiver montada, busca seus dados da torre.
      arrayTemp[i] = verificaSeEstaNaTorre(resposta.getDado(COL_ID_PASTILHA, i),
                                           resposta.getDado(COL_ID_SUPORTE, i), temp);
    }//for

    //Coloca as ferramentas utilizadas como preferencia.
    return preferenciaDasUtilizadas(arrayTemp);
 }//determinaFerramentaRosqueamento

/*
  public Ferramenta[] determinaFerramentaFuracao(){}//determinaFerramentaFuracao

  public Ferramenta[] determinaFerramentaFresamento(){}//determinaFerramentaFresamento
*/
}
