Salome HOME
merge from branch DEV tag mergeto_trunk_04apr08
[modules/yacs.git] / src / yacsorb / yacsSrv.cxx
1 #include <Python.h>
2 #include <yacs.hh>
3 #include "RuntimeSALOME.hxx"
4 #include "Proc.hxx"
5 #include "Exception.hxx"
6 #include "Executor.hxx"
7 #include "Dispatcher.hxx"
8 #include "parsers.hxx"
9
10 #include <iostream>
11 #include <sstream>
12 #include <set>
13
14 //#define _DEVDEBUG_
15 #include "YacsTrace.hxx"
16
17 using namespace std;
18
19 YACS::YACSLoader::YACSLoader* loader;
20 CORBA::ORB_ptr orb;
21 YACS_ORB::YACS_Gen_var myyacsref;
22
23 class MyDispatcher:public YACS::ENGINE::Dispatcher
24 {
25 public:
26   void dispatch(YACS::ENGINE::Node* object, const std::string& event)
27   {
28     std::cerr << "dispatch " << object->getNumId() << std::endl;
29     typedef std::set<YACS_ORB::Observer_ptr>::iterator jt;
30     std::pair<int,std::string> key(object->getNumId(),event);
31     for(jt iter=_observers[key].begin();iter!=_observers[key].end();iter++)
32       {
33         (*iter)->notifyObserver((CORBA::Long)object->getNumId(),event.c_str());
34       }
35   }
36
37   void addObserver(YACS_ORB::Observer_ptr observer,int numid, const std::string& event)
38   {
39     _observers[std::pair<int,std::string>(numid,event)].insert(YACS_ORB::Observer::_duplicate(observer));
40   //  printObservers();
41   }
42 protected:
43   std::map< std::pair<int,std::string> , std::set<YACS_ORB::Observer_ptr> > _observers;
44 };
45
46 class Yacs_i : public POA_YACS_ORB::YACS_Gen,
47                public PortableServer::RefCountServantBase
48 {
49 public:
50   inline Yacs_i() {}
51   virtual ~Yacs_i() {}
52   YACS_ORB::Proc_ptr Load(const char* xmlFile);
53   void Run(YACS_ORB::Proc_ptr p);
54   void addObserver(YACS_ORB::Observer_ptr observer, CORBA::Long numid,const char* event);
55 };
56
57 class Proc_i : public POA_YACS_ORB::Proc,
58                public PortableServer::RefCountServantBase
59 {
60 public:
61   inline Proc_i(YACS::ENGINE::Proc* p) {_proc=p;};
62   virtual ~Proc_i() {};
63   virtual void RunW();
64   CORBA::Long getState(CORBA::Long numid);
65   char * getXMLState(CORBA::Long numid);
66   void getIds(YACS_ORB::longArray_out numids,YACS_ORB::stringArray_out names);
67 protected:
68   YACS::ENGINE::Executor _executor;
69   YACS::ENGINE::Proc* _proc;
70 };
71
72 void Proc_i::RunW()
73 {
74   _executor.RunW(_proc,0);
75 }
76
77 CORBA::Long Proc_i::getState(CORBA::Long numid)
78 {
79   if(YACS::ENGINE::Node::idMap.count(numid) == 0)
80     {
81       std::cerr << "Unknown node id " << numid << std::endl;
82       return (CORBA::Long)-1;
83     }
84   YACS::ENGINE::Node* node= YACS::ENGINE::Node::idMap[numid];
85   CORBA::Long state=node->getEffectiveState();
86   return state;
87 }
88
89 char * Proc_i::getXMLState(CORBA::Long numid)
90 {
91   if(YACS::ENGINE::Node::idMap.count(numid) == 0)
92     {
93       std::cerr << "Unknown node id " << numid << std::endl;
94       return "<state>unknown</state>";
95     }
96   YACS::ENGINE::Node* node= YACS::ENGINE::Node::idMap[numid];
97   std::stringstream msg;
98   msg << "<state>" << node->getEffectiveState() << "</state>";
99   msg << "<name>" << node->getQualifiedName() << "</name>";
100   msg << "<id>" << numid << "</id>";
101   return CORBA::string_dup(msg.str().c_str());
102 }
103
104 void Proc_i::getIds(YACS_ORB::longArray_out numids,YACS_ORB::stringArray_out names)
105 {
106   std::list<YACS::ENGINE::Node *> nodes=_proc->getAllRecursiveNodes();
107   int len=nodes.size();
108   names=new YACS_ORB::stringArray;
109   numids=new YACS_ORB::longArray;
110   names->length(len);
111   numids->length(len);
112   int i=0;
113   for(list<YACS::ENGINE::Node *>::const_iterator iter=nodes.begin();iter!=nodes.end();iter++,i++)
114     {
115       (*names)[i]=CORBA::string_dup((*iter)->getQualifiedName().c_str());
116       (*numids)[i]=(*iter)->getNumId();
117     }
118 }
119
120 YACS_ORB::Proc_ptr Yacs_i::Load(const char* xmlFile)
121 {
122   YACS::ENGINE::Proc* proc=loader->load(xmlFile);
123   Proc_i* p=new Proc_i(proc);
124   YACS_ORB::Proc_ptr pp = p->_this();
125   return pp;
126 }
127
128 void Yacs_i::addObserver(YACS_ORB::Observer_ptr observer, CORBA::Long numid,const char* event)
129 {
130   ((MyDispatcher*)YACS::ENGINE::Dispatcher::getDispatcher())->addObserver(observer,numid,event);
131 }
132
133 void Yacs_i::Run(YACS_ORB::Proc_ptr p)
134 {
135   Proc_i *servant=dynamic_cast<Proc_i *> (PortableServer::POA::_the_root_poa()->reference_to_servant(p));
136   servant->RunW();
137 }
138
139 static CORBA::Boolean bindObjectToName(CORBA::ORB_ptr, CORBA::Object_ptr,const char*);
140 static ostream& operator<<(ostream& os, const CORBA::Exception& e);
141
142 int main(int argc, char** argv)
143 {
144   YACS::ENGINE::RuntimeSALOME::setRuntime();
145   loader= new YACS::YACSLoader::YACSLoader();
146   MyDispatcher* disp=new MyDispatcher();
147   YACS::ENGINE::Dispatcher::setDispatcher(disp);
148
149   try 
150   {
151     orb = CORBA::ORB_init(argc, argv);
152
153     {
154       CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
155       PortableServer::POA_var root_poa = PortableServer::POA::_narrow(obj);
156       // POA manager
157       PortableServer::POAManager_var poa_man = root_poa->the_POAManager();
158       poa_man->activate();
159
160       // Create and activate servant
161       Yacs_i* myyacs = new Yacs_i();
162       // Obtain a reference to the object, and print it out as a
163       // stringified IOR.
164       obj = myyacs->_this();
165       CORBA::String_var sior(orb->object_to_string(obj));
166       DEBTRACE("'" << (char*)sior << "'");
167       myyacsref = YACS_ORB::YACS_Gen::_narrow(obj);
168
169       if( !bindObjectToName(orb, myyacsref,"Yacs") ) return 1;
170
171       // Decrement the reference count of the object implementation, so
172       // that it will be properly cleaned up when the POA has determined
173       // that it is no longer needed.
174       myyacs->_remove_ref();
175     }
176     orb->run();
177   }
178   catch(CORBA::SystemException&) {
179     DEBTRACE("Caught CORBA::SystemException.");
180   }
181   catch(CORBA::Exception& ex) {
182     DEBTRACE("Caught CORBA::Exception." << ex);
183   }
184   catch(omniORB::fatalException& fe) {
185     DEBTRACE("Caught omniORB::fatalException:");
186     DEBTRACE("  file: " << fe.file());
187     DEBTRACE("  line: " << fe.line());
188     DEBTRACE("  mesg: " << fe.errmsg());
189   }
190   catch(...) {
191     DEBTRACE("Caught unknown exception." );
192   }
193
194   return 0;
195 }
196
197
198 //////////////////////////////////////////////////////////////////////
199
200 static CORBA::Boolean
201 bindObjectToName(CORBA::ORB_ptr orb, CORBA::Object_ptr objref,const char *name)
202 {
203   CosNaming::NamingContext_var rootContext;
204
205   try {
206     // Obtain a reference to the root context of the Name service:
207     CORBA::Object_var obj;
208     obj = orb->resolve_initial_references("NameService");
209
210     // Narrow the reference returned.
211     rootContext = CosNaming::NamingContext::_narrow(obj);
212     if( CORBA::is_nil(rootContext) ) {
213       DEBTRACE("Failed to narrow the root naming context.");
214       return 0;
215     }
216   }
217   catch(CORBA::ORB::InvalidName& ex) {
218     // This should not happen!
219     DEBTRACE("Service required is invalid [does not exist]." );
220     return 0;
221   }
222
223   try {
224     // Bind a context called "test" to the root context:
225
226     CosNaming::Name contextName;
227     contextName.length(1);
228     contextName[0].id   = (const char*) "test";       // string copied
229     contextName[0].kind = (const char*) "my_context"; // string copied
230     // Note on kind: The kind field is used to indicate the type
231     // of the object. This is to avoid conventions such as that used
232     // by files (name.type -- e.g. test.ps = postscript etc.)
233
234     CosNaming::NamingContext_var testContext;
235     try {
236       // Bind the context to root.
237       testContext = rootContext->bind_new_context(contextName);
238     }
239     catch(CosNaming::NamingContext::AlreadyBound& ex) {
240       // If the context already exists, this exception will be raised.
241       // In this case, just resolve the name and assign testContext
242       // to the object returned:
243       CORBA::Object_var obj;
244       obj = rootContext->resolve(contextName);
245       testContext = CosNaming::NamingContext::_narrow(obj);
246       if( CORBA::is_nil(testContext) ) {
247         DEBTRACE("Failed to narrow naming context.");
248         return 0;
249       }
250     }
251
252     // Bind objref with name name to the testContext:
253     CosNaming::Name objectName;
254     objectName.length(1);
255     objectName[0].id   = name;   // string copied
256     objectName[0].kind = (const char*) "Object"; // string copied
257
258     try {
259       testContext->bind(objectName, objref);
260     }
261     catch(CosNaming::NamingContext::AlreadyBound& ex) {
262       testContext->rebind(objectName, objref);
263     }
264   }
265   catch(CORBA::COMM_FAILURE& ex) {
266     DEBTRACE("Caught system exception COMM_FAILURE -- unable to contact the "
267              << "naming service.");
268     return 0;
269   }
270   catch(CORBA::SystemException&) {
271     DEBTRACE("Caught a CORBA::SystemException while using the naming service.");
272     return 0;
273   }
274
275   return 1;
276 }
277
278 static ostream& operator<<(ostream& os, const CORBA::Exception& e)
279 {
280   CORBA::Any tmp;
281   tmp<<= e;
282   CORBA::TypeCode_var tc = tmp.type();
283   const char *p = tc->name();
284   if ( *p != '\0' ) {
285     os<<p;
286   }
287   else  {
288     os << tc->id();
289   }
290   return os;
291 }