jueves, 22 de enero de 2009

Invertir los Ejes en una Grafica de jfreechart

Bien esta semana he tenido que actualizar un par de gráficas dentro de un reporte, para esto las gráficas se generan con jfreechart que es una librería para hacer dicha tarea de manera mas fácil y obteniendo resultados muy buenos.

Las gráficas que se estaban generando tenían un pequeño detalle y es que la gráfica debería de contener los valores negativos de las y en la parte superior y no en la parte inferior que es como esta por default y es por eso que revisando ejemplos, asi como el api de jfreechart pues encontré la forma de hacerlo y se puede hacer tanto para el eje x como para el eje y.

por ejemplo tenemos la siguiente grafica con dos series de valores, uno corresponde a la funcion
y = x, y el segundo corresponde a la serie de valores y = x + 2

Bien para esto tengo el siguiente código:

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.io.File;
import java.io.*;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

public class EjemploGrafica {

public BufferedImage generaGrafica(ArrayList areo, ArrayList oseo, String title) {
System.out.println(" Generando la grafica con titulo " + title);
BufferedImage buf = null;
try {

XYSeries series = this.llenaSerie(areo,"Serie Uno");
XYSeries series2 = this.llenaSerie(oseo,"Serie Dos");

XYSeriesCollection data = new XYSeriesCollection(series);
XYSeriesCollection data2 = new XYSeriesCollection(series2);
//Se crea el objeto para generar la grafica
JFreeChart chart = ChartFactory.createXYLineChart(
title,
"",
"",
null,
PlotOrientation.VERTICAL,
false,
true,
false
);

chart.setBorderVisible(true);
chart.setBorderPaint(Color.black);
XYPlot plot = chart.getXYPlot();
pintaSerieCirculo(plot,data );
pintaSerieCirculo(plot,data2 );

/*Comentar esta linea si únicamente queremos que retorne la BufferreImage y el catch con la IOException */
ChartUtilities.saveChartAsJPEG(new File("c:\\Barchart.jpg"), chart, 500,
300);

buf = chart.createBufferedImage(500,300);
} catch (IOException e) {
e.printStackTrace();
System.err.println("Error creando grafico.");
} catch (Exception e) {
System.out.println(e.toString());
System.err.println("Error creando grafico.");
}

return buf;
}


private void pintaSerie(XYPlot plot, XYSeriesCollection data){
int index = plot.getDatasetCount();

System.out.println(" numero de data sets " + index);
plot.setDataset(index,data);
System.out.println(" numero de data sets " + index);
StandardXYItemRenderer sxyiRender = new StandardXYItemRenderer();
//sxyiRender.setPlotImages(true);
plot.setRenderer(index,sxyiRender);
}

private void pintaSerieCirculo(XYPlot plot, XYSeriesCollection data){
int index = plot.getDatasetCount();

System.out.println(" numero de data sets " + index);
plot.setDataset(index,data);
System.out.println(" numero de data sets " + index);
StandardXYItemRenderer sxyiRender = new StandardXYItemRenderer();
//sxyiRender.setPlotImages(true);
sxyiRender.setShapesFilled(true);
sxyiRender.setBaseSeriesVisible(true);
sxyiRender.setBaseShapesVisible(true);
plot.setRenderer(index,sxyiRender);

}

private XYSeries llenaSerie(ArrayList data, String title) {
BeanValoresGrafica valores = null;
XYSeries series = new XYSeries(title);
for(Object valorXy : data){
valores = (BeanValoresGrafica) valorXy;
series.add(valores.getX(), valores.getY());
}
return series;
}

public static void main(String[] args) {
BeanValoresGrafica b = null;
ArrayList a = new ArrayList();
for(int i = -5 ; i < b =" new" ab =" new" i =" -2" b =" new">

Ahora yo necesito que mi gráfica quede asi :
Como observan los valores negativos de y se encuentran en la parte superior y no en la inferior para invertirlos realizaremos lo siguiente (incluir esta parte de codigo despues de obtener el objeto XYPlot y las llamadas del metodo pintaSerieCirculo)

.
.
pintaSerieCirculo(plot,data2 );
plot.setDomainAxisLocation(AxisLocation.TOP_OR_LEFT);
NumberAxis domainAxis = (NumberAxis) plot.getDomainAxis();
//*Invierte los valores del eje x */
// domainAxis.setInverted(true);
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
//*Aqui es donde se invirte el eje y*/
rangeAxis.setInverted(true);
ChartUtilities.saveChartAsJPEG(new File("c:\\Barchart.jpg"), chart, 500,
300);



El metodo que genera la grafica nos retorna un objeto de tipo java.awt.image.BufferedImage este objeto podemos utilizarlo par mostrarlo en una aplicación swing o en un reporte de jasperreport o guardar la imagen en jpg y adjuntarla en algún informe, etc.

Bien pues es lo que yo necesitaba y espero que les sirva

La grafica final :

Como observan es lo mismo que lo anterior solo que se colocaron las etiquetas del eje x en la parte superior para eso tenemos el siguiente código:

AxisLocation axloc = plot.getDomainAxisLocation();
plot.setDomainAxisLocation(AxisLocation.TOP_OR_LEFT);


Bueno eso es todo, ha se me olvidaba que yo utilizo un bean para pasar valores le coloco el bean que no es la gran cosa pero es parte del codigo

import java.io.Serializable;

public class BeanValoresGrafica implements Serializable {


public BeanValoresGrafica() {
}

private double x;
private double y;

public double getX(){
return x;
}

public double getY(){
return y;
}

public double setX(double x){
return this.x = x;
}

public double setY(double y){
return this.y = y;
}

}

martes, 13 de enero de 2009

Acceder a un Ftp con jakarta commons-net

El proyecto jakarta commons-net nos proporciona implementaciones protocolos de Internet en java para poder utilizarlos en el lado del cliente. Los protocolos que soporta son los siguientes:
  • FTP/FTPS
  • NNTP
  • SMTP
  • POP3
  • Telnet
  • TFTP
  • Finger
  • Whois
  • rexec/rcmd/rlogin
  • Time (rdate) and Daytime
  • Echo
  • Discard
  • NTP/SNTP

En este ejemplo veremos como acceder a un ftp con esta libreria

Para usarlo tenemos que descargar los siguientes jar de la pagina oficial:

- commons-net-1.4.1.jar
- jakarta-oro-2.0.8.jar


El primer jar nos proporciona las clases que implementan los protocolos antes mencionados y en el segundo jar contiene algunas clases para evaluar expresiones. El primero usa clases del segundo por lo cual necesitamos agregar ambos a nuestro classpath.

Aquí tenemos el ejemplo :

import java.io.IOException;
import java.net.SocketException;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;

public class Main {
public static void main(String[] args) {
FTPClient f = new FTPClient();
try {
FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX); //Este objeto nos
f.configure(conf); //permite configurar opciones de conexion como idioma y sistema de archivos
f.connect("127.0.0.1"); // ip del servidor ftp
f.login("usuario", "usuario"); // usuario y password para conectarnos al ftp
f.changeWorkingDirectory("diruno"); // Cambiamos de la raiz al subdirectorio uno
System.out.println(" Crea directorio ? "+f.mkd("dirprueba")); //crea un directorio en diruno
FTPFile[] files = f.listFiles(); // Obtiene los archivos del servidor y los mostramos
System.out.println(f.isConnected());
for (FTPFile arch : files){
System.out.println(arch.toString());
}
f.disconnect();
System.out.println(f.isConnected());
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

Les dejo el link de la pagina oficial http://commons.apache.org/net/


Upate: Les dejo un ejemplo mas, es como el anterior pero almacena un arcivo de la maquina local en el ftp



public class Main {

 public static void main(String[] args) {
  FTPClient f = new FTPClient();
  try {
  FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX); //Este objeto nos
  f.configure(conf); //permite configurar opciones de conexion como idioma y sistema de archivos
  f.connect("127.0.0.1"); // ip del servidor ftp
  f.login("usuario", "usuario"); // usuario y password para conectarnos al ftp
  System.out.println(f.isConnected());
  f.changeWorkingDirectory("diruno"); // Cambiamos de la raiz al subdirectorio uno
  System.out.println(" Crea directorio ? "+f.mkd("dirprueba")); //crea un directorio en diruno
 
  FileInputStream fis = new FileInputStream("archivo.doc"); //Se abre un archivo de nuestra maquina local
  f.setFileType(f.BINARY_FILE_TYPE); //Se pone tipo binario para poder enviar archivos de cualquier tipo
  boolean res = ftpClient.storeFile("/diruno/dirprueba", fis ); //Con esta instruccion se sube el archivo al ftp
  System.out.println("Resultado de subir el archivo es " + res);
 
  FTPFile[] files = f.listFiles(); // Obtiene los archivos del servidor y los mostramos
  for (FTPFile arch : files){
  System.out.println(arch.toString());
  }
 
 
  f.disconnect();
  System.out.println(f.isConnected());
  } catch (IOException ex) {
  ex.printStackTrace();
  }
 }
}

jueves, 8 de enero de 2009

Usar el protocolo samba con jCIFS

En el proyecto donde estoy colaborando hay una aplicación que necesita escribir archivos en un directorio compartido en un servidor windows por lo que necesitamos usar el protocolo CIFS/SMB, bien para esto tenemos la librería jCIFS que es una implementación de dicho protocolo y esta hecha en java completamente además de que es opensource.

También es posible usar esta librería para compartir recursos entre maquinas windows y máquinas unix que cuenten con el servicio samba.

Por ejemplo en este metodo escribimos un archivo en la carpeta compartida por otra maquina:

private boolean escribeArchivo(String encodedMessage, String nombreArchivo)
throws SmbException, MalformedURLException, UnknownHostException, IOException{

boolean exitoArchivo = false;

//String url = "smb://127.0.0.1/compartida/"+ nombreArchivo ;
//String url = "smb://usuario:usuario@127.0.0.1/compartida/"+ nombreArchivo ;
String url = "smb://"+ USR_SERVIDOR +":"+ PASS_SERVIDOR +"@"
+ URL_SERVIDOR + nombreArchivo + EXT_ARCHIVO;

try{
SmbFileOutputStream out = new SmbFileOutputStream(url, false);

out.write(encodedMessage.getBytes());
// encodeMessage es el texto que contiene el archivo
// aqui podemos enviar los bytes de algun archivo de la maquina local

out.close();

exitoArchivo = true;

System.out.println("generado " + url );
} catch(IOException ex){
exitoArchivo = false;
} finally{
return exitoArchivo;
}
}


Para borrar un archivo en la carpeta compartida:

private void borraArchivo(String archivo) throws SmbException,
MalformedURLException, UnknownHostException{

//String url = "smb://127.0.0.1/compartida/"+ nombreArchivo ;
//String url = "smb://usuario:usuario@127.0.0.1/compartida/"+ nombreArchivo ;
String url = "smb://"+ USR_SERVIDOR +":"+ PASS_SERVIDOR +"@"+ URL_SERVIDOR ;
String rutArchivo = url + archivo;
SmbFile sFile = new SmbFile(rutArchivo);
if(sFile.exists())
sFile.delete();
}



Para descargar la libreria y un poco de mas informacion pues sigan este link
http://jcifs.samba.org/