Posts
Parsear XML con java
De esto se pueden encontrar miles de ejemplos por la red. En mi caso tenía hecho alguno, el problema es que el código era del año 2001. Y sigue funcionando pero tirando de un fichero jar que contiene unas librerías que vete a saber tú. El caso es que he tratado de hacer un ejemplo de esto con material más actualizado tal y como se cuenta en la web oficial de oracle-java (quién lo diría en el 2001). Bueno, al lío:
Este sería el fichero XML:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE PROPERTIES SYSTEM "properties.dtd">
<PROPERTIES>
<PROPERTY NAME="system_version" >1.0.01 </PROPERTY>
<PROPERTY NAME="loglevel" >1</PROPERTY>
<PROPERTY NAME="logfile" >Data/log/output.log</PROPERTY>
<PROPERTY NAME="multiuser_y_n" >y</PROPERTY>
<PROPERTY NAME="server_y_n" >y</PROPERTY>
<PROPERTY NAME="language" >en</PROPERTY>
<PROPERTY NAME="db_type" >sql</PROPERTY>
<PROPERTY NAME="jdbc_driver" >sun.jdbc.odbc.JdbcOdbcDriver</PROPERTY>
<PROPERTY NAME="jdbc_url" >jdbc:odbc:pruebas</PROPERTY>
<PROPERTY NAME="jdbc_user" ></PROPERTY>
<PROPERTY NAME="jdbc_password" ></PROPERTY>
<PROPERTY NAME="init.d" >Data/etc/init.d</PROPERTY>
</PROPERTIES>
Y como se puede ver debe seguir los dictados de un fichero DTD, que en este caso es muy sencillo y es este:
<?xml version="1.0" encoding="UTF-8"?>
<!-- P. Al. -->
<!-- Generic properties file-->
<!ELEMENT PROPERTIES (PROPERTY*)>
<!ELEMENT PROPERTY (#PCDATA)>
<!ATTLIST PROPERTY
NAME CDATA #REQUIRED
>
Como ya sabrás a estas alturas de siglo existen dos formas básicas de leer un fichero XML desde un programa: una es cargando todo el fichero de golpe.
En este caso he hecho un parser de SAX usando las librerías más simples y menos exóticas posible. Ojo!! para que valida el tema del uso del DTD hay que meter los métodos de error (error, fatalError, warning), porque si no es así no nos empanaremos.
Mock Objects con Mockito
mockito es un framework para trabajar con objetos mock, es decir objetos falsos o simulados. Mockito trata de ser más simple de usar que otras librerías predecesoras como jmock o easymock.
¿Para qué necesitamos objetos simulados? por muchos motivos cuando queremos hacer pruebas unitarias de nuestras clases puede que dependamos de otras clases que tengan alguna pega:
- Son lentas (jdbc, redes, ...)
- No devuelven un resultado concreto
- No se tienen a mano o dependen de algo externo.
- Sencillamente aún no están creadas
En fin, el caso es que puede que haya objetos que necesitemos simularlos a la hora de poder hacer test unitarios de nuestras clases.
Vamos a ver un par de ejemplos en los que se crea una instancia de la clase List falsa y otro ejemplo en el que creamos un BufferedReader de palo.
Mocked List
import static org.mockito.Mockito.*;
import java.util.List;
/**
* @author Pello Altadill
* @greetz ñañañaa MOOOOOOOOOCK (vuvuzela)
*/
public class MockList {
/**
* @param args
*/
public static void main(String[] args) {
// We create a mock list using List interface
// So, this is a false or mocked list
List mockedList = mock(List.class);
// We add something to the list
mockedList.add("Example");
mockedList.add("Another example");
// This will return null
System.out.println("Is anything there?: " + mockedList.get(0));
// Now we establish: when we call get(0) on out list we
// want to return "Pain in the ass"
// This is Stubbing
when(mockedList.get(0)).thenReturn("Pain in the ass");
// We verify that we have stubbed this invocation
// nothing will happen in this case.
verify(mockedList).add("Example");
// Now, this will return: "Pain in the ass"
System.out.println("Let's see: " + mockedList.get(0));
// And this one will return null
System.out.println("And what about this: " + mockedList.get(1));
// This will throw an Exception because add("Another Exception")
// invocation is not stubbed
verify(mockedList).add("Another Example");
}
}
Mocked BufferedReader
import static org.mockito.Mockito.*;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* We mock a BufferedReader using mockito
* @author Pello Xabier Altadill Izura
* @greetz UuuuuuoooAaaaaUUUaa
*/
public class MockFile {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// We create an instance of a false or mocked BufferedReader
BufferedReader mockBufferedReader = mock(BufferedReader.class);
// Then we stub readLine() function. It will return "747:John:Doe"
when(mockBufferedReader.readLine()).thenReturn("747:John:Doe");
// We establish that when mocked reader calls close an exception
// will be thrown
doThrow(new IOException()).when(mockBufferedReader).close();
// Let's try
System.out.println("First line: " + mockBufferedReader.readLine());
// Now we close...
mockBufferedReader.close();
BufferedReader anotherMockReader;
}
}
Las aplicaciones que gestionan datos de cualquier tipo necesitan acceder a repositorios de datos persistentes como las BBDD. Los datos no siempre tienen por qué estar en una BD relacional a la que se accede por JDBC, es más, puede que la BD cambie o que incluso hay otro tipo de orígenes de datos como un LDAP. Con el objeto de separar la lógica de negocio con los detalles de acceso a los datos es habitual aplicar este patrón.
Todas las operaciones se hacen a través de una clase DAO que implementa todas las operaciones necesarias para gestionar determinados datos (CRUD + lo que haga falta). Esa clase DAO conoce los detalles del origen de los datos e incluso utiliza otra clase para gestionar el acceso a los mismos.
Para intercambiar información entre el DAO y la aplicación se utilizan objetos que representan los datos que se sacan del origen de datos, comúnmente suelen ser clases que representan una tabla de una BBDD.
Este es un ejemplo con una BBDD llamada ERP que contiene una tabla llamada Customer.
Aplicando el patrón utilizaremos las siguientes clases:
- Customer: representa los datos de la tabla y se utiliza para intercambiar información entre el programa y la clase DAO.
- CustomerDAO: se encarga de todas las operaciones CRUD.
- DataSource: se encarga de conseguir la conexión con el origen de datos.
- Main: el programa que hace uso del CustomerDAO para interactuar con los datos persistentes.
Customer
/**
* POJO class for Customer
* @author Pello Altadill
*
*/
public class Customer {
private int id;
private String name;
private String address;
/**
* @param id
* @param name
* @param address
*/
public Customer(int id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Customer [id=" + id + ", name=" + name + ", address=" + address
+ "]";
}
/********** Getters/Setters ********************/
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
CustomerDAO
DataSource
Main
import java.util.Scanner;
LaOca - Goose Game
Main
JDBC en java
Este es un churro resumen de las cuatro cosas básicas que se hacen con el JDBC, en concreto:
-Las operaciones CRUD (en jdbc el select de una forma el resto de otra)
-El tema de las PreparedStatement, que es la forma correcta de hacer las cosas.
-El tema de sacar el último campo clave generado. En el caso de autonuméricos nos interesa saberlo en muchas ocasiones y la cosa tiene su aquel en java.
JavaHammer
JavaHammer es una versión simplificada del juego BattleMasters de MB. El BattleMasters era una versión simplificada de Warhammer en la que dos ejércitos se enfre ellos hasta la aniquilación de uno de los dos.
Repositorio subversion con el código.
Cada ejercito está formado por distintas unidades. Cada unidad tiene un nombre, un valor de ataque, un valor de defensa, un valor de movimiento que suele ser 1, un rango de ataque que suele ser 1 y los puntos de vida que suelen ser tres.
Hay varias clases de unidades: infantería, arqueros y caballería.
El escenario es un mapa de 10x10 terrenos. En cada terreno solo cabe una unidad de un ejercito cada vez y tienen que tener un nombre ominoso tipo "llanura del mal innominado"
En el juego debe haber un inicio en el que se genera el mapa de forma aleatoria.
El programa está lleno de CodeSmells debe mejorarse un montón, aunque en todo momento se ha intentado desacoplar, cohersionar, etc...
Este es el aspecto de JavaHammer en consola.
Palíndromo
El clásico ejemplo de palíndromo, en este caso para probar la palabra Shared en los métodos de una clase, que en definitiv equivale al static de java.
Se usa el palíndromo para String y para Enteros.
Banner es el clásico programa de unix para sacar por consola un texto en tamaño grande. Había planteado esto y me mandaron una soluciones efectivas pero algo choriceras. Yo planteo esta. Lo hago pensando orientado a objetos, por tanto divido el problema en cosas, no en funciones. Las cosas que salen son: caracteres, pantalla, y alguien que escribe. En java me quedarían 4 clases, una añadida para hacer el main.
Letter
Este es un hashtable que contiene las letras en un hashtable. No he metido todas, porque al igual que a Carlos esto es algo denigrante.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.cuatrovientos.banner;
import java.util.Hashtable;
/**
* Letters
* singleton hashtable that holds all letters
* @author Pello Xabier
* note: from now on I'll not forget the private constructor, I swear ;)
*/
public class Letters extends Hashtable<String, String[][]>{
private static Letters letters = null;
private static final int LETTER_WIDTH = 4;
private static final int LETTER_HEIGHT = 5;
/**
* private constructor
*/
private Letters () {
initialize();
}
/**
* getLetters
* @return
*/
public static Letters getLetters () {
if (letters == null) {
letters = new Letters();
}
return letters;
}
/**
* initialize
* puts letters into the hashtable
* Note: I'll NOT put all letters, It's too late for this,
* and I know that this font is horrid, but gimme a break.
*/
private void initialize () {
this.put("A",new String[][]{{"A","A","A","A"},
{"A"," "," ","A"},
{"A","A","A","A"},
{"A"," "," ","A"},
{"A"," "," ","A"}});
this.put("B",new String[][]{{"B","B","B","B"},
{"B"," "," ","B"},
{"B","B","B"," "},
{"B"," "," ","B"},
{"B","B","B","B"}});
this.put("C",new String[][]{{"C","C","C","C"},
{"C"," "," "," "},
{"C"," "," "," "},
{"C"," "," "," "},
{"C","C","C","C"}});
this.put("D",new String[][]{{"D","D","D"," "},
{"D"," "," ","D"},
{"D"," "," ","D"},
{"D"," "," ","D"},
{"D","D","D"," "}});
this.put("E",new String[][]{{"E","E","E","E"},
{"E"," "," "," "},
{"E","E","E"," "},
{"E"," "," "," "},
{"E","E","E","E"}});
}
/**
* getHeight
* @return hegith of letters
*/
public int getHeight () {
return LETTER_HEIGHT;
}
/**
* getWidth
* @return width of letters
*/
public int getWidth () {
return LETTER_WIDTH;
}
}
Screen
Representa la pantalla, es una especie de lienzo en forma de array de Strings. La función fill es la que nos permite pintar un caracter en unas coordenadas. Y finalmente la función draw vuelca todo el lienzo en pantalla.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.cuatrovientos.banner;
/**
* Screen
* The class where we paint the Letters
* @author Pello Xabier
* note: from now on I'll not forget the private constructor, I swear ;)
*/
public class Screen {
private final static int WIDTH = 80;
private final static int HEIGHT = 24;
private final static String WHITESPACE = " ";
private final static char NEWLINE = '\n';
private String[][] canvas = new String[HEIGHT][WIDTH];
private static Screen theScreen = null;
// private constructor
private Screen () { clear(); }
/**
* clears the screen
*/
private void clear () {
for (int h = 0;h< HEIGHT; h++)
for (int w=0;w<WIDTH; w++)
canvas[h][w] = WHITESPACE;
}
/**
* getScreen
* @return the one and only screen instance
*/
public static Screen getScreen() {
if (theScreen == null) {
theScreen = new Screen();
}
return theScreen;
}
/**
* fill
* fills the screen with a matrix at given coords
* @param what
* @param x
* @param y
*/
public void fill (String[][] what, int x, int y) {
if (boundsOk(x,y)) {
int i = 0, j = 0;
//go on and fill the canvas
for (int h = y;h< y+what.length; h++) {
for (int w=x;w<x+what[0].length; w++)
canvas[h][w] = what[i][j++];
i++;j=0;
}//for
}//if
}
/**
* draw
* paints contents on console
*/
public void draw () {
for (int h = 0;h< HEIGHT; h++) {
for (int w=0;w<WIDTH; w++)
System.out.print(canvas[h][w]);
System.out.print(NEWLINE);
}
}
/**
* boundsOk
* tell us if given coords are inside Screen margins
* @param x
* @param y
* @return true if coords are ok.
*/
public boolean boundsOk (int x, int y) {
return (y >= 0 && y < HEIGHT && x >= 0 && x < WIDTH);
}
}
Writer
Usando la pantalla va escribiendo caracteres y avanzando el cursor.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.cuatrovientos.banner;
/**
* Writer
* Gets the Screen and writes a word on It.
* @author Pello Xabier
*/
public class Writer {
private int initialX;
private int initialY;
/**
* Writer
* constructor
* initializes positions at 0
*/
public Writer () {
initialX = 0;
initialY = 0;
}
/**
* Writer
* constructor
* initializes positions at x,y
*/
public Writer (int x , int y) {
if (Screen.getScreen().boundsOk(x, y)) {
initialX = x;
initialY = y;
} else { // bajeril stylo
initialX = initialY = 0;
}
}
/**
* writes the string
* @param messageToWrite
*/
public void write (String messageToWrite) {
int x = initialX;
int y = initialY;
if (messageDoesNotFitScreen(messageToWrite)) {
System.out.println("Sorry. Message does not fit the screen");
return;
}
// It's ok, we took each letter, we write on the screen and we move the cursor forward
for (int i = 0; i< messageToWrite.length();i++) {
// TODO next line: choose btw coolness and refactoring
Screen.getScreen().fill(Letters.getLetters().get(messageToWrite.substring(i, i+1).toUpperCase()), x, y);
x = x + Letters.getLetters().getWidth() + 1;
}
// Finally, we draw the screen
Screen.getScreen().draw();
}
/**
* messageDoesNotFitScreen
* @param message
* @return true if message is longer than screen width
*/
private boolean messageDoesNotFitScreen (String message) {
return (((message.length()+1) * Letters.getLetters().getWidth()) > 80);
}
}
Main
Instancia writer y escribe, no más.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.cuatrovientos.banner;
/**
*
* @author pello xabier
* @greetz 1º DAM @cuatrovientos
*/
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Writer writer = new Writer(5,7);
writer.write("ABC");
}
}
Guste o no Visual Basic da de comer y no se puede relegar. Es inevitable
Este el el clásico ejemplo de Visual Basic, un programa para resolver una ecuación de 2º grado. Está hecho con un par de clases, una se ocupa de la ecuación y la otra del interfaz de usuario.
Clase Ecuación
Esta sería la clase que representa la ecuación, y tiene unos métodos para comprobar si tiene solución y luego para resolver la ecuación.
subscribe via RSS