00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00039 #include <math.h>
00040
00041 #include <exception>
00042 #include <string>
00043 #include <vector>
00044 #include <map>
00045
00046
00047 #include <expat.h>
00048
00049 #include <archon/util/term.H>
00050 #include <archon/util/time.H>
00051 #include <archon/util/parse_values.H>
00052 #include <archon/util/text.H>
00053 #include <archon/util/image.H>
00054
00055 #include <archon/x3d/server/field_type.H>
00056 #include <archon/x3d/server/custom_field.H>
00057 #include <archon/x3d/server/server.H>
00058 #include <archon/x3d/server/parse_xml.H>
00059
00060 using namespace std;
00061
00062 namespace Archon
00063 {
00064 using namespace Math;
00065 using namespace Utilities;
00066
00067 namespace X3D
00068 {
00069 namespace XML
00070 {
00071 struct Parser: X3D::Parser
00072 {
00073 XML_Parser xmlParser;
00074 ProgressTracker *progressTracker;
00075 Time creationTimeStamp;
00076 bool progressive;
00077
00078 enum Element
00079 {
00080 elem_nil,
00081 elem_toplevel,
00082 elem_x3d,
00083 elem_head,
00084 elem_meta,
00085 elem_component,
00086 elem_scene,
00087 elem_route,
00088 elem_proto,
00089 elem_field,
00090 elem_node,
00091 elem_use
00092 };
00093
00094 struct StackEntry
00095 {
00096 Element element;
00097
00102 Ref<NodeBase> node;
00103
00108 Ref<CustomFieldBase> field;
00109
00110 const NodeFieldBase *containerField;
00111
00112 int containerStackIndex;
00113
00118 string cdata;
00119
00120 StackEntry(): element(elem_nil), containerField(0), containerStackIndex(-1) {}
00121 };
00122
00123 string getElementName(Element e, const NodeType *t = 0)
00124 {
00125 switch(e)
00126 {
00127 case elem_nil: return "(nil)";
00128 case elem_toplevel: return "(toplevel)";
00129 case elem_x3d: return "X3D";
00130 case elem_head: return "head";
00131 case elem_meta: return "meta";
00132 case elem_component: return "component";
00133 case elem_scene: return "Scene";
00134 case elem_route: return "ROUTE";
00135 case elem_proto: return "PROTO";
00136 case elem_field: return "field";
00137 case elem_node: return t ? t->getName() : "(node)";
00138 case elem_use: return t ? t->getName() : "(use)";
00139 }
00140 ARCHON_THROW1(ArgumentException,
00141 "Invalid element type");
00142 }
00143
00144 string getElementName(const StackEntry &e)
00145 {
00146 return getElementName(e.element, e.node ? e.node->getType() : 0);
00147 }
00148
00157 Element elementLookup(string name)
00158 {
00159 if(Text::compareIgnoreCase(name, "X3D" )==0) return elem_x3d;
00160 if(Text::compareIgnoreCase(name, "head" )==0) return elem_head;
00161 if(Text::compareIgnoreCase(name, "meta" )==0) return elem_meta;
00162 if(Text::compareIgnoreCase(name, "component")==0) return elem_component;
00163 if(Text::compareIgnoreCase(name, "Scene" )==0) return elem_scene;
00164 if(Text::compareIgnoreCase(name, "ROUTE" )==0) return elem_route;
00165 if(Text::compareIgnoreCase(name, "PROTO" )==0) return elem_proto;
00166 if(Text::compareIgnoreCase(name, "field" )==0) return elem_field;
00167 return elem_nil;
00168 }
00169
00170 vector<StackEntry> containmentStack;
00171
00172 void warning(string message)
00173 {
00174 if(logger)
00175 logger->log(sourceName + ":" + Text::toString(XML_GetCurrentLineNumber(xmlParser)) + ": [Warning] "
00176 + message);
00177 }
00178
00179 Parser(Ref<ExecutionContext> context, Ref<GroupingNode> rootGroup,
00180 string sourceName, XML_Parser xmlParser,
00181 ProgressTracker *progressTracker, Logger *logger,
00182 Time creationTimeStamp, bool progressive):
00183 X3D::Parser(context, rootGroup, sourceName, logger),
00184 xmlParser(xmlParser), progressTracker(progressTracker),
00185 creationTimeStamp(creationTimeStamp), progressive(progressive)
00186 {
00187 StackEntry stackEntry;
00188 stackEntry.element = elem_toplevel;
00189 containmentStack.push_back(stackEntry);
00190 initialize();
00191 }
00192
00193
00197 bool isWhiteSpace(const char *s)
00198 {
00199 while(*s == ' ' || *s == '\t' || *s == '\n' ||
00200 *s == '\r' || *s == '\f' || *s == ',') ++s;
00201 return !*s;
00202 }
00203
00213 bool eatWord(const char *&s, const char *&from)
00214 {
00215 const char *_s = s;
00216 while(*_s == ' ' || *_s == '\t' || *_s == '\n' ||
00217 *_s == '\r' || *_s == '\f' || *_s == ',') ++_s;
00218 if(!*_s) return false;
00219 from = _s;
00220 ++_s;
00221 while(*_s && *_s != ' ' && *_s != '\t' && *_s != '\n' &&
00222 *_s != '\r' && *_s != '\f' && *_s != ',') ++_s;
00223 s = _s;
00224 return true;
00225 }
00226
00227 bool eat(const char *&s, bool &v, bool &more)
00228 {
00229 try
00230 {
00231 const char *from;
00232 if(!eatWord(s, from)) return (more = false);
00233 v = ParseValues::parseBoolean(false, from, s);
00234 }
00235 catch(ParseException &e)
00236 {
00237 warning(e.getMessage() + "(assuming false)");
00238 v = false;
00239 }
00240 return true;
00241 }
00242
00243 bool eat(const char *&s, int &v, bool &more)
00244 {
00245 try
00246 {
00247 const char *from;
00248 if(!eatWord(s, from)) return (more = false);
00249 v = ParseValues::parseInteger(true, from, s);
00250 }
00251 catch(ParseException &e)
00252 {
00253 warning(e.getMessage() + "(assuming zero)");
00254 v = 0;
00255 }
00256 return true;
00257 }
00258
00259 bool eat(const char *&s, double &v, bool &more)
00260 {
00261 try
00262 {
00263 const char *from;
00264 if(!eatWord(s, from)) return (more = false);
00265 v = ParseValues::parseDouble(from, s);
00266 }
00267 catch(ParseException &e)
00268 {
00269 warning(e.getMessage() + "(assuming zero)");
00270 v = 0;
00271 }
00272 return true;
00273 }
00274
00275 bool eat(const char *&s, Vector2 &v, bool &more)
00276 {
00277 try
00278 {
00279 const char *from;
00280 if(!eatWord(s, from)) return (more = false);
00281 v[0] = ParseValues::parseDouble(from, s);
00282 if(!eatWord(s, from))
00283 ARCHON_THROW1(ParseException, "2nd component missing");
00284 v[1] = ParseValues::parseDouble(from, s);
00285 }
00286 catch(ParseException &e)
00287 {
00288 warning(e.getMessage() + "(assuming zero)");
00289 v = Vector2::zero();
00290 }
00291 return true;
00292 }
00293
00294 bool eat(const char *&s, Vector3 &v, bool &more)
00295 {
00296 try
00297 {
00298 const char *from;
00299 if(!eatWord(s, from)) return (more = false);
00300 v[0] = ParseValues::parseDouble(from, s);
00301 if(!eatWord(s, from))
00302 ARCHON_THROW1(ParseException, "2nd component missing");
00303 v[1] = ParseValues::parseDouble(from, s);
00304 if(!eatWord(s, from))
00305 ARCHON_THROW1(ParseException, "3rd component missing");
00306 v[2] = ParseValues::parseDouble(from, s);
00307 }
00308 catch(ParseException &e)
00309 {
00310 warning(e.getMessage() + "(assuming zero)");
00311 v = Vector3::zero();
00312 }
00313 return true;
00314 }
00315
00316 bool eat(const char *&s, Vector4 &v, bool &more)
00317 {
00318 try
00319 {
00320 const char *from;
00321 if(!eatWord(s, from)) return (more = false);
00322 v[0] = ParseValues::parseDouble(from, s);
00323 if(!eatWord(s, from))
00324 ARCHON_THROW1(ParseException, "2nd component missing");
00325 v[1] = ParseValues::parseDouble(from, s);
00326 if(!eatWord(s, from))
00327 ARCHON_THROW1(ParseException, "3rd component missing");
00328 v[2] = ParseValues::parseDouble(from, s);
00329 if(!eatWord(s, from))
00330 ARCHON_THROW1(ParseException, "4th component missing");
00331 v[3] = ParseValues::parseDouble(from, s);
00332 }
00333 catch(ParseException &e)
00334 {
00335 warning(e.getMessage() + "(assuming zero)");
00336 v = Vector4::zero();
00337 }
00338 return true;
00339 }
00340
00341 bool eat(const char *&s, Rotation3 &v, bool &more)
00342 {
00343 try
00344 {
00345 const char *from;
00346 if(!eatWord(s, from)) return (more = false);
00347 v.axis[0] = ParseValues::parseDouble(from, s);
00348 if(!eatWord(s, from))
00349 ARCHON_THROW1(ParseException, "y component missing");
00350 v.axis[1] = ParseValues::parseDouble(from, s);
00351 if(!eatWord(s, from))
00352 ARCHON_THROW1(ParseException, "z component missing");
00353 v.axis[2] = ParseValues::parseDouble(from, s);
00354 if(!eatWord(s, from))
00355 ARCHON_THROW1(ParseException, "angle missing");
00356 v.angle = ParseValues::parseDouble(from, s);
00357 }
00358 catch(ParseException &e)
00359 {
00360 warning(e.getMessage() + "(assuming no rotation)");
00361 v = Rotation3::zero();
00362 }
00363 return true;
00364 }
00365
00366
00370 bool eat(const char *&s, Image &v, bool &more)
00371 {
00372 try
00373 {
00374 const char *from;
00375 if(!eatWord(s, from)) return (more = false);
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 }
00389 catch(ParseException &e)
00390 {
00391 warning(e.getMessage() + "(assuming no rotation)");
00392
00393 }
00394 return true;
00395 }
00396
00397 bool eat(const char *&s, Time &v, bool &more)
00398 {
00399 double w;
00400 if(!eat(s, w, more)) return false;
00401 v = Time(w);
00402 return true;
00403 }
00404
00405
00406 template<class T>
00407 bool parseValue(const char *s, T &v)
00408 {
00409 T w;
00410 bool m;
00411 if(!eat(s, w, m))
00412 {
00413 warning("Empty string");
00414 return false;
00415 }
00416 if(!isWhiteSpace(s)) warning("Trailing garbage");
00417 v = w;
00418 return true;
00419 }
00420
00421 template<class T>
00422 bool parseValue(const char *s, vector<T> &l)
00423 {
00424 l.clear();
00425 T v;
00426 bool m = true;
00427 while(m) if(eat(s, v, m)) l.push_back(v);
00428 return true;
00429 }
00430
00435 bool parseValue(const char *s, string &v)
00436 {
00437 v = s;
00438 return true;
00439 }
00440
00444 bool parseValue(const char *s, vector<string> &v)
00445 {
00446 for(;;)
00447 {
00448 while(*s == ' ' || *s == '\t' || *s == '\n' ||
00449 *s == '\r' || *s == '\f' || *s == ',') ++s;
00450 if(!*s) break;
00451 if(*s == '"' || *s == '\'')
00452 {
00453 const char *to = strchr(s+1, *s);
00454 ++s;
00455 int n = to ? to - s : strlen(s);
00456 v.push_back(string(s, n));
00457 if(!to)
00458 {
00459 warning("Unpaired quotation");
00460 break;
00461 }
00462 s += n+1;
00463 continue;
00464 }
00465
00466 const char *to = s+1;
00467 while(*to && *to != '"' && *to != '\'') ++to;
00468 --to;
00469 while(*to == ' ' || *to == '\t' || *to == '\n' ||
00470 *to == '\r' || *to == '\f' || *to == ',') --to;
00471 ++to;
00472 int n = to - s;
00473 v.push_back(string(s, n));
00474 s = to;
00475 }
00476
00477 return true;
00478 }
00479
00480
00481
00482 struct ValueParserBase
00483 {
00484 virtual void parse(const char *, NodeBase *,
00485 const FieldBase *, Parser *) const = 0;
00486
00487 virtual Ref<CustomFieldBase>
00488 newCustomField(CustomFieldNode *c,
00489 int i, string n, const FieldType *t,
00490 bool isEventTarget, bool isEventSource,
00491 Parser *p, const char *s) const = 0;
00492
00493 protected:
00494 virtual ~ValueParserBase() {}
00495 };
00496
00497 template<typename T>
00498 struct SingleValueParser: ValueParserBase
00499 {
00500 void parse(const char *s, NodeBase *n, const FieldBase *f,
00501 Parser *p) const
00502 {
00503 T v;
00504 if(p->parseValue(s, v))
00505 {
00506 Ref<SimpleValue<T> > w = new SimpleValue<T>(f->getType(), v);
00507 Event e(w.get(), p->creationTimeStamp);
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 n->set(f, &e);
00518 }
00519 }
00520
00521 Ref<CustomFieldBase>
00522 newCustomField(CustomFieldNode *c,
00523 int i, string n, const FieldType *t,
00524 bool isEventTarget, bool isEventSource,
00525 Parser *p, const char *s) const
00526 {
00527 T v;
00528 if(s && p->parseValue(s, v))
00529 {
00530 return new SimpleCustomField<T>(c, i, n, t, isEventTarget,
00531 isEventSource, v);
00532 }
00533 return new SimpleCustomField<T>(c, i, n, t, isEventTarget,
00534 isEventSource, defaultValue);
00535 }
00536
00537 SingleValueParser(const T &v): defaultValue(v) {}
00538
00539 private:
00540 T defaultValue;
00541 };
00542
00543 template<typename T>
00544 struct SequenceValueParser: ValueParserBase
00545 {
00546 typedef vector<T> V;
00547
00548 void parse(const char *s, NodeBase *n, const FieldBase *f,
00549 Parser *p) const
00550 {
00551 V v;
00552 if(p->parseValue(s, v))
00553 {
00554 Ref<SimpleValue<V> > w = new SimpleValue<V>(f->getType(), v);
00555 Event e(w.get(), p->creationTimeStamp);
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 n->set(f, &e);
00566 }
00567 }
00568
00569 Ref<CustomFieldBase>
00570 newCustomField(CustomFieldNode *c,
00571 int i, string n, const FieldType *t,
00572 bool isEventTarget, bool isEventSource,
00573 Parser *p, const char *s) const
00574 {
00575 V v;
00576 if(s && p->parseValue(s, v))
00577 {
00578 return new SimpleSeqCustomField<T>(c, i, n, t, isEventTarget,
00579 isEventSource, v);
00580 }
00581 return new SimpleSeqCustomField<T>(c, i, n, t, isEventTarget,
00582 isEventSource, defaultValue);
00583 }
00584
00585 private:
00586 V defaultValue;
00587 };
00588
00589 map<const FieldType *, const ValueParserBase *> valueParsers;
00590
00591 map<string, string> compatibilityFieldTypeNameMap;
00592
00593 void initialize()
00594 {
00595 Vector4 one4;
00596 one4[0] = one4[1] = one4[2] = one4[3] = 1;
00597
00598 valueParsers[SFBool::type] = new SingleValueParser<bool>(false);
00599 valueParsers[MFBool::type] = new SequenceValueParser<bool>;
00600
00601 valueParsers[SFColor::type] = new SingleValueParser<Vector3>(Vector3(1, 1, 1));
00602 valueParsers[MFColor::type] = new SequenceValueParser<Vector3>;
00603
00604 valueParsers[SFColorRGBA::type] = new SingleValueParser<Vector4>(one4);
00605 valueParsers[MFColorRGBA::type] = new SequenceValueParser<Vector4>;
00606
00607 valueParsers[SFDouble::type] = new SingleValueParser<double>(0);
00608 valueParsers[MFDouble::type] = new SequenceValueParser<double>;
00609
00610 valueParsers[SFFloat::type] = new SingleValueParser<double>(0);
00611 valueParsers[MFFloat::type] = new SequenceValueParser<double>;
00612
00613 valueParsers[SFImage::type] = new SingleValueParser<Image>(Image());
00614 valueParsers[MFImage::type] = new SequenceValueParser<Image>;
00615
00616 valueParsers[SFInt32::type] = new SingleValueParser<int>(0);
00617 valueParsers[MFInt32::type] = new SequenceValueParser<int>;
00618
00619 valueParsers[SFRotation::type] = new SingleValueParser<Rotation3>(Rotation3(Vector3(0, 0, 1), 0));
00620 valueParsers[MFRotation::type] = new SequenceValueParser<Rotation3>;
00621
00622 valueParsers[SFString::type] = new SingleValueParser<string>(string());
00623 valueParsers[MFString::type] = new SequenceValueParser<string>;
00624
00625 valueParsers[SFTime::type] = new SingleValueParser<Time>(Time());
00626 valueParsers[MFTime::type] = new SequenceValueParser<Time>;
00627
00628 valueParsers[SFVec2d::type] = new SingleValueParser<Vector2>(Vector2(0, 0));
00629 valueParsers[MFVec2d::type] = new SequenceValueParser<Vector2>;
00630
00631 valueParsers[SFVec2f::type] = new SingleValueParser<Vector2>(Vector2(0, 0));
00632 valueParsers[MFVec2f::type] = new SequenceValueParser<Vector2>;
00633
00634 valueParsers[SFVec3d::type] = new SingleValueParser<Vector3>(Vector3(0, 0, 0));
00635 valueParsers[MFVec3d::type] = new SequenceValueParser<Vector3>;
00636
00637 valueParsers[SFVec3f::type] = new SingleValueParser<Vector3>(Vector3(0, 0, 0));
00638 valueParsers[MFVec3f::type] = new SequenceValueParser<Vector3>;
00639
00640
00641 compatibilityFieldTypeNameMap["Boolean"] = "SFBool";
00642 compatibilityFieldTypeNameMap["Booleans"] = "MFBool";
00643 compatibilityFieldTypeNameMap["Color"] = "SFColor";
00644 compatibilityFieldTypeNameMap["Colors"] = "MFColor";
00645 compatibilityFieldTypeNameMap["Double"] = "SFDouble";
00646 compatibilityFieldTypeNameMap["Doubles"] = "MFDouble";
00647 compatibilityFieldTypeNameMap["Float"] = "SFFloat";
00648 compatibilityFieldTypeNameMap["Floats"] = "MFFloat";
00649 compatibilityFieldTypeNameMap["Image"] = "SFImage";
00650 compatibilityFieldTypeNameMap["Images"] = "MFImage";
00651 compatibilityFieldTypeNameMap["Integer"] = "SFInt32";
00652 compatibilityFieldTypeNameMap["Integers"] = "MFInt32";
00653 compatibilityFieldTypeNameMap["Node"] = "SFNode";
00654 compatibilityFieldTypeNameMap["Nodes"] = "MFNode";
00655 compatibilityFieldTypeNameMap["Rotation"] = "SFRotation";
00656 compatibilityFieldTypeNameMap["Rotations"] = "MFRotation";
00657 compatibilityFieldTypeNameMap["String"] = "SFString";
00658 compatibilityFieldTypeNameMap["Strings"] = "MFString";
00659 compatibilityFieldTypeNameMap["Time"] = "SFTime";
00660 compatibilityFieldTypeNameMap["Times"] = "MFTime";
00661 compatibilityFieldTypeNameMap["Vector2Float"] = "SFVec2f";
00662 compatibilityFieldTypeNameMap["Vector2FloatArray"] = "MFVec2f";
00663 compatibilityFieldTypeNameMap["Vector3Float"] = "SFVec3f";
00664 compatibilityFieldTypeNameMap["Vector3FloatArray"] = "MFVec3f";
00665 compatibilityFieldTypeNameMap["Vector2Double"] = "SFVec2f";
00666 compatibilityFieldTypeNameMap["Vector2DoubleArray"] = "MFVec2f";
00667 compatibilityFieldTypeNameMap["Vector3Double"] = "SFVec3d";
00668 compatibilityFieldTypeNameMap["Vector3DoubleArray"] = "MFVec3d";
00669 }
00670
00671 Ref<NodeBase> lookupUseNode(string name, const NodeType *type)
00672 {
00673 Ref<NodeBase> node = lookupNode(name);
00674 if(!node)
00675 {
00676 warning("Undefined name '" + name + "' in 'USE'");
00677 return 0;
00678 }
00679 if(node->getType() != type)
00680 {
00681 warning("Attempt to use '" + node->getType()->getName() + "' as '" + type->getName() + "'");
00682 return 0;
00683 }
00684 return node;
00685 }
00686
00687 Ref<NodeBase> checkUseAttribute(const char *atts[], const NodeType *nodeType)
00688 {
00689 Ref<NodeBase> n;
00690 bool noUse = false;
00691 for(int i=0; atts[i] && atts[i+1]; i+=2)
00692 {
00693 if(Text::compareIgnoreCase(atts[i], "USE") == 0)
00694 {
00695 if(string(atts[i]) != "USE")
00696 warning("Attribute '" + string(atts[i]) + "' should be spelled 'USE'");
00697 n = lookupUseNode(atts[i+1], nodeType);
00698 }
00699 else if(Text::compareIgnoreCase(atts[i], "containerField") != 0)
00700 noUse = true;
00701 if(noUse && n)
00702 {
00703 warning("Only the 'containerField' attributes is accepted in conjunction with 'USE'");
00704 break;
00705 }
00706 }
00707 return n;
00708 }
00709
00710 void displayStack(bool push)
00711 {
00712 vector<double> columnWidthFractions;
00713 columnWidthFractions.push_back(2);
00714 columnWidthFractions.push_back(5);
00715 columnWidthFractions.push_back(10);
00716 columnWidthFractions.push_back(10);
00717 columnWidthFractions.push_back(2);
00718 columnWidthFractions.push_back(2);
00719 columnWidthFractions.push_back(10);
00720 columnWidthFractions.push_back(10);
00721 Text::Table<string> table(containmentStack.size()+1, columnWidthFractions);
00722 for(unsigned i=0; i<containmentStack.size(); ++i)
00723 {
00724 StackEntry &e = containmentStack[i];
00725 table(i, 0) = Text::toString(i);
00726 table(i, 1) = getElementName(e.element);
00727 table(i, 2) = e.node ? e.node->getType()->getName() : "";
00728 table(i, 3) = e.node ? e.node->getName() : "";
00729 table(i, 4) = "->";
00730 table(i, 5) = Text::toString(e.containerStackIndex);
00731 table(i, 6) = e.containerField ? e.containerField->getName() : "";
00732 table(i, 7) = e.containerField ? e.containerField->getType()->getName() : "";
00733 }
00734
00735 logger->log("Stack " + string(push?"push":"pop") + ":\n" +
00736 Text::format(table, Term::getWidth(), 2, false));
00737 }
00738
00739 bool attr_cmp(string s, string attribute, Element element,
00740 bool deprecated = false)
00741 {
00742 if(Text::compareIgnoreCase(s, attribute)==0)
00743 {
00744 if(s != attribute)
00745 warning("Attribute '" + s + "' of element '" +
00746 getElementName(element) + "' should be spelled '" +
00747 attribute + "'");
00748 if(deprecated)
00749 warning("Use of attribute '" + s + "' in element '" +
00750 getElementName(element) + "' is deprecated.");
00751 return true;
00752 }
00753 return false;
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791 void parseStartElement(const char *name, const char *atts[],
00792 StackEntry *stackEntry)
00793 {
00794
00795 Element element = elementLookup(name);
00796 const NodeType *nodeType = 0;
00797
00798 if(element == elem_nil)
00799 {
00800 nodeType = NodeType::lookup(name);
00801
00802 if(!nodeType || !nodeType->isUserInstantiable())
00803 {
00804 warning("Unknown element '" + string(name) + "' (element ignored)");
00805 return;
00806 }
00807
00808 if(nodeType->getName() != name)
00809 warning("Element '" + string(name) + "' should be spelled '" +
00810 nodeType->getName() + "'");
00811
00812 element = elem_node;
00813 }
00814 else if(getElementName(element) != name)
00815 warning("Element '" + string(name) + "' should be spelled '" +
00816 getElementName(element) + "'");
00817
00818
00819
00820
00821 string containerFieldName;
00822 if(nodeType)
00823 {
00824 bool found = false;
00825 for(int i=0; atts[i] && atts[i+1]; i+=2)
00826 {
00827 if(Text::compareIgnoreCase(atts[i], "containerField") == 0)
00828 {
00829 if(string(atts[i]) != "containerField")
00830 warning("Attribute '" + string(atts[i]) + "' should be spelled 'containerField'");
00831 containerFieldName = atts[i+1];
00832 found = true;
00833 break;
00834 }
00835 }
00836 if(!found) containerFieldName = nodeType->getContainerField();
00837 }
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849 int containerStackIndex = -1;
00850 const NodeFieldBase *containerField = 0;
00851 bool fallThrough = false;
00852 for(int i = int(containmentStack.size())-1; i>=0; --i)
00853 {
00854 if(i < int(containmentStack.size())-1) fallThrough = true;
00855
00856 Element containerElement = containmentStack[i].element;
00857
00858
00859 if(containerElement == elem_nil ||
00860 containerElement == elem_route ||
00861 containerElement == elem_proto ||
00862 containerElement == elem_use) continue;
00863
00864
00865 if(element == elem_node)
00866 {
00867 if(containerElement == elem_field)
00868 {
00869 if(NodeFieldBase *f = dynamic_cast<NodeFieldBase *>(containmentStack[i].field.get()))
00870 {
00871 containerStackIndex = containmentStack[i].containerStackIndex;
00872 containerField = f;
00873 break;
00874 }
00875 continue;
00876 }
00877
00878 if(containerElement == elem_scene &&
00879 nodeType->isDerivedFrom(ChildNode::type))
00880 {
00881 containerStackIndex = i;
00882 break;
00883 }
00884
00885 if(containerElement != elem_node) break;
00886
00887 Ref<NodeBase> n = containmentStack[i].node;
00888 if(!n) ARCHON_THROW1(InternalException,
00889 "x3d/parse_xml: Stack entry "
00890 "unexpectedly had no node");
00891 const NodeType *t = n->getType();
00892 containerField = dynamic_cast<const NodeFieldBase *>(t->lookupField(containerFieldName));
00893 if(!containerField)
00894 {
00895 containerField = t->lookupNodeField(nodeType);
00896 if(containerField)
00897 warning("Bad container field '" + containerFieldName +
00898 "' (using '" + containerField->getName() + "')");
00899 }
00900 if(containerField)
00901 {
00902 containerStackIndex = i;
00903 break;
00904 }
00905 continue;
00906 }
00907
00908
00909 if(element == elem_field)
00910 {
00911 if(containerElement != elem_node) continue;
00912
00913 Ref<NodeBase> n = containmentStack[i].node;
00914 if(!n) ARCHON_THROW1(InternalException,
00915 "XML::Parser::parseStartElement: "
00916 "Stack entry unexpectedly had no "
00917 "node");
00918 if(!dynamic_cast<CustomFieldNode *>(n.get())) continue;
00919 containerStackIndex = i;
00920 break;
00921 }
00922
00923
00924 if(element == elem_route || element == elem_proto)
00925 {
00926 if(containerElement == elem_scene ||
00927 containerElement == elem_node)
00928 {
00929 containerStackIndex = i;
00930 break;
00931 }
00932 continue;
00933 }
00934
00935
00936 if(element == elem_x3d && containerElement == elem_toplevel ||
00937 element == elem_head && containerElement == elem_x3d ||
00938 element == elem_meta && containerElement == elem_head ||
00939 element == elem_component && containerElement == elem_head ||
00940 element == elem_scene && containerElement == elem_x3d)
00941 {
00942 containerStackIndex = i;
00943 break;
00944 }
00945 }
00946
00947
00948
00949
00950
00951
00952
00953
00954 if(containerStackIndex < 0 || fallThrough)
00955 {
00956 string message;
00957 switch(containmentStack.back().element)
00958 {
00959 case elem_toplevel:
00960 message = "Element '" + getElementName(element, nodeType) +
00961 "' is not allowed as the top level element";
00962 break;
00963 case elem_use:
00964 message = "Element '" + getElementName(element, nodeType) +
00965 "' is not allowed in elements that employ the USE "
00966 "attribute";
00967 break;
00968 case elem_nil:
00969 message = "Ill placed element '" +
00970 getElementName(element, nodeType) + "'";
00971 break;
00972 case elem_field:
00973 message = "Node elements are not allowed in field elements "
00974 "of type '" +
00975 containmentStack.back().field->getType()->getName() + "'";
00976 break;
00977 default:
00978 message = "Element '" + getElementName(element, nodeType) +
00979 "' is not allowed in '" +
00980 getElementName(containmentStack.back()) + "'";
00981 }
00982
00983 if(containerStackIndex == -1)
00984 {
00985 warning(message + " (element ignored)");
00986 return;
00987 }
00988
00989 warning(message + " (fall-through to closest '" +
00990 getElementName(containmentStack[containerStackIndex]) +
00991 "' established)");
00992 }
00993
00994
00995 Ref<NodeBase> node;
00996 Ref<CustomFieldBase> field;
00997
00998 if(element == elem_route)
00999 {
01000 string fromNode;
01001 string fromField;
01002 string toNode;
01003 string toField;
01004 bool gotFromNode = false;
01005 bool gotFromField = false;
01006 bool gotToNode = false;
01007 bool gotToField = false;
01008
01009 for(int i=0; atts[i] && atts[i+1]; i+=2)
01010 {
01011 if(attr_cmp(atts[i], "fromNode", element))
01012 {
01013 gotFromNode = parseValue(atts[i+1], fromNode);
01014 }
01015 else if(attr_cmp(atts[i], "fromField", element))
01016 {
01017 gotFromField = parseValue(atts[i+1], fromField);
01018 }
01019 else if(attr_cmp(atts[i], "toNode", element))
01020 {
01021 gotToNode = parseValue(atts[i+1], toNode);
01022 }
01023 else if(attr_cmp(atts[i], "toField", element))
01024 {
01025 gotToField = parseValue(atts[i+1], toField);
01026 }
01027 else
01028 {
01029 warning("Unrecognized attribute '" + string(atts[i]) +
01030 "' of element '" + getElementName(element) + "' (attribute ignored)");
01031 }
01032 }
01033
01034 bool skip = false;
01035 if(!gotFromNode)
01036 {
01037 warning("Required attribute 'fromNode' of element '" +
01038 getElementName(element) + "' is missing (element ignored)");
01039 skip = true;
01040 }
01041 if(!gotFromField)
01042 {
01043 warning("Required attribute 'fromField' of element '" +
01044 getElementName(element) + "' is missing (element ignored)");
01045 skip = true;
01046 }
01047 if(!gotToNode)
01048 {
01049 warning("Required attribute 'toNode' of element '" +
01050 getElementName(element) + "' is missing (element ignored)");
01051 skip = true;
01052 }
01053 if(!gotToField)
01054 {
01055 warning("Required attribute 'toField' of element '" +
01056 getElementName(element) + "' is missing (element ignored)");
01057 skip = true;
01058 }
01059 if(!skip) addRoute(fromNode, fromField, toNode, toField);
01060 }
01061 else if(element == elem_proto)
01062 {
01063 warning("Element '" + getElementName(element) + "' is not supported yet (ignored)");
01064 }
01065 else if(element == elem_field)
01066 {
01067 string name;
01068 string accessType;
01069 string type;
01070 string use;
01071
01072 bool gotName = false;
01073 bool gotAccessType = false;
01074 bool gotType = false;
01075 int gotValue = -1;
01076 bool gotUse = false;
01077
01078 for(int i=0; atts[i] && atts[i+1]; i+=2)
01079 {
01080 if(attr_cmp(atts[i], "name", element))
01081 {
01082 gotName = parseValue(atts[i+1], name);
01083 }
01084 else if(attr_cmp(atts[i], "accessType", element))
01085 {
01086 gotAccessType = parseValue(atts[i+1], accessType);
01087 }
01088 else if(attr_cmp(atts[i], "type", element))
01089 {
01090 gotType = parseValue(atts[i+1], type);
01091 }
01092 else if(attr_cmp(atts[i], "value", element))
01093 {
01094 gotValue = i+1;
01095 }
01096 else if(attr_cmp(atts[i], "USE", element, true))
01097 {
01098
01099 gotUse = parseValue(atts[i+1], use);
01100 }
01101 else
01102 {
01103 warning("Unrecognized attribute '" + string(atts[i]) +
01104 "' of element '" + getElementName(element) + "' (attribute ignored)");
01105 }
01106 }
01107
01108 bool isEventTarget = false;
01109 bool isEventSource = false;
01110
01111 bool skip = false;
01112 if(gotName && !validateIdentifier(name))
01113 {
01114 warning("Illegal value '" + name + "' of attribute 'name' "
01115 "in element 'field' (element ignored)");
01116 skip = true;
01117 }
01118
01119 if(gotAccessType)
01120 {
01121 if(Text::compareIgnoreCase("initializeOnly", accessType) == 0 ||
01122 Text::compareIgnoreCase("field", accessType) == 0);
01123 else if(Text::compareIgnoreCase("inputOnly", accessType) == 0 ||
01124 Text::compareIgnoreCase("eventIn", accessType) == 0)
01125 isEventTarget = true;
01126 else if(Text::compareIgnoreCase("outputOnly", accessType) == 0 ||
01127 Text::compareIgnoreCase("eventOut", accessType) == 0)
01128 isEventSource = true;
01129 else if(Text::compareIgnoreCase("inputOutput", accessType) == 0 ||
01130 Text::compareIgnoreCase("exposedField", accessType) == 0)
01131 isEventTarget = isEventSource = true;
01132 else
01133 {
01134 warning("Unrecognized attribute value '" + accessType +
01135 "' of attribute 'accessType' of element 'field' "
01136 "(assuming 'initializeOnly')");
01137 accessType = "initializeOnly";
01138 }
01139
01140 if(!isEventTarget && !isEventSource &&
01141 accessType != "initializeOnly")
01142 warning("Attribute value '" + accessType + "' of attribute "
01143 "'accessType' of element 'field' should be spelled "
01144 "'initializeOnly'");
01145 if(isEventTarget && !isEventSource && accessType != "inputOnly")
01146 warning("Attribute value '" + accessType + "' of attribute "
01147 "'accessType' of element 'field' should be spelled "
01148 "'inputOnly'");
01149 if(!isEventTarget && isEventSource && accessType != "outputOnly")
01150 warning("Attribute value '" + accessType + "' of attribute "
01151 "'accessType' of element 'field' should be spelled "
01152 "'outputOnly'");
01153 if(isEventTarget && isEventSource && accessType != "inputOutput")
01154 warning("Attribute value '" + accessType + "' of attribute "
01155 "'accessType' of element 'field' should be spelled "
01156 "'inputOutput'");
01157 }
01158
01159 const FieldType *fieldType = 0;
01160 if(gotType)
01161 {
01162 string mappedType = type;
01163 map<string, string>::iterator i =
01164 compatibilityFieldTypeNameMap.find(type);
01165 if(i != compatibilityFieldTypeNameMap.end())
01166 mappedType = i->second;
01167
01168 fieldType = FieldType::lookup(mappedType);
01169 if(!fieldType)
01170 {
01171 warning("Unrecognized attribute value '" + type + "' of attribute "
01172 "'type' of element 'field' (element ignored)");
01173 skip = true;
01174 }
01175 else if(fieldType->getName() != type)
01176 warning("Attribute value '" + type + "' of attribute "
01177 "'type' of element 'field' should be spelled "
01178 "'" + fieldType->getName() + "'");
01179 }
01180
01181 if(!gotName)
01182 {
01183 warning("Required attribute 'Name' of element '" +
01184 getElementName(element) + "' is missing (element ignored)");
01185 skip = true;
01186 }
01187 if(!gotAccessType)
01188 warning("Required attribute 'accessType' of element '" +
01189 getElementName(element) + "' is missing (assuming 'initializeOnly')");
01190 if(!gotType)
01191 {
01192 warning("Required attribute 'type' of element '" +
01193 getElementName(element) + "' is missing (element ignored)");
01194 skip = true;
01195 }
01196
01197
01198 if(!skip && fieldType)
01199 {
01200 CustomFieldNode *n = dynamic_cast<CustomFieldNode *>
01201 (containmentStack[containerStackIndex].node.get());
01202 if(!n) ARCHON_THROW1(InternalException,
01203 "XML::Parser::parseStartElement: "
01204 "Custom field container was not a "
01205 "CustumFieldNode");
01206 int customFieldIndex = getNextCustomFieldIndex(n);
01207
01208 Ref<Node> useNode;
01209 if(gotUse)
01210 {
01211 Ref<NodeBase> u = lookupNode(use);
01212 useNode = dynamic_cast<Node *>(u.get());
01213 if(!useNode)
01214 warning("Undefined node name '" + use + "' in 'USE' "
01215 "attribute of field element");
01216 }
01217
01218 if(fieldType == SFNode::type)
01219 field = new NodeCustomField<Node>
01220 (n, customFieldIndex, name, Node::type,
01221 isEventTarget, isEventSource, useNode);
01222 else if(fieldType == MFNode::type)
01223 {
01224 vector<Ref<Node> > v;
01225 if(useNode) v.push_back(useNode);
01226 field = new NodeSequenceCustomField<Node>
01227 (n, customFieldIndex, name, Node::type,
01228 isEventTarget, isEventSource, v);
01229 }
01230 else
01231 {
01232 field = valueParsers[fieldType]->newCustomField
01233 (n, customFieldIndex, name, fieldType,
01234 isEventTarget, isEventSource,
01235 this, gotValue >= 0 ? atts[gotValue] : 0);
01236 if(useNode)
01237 warning("The USE attribute may not be used in field "
01238 "elements with type '" + fieldType->getName() +
01239 "' (attribute ignored)");
01240 }
01241 }
01242 }
01243 else if(element == elem_node)
01244 {
01245
01246 node = checkUseAttribute(atts, nodeType);
01247
01248
01249
01250
01251
01252
01253 if(node) element = elem_use;
01254 else node = nodeType->instantiate(context);
01255
01256
01257
01258 if(element != elem_use) for(int i=0; atts[i] && atts[i+1]; i+=2)
01259 {
01260 if(Text::compareIgnoreCase(atts[i], "DEF") == 0)
01261 {
01262 if(string(atts[i]) != "DEF")
01263 warning("Attribute '" + string(atts[i]) + "' should be spelled 'DEF'");
01264
01265 const string name = atts[i+1];
01266 if(validateIdentifier(name)) addNamedNode(name, node);
01267 else
01268 warning("Illegal value '" + name + "' of attribute 'DEF' "
01269 "in element '" + nodeType->getName() + "' (attribute ignored)");
01270 }
01271 else if(Text::compareIgnoreCase(atts[i], "containerField") != 0)
01272 {
01273 const FieldBase *field = nodeType->lookupField(atts[i]);
01274 if(!field)
01275 {
01276 warning("Unrecognized attribute '" + string(atts[i]) +
01277 "' of element '" + nodeType->getName() + "' (attribute ignored)");
01278 continue;
01279 }
01280 if(field->getType() == SFNode::type || field->getType() == MFNode::type)
01281 {
01282 warning("Illegal node type attribute '" + string(atts[i]) +
01283 "' of element '" + nodeType->getName() + "' (attribute ignored)");
01284 continue;
01285 }
01286
01287 if(field->getName() != atts[i])
01288 warning("Attribute '" + string(atts[i]) + "' should be spelled '" +
01289 field->getName() + "'");
01290
01291 valueParsers[field->getType()]->parse(atts[i+1], node.get(), field, this);
01292 }
01293 }
01294 }
01295
01296 stackEntry->element = element;
01297 stackEntry->node = node;
01298 stackEntry->field = field;
01299 stackEntry->containerField = containerField;
01300 stackEntry->containerStackIndex = containerStackIndex;
01301
01302 if(progressive &&
01303 (element == elem_node || element == elem_use) &&
01304 !dynamic_cast<CustomFieldNode *>(node.get()))
01305 injectChild(stackEntry);
01306 }
01307
01308 void startElement(const char *name, const char *atts[])
01309 {
01310 StackEntry stackEntry;
01311 parseStartElement(name, atts, &stackEntry);
01312 containmentStack.push_back(stackEntry);
01313
01314 }
01315
01316 void endElement()
01317 {
01318 StackEntry stackEntry = containmentStack.back();
01319 containmentStack.pop_back();
01320
01321
01322
01323 if(stackEntry.element == elem_field)
01324 {
01325 if(!stackEntry.field) return;
01326 if(stackEntry.containerStackIndex < 0) return;
01327 Ref<CustomFieldNode> n = dynamic_cast<CustomFieldNode *>
01328 (containmentStack[stackEntry.containerStackIndex].node.get());
01329 if(!n) ARCHON_THROW1(InternalException,
01330 "XML::Parser::endElement: "
01331 "Custom field container was not a "
01332 "CustomFieldNode");
01333
01334 addScriptField(n, stackEntry.field);
01335
01336 return;
01337 }
01338
01339
01340 if(stackEntry.element != elem_node &&
01341 stackEntry.element != elem_use) return;
01342
01343
01344 if(stackEntry.element == elem_node)
01345 if(CDATANode *n = dynamic_cast<CDATANode *>(stackEntry.node.get()))
01346 {
01347 string s = Text::trim(stackEntry.cdata);
01348 if(s.size()) n->handleCDATA(s, creationTimeStamp);
01349 }
01350
01351 if(!progressive ||
01352 dynamic_cast<CustomFieldNode *>(stackEntry.node.get()))
01353 injectChild(&stackEntry);
01354 }
01355
01356 void injectChild(StackEntry *stackEntry)
01357 {
01358
01359 if(!stackEntry->containerField)
01360 {
01361 addRootGroupChild(dynamic_cast<ChildNode *>
01362 (stackEntry->node.get()), creationTimeStamp);
01363 return;
01364 }
01365
01366
01367
01368 if(!containmentStack[stackEntry->containerStackIndex].node->inject
01369 (stackEntry->containerField, stackEntry->node, creationTimeStamp))
01370 warning("Element '" +
01371 containmentStack[stackEntry->containerStackIndex].node->
01372 getType()->getName() +
01373 "' already contains a '" +
01374 stackEntry->node->getType()->getName() +
01375 "' (additional element ignored)");
01376 }
01377
01378 void characterDataHandler(const char *s, int n)
01379 {
01380 StackEntry &stackEntry = containmentStack.back();
01381 if(dynamic_cast<const CDATANode *>(stackEntry.node.get()))
01382 stackEntry.cdata.append(s, n);
01383 }
01384 };
01385
01386 namespace
01387 {
01388 void startElement(void *userData, const char *name, const char *atts[]) throw()
01389 {
01390 Parser *p = static_cast<Parser *>(userData);
01391 p->startElement(name, atts);
01392 }
01393
01394 void endElement(void *userData, const char *) throw()
01395 {
01396 Parser *p = static_cast<Parser *>(userData);
01397 p->endElement();
01398 }
01399
01400 void characterData(void *userData, const char *s, int n)
01401 {
01402 Parser *p = static_cast<Parser *>(userData);
01403 p->characterDataHandler(s, n);
01404 }
01405
01406 struct XmlParserWrapper
01407 {
01408 const XML_Parser ptr;
01409
01410 XmlParserWrapper(XML_Parser ptr):ptr(ptr) {}
01411
01412 ~XmlParserWrapper()
01413 {{
01414 if(ptr) XML_ParserFree(ptr);
01415 }}
01416 };
01417 }
01418
01419
01420 void parse(Ref<ExecutionContext> context, Ref<GroupingNode> group,
01421 Ref<Stream::Reader> reader, bool progressive, Logger *logger,
01422 string sourceName, ProgressTracker *progressTracker)
01423 {
01424 Ref<Server> server;
01425 try { server = context->server.getRef(); }
01426 catch(ForwardDestroyedException &) { return; }
01427
01428 XmlParserWrapper p(XML_ParserCreate(0));
01429 XML_SetElementHandler(p.ptr, startElement, endElement);
01430 XML_SetCharacterDataHandler(p.ptr, characterData);
01431
01432 Parser parser(context, group,
01433 sourceName.empty() ? context->getBaseUri().getFile() :
01434 sourceName, p.ptr, progressTracker,
01435 logger ? logger : server->getLogger(),
01436 server->getNextTimeStamp(), progressive);
01437 XML_SetUserData(p.ptr, &parser);
01438
01439 const unsigned bufferSize = 1024;
01440 char buffer[bufferSize];
01441
01442 int progress = 0;
01443 for(;;)
01444 {
01445 const int n = reader->read(buffer, bufferSize);
01446 if(!XML_Parse(p.ptr, buffer, n, n==0))
01447 ARCHON_THROW1(ParseException, XML_ErrorString(XML_GetErrorCode(p.ptr)));
01448 if(n==0) break;
01449 progress += n;
01450 if(progressTracker) progressTracker->progress(progress);
01451 }
01452 }
01453 }
01454 }
01455 }