Salome HOME
A part of the code of Valid() method is now in Executable() method
[modules/superv.git] / src / GraphEditor / DataFlowEditor_OutNode.cxx
index 71d498407589cf09a63e76d02d225caa2395bb5f..5221b4f8f01ffc09eb0b925e8236f1798842bc0d 100644 (file)
@@ -32,8 +32,28 @@ using namespace std;
 #include "DataFlowBase_EndOfLoopNode.hxx"
 #include "DataFlowBase_EndOfSwitchNode.hxx"
 
-#include "DataFlowExecutor_DataFlow.hxx"
-extern GraphExecutor::FiniteStateMachine * theAutomaton ;
+//map< string , GraphBase::Graph * > GraphEditor::OutNode::_MapOfGraphs;
+map< string , int > _MapOfGraphNames;
+
+string GraphInstanceName( const char * aGraphName ) {
+  int GraphInstanceNumber = _MapOfGraphNames[ aGraphName ] ;
+  if ( GraphInstanceNumber ) {
+    _MapOfGraphNames[ aGraphName ] = GraphInstanceNumber + 1 ;
+  }
+  else {
+    GraphInstanceNumber = 0 ;
+    _MapOfGraphNames[ aGraphName ] = GraphInstanceNumber + 1 ;
+  }
+  string theGraphInstanceName = string( aGraphName ) ;
+  if ( GraphInstanceNumber ) {
+    theGraphInstanceName += "_" ;
+    ostringstream astr ;
+    astr << GraphInstanceNumber ;
+    theGraphInstanceName += astr.str() ;
+  }
+  return theGraphInstanceName ;
+}
+
 
 // Implementation de la classe GraphEditor::Graph
 
@@ -65,19 +85,16 @@ GraphEditor::OutNode::OutNode( CORBA::ORB_ptr ORB ,
 
   if ( aKindOfNode == SUPERV::DataFlowGraph ) {
     _StreamGraph = NULL ;
-//    _Graph = new GraphBase::Graph( ORB , ptrNamingService , DataFlowName , DebugFileName ) ;
     _Graph = new GraphBase::Graph( ORB , ptrNamingService , DataFlowName , aKindOfNode ,
-                                   _prof_debug , _fdebug ) ;
+                                   _prof_debug , _fdebug ) ; 
+//    MapGraph( _Graph , _Graph->Name() ) ;
   }
   else if ( aKindOfNode == SUPERV::DataStreamGraph ) {
-//    _StreamGraph = new GraphBase::StreamGraph( ORB , ptrNamingService , DataFlowName , DebugFileName ) ;;
     _StreamGraph = new GraphBase::StreamGraph( ORB , ptrNamingService , DataFlowName , aKindOfNode ,
                                                _prof_debug , _fdebug ) ;
     _Graph = _StreamGraph ;
+//    MapGraph( _Graph , _Graph->Name() ) ;
   }
-//  if ( aKindOfNode == SUPERV::DataFlowGraph || aKindOfNode == SUPERV::DataStreamGraph ) {
-//    theAutomaton->MapGraph( _Graph , _Graph->Name() ) ;
-//  }
   _Orb = CORBA::ORB::_duplicate( ORB ) ;
   _Imported = false ;
   _Valid = false ;
@@ -101,11 +118,6 @@ GraphEditor::OutNode::OutNode(
                      const char * DataFlowComputer ,
                      const char * DataFlowComment ,
                      const char * DebugFileName ) {
-//             Graph( ORB , ptrNamingService , DataFlowService , DataFlowComponentName ,
-//                    DataFlowInterfaceName , DataFlowName , DataFlowkind ,
-//                    DataFlowFirstCreation , DataFlowLastModification  ,
-//                    DataFlowEditorRelease , DataFlowAuthor ,
-//                    DataFlowComputer , DataFlowComment , DebugFileName ) {
   _Graph = NULL ;
   Set_prof_debug( ORB , DebugFileName ) ;
 
@@ -117,7 +129,7 @@ GraphEditor::OutNode::OutNode(
                                    DataFlowEditorRelease , DataFlowAuthor ,
                                    DataFlowComputer , DataFlowComment ,
                                    _prof_debug , _fdebug ) ;
-//                                   DataFlowComputer , DataFlowComment , DebugFileName ) ;
+//    MapGraph( _Graph , _Graph->Name() ) ;
   }
   else if ( DataFlowkind == SUPERV::DataStreamGraph ) {
     _StreamGraph = new GraphBase::StreamGraph( ORB , ptrNamingService , DataFlowService , DataFlowComponentName ,
@@ -126,12 +138,9 @@ GraphEditor::OutNode::OutNode(
                                                DataFlowEditorRelease , DataFlowAuthor ,
                                                DataFlowComputer , DataFlowComment ,
                                                _prof_debug , _fdebug ) ;
-//                    DataFlowComputer , DataFlowComment , DebugFileName ) ;
     _Graph = _StreamGraph ;
+//    MapGraph( _Graph , _Graph->Name() ) ;
   }
-//  if ( DataFlowkind == SUPERV::DataFlowGraph || DataFlowkind == SUPERV::DataStreamGraph ) {
-//    theAutomaton->MapGraph( _Graph , _Graph->Name() ) ;
-//  }
   _Orb = CORBA::ORB::_duplicate( ORB ) ;
   _Imported = false ;
   _Valid = false ;
@@ -140,7 +149,7 @@ GraphEditor::OutNode::OutNode(
 } ;
 
 GraphEditor::OutNode::~OutNode() {
-//  theAutomaton->EraseGraph( Graph->Name() ) ;
+//  EraseGraph( Graph->Name() ) ;
 //  delete _DataFlowNode ;
 //  delete _DataFlowDatas ;
 //  delete _GT ;
@@ -148,14 +157,14 @@ GraphEditor::OutNode::~OutNode() {
 
 bool GraphEditor::OutNode::Name( const char * aName ) {
   bool RetVal = false ;
-  if ( !theAutomaton->GraphName( aName ) ) {
-    char * aGraphName = Graph()->Name() ;
+//  if ( !GraphName( aName ) ) {
+//    char * aGraphName = Graph()->Name() ;
     RetVal = Graph()->Name( aName ) ;
-    if ( RetVal ) {
-      theAutomaton->EraseGraph( aGraphName ) ;
-      theAutomaton->MapGraph( Graph() , aName ) ;
-    }
-  }
+//    if ( RetVal ) {
+//      EraseGraph( aGraphName ) ;
+//      MapGraph( Graph() , aName ) ;
+//    }
+//  }
   return RetVal ;
 }
 
@@ -197,7 +206,8 @@ bool GraphEditor::OutNode::LoadDataFlow( const GraphBase::SGraph * aDataFlow ) {
     cdebug << "GraphEditor::OutNode::LoadDataFlow() LoadDatas GraphNodesSize " << Graph()->GraphNodesSize() << endl;
     RetVal = LoadDatas( aMapOfNodes , (*aDataFlow).Datas ) ;
   }
-  cdebug_out << "GraphEditor::OutNode::LoadDataFlow done GraphNodesSize " << Graph()->GraphNodesSize() << endl;
+  cdebug_out << "GraphEditor::OutNode::LoadDataFlow done GraphNodesSize " << Graph()->GraphNodesSize()
+             << " _Valid " << _Valid << " _Executable " << _Executable << " RetVal " << RetVal << endl;
   return RetVal ;
 }
 
@@ -208,8 +218,9 @@ bool GraphEditor::OutNode::LoadXml( const char* myFileName , GraphBase::ListOfSG
     cdebug << "GraphEditor::OutNode::LoadXml() No file" << endl;
     _Imported = true ;
     char * aDataFlowName = Graph()->Name() ;
-    Name( theAutomaton->GraphInstanceName( Graph()->Name() ).c_str() ) ;
-    theAutomaton->MapGraph( Graph() , Graph()->Name() ) ;
+//  Name( Graph()->Name() ) ;
+    Name( GraphInstanceName( Graph()->Name() ).c_str() ) ;
+//    MapGraph( Graph() , Graph()->Name() ) ;
     cdebug << "GraphEditor::OutNode::LoadXml() " << aDataFlowName << " --> " << Graph()->Name() << endl;
     RetVal = true ;
   }
@@ -250,8 +261,9 @@ bool GraphEditor::OutNode::LoadInfo(const GraphBase::SNode &aDataFlowInfo ) {
 //  InterfaceName( aDataFlowInfo.theInterfaceName.c_str() ) ;
   if ( Graph()->IsDataStreamNode() || aDataFlowInfo.theKind == SUPERV::DataFlowGraph ) {
     char * aDataFlowName = Graph()->Name() ;
-    Graph()->Name( theAutomaton->GraphInstanceName( aDataFlowInfo.theName.c_str() ).c_str() ) ;
-    theAutomaton->MapGraph( Graph() , Graph()->Name() ) ;
+//    Graph()->Name( aDataFlowInfo.theName.c_str() ) ;
+    Graph()->Name( GraphInstanceName( aDataFlowInfo.theName.c_str() ).c_str() ) ;
+//    MapGraph( Graph() , Graph()->Name() ) ;
     cdebug << "GraphEditor::OutNode::LoadInfo " << aDataFlowName << " --> " << Graph()->Name()
            << " aDataFlowInfo.Kind " << aDataFlowInfo.theKind << " Kind() " << Graph()->Kind() << endl ;
     if ( Graph()->IsDataStreamNode() ) {
@@ -394,21 +406,36 @@ bool GraphEditor::OutNode::LoadNodes(map< string , int > & aMapOfNodes ,
       return false ;
     }
   }
+
+  // setting coupled pairs of nodes: Loop-EndLoop, Switch-EndSwitch, InLine-GOTO, MacroNode-Graph
   for ( i = 0 ; i < (int ) aListOfNodes.size() ; i++ ) {
     GraphBase::SNode aNode = aListOfNodes[ i ] ;
     cdebug << "GraphEditor::OutNode::LoadNodes " << aNode.theName.c_str() << " Coupled to "
            << aNode.theCoupledNode.c_str() << endl ;
-    anInNode = (GraphEditor::InNode * ) Graph()->GetChangeGraphNode( aNode.theName.c_str() )->GetInNode() ;
+    anInNode = (GraphEditor::InNode * ) Graph()->GetChangeGraphNode( aMapOfNodes[ aNode.theName.c_str() ] )->GetInNode() ;
+
     if ( anInNode->IsOneOfGOTONodes() && strlen( aNode.theCoupledNode.c_str() ) ) {
-      GraphBase::GOTONode * aCoupledNode ;
-      aCoupledNode = (GraphBase::GOTONode * ) Graph()->GetGraphNode( aNode.theName.c_str() ) ;
-      GraphBase::GOTONode * aCoupledCoupledNode ;
-      aCoupledCoupledNode = (GraphBase::GOTONode * ) Graph()->GetChangeGraphNode( aNode.theCoupledNode.c_str() ) ;
-      if ( aCoupledCoupledNode != NULL ) {
-        aCoupledNode->CoupledNode( aCoupledCoupledNode ) ;
+      GraphBase::GOTONode * aGOTONode;
+      aGOTONode = (GraphBase::GOTONode * ) anInNode->ComputingNode() ;
+
+      // asv : 25.10.04 : if aNode is a MacroNode, then its coupled node (another Graph) is NOT in aMapOfNodes 
+      //                  and we must couple MacroNode only with name to its subgraph
+      if ( aGOTONode->IsMacroNode() ) {
+        cdebug << "GraphEditor::OutNode::LoadNodes MacroNode " << aNode.theName.c_str()
+              << " is Coupled ONLY WITH NAME to its subgraph " << aNode.theCoupledNode.c_str() << endl;
+        aGOTONode->CoupledNodeName( aNode.theCoupledNode.c_str() ) ;
       }
-      else {
-        aCoupledNode->CoupledNodeName( aNode.theCoupledNode.c_str() ) ;
+      else { // coupling Loop-EndLoop, Switch-EndSwitch, InLine-GOTO
+       // asv : fix for 6822 : using map because if aNode's name is the same as some existing node's name
+       // aMap will give the correct index any way (aMap has already a different name for aNode, SNode still has old name)
+       int aCoupledNodeIndex = aMapOfNodes[ aNode.theCoupledNode.c_str() ] ;
+       cdebug << "GraphEditor::OutNode::LoadNodes " << aNode.theCoupledNode.c_str()
+              << " index " << aCoupledNodeIndex << endl ;
+        GraphBase::GOTONode * aCoupledNode ;
+        aCoupledNode = (GraphBase::GOTONode * ) Graph()->GetChangeGraphNode( aCoupledNodeIndex ) ;
+        cdebug << "GraphEditor::OutNode::LoadNodes " << aNode.theName.c_str()
+               << " is now Coupled to " << aNode.theCoupledNode.c_str() << endl ;
+        aGOTONode->CoupledNode( aCoupledNode ) ;
       }
     }
   }
@@ -419,6 +446,7 @@ bool GraphEditor::OutNode::LoadNodes(map< string , int > & aMapOfNodes ,
 bool GraphEditor::OutNode::LoadLinks(map< string , int > & aMapOfNodes ,
                                      const GraphBase::ListOfSLinks &aListOfLinks ) {
   bool RetVal = true ;
+  bool RetAddLink ;
   cdebug_in << "GraphEditor::OutNode::LoadLinks" << endl ;
 //  MESSAGE( "GraphEditor::OutNode::LoadLinks" );
   int i , j ;
@@ -432,21 +460,16 @@ bool GraphEditor::OutNode::LoadLinks(map< string , int > & aMapOfNodes ,
            << aLink.ToServiceParameterName.c_str() << " )" << endl ;
     if ( Graph()->GetGraphNode( aMapOfNodes[ aLinkFromNodeName->c_str() ] ) &&
          Graph()->GetGraphNode( aMapOfNodes[ aLinkToNodeName->c_str() ] ) ) {
-//      GraphBase::ComputingNode * aFromNode = (GraphBase::ComputingNode * ) Graph()->GetGraphNode( aMapOfNodes[ aLinkFromNodeName->c_str() ] ) ;
-//      const GraphBase::OutPort * anOutPort = aFromNode->GetOutPort( aLink.FromServiceParameterName.c_str() ) ;
-      RetVal = AddLink( Graph()->GetGraphNode( aMapOfNodes[ aLinkFromNodeName->c_str() ] )->Name() ,
-                        aLink.FromServiceParameterName.c_str() ,
-                        Graph()->GetGraphNode( aMapOfNodes[ aLinkToNodeName->c_str() ] )->Name() ,
-                        aLink.ToServiceParameterName.c_str() ) ;
-//                        , *anOutPort->Value() ) ;
+//JR 08.02.2005 : Rule of CEA : a bad graph may be stored in a xml
+      RetAddLink = AddLink( Graph()->GetGraphNode( aMapOfNodes[ aLinkFromNodeName->c_str() ] )->Name() ,
+                            aLink.FromServiceParameterName.c_str() ,
+                            Graph()->GetGraphNode( aMapOfNodes[ aLinkToNodeName->c_str() ] )->Name() ,
+                            aLink.ToServiceParameterName.c_str() ) ;
     }
     else {
       RetVal = false ;
     }
-//                      aLink.aLinkValue ) ;
-    if ( !RetVal )
-      break ;
-    else {
+    if ( RetVal && RetAddLink ) {
       for ( j = 0 ; j < (int ) aLink.aListOfCoords.size() ; j++ ) {
         RetVal = AddLinkCoord( Graph()->GetGraphNode( aMapOfNodes[ aLinkFromNodeName->c_str() ] )->Name() ,
                                         aLink.FromServiceParameterName.c_str() ,
@@ -462,13 +485,14 @@ bool GraphEditor::OutNode::LoadLinks(map< string , int > & aMapOfNodes ,
     delete aLinkFromNodeName ;
     delete aLinkToNodeName ;
   }
-  cdebug_out << "GraphEditor::OutNode::LoadLinks" << endl ;
+  cdebug_out << "GraphEditor::OutNode::LoadLinks " << RetVal << endl ;
   return RetVal ;
 }
 
 bool GraphEditor::OutNode::LoadDatas(map< string , int > & aMapOfNodes ,
                                      const GraphBase::ListOfSLinks &aListOfDatas ) {
   bool RetVal = true ;
+  bool RetAddLink ;
   cdebug_in << "GraphEditor::OutNode::LoadDatas" << endl ;
 //  MESSAGE( "GraphEditor::OutNode::LoadDatas" );
   int i ;
@@ -483,15 +507,15 @@ bool GraphEditor::OutNode::LoadDatas(map< string , int > & aMapOfNodes ,
 //           << aMapOfNodes[ aLinkFromNodeName->c_str() ] << endl ;
 //      cout << "          " << aLink.ToNodeName.c_str() << " "
 //           << aMapOfNodes[ aLinkToNodeName->c_str() ] << endl ;
-    RetVal = Graph()->AddInputData( Graph()->GetGraphNode( aMapOfNodes[ aLinkToNodeName->c_str() ] )->Name() ,
-                                    aLink.ToServiceParameterName.c_str() ,
-                                    aLink.aLinkValue ) ;
+    RetAddLink = Graph()->AddInputData( Graph()->GetGraphNode( aMapOfNodes[ aLinkToNodeName->c_str() ] )->Name() ,
+                                        aLink.ToServiceParameterName.c_str() ,
+                                        aLink.aLinkValue ) ;
     delete aLinkFromNodeName ;
     delete aLinkToNodeName ;
     if ( !RetVal )
       break ;
   }
-  cdebug_out << "GraphEditor::OutNode::LoadDatas" << endl ;
+  cdebug_out << "GraphEditor::OutNode::LoadDatas " << RetVal << endl ;
   return RetVal ;
 }
 
@@ -514,7 +538,7 @@ bool GraphEditor::OutNode::SaveXml(const char* filename) {
 //    cout << "GraphEditor::OutNode::SaveXML " << xml << endl ;
 //    f << xml << endl ;
 //  }
-  cdebug_out << "GraphEditor::OutNode::SaveXml" << endl;
+  cdebug_out << "GraphEditor::OutNode::SaveXml " << test << endl;
   return test;
 }
 
@@ -526,7 +550,7 @@ bool GraphEditor::OutNode::SavePy( const char* filename ) {
   IsValid() ;
   test = SavePY( f , true );
   f << endl << Graph()->Name() << " = Def" << Graph()->Name() << "()" << endl ;
-  cdebug_out << "GraphEditor::OutNode::SavePy" << endl;
+  cdebug_out << "GraphEditor::OutNode::SavePy " << test << endl;
   return test;
 }
 
@@ -548,9 +572,11 @@ GraphBase::ListOfSGraphs * GraphEditor::OutNode::GetDataFlows( GraphBase::ListOf
   }
   int i ;
   for ( i = 0 ; i < (int ) (*aListOfDataFlows)[ index ].Nodes.size() ; i++ ) {
-    if ( Graph()->GetGraphNode( (*aListOfDataFlows)[ index ].Nodes[i].theName.c_str() )->IsMacroNode() ) {
-      string aCoupledNode = (*aListOfDataFlows)[ index ].Nodes[i].theCoupledNode ;
-      GraphBase::Graph * aGraph = theAutomaton->MapGraph( aCoupledNode.c_str() ) ;
+    const GraphBase::ComputingNode * aNode = Graph()->GetGraphNode( (*aListOfDataFlows)[ index ].Nodes[i].theName.c_str() ) ;
+    if ( aNode->IsMacroNode() ) {
+//      string aCoupledNodeName = (*aListOfDataFlows)[ index ].Nodes[i].theCoupledNode ;
+      GraphBase::Graph * aGraph = (GraphBase::Graph * ) ((GraphBase::GOTONode * ) aNode )->CoupledNode() ;
+//      GraphBase::Graph * aGraph = MapGraph( aCoupledNodeName.c_str() ) ;
       aGraph->GraphEditor()->GraphEditor::OutNode::GetDataFlows( aListOfDataFlows ) ;
     }
   }
@@ -622,6 +648,11 @@ GraphEditor::InNode * GraphEditor::OutNode::AddNode(
   GraphEditor::InNode *Nd = NULL ;
   char * aNodeName = NULLSTRING ;
   bool   GeneratedName = false ;
+//PAL9048 JR Debug : a node may not have the same name as the graph
+  bool GraphNodeSameName = false ;
+  if ( theNodeName && !strcmp( Graph()->Name() , theNodeName ) ) {
+    GraphNodeSameName = true ;
+  }
   if ( NodeKindOfNode == SUPERV::InLineNode ||
        NodeKindOfNode == SUPERV::LoopNode ||
        NodeKindOfNode == SUPERV::EndLoopNode ||
@@ -653,25 +684,36 @@ GraphEditor::InNode * GraphEditor::OutNode::AddNode(
     }
     theNodeName = NULLSTRING ;
   }
-  if ( theNodeName == NULLSTRING || strlen( theNodeName ) == 0 || Graph()->GetGraphNode( theNodeName ) ) {
+//PAL9048 JR Debug : a node may not have the same name as the graph
+//  if ( theNodeName == NULLSTRING || strlen( theNodeName ) == 0 || Graph()->GetGraphNode( theNodeName ) ) {
+  if ( theNodeName == NULLSTRING || strlen( theNodeName ) == 0 ||
+       Graph()->GetGraphNode( theNodeName ) || GraphNodeSameName ) {
+    cdebug << "OutNode::AddNode : '" << theNodeName << "' GraphNodeSameName "
+           << GraphNodeSameName << endl;
     aNodeName = new char[ strlen( NodeService.ServiceName )+1 ] ;
     strcpy( aNodeName , NodeService.ServiceName ) ;
-    if ( Graph()->GetGraphNode( NodeService.ServiceName ) ) {
+//    if ( Graph()->GetGraphNode( NodeService.ServiceName ) ) {
+    if ( Graph()->GetGraphNode( NodeService.ServiceName ) || GraphNodeSameName ) {
       GeneratedName = true ;
-      while ( Graph()->GetGraphNode( aNodeName ) ) {
+      while ( Graph()->GetGraphNode( aNodeName ) || GraphNodeSameName ) {
+        cdebug << "OutNode::AddNode : '" << aNodeName << "' exists or GraphNodeSameName "
+               << GraphNodeSameName << endl;
         if ( aNodeName ) {
           delete [] aNodeName ;
        }
-        int num = Graph()->GetServiceNameNumber( NodeService ) ;
+//JR 09.08.2005 Debug : folowing line does not run with OMNIORB4
+//        char * aServiceName = (CORBA::String_member ) NodeService.ServiceName ;
+        int num = Graph()->GetNewServiceInstanceNumber( (CORBA::String_member ) NodeService.ServiceName ) ;
         ostringstream astr ;
         astr << num << ends ;
-        const char * n_instance = astr.str().c_str() ;
+//        const char * n_instance = astr.str().c_str() ;
         int lname = strlen( NodeService.ServiceName ) + 1 +
-                    strlen( n_instance ) + 1 ;
+                    strlen( astr.str().c_str() ) + 1 ;
         aNodeName = new char[lname] ;
         strcpy( aNodeName , NodeService.ServiceName ) ;
         strcat( aNodeName , "_" ) ;
-        strcat( aNodeName , n_instance ) ;
+        strcat( aNodeName , astr.str().c_str() ) ;
+        GraphNodeSameName = !strcmp( Graph()->Name() , aNodeName ) ;
       }
     }
   }
@@ -694,15 +736,18 @@ GraphEditor::InNode * GraphEditor::OutNode::AddNode(
                                   NodeComputer , NodeComment , GeneratedName ,
                                   NodeX , NodeY ,
                                   _prof_debug , _fdebug ) ;
-//    MESSAGE( "GraphEditor::OutNode::AddNode " << hex << (void *) Nd << dec );
-//    if ( GraphBase::Graph::AddNode( Nd ) ) {
+    
+    // asv: 28.09.04 fix for 6621
+    //if ( Nd->IsMacroNode() )
+    //  MapGraph( Nd->GraphMacroNode(), aNodeName );
 
     if ( Graph()->IsDataStreamNode() && ( Nd->IsComputingNode() || Nd->IsFactoryNode() ) ) {
       unsigned int i ;
       for ( i = 0 ; i < NodeService.ServiceinDataStreamParameter.length() ; i++ ) {
         GraphBase::InDataStreamPort * aDataStreamPort ;
         aDataStreamPort = Nd->ComputingNode()->AddInDataStreamPort(
-                                         my_strdup( NodeService.ServiceinDataStreamParameter[i].Parametername ) ,
+//JR 17.02.2005 Memory Leak                                         my_strdup( NodeService.ServiceinDataStreamParameter[i].Parametername ) ,
+                                         NodeService.ServiceinDataStreamParameter[i].Parametername ,
                                          NodeService.ServiceinDataStreamParameter[i].Parametertype ,
                                          NodeService.ServiceinDataStreamParameter[i].Parameterdependency ,
                                         SUPERV::DataStreamParameter ) ;
@@ -710,7 +755,8 @@ GraphEditor::InNode * GraphEditor::OutNode::AddNode(
       for ( i = 0 ; i < NodeService.ServiceoutDataStreamParameter.length() ; i++ ) {
         GraphBase::OutDataStreamPort * aDataStreamPort ;
         aDataStreamPort = Nd->ComputingNode()->AddOutDataStreamPort(
-                                         my_strdup( NodeService.ServiceoutDataStreamParameter[i].Parametername ) ,
+//JR 17.02.2005 Memory Leak                                         my_strdup( NodeService.ServiceoutDataStreamParameter[i].Parametername ) ,
+                                         NodeService.ServiceoutDataStreamParameter[i].Parametername ,
                                          NodeService.ServiceoutDataStreamParameter[i].Parametertype ,
                                          NodeService.ServiceoutDataStreamParameter[i].Parameterdependency ,
                                         SUPERV::DataStreamParameter ) ;
@@ -729,8 +775,13 @@ GraphEditor::InNode * GraphEditor::OutNode::AddNode(
     cdebug << "ERROR NodeName is NULL or already exists." << endl ;
   }
 //  delete [] aNodeName ;
-  cdebug_out << "GraphEditor::OutNode::AddNode" << endl;
   _Valid = false ;
+  if ( Nd == NULL ) {
+    cdebug_out << "GraphEditor::OutNode::AddNode : NULL" << endl;
+  }
+  else {
+    cdebug_out << "GraphEditor::OutNode::AddNode : " << Nd << " " << Nd->Name() << endl;
+  }
   return Nd ;
 }
 
@@ -901,16 +952,21 @@ bool GraphEditor::OutNode::UnValid() {
   return RetVal ;
 }
 
+//JR Optional parameter kLoopSwitch (default = true) :
+//In some cases we do not need to check the validity of loops and switchs
+//JR 07.07.2005 PAL9342 : that code is now in Executable() method instead of Valid() method
+//bool GraphEditor::OutNode::Valid(bool kLoopSwitch ) {
 bool GraphEditor::OutNode::Valid() {
-  if ( _Valid )
-    return true ;
-
+  bool RetVal = true ;
   cdebug_in << "GraphEditor::OutNode::Valid" << endl;
+//  if ( _Valid )
+//    return true ;
+
   _Executable = false ;
 
   if ( !Graph()->CreateService() ) {
-    cdebug_out << "GraphEditor::OutNode::Valid " << _Valid << endl;
-    return false ;
+    cdebug << "GraphEditor::OutNode::Valid ERROR _Valid " << _Valid << endl;
+    RetVal = false ;
   }
   
   if ( Graph()->GraphMacroLevel() != 0 ) {
@@ -928,76 +984,144 @@ bool GraphEditor::OutNode::Valid() {
     Graph()->CoupledNode()->GraphEditor()->UnValid() ;
   }
 
+  Graph()->InLineServices() ;
+
+//JR 07.07.2005 PAL9342 : that code is now in Executable() method instead of Valid() method
+#if 0
   int SubStreamGraphsNumber = 0 ;
   if ( !Graph()->Sort( SubStreamGraphsNumber ) ) {
     cdebug_out << "This DataFlow is not valid." << endl ;
-    return false ;
+    RetVal = false ;
   }
   if ( Graph()->IsDataStreamNode() ) {
     StreamGraph()->SubStreamGraphsNumber( SubStreamGraphsNumber ) ;
   }
-  
-//  CreateService() ;
 
-  Graph()->InLineServices() ;
+//JR Debug 24.08.2005 : InLineServices is needed for Export ==> it is executed above
+//  Graph()->InLineServices() ;
 
+  if ( kLoopSwitch ) {
+    if ( !Graph()->ValidLoops() ) {
+      cdebug_out << "This DataFlow have not valid Loops." << endl ;
+      RetVal = false ;
+    }
+    if ( !Graph()->ValidSwitchs() ) {
+      cdebug_out << "This DataFlow have not valid Switchs." << endl ;
+      RetVal = false ;
+    }
+  }
+  
   Graph()->ComputingNodes() ;
+#endif
 
-  _Valid = true ;
+  if ( RetVal ) {
+    _Valid = true ;
+  }
 
-  cdebug_out << "GraphEditor::OutNode::Valid " << _Valid << endl;
-  return _Valid ;
+  cdebug_out << "GraphEditor::OutNode::Valid " << _Valid << " RetVal " << RetVal << endl;
+  return RetVal ;
 }
 
 bool GraphEditor::OutNode::Executable() {
   cdebug_in << "GraphEditor::OutNode::Executable" << endl;
+  bool RetVal = true ;
   bool NewLink ;
+// LinkLoopNodes manage input values of LoopNodes and EndLoopNodes
   if ( Graph()->LinkLoopNodes( NewLink ) ) {
     if ( NewLink ) {
       _Valid = false ;
+      RetVal = false ;
     }
   }
   else {
-    cdebug << "This DataFlow is not executable." << endl ;
+    cdebug << "Editor::OutNode::Executable This DataFlow is not executable(LinkLoopNodes)." << endl ;
     _Executable = false ;
+    RetVal = false ;
   }
   if ( !IsValid() ) {
     Valid() ;
   }
   if ( !IsValid() ) {
-    return false ;
+    RetVal = false ;
+  }
+
+//JR 07.07.2005 PAL9342 : that code is now in Executable() method instead of Valid() method
+  bool IsValid = true;
+  int SubStreamGraphsNumber = 0 ;
+  if ( !Graph()->Sort( SubStreamGraphsNumber ) ) {
+    cdebug << "Editor::OutNode::Executable This DataFlow is not valid(Sort)." << endl ;
+    RetVal = false ;
+    //mkr : 28.09.2005 : if dataflow is not valid => it is not executable
+    IsValid = false ;
   }
+  if ( Graph()->IsDataStreamNode() )
+    StreamGraph()->SubStreamGraphsNumber( SubStreamGraphsNumber ) ;
+
+  Graph()->InLineServices() ;
+
+//  if ( kLoopSwitch ) {
+    if ( !Graph()->ValidLoops() ) {
+      cdebug << "Editor::OutNode::Executable This DataFlow have not valid Loops(ValidLoops)." << endl ;
+      RetVal = false ;
+      //mkr : 28.09.2005 : if dataflow is not valid => it is not executable
+      IsValid = false ;
+    }
+    if ( !Graph()->ValidSwitchs() ) {
+      cdebug << "Editor::OutNode::Executable This DataFlow have not valid Switchs(ValidSwitchs)." << endl ;
+      RetVal = false ;
+      //mkr : 28.09.2005 : if dataflow is not valid => it is not executable
+      IsValid = false ;
+    }
+//  }
+  
+  Graph()->ComputingNodes() ;
+
   if ( Graph()->DataServerNodes() )
     _Executable = true ;
   else {
-    cdebug << "This DataFlow is not executable." << endl ;
+    cdebug << "Editor::OutNode::Executable This DataFlow is not executable(DataServerNodes)." << endl ;
     _Executable = false ;
+    RetVal = false ;
   }
 
   if ( _Executable && Graph()->IsDataStreamNode() ) {
     StreamGraph()->CreateStreamTopology( "/tmp/" ) ;
   }
 
-  cdebug_out << "GraphEditor::OutNode::Executable" << endl;
-  return _Executable ;
+  // asv : 13.12.04 : introducing check for compatibility of linked ports' types.
+  if ( !IsLinksCompatible() ) {
+    _Executable = false;
+    RetVal = false ;
+  }    
+
+  //mkr : 28.09.2005 : if dataflow is not valid => it is not executable
+  if ( !IsValid ) _Executable = false ;
+
+  cdebug_out << "GraphEditor::OutNode::Executable _Executable " << _Executable << " RetVal " << RetVal
+             << endl;
+  return RetVal ;
 }
 
-const CORBA::Any *GraphEditor::OutNode::GetInData(
+//JR 30.03.2005const CORBA::Any *GraphEditor::OutNode::GetInData(
+const CORBA::Any GraphEditor::OutNode::GetInData(
                               const char * ToNodeName ,
                               const char * ToParameterName ) {
 //  cdebug_in << "GraphEditor::OutNode::GetInData " << ToNodeName
 //            << " " << ToParameterName << endl ;
-  const CORBA::Any * retdata = Graph()->PortInData( ToNodeName , ToParameterName ) ;
+//JR 30.03.2005  const CORBA::Any * retdata = Graph()->PortInData( ToNodeName , ToParameterName ) ;
+  const CORBA::Any retdata = Graph()->PortInData( ToNodeName , ToParameterName ) ;
 //  cdebug_out << "GraphEditor::OutNode::GetInData" << endl ;
   return retdata ;
 }
 
-const CORBA::Any *GraphEditor::OutNode::GetOutData(
+//JR 30.03.2005const CORBA::Any *GraphEditor::OutNode::GetOutData(
+const CORBA::Any GraphEditor::OutNode::GetOutData(
                               const char * FromNodeName ,
                               const char * FromParameterName ) {
 //  cdebug_in << "GraphEditor::OutNode::GetOutData " << FromNodeName
 //            << " " << FromParameterName << endl ;
-  const CORBA::Any * retdata = Graph()->PortOutData( FromNodeName , FromParameterName ) ;
+//JR 30.03.2005  const CORBA::Any * retdata = Graph()->PortOutData( FromNodeName , FromParameterName ) ;
+  const CORBA::Any retdata = Graph()->PortOutData( FromNodeName , FromParameterName ) ;
 //  cdebug_out << "GraphEditor::OutNode::GetOutData" << endl ;
   return retdata ;
 }
@@ -1070,9 +1194,24 @@ bool GraphEditor::OutNode::LinkSaveXML( QDomDocument & Graph , QDomElement & lin
         aLink.aLinkValue >>= retstr;
 //        f << Tabs << "       <value>" << retstr << "</value>" << endl ;
         QDomElement value = Graph.createElement( "value" ) ;
-        aField = Graph.createTextNode( retstr ) ;
+//PAL9133 Debug JR : accept void strings
+        QDomCDATASection aCDATA ;
+        int i ;
+        for ( i = 0 ; i < (int ) strlen( retstr ) ; i++ ) {
+          if ( retstr[ i ] != ' ' ) {
+            break ;
+         }
+        }
+        if ( i == (int ) strlen( retstr ) ) {
+          aCDATA = Graph.createCDATASection( "?" ) ;
+        }
+        else {
+          aCDATA = Graph.createCDATASection( retstr ) ;
+       }
+//        aField = Graph.createTextNode( retstr ) ;
         datavalue.appendChild( value ) ;
-        value.appendChild( aField ) ;
+//        datavalue.appendChild( value ) ;
+        value.appendChild( aCDATA ) ;
 //        MESSAGE( "ToString( string ) " << retstr );
         break ;
       }
@@ -1393,6 +1532,7 @@ bool GraphEditor::OutNode::SaveXML( ostream & f , QDomDocument & GraphQDom ,
 bool GraphEditor::OutNode::SavePY( ostream & f , bool importSuperV ) {
   int i ;
   int j ;
+  const GraphBase::ListOfSLinks * Links ;
   if ( importSuperV ) {
     f << endl << "# Generated python file of Graph " << Graph()->Name() << endl << endl ;
 
@@ -1509,7 +1649,7 @@ bool GraphEditor::OutNode::SavePY( ostream & f , bool importSuperV ) {
     }
   }
 
-  const GraphBase::ListOfSLinks * Links = Graph()->GetLinks() ;
+  Links = Graph()->GetLinks() ;
 //  bool intervar ;
 //  map< string , int > aMapOfOutPorts ;
   first = true ;
@@ -1643,7 +1783,81 @@ bool GraphEditor::OutNode::SavePY( ostream & f , bool importSuperV ) {
   return true ;
 }
 
+/** Iterate through ALL links (OutPort-InPort pairs) and check if their types are 
+ *  compatible - call GraphEditor::DataFlow::IsCompatible(type1, type2).
+ *  Returns true if all are compatible.
+ */
+bool GraphEditor::OutNode::IsLinksCompatible() {
+  cdebug_in << "Editor::OutNode::IsLinksCompatible()" << endl ;
+  bool RetVal = true;
+  bool b ;
+  const GraphBase::ListOfSLinks * Links = Graph()->GetLinks( true ) ;
+  cdebug_in << "Editor::OutNode::IsLinksCompatible() " << Links->size() << " Links" << endl ;
+//  for ( int i = 0 ; i < (int ) Links->size() && b ; i++ ) {
+  for ( int i = 0 ; i < (int ) Links->size() ; i++ ) {
+    GraphBase::SLink aLink = (*Links)[i];
+    GraphBase::ComputingNode* anOutNode = Graph()->GetChangeGraphNode( aLink.FromNodeName.c_str() );
+    GraphBase::ComputingNode* anInNode = Graph()->GetChangeGraphNode( aLink.ToNodeName.c_str() );
+    const GraphBase::OutPort* anOutPort = anOutNode->GetOutPort( aLink.FromServiceParameterName.c_str() );
+    const GraphBase::InPort* anInPort = anInNode->GetInPort( aLink.ToServiceParameterName.c_str() );    
+    b = IsCompatible( anOutPort->PortType(), anInPort->PortType() );
+    cdebug << "GraphEditor::OutNode::IsLinksCompatible:  " << aLink.FromNodeName << "( "
+           << aLink.FromServiceParameterName << " " << anOutPort->PortType()
+           << " )  -->  " << aLink.ToNodeName <<"( " << aLink.ToServiceParameterName << " "
+           << anInPort->PortType() << " ) = " << (b ? "OK" : "Not compatible (ERROR)") << endl;
+    if ( !b ) {
+      RetVal = false ;
+      MESSAGE( "Graph structure ERROR: type of port \"" << aLink.FromServiceParameterName
+               << "\" of node \"" << aLink.FromNodeName
+               << "\" is not compatible with type of linked port \""
+              << aLink.ToServiceParameterName << "\" of node \"" << aLink.ToNodeName<<"\"" ) ; 
+      ostringstream aTypeOutPortstr ;
+      aTypeOutPortstr << anOutPort->PortType() ;
+      ostringstream aTypeInPortstr ;
+      aTypeInPortstr << anInPort->PortType() ;
+      string anErrorMessage = string( "PortTypes of " ) + string( aLink.FromNodeName ) +
+                              string( "( " ) + aLink.FromServiceParameterName +
+                              string( " ) " ) + aTypeOutPortstr.str() + string( " and " ) +
+                              string( aLink.ToNodeName ) + string( "( " ) +
+                              string( aLink.ToServiceParameterName ) + 
+                              string( " ) " ) + aTypeInPortstr.str() +
+                              string( " are not compatibles.\n" ) ;
+      Graph()->SetMessages( anErrorMessage ) ;
+    }
+  }
+  cdebug_out << "Editor::OutNode::IsLinksCompatible() RetVal " << RetVal << endl ;
+  return RetVal ;
+}
+
+static const char* gSimpleTypes[] = 
+  {"boolean", "char", "short", "int", "long", "float", "double"};
+bool isSimpleType( string type ) {
+  for ( int i = 0; i < 7; i++ )
+    if ( type == gSimpleTypes[i] )
+      return true;
+  return false;
+}
 
+/**Returns true if an out-port of type "OutPortType" can be bound with in-port of type "InPortType". 
+ * Types: {"string", "boolean", "char", "short", "int", "long", "float", "double", "objref"};
+ * Currently considered compatible ALL types except for objref - they must match exactly
+ */
+bool GraphEditor::OutNode::IsCompatible( const char* OutPortType, const char* InPortType ) const {
+  bool ret = true;
+  string t1 = OutPortType;
+  string t2 = InPortType;
+  // if ANY is a string - the link is OK
+  if ( t1 == "string" || t2 == "string" )
+    ret = true;
+
+  // the next check prohibits linkage of "objref" to any simple type (int, char, etc.)
+  // it is still possible to link "objref" to some UNKNOWN type (probably objref, too,
+  // which interface name came from Cataloge
+  else if ( ( t1 == "objref" && isSimpleType( t2 ) ) ||  
+           ( t2 == "objref" && isSimpleType( t1 ) ) )
+    ret = false; 
+  return ret;
+}
 
 ostream & operator<< (ostream & f,const GraphEditor::OutNode & G) {
   f << (GraphBase::ComputingNode ) *(G.Graph()) ;
@@ -1695,10 +1909,27 @@ ostream & operator<< (ostream &fOut,const SUPERV::SDate &D)
   return fOut;
 }
 
+/*
+GraphBase::Graph * GraphEditor::OutNode::MapGraph( const char * aGraphName ) {
+  GraphBase::Graph * aGraph = _MapOfGraphs[ aGraphName ] ;
+  return aGraph ;
+}
 
+bool GraphEditor::OutNode::MapGraph( GraphBase::Graph * aGraph , const char * aGraphName ) {
+  if ( MapGraph( aGraphName ) ) {
+    return false ;
+  }
+  _MapOfGraphs[ aGraphName ] = aGraph ;
+  return true ;
+}
 
+void GraphEditor::OutNode::EraseGraph( const char * aGraphName ) {
+  _MapOfGraphs.erase( aGraphName ) ;
+}
 
-
-
+bool GraphEditor::OutNode::GraphName( const char * aGraphName ) {
+  return  _MapOfGraphNames[ aGraphName ] ;
+}
+*/