Salome HOME
Fix for bug PAL12235 : Init values on input port not retrievable after write/read...
[modules/superv.git] / src / GraphBase / DataFlowBase_SwitchNode.cxx
index 45cf94a44c5fdd41bd5f930d44f5ddce05a3163a..4586720b2c270f4c8993908e5128e874f02aa435 100644 (file)
@@ -1,16 +1,21 @@
-using namespace std;
-//=============================================================================
-// File      : DataFlowBase_SwitchNode.cxx
-// Created   : 2003
-// Author    : Jean Rahuel, CEA
-// Project   : SALOME
-// $Header:
-//=============================================================================
+//  SUPERV GraphBase : contains fondamental classes for Services, Input Ports, Output Ports Links and Nodes.
+//
+//  Copyright (C) 2003  CEA/DEN, EDF R&D
+//
+//
+//
+//  File   : DataFlowBase_SwitchNode.cxx
+//  Author : Jean Rahuel, CEA
+//  Module : SUPERV
+//  $Header:
 
-#include <strstream>
-#include <iostream>
+using namespace std;
+//#include <sstream>
+//#include <iostream>
 
 #include "DataFlowBase_SwitchNode.hxx"
+#include "DataFlowBase_EndOfSwitchNode.hxx"
+#include "DataFlowBase_Graph.hxx"
 
 GraphBase::SwitchNode::SwitchNode() :
   GraphBase::GOTONode::GOTONode() {
@@ -36,7 +41,7 @@ GraphBase::SwitchNode::SwitchNode( CORBA::ORB_ptr ORB ,
                                    const long   X ,
                                    const long   Y ,
                                    int * Graph_prof_debug ,
-                                   ostream * Graph_fdebug ) :
+                                   ofstream * Graph_fdebug ) :
   GraphBase::GOTONode::GOTONode( ORB , ptrNamingService , FuncName , aPythonFunction ,
                                  NodeName , akind , NodeFirstCreation ,
                                  NodeLastModification  , NodeEditorRelease ,
@@ -70,3 +75,353 @@ GraphBase::SwitchNode::~SwitchNode() {
 //    delete [] _Comment;
 }
 
+bool GraphBase::SwitchNode::CheckSwitch() const {
+  GraphBase::EndOfSwitchNode * anEndSwitchNode ;
+  anEndSwitchNode = (GraphBase::EndOfSwitchNode * ) CoupledNode() ;
+  cdebug_in << Name() << "->SwitchNode::CheckSwitch EndSwitchNode "
+            << anEndSwitchNode->Name() << endl;
+  int i ;
+
+  string anErrorMessage = string( "SwitchCheck of " ) + string( Name() ) + " --> " +
+                          string( anEndSwitchNode->Name() ) + string( " :\n" ) ;
+  bool RetVal = true ;
+
+//All nodes between Switch and EndSwitch will have _BranchOfSwitchDone to false
+//When we have to execute such a node in a switchbranch, if _BranchOfSwitchDone is true we have
+// an error ; else we set _BranchOfSwitchDone to true
+  for ( i = 0 ; i < GetNodeOutPortsSize() ; i++ ) {
+    GraphBase::OutPort * anOutPort = GetChangeNodeOutPort( i ) ;
+    if ( anOutPort->IsSwitch() || anOutPort->IsGate() ) {
+      int j ;
+      for ( j = 0 ; j < anOutPort->InPortsSize() ; j++ ) {
+        GraphBase::InPort * anInPort = anOutPort->ChangeInPorts( j ) ;
+        GraphBase::ComputingNode * aNode ;
+        aNode = GraphOfNode()->GetChangeGraphNode( anInPort->NodeName() ) ;
+        if ( aNode && aNode != anEndSwitchNode ) {
+          aNode->InitBranchOfSwitchDone( true , anEndSwitchNode , anErrorMessage ) ;
+       }
+      }
+    }
+  }
+
+  bool DefaultConnected = false ;
+//OutPorts of the SwitchNode
+  for ( i = 0 ; i < GetNodeOutPortsSize() ; i++ ) {
+    GraphBase::OutPort * anOutPort = GetChangeNodeOutPort( i ) ;
+    if ( anOutPort->IsSwitch() || anOutPort->IsGate() ) {
+// We have a branch of the switch
+      anErrorMessage = anErrorMessage + string( "Branch " ) + string( Name() ) + string( "( " ) +
+                       string( anOutPort->PortName() ) + string( " ) :\n" ) ;
+      cdebug << endl << Name() << "->SwitchNode::CheckSwitch OutPort " << anOutPort->PortName()
+             << " " << anOutPort->PortStatus() << " " << anOutPort->Kind()
+             << " SWITCHBRANCH" << endl
+             << "===================================================================================="
+             << endl ;
+
+//JR 11.02.2005 : if Default is not connected and if Default is true at execution time, the SwitchNode
+// execution will be aborted
+//Behavior : in that case, that means that a SwitchBranch should be a DefaultBranch and it is not the case !
+//1. DEFAULT_OUTPORT
+//JR 07.04.2005 Debug : an OutPort of the SwitchNode may be linked to the DefaultPort of
+//                      the EndSwitchNode <==>
+//                      SwitchNode( Default ) --> EndSwitchNode( Default )
+      bool EndSwitchNode_Default = false ;
+      if ( anOutPort->InPortsSize() ) {
+        GraphBase::InPort * anInPort = anOutPort->ChangeInPorts( 0 ) ;
+        GraphBase::ComputingNode * aNode ;
+        aNode = GraphOfNode()->GetChangeGraphNode( anInPort->NodeName() ) ;
+        if ( aNode == anEndSwitchNode ) {
+          EndSwitchNode_Default = true ;
+       }
+      }
+//JR 07.04.2005      if ( anOutPort->IsGate() ) {
+      if ( anOutPort->IsGate() || EndSwitchNode_Default ) {
+        if ( anOutPort->InPortsSize() == 0 ) {
+// DefaultPort of the SwitchNode is not connected
+          cdebug << Name() << "->SwitchNode::CheckSwitch EndSwitchNode "
+                 << anEndSwitchNode->Name() << " OutPort " << anOutPort->PortName() << " "
+                 << anOutPort->InPortsSize() << " InPortsSize EndSwitch(Default) "
+                 << anEndSwitchNode->GetNodeInGate()->PortStatus() << "WARNING" << endl;
+       }
+        else {
+// But the DefaultPort of the EndSwitchNode is connected : so there is a branch going to
+// that DefaultPort
+          cdebug << Name() << "->SwitchNode::CheckSwitch EndSwitchNode "
+                 << anEndSwitchNode->Name() << " OutPort " << anOutPort->PortName() << " "
+                 << " " << anOutPort->PortStatus() << " " << anOutPort->InPortsSize() << " InPortsSize "
+                     << endl ;
+          DefaultConnected = true ;
+
+          anEndSwitchNode->InitEndSwitchInPortLinked() ;
+
+// That DefaultBranch have to go directly to the EndSwitchNode
+          GraphBase::InPort * anInPort = anOutPort->ChangeInPorts( 0 ) ;
+          GraphBase::ComputingNode * aNode ;
+          aNode = GraphOfNode()->GetChangeGraphNode( anInPort->NodeName() ) ;
+          if ( aNode != anEndSwitchNode ) {
+            anErrorMessage = anErrorMessage + string( Name() ) + "( " +
+                             string( anOutPort->PortName() ) +
+                             string( " ) should not be linked to " ) +
+                             string( aNode->Name() ) + string( "( " ) +
+                             string( anInPort->PortName() ) + string ( " )\n" ) ;
+            cdebug << "1. " << Name() << "->SwitchNode::CheckSwitch EndSwitchNode "
+                   << anEndSwitchNode->Name() << " for OutPort " << anOutPort->PortName()
+                   << " linked to " << aNode->Name() << " ERROR false" << endl;
+            RetVal = false ;
+         }
+          cdebug << endl << Name() << " Check of " << anOutPort->PortName() << " switch port branch"
+                 << " to EndSwitchNode" << endl ;
+// All of InPorts of the EndSwitchNode have to be done :
+          int k ;
+          for ( k = 0 ; k < GetNodeOutPortsSize() ; k++ ) {
+            GraphBase::OutPort * anOutPort = GetChangeNodeOutPort( k ) ;
+//JR 06.07.2005 : the InGatePort must also be counted now (enhancement) ...
+//                But it is done in EndSwitchNode::CheckEndSwitchInPortsLinked
+            if ( !anOutPort->IsGate() ) {
+              GraphBase::InPort * anInPort = NULL ;
+//JR 22.06.2005 : Enhancement of the behaviour :
+//                For the DefaultBranch, if we have same PortsNames, Values are automatically
+//                    transmitted
+//                But for the DefaultBranch, if we have NOT same PortsNames, we may create links.
+//                Look at GraphSyrControlAve* ...
+              int kk ;
+//JR 22.06.2005 : At first look at OutPorts linked to InPorts of the EndSwitchNode with
+//                different PortsNames :
+              for ( kk = 0 ; kk < anOutPort->InPortsSize() ; kk++ ) {
+                anInPort = anOutPort->ChangeInPorts( kk ) ;
+                if ( GraphOfNode()->GetGraphNode( anInPort->NodeName() ) == anEndSwitchNode ) {
+                  if ( !anEndSwitchNode->GetChangeInPort( anOutPort->PortName() ) ) {
+                    if ( anInPort && !anEndSwitchNode->DecrEndSwitchInPortLinked( anInPort ,
+                                                                                  anErrorMessage ) ) {
+                      cdebug << "2. " << Name() << "->SwitchNode::CheckSwitch EndSwitchNode : "
+                             << anEndSwitchNode->Name() << " to port " << anInPort->PortName()
+                             << " from port " << Name() << "( " << anOutPort->PortName()
+                             << " ) ERROR false" << endl;
+                      RetVal = false ;
+                   }
+                 }
+               }
+             }
+//Get an InPort of the EndSwitchNode with the same name as that OutPort of the SwitchNode
+              anInPort = anEndSwitchNode->GetChangeInPort( anOutPort->PortName() ) ;
+              if ( anInPort && !anEndSwitchNode->DecrEndSwitchInPortLinked( anInPort ,
+                                                                            anErrorMessage ) ) {
+                cdebug << "3. " << Name() << "->SwitchNode::CheckSwitch EndSwitchNode "
+                       << anEndSwitchNode->Name() << " for port " << anInPort->PortName()
+                       << " ERROR false" << endl;
+                RetVal = false ;
+             }
+              else {
+                cdebug << Name() << "->SwitchNode::CheckSwitch EndSwitchNode "
+                       << anEndSwitchNode->Name() << " OutPort " << anOutPort->PortName()
+                       << " " << anOutPort->PortStatus() << " " << anOutPort->Kind()
+                       << " not in EndSwitchNode : IGNORED"
+                       << endl;
+             }
+//JR 06.07.2005 : the InGatePort must also be counted now (enhancement) ...
+//                But it is done in EndSwitchNode::CheckEndSwitchInPortsLinked
+           }
+            else {
+              cdebug << Name() << "->SwitchNode::CheckSwitch EndSwitchNode "
+                     << anEndSwitchNode->Name() << " OutPort " << anOutPort->PortName()
+                     << " " << anOutPort->PortStatus() << " " << anOutPort->Kind()
+                     << " SwitchPort or Gate : IGNORED"
+                     << endl;
+           }
+         }
+// Check that all InPorts of the EndSwitchNode have a value :
+          if ( !anEndSwitchNode->CheckEndSwitchInPortsLinked( anErrorMessage ) ) {
+            cdebug << "4. " << Name() << "->SwitchNode::CheckSwitch EndSwitchNode "
+                   << anEndSwitchNode->Name() << " " << aNode->Name()
+                   << " ERROR false" << endl;
+            RetVal = false ;
+          }
+       }
+      }
+
+//2. SWITCH_OUTPORT
+      else {
+// We have a SwitchPort which is connected to Gates
+// We initialize the _NodeDoneInBranchOfSwitch field to false for each node of the
+// InPortsSize() branch(es)
+        int j ;
+        for ( j = 0 ; j < anOutPort->InPortsSize() ; j++ ) {
+          GraphBase::InPort * anInPort = anOutPort->ChangeInPorts( j ) ;
+          GraphBase::ComputingNode * aNode ;
+          aNode = GraphOfNode()->GetChangeGraphNode( anInPort->NodeName() ) ;
+          if ( aNode && aNode != anEndSwitchNode ) {
+            if ( !aNode->InitBranchOfSwitchDone( false , anEndSwitchNode , anErrorMessage ) ) {
+              anErrorMessage = anErrorMessage + string( Name() ) +
+                               string( " Node(s) are common to two or more branchs of switch.\n" ) ;
+              cdebug << "5. " << Name() << "->ComputingNode::InitBranchOfSwitchDone ERROR false"
+                     << " Node common to two or more branchs of switch" << endl ;
+              RetVal = false ;
+           }
+         }
+       }
+
+        anEndSwitchNode->InitEndSwitchInPortLinked() ;
+
+// At first all of not SwitchPort should have to be done also :
+// Not Switch Branches (Gate not connected to a switch port of a SwitchNode) :
+// They are always executed except if we execute the DefaultBranch ...
+        
+        cdebug << "1. " << Name() << "->SwitchNode::CheckSwitch at first NOTSWITCHBRANCH_OUTPORT FOR "
+               << anOutPort->PortName() << " " << anOutPort->PortStatus() << " " << anOutPort->Kind()
+               << " :" << endl ;
+        for ( j = 0 ; j < GetNodeOutPortsSize() ; j++ ) {
+          GraphBase::OutPort * anOutPort = GetChangeNodeOutPort( j ) ;
+          cdebug << Name() << "->SwitchNode::CheckSwitch for OutPort" << j << " "
+                 << anOutPort->PortName() << " " << anOutPort->PortStatus() << " " << anOutPort->Kind()
+                 << " InPortsSize " << anOutPort->InPortsSize() << endl ;
+          if ( !anOutPort->IsSwitch() && !anOutPort->IsGate() ) {
+//JR 23.06.2005 : implicit connection with same PortsNames was missing in SwitchNodeBranches :
+            if ( anOutPort->IsExternConnected() ) {
+              GraphBase::InPort * anInPort ;
+              anInPort = anEndSwitchNode->GetChangeInPort( anOutPort->PortName() ) ;
+              if ( anInPort ) {
+                anErrorMessage = anErrorMessage + string( "Implicit NotSwitchBranch " ) +
+                                 string( Name() ) + string( "( " ) + string( anOutPort->PortName() ) +
+                                 string( " ) --> " ) + string( anEndSwitchNode->Name() ) +
+                                 string( "( " ) + string( anInPort->PortName() ) + string( " ).\n" ) ;
+                if ( !anEndSwitchNode->DecrEndSwitchInPortLinked( anInPort ,
+                                                                  anErrorMessage ) ) {
+                  cdebug << "6. " << Name() << "->SwitchNode::CheckSwitch EndSwitchNode "
+                         << anEndSwitchNode->Name() << " for port " << anInPort->PortName()
+                         << " ERROR false" << endl;
+                  RetVal = false ;
+               }
+                cdebug << Name() << "->SwitchNode::CheckSwitch Check of '"
+                       << anOutPort->PortName() << "' " << anOutPort->Kind()
+                       << " NOT switch port Branch to EndSwitchNode "
+                       << anEndSwitchNode->Name() << " is done" << endl ;
+             }
+              else {
+                cdebug << Name() << "->SwitchNode::CheckSwitch Check of '"
+                       << anOutPort->PortName() << "' " << anOutPort->Kind()
+                       << " NOT switch port does not exist in EndSwitchNode. Ignoed " << endl ;
+             }
+           }
+            else {
+              int k ;
+              for ( k = 0 ; k < anOutPort->InPortsSize() ; k++ ) {
+                GraphBase::InPort * anInPort = anOutPort->ChangeInPorts( k ) ;
+                GraphBase::ComputingNode * aNode ;
+                aNode = GraphOfNode()->GetChangeGraphNode( anInPort->NodeName() ) ;
+                if ( aNode ) {
+                  const GraphBase::InPort * anInGatePort = aNode->GetNodeInGate() ;
+                  cdebug << Name() << "->SwitchNode::CheckSwitch InPort" << k << ". "
+                         << anInPort->PortName() << " of " << aNode->Name() << " :" << endl ;
+// Direct Connexion to the EndSwitchNode : always executed (except for DefaultBranch)
+                  if ( aNode == anEndSwitchNode ) {
+                    anErrorMessage = anErrorMessage + string( "NotSwitchBranch " ) + string( Name() ) +
+                                     string( "( " ) + string( anOutPort->PortName() ) +
+                                     string( " ) --> " ) + string( aNode->Name() ) +
+                                     string( "( " ) + string( anInPort->PortName() ) +
+                                     string( " ).\n" ) ;
+                    if ( !anEndSwitchNode->DecrEndSwitchInPortLinked( anInPort ,
+                                                                      anErrorMessage ) ) {
+                      cdebug << "7. " << Name() << "->SwitchNode::CheckSwitch EndSwitchNode "
+                             << anEndSwitchNode->Name() << " for port " << anInPort->PortName()
+                             << " ERROR false" << endl;
+                      RetVal = false ;
+                   }
+                    cdebug << Name() << "->SwitchNode::CheckSwitch Check of '"
+                           << anOutPort->PortName() << "' " << anOutPort->Kind()
+                           << " NOT switch port Branch to EndSwitchNode "
+                           << aNode->Name() << " is done" << endl ;
+                 }
+// Check that InGate is not linked from a SwitchPort or a GatePort of the SwitchNode :
+                  else if ( !anInGatePort->GetOutPort() ) {
+                    cdebug << Name() << "->SwitchNode::CheckSwitch Check of '"
+                           << anOutPort->PortName() << "' " << anOutPort->Kind()
+                           << " NOT switch port Branch to node "
+                           << aNode->Name() << " will be done" << endl ;
+                    anErrorMessage = anErrorMessage + string( "NotSwitchBranch " ) + string( Name() ) +
+                                     string( "( " ) + string( anOutPort->PortName() ) +
+                                     string( " ) --> " ) + string( aNode->Name() ) +
+                                     string( "( " ) + string( anInPort->PortName() ) +
+                                     string( " ).\n" ) ;
+                    if ( !aNode->CheckSwitch( anEndSwitchNode , anErrorMessage ) ) {
+                      cdebug << "8. " << Name() << "->SwitchNode::CheckSwitch EndSwitchNode "
+                             << anEndSwitchNode->Name() << " " << aNode->Name()
+                             << " ERROR false" << endl;
+                      RetVal = false ;
+                   }
+                    cdebug << Name() << "->SwitchNode::CheckSwitch Check of '"
+                           << anOutPort->PortName() << "' " << anOutPort->Kind()
+                           << " NOT switch port Branch to node "
+                           << aNode->Name() << " is done" << endl ;
+                 }
+                  else {
+                    cdebug << Name() << "->SwitchNode::CheckSwitch Check of '"
+                           << anOutPort->PortName() << "' " << anOutPort->Kind()
+                           << " NOT switch port Branch to node "
+                           << aNode->Name() << " has InGate connected IGNORED for that branch"
+                           << endl ;
+                 }
+               }
+             }
+           }
+         }
+       }
+
+        cdebug << "2. "<< Name() << "->SwitchNode::CheckSwitch and now SWITCH_BRANCH_OUTPORT "
+               << anOutPort->PortName()
+               << " " << anOutPort->PortStatus() << " " << anOutPort->Kind() << endl ;
+// And all links from the switchport anOutPort (connected to Gates) will be checked
+        for ( j = 0 ; j < anOutPort->InPortsSize() ; j++ ) {
+          GraphBase::InPort * anInPort = anOutPort->ChangeInPorts( j ) ;
+          GraphBase::ComputingNode * aNode ;
+          aNode = GraphOfNode()->GetChangeGraphNode( anInPort->NodeName() ) ;
+          if ( aNode == NULL ) {
+            cdebug << Name() << "->SwitchNode::CheckSwitch Check of " << anOutPort->PortName()
+                   << " switch port branch "
+                   << aNode->Name() << " ignored" << endl ;
+         }
+
+
+          else {
+// That branch does not go directly to the EndSwitchNode
+// Control the OutPorts Values of the SwitchNode through the branch
+            cdebug << Name() << " Check of " << anOutPort->PortName()
+                   << " switch port Branch to node "
+                   << aNode->Name() << endl ;
+            if ( !aNode->CheckSwitch( anEndSwitchNode , anErrorMessage ) ) {
+              cdebug << "9. " << Name() << "->SwitchNode::CheckSwitch EndSwitchNode "
+                     << anEndSwitchNode->Name() << " " << aNode->Name() << " ERROR false"
+                     << endl;
+              RetVal = false ;
+           }
+         }
+        }
+// Check that all InPorts of the EndSwitchNode have a value :
+        if ( !anEndSwitchNode->CheckEndSwitchInPortsLinked( anErrorMessage ) ) {
+          cdebug << "10. " << Name() << "->SwitchNode::CheckSwitch EndSwitchNode "
+                 << anEndSwitchNode->Name() << " CheckEndSwitchInPortsLinked ERROR false"
+                 << endl;
+          RetVal = false ;
+        }
+        else {
+          cdebug << Name() << "->SwitchNode::CheckSwitch OutPort " << anOutPort->PortName()
+                 << " " << anOutPort->PortStatus() << " " << anOutPort->Kind()
+                 << " SWITCHBRANCH IS OK" << endl << endl ;
+       }
+      }
+    }
+    else {
+      cdebug << Name() << "->SwitchNode::CheckSwitch OutPort " << anOutPort->PortName()
+             << " " << anOutPort->PortStatus() << " " << anOutPort->Kind() << " NOTSWITCHBRANCH"
+             << " IGNORED" << endl ;
+    }
+  }
+
+  if ( !RetVal ) {
+    GraphOfNode()->SetMessages( anErrorMessage ) ;
+  }
+
+  cdebug_out << Name() << "->SwitchNode::CheckSwitch EndSwitchNode "
+             << anEndSwitchNode->Name() << " RetVal " << RetVal << endl;
+  return RetVal ;
+}
+