Ejemplo Linea de ComandosEsta página recoge uno de los ejemplos de uso de las rutinas ISValidator. Puede así mismo ver los ejemplos que se incluyen en el paquete para descargar. Supongamos que queremos realizar un programa que funcione bajo la línea de comandos del Sistema Operativo para mandar emails y registrarlos en una base de datos. A este programa se le deben pasar cuatro parámetros:
Si alguna de estas restricciones no se cumpliese se deberá mostrar un mensaje por pantalla indicando todas las condiciones incumplidas. CodigoVamos a ver este ejemplo que hemos puesto en código Java utilizando ISValidator.
package com.inigoserrano.isvalidator.examples;
import java.util.Enumeration;
import java.util.Hashtable;
import com.inigoserrano.isvalidator.check.DateCheck;
import com.inigoserrano.isvalidator.check.EmailCheck;
import com.inigoserrano.isvalidator.check.RegularExpresionCheck;
import com
.inigoserrano
.isvalidator
.checkExceptions
.CommandLineDataGroupException;
import com.inigoserrano.isvalidator.data.CommandLineArgumentData;
import com.inigoserrano.isvalidator.data.Data;
import com.inigoserrano.isvalidator.dataGroup.CommandLineDataGroup;
import com.inigoserrano.isvalidator.errorDo.ErrorDo;
import com.inigoserrano.isvalidator.errorDo.ErrorDoGroup;
import com.inigoserrano.isvalidator.errorDo.ErrorDoInternalException;
import com.inigoserrano.isvalidator.errorDo.SimpleErrorDo;
import com.inigoserrano.isvalidator.errorDo.SimpleErrorDoGroup;
import com.inigoserrano.isvalidator.okDo.OkDoInternalException;
import com.inigoserrano.isvalidator.okDo.SimpleOkDo;
/**
* Example of the use of ISValidator from the commandLine
* and using DataGroups
*
* This software is copyright by Iñigo Serrano and license under the terms
* of the GPL v 2.1
*
* @version 1.0
* @author Iñigo Serrano
*/
public class ExampleCommandLineDataGroup {
/**
* to store the error messages
*/
private static Hashtable errorMessages = new Hashtable();
/**
* Default Constructor
*/
public ExampleCommandLineDataGroup() {
super();
}
/**
* To execute the example
* @param args the arguments
*/
public static void main(String[] args) {
// this can be read from a properties file, but in this example is
//in the code for simplicity
errorMessages.put(
"EmailCheck",
"The argument $argumentName; with "
+ "value \"$valueToCheck;\" is not a valid email");
errorMessages.put(
"RegularExpresionCheck",
"The argument $argumentName; with "
+ "value \"$valueToCheck;\" isn´t valid");
errorMessages.put(
"DateCheck",
"The argument $argumentName; with "
+ "value \"$valueToCheck;\" is not a valid date");
errorMessages.put(
"NotNullCheck",
"You haven´t put all the parameters");
errorMessages.put(
"NotBlankCheck",
"You have put a blank parameter");
// end of properties file
try {
//The meta container
CommandLineDataGroup inputParameters =
new CommandLineDataGroup(4, args);
//For the email
CommandLineArgumentData theEmail =
new CommandLineArgumentData(0, "email", inputParameters);
theEmail.addCheck(new EmailCheck());
theEmail.addCheck(new RegularExpresionCheck(".{1,100}"));
//For the subject
CommandLineArgumentData theSubject =
new CommandLineArgumentData(1, "subject", inputParameters);
theSubject.addCheck(new RegularExpresionCheck(".{1,255}"));
//For the Date
CommandLineArgumentData theDate =
new CommandLineArgumentData(2, "date", inputParameters);
theDate.addCheck(new DateCheck());
//For the Body
//In this parameter we use a diferente constructor,
//without the metacontainer.
//If we use the default constructor (without arguments) in the
//metacontainer this is the only way to add
//constraintContainers, because the metacontainer dosen´t know
//the arguments
CommandLineArgumentData theBody =
new CommandLineArgumentData(3, "body", args);
theBody.addCheck(new RegularExpresionCheck(".{1,1000}"));
//we have use the constructor without the metacontainer so we
//must add the constraint container to it. It is a diferent way
//to do.
inputParameters.addData(theBody);
//here we are using the metacontainer to check the data and like
//a model of it.
if (inputParameters.check()) {
//in this case the processor for the correct and incorrect is
// the same, paint it
paintData(inputParameters);
} else {
//in this case the processor for the correct and incorrect is
//the same, paint it
paintData(inputParameters);
}
} catch (CommandLineDataGroupException e) {
System.out.println(
"Error in the number of parameters, you have introduced "
+ e.getIntroducedArguments()
+ " and this program requires "
+ e.getRequiredArguments()
+ " arguments.");
System.out.println("Usage:");
System.out.println(
"java com.inigoserrano.isvalidator.examples."
+ "ExampleCommandLineDataGroup email subject date body");
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
/**
* To paint the data
* @param data ComandLineMetaContainer
* @throws ErrorDoInternalException for internal error only
* @throws OkDoInternalException for internal error only
*/
private static void paintData(CommandLineDataGroup dataGroup)
throws ErrorDoInternalException, OkDoInternalException {
//here we are using the dataGroup like a model of the data
//if the check dosen´t match then I must initialitate the
//errorDo
if (!dataGroup.match()) {
dataGroup.setErrorDo(
new SimpleErrorDo(errorMessages),
new SimpleErrorDoGroup());
}
//print the email
if (dataGroup.getData("email").match()) {
paintValidData(dataGroup.getData("email"));
} else {
paintInValidData(dataGroup.getData("email"));
}
//print the subject
if (dataGroup.getData("subject").match()) {
paintValidData(dataGroup.getData("subject"));
} else {
paintInValidData(dataGroup.getData("subject"));
}
//print the date
if (dataGroup.getData("date").match()) {
paintValidData(dataGroup.getData("date"));
} else {
paintInValidData(dataGroup.getData("date"));
}
//print the body
if (dataGroup.getData("body").match()) {
paintValidData(dataGroup.getData("body"));
} else {
paintInValidData(dataGroup.getData("dody"));
}
}
/**
* To paint the data when it is invalid
* @param data the data to paint
* @throws ErrorDoInternalException for internal error only
*/
private static void paintInValidData(Data data)
throws ErrorDoInternalException {
//here we are using the dataGroup to help us to paint the data,
//in this case when it is invalid
ErrorDoGroup errorContainer = null;
// get all the error messages
errorContainer = data.getErrorDoGroup();
Enumeration iterator = errorContainer.elements();
// and print it
while (iterator.hasMoreElements()) {
System.out.println(((ErrorDo) iterator.nextElement()).getMessage());
}
}
/**
* To paint the data when it is OK
* @param data the data to paint
*/
private static void paintValidData(Data data) {
try {
System.out.println(data.executeOkDo(new SimpleOkDo()));
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
}
DescripcionVamos a describir paso a paso el codigo. Como se podrá comprobar este es muy sistemático Lo primero wue se encuentra en el código es la definición de una Hashtable con las descripciones de los mensajes de error. El formato de esta Hashtable es poner como key el identificador de la Check, normalmente el nombre de la clase y poner como value el mensaje. Este mensaje es un String con unos parámetros que seran substituidos por los valores adecuados.
// this can be read from a properties file, but in this example is
//in the code for simplicity
errorMessages.put(
"EmailCheck",
"The argument $argumentName; with "
+ "value \"$valueToCheck;\" is not a valid email");
errorMessages.put(
"RegularExpresionCheck",
"The argument $argumentName; with "
+ "value \"$valueToCheck;\" isn´t valid");
errorMessages.put(
"DateCheck",
"The argument $argumentName; with "
+ "value \"$valueToCheck;\" is not a valid date");
errorMessages.put(
"NotNullCheck",
"You haven´t put all the parameters");
errorMessages.put(
"NotBlankCheck",
"You have put a blank parameter");
// end of properties file
Seguidamente se crea el DataGroup que contendrá los Data. En este caso se utiliza el CommandLineDataGroup, que sirve para recoger y modelar los datos provinientes de la linea de comandos, en otras situaciones se podrían utilizar otros DataGroup.
//The meta container
CommandLineDataGroup inputParameters =
new CommandLineDataGroup(4, args);
Seguidamente se crean los Data, uno por campo a validar. En este ejemplo se utiliza el CommandLineArgumentData que es el adecuado para los argumentos de la línea de comandos, aunque se podría utilizar otro, como se verá en los otros ejemplo (también se pueden crear nuevos contenedores). Al Data se le añaden los Check. Se puede comprobar que el campo email tiene dos restricciones y el resto tiene solo una. Utilizando este constructor del Data este se añade directamente al DataGroup (
//For the email
CommandLineArgumentData theEmail =
new CommandLineArgumentData(0, "email", inputParameters);
theEmail.addCheck(new EmailCheck());
theEmail.addCheck(new RegularExpresionCheck(".{1,100}"));
Con esta información ya se puede comprobar si son todos válidos. Conforme los datos sean validos o invalidos se procesaran adecuadamente. En este caso particular se llama al mismo método para que muestre la informacion.
if (inputParameters.check()) {
//in this case the processor for the correct and incorrect is
// the same, paint it
paintData(inputParameters);
} else {
//in this case the processor for the correct and incorrect is
//the same, paint it
paintData(inputParameters);
}
A la hora de pintar los datos debemos saber si hay errores o son todos validos. Si hay errores deberemos inicializar el ErrorDo. En este caso utilizaremos el SimpleErrorDo y su agrupación SimpleErrorDoGroup. comprobamos si el dato concreto es valido o no y lo procesamos.
//here we are using the dataGroup like a model of the data
if (!dataGroup.match()) {
data.setErrorDo(
new SimpleErrorDo(errorMessages),
new SimpleErrorDoGroup());
}
//print the email
if (dataGroup.getData("email").match()) {
paintValidData(data.getData("email"));
} else {
paintInValidData(dataGroup.getData("email"));
}
El método para pintar los datos invalidos obtiene del Data el errorDoGroup que contiene todos los errorDo correctamente inicializados, uno por cada Check que no cumpla. Una vez que se tiene el errorDoGroup se recorre para pintar todos los mensajes de error.
private static void paintInValidData(Data data)
throws ErrorDoInternalException {
ErrorDoGroup errorContainer = null;
// get all the error messages
errorContainer = data.getErrorDoGroup();
Enumeration iterator = errorContainer.elements();
// and print it
while (iterator.hasMoreElements()) {
System.out.println(((ErrorDo) iterator.nextElement()).getMessage());
}
}
El método para pintar los datos validos simplemente crea un OkDo y se lo asigna al Data para que devuelva el mensaje apropiado
private static void paintValidData(Data data) {
try {
System.out.println(data.executeOkDo(new SimpleOkDo()));
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
VariantesSe presentan a continuación una serie de variantes del funcionamiento de este ejemplo Lanzamiento de ExcepcionesExiste una variante general a este funcionamiento y es la de que ante el incumplimiento de una determinada restricción se lance una excepción para romper el flujo del programa. Esta modalidad es útil si ante un error no se va a realizar ningún tratamiento, y con que uno falle ya se da todo por inválido. Realmente el no indicar nada en el valor booleano de lanzar excepción, como en el ejemplo principal es lo mismo que indicar que el valor es false.
//For the email
CommandLineArgumentData theEmail =
new CommandLineArgumentData(0, "email", inputParameters, true);
theEmail.addCheck(new EmailCheck());
theEmail.addCheck(new RegularExpresionCheck(".{1,100}",false));
En este caso se indica a nivel del Data que se quiere lanzar una excepción cuando no se satisfaga una restriccion. Si se indica una opción a nivel de restricción esta tiene prevalencia sobre la del Data. En el ejemplo anterior en el caso de que no se cumpliese la segunda restricción no se lanzaría una excepción, porque explícitamente se ha dicho que no se quiere que el incumplimiento de esa restricción lance excepciones. No inclusion automatica del Data en el DataGroupOtra de las variantes que se pueden utilizar es la de que el Data no se añada directamente al DataGroup, y realizarlo manualmente. Esta situación se puede ver en el caso del Body.
//For the Body
CommandLineArgumentData theBody =
new CommandLineArgumentData(3, "body", args);
theBody.addCheck(new RegularExpresionCheck(".{1,1000}"));
inputParameters.addData(theBody);
Se observa que el constructor del Data es diferente al utilizado en los otros casos ya que no se le pasa el DataGroup, sino el Array de Strings. Tambien se puede comprobar que hay que añadir manualmente el Data al DataGroup utilizando el método |