package de.tu_darmstadt.tk.SmartHomeNetworkSim.core; import java.util.Collection; import java.util.LinkedList; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Connection; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Link; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Packet; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.SmartDevice; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.util.PacketComparator; import java.util.ArrayList; /** * Simple Implementation of {@link Link}, which allows connection of multiple * devices, with an more precise calculation than {@link de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.SimpleLink} * * @author Andreas T. Meyer-Berg */ public class PrecisionLink implements Link { /** * Name of the connection */ private String name; /** * Devices connected by this Link */ private ArrayList devices; /** * Connections running via this Link */ private ArrayList connections; /** * List of packages to store packages sent during simulation intervals, or * after termination */ private LinkedList packets; /** * Packets which should be returned in the next time step */ private LinkedList outOfBoundsPackets = new LinkedList(); /** * whether the status changed during the last simulation step */ private boolean statusChanged; /** * Delay between two devices, fixed */ private long fixedDelay=3; /** * Initializes a simple Link with name and an empty devices list. * * @param name * Name the Link should have */ public PrecisionLink(String name) { this.name = name; this.devices = new ArrayList(); this.packets = new LinkedList(); this.connections = new ArrayList(); } /** * Initializes a simple Link with default name and an empty devices list. */ public PrecisionLink() { this.name = "link name"; this.devices = new ArrayList(); this.packets = new LinkedList(); this.connections = new ArrayList(); } /** * Returns the name of this Link * * @return name of this Link */ public String getName() { return name; } /** * Sets the name of this Link * * @param name * the name to set */ public void setName(String name) { this.name = name; } /** * Returns the device that are part of this connection * * @return the devices of this Link */ public Collection getDevices() { return devices; } /** * Adds the SmartDevice to this Link * * @param device * the devices to add */ public void addDevice(SmartDevice device) { this.devices.add(device); } /** * Remove SmartDevice from this Link * * @param device * the device to remove */ public void removeDevice(SmartDevice device) { this.devices.remove(device); } @Override public void simulateTimeInterval(long startTime, long duration) { packets.clear(); statusChanged = false; packets.addAll(outOfBoundsPackets); for (Connection c : connections) { if (c.getLink() != this) continue; // Simulate just if source and link match if ((c.getStatus() == Connection.ACTIVE || c.getStatus() == Connection.HALTED)) packets.addAll(c.simulateTimeInterval(startTime, duration)); else if (c.getStatus() == Connection.FINISHED || c.getStatus() == Connection.TERMINATED) //Produce Termination packages packets.addAll(c.getTerminationPackages(startTime)); statusChanged|=c.getStatusChanged(); } packets.sort(new PacketComparator()); /** * Remove packets which are not being sent in this time interval */ outOfBoundsPackets.clear(); /** * Last package, which should be sent in the next time step */ Packet last = packets.isEmpty()? null : packets.getLast(); while (last != null&&last.getTimestamp()>startTime+duration) { outOfBoundsPackets.addFirst(packets.removeLast()); if(packets.isEmpty()) break; last = packets.getLast(); } } @Override public Collection encapsulatePackages(Collection packets){ return packets; } @Override public Collection getPackets() { return packets; } @Override public Collection getConnections() { return connections; } @Override public void addConnection(Connection connection) { connections.add(connection); } @Override public void removeConnection(Connection connection) { connections.remove(connection); } @Override public boolean getStatusChanged() { return statusChanged; } @Override public long getTransmissionDelayFrom(SmartDevice from, SmartDevice to) { return fixedDelay; } /** * Set the delay of this Link * @param delay fixed transmission delay */ public void setFixedDelay(long delay){ this.fixedDelay = delay; } /** * Returns the fixed transmission delay * @return transmission delay */ public long getFixedDelay(){ return this.fixedDelay; } @Override public void addPackets(Collection packets) { this.packets.addAll(packets); } @Override public void initSimulationInterval(long startTime, long duration) { /** * Reset packets */ packets.clear(); /** * Add out of Bounds packets */ packets.addAll(outOfBoundsPackets); } @Override public void finalizeSimulationInterval(long startTime, long duration) { //Remove out of Bounds Packets /** * Remove packets which are not being sent in this time interval */ outOfBoundsPackets.clear(); /** * Last package, which should be sent in the next time step */ Packet last = packets.isEmpty()? null : packets.getLast(); while (last != null&&last.getTimestamp()>startTime+duration) { outOfBoundsPackets.addFirst(packets.removeLast()); if(packets.isEmpty()) break; last = packets.getLast(); } } }