1   package de.uni_stuttgart.informatik.canu.mobisim.core;
2   
3   import java.util.ArrayList;
4   import java.util.HashMap;
5   import java.util.concurrent.ConcurrentHashMap;
6   
7   import org.w3c.dom.Element;
8   import org.w3c.dom.NodeList;
9   
10  import de.uni_stuttgart.informatik.canu.mobisim.notifications.DebugNotification;
11  import de.uni_stuttgart.informatik.canu.mobisim.notifications.LoaderNotification;
12  import de.uni_stuttgart.informatik.canu.mobisim.notifications.NodeAddedNotification;
13  import de.uni_stuttgart.informatik.canu.mobisim.notifications.NodeRemovedNotification;
14  import de.uni_stuttgart.informatik.canu.mobisim.notifications.StartingPositionSetNotification;
15  import de.uni_stuttgart.informatik.canu.uomm.CommunicationsManager;
16  
17  /**
18   * Title:        Canu Mobility Simulation Environment
19   * Description:
20   * Copyright:    Copyright (c) 2001-2003
21   * Company:      University of Stuttgart
22   * <p>Patches: </p>
23   * <p> v1.2 (23/08/2005): The x-y-z dimemsion of the Universe
24   *                                                  the time step of the simulation must 
25   *                                                  be loaded before all sebsequent
26   *                                                  extensions.
27   *                                                  A seed tag has been added in order to 
28   *                                                  be able to feed the RNG.</p> 
29   * @author Canu Research group
30   * @author v1.2: Jerome Haerri (haerri@ieee.org) 
31   * @version 1.2 
32   */
33  
34  /**
35   * This class implements the "Universe" object
36   * <p>Patches: </p>
37   * <p> <i> Version 1.2 by Jerome Haerri (haerri@ieee.org) on 08/23/2005:
38   * <br> &nbsp;&nbsp;&nbsp;&nbsp; The x-y-z dimemsion of the Universe
39   *                                                  the time step of the simulation must 
40   *                                                  be loaded before all sebsequent
41   *                                                  extensions.
42   *                                                  A seed tag has been added in order to 
43   *                                                  be able to feed the RNG.</i></p>
44   * @author 1.0-1.1 Illya Stepanov
45   * @author 1.0 1.1 Gregor Schiele
46   * @author 1.2 Jerome Haerri
47   * @version 1.2
48   */
49  public final class Universe extends ExtendableObject
50                              implements NotificationListener
51  {
52    // Allow only one instance of this class
53    /**
54     * Global instance of the object
55     */
56    private static Universe ui=new Universe();
57  
58    /**
59     * Gets a reference to the Universe object. <br>
60     * <br>
61     * @return reference to the Universe object
62     */
63    public static final Universe getReference()
64    {
65      return ui;
66    }
67  
68    /**
69     * Duration of single simulation step (in ms)
70     */
71    private int stepDuration = 1;             //in ms
72    /**
73     * X-size of Universe (in m)
74     */
75    private float dimensionX = 0.0f;          //in m
76    /**
77     * Y-size of Universe (in m)
78     */
79    private float dimensionY = 0.0f;          //in m
80    /**
81     * Z-size of Universe (in m)
82     */
83    private float dimensionZ = 0.0f;          //in m
84  
85    /**
86     * Simulation events receivers
87     */
88    private java.util.Collection listeners;
89  
90    /**
91     * Current simulation time (in steps)
92     */
93    private long currentTime;
94    /**
95     * Random number generator
96     */
97    private java.util.Random rand;
98  
99    /**
100    * Array of nodes
101    */
102   private java.util.ArrayList allNodes;
103   
104   private String testCase;
105 
106 
107   public String getTestCase() {
108     return testCase;
109 }
110 
111 public void setTestCase(String testCase) {
112     this.testCase = testCase;
113 }
114 
115 
116 
117 private int numOfVehicles;
118 
119 public int getNumOfVehicles() {
120     return numOfVehicles;
121 }
122 
123 public void setNumOfVehicles(int vehNum) {
124     this.numOfVehicles = vehNum;
125 }
126 
127 private boolean jnReachedFlag = false;
128   public boolean isJnReachedFlag() {
129     return jnReachedFlag;
130 }
131 
132   //ADDED
133   private ConcurrentHashMap goodToEval = new ConcurrentHashMap();
134   private boolean readyFlag=false;
135   
136   public void setReadyFlag(ConcurrentHashMap obtainedMap){
137      // System.out.println("Setting the Ready Flag map");
138       this.goodToEval = obtainedMap;
139   }
140   
141   public boolean getReadyFlagValue(String vID){
142       if(goodToEval!=null){
143           Boolean flag= (Boolean) goodToEval.get(allNodes);
144           if(flag!=null){
145               readyFlag = flag.booleanValue();
146               return readyFlag;
147           }
148       }
149       return false;
150   }
151   
152   public ConcurrentHashMap returnFlagMap(){
153       return goodToEval;
154   }
155 //ADDED
156   
157 public void setJnReachedFlag(boolean jnReachedFlag) {
158     System.out.println("::::::::::::Set");
159     this.jnReachedFlag = jnReachedFlag;
160 }
161   /**
162    * Constructor
163    */
164 private HashMap<String,ArrayList> pathPoints = new HashMap<String,ArrayList>();
165 public HashMap<String,ArrayList> getPathPoints() {
166     return pathPoints;
167 }
168 
169 public void setPathPoints(HashMap<String,ArrayList> pathPoints) {
170     this.pathPoints = pathPoints;
171 }
172  
173 private Universe()
174   {
175     u = this;
176     
177     allNodes        = new java.util.ArrayList();
178     rand            = new java.util.Random();
179     listeners       = new java.util.ArrayList();
180   }
181 
182   /**
183    * Performs the modules' initialization
184    */
185   public void initialize()
186   {
187     super.initialize();
188     Node n = null;
189     
190     System.out.println("Initialize:Universe");
191     // initialize mobile nodes
192     for (int i=0; i<allNodes.size(); i++)
193     {
194       ((ExtendableObject)allNodes.get(i)).initialize();
195     //ADDED
196       n = (Node) allNodes.get(i);
197       if(n!=null){
198           goodToEval.put(n.getID(), true);
199       }
200     //ADDED
201     }
202     
203     u.sendNotification(new DebugNotification(this, u,
204       "Dimensions = ("+getDimensionX()+" m x "+
205     
206               
207       getDimensionY()+" m x "+getDimensionZ()+" m)"));
208     u.sendNotification(new DebugNotification(this, u,
209       "Simulation step = "+stepDuration+" ms"));
210 
211     // output positions of mobile devices
212     for (int i=0; i<allNodes.size(); i++)
213     {
214       u.sendNotification(new StartingPositionSetNotification(allNodes.get(i), u));
215     }
216     
217     CommunicationsManager.initialiseTheMap();
218     
219   }
220 
221   /**
222    * Adds a simulation events receiver. <br>
223    * <br>
224    * @param listener new event listener
225    */
226   public void addNotificationListener(NotificationListener listener)
227   {
228     listeners.add(listener);
229   }
230 
231   /**
232    * Removes a simulation events receiver. <br>
233    * <br>
234    * @param listener event listener
235    */
236   public void removeNotificationListener(NotificationListener listener)
237   {
238     listeners.remove(listener);
239   }
240 
241   /**
242    * Notification passing method. <br>
243    * <br>
244    * Method is used to pass simulation notifications
245    * to listeners. Listener can be registered using the
246    * {@link #addNotificationListener addNotificationListener}
247    * method.
248    * The simulation environment sends the notification to all
249    * registered listeners.
250    * @param notification notification
251    */
252   public void sendNotification(Notification notification)
253   {
254     java.util.Iterator iter = listeners.iterator();
255     while (iter.hasNext())
256     {
257       NotificationListener listener = (NotificationListener)iter.next();
258       listener.sendNotification(notification);
259     }
260   }
261 
262   /**
263    * Gets an array of nodes. <br>
264    * <br>
265    * @return array of nodes
266    */
267   public final java.util.ArrayList getNodes()
268   {
269     return allNodes;
270   }
271 
272   /**
273    * Searches a node by id. <br>
274    * <br>
275    * @param id id of node
276    * @return node, if found, null otherwise
277    */
278   public final Node getNode(String id)
279   {
280     java.util.Iterator iter=allNodes.iterator();
281     while (iter.hasNext())
282     {
283       Node node=(Node)iter.next();
284       if (node.id.equals(id))
285         return node;
286     }
287 
288     return null;
289   }
290 
291   /**
292    * Adds a node to simulation. <br>
293    * <br>
294    * @param aNode node to be added
295    */
296   public void addNode(Node aNode)
297   {
298     allNodes.add(aNode);
299     sendNotification(new NodeAddedNotification(this, this, aNode));
300   }
301 
302   /**
303    * Removes a node from simulation. <br>
304    * <br>
305    * @param aNode node to be removed
306    */
307   public void removeNode(Node aNode)
308   {
309     allNodes.remove(aNode);
310     sendNotification(new NodeRemovedNotification(this, this, aNode));
311   }
312 
313   /**
314    * Gets a reference to the random number generator object. <br>
315    * <br>
316    * @return reference to the random number generator object
317    */
318   public final java.util.Random getRandom()
319   {
320     return rand;
321   }
322 
323   /**
324    * Gets the X-dimension of Universe. <br>
325    * <br>
326    * @return X-dimension of Universe (in m)
327    */
328   public float getDimensionX()
329   {
330     return dimensionX;
331   }
332 
333   /**
334    * Sets the X-dimension of Universe. <br>
335    * <br>
336    * @param dimensionX X-dimension of Universe (in m)
337    */
338   public void setDimensionX(float dimensionX)
339   {
340     this.dimensionX = dimensionX;
341   }
342 
343   /**
344    * Gets the Y-dimension of Universe. <br>
345    * <br>
346    * @return Y-dimension of Universe (in m)
347    */
348   public float getDimensionY()
349   {
350     return dimensionY;
351   }
352 
353   /**
354    * Sets the Y-dimension of Universe. <br>
355    * <br>
356    * @param dimensionY Y-dimension of Universe (in m)
357    */
358   public void setDimensionY(float dimensionY)
359   {
360     this.dimensionY = dimensionY;
361   }
362 
363   /**
364    * Gets the Z-dimension of Universe. <br>
365    * <br>
366    * @return Z-dimension of Universe (in m)
367    */
368   public float getDimensionZ()
369   {
370     return dimensionZ;
371   }
372 
373   /**
374    * Sets the Z-dimension of Universe. <br>
375    * <br>
376    * @param dimensionZ Z-dimension of Universe (in m)
377    */
378   public void setDimensionZ(float dimensionZ)
379   {
380     this.dimensionZ = dimensionZ;
381   }
382 
383   /**
384    * Gets a duration of single simulation time step. <br>
385    * <br>
386    * @return duration of single simulation time step (in ms)
387    */
388   public final int getStepDuration()
389   {
390     return stepDuration;
391   }
392 
393   /**
394    * Gets current time (in steps). <br>
395    * <br>
396    * @return current time (in steps)
397    */
398   public long getTimeInSteps()
399   {
400     return currentTime;
401   }
402 
403 
404   /**
405    * Gets current time (in ms). <br>
406    * <br>
407    * @return current time (in ms)
408    */
409   public long getTime()
410   {
411     return currentTime*stepDuration;
412   }
413 
414   /**
415    * Gets a readable time representation in ms. <br>
416    * <br>
417    * @return readable time representation (in ms)
418    */
419   public String getTimeAsString()
420   {
421     return timeToString(currentTime);
422   }
423 
424   /**
425    * Converts time from steps to readable representation in ms. <br>
426    * <br>
427    * @return readable time representation (in ms)
428    */
429   public String timeToString(long time)
430   {
431     return ""+ (float)getTime()/1000.0+" s";
432   }
433 
434 
435   /**
436    * Executes a single simulation timestep. <br>
437    * <br>
438    * Performs execution of the exetensions and nodes,
439    * increments simulation time.
440    */
441   public void advanceTime()
442   {
443     // execute extensions
444     super.act();
445     Node node = null;
446     Boolean val = null;
447     boolean finalVal = true;
448    
449     // execute mobile nodes
450     for (int i=0, n=allNodes.size(); i<n; i++)
451     {
452     //  System.out.println("Actig..."+((Node)allNodes.get(i)).getID());
453        //Added
454     node = ((Node) allNodes.get(i));
455     node.act();
456   
457    if(this.goodToEval!=null && node!=null){
458     val = (Boolean) this.goodToEval.get(node.getID());
459         if(val!=null){
460             if(!val.booleanValue()){
461                 finalVal = false;
462             // if(node.getID().equals("#1")){
463             //  System.out.println("final flag in universe is false : "+ node.getID());
464         //   }
465             }
466         }
467     }
468     }
469 //Added
470   
471     if(finalVal){
472         currentTime++;
473     }
474   
475   }
476     
477     /**
478     * Re-Initializes all variables. <br>
479     * <br>
480     * Resets current time, remove all nodes, 
481         * deletes extensions, and resets the random number generator
482         * @since 1.2
483     */
484     public void flush() {
485       currentTime = 0;
486         allNodes.clear();
487         getExtensions().clear();
488     rand = new java.util.Random();
489     listeners.clear();
490         
491         
492     }
493   /**
494     * Initializes the object from XML tag. <br>
495         * <br>
496         * <i>Version 1.2 by Jerome Haerri (haerri@ieee.org) : 
497         * <br> &nbsp;&nbsp;&nbsp;&nbsp; - A seed extention has been added
498         *   <br> &nbsp;&nbsp;&nbsp;&nbsp; - x-y-z dim + step + seed are loaded before all subsequent extensions.</i>
499     * <br>
500     * @param element source tag
501     * @throws Exception Exception if parameters are invalid
502     */
503   public void load(org.w3c.dom.Element element,org.w3c.dom.Document configDoc) throws Exception
504   {
505         
506         //JHNote (23/08/2005) : Patch here in order to do some preloading
507         //                                        We think that the x-y-z dim + step of the Universe
508         //                                        should be loaded before all subsequent extensions.
509         //                                        Moreover, the seed must be set before any 
510         //                                          subsequent load.
511         org.w3c.dom.NodeList list = element.getChildNodes();
512     int len=list.getLength();
513     
514     
515         u.sendNotification(new LoaderNotification(this, u,
516           "Preprocessing tags"));
517         
518     System.out.println("Load:Universe");    
519     for(int i=0; i<len; i++)
520     {
521       org.w3c.dom.Node item = list.item(i);
522       String tag = item.getNodeName();
523 
524       if(tag.equals("#text")) {
525         // skip it
526         continue;
527       }
528       else
529       if(tag.equals("#comment")) {
530         // skip it
531         continue;
532       }
533       else
534         if(tag.equals("seed")) {
535                 u.sendNotification(new LoaderNotification(this, u,
536           "Processing <seed> tag"));
537                 long seed = (Long.parseLong(item.getFirstChild().getNodeValue()));
538                 if (seed > 0) {
539                     //System.out.println("Setting seed to " + seed);
540                     u.getRandom().setSeed(seed);
541                 }
542                 u.sendNotification(new LoaderNotification(this, u,
543           "Finished processing <seed> tag"));
544             }
545             else
546       if(tag.equals("step")) {
547         u.sendNotification(new LoaderNotification(this, u,
548           "Processing <step> tag"));
549 
550         stepDuration=(int)(Float.parseFloat(item.getFirstChild().
551           getNodeValue())*1000);
552 
553         u.sendNotification(new LoaderNotification(this, u,
554           "Finished processing <step> tag"));
555       }
556       else
557       if(tag.equals("dimx")) {
558         u.sendNotification(new LoaderNotification(this, u,
559           "Processing <dimx> tag"));
560 
561         setDimensionX(Float.parseFloat(item.getFirstChild().getNodeValue()));
562 
563         u.sendNotification(new LoaderNotification(this, u,
564           "Finished processing <dimx> tag"));
565       }
566       else
567       if(tag.equals("dimy")) {
568         u.sendNotification(new LoaderNotification(this, u,
569           "Processing <dimy> tag"));
570 
571         setDimensionY(Float.parseFloat(item.getFirstChild().getNodeValue()));
572 
573         u.sendNotification(new LoaderNotification(this, u,
574           "Finished processing <dimy> tag"));
575       }
576       else
577       if(tag.equals("dimz")) {
578         u.sendNotification(new LoaderNotification(this, u,
579           "Processing <dimz> tag"));
580 
581         setDimensionZ(Float.parseFloat(item.getFirstChild().getNodeValue()));
582 
583         u.sendNotification(new LoaderNotification(this, u,
584           "Finished processing <dimz> tag"));
585       }
586         }
587         
588         // checkout
589     if (stepDuration<=0)
590       throw new Exception("Simulation step is invalid: "+
591         (float)stepDuration/1000);
592     if (getDimensionX()<0.0f)
593       throw new Exception("Simulation parameter dimX is invalid: "+getDimensionX());
594     if (getDimensionY()<0.0f)
595       throw new Exception("Simulation parameter dimY is invalid: "+getDimensionY());
596     if (getDimensionZ()<0.0f)
597       throw new Exception("Simulation parameter dimZ is invalid: "+getDimensionZ());
598     if (getDimensionX()+getDimensionY()+getDimensionZ() == 0.0f)
599       throw new Exception("Simulation area dimensions are null");
600         
601         u.sendNotification(new LoaderNotification(this, u,
602           "Finished preprocessing tags"));
603         
604     super.load(element);
605         
606         u.sendNotification(new LoaderNotification(this, u,
607           "Postprocessing tags"));
608    /* org.w3c.dom.NodeList list = element.getChildNodes();
609     int len=list.getLength();*/
610 
611     for(int i=0; i<len; i++)
612     {
613       org.w3c.dom.Node item = list.item(i);
614       String tag = item.getNodeName();
615 
616       if(tag.equals("#text"))
617       {
618         // skip it
619         continue;
620       }
621       else
622       if(tag.equals("#comment"))
623       {
624         // skip it
625         continue;
626       }
627       else
628       if(tag.equals("node"))
629       {
630         u.sendNotification(new LoaderNotification(this, u,
631           "Processing <node> tag"));
632 
633         // read and add a mobile node
634         org.w3c.dom.Element e = (org.w3c.dom.Element)item;
635 
636         String classTag = e.getAttribute("class");
637         if (classTag.length()==0)
638           classTag = Node.class.getName();
639 
640         Node node=(Node)Class.forName(classTag).newInstance();
641         node.load(e);
642 
643         addNode(node);
644 
645         u.sendNotification(new LoaderNotification(this, u,
646           "Finished processing <node> tag"));
647       }
648       /*else
649       if(tag.equals("nodegroup"))
650       {
651         u.sendNotification(new LoaderNotification(this, u,
652           "Processing <nodegroup> tag"));
653 
654         org.w3c.dom.Element e = (org.w3c.dom.Element)item;
655 
656         // number of nodes in the group
657         int n = Integer.parseInt(e.getAttribute("n"));
658 
659         // group id
660         String g_id = e.getAttribute("id");
661         
662         // class of nodes
663         String classTag = e.getAttribute("class");
664         if (classTag.length()==0)
665           classTag = Node.class.getName();
666 
667         for (int n_i=0; n_i<n; n_i++)
668         {
669           u.sendNotification(new LoaderNotification(this, u,
670             "Creating mobile node"));
671           
672           Node node=(Node)Class.forName(classTag).newInstance();
673           e.setAttribute("id", g_id+"#"+n_i);
674           node.load(e);
675 
676           addNode(node);
677           
678           u.sendNotification(new LoaderNotification(this, u,
679             "Finished creating mobile node"));
680         }
681 
682         u.sendNotification(new LoaderNotification(this, u,
683           "Finished processing <nodegroup> tag"));
684       }*/
685       /*else
686       if(tag.equals("step"))
687       {
688         u.sendNotification(new LoaderNotification(this, u,
689           "Processing <step> tag"));
690 
691         stepDuration=(int)(Float.parseFloat(item.getFirstChild().
692           getNodeValue())*1000);
693 
694         u.sendNotification(new LoaderNotification(this, u,
695           "Finished processing <step> tag"));
696       }
697       else
698       if(tag.equals("dimx"))
699       {
700         u.sendNotification(new LoaderNotification(this, u,
701           "Processing <dimx> tag"));
702 
703         setDimensionX(Float.parseFloat(item.getFirstChild().getNodeValue()));
704 
705         u.sendNotification(new LoaderNotification(this, u,
706           "Finished processing <dimx> tag"));
707       }
708       else
709       if(tag.equals("dimy"))
710       {
711         u.sendNotification(new LoaderNotification(this, u,
712           "Processing <dimy> tag"));
713 
714         setDimensionY(Float.parseFloat(item.getFirstChild().getNodeValue()));
715 
716         u.sendNotification(new LoaderNotification(this, u,
717           "Finished processing <dimy> tag"));
718       }
719       else
720       if(tag.equals("dimz"))
721       {
722         u.sendNotification(new LoaderNotification(this, u,
723           "Processing <dimz> tag"));
724 
725         setDimensionZ(Float.parseFloat(item.getFirstChild().getNodeValue()));
726 
727         u.sendNotification(new LoaderNotification(this, u,
728           "Finished processing <dimz> tag"));
729       }*/
730     }
731 
732         u.sendNotification(new LoaderNotification(this, u,
733           "Finished postprocessing tags"));
734         int j=0;
735         org.w3c.dom.NodeList configList = configDoc.getElementsByTagName("nodegroup");//configElement.getChildNodes();
736         int configLen=configList.getLength();
737         for (j=0; j<configLen; j++){
738           org.w3c.dom.Node configItem = configList.item(j);
739           String configTag = configItem.getNodeName();
740           /*if(configTag.equals("nodegroup"))
741           {*/
742               u.sendNotification(new LoaderNotification(this, u,
743                       "Processing <nodegroup> tag"));
744 
745                    
746                  //   NodeList nl = e.getElementsByTagName("t");
747                   //nl.item(0).getFirstChild().getNodeName();
748                     if (configItem.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
749                          org.w3c.dom.Element e = (org.w3c.dom.Element)configItem;
750 
751                         // number of nodes in the group
752                         int n = Integer.parseInt(e.getAttribute("n"));
753                         NodeList nodes = e.getElementsByTagName("t").item(0).getChildNodes();
754                         String s = getValue("t",e);
755                         System.out.println("value of t: "+s);
756                         n=getNumOfVehicles();
757                     System.out.println("num of vehicles "+n);
758                     // group id
759                     String g_id = e.getAttribute("id");
760                     
761                     // class of nodes
762                     String classTag = e.getAttribute("class");
763                     if (classTag.length()==0)
764                       classTag = Node.class.getName();
765 
766                     for (int n_i=0; n_i<n; n_i++)
767                     {
768                       u.sendNotification(new LoaderNotification(this, u,
769                         "Creating mobile node"));
770                       
771                       Node node=(Node)Class.forName(classTag).newInstance();
772                       e.setAttribute("id", g_id+"#"+n_i);
773                       node.load(e);
774 
775                       addNode(node);
776                       
777                       u.sendNotification(new LoaderNotification(this, u,
778                         "Finished creating mobile node"));
779                     }
780 
781                     u.sendNotification(new LoaderNotification(this, u,
782                       "Finished processing <nodegroup> tag"));
783         }
784                     //  }  
785           
786   }//outer for loop     
787         
788    /* // checkout
789     if (stepDuration<=0)
790       throw new Exception("Simulation step is invalid: "+
791         (float)stepDuration/1000);
792     if (getDimensionX()<0.0f)
793       throw new Exception("Simulation parameter dimX is invalid: "+getDimensionX());
794     if (getDimensionY()<0.0f)
795       throw new Exception("Simulation parameter dimY is invalid: "+getDimensionY());
796     if (getDimensionZ()<0.0f)
797       throw new Exception("Simulation parameter dimZ is invalid: "+getDimensionZ());
798     if (getDimensionX()+getDimensionY()+getDimensionZ() == 0.0f)
799       throw new Exception("Simulation area dimensions are null");*/
800   }//proc
801 
802     private static String getValue(String tag, Element element) {
803             
804         NodeList nodes = element.getElementsByTagName(tag).item(0).getChildNodes();
805         
806             org.w3c.dom.Node node = (org.w3c.dom.Node) nodes.item(0);
807         
808             return node.getNodeValue();
809     }
810 }
811