quarta-feira, 25 de fevereiro de 2009

Delphi Intraweb - Gerar dinamicamente JavaScript

Continuação do artigo Delphi Intraweb – JavaScript II (Continua)

Antes de qualquer coisa, preciso registrar a alegria de podermos contar com mais um colaborador no nosso blog.
Prezados leitores, em nome de todos os colaboradores, quero manifestar a alegria em poder contar com mais um grande amigo no time do Estação ZN. Rodrigo Alencar, brother de longas datas tem contribuído com um material de extrema qualidade, pertinência e originalidade.
Rodrigão, seja bem vindo ao Estação ZN, é uma honra poder contar com o sua participação!

Dando continuidade ao tema ...

Para controlarmos, através de JavaScript, a ação de habilitar e desabilitar o IWCombo1 (O que carregamos com os nomes das bandas) vamos gerar dinamicamente o script que vai no browser fazer esse gerenciamento.
Adicione no IWForm mais um IWCheckBox, e codifique conforme ilustrado abaixo:


private
procedure LoadComboBandas;
procedure DesabilitaControles;
procedure BuildScriptControlEnabled;
public

Na seção “private” declarei o método que vai construir dinamicamente o JavaScript, “BuildScriptControlEnabled”.
procedure TZnIWForm.BuildScriptControlEnabled;
const
  FunctionJsBodyStatment = 'function %s{%s}';
  AQuebraLinhaJs = #13;
  AStatementFnc =
      '  var ZnComboLnd = FindElem("%s");' + AQuebraLinhaJs +
      '  alert(ZnComboLnd[ZnComboLnd.selectedIndex].innerHTML);' + AQuebraLinhaJs +
      '  var ZnChkBox = FindElem("%s");' + AQuebraLinhaJs +
      '  alert(ZnChkBox.innerHTML);' + AQuebraLinhaJs +
      '  ZnChkBox.checked  = !ZnChkBox.checked;' + AQuebraLinhaJs +
      '  ZnComboLnd.disabled = !ZnChkBox.checked;'  + AQuebraLinhaJs +
      ' if (!ZnComboLnd.disabled){ ' + AQuebraLinhaJs +
      '   alert(ZnComboLnd.name + " está Habilitado"); ' + AQuebraLinhaJs +
      '   ZnComboLnd.style.backgroundColor = "#FFFFFF"; ' + AQuebraLinhaJs +
      '   ZnComboLnd.focus(); ' + AQuebraLinhaJs +
      '   return true; ' + AQuebraLinhaJs +
      '  } ' + AQuebraLinhaJs +
      ' else{ '+ AQuebraLinhaJs +
      ' ZnComboLnd.style.backgroundColor ="#E7E7E7"; '+ AQuebraLinhaJs +
      '   return false; ' + AQuebraLinhaJs +
      ' };'+ AQuebraLinhaJs;
var
  StrStatement: String;
begin
  StrStatement := AQuebraLinhaJs;
  StrStatement :=  StrStatement + Format(AStatementFnc,
    [UpperCase(IWComboBox1.Name), UpperCase(ChckBoxBandas.Name)]);

  StrStatement := Format(FunctionJsBodyStatment,
    ['ZnHabilitaCmbBanda()', StrStatement]);
  Self.JavaScript.Add(StrStatement);
  ChckBoxBandas.ScriptEvents.Add('onClick').EventCode.Add('ZnHabilitaCmbBanda()');
end;


Observe que temos problemas na hora de trabalharmos com o objeto do tipo “CheckBox”. Veja que, para montar a string que será adicionada a propriedade “JavaScript” do IWForm, na linha 8, recuperamos o objeto com função “FindElem()”.Do contrário, teríamos que usar o nome completo do componente (definido em JavaScript na página web). Ou seja, teríamos que concatenar com o nome do controle (IWCheckBox) no Delphi como bendito sufixo “_CHECKBOX”.
Na linha 9, somos obrigados a simular o comportamento “Click” do objeto. Que absurdo! Do contrário ele não efetiva o “Click”. Pelo menos, essa foi a solução que encontrei, visto que o click do componente não rolava.
Na linha 10, somente então, efetivamos a atribuição de valor a propriedade “disabled” do objeto recuperado na linha 7 (o “IWComboBox1”).

No trecho de código abaixo, podemos ver como ficou no browser a função que dinamicamente montamos no Delphi:
function ZnHabilitaCmbBanda(){
  var ZnCombo = document.forms[0].IWCOMBOBOX1;
  var ZnChkBox = FindElem("CHCKBOXBANDAS");
  ZnChkBox.checked  = !ZnChkBox.checked;
  ZnCombo.disabled = !ZnChkBox.checked;
 if (!ZnCombo.disabled){ 
   alert(ZnCombo.name + " está Habilitado"); 
   ZnCombo.style.backgroundColor = "#FFFFFF"; 
   ZnCombo.focus(); 
   return true; 
  }; 
 else{ 
 ZnCombo.style.backgroundColor ="#E7E7E7"; 
 };
}


Isso acontece especialmente no Intraweb 8 porque ele trata o comportamento de todo “CheckBox” com uma tag “span”. Como se não bastasse isso, para complicar ainda mais, ele agrega, arbitráriamente, um sufixo ao nome original do componente, “_CHECKBOX”. Isso certamente deve ter complicado a vida de quem tentou trabalhar com JavaScript no Intraweb 8. Veja um trecho de código gerado no browser pelo Intraweb 8 na definição do “CHCKBOXBANDAS”:


<input tabindex="27" type="CHECKBOX" name="CHCKBOXBANDAS_CHECKBOX">
<span onclick="FindElem('CHCKBOXBANDAS_CHECKBOX').checked =
!FindElem('CHCKBOXBANDAS_CHECKBOX').checked;">Habilitar Bandas</span>
</span>


No Intraweb 5 isso não acontece. Primeiro, não existe o sufixo na definição JavaScript do componente. Segundo, embora exista a tag span, ela presta somente para exibir o conteúdo do caption do IWCheckBox, o comportamento do CheckBox não está programado nela. Portanto, não precisaríamos simular o click em código conforme eu fiz na linha 04 da “function ZnHabilitaCmbBanda()”. Alias, se alguém tiver algo a acrescentar a minha análise, por favor, fique a vontade. Em outras, palavras, foi a solução que encontrei.

Outro ponto importante, quero destacar nesse exemplo a atribuição dinâmica da propriedade “ScriptEvent” do TIWCheckBox, “ChkBoxBandas”. Isso está sendo feito na linha 28 do procedimento “BuildScriptControlEnabled”.

Artigo completo (View Full Post)

segunda-feira, 9 de fevereiro de 2009

Sistema de tarifação, HSQLDB e Java - PARTE 2.

Continuando o post anterior...

O problema é interceptar determinados eventos em um servidor de download para tarifação em tempo real em um servidor de tarifação. O servidor de download permite a instalação de plug-ins escritos em Java para interceptar os eventos de download.

No post anterior vimos a implementação do servidor de download e um plugin de exemplo. Neste post vamos ver a outra ponta: o sistema de tarifação. O sistema de tarifação é um sistema implementado em um servidor de banco de dados com tabelas e stored procedures.

O sistema que vamos ver é um sistema simulado, composto de uma tabela e três procedures que consultam e atualizam o sistema.

As procedures são as seguintes e todas possuem dois parâmetros, o primeiro é o id do usuário e o segundo o servico que ele esta tentando acessar.

boolean queryBalance(int, string) - consulta se o usuário possui saldo para acessar o serviço.
void charge(int, string) - tarifa o usuário no serviço especificado.
void credit(int, string) - estorna o usuário no serviço especificado.

O sistema é implementado no HSQLDB, um gerenciador de banco de dados escrito em Java. O HSQLDB possui um instalação simples e rápida. O HSQLDB possui suporte a stored procedures escritas em Java.

Para a instalação basta fazer o download e descompactar o arquivo no diretório de sua preferência.

Após descompactar no diretório de destino você vai ter uma pasta chamada hsqldb. No prompt de comando dentro dessa pasta execute o camando abaixo para executar o HSQLDB no modo servidor.

java -classpath ./lib/hsqldb.jar org.hsqldb.Server

Para executar a ferramenta administrativa do HSQLDB execute o comando abaixo.

java -cp ./lib/hsqldb.jar org.hsqldb.util.DatabaseManager

Para a criação das stored procedures utilizei o Netbeans. Uma stored procedure no HSQLDB é um método stático de uma classe Java. E a classe Java deve estar no classpath do servidor. Esse método acessa o ambiente do servidor através de um parâmetro Connection declarado na assinatura do método.

Nesse sistema criei uma classe chamada hsqldbSP_Billing no pacote hsqldbSP_Billing. A classe é a seguinte.

package hsqldbSP_Billing;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class hsqldbSP_Billing {

    public static double DOWNLOAD = 10;

    public static boolean query(Connection conn, Integer id, String service) throws SQLException{
        boolean hasBalance = false;
        Statement st = null;
        ResultSet rs = null;
        st = conn.createStatement();
        String sql = "select amount from balance where id = " + id;
        rs = st.executeQuery(sql);

        if(rs.next()) {
            double amount = rs.getDouble("amount");
            if(amount > 0){
                hasBalance = true;
            }
        }

        st.close();
        return hasBalance;
    }

    public static void charge(Connection conn, Integer id, String service) throws SQLException{
        String sql = "update balance set amount = amount - ? where id = ?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setDouble(1, DOWNLOAD);
        pstmt.setInt(2, id);

        pstmt.executeUpdate();

        pstmt.close();
    }

    public static void credit(Connection conn, Integer id, String service) throws SQLException{
        String sql = "update balance set amount = amount + ? where id = ?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setDouble(1, DOWNLOAD);
        pstmt.setInt(2, id);

        pstmt.executeUpdate();

        pstmt.close();
    }
}


No HSQLDB podemos criar aliases para as SPs através do seguinte comando.
CREATE ALIAS QUERYBALANCE FOR "hsqldbSP_Billing.hsqldbSP_Billing.query"

No HSQLDB a assinatura da procedure possui somente do dois últimos parâmetros pois a Connection será passada pelo servidor. Parar executar as stores procedures a sintaxe é a seguinte.
call queryBalance(1, 'DOWNLOAD')
call charge(1, 'DOWNLOAD')
call credit(1, 'DOWNLOAD')

Executando o código.

Faça o download do arquivo hsqldb.zip e copie seu conteúdo para a pasta do HSQLDB. Este arquivo possui dois arquivos para auxiliar na execução do HSQLDB para este exemplo, o run.bat que executa o servidor HSQLDB com as SPs no classpath e o arquivo manager.bat que executa a ferramente administrativa do HSQLDB. Além disso esse arquivo possui a configuração inicial das tabelas e aliases necessárias para o sistema.

No arquivo hsqldbSP_Billing.zip está o projeto Netbeans com o código das SPs criadas.

No próximo post vamos criar a infra necessária para acessar o sistema de tarifação através de um sistema BPEL.

Até o próximo post!
Rodrigo Alencar.

Artigo completo (View Full Post)

 
BlogBlogs.Com.Br