org.gofleet.module.routing.RoutingMap.java Source code

Java tutorial

Introduction

Here is the source code for org.gofleet.module.routing.RoutingMap.java

Source

/**
 * Copyright (C) 2010, Emergya (http://www.emergya.es)
 *
 * @author <a href="mailto:marias@emergya.es">Mara Arias de Reyna</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 org.gofleet.module.routing;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import javax.swing.filechooser.FileFilter;

import org.apache.commons.logging.LogFactory;
import org.gofleet.context.GoWired;
import org.gofleet.internacionalization.I18n;
import org.gofleet.openls.RoutingServiceStub;
import org.gofleet.openls.RoutingServiceStub.GetTravellingSalesmanPlan;
import org.gofleet.openls.RoutingServiceStub.GetTravellingSalesmanPlanResponse;
import org.gofleet.openls.RoutingServiceStub.TSPPlan;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.gpx.GpxData;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.Way;
import org.openstreetmap.josm.gui.layer.GpxLayer;
import org.openstreetmap.josm.gui.layer.Layer;
import org.openstreetmap.josm.gui.layer.OsmDataLayer;
import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
import org.openstreetmap.josm.gui.mappaint.LineElemStyle;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.io.WKTReader;

import edu.emory.mathcs.backport.java.util.Collections;
import es.emergya.actions.Authentication;
import es.emergya.cliente.constants.LogicConstants;
import es.emergya.consultas.IncidenciaConsultas;
import es.emergya.consultas.RecursoConsultas;
import es.emergya.ui.base.BasicWindow;
import es.emergya.ui.base.plugins.PluginType;
import es.emergya.ui.gis.CustomMapView.InitAdapter;
import es.emergya.ui.gis.MapViewer;

public class RoutingMap extends MapViewer implements ActionListener {

    private static final org.apache.commons.logging.Log log = LogFactory.getLog(RoutingMap.class);
    private static final long serialVersionUID = -1837324556102054550L;
    private final WKTReader wktReader = new WKTReader();

    /**
     * @param title
     * @param type
     * @param order
     * @param icon
     * @param layers
     * @param mouseWheelListener
     * @param mouseListener
     * @param mouseMotionListener
     * @param initAdapter
     */
    public RoutingMap(String title, PluginType type, int order, String icon, List<MarkerLayer> layers,
            MouseWheelListener mouseWheelListener, MouseListener mouseListener,
            MouseMotionListener mouseMotionListener, InitAdapter initAdapter) {
        super(title, type, order, icon, layers, mouseWheelListener, mouseListener, mouseMotionListener,
                initAdapter);

    }

    @GoWired
    public I18n i18n;

    /**
     * @return the i18n
     */
    public I18n getI18n() {
        return i18n;
    }

    /**
     * @param i18n
     *            the i18n to set
     */
    public void setI18n(I18n i18n) {
        this.i18n = i18n;
    }

    @GoWired
    public BasicWindow basicWindow;

    /**
     * @return the i18n
     */
    public BasicWindow getBasicWindow() {
        return basicWindow;
    }

    /**
     * @param i18n
     *            the i18n to set
     */
    public void setBasicWindow(BasicWindow basicWindow) {
        this.basicWindow = basicWindow;
    }

    /**
     * @param title
     * @param type
     * @param order
     * @param icon
     * @param layers
     */
    public RoutingMap(String title, PluginType type, int order, String icon, List<MarkerLayer> layers) {
        super(title, type, order, icon, layers);
    }

    /**
     * @param title
     * @param type
     * @param order
     * @param icon
     */
    public RoutingMap(String title, PluginType type, int order, String icon) {
        super(title, type, order, icon);
    }

    @Override
    public void actionPerformed(final ActionEvent e) {

        SwingWorker<Object, Object> sw = new SwingWorker<Object, Object>() {
            @Override
            protected Object doInBackground() throws Exception {
                String mapMenuNewPlanning = i18n.getString("map.menu.new.planning");
                try {
                    if (e.getActionCommand().equals(mapMenuNewPlanning)) {
                        LatLon from = RoutingMap.this.mapView.getLatLon(
                                RoutingMap.this.mapView.lastMEvent.getPoint().x,
                                RoutingMap.this.mapView.lastMEvent.getPoint().y);
                        newPlan(from);
                    } else {
                        log.error(
                                "ActionCommand desconocido: " + e.getActionCommand() + " vs " + mapMenuNewPlanning);
                    }
                } catch (Throwable t) {
                    log.error("Error al ejecutar la accion del menu contextual", t);
                }
                return null;
            }
        };

        sw.execute();
    }

    private void newPlan(LatLon from) {
        JDialog d = new JDialog(basicWindow.getFrame(), "Generating New Plan");
        try {
            JFileChooser fc = new JFileChooser();
            fc.addChoosableFileFilter(new RoutingFilter());
            fc.setAcceptAllFileFilterUsed(true);
            int returnVal = fc.showOpenDialog(basicWindow.getFrame());
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = fc.getSelectedFile();
                log.debug("Opening: " + file.getName());

                JProgressBar progressBar = new JProgressBar(0, getNumberLines(file) * 2);
                progressBar.setValue(0);
                progressBar.setPreferredSize(new Dimension(150, 50));
                progressBar.setStringPainted(true);

                d.add(progressBar);
                d.pack();
                d.setVisible(true);

                TSPPlan[] param = processFile(file, progressBar);

                Map<String, String> values = getValues(from);

                double[] origin = new double[2];
                origin[0] = new Double(values.get("origin_x"));
                origin[1] = new Double(values.get("origin_y"));

                TSPPlan[] res = calculateRouteOnWS(new Integer(values.get("maxDistance")),
                        new Integer(values.get("maxTime")), origin, new Integer(values.get("startTime")), param,
                        new Integer(values.get("timeSpentOnStop")));

                progressBar.setValue(progressBar.getMaximum() - res.length);

                processTSPPlan(res, progressBar);

            } else {
                log.trace("Open command cancelled by user.");
            }
        } catch (Throwable t) {
            log.error("Error computing new plan", t);
            JOptionPane.showMessageDialog(basicWindow.getFrame(),
                    "<html><p>" + i18n.getString("Main.Error") + ":</p><p>" + t.toString() + "</p><html>",
                    i18n.getString("Main.Error"), JOptionPane.ERROR_MESSAGE);
        } finally {
            d.setVisible(false);
            d.dispose();
        }

    }

    private Map<String, String> getValues(LatLon from) {
        final Map<String, String> mapa = new HashMap<String, String>();
        final JDialog frame = new JDialog(basicWindow.getFrame(), "Configuration");
        JPanel panel = new JPanel(new GridLayout(0, 2));
        int width = 10;

        final JTextField maxDistance = new JTextField(width);
        maxDistance.setText("10");
        final JTextField maxTime = new JTextField(width);
        maxTime.setText("8");
        final JTextField origin_x = new JTextField(width / 2);
        origin_x.setText((new Double(from.getX())).toString());
        final JTextField origin_y = new JTextField(width / 2);
        origin_y.setText((new Double(from.getY())).toString());
        final JTextField startTime = new JTextField(width);
        startTime.setText("7");
        final JTextField timeSpentOnStop = new JTextField(width);
        timeSpentOnStop.setText("1");
        JLabel lmaxDistance = new JLabel("Maximum Distance (km)");
        lmaxDistance.setLabelFor(maxDistance);
        JLabel lmaxTime = new JLabel("Maximum Time (hours)");
        lmaxTime.setLabelFor(maxTime);
        JLabel lorigin = new JLabel("Point of Origin");
        lorigin.setLabelFor(origin_x);
        JLabel lstartTime = new JLabel("Start Time of Plan (0-24)");
        lstartTime.setLabelFor(startTime);
        JLabel ltimeSpentOnStop = new JLabel("Time Spent on Stop (hours)");
        ltimeSpentOnStop.setLabelFor(timeSpentOnStop);

        JButton close = new JButton("OK");
        close.addActionListener(new AbstractAction() {

            private static final long serialVersionUID = -8912729211256933464L;

            @Override
            public void actionPerformed(ActionEvent arg0) {
                try {
                    mapa.put("maxDistance", maxDistance.getText());
                    mapa.put("maxTime", maxTime.getText());
                    mapa.put("origin_x", origin_x.getText());
                    mapa.put("origin_y", origin_y.getText());
                    mapa.put("startTime", startTime.getText());
                    mapa.put("timeSpentOnStop", timeSpentOnStop.getText());
                    frame.dispose();
                } catch (Throwable t) {
                    log.error("Error configuring New Route Plan" + t);
                    JOptionPane.showMessageDialog(RoutingMap.this, "Some values are wrong. Check them again.");
                }
            }
        });

        panel.add(lmaxDistance);
        panel.add(maxDistance);
        panel.add(lmaxTime);
        panel.add(maxTime);
        panel.add(lorigin);
        JPanel panel_origin = new JPanel();
        panel_origin.add(origin_x);
        panel_origin.add(origin_y);
        panel.add(panel_origin);
        panel.add(lstartTime);
        panel.add(startTime);
        panel.add(ltimeSpentOnStop);
        panel.add(timeSpentOnStop);
        panel.add(close);
        frame.add(panel, BorderLayout.CENTER);
        frame.pack();
        frame.setModalityType(ModalityType.APPLICATION_MODAL);
        frame.setVisible(true);

        return mapa;
    }

    private void processTSPPlan(TSPPlan[] res, JProgressBar progressBar) {
        Random random = new Random();
        try {

            @SuppressWarnings("unchecked")
            Collection<Layer> allLayers = Collections.unmodifiableCollection(this.mapView.getAllLayers());
            List<Layer> toremove = new LinkedList<Layer>();
            for (Layer l : allLayers) {
                if (l.name.startsWith("Route Plan") || l.name.startsWith("Stops"))
                    toremove.add(l);
            }
            for (Layer l : toremove)
                this.mapView.removeLayer(l);

            LatLon latlon_origin = null;
            int id_layer = 0;
            for (TSPPlan plan : res) {
                latlon_origin = new LatLon(plan.getOrigin()[1], plan.getOrigin()[0]);
                log.info(latlon_origin);
                LineElemStyle ls = new LineElemStyle();
                float f = random.nextFloat();
                ls.color = Color.getHSBColor(f * random.nextFloat(), 0.9f, 0.9f);
                ls.width = LogicConstants.getInt("PLAN_WAY_WIDTH", 2);
                MarkerLayer stops = new MarkerLayer(new GpxData(), "Stops " + id_layer,
                        File.createTempFile("stops", "tmp"), new GpxLayer(new GpxData()), this.mapView);
                stops.data.add(new StopMarker(latlon_origin, "origin", "tsp_stop", stops, 0, 0, ls.color));
                for (String stop : plan.getStops()) {
                    String[] array = stop.split(",");
                    double[] point = new double[2];
                    point[1] = new Double(array[0]);
                    point[0] = new Double(array[1]);

                    LatLon ll = new LatLon(point[0], point[1]);
                    log.info(ll);
                    stops.data.add(new StopMarker(ll, array[2], "tsp_stop", stops, 0, 0, ls.color));
                }
                this.mapView.addLayer(stops, true);

                OsmDataLayer layer = new OsmDataLayer(new DataSet(), "Route Plan " + id_layer++,
                        File.createTempFile("planning", "route"));
                String way2 = plan.getWay();

                if (way2 != null) {
                    Way way = new Way();
                    LatLon info = null;

                    MultiLineString multilinestring = (MultiLineString) wktReader.read(way2);
                    multilinestring.getLength();
                    int numGeometries = multilinestring.getNumGeometries();
                    for (int i = 0; i < numGeometries; i++) {
                        for (Coordinate coordenada : multilinestring.getGeometryN(i).getCoordinates()) {
                            LatLon ll = new LatLon(coordenada.y, coordenada.x);
                            way.addNode(new Node(ll));
                            if (info == null)
                                info = ll;
                        }
                        way.mappaintStyle = ls;
                        layer.data.ways.add(way);
                        way = new Way();
                    }
                    progressBar.setValue(progressBar.getValue() + 1);

                    StopMarker marker = new StopMarker(info,
                            (new Double(plan.getDistance())).toString().substring(0, 5) + " km in "
                                    + (new Double(plan.getTime() / 60)).toString().substring(0, 3) + " hours",
                            "tsp_stop", stops, 0, 0, ls.color);
                    marker.setPaintIcon(false);
                    stops.data.add(marker);
                }
                this.mapView.addLayer(layer, true);

                layer.visible = true;
                stops.visible = true;
            }
        } catch (Throwable e) {
            log.error("Error painting plan", e);
        }
    }

    private TSPPlan[] calculateRouteOnWS(Integer maxDistance, Integer maxTime, double[] doubles, Integer startTime,
            TSPPlan[] stops, Integer timeSpentOnStop) {

        try {
            TSPPlan[] tspplan = new TSPPlan[stops.length];
            RoutingServiceStub rss = new RoutingServiceStub(LogicConstants.get("URL_ROUTING",
                    "http://46.105.24.58:8080/openLS/services/RoutingService.RoutingServiceHttpSoap12Endpoint/"));

            for (int i = 0; i < tspplan.length; i++) {
                final TSPPlan tspPlan2 = new TSPPlan();
                tspPlan2.setDistance(-1);
                tspPlan2.setOrigin(doubles);
                tspPlan2.setTime(-1);
                tspPlan2.setWay(null);
                tspPlan2.setStops(stops[i].getStops());
                tspplan[i] = tspPlan2;
                GetTravellingSalesmanPlan param = new GetTravellingSalesmanPlan();
                param.setMaxDistance(maxDistance);
                param.setMaxTime(maxTime);
                param.setStartTime(startTime);
                param.setTimeSpentOnStop(timeSpentOnStop);
                param.setParam(tspplan[i]);

                try {
                    GetTravellingSalesmanPlanResponse res = rss.getTravellingSalesmanPlan(param);
                    tspplan[i] = res.get_return();
                } catch (Throwable t) {
                    log.error("error computing " + i + " plan", t);
                }
            }

            return tspplan;
        } catch (Throwable t) {
            JOptionPane.showMessageDialog(basicWindow.getFrame(),
                    "<html><p>" + "Error" + ":</p><p>" + t.toString() + "</p><html>", i18n.getString("Main.Error"),
                    JOptionPane.ERROR_MESSAGE);
            log.error(t, t);
        }
        return new TSPPlan[0];
    }

    private TSPPlan[] processFile(File file, JProgressBar progressbar) {
        try {
            LinkedList<TSPPlan> res = new LinkedList<TSPPlan>();
            BufferedReader br = new BufferedReader(new FileReader(file));
            String line;
            int i = 0;
            TSPPlan plan = new TSPPlan();

            while ((line = br.readLine()) != null) {
                log.trace(line);
                progressbar.setValue(i++);

                if (!line.isEmpty())
                    plan.addStops(line);
                else {
                    res.add(plan);
                    plan = new TSPPlan();
                }
            }
            res.add(plan);
            return res.toArray(new TSPPlan[0]);
        } catch (Throwable e) {
            log.error("Error processing file", e);
        }
        return null;
    }

    private int getNumberLines(File f) {
        LineNumberReader lineCounter;
        try {
            lineCounter = new LineNumberReader(new InputStreamReader(new FileInputStream(f.getPath())));

            while (lineCounter.readLine() != null)
                ;
            return lineCounter.getLineNumber();
        } catch (Exception done) {
            log.error(done, done);
            return -1;
        }

    }

    @Override
    protected JPopupMenu getContextMenu() {
        JPopupMenu menu = new JPopupMenu();

        menu.setBackground(Color.decode("#E8EDF6"));

        String mapMenuTituloPlanning = i18n.getString("map.menu.titulo.planning");
        String mapMenuNewPlanning = i18n.getString("map.menu.new.planning");
        // Ttulo
        final JMenuItem titulo = new JMenuItem(mapMenuTituloPlanning);
        titulo.setFont(LogicConstants.deriveBoldFont(10.0f));
        titulo.setBackground(Color.decode("#A4A4A4"));
        titulo.setFocusable(false);

        menu.add(titulo);

        // New Planning
        final JMenuItem to = new JMenuItem(mapMenuNewPlanning, KeyEvent.VK_F6);
        to.setIcon(LogicConstants.getIcon("menucontextual_icon_destinoruta"));
        to.addActionListener(this);
        menu.add(to);

        menu.addSeparator();

        return menu;
    }

    @Override
    protected void initializeLayers() {
        super.initializeLayers();
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void updateControls() {
        if (Authentication.isAuthenticated()) {
            controlPanel.setAvaliableResources(
                    Collections.synchronizedCollection(RecursoConsultas.getAll(Authentication.getUsuario())));
            controlPanel
                    .setAvaliableIncidences(Collections.synchronizedCollection(IncidenciaConsultas.getOpened()));
        }
    }

}

class RoutingFilter extends FileFilter {

    // gfr, GoFleetRouting
    @Override
    public boolean accept(File arg0) {
        return arg0.getName().endsWith(".gfr");
    }

    @Override
    public String getDescription() {
        return "GoFleet Routing files.";
    }

}