001    /**
002     *  "TRMSim-WSN, Trust and Reputation Models Simulator for Wireless 
003     * Sensor Networks" is free software: you can redistribute it and/or 
004     * modify it under the terms of the GNU Lesser General Public License
005     * as published by the Free Software Foundation, either version 3 of 
006     * the License, or (at your option) any later version always keeping 
007     * the additional terms specified in this license.
008     *
009     * This program is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012     * GNU Lesser General Public License for more details.
013     * 
014     * 
015     * Additional Terms of this License
016     * --------------------------------
017     * 
018     * 1. It is Required the preservation of specified reasonable legal notices
019     *   and author attributions in that material and in the Appropriate Legal
020     *   Notices displayed by works containing it.
021     * 
022     * 2. It is limited the use for publicity purposes of names of licensors or
023     *   authors of the material.
024     * 
025     * 3. It is Required indemnification of licensors and authors of that material
026     *   by anyone who conveys the material (or modified versions of it) with
027     *   contractual assumptions of liability to the recipient, for any liability
028     *   that these contractual assumptions directly impose on those licensors
029     *   and authors.
030     * 
031     * 4. It is Prohibited misrepresentation of the origin of that material, and it is
032     *   required that modified versions of such material be marked in reasonable
033     *   ways as different from the original version.
034     * 
035     * 5. It is Declined to grant rights under trademark law for use of some trade
036     *   names, trademarks, or service marks.
037     * 
038     * You should have received a copy of the GNU Lesser General Public License
039     * along with this program (lgpl.txt).  If not, see <http://www.gnu.org/licenses/>
040    */
041    
042    package es.ants.felixgm.trmsim_wsn.network;
043    
044    import es.ants.felixgm.trmsim_wsn.search.ISearchCondition;
045    import es.ants.felixgm.trmsim_wsn.search.IsClientSearchCondition;
046    import es.ants.felixgm.trmsim_wsn.search.IsServerSearchCondition;
047    import java.io.BufferedWriter;
048    import java.io.File;
049    import java.io.FileWriter;
050    
051    import java.util.Iterator;
052    import java.util.Collection;
053    import java.util.ArrayList;
054    
055    import java.util.Vector;
056    import javax.xml.parsers.DocumentBuilder;
057    import javax.xml.parsers.DocumentBuilderFactory;
058    
059    import org.w3c.dom.Document;
060    import org.w3c.dom.NamedNodeMap;
061    import org.w3c.dom.NodeList;
062    
063    /**
064     * <p>This class models a P2P, Ad-hoc or Wireless Sensor Network, or even a
065     * multi-agent system.</p>
066     * <p>It is composed of several clients requesting services and servers offering services</p>
067     * <p><a name="xmlFileStructure"></a>The constructor
068     * {@link #Network Network}
069     * requires a XML file following the next structure:</p>
070     * <pre>
071     *    &lt;?xml version="1.0" encoding="UTF-8"?&gt;
072     *    &lt;wsn&gt;
073     *        &lt;client id="1" x="30.5" y="56.2"&gt;
074     *            &lt;server id="2"/&gt;
075     *            &lt;server id="3"/&gt;
076     *        &lt;/client&gt;
077     *        &lt;client id="7" x="10.3" y="26.4"&gt;
078     *            &lt;server id="4"/&gt;
079     *            &lt;server id="6"/&gt;
080     *        &lt;/client&gt;
081     *        &lt;server id="2" x="14.8" y="63.7"&gt;
082     *            &lt;service id="Relay" goodness="1.0"/&gt;
083     *            &lt;server id="4"/&gt;
084     *            &lt;server id="5"/&gt;
085     *            &lt;client id="1"/&gt;
086     *        &lt;/server&gt;
087     *        &lt;server id="3" x="29.7" y="73.7"&gt;
088     *            &lt;service id="Relay" goodness="1.0"/&gt;
089     *            &lt;service id="Service 1" goodness="0.05"/&gt;
090     *            &lt;server id="4"/&gt;
091     *        &lt;/server&gt;
092     *        &lt;server id="4" x="38.4" y="56.2"&gt;
093     *            &lt;service id="Relay" goodness="1.0"/&gt;
094     *            &lt;server id="6"/&gt;
095     *        &lt;/server&gt;
096     *        &lt;server id="5" x="95.6" y="36.8"&gt;
097     *            &lt;service id="Relay" goodness="1.0"/&gt;
098     *            &lt;service id="Service 1" goodness="0.12"/&gt;
099     *            &lt;server id="6"/&gt;
100     *            &lt;client id="7"/&gt;
101     *        &lt;/server&gt;
102     *        &lt;server id="6" x="53.5" y="97.4"&gt;
103     *            &lt;service id="Relay" goodness="1.0"/&gt;
104     *            &lt;service id="Service 1" goodness="0.98"/&gt;
105     *            &lt;server id="3"/&gt;
106     *        &lt;/server&gt;
107     *    &lt;/tacs&gt;
108     * </pre> 
109     * <p><a href="http://ants.dif.um.es/~felixgm/research/trmsim-wsn/resources/wsn1.xml" target=_blank">
110     * This file</a> represents the following network:</p>
111     * <img src="http://ants.dif.um.es/~felixgm/research/trmsim-wsn/img/wsn1.gif">
112     <font color="#FF0000">
113     <p><strong>A subclass of this class, modeling the specific network, has to be
114     implemented in order to add a new Trust and Reputation Model</strong></p>
115     </font>
116     * @author <a href="http://ants.dif.um.es/~felixgm/en" target="_blank">F&eacute;lix G&oacute;mez M&aacute;rmol</a>, <a href="http://webs.um.es/gregorio" target="_blank">Gregorio Mart&iacute;nez P&eacute;rez</a>
117     * @version 0.5
118     * @since 0.1
119     */
120    public abstract class Network {
121        /** Maximum distance between two nodes in the network */
122        protected static final double maxDistance = 100.0;
123        /** The clients requesting services */
124        protected Collection<Sensor> clients;
125        /** The servers offering services */
126        protected Collection<Sensor> servers;
127        /** All the sensors composing the network */
128        protected Collection<Sensor> sensors;
129        /** All the services offered by the network */
130        protected Collection<Service> services;
131        
132        /**
133         * This constructor creates a new Network from a given set of clients,
134         * servers and services
135         * @param clients The clients requesting services
136         * @param servers The servers offering services
137         * @param services All the services offered by the network
138         */
139        public Network(Collection<Sensor> clients, Collection<Sensor> servers, Collection<Service> services) {
140            this.clients = clients;
141            this.servers = servers;
142    
143            sensors = new ArrayList<Sensor>();
144            if (clients != null)
145                for (Sensor client : clients)
146                    sensors.add(client);
147            if (servers != null)
148                for (Sensor server : servers)
149                    sensors.add(server);
150    
151            this.services = services;
152        }
153    
154        /**
155         * This constructor creates a new random Network using the given parameters
156         * @param numSensors Number of sensors composing the network
157         * @param probClients Probability of a sensor to act as a client requesting services
158         * @param rangeFactor Maximum wireless range of every sensor. It determines the neighborhood of every sensor
159         * @param probServices A collection of probabilities of offering a certain service, one per service
160         * @param probGoodness A collection of goodnesses about offering a certain service, one per service
161         * @param services All the services offered by the generated Network
162         */
163        public Network(
164                int numSensors,
165                double probClients,
166                double rangeFactor,
167                Collection<Double> probServices,
168                Collection<Double> probGoodness,
169                Collection<Service> services) {
170            clients = new ArrayList<Sensor>();
171            servers = new ArrayList<Sensor>();
172            sensors = new ArrayList<Sensor>();
173            this.services = new ArrayList<Service>();
174    
175            Sensor.resetId();
176            Sensor.setMaxDistance(maxDistance);
177    
178            for (int i = 0; i < numSensors; i++) {
179                if (Math.random() <= probClients) {
180                    Sensor client = newSensor();
181                    clients.add(client);
182                    sensors.add(client);
183                } else {
184                    Sensor server = newSensor();
185                    servers.add(server);
186                    sensors.add(server);
187    
188                    Iterator<Double> itProbServices = probServices.iterator();
189                    Iterator<Double> itProbGoodness = probGoodness.iterator();
190                    for (Service service : services)
191                        if (Math.random() <= itProbServices.next().doubleValue()) {
192                            if (Math.random() <= itProbGoodness.next().doubleValue())
193                                server.addService(service, 1.0);
194                            else
195                                server.addService(service, 0.0);
196    
197                            if (!this.services.contains(service))
198                                this.services.add(service);
199                        }
200                }
201            }
202    
203            if (clients.size() == 0) {
204                Sensor client = newSensor();
205                clients.add(client);
206                sensors.add(client);
207            }
208    
209            // We are going to link the sensors in the network.
210            double rangeThreshold = rangeFactor*Math.sqrt(2.0)*maxDistance;
211            for (Sensor server : servers) {
212                for (Sensor client : clients)
213                    if (server.distance(client) < rangeThreshold) {
214                        client.addLink(server);
215                        server.addLink(client);
216                    }
217    
218                for (Sensor server2 : servers)
219                    if ((!server.equals(server2)) && (server.distance(server2) < rangeThreshold)) {
220                        server.addLink(server2);
221                        server2.addLink(server);
222                    }
223            }
224    
225            for (Sensor client1 : clients) {
226                for (Sensor client2 : clients)
227                    if ((!client1.equals(client2)) && (client1.distance(client2) < rangeThreshold)) {
228                        client1.addLink(client2);
229                        client2.addLink(client1);
230                    }
231    
232                for (Sensor server : servers)
233                    if (server.distance(client1) < rangeThreshold) {
234                        client1.addLink(server);
235                        server.addLink(client1);
236                    }
237            }
238        }
239    
240        /**
241         * <p>This method reads a Network from a XML file and builds its corresponding object</p>
242         * <p>The XML file given should have <a href="#xmlFileStructure">this structure</a></p>
243         * @param xmlFilePath Path of the XML file describing the Network to create
244         * @throws java.lang.Exception If the XML file given does not have the structure shown before, or if
245         * a node links to an undefined node, or if a node links to itself
246         */
247        public Network(String xmlFilePath) throws Exception {
248            if (!xmlFilePath.endsWith(".xml"))
249                throw new Exception("Only XML files are accepted");
250            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
251            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
252            Document doc = docBuilder.parse(new File(xmlFilePath));
253            doc.getDocumentElement().normalize();
254            org.w3c.dom.Node root = doc.getDocumentElement();
255            NodeList nodes = root.getChildNodes();
256    
257            clients = new ArrayList<Sensor>();
258            servers = new ArrayList<Sensor>();
259            sensors = new ArrayList<Sensor>();
260            services = new ArrayList<Service>();
261            Sensor.resetId();
262    
263            /*
264             * In the first parsing we create every client and server
265             * In the second one, all the links are eestablished
266             */
267            for (int i = 1; i < nodes.getLength(); i++) {
268                org.w3c.dom.Node node = nodes.item(i);
269                if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
270                    NamedNodeMap attributes = node.getAttributes();
271                    int id = Integer.parseInt(attributes.getNamedItem("id").getNodeValue());
272                    double x = Double.parseDouble(attributes.getNamedItem("x").getNodeValue());
273                    double y = Double.parseDouble(attributes.getNamedItem("y").getNodeValue());
274                    if (node.getNodeName().equals("client")) {
275                        Sensor client = newSensor(id, x, y);
276                        if (!clients.contains(client)) {
277                            clients.add(client);
278                            sensors.add(client);
279                        }
280                    } else if ((node.getNodeName().equals("server")) && (attributes != null)) {
281                        Sensor server = newSensor(id,x,y);
282    
283                        if (!servers.contains(server)) {
284                            servers.add(server);
285                            sensors.add(server);
286                        }
287    
288                        NodeList nodeChildren = node.getChildNodes();
289                        for (int j = 0; j < nodeChildren.getLength(); j++)
290                            if (nodeChildren.item(j).getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
291                                if (nodeChildren.item(j).getNodeName().equals("service")) {
292                                    double goodness = Double.parseDouble(nodeChildren.item(j).
293                                            getAttributes().getNamedItem("goodness").getNodeValue());
294                                    String idService = nodeChildren.item(j).
295                                            getAttributes().getNamedItem("id").getNodeValue();
296    
297                                    Service service = new Service(idService);
298                                    if (!services.contains(service))
299                                        services.add(service);
300                                    server.addService(service, goodness);
301                                } else if ((!nodeChildren.item(j).getNodeName().equals("server")) &&
302                                        (!nodeChildren.item(j).getNodeName().equals("client")))
303                                    throw new Exception("Unexpected tag found '"+nodeChildren.item(j).getNodeName()+"' while looking for server "+id+" neighbors and services");
304                            }
305                    } else
306                        throw new Exception("Unexpected tag found '"+node.getNodeName()+"' while looking for servers");
307                }
308            }
309    
310            for (int i = 1; i < nodes.getLength(); i++) {
311                org.w3c.dom.Node node = nodes.item(i);
312                if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
313                    NamedNodeMap attributes = node.getAttributes();
314                    if ((node.getNodeName().equals("client")) && (attributes != null)) {
315                        int id = Integer.parseInt(attributes.getNamedItem("id").getNodeValue());
316                        Sensor client = null;
317                        for (Sensor client_aux : clients)
318                            if (client_aux.id() == id)
319                                client = client_aux;
320    
321                        NodeList clientChildren = node.getChildNodes();
322                        for (int j = 0; j < clientChildren.getLength(); j++)
323                            if (clientChildren.item(j).getNodeType() == org.w3c.dom.Node.ELEMENT_NODE)
324                                if (clientChildren.item(j).getNodeName().equals("server")) {
325                                    int idServer = Integer.parseInt(clientChildren.item(j).
326                                            getAttributes().getNamedItem("id").getNodeValue());
327    
328                                    Sensor server = null;
329                                    for (Sensor server_aux : servers)
330                                        if (server_aux.id() == idServer)
331                                            server = server_aux;
332                                    client.addLink(server);
333                                } else if (clientChildren.item(j).getNodeName().equals("client")) {
334                                    int idClient = Integer.parseInt(clientChildren.item(j).
335                                            getAttributes().getNamedItem("id").getNodeValue());
336                                    if (id == idClient)
337                                        throw new Exception("Client "+id+" has a link to itself");
338                                    Sensor client_aux = null;
339                                    for (Sensor client_aux2 : clients)
340                                        if (client_aux2.id() == idClient)
341                                            client_aux = client_aux2;
342                                    client.addLink(client_aux);
343                                } else
344                                    throw new Exception("Unexpected tag found '"+clientChildren.item(i).getNodeName()+"' while looking for client's neighbors");
345    
346                    } else if ((node.getNodeName().equals("server")) && (attributes != null)) {
347                        int id = Integer.parseInt(attributes.getNamedItem("id").getNodeValue());
348    
349                        Sensor server = null;
350                        for (Sensor server_aux : servers)
351                            if (server_aux.id() == id)
352                                server = server_aux;
353    
354                        NodeList nodeChildren = node.getChildNodes();
355                        for (int j = 0; j < nodeChildren.getLength(); j++)
356                            if (nodeChildren.item(j).getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
357                                if (nodeChildren.item(j).getNodeName().equals("server")) {
358                                    int idServer = Integer.parseInt(nodeChildren.item(j).
359                                            getAttributes().getNamedItem("id").getNodeValue());
360                                    Sensor neighbour = null;
361                                    for (Sensor server_aux : servers)
362                                        if (server_aux.id() == idServer)
363                                            neighbour = server_aux;
364                                    if (id == idServer)
365                                        throw new Exception("Server "+id+" has a link to itself");
366    
367                                    server.addLink(neighbour);
368                                } else if (nodeChildren.item(j).getNodeName().equals("client")) {
369                                    int idClient = Integer.parseInt(nodeChildren.item(j).
370                                            getAttributes().getNamedItem("id").getNodeValue());
371                                    if (id == idClient)
372                                        throw new Exception("Client "+id+" has a link to itself");
373                                    Sensor client = null;
374                                    for (Sensor client_aux : clients)
375                                        if (client_aux.id() == idClient)
376                                            client = client_aux;
377                                    server.addLink(client);
378                                } else if (!nodeChildren.item(j).getNodeName().equals("service"))
379                                    throw new Exception("Unexpected tag found '"+nodeChildren.item(j).getNodeName()+"' while looking for server "+id+" neighbors and services");
380                            }
381                    } else
382                        throw new Exception("Unexpected tag found '"+node.getNodeName()+"' while looking for servers");
383                }
384            }
385        }
386    
387        /**
388         * This method turns every benevolent server in the network into malicious and
389         * counts the number of swapped servers. Then (when every server is malicious)
390         * it randomly selects malicious servers and converts them into benevolent until
391         * the number of benevolent servers is equal to the one before calling this method
392         * @param service Service over what the oscillation is to be carried out
393         */
394        public void oscillate(Service service) {
395            try {
396                int numBenevolentServers = 0;
397                for (Sensor server : servers)
398                    if ((server.offersService(service)) && (server.get_goodness(service) >= 0.5)) {
399                        numBenevolentServers++;
400                        server.set_goodness(service,0.0);
401                    }
402                
403                double prob = ((double)numBenevolentServers/servers.size());
404                while (numBenevolentServers > 0)
405                    for (Sensor server : servers)
406                        if ((Math.random() < prob) && (server.offersService(service)) && (server.get_goodness(service)< 0.5)) {
407                            server.set_goodness(service,1.0);
408                            numBenevolentServers--;
409                            if (numBenevolentServers == 0)
410                                break;
411                        }
412            } catch(Exception ex){ ex.printStackTrace(); }
413        }
414        
415        /**
416         * This method creates a new sensor. It must be redefined in each subclass
417         * according to the requirements of each particular trust and reputation
418         * model
419         * @return New created sensor
420         */
421        public abstract Sensor newSensor();
422    
423        /**
424         * This method creates a new sensor. It must be redefined in each subclass
425         * according to the requirements of each particular trust and reputation
426         * model
427         * @param id Sensor's identifier
428         * @param x X coordinate of the new sensor
429         * @param y Y coordinate of the new sensor
430         * @return New created sensor
431         */
432        public abstract Sensor newSensor(int id, double x, double y);
433    
434        /**
435         * This method resets this network to its initial state
436         */
437        public void reset() {
438            for (Sensor sensor : sensors)
439                sensor.reset();
440        }
441    
442        /**
443         * This method establishes every sensor's new neighborhood according to
444         * a new wireless range
445         * @param newRange New wireless range determining every sensor's neighbors
446         */
447        public void setNewNeighbors(double newRange) {
448            double rangeThreshold = newRange*Math.sqrt(2.0)*maxDistance;
449    
450            for (Sensor sensor : sensors) {
451                sensor.removeAllNeighbors();
452                for (Sensor sensor2 : sensors)
453                    if ((!sensor.equals(sensor2)) && (sensor.distance(sensor2) < rangeThreshold))
454                    {
455                        sensor.addLink(sensor2);
456                        sensor2.addLink(sensor);
457                    }
458            }
459        }
460        
461        /**
462         * This method writes the current Network into a XML file following 
463         * <a href="#xmlFileStructure">this structure</a>
464         * @param fileName Path of the XML file where to write the current Network
465         * @throws Exception If there is any problem when writing to the XML file
466         */
467        public void writeToXMLFile(String fileName) throws Exception {
468            try {
469                if (!fileName.endsWith(".xml"))
470                    fileName += ".xml";
471                BufferedWriter out = new BufferedWriter(new FileWriter(fileName));
472                
473                out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
474                out.write("<wsn>\n");
475                for (Sensor client : clients) {
476                    out.write("\t<client id=\""+client.id()
477                    +"\" x=\""+(((int)(client.getX()*100))/100.0)
478                    +"\" y=\""+(((int)(client.getY()*100))/100.0)
479                    +"\">\n");
480                    for (Sensor neighbor : client.getNeighbors())
481                        if (neighbor.get_numServices() == 0)
482                            out.write("\t\t<client id=\""+neighbor.id()+"\"/>\n");
483                        else
484                            out.write("\t\t<server id=\""+neighbor.id()+"\"/>\n");
485                    out.write("\t</client>\n");
486                }
487                
488                for (Sensor server : servers) {
489                    out.write("\t<server id=\""+server.id()
490                    +"\" x=\""+(((int)(server.getX()*100))/100.0)
491                    +"\" y=\""+(((int)(server.getY()*100))/100.0)
492                    +"\">\n");
493                    for (Service service : server.get_services())
494                        out.write("\t\t<service id=\""+service.id()+"\" "
495                            +"goodness=\""+server.get_goodness(service)+"\""
496                            +"/>\n");
497                    for (Sensor neighbor : server.getNeighbors())
498                        if (neighbor.get_numServices() == 0)
499                            out.write("\t\t<client id=\""+neighbor.id()+"\"/>\n");
500                        else
501                            out.write("\t\t<server id=\""+neighbor.id()+"\"/>\n");
502                    out.write("\t</server>\n");
503                    
504                }
505                
506                out.write("</wsn>\n");
507                out.flush();
508                out.close();
509            } catch (Exception ex) {
510                throw new Exception("writeToXMLFile: "+ex);
511            }
512        }
513        
514        /**
515         * Prints the whole Network, with all the offered services
516         * @return A string with the whole Network, with all the offered services
517         */
518        @Override
519        public String toString() {
520            String s = "";
521            for (Sensor client : clients)
522                s += "C "+client+"\n";
523            for (Sensor server : servers)
524                s += "S "+server+"\n";
525            return s;
526        }
527    
528        /**
529         * Average transmitted distance per sensor of this network
530         * @param searchCondition Condition to be accomplished by the querying sensors
531         * @param requiredService Service requested by the clients
532         * @return Average transmitted distance per sensor of this network
533         */
534        public long get_sensorsTransmittedDistance(ISearchCondition searchCondition, Service requiredService) {
535            long sensorsTransmittedDistance = 0;
536            long numSensors = 0;
537    
538            for (Sensor sensor : sensors)
539                if (searchCondition.sensorAcomplishesCondition(sensor) &&
540                    reachesQualifiedService(sensor,requiredService)) {
541                    sensorsTransmittedDistance += sensor.get_transmittedDistance();
542                    numSensors++;
543                }
544    
545            if (numSensors != 0)
546                return sensorsTransmittedDistance/numSensors;
547    
548            return 0;
549        }
550    
551        /**
552         * This method checks if a given sensor can reach any client and any benevolent server offering a given service
553         * @param sensor Sensor to find out whether it can reach a benevolent server or not
554         * @param requiredService Service requested by the clients
555         * @return true if the given sensor can reach any client and any benevolent server offering the given service, false otherwise
556         */
557        protected boolean reachesQualifiedService(Sensor sensor, Service requiredService) {
558            boolean reachableClient = false;
559            boolean reachableBenevolentServer = false;
560            if (sensor.isActive())
561                try {
562                    reachableClient = (sensor.get_numServices() == 0);
563                    reachableBenevolentServer = ((sensor.get_numServices() > 1) && (sensor.get_goodness(requiredService) > 0.5));
564    
565                    if (!reachableClient) {
566                        Collection<Vector<Sensor>> pathsToClients = sensor.findSensors(new IsClientSearchCondition());
567                        reachableClient = ((pathsToClients != null) && (pathsToClients.size() > 0));
568                    }
569                    if (!reachableBenevolentServer) {
570                        Collection<Vector<Sensor>> pathsToServers = sensor.findSensors(new IsServerSearchCondition(requiredService,IsServerSearchCondition.BENEVOLENT_SERVER));
571                        reachableBenevolentServer = ((pathsToServers != null) && (pathsToServers.size() > 0));
572                    }
573                } catch (Exception ex) { ex.printStackTrace(); }
574    
575            return (reachableClient && reachableBenevolentServer);
576        }
577    
578        /**
579         * This method returns the sensor with identifier id. If such sensor does not exist, it returns null
580         * @param id Identifier of the sensor to be retrieved
581         * @return The sensor with identifier id. If such sensor does not exist, it returns null
582         */
583        public Sensor getSensor(int id) {
584            if ((sensors == null) || (sensors.isEmpty()))
585                return null;
586            
587            for (Sensor sensor : sensors) 
588                if (sensor.id() == id)
589                    return sensor;
590            
591            return null;
592        }
593        
594        /**
595         * This method retrieves the set of clients belonging to this network
596         * @return The set of clients belonging to this network
597         */
598        public Collection<Sensor> get_clients() { return clients; }
599    
600        /**
601         * This method retrieves the set of servers belonging to this network
602         * @return The set of servers belonging to this network
603         */
604        public Collection<Sensor> get_servers() { return servers; }
605    
606        /**
607         * This method retrieves the set of sensors belonging to this network
608         * @return The set of sensors belonging to this network
609         */
610        public Collection<Sensor> get_sensors() { return sensors; }
611    
612        /**
613         * This method retrieves the set of services offered by this network
614         * @return The set of services offered by this network
615         */
616        public Collection<Service> get_services() { return services; }
617    
618        /**
619         * This method retrieves the total number of sensors composing this network
620         * @return The total number of sensors composing this network
621         */
622        public int get_numSensors() { return sensors.size(); }
623    
624        /**
625         * This method retrieves the number of clients belonging to this network
626         * @return The number of clients belonging to this network
627         */
628        public int get_numClients() { return clients.size(); }
629    
630        /**
631         * This method retrieves the number of servers belonging to this network
632         * @return The number of servers belonging to this network
633         */
634        public int get_numServers() { return servers.size(); }
635    
636        /**
637         * This method retrieves the maximum distance between two nodes in this network
638         * @return The maximum distance between two nodes in this network
639         */
640        public static double get_maxDistance() { return maxDistance; }
641    
642        /**
643         * This method establishes if a collusion is to be formed or not in this network
644         * @param collusion Indicates if a collusion is to be formed or not in this network
645         */
646        public void set_collusion(boolean collusion) { Sensor.setCollusion(collusion); }
647    
648        /**
649         * This method establishes if the topology of this network is dynamic, because
650         * sensors can sleep or not
651         * @param dynamic Indicates if the topology of this network is dynamic, because
652         * sensors can sleep or not
653         */
654        public void set_dynamic(boolean dynamic) { Sensor.setDynamic(dynamic); }
655    }