| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 | 
							- <?php
 
- /**
 
-  * Input converter for FSM from Dia
 
-  *
 
-  * This class converts an UML diagram from Dia 0.9.6 into an abstract FSM graph
 
-  * which can then be output by another class to the FSM XML format used by
 
-  * the OSInet FSM 1.6.
 
-  *
 
-  * @copyright  (c) 2007-2012 Ouest Systèmes Informatiques
 
-  * @author     Frederic G. MARAND
 
-  * @license    CeCILL 2.0
 
-  * @link       http://wiki.audean.com/fsm/fsm
 
-  * @since      FSM 1.6
 
-  */
 
- namespace OSInet\Finite_State_Machine;
 
- $erFsmFromDia = error_reporting(E_ALL|E_STRICT);
 
- /**
 
-  * This class converts an UML diagram from Dia 0.9.6 into an abstract FSM graph.
 
-  *
 
-  * @todo Validate the diagram: currently it will just choke on non-accepted diagrams.
 
-  */
 
- class DiaLoader {
 
-   const DIA_NAMESPACE = "http://www.lysator.liu.se/~alla/dia/";
 
-   /**
 
-    * The DOM for the source Dia diagram.
 
-    *
 
-    * @var \DOMDocument
 
-    */
 
-   protected $dom;
 
-   /**
 
-    * The FSM writer instance to save to.
 
-    *
 
-    * @var Writer
 
-    */
 
-   protected $fsm;
 
-   /**
 
-    * Sequence generator for unnamed event results (guards).
 
-    *
 
-    * @var integer
 
-    */
 
-   protected $resultGenerator = 0;
 
-   /**
 
-    * Extract the initial/final status from a Dia "UML - State Term".
 
-    *
 
-    * @param DOMElement $element
 
-    *
 
-    * @return array
 
-    */
 
-   protected function getStateTermInfo($element) {
 
-     $query = 'dia:attribute[@name="is_final"]/dia:boolean';
 
-     $xpath = new \DOMXPath($this->dom);
 
-     $xpath->registerNamespace("dia", self::DIA_NAMESPACE);
 
-     $id = $element->getAttribute('id');
 
-     $diaAttributes = $xpath->query($query, $element);
 
-     // Normal case
 
-     if ($diaAttributes->length == 1) {
 
-       // "is_final" is a Dia boolean
 
-       $diaBoolean = $diaAttributes->item(0);
 
-       $val = $diaBoolean->getAttribute('val');
 
-       switch ($val) {
 
-         case 'true':
 
-           $ret = Machine::FINAL_STATE;
 
-           break;
 
-         case 'false':
 
-           $ret = Machine::INIT_STATE;
 
-           break;
 
-         default:
 
-           $ret = "anomalous($val)";
 
-         break;
 
-       }
 
-     }
 
-     else {
 
-       echo "Initial/final state #$id does not bear the is_final attribute: anomaly.\n";
 
-     }
 
-     return array('type' => $ret, 'name' => $ret);
 
-   }
 
-   /**
 
-    * Extract the name from a Dia "UML - State".
 
-    *
 
-    * @param DOMElement $element
 
-    *
 
-    * @return array
 
-    */
 
-   protected function getStateInfo($element) {
 
-     $query = 'dia:attribute[@name="text"]/dia:composite/dia:attribute[@name="string"]/dia:string';
 
-     $xpath = new \DOMXPath($this->dom);
 
-     $xpath->registerNamespace("dia", self::DIA_NAMESPACE);
 
-     $id = $element->getAttribute('id');
 
-     $diaString = $xpath->query($query, $element);
 
-     // Normal case
 
-     if ($diaString->length == 1) {
 
-       $diaText = $diaString->item(0);
 
-       $ret = trim($diaText->textContent, '#');
 
-     }
 
-     else {
 
-       echo "Standard state #$id does not contain the expected content: anomaly.\n";
 
-     }
 
-     return array('type' => 'standard', 'name' => $ret);
 
-   }
 
-   /**
 
-    * Extract the actual text content from a query for a Dia string element.
 
-    *
 
-    * This is to be used over XPath query results
 
-    *
 
-    * @param DOMNodeList $nodes
 
-    *
 
-    * @return string
 
-    */
 
-   private function getTextFromDiaString ($nodes) {
 
-     if ($nodes->length == 1) {
 
-       $ret = $nodes->item(0);
 
-       $ret = trim($ret->textContent, '#');
 
-     }
 
-     else {
 
-       $ret = NULL;
 
-     }
 
-     return $ret;
 
-   }
 
-   /**
 
-    * Extract the various information fields from a Dia "UML - Connection".
 
-    *
 
-    * @param DOMElement $element
 
-    *
 
-    * @return array
 
-    */
 
-   protected function getTransitionInfo($element) {
 
-     $xpath = new \DOMXPath($this->dom);
 
-     $xpath->registerNamespace("dia", self::DIA_NAMESPACE );
 
-     $id = $element->getAttribute('id');
 
-     $baseQuery = 'dia:attribute[@name="%s"]/dia:string';
 
-     foreach (array('trigger', 'action', 'guard') as $parameter) {
 
-       $query = sprintf($baseQuery, $parameter);
 
-       $nodes = $xpath->query($query, $element);
 
-       $ret[$parameter] = $this->getTextFromDiaString($nodes);
 
-       // Triggers and actions.
 
-       if ($parameter <> 'guard') {
 
-         $ret[$parameter] = ucfirst($ret[$parameter]);
 
-       }
 
-     }
 
-     $query = 'dia:connections/dia:connection';
 
-     $diaConnections = $xpath->query($query, $element);
 
-     // echo "Connections: {$dia_connections->length}\n";
 
-     if ($diaConnections->length == 2) {
 
-       // echo "Transition $id links" ;
 
-       foreach ($diaConnections as $end) {
 
-         $handle = $end->getAttribute('handle');
 
-         $link   = $end->getAttribute('to');
 
-         switch ($handle) {
 
-           case '0' :
 
-             $kind = 'from';
 
-             $ret['from'] = $link ;
 
-             break;
 
-           case '1' :
 
-             $kind = 'to';
 
-             $ret['to']   = $link ;
 
-             break;
 
-           default:
 
-             $kind = "anomaly($handle)";
 
-           break;
 
-         }
 
-         // echo " $kind $link";
 
-       }
 
-     }
 
-     else {
 
-       echo "Anomaly detected on the connection properties of transition #$id.\n";
 
-     }
 
-     // echo " on ${trigger}[$guard]/$action.\n";
 
-     return $ret;
 
-   }
 
-   /**
 
-    * Load a Dia file into the DOM
 
-    *
 
-    * @param string $filePath
 
-    *
 
-    * @return void
 
-    */
 
-   public function __construct($filePath) {
 
-     $this->dom = new \DOMDocument();
 
-     $this->dom->load($filePath);
 
-     $this->fsm = new Writer();
 
-   }
 
-   /**
 
-    * Parse the DOM to extract the various UML elements to an abstract FSM array.
 
-    *
 
-    * @return array
 
-    */
 
-   public function parse() {
 
-     $query = '//dia:object';
 
-     $xpath = new \DOMXPath($this->dom);
 
-     $xpath->registerNamespace("dia", self::DIA_NAMESPACE);
 
-     $result = $xpath->query($query);
 
-     foreach ($result as $object) {
 
-       $type = $object->getAttribute('type');
 
-       $id   = $object->getAttribute('id');
 
-       switch ($type) {
 
-         case 'UML - State Term':
 
-           $state = $this->getStateTermInfo($object);
 
-           $this->fsm->addState($state['name']);
 
-           $this->states[$id] = $state; // needed to match transitions
 
-           if (($state['type'] == Machine::INIT_STATE) || ($state['type'] == Machine::FINAL_STATE)) {
 
-             $this->fsm->setSpecialState($state['type'], $state['name']);
 
-           }
 
-           break;
 
-         case 'UML - State':
 
-           $state = $this->getStateInfo($object);
 
-           $this->fsm->addState($state['name']);
 
-           // Needed to match transitions.
 
-           $this->states[$id] = $state;
 
-           break;
 
-         case 'UML - Transition':
 
-           $transition  = $this->getTransitionInfo($object);
 
-           $stateName     = $this->states[$transition['from']]['name'];
 
-           $nextStateName = $this->states[$transition['to']]['name'];
 
-           $eventName     = $transition['trigger'];
 
-           $resultName    = $transition['guard'];
 
-           $actionName    = $transition['action'];
 
-           // Not allowed.
 
-           if (empty($resultName)) {
 
-             $resultName = "unnnamed_result_" . $this->resultGenerator++;
 
-           }
 
-           // This add will fail when adding outcomes to existing events, but
 
-           // this is as designed.
 
-           $this->fsm->addEvent($stateName, $eventName);
 
-           $this->fsm->addOutcome($stateName, $eventName, $resultName,
 
-               $nextStateName, $actionName);
 
-           break;
 
-         default:
 
-           echo "Object #$id is of unknown type $type: ignored.\n";
 
-         break;
 
-       }
 
-     }
 
-   }
 
-   /**
 
-    * Facade for Writer.
 
-    *
 
-    * @param string $prefix
 
-    * @param boolean $php
 
-    * @param boolean $overwrite
 
-    */
 
-   public function saveFsm($prefix = 'fsm', $php = FALSE, $overwrite = FALSE) {
 
-     $this->fsm->saveFsm($prefix, $php, $overwrite);
 
-   }
 
- }
 
- error_reporting($erFsmFromDia);
 
- unset ($erFsmFromDia);
 
 
  |