sk.stuba.fiit.kvasnicka.qsimsimulation.rule.SimulationRuleBean.java Source code

Java tutorial

Introduction

Here is the source code for sk.stuba.fiit.kvasnicka.qsimsimulation.rule.SimulationRuleBean.java

Source

/*******************************************************************************
 * This file is part of qSim.
 *
 * qSim 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 3 of the License, or
 * (at your option) any later version.
 *
 * qSim 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 qSim.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sk.stuba.fiit.kvasnicka.qsimsimulation.rule;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import sk.stuba.fiit.kvasnicka.qsimdatamodel.data.NetworkNode;
import sk.stuba.fiit.kvasnicka.qsimdatamodel.data.utils.PacketCreationDelayFunction;
import sk.stuba.fiit.kvasnicka.qsimsimulation.enums.IpPrecedence;
import sk.stuba.fiit.kvasnicka.qsimsimulation.enums.Layer4TypeEnum;
import sk.stuba.fiit.kvasnicka.qsimsimulation.events.packet.PacketDeliveredEvent;
import sk.stuba.fiit.kvasnicka.qsimsimulation.events.packet.PacketDeliveredListener;
import sk.stuba.fiit.kvasnicka.qsimsimulation.events.ping.PingPacketDeliveredEvent;
import sk.stuba.fiit.kvasnicka.qsimsimulation.events.ping.PingPacketDeliveredListener;
import sk.stuba.fiit.kvasnicka.qsimsimulation.exceptions.RoutingException;
import sk.stuba.fiit.kvasnicka.qsimsimulation.qos.classification.utils.dscp.DscpValuesEnum;

import javax.swing.event.EventListenerList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * this bean represents user definition of a simulation rule
 * this bean has got equals/hash code properly overridden, so it can be a key in hash map/set
 *
 * @author Igor Kvasnicka
 */
@Getter
@EqualsAndHashCode(of = "uniqueID")
public class SimulationRuleBean {

    private final String uniqueID;

    @Setter
    private boolean active;
    private NetworkNode source;
    private NetworkNode destination;
    /**
     * simulation time when this rule became active
     */
    @Setter
    private double activationTime; //(msec)
    /**
     * number of packets yet to create - this field changes
     *
     * @see #decreaseNumberOfPackets()
     */
    private int numberOfPackets;
    private int packetSize;

    /**
     * here is a "routing table" for this simulation rule
     * this means, that multiple simulation rules may have contradictory routing,
     * e.g: A-B-C-D and A-X-C-Y-D (the same source, destination and one network node in the middle)
     * this also allows to create new simulation rules at runtime (e.g. "ping") without affecting other routing tables
     */
    private Map<NetworkNode, NetworkNode> routes;//key=current network node; value=next hop network node
    private Layer4TypeEnum layer4Type;
    @Getter
    private List<NetworkNode> route;
    @Getter
    private String name;
    @Getter
    private IpPrecedence ipPrecedence;
    @Getter
    private DscpValuesEnum dscpValue;

    @Getter
    private int srcPort;
    @Getter
    private int destPort;
    @Setter
    private double creationTimeSaved = 0;

    @Getter
    /**
     * this is a flag that is used mainly (only) for ping - ping simulation rule may be active, but when a packet did not finish its round-trip, no new packet
     * can be created
     */
    private boolean canCreateNewPacket = true;

    @Getter
    private PacketCreationDelayFunction packetCreationDelayFunction;

    /**
     * list of all who wants to be notified, when packet is delivered
     * especially useful when waiting for a ping to be delivered
     */
    private transient javax.swing.event.EventListenerList listenerList = new javax.swing.event.EventListenerList();

    /**
     * creates new simulation rule
     * all arguments are self-explained
     * <p/>
     * do not forget to set route
     * <p/>
     *
     * @param id              if null or empty, it will be generated
     * @param source
     * @param destination
     * @param numberOfPackets
     * @param packetSize
     * @param activeDelay
     * @param srcPort
     * @param destPort
     * @see #setRoute(java.util.List)
     */
    public SimulationRuleBean(String id, String name, NetworkNode source, NetworkNode destination,
            PacketCreationDelayFunction packetCreationDelayFunction, int numberOfPackets, int packetSize,
            double activeDelay, Layer4TypeEnum layer4Type, IpPrecedence ipPrecedence, DscpValuesEnum dscpValue,
            int srcPort, int destPort) {
        if ((dscpValue != null) && (ipPrecedence != null)) {
            throw new IllegalArgumentException("DSCP and IP ToS must not be sent both");
        }
        if (StringUtils.isEmpty(id)) {
            uniqueID = UUID.randomUUID().toString();
        } else {
            uniqueID = id;
        }
        this.packetCreationDelayFunction = packetCreationDelayFunction;
        this.name = name;
        this.activationTime = activeDelay;
        this.layer4Type = layer4Type;
        this.ipPrecedence = ipPrecedence;
        this.dscpValue = dscpValue;
        this.srcPort = srcPort;
        this.destPort = destPort;
        this.active = false;
        this.source = source;
        this.destination = destination;
        this.numberOfPackets = numberOfPackets;
        this.packetSize = packetSize;
        routes = new HashMap<NetworkNode, NetworkNode>();
    }

    public SimulationRuleBean(String name, NetworkNode source, NetworkNode destination,
            PacketCreationDelayFunction packetCreationDelayFunction, int numberOfPackets, int packetSize,
            double activeDelay, Layer4TypeEnum layer4Type, IpPrecedence ipPrecedence, DscpValuesEnum dscpValue,
            int srcPort, int destPort) {
        this("", name, source, destination, packetCreationDelayFunction, numberOfPackets, packetSize, activeDelay,
                layer4Type, ipPrecedence, dscpValue, srcPort, destPort);
    }

    public void setCanCreateNewPacket(boolean canCreateNewPacket) {
        if (!isPing())
            throw new IllegalStateException("Only ping simulation rules can change this property!");
        this.canCreateNewPacket = canCreateNewPacket;
    }

    /**
     * determines, if it is a ping simulation rule
     *
     * @return
     */
    public boolean isPing() {
        return layer4Type == Layer4TypeEnum.ICMP;
    }

    public void decreaseNumberOfPackets() {
        if (numberOfPackets == -1)
            return; //-1 is infinity
        numberOfPackets--;
    }

    /**
     * sometimes simulation rule needs more time quantums to be finished
     *
     * @param timeQuantum
     */
    public void increaseActivationTime(double timeQuantum) {
        activationTime += timeQuantum;
    }

    public boolean isFinished() {
        return numberOfPackets == 0;
    }

    /**
     * forces simulation rule to send on 1 packet
     */
    public void resetNumberOfPacketsToOne() {
        if (numberOfPackets == -1)
            return;
        numberOfPackets = 1;
    }

    /**
     * clears the routing table however directly connected routes MUST be
     * persisted
     */
    public void clearRoutingTable() {
        routes.clear();
    }

    /**
     * adds new routing rule (new route) to routing table
     * route must consist of at least 2 network nodes: source and destination
     *
     * @param route list of network nodes in which packet will be routed
     */
    public void setRoute(List<NetworkNode> route) {
        if (route == null)
            throw new IllegalArgumentException("route is NULL");
        if (route.size() < 2) {
            throw new IllegalArgumentException(
                    "route must consist of at least 2 network nodes: source and destination; this route is long: "
                            + route.size());
        }
        this.route = route;

        routes.clear();

        //routes from node1 to node2....
        for (int i = 0; i < route.size() - 1; i++) {
            routes.put(route.get(i), route.get(i + 1));
        }
    }

    public NetworkNode getNextHopFromRoutingTable(NetworkNode currentNode) {
        if (!routes.containsKey(currentNode)) {
            throw new IllegalStateException(
                    "cannot find route for destination: " + getDestination() + " from " + currentNode);
        }
        return routes.get(currentNode);
    }

    /**
     * finds network node that was previous hop
     *
     * @param currentNode network node, where packet is currently placed
     * @return previous network node
     */
    public NetworkNode getPreviousHopFromRoutingTable(NetworkNode currentNode) throws RoutingException {
        if (!routes.containsValue(currentNode)) {
            throw new RoutingException("cannot find previous network node for: " + currentNode);
        }
        for (NetworkNode node : routes.keySet()) {
            if (routes.get(node).equals(currentNode)) {//this is the route I came here
                return node;
            }
        }
        throw new IllegalStateException(
                "node I am looking for is in the routing table, but I cannot find it: " + currentNode);
    }

    public void addPingPacketDeliveredListener(PingPacketDeliveredListener listener) {
        listenerList.add(PingPacketDeliveredListener.class, listener);
    }

    public void removePingPacketDeliveredListener(PingPacketDeliveredListener listener) {
        listenerList.remove(PingPacketDeliveredListener.class, listener);
    }

    public void firePingPacketDeliveredEvent(PingPacketDeliveredEvent evt) {
        Object[] listeners = listenerList.getListenerList();
        for (int i = 0; i < listeners.length; i += 2) {
            if (listeners[i].equals(PingPacketDeliveredListener.class)) {
                ((PingPacketDeliveredListener) listeners[i + 1]).pingPacketDeliveredOccurred(evt);
            }
        }
    }

    public void addPacketDeliveredListener(PacketDeliveredListener listener) {
        listenerList.add(PacketDeliveredListener.class, listener);
    }

    public void removePacketDeliveredListener(PacketDeliveredListener listener) {
        listenerList.remove(PacketDeliveredListener.class, listener);
    }

    public void firePacketDeliveredEvent(PacketDeliveredEvent evt) {
        Object[] listeners = listenerList.getListenerList();
        for (int i = 0; i < listeners.length; i += 2) {
            if (listeners[i].equals(PacketDeliveredListener.class)) {
                ((PacketDeliveredListener) listeners[i + 1]).packetDeliveredOccurred(evt);
            }
        }
    }

    /**
     * removes all delivery listeners
     */
    public void removeAllDeliveryListeners() {
        listenerList = new EventListenerList(); //listenerList cannot remove all listeners, so I simply create a new object instead...
    }
}