es.emergya.bbdd.dao.HistoricoGPSHome.java Source code

Java tutorial

Introduction

Here is the source code for es.emergya.bbdd.dao.HistoricoGPSHome.java

Source

/*
 * Copyright (C) 2010, Emergya (http://www.emergya.es)
 *
 * @author <a href="mailto:jlrodriguez@emergya.es">Juan Lus Rodrguez</a>
 * @author <a href="mailto:marias@emergya.es">Mara Arias</a>
 *
 * This file is part of GoFleet
 *
 * This software is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * As a special exception, if you link this library with other files to
 * produce an executable, this library does not by itself cause the
 * resulting executable to be covered by the GNU General Public License.
 * This exception does not however invalidate any other reasons why the
 * executable file might be covered by the GNU General Public License.
 */
package es.emergya.bbdd.dao;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.appfuse.dao.hibernate.GenericDaoHibernate;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.vividsolutions.jts.geom.Point;

import es.emergya.bbdd.bean.Flota;
import es.emergya.bbdd.bean.HistoricoGPS;
import es.emergya.bbdd.bean.Incidencia;
import es.emergya.bbdd.bean.Recurso;
import es.emergya.bbdd.bean.Usuario;
import es.emergya.bbdd.bean.notmapped.Posicion;
import es.emergya.utils.LogicConstants;

@Repository("historicoGPSHome")
public class HistoricoGPSHome extends GenericDaoHibernate<HistoricoGPS, Long> {

    //TODO no longer supports GPX
    private static final String DIRECTORIO_GPX_DEFAULT = "/var/gpx/";
    private static final String DIRECTORIO_GPX = "DIRECTORIO_GPX";
    private static final Log log = LogFactory.getLog(HistoricoGPSHome.class);
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    private static synchronized Date parse(String time) {
        try {
            return sdf.parse(time);
        } catch (Throwable t) {
            log.error("Error parseando fecha de fichero '" + time + "'");
            return null;
        }
    }

    public HistoricoGPSHome() {
        super(HistoricoGPS.class);
    }

    @Override
    public HistoricoGPS get(Long id) {
        try {
            return super.get(id);
        } catch (Throwable t) {
            log.error("Estamos buscando un objeto que no existe", t);
            return null;
        }
    }

    public Date lastGPSDateForRecurso(Recurso r) {
        final HistoricoGPS lastGPSForRecurso = lastGPSForRecurso(r);
        if (lastGPSForRecurso != null)
            return lastGPSForRecurso.getMarcaTemporal();
        else
            return null;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true, rollbackFor = Throwable.class)
    public HistoricoGPS lastGPSForRecurso(Recurso r) {
        if (r == null)
            return null;

        try {

            Session currentSession = getSession();
            currentSession.flush();
            currentSession.refresh(r);
            if (r.getHistoricoGps() != null) {
                r.getHistoricoGps().getPosX();
                return r.getHistoricoGps();
            }
        } catch (Throwable t) {
        }

        return lastGPSForRecurso(r.getIdentificador());
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true, rollbackFor = Throwable.class)
    public HistoricoGPS lastGPSForRecurso(String r) {
        HistoricoGPS res = null;
        if (r == null)
            return res;

        Session currentSession = getSession();
        currentSession.flush();
        res = ((Recurso) getSession().createCriteria(Recurso.class).add(Restrictions.eq("identificador", r))
                .setMaxResults(1).uniqueResult()).getHistoricoGps();

        return res;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true, rollbackFor = Throwable.class)
    public Calendar firstGPSForRecurso(String r) {
        HistoricoGPS res = null;
        if (r == null)
            return null;

        Session currentSession = getSession();
        currentSession.flush();
        res = (HistoricoGPS) getSession().createCriteria(HistoricoGPS.class).add(Restrictions.eq("recurso", r))
                .addOrder(Order.asc("marcaTemporal")).setMaxResults(1).uniqueResult();

        if (res == null || res.getMarcaTemporal() == null)
            return null;

        Calendar resultado = Calendar.getInstance();
        resultado.setTime(res.getMarcaTemporal());

        return resultado;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false, rollbackFor = Throwable.class)
    public void delete(String identificador, Calendar ini, Calendar fin) {
        Session currentSession = getSession();
        currentSession
                .createSQLQuery("DELETE FROM historico_gps "
                        + "WHERE recurso like :ID AND marca_temporal > :INI AND marca_temporal < :FIN")
                .setDate("FIN", fin.getTime()).setDate("INI", ini.getTime()).setString("ID", identificador)
                .executeUpdate();
    }

    @Transactional(readOnly = false, rollbackFor = Throwable.class, propagation = Propagation.REQUIRES_NEW)
    public HistoricoGPS saveOrUpdate(HistoricoGPS hgps) {

        Session currentSession = getSession();
        currentSession.clear();

        HistoricoGPS entity = null;

        if (hgps.getId() == null || (hgps.getId() != null && this.get(hgps.getId()) == null))
            entity = hgps;
        else
            entity = (HistoricoGPS) currentSession.merge(hgps);

        currentSession.saveOrUpdate(entity);
        return entity;
    }

    @Transactional(readOnly = false, rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
    public HistoricoGPS saveServer(HistoricoGPS hgps) {
        Session currentSession = getSession();
        currentSession.save(hgps);
        currentSession.flush();
        return hgps;
    }

    // TODO

    /**
     * TIME#FLOTA#IDENTIFICADOR
     * 
     * @param fileName
     * @return
     */
    private static String getFlotaFromFileName(String fileName) {
        try {
            return fileName.substring(fileName.indexOf("#") + 1, fileName.lastIndexOf("#"));
        } catch (Throwable t) {
            log.error("Error al extraer el nombre de la flota del fichero '" + fileName + "'");
            return null;
        }
    }

    private static String getRecursoFromFileName(String fileName) {
        try {
            return fileName.substring(fileName.lastIndexOf("#") + 1, fileName.lastIndexOf(".gpx"));
        } catch (Throwable t) {
            log.error("Error al extraer el nombre del recurso del fichero '" + fileName + "'");
            return null;
        }
    }

    private static Date getTimeFromFileName(String fileName) {
        try {
            return parse(fileName.substring(0, fileName.indexOf("#")));
        } catch (Throwable t) {
            log.error("Error al extraer la fecha del fichero '" + fileName + "'");
            return null;
        }
    }

    /**
     * Dado un conjuto de flotas y una fecha de inicio y fin, devuelve los
     * nombres de los recursos que pertenecan a alguna de estas flotas y que
     * enviaron alguna posicin en el periodo. Si alguna fecha es null no se
     * tienen en cuenta (no se aade a la condicin)
     * 
     * @param flotas
     *            conjunto de flotas en las que estamos interesados.
     * @param initDate
     *            fecha/hora inicial del periodo de bsqueda.
     * @param endDate
     *            fecha/hora final del periodo de bsqueda.
     * 
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true, rollbackFor = Throwable.class)
    public List<String> findRecursosInIntervalForFoltas(Set<Flota> flotas, Calendar initDate, Calendar endDate,
            Usuario user) {
        log.info("findRecursosInINtervalForFlotas");
        List<String> result = new LinkedList<String>();

        try {
            Date inicio = null;
            Date fin = null;

            if (initDate != null) {
                inicio = initDate.getTime();
            }
            if (endDate != null) {
                fin = endDate.getTime();
            }

            Calendar c = Calendar.getInstance();
            Date inicio_day = null;
            if (inicio != null) {
                c.setTime(inicio);
                c.set(Calendar.HOUR_OF_DAY, 0);
                c.set(Calendar.MINUTE, 0);
                c.set(Calendar.SECOND, 0);
                c.set(Calendar.MILLISECOND, 0);

                c.add(Calendar.SECOND, -1);
                inicio_day = c.getTime();
            }

            Date fin_day = null;
            if (fin != null) {
                c.setTime(fin);
                c.set(Calendar.HOUR_OF_DAY, 0);
                c.set(Calendar.MINUTE, 0);
                c.set(Calendar.SECOND, 0);
                c.set(Calendar.MILLISECOND, 0);
                c.add(Calendar.DAY_OF_YEAR, 1);
                fin_day = c.getTime();
            }

            // Creamos un array con los nombres de las subflotas para usarlos en
            // una
            // condicin IN
            if (flotas == null || (flotas != null && flotas.size() == 0)) {
                return result;
            }
            Date fin_provisional = null;
            String[] nombreFlotas = new String[flotas.size()];
            int i = 0;
            for (Flota f : flotas) {
                nombreFlotas[i++] = f.getNombre();
            }

            // Si no hemos recibido fechas de inicio o fin significa que estamos
            // consultando ltimas posiciones. Utilizamos la tabla recursos para
            // obtener las ltimas posiciones.
            if (inicio == null || fin == null) {
                log.trace("No hay fecha de inicio o fin. Buscamos solo las ultimas posiciones.");
                result.addAll(calculateRecursosUltimasPosiciones(user));
            } else {
                StringBuilder stringFlotas = new StringBuilder("");
                if (nombreFlotas.length > 0) {
                    stringFlotas.append(" subflota in ('" + nombreFlotas[0]);
                    for (i = 1; i < nombreFlotas.length; i++) {
                        stringFlotas.append("', '").append(nombreFlotas[i]);
                    }
                    stringFlotas.append("') ");
                }
                while (inicio != null && fin != null && inicio.before(fin)) {
                    initDate.add(Calendar.DAY_OF_YEAR, 1);
                    fin_provisional = initDate.getTime();
                    if (fin.before(fin_provisional))
                        fin_provisional = fin;
                    result.addAll(calculateRecursos(inicio, fin_provisional, stringFlotas.toString(), result));
                    log.trace("De momento llevamos " + result);
                    inicio = fin_provisional;
                }
            }

            if (fin != null && inicio != null)
                try {
                    File directorio = new File(LogicConstants.get(DIRECTORIO_GPX, DIRECTORIO_GPX_DEFAULT));

                    if (!directorio.isDirectory()) {
                        throw new IOException("La ruta pasada para los gpx no es un directorio");
                    }

                    List<String> fltas = new LinkedList<String>();
                    for (String s : nombreFlotas) {
                        fltas.add(s);
                    }

                    log.trace("Flotas: " + flotas);

                    for (File file : directorio.listFiles()) {
                        log.trace(file.getAbsolutePath());
                        try {
                            if (file.isDirectory()) {
                                throw new IOException(file + " no es un fichero");
                            }

                            if (!file.canRead()) {
                                throw new IOException(file + " no es legible");
                            }

                            String nombreFichero = file.getName();

                            final String recurso = getRecursoFromFileName(nombreFichero);
                            final String flota = getFlotaFromFileName(nombreFichero);

                            log.debug("Encontrado " + recurso + " de " + flota);

                            if (!result.contains(recurso)) {
                                log.trace("Miramos el recurso " + recurso + " de " + flota + " en " + flotas);
                                if (fltas.contains(flota)) {
                                    Date time = getTimeFromFileName(nombreFichero);
                                    // Si las fechas coinciden

                                    if (time != null) {
                                        log.trace("Hora del recurso: " + time);
                                        if (inicio_day == null || inicio_day.before(time)) {
                                            if (fin_day == null || fin_day.after(time)) {
                                                result.add(recurso);
                                                log.trace("Metemos a " + recurso);
                                            }
                                        }
                                    }
                                }
                            }
                        } catch (Throwable t) {
                            log.error("No pude leer a " + file, t);
                        }
                    }
                } catch (Throwable t) {
                    log.error("No pudimos buscar en los gpx", t);
                }

            Collections.sort(result);
        } catch (Throwable t) {
            log.error("Error al buscar los recursos", t);
        }

        return result;

    }

    @SuppressWarnings("unchecked")
    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true, rollbackFor = Throwable.class)
    private List<String> calculateRecursos(Date inicio, Date fin, String flotas,
            List<String> recursosYaEncontrados) {
        int i;
        StringBuffer sb = new StringBuffer();
        sb.append("select distinct(rec.recurso) as nombreRecurso from ");

        sb.append(" (select st_collect(geom) as geom, recurso from historico_gps where ");

        sb.append(flotas);

        if (recursosYaEncontrados.size() > 0) {
            if (flotas.length() > 0) {
                sb.append(" and ");
            }
            sb.append("recurso not in ('");
            sb.append(recursosYaEncontrados.get(0));
            for (i = 1; i < recursosYaEncontrados.size(); i++) {
                sb.append("', '").append(recursosYaEncontrados.get(i));
            }
            sb.append("') ");
        }

        if (inicio != null) {
            sb.append(" and marca_temporal >= :FECHA_INICIO ");

        }

        if (fin != null) {
            sb.append(" and marca_temporal <= :FECHA_FIN ");
        }

        sb.append(" group by recurso) as rec");

        SQLQuery q = getSession().createSQLQuery(sb.toString());
        if (inicio != null) {
            q.setParameter("FECHA_INICIO", inicio, Hibernate.TIMESTAMP);

        }

        if (fin != null) {
            q.setParameter("FECHA_FIN", fin, Hibernate.TIMESTAMP);
        }

        q.addScalar("nombreRecurso", Hibernate.STRING);

        log.debug(sb.toString() + " => " + inicio + " " + fin);

        List<String> result = q.list();

        return result;
    }

    /**
     * Dado una lista de zonas y un usuario, devuelve la lista de recursos que
     * el que usuario puede ver por su rol y cuya ltima posicin en la base de
     * datos est en alguna de las zonas pasadas.
     * 
     * @param zonas
     * @param u
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true, rollbackFor = Throwable.class)
    private List<String> calculateRecursosUltimasPosiciones(Usuario u) {
        int i;

        StringBuffer sb = new StringBuffer();
        sb.append("select distinct r.nombre as nombreRecurso ")
                .append("from recursos r inner join flotas f on r.flota_x_flota=f.x_flota ")
                .append("inner join roles_x_flotas rxf on rxf.x_flota = f.x_flota ")
                .append("inner join roles rol on rxf.x_rol=rol.x_rol ")
                .append("inner join usuarios u on u.fk_roles = rol.x_rol ")
                .append("inner join historico_gps h on r.fk_historico_gps = h.x_historico ");

        sb.append("and u.nombre_usuario=:USUARIO ");

        sb.append("order by nombreRecurso");

        SQLQuery q = getSession().createSQLQuery(sb.toString());

        q.addScalar("nombreRecurso", Hibernate.STRING);
        q.setString("USUARIO", u.getNombreUsuario());
        if (log.isDebugEnabled()) {
            log.debug(sb.toString());
        }

        List<String> result = q.list();
        return result;
    }

    /**
     * Devuelve las entradas de historico_gps que fueron producidas en el
     * itervalo indicado por el recurso pasado com parmetro ordenadas por marca
     * temporal asc.
     * 
     * @param recurso
     *            nombre del recurso.
     * @param inicio
     *            fecha / hora de inicio.
     * @param fin
     *            fecha / hora de fin.
     * @return la lista de HistoricoGPS del recurso en el intervalo ordenada por
     *         marcaTemporal ascendente.
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true, rollbackFor = Throwable.class)
    public List<HistoricoGPS> getPosicionesEnIntervalo(String recurso, Date inicio, Date fin) {
        List<HistoricoGPS> result = getPosicionesEnIntervaloSoloBBDD(recurso, inicio, fin);
        //      try {
        //         getPosicionesEnIntervaloFromGPX(inicio, fin, recurso, result);
        //         ordenar(result);
        //      } catch (Throwable t) {
        //         log.error("Error al extraer posiciones en intervalo", t);
        //      }
        return result;
    }

    private void ordenar(List<HistoricoGPS> result) {
        java.util.Collections.sort(result, new Comparator<HistoricoGPS>() {

            @Override
            public int compare(HistoricoGPS arg0, HistoricoGPS arg1) {
                if (arg0 == null || arg1 == null)
                    return 0;
                if (arg0.getMarcaTemporal() == null || arg1.getMarcaTemporal() == null)
                    return 0;
                return arg0.getMarcaTemporal().compareTo(arg1.getMarcaTemporal());
            }
        });
    }

    /**
     * Obtiene las posiciones histricas del recurso indicado durante el periodo
     * pasado como parmetro. Slo consulta la base de datos, no los GPX.
     * 
     * @param recurso
     * @param inicio
     * @param fin
     * @return la lista de posiciones histricas del recurso ordenadas por marca
     *         temporal ascentente
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true, rollbackFor = Throwable.class)
    public List<HistoricoGPS> getPosicionesEnIntervaloSoloBBDD(String recurso, Date inicio, Date fin) {
        List<HistoricoGPS> result = new LinkedList<HistoricoGPS>();
        try {
            Criteria crit = getSession().createCriteria(HistoricoGPS.class);

            if (inicio != null) {
                crit.add(Restrictions.ge("marcaTemporal", inicio));
            }
            if (fin != null) {
                crit.add(Restrictions.lt("marcaTemporal", fin));
            }

            crit.add(Restrictions.eq("recurso", recurso)).addOrder(Order.asc("marcaTemporal"));

            result = crit.list();
        } catch (Throwable t) {
            log.error("Error al extraer posiciones solo BBDD en intervalo. Recurso=" + recurso + ", Inicio= "
                    + inicio + ", Fin= " + fin, t);

        }

        return result;
    }

    // /**
    // * Busca posiciones en el intervalo para el recurso nicamente usando los
    // * datos de los GPX.
    // *
    // * @param inicio
    // * @param fin
    // * @param recurso
    // * @param result
    // */
    // private void getPosicionesEnIntervaloFromGPX(Date inicio, Date fin,
    // String recurso, List<HistoricoGPS> result) {
    // try {
    // File directorio = new File(LogicConstants.get(DIRECTORIO_GPX,
    // DIRECTORIO_GPX_DEFAULT));
    // if (!directorio.isDirectory()) {
    // throw new IOException(
    // "La ruta pasada para los gpx no es un directorio");
    // }
    // Calendar c = Calendar.getInstance();
    // Date inicio_day = null;
    // if (inicio != null) {
    // c.setTime(inicio);
    // c.set(Calendar.HOUR_OF_DAY, 0);
    // c.set(Calendar.MINUTE, 0);
    // c.set(Calendar.SECOND, 0);
    // c.set(Calendar.MILLISECOND, 0);
    // c.add(Calendar.SECOND, -1);
    // inicio_day = c.getTime();
    // }
    // Date fin_day = null;
    // if (fin != null) {
    // c.setTime(fin);
    // c.set(Calendar.HOUR_OF_DAY, 0);
    // c.set(Calendar.MINUTE, 0);
    // c.set(Calendar.SECOND, 0);
    // c.set(Calendar.MILLISECOND, 0);
    // c.add(Calendar.DAY_OF_YEAR, 1);
    // fin_day = c.getTime();
    // }
    // for (File file : directorio.listFiles()) {
    // try {
    // if (file.isDirectory()) {
    // throw new IOException(file + " no es un fichero");
    // }
    // if (!file.canRead()) {
    // throw new IOException(file + " no es legible");
    // }
    // String nombreFichero = file.getName();
    // // Si este fichero es de este recurso
    // if (recurso.equals(getRecursoFromFileName(nombreFichero))) {
    // Date time = getTimeFromFileName(nombreFichero);
    // // Y las fechas coinciden
    // if (time != null) {
    // if (inicio_day == null || inicio_day.before(time)) {
    // if (fin_day == null || fin_day.after(time)) {
    // log.trace("Procesamos "
    // + file.getAbsolutePath());
    // for (HistoricoGPS hgps : extractPositions(file)) {
    // // Aunque sea el fichero correcto,
    // // volvemos a comprobar las marcas
    // // temporales
    // final Date marcaTemporal = hgps
    // .getMarcaTemporal();
    // log.info(inicio + " - " + marcaTemporal
    // + " - " + fin);
    // if (fin == null
    // || (marcaTemporal.before(fin))
    // && (inicio == null || marcaTemporal
    // .after(inicio))) {
    // result.add(hgps);
    // }
    // }
    // }
    // }
    // }
    // }
    // } catch (Throwable t) {
    // log.error("No pude leer a " + file, t);
    // }
    // }
    // } catch (Throwable t) {
    // log.error("No pudimos buscar en los gpx", t);
    // }
    // }

    //   private List<HistoricoGPS> extractPositions(File file) {
    //      log.trace("extractPositions(" + file.getAbsolutePath() + ")");
    //      List<HistoricoGPS> resultado = new LinkedList<HistoricoGPS>();
    //
    //      String fileName = file.getName();
    //      String recurso = getRecursoFromFileName(fileName);
    //      String flota = getFlotaFromFileName(fileName);
    //
    //      FileInputStream is;
    //
    //      try {
    //         is = new FileInputStream(file);
    //         GpxReader reader = new GpxReader(is);
    //         reader.parse(true);
    //
    //         GpxData data = reader.data;
    //
    //         for (GpxRoute r : data.routes) {
    //            for (WayPoint w : r.routePoints) {
    //               resultado.add(convert(w, recurso, flota));
    //
    //            }
    //         }
    //
    //         for (WayPoint w : data.waypoints) {
    //            resultado.add(convert(w, recurso, flota));
    //
    //         }
    //
    //         for (ImmutableGpxTrack tr : data.tracks) {
    //            for (GpxTrackSegment seg : tr.getSegments()) {
    //               for (WayPoint w : seg.getWayPoints()) {
    //                  resultado.add(convert(w, recurso, flota));
    //
    //               }
    //            }
    //         }
    //
    //      } catch (Throwable e) {
    //         log.error("No pude extraer el historico", e);
    //
    //      }
    //
    //      return resultado;
    //
    //   }
    //
    //   private HistoricoGPS convert(WayPoint w, String recurso, String subflota) {
    //      log.trace("convert(" + w + ", " + recurso + ", " + subflota + ")");
    //      HistoricoGPS his = new HistoricoGPS();
    //      w.setTime();
    //      Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
    //      Calendar c2 = Calendar.getInstance();
    //      c2.setTime(new Date((long) (w.time * 1000)));
    //      for (Integer i : new Integer[] { Calendar.YEAR, Calendar.MONTH,
    //            Calendar.DAY_OF_MONTH, Calendar.HOUR_OF_DAY, Calendar.MINUTE,
    //            Calendar.SECOND, Calendar.MILLISECOND })
    //         c.set(i, c2.get(i));
    //      his.setMarcaTemporal(c.getTime());
    //      log.trace("Historico GPS a las " + his.getMarcaTemporal()
    //            + " y deberia ser a las " + new Date((long) (w.time * 1000)));
    //      his.setRecurso(recurso);
    //      his.setSubflota(subflota);
    //      LatLon latlon = w.latlon;
    //      GeometryFactory factory = new GeometryFactory();
    //      Geometry geom = factory.createPoint(new Coordinate(latlon.getX(),
    //            latlon.getY()));
    //      his.setGeom(geom);
    //      his.setPosX(geom.getCentroid().getX());
    //      his.setPosY(geom.getCentroid().getY());
    //
    //      return his;
    //
    //   }

    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true, rollbackFor = Throwable.class)
    public Posicion[] getUltimasPosiciones(String[] idRecursos) {
        if (idRecursos == null || idRecursos.length == 0) {
            return new Posicion[] {};
        }

        List<Posicion> resultado = new LinkedList<Posicion>();

        for (String idRecurso : idRecursos) {
            Criteria crit = getSession().createCriteria(HistoricoGPS.class)
                    .add(Restrictions.eq("recurso", idRecurso)).addOrder(Order.desc("marcaTemporal"))
                    .setMaxResults(1);

            HistoricoGPS hist = (HistoricoGPS) crit.uniqueResult();
            Posicion p = new Posicion();
            if (hist != null) {
                p.setX(hist.getPosX());
                p.setY(hist.getPosY());
                p.setIdentificador(idRecurso);
                Calendar marcaTemporal = Calendar.getInstance();
                marcaTemporal.setTimeInMillis(hist.getMarcaTemporal().getTime());

                p.setMarcaTemporal(marcaTemporal);
                resultado.add(p);
            }

        }

        return resultado.toArray(new Posicion[0]);

    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true, rollbackFor = Throwable.class)
    public Posicion[] getPosicionesIncidencias(String[] idIncidencias) {
        if (idIncidencias == null) {
            return new Posicion[] {};

        }

        int i = 0;

        ArrayList<Long> ids = new ArrayList<Long>();

        for (String s : idIncidencias) {
            try {
                ids.add(new Long(s));

            } catch (Throwable t) {
                log.error(t, t);

            }
        }

        Posicion[] resultado = new Posicion[idIncidencias.length];

        for (Long idIncidencia : ids) {
            Criteria crit = getSession().createCriteria(Incidencia.class).add(Restrictions.eq("id", idIncidencia))
                    .setMaxResults(1);
            Incidencia incidencia = (Incidencia) crit.uniqueResult();

            if (incidencia != null) {
                Posicion p = new Posicion();

                Point geom = incidencia.getGeometria().getCentroid();

                if (geom != null) {
                    p.setX(geom.getCoordinate().x);
                    p.setY(geom.getCoordinate().y);
                    p.setIdentificador(incidencia.getTitulo());
                    Calendar marcaTemporal = Calendar.getInstance();
                    marcaTemporal.setTimeInMillis(incidencia.getFechaCreacion().getTime());

                    p.setMarcaTemporal(marcaTemporal);
                    log.debug("Posicion de incidencia: " + p);
                    resultado[i++] = p;
                } else {
                    log.error("Incidencia sin posicion (" + idIncidencia + ")");
                }
            } else {
                log.error("Se pidio la posicion de una incidencia desconocida: " + idIncidencia);
            }
        }

        return resultado;

    }

}