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 <parallel> 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