domenica 24 luglio 2011

Esempio JSP e Ajax


In questo post vediamo un esempio di utilizzo della tecnologia Ajax “nuda e cruda”;capita a volte infatti di dover intervenire su applicazioni già pre esistenti e può essere utile “modernizzarle” senza dover per forza riscrivere tutto oppure utilizzare framework javascript.
E' utile inoltre anche per capire le basi di questa tecnologia che ha rivoluzionato il web avvicinandolo sempre più al mondo desktop.
Nell'esempio abbiamo una jsp con una textbox su cui inserire un numero e poi due bottoni, uno per la chiamata Ajax ed una per il post tradizionale.
Entrambi i pulsanti richiamano la stessa servlet, che dato il numero inserito calcola il codice Isin corretto (ove possibile) ; la classe richiamata è la stessa del precedente post.

La pagina jsp è la seguente:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="/WebAjaxTest/js/util.js"></script>
<title>Test Isin Ajax</title>
</head>
<body>
<form method="post" action="/WebAjaxTest/GestioneIsin">
<input type="text" name="txtName" id="idTxtName" value="${valoreCodice}"/><br>
<div id="contenuto">

${result}
</div>
<input type="button" onclick="javascript:chiamaServlet('/WebAjaxTest/GestioneIsin')" name="btnInvio" value="Test chiamata Ajax"/>
<input type="submit" value="Test Chiamata Server"/>
</form>
</body>
</html>


Il pulsante di tipo “button” effettua la chiamata al metodo javascript per scatenare ajax, mentre il pulsante di tipo “submit” effettua la chiamata lato server classica. Entrambe valorizzano il div con id “contenuto” riportando all'interno il codice isin completo elaborato lato server.
Il metodo doPost della Servlet (GestioneIsin) è il seguente:

String valoreCodice=request.getParameter("txtName");
try
{
String codiceIsinCompleto=ItalianIsin.getIsin(valoreCodice);
String richiestaAjax=request.getParameter("ajaxRequest");
if("true".equals(richiestaAjax)){
PrintWriter pw=response.getWriter();
pw.println(codiceIsinCompleto);
pw.flush();
}
else
{
request.setAttribute("result", codiceIsinCompleto);
request.setAttribute("valoreCodice", valoreCodice);
request.getRequestDispatcher("jsp/TestAjax.jsp").forward(request, response);
}
}
catch(IllegalArgumentException iex){
String richiestaAjax=request.getParameter("ajaxRequest");
if("true".equals(richiestaAjax)){
PrintWriter pw=response.getWriter();
pw.println(iex.getMessage());
pw.flush();
}
else
{
request.setAttribute("result", iex.getMessage());
request.setAttribute("valoreCodice", valoreCodice);
request.getRequestDispatcher("jsp/TestAjax.jsp").forward(request, response);
}
}
}


Lato javascript abbiamo invece
/**
* Recupera l'oggetto XMLHttpRequest
*/
function getXMLHttpRequest() {
try {

return new XMLHttpRequest();
} catch (e) {
try {

return new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {
try {
return new ActiveXObject('MSXML2.XMLHTTP.3.0');
} catch(e) {alert('errore');}
}
}
return null;
}
/**
  • Effettua chiamata asincrona in post alla servlet,
  • e mette il contenuto della response http nell'elemento della pagina con
  • id “contenuto”, cioè il div sotto la textbox
*/
function chiamaServlet( url){
var xmlHttp=getXMLHttpRequest();
xmlHttp.onreadystatechange=function (){
if(xmlHttp.readyState==4){
if(xmlHttp.status==200 || xmlHttp.status==0){
var risultatoTxt=xmlHttp.responseText;
var elem=document.getElementById("contenuto");
elem.innerHTML="";
elem.innerHTML=risultatoTxt;
}
else
{
alert('Comunicazione fallita '+xmlHttp.status+" Motivo: "+xmlHttp.statusText);
}
}
};
xmlHttp.open("POST",url,true);
xmlHttp.setRequestHeader("content-type", "application/x-www-form-urlencoded");
xmlHttp.setRequestHeader("connection", "close");
xmlHttp.send("txtName="+document.getElementById("idTxtName").value+"&ajaxRequest=true");
}

Da notare la chiamata in post utilizzando l'oggetto XmlHttpRequest, in particolare l'utilizzo del metodo send concatenando i parametri con il caratter & . Effettuando invece la chiamata in get basta concatenare i parametri nell'url e invocare il metodo send passando il parametro null.
La gestione asincrona della chiamata è implementata utilizzando una funzione anonima javascript che valorizza la proprietà onreadystatechange dell'oggetto XmlHttpRequest

venerdì 22 luglio 2011

Calcolo del CIN in java

Il codice ISIN è un codice internazionale per identificare univocamente gli strumenti finanziari. La struttura del codice e le regole per la sua assegnazione sono stabilite dall'ISO (International Organization for Standardization) nello standard ISO 6166.” (Fonte Banca D’Italia)

ISIN sta per International Securities Identification Number.
Per calcolare il CIN (Control Internal Number) si procede in questo modo:

1. Si concatena il codice nazione e le 9 cifre numeriche inserite dall’utente (con il padding degli zeri a sinistra nel caso siano inferiori a 9), si ottiene così una stringa di 13 caratteri;
2. Ogni cifra dispari nella stringa di 13 è moltiplicata per 2, le cifre così ottenute sono sommate per ottenere un totale di 3 cifre;
3. Al risultato ottenuto al punto 2 si sommano le cifre pari della stringa di 13;
4. Si esegue la differenza tra il numero 10 e la prima cifra a partire da destra del risultato del punto 3, questo è il CIN.

Quindi il codice ISIN sarà dato da IT+9cifre conto+CIN (ovviamente IT nel caso italiano).

Di seguito un esempio di codifica java, con due metodi pubblici che dato il numero conto (come stringa o come intero) calcolano il valore completo dell’ISIN:

1. public static String getIsin(int valoreConto);
2. public static String getIsin(String valoreConto);

 
public class ItalianIsin {

      private static final String ITALIAN_CODE="1829";
     
      /**
       * Torna l'ISIN sotto forma di Stringa contenente
       * IT- 9 cifre con padding degli 0 - CIN
       * @param valoreConto - intero
       * @return
       */
      public static String getIsin(int valoreConto){
            valida(valoreConto);
            String valConto=String.valueOf(valoreConto);
            return getIsin(valConto);
      }
      private static void valida(int valoreConto)
      {
            if(valoreConto>999999999) throw new IllegalArgumentException("Attenzione, il codice conto non può superare le nove cifre!");
          if(valoreConto<=0) throw new IllegalArgumentException("Attenzione, il codice Isin non può essere negativo o nullo");
      }
      /**
       * Torna l'ISIN sotto forma di Stringa contenente
       * IT- 9 cifre con padding degli 0 - CIN
       * @param valoreConto - Stringa
       * @return
       */
      public static String getIsin(String valoreConto){
            String valore1=getCodice(valoreConto,true);
            int totale1=getTotale(valore1);
            int totale2=addCifrePari(totale1, valore1);
            String  cin=getCin(totale2);
            StringBuffer isin=new StringBuffer();
            isin.append("IT");
            isin.append(getCodice(valoreConto, false));
            isin.append(cin);
            return isin.toString();
           
      }
      private static int getValoreProdotto(int val)
      {
            if(val>18)
            {
                  throw new IllegalArgumentException("Attenzione, " +
                             " errore nel calcolo dell'algoritmo per il codice ISIN");
            }
            else
            {
            DecimalFormat d=new DecimalFormat("00");
            String valore=d.format(val);
            char[] list=valore.toCharArray();
            int primo=getIntFromChar(list[0]);
            int secondo=getIntFromChar(list[1]);
           
            return primo+secondo;
           
                 
            }
      }
      /**
       * Cicla sulle cifre dispari,
       * ogni cifra viene moltiplicata per 2
       * e vengono sommate le due cifre del risultato.
       * La somma del risultato così trovato per tutte le cifre
       * costituisce il TOTALE
       * @param theString
       * @return
       */
      private static int getTotale(String theString)
      {
            int totale=0;
            int valore=0;
            for(int i=0;i<theString.length();)
            {
                 
                        char s=theString.toCharArray()[i];
                       
                        valore=getIntFromChar(s)*2;
                        totale+=getValoreProdotto(valore);
                       
                 
                  i=i+2;
            }
            return totale;
      }
     
      private static int getIntFromChar(char c)
      {
            String s=String.valueOf(c);
            return Integer.valueOf(s);
      }
      /**
       * Al totale si sommano le cifre pari
       * @param totale
       * @param theString
       * @return
       */
      private static int addCifrePari(int totale,String theString)
      {
            int retVal=totale;
            for(int i=1;i<theString.length();){
                 
                        char c=theString.toCharArray()[i];
                        retVal+=getIntFromChar(c);
                      i=i+2;
                 
            }
            return retVal;
      }
      /**
       * Viene fatto il padding a 3 cifre sull'intero e
       * poi è presa l'ultima cifra , quindi si
       * sottrae a 10 questa cifra
       * @param elaborato
       * @return
       */
      private static String getCin(int elaborato)
      {
            DecimalFormat df=new DecimalFormat("000");
            String val=df.format(elaborato);
            char myVal=val.toCharArray()[2];
            int isin=10-getIntFromChar(myVal);
            return String.valueOf(isin);
      }
      /**
       * dato il codice come intero, se è per il calcolo fa il padding degli
       * zeri e poi aggiunge in testa 1829, che è il codice dell'Italia.
       * altrimenti torna il valore col padding
       * @param s
       * @param isForCalcolo
       * @return
       */
    private static String getCodice(int s,boolean isForCalcolo)
    {
      DecimalFormat df=new DecimalFormat("000000000");
      if(isForCalcolo){
            return ITALIAN_CODE+df.format(s);
      }
      else
      {
            return df.format(s);
      }
     
    }
   
    private static String getCodice(String s,boolean isForCalcolo)
    {
            try {
                  int val = Integer.valueOf(s);
                  valida(val);
                  return getCodice(val, isForCalcolo);
            } catch (NumberFormatException nfe) {
            throw new IllegalArgumentException("Attenzione il valore inserito per il conto non è un numero");
            }
    }
   
   
}