mercoledì 19 dicembre 2012

Caricare combo da HashMap con JSF 2.0

Per caricare una combo in un componente JSF si possono seguire varie strade.
In questo post vediamo come caricarla a partire da un HashMap.
Di seguito il codice del managed bean:


package org.primefaces.examples.domain;
import java.util.HashMap;
import java.util.Map;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
@ManagedBean(name="myBean")
@ViewScoped
public class CaricaTest {
private Map<String,String> lista=null;
public Map<String, String> getLista() {
 return lista;
}
public void setLista(Map<String, String> lista) {
 this.lista = lista;
}
public CaricaTest(){
 lista=new HashMap<String, String>();
 lista.put("01", "Primo valore");
 lista.put("02", "Secondo valore");
 lista.put("03", "Terzo valore");
}
private String valore;

public String getValore() {
 return valore;
}

public void setValore(String valore) {
 this.valore = valore;
}

}

Adesso vediamo il codice dell'xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"  
    xmlns:h="http://java.sun.com/jsf/html"  
    xmlns:f="http://java.sun.com/jsf/core"  
    xmlns:p="http://primefaces.org/ui"
    xmlns:ui="http://java.sun.com/jsf/facelets">  
   <h:head>
   </h:head>
<h:body> 
<h:form id="form">  
<h:outputText value="Lista: " />  
    <h:selectOneMenu value="myBean.valore">
      <f:selectItems value="#{myBean.lista}" />  
    </h:selectOneMenu>
  </h:form>
</h:body>
</html>

Così facendo però abbiamo un comportamento all'apparenza strano.
A video infatti apparirà la seguente schermata:


Guardando al codice HTML generato vediamo che sono "invertiti" chiave e valore della mappa.
Il comportamento è infatti quello di base del componente, voluto così proprio da specifica.
 La logica è che si preferisce  evitare di far vedere all'utente duplicati nel valore mostrato a video e quindi la key della mappa diventa  la descrizione nella combo e viceversa.
Per impostare la visualizzazione che vogliamo occorre modificare il componente f::selectItems  in questo modo:


<f:selectItems  value="#{myBean.lista.entrySet()}" var="entry" 
     itemValue="#{entry.key}" itemLabel="#{entry.value}" 
     itemDescription="#{entry.value}" />  

In questo modo abbiamo il risultato desiderato (si noti che itemDescription è il tooltip del valore):

lunedì 17 dicembre 2012

Generare xsd da xml

Per effettuare questa operazione è possibile utilizzare svariate utility, una delle più comode è TRANG.
Accedendo al link http://www.thaiopensource.com/download/ bisogna scegliere il link evidenziato nella immagine sottostante:
A questo punto bisogna:
  1. Scompattare il contenuto in una directory del file system;
  2. Copiare in questa directory l'xml dal quale vogliamo ottenere l'xsd;
  3. Da shell digitare il comando java -jar trang.jar xmlFile.xml xmlFile.xsd.



giovedì 13 dicembre 2012

Differenza tra ClassNotFoundException e NoClassDefFoundError

Le due eccezioni sono concettualmente simili (manca qualche jar o .class nel classpath) ma è diversa la tipologia di eccezione, la ClassNotFoundException è di tipo checked (che estende dunque da java.lang.Exception e che ha bisogno del try/catch) mentre la NoClassDefFoundError è di tipo Error , quindi unchecked

java.lang.ClassNotFoundException

L' eccezione ClassNotFoundException si verifica quando una applicazione tenta di chiamare una classe utilizzando :

  • Il metodo forName nella classe Class.
  • Il metodo findSystemClass nella classe  ClassLoader .
  • Il metodo loadClass nella classe ClassLoader
Esempio classico:


public static void main(String[] args) throws Exception{
  Class c=Class.forName("classenonEsistente");
  System.out.println(c.getName());
 }


Tale codice produce il seguente risultato:

Exception in thread "main" java.lang.ClassNotFoundException: classenonEsistente
 at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
 at java.lang.Class.forName0(Native Method)
 at java.lang.Class.forName(Class.java:169)
 at ExceptionSample.main(ExceptionSample.java:5)



java.lang.NoClassDefException

Questa eccezione è sollevata dalla JVM quando cerca di caricare una classe a runtime e non la trova.
E' una sottoclasse di java.lang.LinkageError, il problema è che la classe che stiamo chiamando ne utilizza un'altra a runtime non presente.
Il classico esempio si ha quando proviamo ad invocare da console una classe java dimenticandoci il nome completo del package (il classico Hello World che all'inizio non funziona mai).
Esempio:
Supponiamo di utilizzare la libreria jmimemagic (descritta in un precedente post) e di usarla dimenticandoci di aggiungere al classpath la libreria commons-logging.jar.
Il codice compila correttamente, in quanto la nostra classe richiama esclusivamente la classe MagicMatcher che fa parte della libreria jmimemagic e che è inclusa nel classpath.

A  Runtime abbiamo una NoClassDefException .


public static void main(String[] args)  {
  try
  {
  Magic m=new Magic();
  byte[] lb=FileUtil.load(new File("file/WS.png"));
  MagicMatch match = m.getMagicMatch(lb);
  System.out.println(match.getMimeType());
  }
  catch (Exception e) {
   System.out.println("Eccezione!!!");
   e.printStackTrace();
  }
 }


Eseguendo il codice non si passa per il catch (si ricordi che l'eccezione è sottoclasse di LinkageError e quindi di Throwable, non di Exception) e in console sarà stampata direttamente la NoClassDefException, nel cui stacktrace troviamo anche l'origine dell'errore, che è una eccezione di tipo ClassNotFoundException per l'appunto.

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
 at net.sf.jmimemagic.Magic.(Magic.java:46)
 at MatchMagic.main(MatchMagic.java:21)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
 at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
 ... 2 more


mercoledì 12 dicembre 2012

Itext per generare tabella rtf

In questo esempio vediamo come generare un RTF con IText in cui posizioniamo una tabella generata dinamicamente, passando al metodo di creazione :
  • un array di Stringhe che rappresentano gli header di colonne;
  • una lista di Stringhe che rappresentano i valori , e che devono essere un multiplo della size dell'array di header, esempio con 4 colonne di intestazione per avere 2 righe la size di questa lista deve essere di 8.
Il vantaggio di avere questa tabella è che Itext (a differenza di Jasper Report o meglio del Jasper report che ho usato io qualche anno fa, non so le ultime versioni) genera tabelle facilmente modificabili, mentre Jasper mette dei place holders tipo caselle di testo che rendono molto difficoltoso modificare il file.

Sotto posto il codice:

package chart.example;
import java.awt.Color;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import com.lowagie.text.Cell;
import com.lowagie.text.Document;
import com.lowagie.text.Element;
import com.lowagie.text.Font;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Table;
import com.lowagie.text.rtf.RtfWriter2;

public class TableCreator {
 
 public static void main(String[] args) throws Exception
 {
  FileOutputStream fos = new FileOutputStream("file/executive_summary.rtf");
  Document d=new Document();
  RtfWriter2.getInstance(d, fos );
     d.open();
     String[] lista=new String[]{"Lunedi","Martedi","Mercoledi","Giovedi"};
     List<String> valTot=new ArrayList<String>();
     valTot.add("12");
     valTot.add("15");
     valTot.add("16");
     valTot.add("98");
     valTot.add("12");
     valTot.add("15");
     valTot.add("16");
     valTot.add("98");
     valTot.add("dsfddsdsf");
     valTot.add("baiaffa");
     valTot.add("16");
     valTot.add("98");
     valTot.add("ssssss");
     valTot.add("baiaffone");
     valTot.add("13");
     valTot.add("983");
     valTot.add("dsdsdsdsds");
     valTot.add("baiaffone");
     valTot.add("13");
     valTot.add("983");
     d.add(getSimpleTable(lista, valTot));
     d.close();
    
 }
 
 public static int myFontStyle = Font.UNDEFINED;
 public static Font baseFont = new Font ( myFontStyle, 12, Font.NORMAL );
 public static Font baseFontTabelleHeader=new Font ( myFontStyle, 10, Font.NORMAL );
 public static Table getSimpleTable( String[] header_cells, List<String> column_cells ) throws Exception
 {
  Table table = new Table( header_cells.length );
        if(column_cells.size()%header_cells.length!=0){
        throw new IllegalArgumentException("Attenzione il numero di valori " +
           "deve essere un multiplo del numero di colonne, " +
           "quindi di "+header_cells.length+" " +
             "il valore risulta invece "+column_cells.size());
        }
  table.setBorderWidth(1);
  table.setPadding(2);
        table.setSpacing(0);

        for ( int i = 0 ; i < header_cells.length ; i++ )
        {
         table.addCell( getHeaderCell( header_cells[i], baseFontTabelleHeader ) );
        }
       
        for ( int i = 0 ; i < column_cells.size() ;  )
        {
         for(int k=0;k<header_cells.length;k++){
          table.addCell( getCell( column_cells.get(i), baseFont ) );
          i++;
         }
        }

  return table;
 }

 public static Cell getHeaderCell( String text, Font font ) throws Exception
 {
  Font f = new Font( font );
  f.setStyle(Font.BOLD);
  Cell cell = new Cell( new Paragraph( text, f ) );
        cell.setHeader(true);
        cell.setBackgroundColor( new Color(0xE1E1E1) );
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        return cell;
 }

 public static Cell getCell( String text, Font font ) throws Exception
 {
  Cell cell = new Cell( new Paragraph( text, font ) );
  cell.setHeader(false);
        cell.setHorizontalAlignment(Element.ALIGN_LEFT);
        return cell;
 }

 public static Cell getCenteredCell( String text, Font font ) throws Exception
 {
  Cell cell = new Cell( new Paragraph( text, font ) );
  cell.setHeader(false);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        return cell;
 }
}



sabato 8 dicembre 2012

JFreeChart, esempi realizzazione grafici

In questo posto vediamo come generare 4 tipologie di grafici con JFreeChart, in particolare:

  • Tachimetro (grafico a lancetta);
  • Torta;
  • Istogramma semplice;
  • Istogramma multiplo.
Ho creato un semplice Java Project includendo le seguenti librerie nel classpath:

  • jfreechart-1.0.9.jar;
  • jcommon-1.0.12.jar;
  • iText-2.0.8.jar.
Di seguito incollo la classe main principale, con dei metodi statici che generano delle immagini png per ciascun tipo grafico definito:


package chart.example;
import java.awt.BasicStroke;
import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.PieSectionLabelGenerator;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DialShape;
import org.jfree.chart.plot.MeterInterval;
import org.jfree.chart.plot.MeterPlot;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.Range;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.DefaultValueDataset;
import org.jfree.ui.TextAnchor;
import com.lowagie.text.Font;
public class ChartCreator {
 public static int myFontStyle = Font.UNDEFINED;
 public static Font baseFont = new Font ( myFontStyle, 12, Font.NORMAL );
 public static void main(String[] args) throws Exception {
   creaGraficoATorta();
        creaIstogrammaMultiplo();
        creaTachimetro();
        creaIstogrammaSemplice();
 }
 private static void creaGraficoATorta() throws Exception{
  OutputStream fos=new FileOutputStream(new File("out/torta.png"));
  String[] componenti=new String[]{"Inter","Milan","Rubentus"};
  double[] valori=new double[]{18.0,18.0,28.0};
  JFreeChart chart=creaGraficoATorta(componenti, valori, false);
  ChartUtilities.writeChartAsPNG(fos, chart, 500, 300);
 }
 private static void creaIstogrammaMultiplo() throws Exception{
  OutputStream fos=new FileOutputStream(new File("out/istoMul.png"));
  double[] valori=new double[9];
  valori[0]=20.0;
  valori[1]=65.0;
  valori[2]=15.0;
  valori[3]=30.0;
  valori[4]=50.0;
  valori[5]=20.0;
  valori[6]=25.0;
  valori[7]=60.0;
  valori[8]=15.0;
  String[] componenti=new String[3];
  componenti[0]="Lazio";
  componenti[1]="Lombardia";
  componenti[2]="Toscana";
  String[] sottocomponenti=new String[3];
  sottocomponenti[0]="Ricchi";
  sottocomponenti[1]="Classe Media";
  sottocomponenti[2]="Poveri";
  JFreeChart chart=creaIstogramma(componenti,sottocomponenti, valori, "Ripartizione classi sociali", "Regioni", "Percentuali");
   ChartUtilities.writeChartAsPNG(fos, chart, 500, 300);
 }
 
 private static void creaIstogrammaSemplice() throws Exception
 {
  OutputStream fos=new FileOutputStream(new File("out/isto.png"));
  String[] componenti=new String[]{"Alto","Medio","Basso"};
  double[] valori=new double[]{85.5,75.12,45.56};
  JFreeChart chart=creaIstogramma(componenti, valori, "Andamenti", "", "");
  ChartUtilities.writeChartAsPNG(fos, chart, 500, 300);
 }
 private static void creaTachimetro() throws Exception{
  OutputStream fos=new FileOutputStream(new File("out/tachimetro.png"));
  BigDecimal a=new BigDecimal(37.0);
  BigDecimal b=new BigDecimal(49.0);
  BigDecimal res=a.divide(b,2,RoundingMode.HALF_UP);
  double v=res.doubleValue()*(double)100;
  JFreeChart chart=creaTachimetro(new Double(v), "Esempio", "", Color.WHITE);
  ChartUtilities.writeChartAsPNG(fos, chart, 500, 300);
 }

 public static JFreeChart creaTachimetro(Double valore, String titolo, String sottotitolo, Color bgcolor)
 {
  DefaultValueDataset ds = new DefaultValueDataset();
  ds.setValue(valore);
  MeterPlot plot = new MeterPlot(ds);
  plot.setUnits("%");
  plot.setRange(new Range(0, 100));
  plot.setMeterAngle(210);
  plot.addInterval(new MeterInterval("Intervallo1", new Range(90.0, 100.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(255, 0, 0, 200)));
  plot.addInterval(new MeterInterval("Intervallo2", new Range(80.0, 90.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(255, 51, 0, 200)));
  plot.addInterval(new MeterInterval("Intervallo3", new Range(70.0, 80.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(255, 102, 0, 200)));
  plot.addInterval(new MeterInterval("Intervallo4", new Range(60.0, 70.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(255, 153, 0, 200)));
  plot.addInterval(new MeterInterval("Intervallo5", new Range(50.0, 60.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(255, 204, 0, 200)));
  plot.addInterval(new MeterInterval("Intervallo6", new Range(40.0, 50.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(255, 255, 0, 200)));
  plot.addInterval(new MeterInterval("Intervallo7", new Range(30.0, 40.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(192, 255, 0, 200)));
  plot.addInterval(new MeterInterval("Intervallo8", new Range(20.0, 30.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(128, 255, 0, 200)));
  plot.addInterval(new MeterInterval("Intervallo9", new Range(10.0, 20.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(64, 255, 0, 200)));
  plot.addInterval(new MeterInterval("Intervallo10", new Range(0.0, 10.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(0, 255, 0, 200)));
  plot.setBackgroundPaint(bgcolor);
  plot.setNeedlePaint(Color.BLACK);
  plot.setDialBackgroundPaint(bgcolor);
  plot.setDialOutlinePaint(bgcolor);
  plot.setDialShape(DialShape.CIRCLE);
  plot.setTickLabelsVisible(false);
  plot.setTickSize(100.0);
  plot.setTickPaint(Color.GRAY);
  plot.setValueFont(new java.awt.Font("Dialog", Font.BOLD, 14));
  plot.setValuePaint(Color.BLACK);
  JFreeChart chart = new JFreeChart(null, null, plot, false);
  chart.setBackgroundPaint(bgcolor);
  if (!titolo.equals("")) {
   TextTitle title = new TextTitle(titolo);
   title.setFont(new java.awt.Font("Verdana", Font.BOLD, 12));
   title.setPaint(new Color(0x2684B3));
   chart.setTitle(title);
  }
  if (!sottotitolo.equals("")) {
   TextTitle subtitle = new TextTitle(sottotitolo);
   subtitle.setFont(new java.awt.Font("Verdana", java.awt.Font.ITALIC, 11));
   subtitle.setPaint(new Color(0x2684B3));
   chart.addSubtitle(subtitle);
  }
  return chart;
 }
 public static JFreeChart creaIstogramma(String[] componenti,String[] sottocomponenti,double[] valori,String titolo,String ascissa,String ordinata){
  DefaultCategoryDataset cds=new DefaultCategoryDataset();
  int j=0;
  int cambioComponente=sottocomponenti.length;
  String comp=componenti[j];
  int sottoComp=0;
        for(int i=0;i 1) {
   for (int i = 0; i < componenti.length; i++) {
    renderer.setSeriesItemLabelsVisible(i, true);
    renderer.setSeriesItemLabelGenerator(i, new SeriesLabelGenerator());
   }
  } else {
   renderer.setSeriesItemLabelsVisible(0, true);
   renderer.setSeriesItemLabelGenerator(0, new LabelGenerator(null));
  }
      return chart;
 }
 public static JFreeChart creaIstogramma(String[] componenti,double[] valori,String titolo,String ascissa,String ordinata){
  DefaultCategoryDataset cds=new DefaultCategoryDataset();
        for(int i=0;i

Nel codice sono utilizzate due classi (LabelGenerator e SeriesLabelGenerator) che servono a mostrare nei grafici a torta e a istogramma semplice (LabelGenerator) e nel grafico a istogramma multiplo (SeriesLabelGenerator) i valori con le percentuali.

LabelGenerator


package chart.example;
import java.text.NumberFormat;
import org.jfree.chart.labels.AbstractCategoryItemLabelGenerator;
import org.jfree.chart.labels.CategoryItemLabelGenerator;
import org.jfree.data.category.CategoryDataset;
public class LabelGenerator extends AbstractCategoryItemLabelGenerator implements CategoryItemLabelGenerator {

 private static final long serialVersionUID = 7389531138610633787L;
 private Integer category;
 private NumberFormat formatter = NumberFormat.getPercentInstance();
 public LabelGenerator(int category) {
  this(new Integer(category));
 }
 public LabelGenerator(Integer category) {
  super("", NumberFormat.getInstance());
 this.category = category;
 }
 public String generateLabel(CategoryDataset dataset, int series, int category ) {
  String result = null;
  double base = 0.0;
  if (this.category != null) {
   final Number b = dataset.getValue(series, this.category.intValue());
   base = b.doubleValue();
  }
  else {
   base = calculateSeriesTotal(dataset, series);
  }
  Number value = dataset.getValue(series, category);
  if (value != null) {
   final double v = value.doubleValue();
   //  you could apply some formatting here
   result = "     "+ value.toString() + " (" + this.formatter.format(v / base) + ")";
  }
  return result;
 }
 private double calculateSeriesTotal(CategoryDataset dataset, int series) {
  double result = 0.0;
  for (int i = 0; i < dataset.getColumnCount(); i++) {
   Number value = dataset.getValue(series, i);
   if (value != null) {
    result = result + value.doubleValue();
    }
  }
  return result;
 }
}



SeriesLabelGenerator



package chart.example;
import java.text.NumberFormat;
import org.jfree.chart.labels.AbstractCategoryItemLabelGenerator;
import org.jfree.chart.labels.CategoryItemLabelGenerator;
import org.jfree.data.category.CategoryDataset;
public class SeriesLabelGenerator extends AbstractCategoryItemLabelGenerator implements CategoryItemLabelGenerator {
 private static final long serialVersionUID = 7389531138610633787L;
 private NumberFormat formatter = NumberFormat.getPercentInstance();
 public SeriesLabelGenerator() {
  super("", NumberFormat.getInstance());
 }
 public String generateLabel(CategoryDataset dataset, int series, int category ) {
  String result = null;
  double base = 0.0;
  base = calculateCategoryTotal(dataset, category);
  Number value = dataset.getValue(series, category);
  if (value != null) {
   final double v = value.doubleValue();
   result = "     "+ value.toString() + " (" + this.formatter.format(v / base) + ")";
  }
  return result;
 }
 private double calculateCategoryTotal(CategoryDataset dataset, int category) {
  double result = 0.0;
  for (int i = 0; i < dataset.getRowCount(); i++) {
   Number value = dataset.getValue(i,category);
   if (value != null) {
    result = result + value.doubleValue();
    }
  }
  return result;
 }
}



Il risultato del codice è la generazione delle seguenti immagini:

Torta





Istogramma semplice


Istogramma multiplo


Grafico a lancetta




martedì 4 dicembre 2012

Calcolare il giorno della settimana di un determinato anno

Si può applicare questa formula per calcolare il giorno della settimana dalla data:

x = N + (q)(N - 1) : 4 - (q)(N - 1) : 100 + (q)(N - 1) : 400 + t

Dove
N = anno corrente
q =  resto della divisione
t =  numero giorni trascorsi dall'inizio dell'anno in questione alla data presa in considerazione

Questa formula vale per qualsiasi data successiva al 15/10/1582.
Sotto una veloce implementazione in una classe Java:


import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class GetGiornoSettimana {

	/**
	 * x = N + (q)(N - 1) : 4 - (q)(N - 1) : 100 + (q)(N - 1) : 400 + t
	 * @param args
	 */
	public static void main(String[] args) {
		GetGiornoSettimana g=new GetGiornoSettimana();
		System.out.println(g.getGiornoSettimana(new Date()));
        System.out.println(g.getGiornoSettimana(20, 4, 1978));
       
	}
	private boolean isLeapYear(int anno){
		GregorianCalendar gc=new GregorianCalendar();
		return gc.isLeapYear(anno);
	}
	public String getGiornoSettimana(int giorno,int mese,int anno){
		return getGiornoSettimana(creaData(giorno, mese, anno));
	}
    public  String getGiornoSettimana(Date data){
    	String retVal="";
    	int anno=getAnnoDaData(data);
    	int val1=anno+getPrimoElemento(anno);
    	int giorniTrascorsi=getGiorniFromInizioAnno(data);
    	int r=val1+giorniTrascorsi;
    	int resto=r%7;
    	switch(resto){
    	case 0:
    		retVal="sabato";
    		break;
    	case 1:
    		retVal="domenica";
    		break;
    	case 2:
    		retVal="lunedi";
    		break;
    	case 3:
    		retVal="martedi";
    		break;
    	case 4:
    		retVal="mercoledi";
    		break;
    	case 5:
    		retVal="giovedi";
    		break;
    	case 6:
    		retVal="venerdi";
    		break;
    		
    	}
    	return retVal;
    }
    private int getPrimoElemento(int anno){
    	return getElemento(anno-1, 4)-getElemento(anno-1, 100)+getElemento(anno-1, 400);
    }
    private int getElemento(int anno,int div){
    	int r=(int)Math.floor((double)anno/(double)div);
    	System.out.println(r);
    	return r;
    }
    private int getGiorniFromInizioAnno(Date d){
    	int anno=getAnnoDaData(d);
    	boolean bisestile=isLeapYear(anno)?true:false;
    	int retVal=0;
    	int mese=getMeseDaData(d);
    	int giorno=getGiornoDaData(d);
    	for(int i=1;i<mese;i++){
    		switch(i){
    		case 2:
    			retVal+=bisestile?29:28;
    		 break;
    		case 4:
    		case 6:
    		case 9:
    		case 11:
    			retVal+=30;
    		 break;
    		default:
    			retVal+=31;
    		 break;
    		}
    	}
    	retVal+=giorno;
    	return retVal;
    }
    private int getAnnoDaData(Date data){
    	Calendar c=Calendar.getInstance();
    	c.setTime(data);
    	return c.get(Calendar.YEAR);
    }
    private int getMeseDaData(Date data){
    	Calendar c=Calendar.getInstance();
    	c.setTime(data);
    	return c.get(Calendar.MONTH)+1;
    }
    private int getGiornoDaData(Date data){
    	Calendar c=Calendar.getInstance();
    	c.setTime(data);
    	return c.get(Calendar.DAY_OF_MONTH);
    }
    private Date creaData(int giorno,int mese,int anno){
        Calendar c=Calendar.getInstance();
        c.set(Calendar.YEAR, anno);
        c.set(Calendar.MONTH, mese-1);
        c.set(Calendar.DAY_OF_MONTH, giorno);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTime();
    } 
   
}




domenica 2 dicembre 2012

JSF 2.0 bean validation con Tomcat

Con il meccanismo di tipo bean validation è possibile, senza specificare per ogni campo la tipologia di validazione necessaria, magari richiamando un metodo del managed bean ogni volta, definire una tipologia generica di validazione a livello di managed bean con una annotazione customizzata, in modo che i metodi di validazione siano richiamati ogni volta che si effettua la validazione del managed bean.
Poichè Tomcat non ha nelle sue librerie quelle del package javax.validation.* occorre per prima cosa scaricare i jar corretti e metterli nella lib del progetto Web.
Ho scaricato l'implementazione hibernate validator 4.3.1 dal sito.
Attenzione, non basta scaricare soltanto la libreria della jsr validation-api-1.0.0.jar, questa infatti è solo un'interfaccia, e peraltro per qualche strano motivo che non ho capito se si inserisce nel classpath soltanto la libreria della JSR non si incappa in nessun errore, ma semplicemente i validatori posti come annotation a livello di managed bean sono ignorati.
Le librerie nella lib del progetto sono quindi le seguenti:
  • hibernate-validator-4.3.1.Final.jar;
  • hibernate-validator-annotation-processor-4.3.1.Final.jar;
  • jboss-logging-3.1.0.CR2.jar;
  • validation-api-1.0.0.GA.jar.
Oltre all'implementazione di JSF 2.0 (ho usato Mojarra):

  • javax.faces-2.1.14.jar;
  • jstl-1.2.jar.

Ho inserito il seguente validatore per il campo tipo mail:



package com.jsfcompref.annotation;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class EmailConstraintValidator implements ConstraintValidator {
 private static final String EMAIL_PATTERN = 
  "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
  + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
 @Override
 public void initialize(Email parameters) {
  // TODO Auto-generated method stub
  
 }

 @Override
 public boolean isValid(String value, ConstraintValidatorContext arg1) {
  Pattern pattern = Pattern.compile(EMAIL_PATTERN);
  Matcher matcher=pattern.matcher(value);
  return matcher.matches();
 }

}
L'annotation chiamata Email è così definita:

package com.jsfcompref.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.*;
import javax.validation.Constraint;
@Documented
@Constraint(validatedBy=EmailConstraintValidator.class)
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Email {
String message() default "{validator.email})";
Class[] groups() default{};
Class[] payload() default{};
}


Quindi basta annotare il managed bean in questo modo:

.....

@Email(message="Attenzione email non valida")
 private String email;
// getter e setter
E poi sulla facelet definire semplicemente il campo mail così:

<h:inputText label="Email" id="email" value="#{userBean.email}" required="true"/>


Nel caso di errori nel campo mail comparirà quindi il messaggio specificato nell'annotation (di default cerca il messaggio nel file di properties).