1 /**************************************************************************\
2  * Copyright (c) Kongsberg Oil & Gas Technologies AS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32 
33 #include <Inventor/scxml/ScXMLParallelElt.h>
34 
35 /*!
36   \class ScXMLParallelElt ScXMLParallelElt.h Inventor/scxml/ScXMLParallelElt.h
37   \brief implements the &lt;parallel&gt; SCXML element.
38 
39   \since Coin 3.0
40   \ingroup scxml
41 */
42 
43 #include <cassert>
44 #include <cstring>
45 #include <algorithm>
46 #include <vector>
47 
48 #include <boost/scoped_ptr.hpp>
49 
50 #include <Inventor/C/tidbits.h>
51 #include <Inventor/errors/SoDebugError.h>
52 #include <Inventor/C/XML/element.h>
53 #include <Inventor/scxml/ScXML.h>
54 #include <Inventor/scxml/ScXMLDocument.h>
55 #include <Inventor/scxml/ScXMLInvokeElt.h>
56 #include <Inventor/scxml/ScXMLOnExitElt.h>
57 #include <Inventor/scxml/ScXMLOnEntryElt.h>
58 #include <Inventor/scxml/ScXMLTransitionElt.h>
59 #include <Inventor/scxml/ScXMLStateElt.h>
60 #include <Inventor/scxml/ScXMLInitialElt.h>
61 #include <Inventor/scxml/ScXMLFinalElt.h>
62 #include <Inventor/scxml/ScXMLHistoryElt.h>
63 #include <Inventor/scxml/ScXMLAnchorElt.h>
64 #include <Inventor/scxml/ScXMLDataModelElt.h>
65 #include <Inventor/scxml/ScXMLScxmlElt.h>
66 
67 #include "scxml/ScXMLCommonP.h"
68 
69 #ifndef COIN_WORKAROUND_NO_USING_STD_FUNCS
70 using std::strlen;
71 using std::strcpy;
72 using std::strcmp;
73 #endif // !COIN_WORKAROUND_NO_USING_STD_FUNCS
74 
75 // *************************************************************************
76 
77 class ScXMLParallelEltReader : public ScXMLEltReader {
78 public:
79   ScXMLParallelEltReader(void);
80   virtual ScXMLElt * read(ScXMLElt * container, cc_xml_elt * xmlelt, ScXMLDocument * doc, ScXMLStateMachine * sm);
81 };
82 
ScXMLParallelEltReader(void)83 ScXMLParallelEltReader::ScXMLParallelEltReader(void)
84 : ScXMLEltReader("parallel")
85 {
86 }
87 
88 namespace { namespace ScXMLParallelNS {
89 
90 template <class Type>
91 Type *
clone(Type * objptr)92 clone(Type * objptr)
93 {
94   return coin_assert_cast<Type *>(objptr->clone());
95 }
96 
97 } }
98 
99 ScXMLElt *
read(ScXMLElt * container,cc_xml_elt * xmlelt,ScXMLDocument * doc,ScXMLStateMachine * sm)100 ScXMLParallelEltReader::read(ScXMLElt * container, cc_xml_elt * xmlelt, ScXMLDocument * doc, ScXMLStateMachine * sm)
101 {
102   assert(container && xmlelt);
103   ScXMLParallelElt * parallel = new ScXMLParallelElt;
104   parallel->setContainer(container);
105   this->setXMLAttributes(parallel, xmlelt);
106 
107   // handle XML attributes
108   if (unlikely(!parallel->handleXMLAttributes())) {
109     SoDebugError::post("ScXMLParallelEltReader::read",
110                        "invalid XML attributes");
111     delete parallel;
112     return NULL;
113   }
114 
115   const char * extref = parallel->getSrcAttribute();
116   if ((extref != NULL) && (extref[0] != '\0')) {
117     SbString reference(extref);
118     char * eltnameref = const_cast<char *>(strchr(reference.getString(), '#'));
119     if (eltnameref) {
120       eltnameref[0] = '\0';
121       ++eltnameref;
122     }
123     ScXMLDocument * refdoc = ScXMLDocument::readFile(reference.getString());
124     if (refdoc) {
125       ScXMLElt * parentelt = refdoc->getRoot();
126       if (eltnameref) {
127         parentelt = refdoc->getStateById(SbName(eltnameref));
128       }
129       if (parentelt) {
130         if (parentelt->isOfType(ScXMLScxmlElt::getClassTypeId())) {
131           ScXMLScxmlElt * parent =
132             coin_assert_cast<ScXMLScxmlElt *>(parentelt);
133           int c = 0;
134 #if 0
135           if (parent->getInitial()) {
136             ScXMLInitialElt * initialelt =
137               coin_assert_cast<ScXMLInitialElt *>(parent->getInitial()->clone());
138             parallel->setInitial(initialelt);
139           }
140 #endif
141           for (c = 0; c < parent->getNumStates(); ++c) {
142             ScXMLStateElt * stateelt = ::ScXMLParallelNS::clone(parent->getState(c));
143 //            coin_assert_cast<ScXMLStateElt *>(parent->getState(c)->clone());
144             parallel->addState(stateelt);
145           }
146           for (c = 0; c < parent->getNumParallels(); ++c) {
147             ScXMLParallelElt * parallelelt =
148               coin_assert_cast<ScXMLParallelElt *>(parent->getParallel(c)->clone());
149             parallel->addParallel(parallelelt);
150           }
151           for (c = 0; c < parent->getNumFinals(); ++c) {
152             ScXMLFinalElt * finalelt =
153               coin_assert_cast<ScXMLFinalElt *>(parent->getFinal(c)->clone());
154             parallel->addFinal(finalelt);
155           }
156           if (parent->getDataModel()) {
157             ScXMLDataModelElt * datamodelelt =
158               coin_assert_cast<ScXMLDataModelElt *>(parent->getDataModel()->clone());
159             parallel->setDataModel(datamodelelt);
160           }
161 #if 0
162           for (c = 0; c < parent->getNumScripts(); ++c) {
163             ScXMLScriptElt * scriptelt =
164               coin_assert_cast<ScXMLScriptElt *>(parent->getScript(c)->clone());
165             parallel->addScript(scriptelt);
166           }
167 #endif
168         }
169         else if (parentelt->isOfType(ScXMLStateElt::getClassTypeId())) {
170           ScXMLStateElt * parent =
171             coin_assert_cast<ScXMLStateElt *>(parentelt);
172           int c = 0;
173           if (parent->getOnEntry()) {
174             ScXMLOnEntryElt * onentryelt =
175               coin_assert_cast<ScXMLOnEntryElt *>(parent->getOnEntry()->clone());
176             parallel->setOnEntry(onentryelt);
177           }
178           if (parent->getOnExit()) {
179             ScXMLOnExitElt * onexitelt =
180               coin_assert_cast<ScXMLOnExitElt *>(parent->getOnExit()->clone());
181             parallel->setOnExit(onexitelt);
182           }
183           for (c = 0; c < parent->getNumTransitions(); ++c) {
184             ScXMLTransitionElt * transitionelt =
185               coin_assert_cast<ScXMLTransitionElt *>(parent->getTransition(c)->clone());
186             parallel->addTransition(transitionelt);
187           }
188 #if 0
189           if (parent->getInitial()) {
190             ScXMLInitialElt * initialelt =
191               coin_assert_cast<ScXMLInitialElt *>(parent->getInitial()->clone());
192             parallel->setInitial(initialelt);
193           }
194 #endif
195           for (c = 0; c < parent->getNumStates(); ++c) {
196             ScXMLStateElt * stateelt =
197               coin_assert_cast<ScXMLStateElt *>(parent->getState(c)->clone());
198             parallel->addState(stateelt);
199           }
200           for (c = 0; c < parent->getNumParallels(); ++c) {
201             ScXMLParallelElt * parallelelt =
202               coin_assert_cast<ScXMLParallelElt *>(parent->getParallel(c)->clone());
203             parallel->addParallel(parallelelt);
204           }
205           for (c = 0; c < parent->getNumFinals(); ++c) {
206             ScXMLFinalElt * finalelt =
207               coin_assert_cast<ScXMLFinalElt *>(parent->getFinal(c)->clone());
208             parallel->addFinal(finalelt);
209           }
210           for (c = 0; c < parent->getNumHistories(); ++c) {
211             ScXMLHistoryElt * historyelt =
212               coin_assert_cast<ScXMLHistoryElt *>(parent->getHistory(c)->clone());
213             parallel->addHistory(historyelt);
214           }
215           for (c = 0; c < parent->getNumAnchors(); ++c) {
216             ScXMLAnchorElt * anchorelt =
217               coin_assert_cast<ScXMLAnchorElt *>(parent->getAnchor(c)->clone());
218             parallel->addAnchor(anchorelt);
219           }
220           if (parent->getDataModel()) {
221             ScXMLDataModelElt * datamodelelt =
222               coin_assert_cast<ScXMLDataModelElt *>(parent->getDataModel()->clone());
223             parallel->setDataModel(datamodelelt);
224           }
225         }
226         else if (parentelt->isOfType(ScXMLParallelElt::getClassTypeId())) {
227           ScXMLParallelElt * parent =
228             coin_assert_cast<ScXMLParallelElt *>(parentelt);
229           int c = 0;
230           if (parent->getOnEntry()) {
231             ScXMLOnEntryElt * onentryelt =
232               coin_assert_cast<ScXMLOnEntryElt *>(parent->getOnEntry()->clone());
233             parallel->setOnEntry(onentryelt);
234           }
235           if (parent->getOnExit()) {
236             ScXMLOnExitElt * onexitelt =
237               coin_assert_cast<ScXMLOnExitElt *>(parent->getOnExit()->clone());
238             parallel->setOnExit(onexitelt);
239           }
240           for (c = 0; c < parent->getNumTransitions(); ++c) {
241             ScXMLTransitionElt * transitionelt =
242               coin_assert_cast<ScXMLTransitionElt *>(parent->getTransition(c)->clone());
243             parallel->addTransition(transitionelt);
244           }
245 #if 0
246           if (parent->getInitial()) {
247             ScXMLInitialElt * initialelt =
248               coin_assert_cast<ScXMLInitialElt *>(parent->getInitial()->clone());
249             parallel->setInitial(initialelt);
250           }
251 #endif
252           for (c = 0; c < parent->getNumStates(); ++c) {
253             ScXMLStateElt * stateelt =
254               coin_assert_cast<ScXMLStateElt *>(parent->getState(c)->clone());
255             parallel->addState(stateelt);
256           }
257           for (c = 0; c < parent->getNumParallels(); ++c) {
258             ScXMLParallelElt * parallelelt =
259               coin_assert_cast<ScXMLParallelElt *>(parent->getParallel(c)->clone());
260             parallel->addParallel(parallelelt);
261           }
262           for (c = 0; c < parent->getNumFinals(); ++c) {
263             ScXMLFinalElt * finalelt =
264               coin_assert_cast<ScXMLFinalElt *>(parent->getFinal(c)->clone());
265             parallel->addFinal(finalelt);
266           }
267           for (c = 0; c < parent->getNumHistories(); ++c) {
268             ScXMLHistoryElt * historyelt =
269               coin_assert_cast<ScXMLHistoryElt *>(parent->getHistory(c)->clone());
270             parallel->addHistory(historyelt);
271           }
272           for (c = 0; c < parent->getNumAnchors(); ++c) {
273             ScXMLAnchorElt * anchorelt =
274               coin_assert_cast<ScXMLAnchorElt *>(parent->getAnchor(c)->clone());
275             parallel->addAnchor(anchorelt);
276           }
277           if (parent->getDataModel()) {
278             ScXMLDataModelElt * datamodelelt =
279               coin_assert_cast<ScXMLDataModelElt *>(parent->getDataModel()->clone());
280             parallel->setDataModel(datamodelelt);
281           }
282         }
283         else if (parentelt->isOfType(ScXMLFinalElt::getClassTypeId())) {
284           // huh?
285         }
286       }
287       delete refdoc;
288     }
289   }
290 
291   // read in all children, and recurse down
292   const int numchildren = cc_xml_elt_get_num_children(xmlelt);
293   for (int c = 0; c < numchildren; ++c) {
294     cc_xml_elt * element = cc_xml_elt_get_child(xmlelt, c);
295     const char * elementtype = cc_xml_elt_get_type(element);
296 
297     if (strcmp(elementtype, COIN_XML_CDATA_TYPE) == 0) {
298       // ignore CDATA
299       continue;
300     }
301 
302     if (strcmp(elementtype, "onentry") == 0) {
303       // <onentry> - zero or one time
304       if (unlikely(parallel->getOnEntry())) {
305         SoDebugError::post("ScXMLParallelEltReader::read",
306                            "<parallel> elements can only have one <onentry> element");
307         delete parallel;
308         return NULL;
309       }
310       ScXMLEltReader * onentryreader = ScXMLOnEntryElt::getElementReader();
311       ScXMLElt * onentryobj = onentryreader->read(parallel, element, doc, sm);
312       if (unlikely(!onentryobj)) {
313         delete parallel;
314         return NULL;
315       }
316       assert(onentryobj->isOfType(ScXMLOnEntryElt::getClassTypeId()));
317       parallel->setOnEntry(static_cast<ScXMLOnEntryElt *>(onentryobj));
318     }
319 
320     else if (strcmp(elementtype, "onexit") == 0) {
321       // <onexit> - zero or one time
322       if (unlikely(parallel->getOnExit())) {
323         SoDebugError::post("ScXMLParallelEltReader::read",
324                            "<parallel> elements can only have one <onexit> element");
325         delete parallel;
326         return NULL;
327       }
328       ScXMLEltReader * onexitreader = ScXMLOnExitElt::getElementReader();
329       ScXMLElt * onexitobj = onexitreader->read(parallel, element, doc, sm);
330       if (unlikely(!onexitobj)) {
331         delete parallel;
332         return NULL;
333       }
334       assert(onexitobj->isOfType(ScXMLOnExitElt::getClassTypeId()));
335       parallel->setOnExit(static_cast<ScXMLOnExitElt *>(onexitobj));
336     }
337 
338     else if (strcmp(elementtype, "transition") == 0) {
339       // <transition> - zero or more times
340       ScXMLEltReader * transitionreader = ScXMLTransitionElt::getElementReader();
341       ScXMLElt * transitionobj = transitionreader->read(parallel, element, doc, sm);
342       if (unlikely(!transitionobj)) {
343         delete parallel;
344         return NULL;
345       }
346       assert(transitionobj->isOfType(ScXMLTransitionElt::getClassTypeId()));
347       parallel->addTransition(static_cast<ScXMLTransitionElt *>(transitionobj));
348     }
349 
350     else if (strcmp(elementtype, "initial") == 0) {
351       // <initial> - must occur iff states+parallels >= 1
352       if (unlikely(parallel->getInitial())) {
353         SoDebugError::post("ScXMLInitialEltReader::read",
354                            "<parallel> elements can contain only one <initial> element");
355         delete parallel;
356         return NULL;
357       }
358       ScXMLEltReader * initialreader = ScXMLInitialElt::getElementReader();
359       ScXMLElt * initialobj = initialreader->read(parallel, element, doc, sm);
360       if (unlikely(!initialobj)) {
361         delete parallel;
362         return NULL;
363       }
364       assert(initialobj->isOfType(ScXMLInitialElt::getClassTypeId()));
365       parallel->setInitial(static_cast<ScXMLInitialElt *>(initialobj));
366     }
367 
368     else if (strcmp(elementtype, "state") == 0) {
369       // <state> - zero or more times
370       ScXMLEltReader * statereader = ScXMLStateElt::getElementReader();
371       ScXMLElt * stateobj = statereader->read(parallel, element, doc, sm);
372       if (unlikely(!stateobj)) {
373         delete parallel;
374         return NULL;
375       }
376       assert(stateobj->isOfType(ScXMLStateElt::getClassTypeId()));
377       parallel->addState(static_cast<ScXMLStateElt *>(stateobj));
378     }
379 
380     else if (strcmp(elementtype, "parallel") == 0) {
381       // <parallel> - zero or more times
382       ScXMLEltReader * parallelreader = ScXMLParallelElt::getElementReader();
383       ScXMLElt * parallelobj = parallelreader->read(parallel, element, doc, sm);
384       if (unlikely(!parallelobj)) {
385         delete parallel;
386         return NULL;
387       }
388       assert(parallelobj->isOfType(ScXMLParallelElt::getClassTypeId()));
389       parallel->addParallel(static_cast<ScXMLParallelElt *>(parallelobj));
390     }
391 
392     else if (strcmp(elementtype, "final") == 0) {
393       // <final> - zero or more times
394       ScXMLEltReader * finalreader = ScXMLFinalElt::getElementReader();
395       ScXMLElt * finalobj = finalreader->read(parallel, element, doc, sm);
396       if (unlikely(!finalobj)) {
397         delete parallel;
398         return NULL;
399       }
400       assert(finalobj->isOfType(ScXMLFinalElt::getClassTypeId()));
401       parallel->addFinal(static_cast<ScXMLFinalElt *>(finalobj));
402     }
403 
404     else if (strcmp(elementtype, "history") == 0) {
405       // <history> - zero or more times
406       ScXMLEltReader * historyreader = ScXMLHistoryElt::getElementReader();
407       ScXMLElt * historyobj = historyreader->read(parallel, element, doc, sm);
408       if (unlikely(!historyobj)) {
409         delete parallel;
410         return NULL;
411       }
412       assert(historyobj->isOfType(ScXMLHistoryElt::getClassTypeId()));
413       parallel->addHistory(static_cast<ScXMLHistoryElt *>(historyobj));
414     }
415 
416     else if (strcmp(elementtype, "anchor") == 0) {
417       // <anchor> - zero or more times
418       ScXMLEltReader * anchorreader = ScXMLAnchorElt::getElementReader();
419       ScXMLElt * anchorobj = anchorreader->read(parallel, element, doc, sm);
420       if (unlikely(!anchorobj)) {
421         delete parallel;
422         return NULL;
423       }
424       assert(anchorobj->isOfType(ScXMLAnchorElt::getClassTypeId()));
425       parallel->addAnchor(static_cast<ScXMLAnchorElt *>(anchorobj));
426     }
427 
428     else if (strcmp(elementtype, "datamodel") == 0) {
429       // <datamodel> - zero or one time
430       if (unlikely(parallel->getDataModel())) {
431         SoDebugError::post("ScXMLParallelEltReader::read",
432                            "<parallel> elements can only have one <datamodel> element");
433         delete parallel;
434         return NULL;
435       }
436       ScXMLEltReader * datamodelreader = ScXMLDataModelElt::getElementReader();
437       ScXMLElt * datamodelobj = datamodelreader->read(parallel, element, doc, sm);
438       if (unlikely(!datamodelobj)) {
439         delete parallel;
440         return NULL;
441       }
442       assert(datamodelobj->isOfType(ScXMLDataModelElt::getClassTypeId()));
443       parallel->setDataModel(static_cast<ScXMLDataModelElt *>(datamodelobj));
444     }
445 
446 #if 0
447 #if 0
448     // <invoke> - one time iff states+parallel == 0
449     else if (strcmp(elementtype, "invoke") == 0) {
450       ScXMLObject * invokeobj = ScXMLP::readScXMLInvokeElt(state, element, xmlns);
451       if (invokeobj) {
452         assert(invokeobj->isOfType(ScXMLInvokeElt::getClassTypeId()));
453         state->addInvoke(static_cast<ScXMLInvokeElt *>(invokeobj));
454       } else {
455         SoDebugError::post("ScXML::readFile", "error reading <%s> element", elementtype);
456         delete state;
457         return NULL;
458       }
459     }
460 #endif
461 #endif
462     else {
463       SoDebugError::post("ScXML::readFile",
464                          "unexpected XML element '<%s>' found in <parallel>",
465                          elementtype);
466       delete parallel;
467       return NULL;
468     }
469   }
470 
471   return parallel;
472 }
473 
474 // *************************************************************************
475 
476 class ScXMLParallelElt::PImpl {
477 public:
PImpl(void)478   PImpl(void)
479   : onentryptr(NULL),
480     onexitptr(NULL),
481     initialptr(NULL),
482     datamodelptr(NULL),
483     invokeptr(NULL)
484     //srcref(NULL)
485   {
486   }
487 
~PImpl(void)488   ~PImpl(void)
489   {
490     SCXML__CLEAR_STD_VECTOR(this->transitionlist, ScXMLTransitionElt *);
491     SCXML__CLEAR_STD_VECTOR(this->statelist, ScXMLStateElt *);
492     SCXML__CLEAR_STD_VECTOR(this->parallellist, ScXMLParallelElt *);
493     SCXML__CLEAR_STD_VECTOR(this->finallist, ScXMLFinalElt *);
494     SCXML__CLEAR_STD_VECTOR(this->historylist, ScXMLHistoryElt *);
495     SCXML__CLEAR_STD_VECTOR(this->anchorlist, ScXMLAnchorElt *);
496   }
497 
498   boost::scoped_ptr<ScXMLOnEntryElt> onentryptr;
499   boost::scoped_ptr<ScXMLOnExitElt> onexitptr;
500   std::vector<ScXMLTransitionElt *> transitionlist;
501   boost::scoped_ptr<ScXMLInitialElt> initialptr;
502   std::vector<ScXMLStateElt *> statelist;
503   std::vector<ScXMLParallelElt *> parallellist;
504   std::vector<ScXMLFinalElt *> finallist;
505   std::vector<ScXMLHistoryElt *> historylist;
506   std::vector<ScXMLAnchorElt *> anchorlist;
507   boost::scoped_ptr<ScXMLDataModelElt> datamodelptr;
508   boost::scoped_ptr<ScXMLInvokeElt> invokeptr;
509   //boost::scoped_ptr<ScXMLDocument> srcref;
510 };
511 
512 #define PRIVATE(obj) ((obj)->pimpl)
513 
514 SCXML_ELEMENT_SOURCE(ScXMLParallelElt);
515 
516 /*!
517 */
518 void
initClass(void)519 ScXMLParallelElt::initClass(void)
520 {
521   SCXML_OBJECT_INIT_CLASS(ScXMLParallelElt, ScXMLAbstractStateElt, "ScXMLAbstractStateElt");
522   SCXML_ELEMENT_REGISTER_READER(ScXMLParallelElt, "parallel", ScXMLParallelEltReader);
523 }
524 
525 /*!
526 */
527 void
cleanClass(void)528 ScXMLParallelElt::cleanClass(void)
529 {
530   SCXML_ELEMENT_UNREGISTER_READER(ScXMLParallelElt);
531   ScXMLParallelElt::classTypeId = SoType::badType();
532 }
533 
ScXMLParallelElt(void)534 ScXMLParallelElt::ScXMLParallelElt(void)
535 : src(NULL)
536 {
537 }
538 
~ScXMLParallelElt(void)539 ScXMLParallelElt::~ScXMLParallelElt(void)
540 {
541   this->setSrcAttribute(NULL);
542 }
543 
544 void
setSrcAttribute(const char * srcstr)545 ScXMLParallelElt::setSrcAttribute(const char * srcstr)
546 {
547   if (this->src && strcmp(this->src, "") != 0) {
548     // FIXME: remove externally sources states?
549   }
550   SCXML__SET_ATTRIBUTE_VALUE(this->src, "src", srcstr);
551   if ((this->src != NULL) && (strcmp(this->src, "") != 0)) {
552     // FIXME: scan string for #
553     // FIXME: load externally referenced states
554   }
555 }
556 
557 // const char * ScXMLParallelElt::getSrcAttribute(void) const
558 
559 SbBool
handleXMLAttributes(void)560 ScXMLParallelElt::handleXMLAttributes(void)
561 {
562   if (!inherited::handleXMLAttributes()) {
563     return FALSE;
564   }
565 
566   this->setSrcAttribute(this->getXMLAttribute("src"));
567 
568   return TRUE;
569 }
570 
571 void
copyContents(const ScXMLElt * rhs)572 ScXMLParallelElt::copyContents(const ScXMLElt * rhs)
573 {
574   inherited::copyContents(rhs);
575   const ScXMLParallelElt * orig = coin_assert_cast<const ScXMLParallelElt *>(rhs);
576   this->setSrcAttribute(orig->getSrcAttribute());
577 
578   int c;
579   if (orig->getOnEntry()) {
580     ScXMLOnEntryElt * onentry =
581       coin_assert_cast<ScXMLOnEntryElt *>(orig->getOnEntry()->clone());
582     this->setOnEntry(onentry);
583   }
584   if (orig->getOnExit()) {
585     ScXMLOnExitElt * onexit =
586       coin_assert_cast<ScXMLOnExitElt *>(orig->getOnExit()->clone());
587     this->setOnExit(onexit);
588   }
589   for (c = 0; c < orig->getNumTransitions(); ++c) {
590     ScXMLTransitionElt * transition =
591       coin_assert_cast<ScXMLTransitionElt *>(orig->getTransition(c)->clone());
592     this->addTransition(transition);
593   }
594   if (orig->getInitial()) {
595     ScXMLInitialElt * initial =
596       coin_assert_cast<ScXMLInitialElt *>(orig->getInitial()->clone());
597     this->setInitial(initial);
598   }
599   for (c = 0; c < orig->getNumStates(); ++c) {
600     ScXMLStateElt * state =
601       coin_assert_cast<ScXMLStateElt *>(orig->getState(c)->clone());
602     this->addState(state);
603   }
604   for (c = 0; c < orig->getNumParallels(); ++c) {
605     ScXMLParallelElt * parallel =
606       coin_assert_cast<ScXMLParallelElt *>(orig->getParallel(c)->clone());
607     this->addParallel(parallel);
608   }
609   for (c = 0; c < orig->getNumFinals(); ++c) {
610     ScXMLFinalElt * final =
611       coin_assert_cast<ScXMLFinalElt *>(orig->getFinal(c)->clone());
612     this->addFinal(final);
613   }
614   for (c = 0; c < orig->getNumHistories(); ++c) {
615     ScXMLHistoryElt * history =
616       coin_assert_cast<ScXMLHistoryElt *>(orig->getHistory(c)->clone());
617     this->addHistory(history);
618   }
619   for (c = 0; c < orig->getNumAnchors(); ++c) {
620     ScXMLAnchorElt * anchor =
621       coin_assert_cast<ScXMLAnchorElt *>(orig->getAnchor(c)->clone());
622     this->addAnchor(anchor);
623   }
624   if (orig->getDataModel()) {
625     ScXMLDataModelElt * datamodel =
626       coin_assert_cast<ScXMLDataModelElt *>(orig->getDataModel()->clone());
627     this->setDataModel(datamodel);
628   }
629 }
630 
631 const ScXMLElt *
search(const char * attrname,const char * attrvalue) const632 ScXMLParallelElt::search(const char * attrname, const char * attrvalue) const
633 {
634   const ScXMLElt * hit = inherited::search(attrname, attrvalue);
635   if (hit) {
636     return hit;
637   }
638   if (strcmp(attrname, "src") == 0) {
639     if (this->src && strcmp(attrvalue, this->src) == 0) {
640       return this;
641     }
642   }
643   if (PRIVATE(this)->onentryptr.get()) {
644     hit = PRIVATE(this)->onentryptr->search(attrname, attrvalue);
645     if (hit) {
646       return hit;
647     }
648   }
649   if (PRIVATE(this)->onexitptr.get()) {
650     hit = PRIVATE(this)->onexitptr->search(attrname, attrvalue);
651     if (hit) {
652       return hit;
653     }
654   }
655   {
656     std::vector<ScXMLTransitionElt *>::const_iterator it = PRIVATE(this)->transitionlist.begin();
657     while (it != PRIVATE(this)->transitionlist.end()) {
658       hit = (*it)->search(attrname, attrvalue);
659       if (hit) {
660         return hit;
661       }
662       ++it;
663     }
664   }
665   if (PRIVATE(this)->initialptr.get()) {
666     hit = PRIVATE(this)->initialptr->search(attrname, attrvalue);
667     if (hit) {
668       return hit;
669     }
670   }
671   {
672     std::vector<ScXMLStateElt *>::const_iterator it = PRIVATE(this)->statelist.begin();
673     while (it != PRIVATE(this)->statelist.end()) {
674       hit = (*it)->search(attrname, attrvalue);
675       if (hit) {
676         return hit;
677       }
678       ++it;
679     }
680   }
681   {
682     std::vector<ScXMLParallelElt *>::const_iterator it = PRIVATE(this)->parallellist.begin();
683     while (it != PRIVATE(this)->parallellist.end()) {
684       hit = (*it)->search(attrname, attrvalue);
685       if (hit) {
686         return hit;
687       }
688       ++it;
689     }
690   }
691   {
692     std::vector<ScXMLFinalElt *>::const_iterator it = PRIVATE(this)->finallist.begin();
693     while (it != PRIVATE(this)->finallist.end()) {
694       hit = (*it)->search(attrname, attrvalue);
695       if (hit) {
696         return hit;
697       }
698       ++it;
699     }
700   }
701   {
702     std::vector<ScXMLHistoryElt *>::const_iterator it = PRIVATE(this)->historylist.begin();
703     while (it != PRIVATE(this)->historylist.end()) {
704       hit = (*it)->search(attrname, attrvalue);
705       if (hit) {
706         return hit;
707       }
708       ++it;
709     }
710   }
711   {
712     std::vector<ScXMLAnchorElt *>::const_iterator it = PRIVATE(this)->anchorlist.begin();
713     while (it != PRIVATE(this)->anchorlist.end()) {
714       hit = (*it)->search(attrname, attrvalue);
715       if (hit) {
716         return hit;
717       }
718       ++it;
719     }
720   }
721   if (PRIVATE(this)->datamodelptr.get()) {
722     hit = PRIVATE(this)->datamodelptr->search(attrname, attrvalue);
723     if (hit) {
724       return hit;
725     }
726   }
727   return NULL;
728 }
729 
730 SCXML_SINGLE_OBJECT_API_IMPL(ScXMLParallelElt, ScXMLOnEntryElt, PRIVATE(this)->onentryptr, OnEntry);
731 
732 SCXML_SINGLE_OBJECT_API_IMPL(ScXMLParallelElt, ScXMLOnExitElt, PRIVATE(this)->onexitptr, OnExit);
733 
734 SCXML_LIST_OBJECT_API_IMPL(ScXMLParallelElt, ScXMLTransitionElt, PRIVATE(this)->transitionlist, Transition, Transitions);
735 
736 SCXML_SINGLE_OBJECT_API_IMPL(ScXMLParallelElt, ScXMLInitialElt, PRIVATE(this)->initialptr, Initial);
737 
738 SCXML_LIST_OBJECT_API_IMPL(ScXMLParallelElt, ScXMLStateElt, PRIVATE(this)->statelist, State, States);
739 
740 SCXML_LIST_OBJECT_API_IMPL(ScXMLParallelElt, ScXMLParallelElt, PRIVATE(this)->parallellist, Parallel, Parallels);
741 
742 SCXML_LIST_OBJECT_API_IMPL(ScXMLParallelElt, ScXMLFinalElt, PRIVATE(this)->finallist, Final, Finals);
743 
744 SCXML_LIST_OBJECT_API_IMPL(ScXMLParallelElt, ScXMLHistoryElt, PRIVATE(this)->historylist, History, Histories);
745 
746 SCXML_LIST_OBJECT_API_IMPL(ScXMLParallelElt, ScXMLAnchorElt, PRIVATE(this)->anchorlist, Anchor, Anchors);
747 
748 SCXML_SINGLE_OBJECT_API_IMPL(ScXMLParallelElt, ScXMLDataModelElt, PRIVATE(this)->datamodelptr, DataModel);
749 
750 // SCXML_SINGLE_OBJECT_API_IMPL(ScXMLParallelElt, ScXMLInvokeElt, PRIVATE(this)->invokeptr, Invoke);
751 
752 /*!
753   Returns TRUE if this is an "atomic state", which means that it has no
754   sub-states but contains executable content.
755 */
756 SbBool
isAtomicState(void) const757 ScXMLParallelElt::isAtomicState(void) const
758 {
759   return ((PRIVATE(this)->statelist.size() == 0) &&
760           (PRIVATE(this)->parallellist.size() == 0) &&
761           (PRIVATE(this)->invokeptr.get() != NULL));
762 }
763 
764 #undef PRIVATE
765