/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package practica1.manejoExperimento;
import beancomentarios.Comentario;
import beancomentarios.ModeloComentarios;
import es.miguelgonzalez.jgraficacomida.GraficaComidaIncorrectValueException;
import es.miguelgonzalez.jgraficacomida.ModeloGraficaComida;
import java.io.*;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import practica1.Practica1;
import practica1.language.Language;
import practica1.logic.LogicExperimento;
import practica1.logic.LogicPoblacion;
import practica1.ui.tablaPoblacion.ModeloPoblacionTabla;
/**
* Clase que permite manejar un experimento en disco duro
* @author Miguel González - Ceura
*/
public class ManejoExperimento {
private static Document xmlDoc = null;
private static Element elementoCabecera = null;
/**
* Método estático que permite abrir un experimento del disco duro
* @param fichExperimento Fichero del experimento a abrir
* @return LogicExperimento
* @throws ExperimentoInvalidoException Lanza un error si no se pudo abrir
* el experimento por tener un formato inválido
*/
public static LogicExperimento abrirExperimento(File fichExperimento)
throws ExperimentoInvalidoException {
String nombreExperimento = "";
String tipoBacteria = "";
String nombreInvestigador = "";
String proyectoInvestigacion = "";
//Construimos el DOM con las preferencias
DocumentBuilderFactory dbFactory;
DocumentBuilder docBuilder;
LogicExperimento experimento = null;
try
{
dbFactory = DocumentBuilderFactory.newInstance();
docBuilder = dbFactory.newDocumentBuilder();
if(fichExperimento.exists()) {
xmlDoc = docBuilder.parse(fichExperimento);
elementoCabecera = xmlDoc.getDocumentElement();
} else {
Practica1.log.error("Abrir, no existe el experimento");
throw new ExperimentoInvalidoException(
Language.getI().getP("NO_EXISTE_EXPERIMENTO"));
}
//Buscamos las propiedades del experimento
NodeList lstPropiedades = elementoCabecera.
getElementsByTagName("propiedades-experimento");
boolean propiedadesCorrecto = false;
if(lstPropiedades.getLength() == 1) {
Node nodePropiedades = lstPropiedades.item(0);
//Obtenemos las propiedades del experimento
NodeList lstValores = nodePropiedades.getChildNodes();
//Recorremos las propiedades
for(int i=0; i<lstValores.getLength(); i++) {
Node nodoPropExp = lstValores.item(i);
if(nodoPropExp.getNodeType() == Node.ELEMENT_NODE) {
String nProp = nodoPropExp.getNodeName();
//Comprobamos en orden que se cumplen las propiedades esperadas
switch(i) {
case 1: //Nombre experimento
if(nProp.equals("nombre-experimento")) {
nombreExperimento = nodoPropExp.
getTextContent();
} else {
Practica1.log.error("Abrir, nombre experimento inválido");
throw new ExperimentoInvalidoException(
Language.getI().getP("FICHERO_INVALIDO"));
}
break;
case 3:
if(nProp.equals("tipo-bacteria")) {
tipoBacteria = nodoPropExp.
getTextContent();
} else {
Practica1.log.error("Abrir, tipo bacteria inválido");
throw new ExperimentoInvalidoException(
Language.getI().getP("FICHERO_INVALIDO"));
}
break;
case 5:
if(nProp.equals("nombre-investigador")) {
nombreInvestigador = nodoPropExp.
getTextContent();
} else {
Practica1.log.error("Abrir, nombre investigador inválido");
throw new ExperimentoInvalidoException(
Language.getI().getP("FICHERO_INVALIDO"));
}
break;
case 7:
if(nProp.equals("proyecto-investigacion")) {
proyectoInvestigacion = nodoPropExp.
getTextContent();
propiedadesCorrecto = true;
} else {
Practica1.log.error("Abrir, proyecto investigación inválido");
throw new ExperimentoInvalidoException(
Language.getI().getP("FICHERO_INVALIDO"));
}
break;
}
}
}
} else {
Practica1.log.error("Abrir, fichero inválido");
throw new ExperimentoInvalidoException(
Language.getI().getP("FICHERO_INVALIDO"));
}
if(!propiedadesCorrecto) {
throw new ExperimentoInvalidoException(
Language.getI().getP("FICHERO_INVALIDO"));
}
//Creamos el modelo del experimento
experimento = new LogicExperimento(fichExperimento,
nombreExperimento, tipoBacteria, nombreInvestigador,
proyectoInvestigacion);
//Buscamos las poblaciones del experimento
NodeList lstPoblaciones = elementoCabecera.
getElementsByTagName("poblacion");
//Recorremos las poblaciones y las analizamos
for(int i=0; i<lstPoblaciones.getLength(); i++) {
if(lstPoblaciones.item(i).getNodeType() == Node.ELEMENT_NODE) {
cargarPoblacion(experimento, lstPoblaciones.item(i));
}
}
}
catch (Exception ex)
{
Practica1.log.error(Language.getI().getP("ERROR"), ex);
throw new ExperimentoInvalidoException(ex);
}
xmlDoc = null;
elementoCabecera= null;
experimento.setModified(false);
return experimento;
}
/**
* Carga los datos del XML de la población a un LogicPoblacion
* @param exp LogicExperimento que contendrá la población
* @param nPoblacion Nodo XML de la población
* @throws ExperimentoInvalidoException Lanza un error si el experimento
* es inváldio
*/
private static void cargarPoblacion(LogicExperimento exp, Node nPoblacion)
throws ExperimentoInvalidoException {
String nombre = "";
int tamanio = 0;
int temperatura = 0;
String escala = "";
String fecha = "";
String luminosidad = "";
boolean sincronizar = true;
ModeloGraficaComida modeloGraficaComida = null;
ModeloPoblacionTabla modeloPoblacionTabla = null;
ModeloComentarios modeloComentarios = null;
//Obtenemos las propiedades de la población
NodeList lstValores = nPoblacion.getChildNodes();
String[] propPoblacion = new String[]{"nombre", "tamaño", "temperatura",
"escala-temperatura", "fecha", "luminosidad", "sincronizar",
"alimentacion", "tabla-datos", "comentarios"};
boolean xmlValido = true;
if(lstValores.getLength() >= 17) {
for(int i=1; i<=17; i+= 2) {
if(!lstValores.item(i).getNodeName().equals(propPoblacion[(int)i/2])) {
xmlValido = false;
}
}
}
if(xmlValido) {
nombre = lstValores.item(1).getTextContent();
tamanio = Integer.parseInt(lstValores.item(3).getTextContent());
temperatura = Integer.parseInt(lstValores.item(5).getTextContent());
escala = lstValores.item(7).getTextContent();
fecha = lstValores.item(9).getTextContent();
luminosidad = lstValores.item(11).getTextContent();
sincronizar = lstValores.item(13).getTextContent().equals("si");
modeloGraficaComida = cargarAlimentacion(lstValores.item(15));
modeloPoblacionTabla = cargarTablaDatos(lstValores.item(17));
modeloComentarios = cargarComentarios(lstValores.item(19));
} else {
Practica1.log.error("Abrir, error cargar población");
throw new ExperimentoInvalidoException(
Language.getI().getP("FICHERO_INVALIDO"));
}
//Creamos un modelo de población genérico
LogicPoblacion modPoblacion = new LogicPoblacion("PobGenerica", exp);
//Cargamos los datos
modPoblacion.setNombrePoblacion(nombre);
modPoblacion.setTamanioPoblacion(tamanio);
modPoblacion.setTemperatura(temperatura);
modPoblacion.setEscalaTemperatura(escala);
modPoblacion.setFecha(fecha);
modPoblacion.setLuminosidad(luminosidad);
modPoblacion.setSincronizarComida(sincronizar);
modPoblacion.setModeloGraficaComida(modeloGraficaComida);
modPoblacion.setModeloPoblacionTabla(modeloPoblacionTabla);
modPoblacion.setModeloComentarios(modeloComentarios);
modPoblacion.setModified(false);
//Añadimos el modelo de la población al experimento
exp.addPoblacion(modPoblacion);
}
/**
* Carga el modelo de los comentarios de la población
* @param nCom Nodo de los comentarios
* @return ModeloComentarios de la población
* @throws ExperimentoInvalidoException Lanza un error si el experimento
* es inválido
*/
private static ModeloComentarios cargarComentarios(Node nCom)
throws ExperimentoInvalidoException {
ModeloComentarios modeloComentarios = new ModeloComentarios();
//Obtenemos los comentarios
NodeList lstComentarios = nCom.getChildNodes();
for(int i=1; i<lstComentarios.getLength(); i = i + 2) {
NodeList nComentario = lstComentarios.item(i).getChildNodes();
String[] datosComentario = new String[]{"fecha", "texto"};
boolean xmlValido = true;
if(nComentario.getLength() >= 7) {
for(int j=1; j<=3; j += 2) {
if(!nComentario.item(j).getNodeName().
equals(datosComentario[(int)j/2])) {
xmlValido = false;
}
}
}
if(xmlValido) {
String fecha = nComentario.item(1).getTextContent();
String texto = nComentario.item(3).getTextContent();
modeloComentarios.addComentario(new Comentario(texto, fecha));
} else {
Practica1.log.error("Abrir, error cargar comentarios");
throw new ExperimentoInvalidoException(
Language.getI().getP("FICHERO_INVALIDO"));
}
}
return modeloComentarios;
}
/**
* Carga el modelo de la gÅ•afica de la población
* @param nAlim Nodo XML de la alimentación de la gráfica
* @return ModeloGraficaComida de la población
* @throws ExperimentoInvalidoException Lanza un error si el experimento es
* inválido
*/
private static ModeloGraficaComida cargarAlimentacion(Node nAlim)
throws ExperimentoInvalidoException {
int aliI = 150;
int aliM = 150;
int dia = 15;
int aliF = 150;
//Obtenemos las propiedades de la alimentación
NodeList lstValores = nAlim.getChildNodes();
String[] datosModeloComida = new String[]{"alimentacion-inicial",
"alimentacion-maxima", "alimentacion-dia", "alimentacion-final"};
boolean xmlValido = true;
if(lstValores.getLength() >= 7) {
for(int i=1; i<=7; i += 2) {
if(!lstValores.item(i).getNodeName().
equals(datosModeloComida[(int)i/2])) {
xmlValido = false;
}
}
}
if(xmlValido) {
aliI = Integer.parseInt(lstValores.item(1).getTextContent());
aliM = Integer.parseInt(lstValores.item(3).getTextContent());
dia = Integer.parseInt(lstValores.item(5).getTextContent());
aliF = Integer.parseInt(lstValores.item(7).getTextContent());
} else {
Practica1.log.error("Abrir, error cargar alimentación");
throw new ExperimentoInvalidoException(
Language.getI().getP("FICHERO_INVALIDO"));
}
ModeloGraficaComida modeloGraficaComida = null;
try {
modeloGraficaComida = new ModeloGraficaComida(aliI, dia, aliM, aliF);
} catch (GraficaComidaIncorrectValueException ex) {
throw new ExperimentoInvalidoException(ex);
}
return modeloGraficaComida;
}
/**
* Carga del modelo de la tabla de la población
* @param nDat Nodo de los datos de la tabla
* @return ModeloPoblacionTabla de la población
* @throws ExperimentoInvalidoException Lanza un error si el experimento
* es inválido
*/
private static ModeloPoblacionTabla cargarTablaDatos(Node nDat)
throws ExperimentoInvalidoException {
//Obtenemos las filas de datos
NodeList lstValores = nDat.getChildNodes();
String [][] datos = new String[30][];
String []cabeceras = new String[]{
Language.getI().getP("DIA"),
Language.getI().getP("TAMANIO_POBLACION"),
Language.getI().getP("BACTERIAS_MUERTAS"),
Language.getI().getP("TEMPERATURA"),
Language.getI().getP("DOSIS_COMIDA")};
if(lstValores.getLength() != 0) {
//Recorremos las filas
int contDias = 0;
for(int i=0; i<lstValores.getLength(); i++) {
Node nodoDiaTabla = lstValores.item(i);
if(nodoDiaTabla.getNodeType() == Node.ELEMENT_NODE) {
String nProp = nodoDiaTabla.getNodeName();
//Si está el día en orden correcto
if(nProp.equals("datos-dia-" + (contDias + 1))) {
datos[contDias] = cargarTablaDia(contDias + 1, nodoDiaTabla);
contDias++;
} else {
Practica1.log.error("Abrir, errror cargar tabla datos");
throw new ExperimentoInvalidoException(
Language.getI().getP("FICHERO_INVALIDO"));
}
}
}
} else {
throw new ExperimentoInvalidoException(
Language.getI().getP("FICHERO_INVALIDO"));
}
return new ModeloPoblacionTabla(datos, cabeceras);
}
/**
* Carga una fila de la tabla
* @param dia Número del día
* @param nDia Nodo del día
* @return String[] Datos de la fila
* @throws ExperimentoInvalidoException Lanza un error si el experimento
* es inválido
*/
private static String[] cargarTablaDia(int dia, Node nDia)
throws ExperimentoInvalidoException {
//Obtenemos las propiedades del día
NodeList lstValores = nDia.getChildNodes();
String tamanio = "";
String bacterias = "";
String temperatura = "";
String comida = "";
String[] datosTabla = new String[]{"tamaño-poblacion", "bacterias-muertas",
"temperatura", "cantidad-comida"};
boolean xmlValido = true;
if(lstValores.getLength() >= 7) {
for(int i=1; i<=7; i += 2) {
if(!lstValores.item(i).getNodeName().equals(datosTabla[(int)i/2])) {
xmlValido = false;
}
}
}
if(xmlValido) {
tamanio = lstValores.item(1).getTextContent();
bacterias = lstValores.item(3).getTextContent();
temperatura = lstValores.item(5).getTextContent();
comida = lstValores.item(7).getTextContent();
} else {
Practica1.log.error("Abrir, error cargar tabla día");
throw new ExperimentoInvalidoException(
Language.getI().getP("FICHERO_INVALIDO"));
}
return new String[]{Integer.toString(dia),
tamanio, bacterias, temperatura, comida};
}
/**
* Clase estática que permite guardar un experimento en memoria
* @param experimento LogicExperimento a guardar
* @throws ExperimentoInvalidoException Si hay un problema al guardar el
* experimento se provoca el error
*/
public static void guardarExperimento(LogicExperimento experimento)
throws ExperimentoInvalidoException {
//Construimos el DOM con las preferencias
DocumentBuilderFactory dbFactory;
DocumentBuilder docBuilder;
try
{
dbFactory = DocumentBuilderFactory.newInstance();
docBuilder = dbFactory.newDocumentBuilder();
xmlDoc = docBuilder.newDocument();
//Creamos el elemento que solo contendrá la cabecera
elementoCabecera = xmlDoc.createElement("experimento");
xmlDoc.appendChild(elementoCabecera);
//Agregamos las propiedades del experimento
Element propiedades = xmlDoc.createElement("propiedades-experimento");
elementoCabecera.appendChild(propiedades);
Element nombreExp = xmlDoc.createElement("nombre-experimento");
nombreExp.setTextContent(experimento.getNombreExperimento());
propiedades.appendChild(nombreExp);
Element tipoBacteria = xmlDoc.createElement("tipo-bacteria");
tipoBacteria.setTextContent(experimento.getTipoBacteria());
propiedades.appendChild(tipoBacteria);
Element nombreInvestigador = xmlDoc.createElement("nombre-investigador");
nombreInvestigador.setTextContent(experimento.getNombreInvestigador());
propiedades.appendChild(nombreInvestigador);
Element proyectoInvestigacion = xmlDoc.createElement("proyecto-investigacion");
proyectoInvestigacion.setTextContent(experimento.getProyectoInvestigacion());
propiedades.appendChild(proyectoInvestigacion);
ArrayList<LogicPoblacion> poblaciones =
experimento.getPoblaciones();
//Guardamos las poblaciones
for(LogicPoblacion poblacion : poblaciones) {
poblacion.setModified(false);
guardarXMLPoblacion(poblacion);
}
//Escribimos el XML en el fichero
OutputStream out = null;
OutputStreamWriter osw = null;
StreamResult result;
DOMSource source;
Transformer transformer;
TransformerFactory transformerFactory;
try {
transformerFactory = TransformerFactory.newInstance();
transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
source = new DOMSource(xmlDoc);
out = new FileOutputStream(
experimento.getFichExperimento(), false);
osw = new OutputStreamWriter(out, "UTF-8");
result = new StreamResult(osw);
transformer.transform(source, result);
} catch (TransformerException ex) {
Practica1.log.error("Guardar, error");
Practica1.log.error(Language.getI().getP("ERROR"), ex);
throw new ExperimentoInvalidoException(ex);
} catch(IOException ex) {
Practica1.log.error("Guardar, error");
Practica1.log.error(Language.getI().getP("ERROR"), ex);
throw new ExperimentoInvalidoException(ex);
} finally {
try {
if(osw != null) {
osw.close();
}
if(out != null) {
out.close();
}
} catch(IOException ex) {
Practica1.log.error("Guardar, error");
Practica1.log.error(Language.getI().getP("ERROR"), ex);
throw new ExperimentoInvalidoException(ex);
}
}
experimento.setModified(false);
} catch (Exception ex)
{
Practica1.log.error("Guardar, error");
Practica1.log.error(Language.getI().getP("ERROR"), ex);
throw new ExperimentoInvalidoException(ex);
}
}
/**
* Carga en el XML para ser guardado la población que se está procesando
* @param poblacion LogicPoblacion a cargar en el XML
*/
private static void guardarXMLPoblacion(LogicPoblacion poblacion) {
//Agregamos una población al experimento
Element elPob = xmlDoc.createElement("poblacion");
elementoCabecera.appendChild(elPob);
//Cargamos todas las propiedades de la población
String nomP = poblacion.getNombrePoblacion();
String tamP = Integer.toString(poblacion.getTamanioPoblacion());
String temP = Integer.toString(poblacion.getTemperatura());
String escP = poblacion.getEscalaTemperatura();
String fecP = poblacion.getFecha();
String lumP = poblacion.getLuminosidad();
String sinP = poblacion.isSincronizarComida() ? "si" : "no";
ModeloGraficaComida graP = poblacion.getModeloGraficaComida();
ModeloPoblacionTabla tabP = poblacion.getModeloPoblacionTabla();
Element nombre = xmlDoc.createElement("nombre");
nombre.setTextContent(nomP);
elPob.appendChild(nombre);
Element tamanio = xmlDoc.createElement("tamaño");
tamanio.setTextContent(tamP);
elPob.appendChild(tamanio);
Element temperatura = xmlDoc.createElement("temperatura");
temperatura.setTextContent(temP);
elPob.appendChild(temperatura);
Element escalaT = xmlDoc.createElement("escala-temperatura");
escalaT.setTextContent(escP);
elPob.appendChild(escalaT);
Element fecha = xmlDoc.createElement("fecha");
fecha.setTextContent(fecP);
elPob.appendChild(fecha);
Element luminosidad = xmlDoc.createElement("luminosidad");
luminosidad.setTextContent(lumP);
elPob.appendChild(luminosidad);
Element sincronizar = xmlDoc.createElement("sincronizar");
sincronizar.setTextContent(sinP);
elPob.appendChild(sincronizar);
String graPAlimI = Integer.toString(graP.getAlimentoInicial());
String graPAlimM = Integer.toString(graP.getAlimentoMax());
String graPAlimD = Integer.toString(graP.getDiaMax());
String graPAlimF = Integer.toString(graP.getAlimentoFinal());
Element alimentacion = xmlDoc.createElement("alimentacion");
elPob.appendChild(alimentacion);
Element alimentoIni = xmlDoc.createElement("alimentacion-inicial");
alimentoIni.setTextContent(graPAlimI);
alimentacion.appendChild(alimentoIni);
Element alimentoMax = xmlDoc.createElement("alimentacion-maxima");
alimentoMax.setTextContent(graPAlimM);
alimentacion.appendChild(alimentoMax);
Element alimentoDia = xmlDoc.createElement("alimentacion-dia");
alimentoDia.setTextContent(graPAlimD);
alimentacion.appendChild(alimentoDia);
Element alimentoFin = xmlDoc.createElement("alimentacion-final");
alimentoFin.setTextContent(graPAlimF);
alimentacion.appendChild(alimentoFin);
Element tabla = xmlDoc.createElement("tabla-datos");
elPob.appendChild(tabla);
//Recorro las filas de la tabla
for(int i=0; i < 30; i++) {
Element diaDatos = xmlDoc.createElement("datos-dia-" + (i + 1));
tabla.appendChild(diaDatos);
Element tamanioPoblacionDia = xmlDoc.createElement("tamaño-poblacion");
tamanioPoblacionDia.setTextContent((String)tabP.getValueAt(i, 1));
diaDatos.appendChild(tamanioPoblacionDia);
Element bacteriasMuertasDia = xmlDoc.createElement("bacterias-muertas");
bacteriasMuertasDia.setTextContent((String)tabP.getValueAt(i, 2));
diaDatos.appendChild(bacteriasMuertasDia);
Element temperaturaDia = xmlDoc.createElement("temperatura");
temperaturaDia.setTextContent((String)tabP.getValueAt(i, 3));
diaDatos.appendChild(temperaturaDia);
Element cantidadComida = xmlDoc.createElement("cantidad-comida");
cantidadComida.setTextContent((String)tabP.getValueAt(i, 4));
diaDatos.appendChild(cantidadComida);
}
Element comentarios = xmlDoc.createElement("comentarios");
elPob.appendChild(comentarios);
for(Comentario comentario : poblacion.getModeloComentarios().
getComentarios()) {
Element c = xmlDoc.createElement("comentario");
comentarios.appendChild(c);
Element fC = xmlDoc.createElement("fecha");
fC.setTextContent(comentario.getFecha());
c.appendChild(fC);
Element tC = xmlDoc.createElement("texto");
tC.setTextContent(comentario.getTexto());
c.appendChild(tC);
}
}
}