diff src/main/gov/nasa/jpf/util/event/EventTree.java @ 0:61d41facf527

initial v8 import (history reset)
author Peter Mehlitz <Peter.C.Mehlitz@nasa.gov>
date Fri, 23 Jan 2015 10:14:01 -0800
parents
children b920e6b1be83
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/gov/nasa/jpf/util/event/EventTree.java	Fri Jan 23 10:14:01 2015 -0800
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2014, United States Government, as represented by the
+ * Administrator of the National Aeronautics and Space Administration.
+ * All rights reserved.
+ *
+ * The Java Pathfinder core (jpf-core) platform is licensed under the
+ * Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ * 
+ *        http://www.apache.org/licenses/LICENSE-2.0. 
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package gov.nasa.jpf.util.event;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * an abstract class that creates Event trees
+ * 
+ * While there is no need to provide specialized Event types or additional event 
+ * constructors, concrete subclasses have to provide a createEventTree() implementation.
+ * 
+ * A typical implementation looks like this
+ * 
+ *   public Event createEventTree1() {
+ *     return sequence(
+ *             event("a"),
+ *             alternatives(
+ *                     event("1"),
+ *                     iteration(2,
+ *                             event("x")
+ *                     )
+ *             ),
+ *             event("b")
+ *     );
+ *   }
+ */
+public class EventTree extends EventConstructor {
+  
+  public static final String CONFIG_KEY = "event.class";
+  
+  protected Event root;
+
+  /**
+   * this is our purpose in life, which has to be provided by concrete subclasses 
+   */
+  public Event createEventTree() {
+    // nothing here, needs to be overridden by subclass to populate tree
+    return null;
+  }
+
+  protected EventTree (){
+    root = createEventTree();
+  }
+
+  protected EventTree (Event root){
+    this.root = root;
+  }
+  
+  public Event getRoot(){
+    return root;
+  }
+    
+  //--- inspection and debugging
+
+  static final List<Event> NO_EVENTS = new ArrayList<Event>(0);
+  
+  public List<Event> visibleEndEvents(){
+    if (root != null){
+      return root.visibleEndEvents();
+    } else {
+      return NO_EVENTS;
+    }
+  }
+  
+  public void printPaths(){
+    for (Event es : visibleEndEvents()){
+      es.printPath(System.out);
+      System.out.println('.');
+    }
+  }
+
+  public void printTree (){
+    if (root != null){
+      root.printTree(System.out, 0);
+    }
+  }
+
+  /**
+   * this should be overridden in case we want to check if this is an expected trace
+   * The generic form can only check if this is a valid end event.
+   * 
+   * To check for a whole trace, implementors should keep some sort of expected event specs
+   */
+  public boolean checkPath (Event lastEvent){
+    for (Event ee : root.visibleEndEvents()){
+      if (ee.equals(lastEvent)){
+        return true;
+      }
+    }
+    
+    return false;
+  }
+  
+  public boolean checkPath (Event lastEvent, String[] pathSpecs) {
+    String trace = lastEvent.getPathString(null);
+
+    for (int i = 0; i < pathSpecs.length; i++) {
+      if (trace.equals(pathSpecs[i])) {
+        pathSpecs[i] = null;
+        return true;
+      }
+    }
+
+    return false; // unexpected trace
+  }
+  
+  /**
+   * override this if the concrete model keeps track of coverage
+   * 
+   * @return [0.0..1.0]
+   */
+  public float getPathCoverage (){
+    throw new UnsupportedOperationException("path coverage not supported by generic EventTree");
+  }
+  
+  /**
+   * override this if the concrete model can keep track of coverage
+   * call at the end of execution
+   */
+  public boolean isCompletelyCovered (){
+    throw new UnsupportedOperationException("path coverage not supported by generic EventTree");
+  }
+  
+  /**
+   * extend this tree with a new path 
+   */
+  public void addPath (Event... path){
+    if (root != null){
+      root.addPath(path.length, path);
+    } else {
+      root = sequence(path);
+    }
+  }
+  
+  public Event interleave (Event... otherTrees){
+    if (root != null){
+      return root.interleave( otherTrees);
+      
+    } else {
+      if (otherTrees == null || otherTrees.length == 0){
+        return root;
+        
+      } else {
+        Event first = null;
+        List<Event> rest = new ArrayList<Event>();
+        for (int i=0; i< otherTrees.length; i++){
+          if (otherTrees[i] != null){
+            if (first == null){
+              first = otherTrees[i];
+            } else {
+              rest.add( otherTrees[i]);
+            }
+          }
+        }
+        
+        if (first != null){
+          if (rest.isEmpty()){
+            return first;
+          } else {
+            Event[] ot = new Event[rest.size()];
+            rest.toArray(ot);
+            return first.interleave(ot);
+          }
+          
+        } else {      // nothing to interleave at all
+          return null;
+        }
+      }
+    }
+  }
+
+  public EventTree interleave (EventTree... otherTrees){
+    Event[] otherRoots = new Event[otherTrees.length];
+    for (int i=0; i<otherRoots.length; i++){
+      otherRoots[i] = otherTrees[i].root;
+    }
+    return new EventTree( interleave( otherRoots));
+  }  
+  
+  public Event removeSource (Object source){
+    if (root != null){
+      return root.removeSource(source);
+      
+    } else { // nothing to remove from
+      return null;
+    }
+  }
+  
+  public int getMaxDepth(){
+    if (root != null){
+      return root.getMaxDepth();
+    } else {
+      return 0;
+    }
+  }
+  
+}