Package ch.rakudave.jnetmap.model

Source Code of ch.rakudave.jnetmap.model.Map

package ch.rakudave.jnetmap.model;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import ch.rakudave.jnetmap.controller.Scheduler;
import ch.rakudave.jnetmap.controller.command.Command;
import ch.rakudave.jnetmap.controller.command.CommandHistory;
import ch.rakudave.jnetmap.model.MapEvent.Type;
import ch.rakudave.jnetmap.model.IF.LogicalIF;
import ch.rakudave.jnetmap.model.IF.NetworkIF;
import ch.rakudave.jnetmap.model.IF.PhysicalIF;
import ch.rakudave.jnetmap.model.IF.TransparentIF;
import ch.rakudave.jnetmap.model.device.Device;
import ch.rakudave.jnetmap.model.device.DeviceEvent;
import ch.rakudave.jnetmap.model.device.DeviceListener;
import ch.rakudave.jnetmap.plugins.Notifier;
import ch.rakudave.jnetmap.util.Crypto;
import ch.rakudave.jnetmap.util.IO;
import ch.rakudave.jnetmap.util.Lang;
import ch.rakudave.jnetmap.util.Settings;
import ch.rakudave.jnetmap.util.SkippingCollectionConverter;
import ch.rakudave.jnetmap.util.XStreamHelper;
import ch.rakudave.jnetmap.util.logging.Logger;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamOmitField;

import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.algorithms.layout.StaticLayout;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.MultiGraph;
import edu.uci.ics.jung.graph.SparseMultigraph;
import edu.uci.ics.jung.graph.util.EdgeType;
import edu.uci.ics.jung.graph.util.Pair;

/**
* @author rakudave
*/
@XStreamAlias("Map")
public class Map implements MultiGraph<Device, Connection>, Graph<Device, Connection>, DeviceListener {
  private Map _this = this;
  @XStreamOmitField
  private File mapFile;
  @XStreamOmitField
  private String password = "";
  @XStreamOmitField
  private CommandHistory history;
  private int updateInterval = 5;
  private Graph<Device, Connection> graph;
  private Layout<Device, Connection> layout;
  @XStreamOmitField
  private List<MapListener> mapListeners;
  @XStreamConverter(SkippingCollectionConverter.class)
  private List<Notifier> statusListeners;
 
  public Map() {
    history = new CommandHistory(Settings.getInt("commandhistory.size", 20));
    graph = new SparseMultigraph<Device, Connection>();
    layout = new StaticLayout<Device, Connection>(this);
    mapListeners = new LinkedList<MapListener>();
    statusListeners = new LinkedList<Notifier>();
  }
 
  public boolean addMapListener(MapListener listener) {
    if (listener == null) return false;
    if (mapListeners == null) mapListeners = new LinkedList<MapListener>();
    return mapListeners.add(listener);
  }
 
  public boolean removeMapListener(MapListener listener) {
    if (listener == null || mapListeners == null) return false;
    return mapListeners.remove(listener);
  }
 
  public boolean addStatusListener(Notifier listener) {
    if (listener == null) return false;
    if (statusListeners == null) statusListeners = new LinkedList<Notifier>();
    return statusListeners.add(listener);
  }
 
  public boolean removeStatusListener(Notifier listener) {
    if (listener == null || statusListeners == null) return false;
    return statusListeners.remove(listener);
  }
 
  public List<Notifier> getStatusListeners() {
    return statusListeners;
  }
 
  private void notifyListeners(final MapEvent e) {
    Logger.trace("Received MapEvent "+e);
    for (MapListener l : mapListeners) {
      try {
        l.mapChanged(e);
      } catch (Exception ex) {
        Logger.error("Unable to notify MapListener "+l, ex);
      }
    }
    if (e.getType() == Type.DEVICE_EVENT) {
      Logger.trace("Received DeviceEvent "+e);
      Scheduler.execute(new Runnable() {
        @Override
        public void run() {
          DeviceEvent ev = (DeviceEvent) e.getSubject();
          if (ev.getType() == DeviceEvent.Type.STATUS_CHANGED
              || ev.getType() == DeviceEvent.Type.INTERFACE_STATUS_CHANGED) {
            for (Notifier l : statusListeners) {
              try {
                l.statusChanged(ev, _this);
              } catch (Exception e2) {
                Logger.error("Unable to notify StatusListener "+l, e2);
              }
            }
          }
        }
      });
    }
  }
 
  /* (non-Javadoc)
   * @see java.lang.Object#equals(java.lang.Object)
   */
  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    Map other = (Map) obj;
    if (mapFile == null || other.mapFile == null) {
        return false;
    } else {
      return mapFile.equals(other.mapFile);
    }
  }

  public String getFileName() {
    return (mapFile != null)?mapFile.getName().replace(".jnm", ""):Lang.getNoHTML("map.newmap");
  }

  public String getFilePath() {
    return (mapFile != null)?mapFile.getAbsolutePath():Lang.getNoHTML("map.unsaved");
  }
 
  public Layout<Device, Connection> getGraphLayout() {
    return layout;
  }

  /**
   * @return the history
   */
  public CommandHistory getHistory() {
    if (history == null) history = new CommandHistory(Settings.getInt("commandhistory.size", 20));
    return history;
  }

  /* (non-Javadoc)
   * @see java.lang.Object#hashCode()
   */
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((graph == null) ? 0 : graph.hashCode());
    result = prime * result + ((mapFile == null) ? 0 : mapFile.hashCode());
    return result;
  }
 
  public boolean isSaved() {
    return getHistory().isSaved();
  }
 
  public boolean save() {
    XStream xs = XStreamHelper.getXStream();
    try {
      String xml = xs.toXML(this);
      if (password != null && !password.isEmpty()) {
        xml = Crypto.encrypt(xml, password);
      }
      IO.copy(new ByteArrayInputStream(xml.getBytes("UTF-8")), new FileOutputStream(mapFile));
      getHistory().setSaved(true);
      return true;
    } catch (Exception e) {
      Logger.error("unable to save map to " + mapFile, e);
      return false;
    }
  }

  public boolean setFile(File f) {
    if (f != null && f.exists() && f.canWrite()) {
      mapFile = f.getAbsoluteFile();
      return true;
    } else {
      return false;
    }
  }
 
  public void setLayout(Layout<Device, Connection> layout) {
    if (layout != null) this.layout = layout;
  }
 
  // Delegate-Methods

  /**
   * @param arg0
   * @param arg1
   * @param arg2
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#addEdge(java.lang.Object, java.util.Collection, edu.uci.ics.jung.graph.util.EdgeType)
   */
  public boolean addEdge(final Connection arg0, final Collection<? extends Device> arg1, final EdgeType arg2) {
    return addEdge(arg0, arg1); //ignore EdgeType, is always UNDIRECTED
  }

  /**
   * @param arg0
   * @param arg1
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#addEdge(java.lang.Object, java.util.Collection)
   */
  public boolean addEdge(final Connection arg0, final Collection<? extends Device> arg1) {
    return (Boolean) getHistory().execute(new Command() {
      @Override
      public Object undo() {
        boolean b = graph.removeEdge(arg0);
        notifyListeners(new MapEvent(_this, Type.EDGE_REMOVED, arg0));
        return b;
      }
     
      @Override
      public Object redo() {
        boolean b = graph.addEdge(arg0, arg1);
        notifyListeners(new MapEvent(_this, Type.EDGE_ADDED, arg0));
        return b;
      }
    });
  }

  /**
   * @param arg0
   * @param arg1
   * @param arg2
   * @param arg3
   * @return
   * @see edu.uci.ics.jung.graph.Graph#addEdge(java.lang.Object, java.lang.Object, java.lang.Object, edu.uci.ics.jung.graph.util.EdgeType)
   */
  public boolean addEdge(final Connection arg0, final Device arg1, final Device arg2, EdgeType arg3) {
    return addEdge(arg0, arg1, arg2); // ignore EdgeType, is always UNDIRECTED
  }

  /**
   * @param arg0
   * @param arg1
   * @param arg2
   * @return
   * @see edu.uci.ics.jung.graph.Graph#addEdge(java.lang.Object, java.lang.Object, java.lang.Object)
   */
  public boolean addEdge(final Connection arg0, final Device arg1, final Device arg2) {
    return (Boolean) getHistory().execute(new Command() {
      @Override
      public Object undo() {
        arg1.removeInterface(arg1.getInterfaceFor(arg0));
        arg2.removeInterface(arg2.getInterfaceFor(arg0));
        boolean b = graph.removeEdge(arg0);
        notifyListeners(new MapEvent(_this, Type.EDGE_REMOVED, arg0));
        return b;
      }
     
      @Override
      public Object redo() {
        addInterfaceIfMissing(arg0, arg1, arg2);
        addInterfaceIfMissing(arg0, arg2, arg1);
        boolean b = graph.addEdge(arg0, arg1, arg2);
        notifyListeners(new MapEvent(_this, Type.EDGE_ADDED, arg0));
        return b;
      }
    });
  }
 
  private void addInterfaceIfMissing(Connection arg0, Device arg1, Device arg2) {
    if (arg1.getInterfaceFor(arg0) == null) {
      if (arg1.equals(arg2)) {
        arg1.addInterface(new LogicalIF(arg1, arg0, ""));
      } else {
        String t = arg1.getType().toString() + "";
        NetworkIF nif;
        if (t.contains("Switch") || t.contains("Hub") || t.contains("Wireless")) {
          nif = new TransparentIF(arg1, arg0, arg2.getInterfaceFor(arg0));
        } else {
          nif = new PhysicalIF(arg1, arg0, "");
        }
        arg1.addInterface(nif);
        NetworkIF counterpart = arg2.getInterfaceFor(arg0);
        if (counterpart != null && counterpart instanceof TransparentIF) {
          ((TransparentIF) counterpart).setCounterpart(nif);
        }
      }
    }
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#addVertex(java.lang.Object)
   */
  public boolean addVertex(final Device arg0) {
    return (Boolean) getHistory().execute(new Command() {
      @Override
      public Object undo() {
        boolean b = graph.removeVertex(arg0);
        notifyListeners(new MapEvent(_this, Type.VERTEX_REMOVED, arg0));
        arg0.removeDeviceListener(_this);
        return b;
      }
     
      @Override
      public Object redo() {
        boolean b = graph.addVertex(arg0);
        notifyListeners(new MapEvent(_this, Type.VERTEX_ADDED, arg0));
        arg0.addDeviceListener(_this);
        return b;
      }
    });
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#containsEdge(java.lang.Object)
   */
  public boolean containsEdge(Connection arg0) {
    return graph.containsEdge(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#containsVertex(java.lang.Object)
   */
  public boolean containsVertex(Device arg0) {
    return graph.containsVertex(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#degree(java.lang.Object)
   */
  public int degree(Device arg0) {
    return graph.degree(arg0);
  }

  /**
   * @param arg0
   * @param arg1
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#findEdge(java.lang.Object, java.lang.Object)
   */
  public Connection findEdge(Device arg0, Device arg1) {
    return graph.findEdge(arg0, arg1);
  }

  /**
   * @param arg0
   * @param arg1
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#findEdgeSet(java.lang.Object, java.lang.Object)
   */
  public Collection<Connection> findEdgeSet(Device arg0, Device arg1) {
    return graph.findEdgeSet(arg0, arg1);
  }

  /**
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#getDefaultEdgeType()
   */
  public EdgeType getDefaultEdgeType() {
    return graph.getDefaultEdgeType();
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Graph#getDest(java.lang.Object)
   */
  public Device getDest(Connection arg0) {
    return graph.getDest(arg0);
  }

  /**
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#getEdgeCount()
   */
  public int getEdgeCount() {
    return graph.getEdgeCount();
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#getEdgeCount(edu.uci.ics.jung.graph.util.EdgeType)
   */
  public int getEdgeCount(EdgeType arg0) {
    return graph.getEdgeCount(arg0);
  }

  /**
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#getEdges()
   */
  public Collection<Connection> getEdges() {
    return graph.getEdges();
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#getEdges(edu.uci.ics.jung.graph.util.EdgeType)
   */
  public Collection<Connection> getEdges(EdgeType arg0) {
    return graph.getEdges(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#getEdgeType(java.lang.Object)
   */
  public EdgeType getEdgeType(Connection arg0) {
    return graph.getEdgeType(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Graph#getEndpoints(java.lang.Object)
   */
  public Pair<Device> getEndpoints(Connection arg0) {
    return graph.getEndpoints(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentCount(java.lang.Object)
   */
  public int getIncidentCount(Connection arg0) {
    return graph.getIncidentCount(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentEdges(java.lang.Object)
   */
  public Collection<Connection> getIncidentEdges(Device arg0) {
    return graph.getIncidentEdges(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentVertices(java.lang.Object)
   */
  public Collection<Device> getIncidentVertices(Connection arg0) {
    return graph.getIncidentVertices(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Graph#getInEdges(java.lang.Object)
   */
  public Collection<Connection> getInEdges(Device arg0) {
    return graph.getInEdges(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#getNeighborCount(java.lang.Object)
   */
  public int getNeighborCount(Device arg0) {
    return graph.getNeighborCount(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#getNeighbors(java.lang.Object)
   */
  public Collection<Device> getNeighbors(Device arg0) {
    return graph.getNeighbors(arg0);
  }

  /**
   * @param arg0
   * @param arg1
   * @return
   * @see edu.uci.ics.jung.graph.Graph#getOpposite(java.lang.Object, java.lang.Object)
   */
  public Device getOpposite(Device arg0, Connection arg1) {
    return graph.getOpposite(arg0, arg1);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Graph#getOutEdges(java.lang.Object)
   */
  public Collection<Connection> getOutEdges(Device arg0) {
    return graph.getOutEdges(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Graph#getPredecessorCount(java.lang.Object)
   */
  public int getPredecessorCount(Device arg0) {
    return graph.getPredecessorCount(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Graph#getPredecessors(java.lang.Object)
   */
  public Collection<Device> getPredecessors(Device arg0) {
    return graph.getPredecessors(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Graph#getSource(java.lang.Object)
   */
  public Device getSource(Connection arg0) {
    return graph.getSource(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Graph#getSuccessorCount(java.lang.Object)
   */
  public int getSuccessorCount(Device arg0) {
    return graph.getSuccessorCount(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Graph#getSuccessors(java.lang.Object)
   */
  public Collection<Device> getSuccessors(Device arg0) {
    return graph.getSuccessors(arg0);
  }

  /**
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#getVertexCount()
   */
  public int getVertexCount() {
    return graph.getVertexCount();
  }

  /**
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#getVertices()
   */
  public Collection<Device> getVertices() {
    return graph.getVertices();
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Graph#inDegree(java.lang.Object)
   */
  public int inDegree(Device arg0) {
    return graph.inDegree(arg0);
  }

  /**
   * @param arg0
   * @param arg1
   * @return
   * @see edu.uci.ics.jung.graph.Graph#isDest(java.lang.Object, java.lang.Object)
   */
  public boolean isDest(Device arg0, Connection arg1) {
    return graph.isDest(arg0, arg1);
  }

  /**
   * @param arg0
   * @param arg1
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#isIncident(java.lang.Object, java.lang.Object)
   */
  public boolean isIncident(Device arg0, Connection arg1) {
    return graph.isIncident(arg0, arg1);
  }

  /**
   * @param arg0
   * @param arg1
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#isNeighbor(java.lang.Object, java.lang.Object)
   */
  public boolean isNeighbor(Device arg0, Device arg1) {
    return graph.isNeighbor(arg0, arg1);
  }

  /**
   * @param arg0
   * @param arg1
   * @return
   * @see edu.uci.ics.jung.graph.Graph#isPredecessor(java.lang.Object, java.lang.Object)
   */
  public boolean isPredecessor(Device arg0, Device arg1) {
    return graph.isPredecessor(arg0, arg1);
  }

  /**
   * @param arg0
   * @param arg1
   * @return
   * @see edu.uci.ics.jung.graph.Graph#isSource(java.lang.Object, java.lang.Object)
   */
  public boolean isSource(Device arg0, Connection arg1) {
    return graph.isSource(arg0, arg1);
  }

  /**
   * @param arg0
   * @param arg1
   * @return
   * @see edu.uci.ics.jung.graph.Graph#isSuccessor(java.lang.Object, java.lang.Object)
   */
  public boolean isSuccessor(Device arg0, Device arg1) {
    return graph.isSuccessor(arg0, arg1);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Graph#outDegree(java.lang.Object)
   */
  public int outDegree(Device arg0) {
    return graph.outDegree(arg0);
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#removeEdge(java.lang.Object)
   */
  public boolean removeEdge(final Connection arg0) {
    return (Boolean) getHistory().execute(new Command() {
      private Pair<Device> arg1 = getEndpoints(arg0);
      @Override
      public Object undo() {
        if (arg1.getFirst() != null) arg1.getFirst().addInterface(arg1.getFirst().getInterfaceFor(arg0));
        if (arg1.getSecond() != null) arg1.getSecond().addInterface(arg1.getSecond().getInterfaceFor(arg0));
        boolean b = graph.addEdge(arg0, arg1);
        notifyListeners(new MapEvent(_this, Type.EDGE_ADDED, arg0));
        return b;
      }
     
      @Override
      public Object redo() {
        if (arg1.getFirst() != null) arg1.getFirst().removeInterface(arg1.getFirst().getInterfaceFor(arg0));
        if (arg1.getSecond() != null) arg1.getSecond().removeInterface(arg1.getSecond().getInterfaceFor(arg0));
        boolean b = graph.removeEdge(arg0);
        notifyListeners(new MapEvent(_this, Type.EDGE_REMOVED, arg0));
        return b;
      }
    });
  }

  /**
   * @param arg0
   * @return
   * @see edu.uci.ics.jung.graph.Hypergraph#removeVertex(java.lang.Object)
   */
  public boolean removeVertex(final Device arg0) {
    return (Boolean) getHistory().execute(new Command() {
      HashMap<Pair<Device>, Connection> connectors = new HashMap<Pair<Device>, Connection>();
      HashMap<Connection, NetworkIF> oppositeIFs = new HashMap<Connection, NetworkIF>();
     
      @Override
      public Object undo() {
        boolean b = graph.addVertex(arg0);
        for (Pair<Device> p : connectors.keySet()) {
          Connection c = connectors.get(p);
          graph.addEdge(c, p);
          Device other = (p.getFirst().equals(arg0))?p.getSecond():p.getFirst();
          other.addInterface(oppositeIFs.get(c));
        }
        notifyListeners(new MapEvent(_this, Type.VERTEX_ADDED, arg0));
        arg0.addDeviceListener(_this);
        return b;
      }
     
      @Override
      public Object redo() {
        for (Connection c : graph.getOutEdges(arg0)) {
          Pair<Device> pair = graph.getEndpoints(c);
          connectors.put(pair, c);
          Device other = (pair.getFirst().equals(arg0))?pair.getSecond():pair.getFirst();
          NetworkIF nif = other.getInterfaceFor(c);
          oppositeIFs.put(c, nif);
          other.removeInterface(nif);
        }
        boolean b = graph.removeVertex(arg0);
        notifyListeners(new MapEvent(_this, Type.VERTEX_REMOVED, arg0));
        arg0.removeDeviceListener(_this);
        return b;
      }
    });
  }

  @Override
  public void deviceChanged(DeviceEvent e) {
    notifyListeners(new MapEvent(this, Type.DEVICE_EVENT, e));
  }

  public void setPassword(String password) {
    if (password == null) return;
    this.password = password;
  }

  public String getPassword() {
    return password;
  }

  public void setUpdateInterval(int updateInterval) {
    if (updateInterval <= 0) return;
    this.updateInterval = updateInterval;
  }

  public int getUpdateInterval() {
    return updateInterval;
  }
 
  public void refreshView() {
    notifyListeners(new MapEvent(this, Type.REFRESH, null));
  }
}

  
TOP

Related Classes of ch.rakudave.jnetmap.model.Map

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.