bool ClassHandler::init(Core::BaseObject *obj, void *n, TagSet &mandatory) { xmlNodePtr node = reinterpret_cast<xmlNodePtr>(n); // Fill in mandatory tags for ( MemberList::iterator it = attributes.begin(); it != attributes.end(); ++it ) { if ( !it->optional ) mandatory.insert(it->tag); } for ( MemberList::iterator it = elements.begin(); it != elements.end(); ++it ) { if ( !it->optional && !it->tag.empty() ) mandatory.insert(it->tag); } for ( MemberList::iterator it = childs.begin(); it != childs.end(); ++it ) { if ( !it->optional && !it->tag.empty() ) mandatory.insert(it->tag); } if ( cdataUsed ) cdata.get(obj, n, this); if ( attributes.empty() ) return true; for ( xmlAttrPtr attr = node->properties; attr != NULL; attr = attr->next ) { if ( attr->children ) { for ( MemberList::iterator it = attributes.begin(); it != attributes.end(); ++it ) { if ( equalsTag(attr, it->tag.c_str(), it->nameSpace.c_str()) ) { if ( it->get(obj, attr, this) && !it->optional ) { mandatory.erase(it->tag); break; } } } } } return true; }
bool Importer::traverse(NodeHandler *handler, void *n, void *c, Core::BaseObject *target) { xmlNodePtr node = reinterpret_cast<xmlNodePtr>(n); xmlNodePtr childs = reinterpret_cast<xmlNodePtr>(c); ChildList remaining; TagSet mandatory; handler->init(target, n, mandatory); bool result = true; for ( xmlNodePtr child = childs; child != NULL; child = child->next ) { if ( child->type != XML_ELEMENT_NODE ) continue; handler->propagate(NULL, false, true); try { handler->get(target, child); } catch ( std::exception &e ) { if ( handler->isOptional ) SEISCOMP_WARNING("(optional) %s.%s: %s", node->name, child->name, e.what()); else throw e; } if ( !handler->isOptional ) mandatory.erase((const char*)child->name); if ( handler->object == NULL && handler->isAnyType ) { if ( _any.get(target, child) ) { handler->object = _any.object; handler->childHandler = _any.childHandler; handler->newInstance = _any.newInstance; } } Core::BaseObject *newTarget = handler->object; MemberNodeHandler *memberHandler = handler->memberHandler; NodeHandler *childHandler = handler->childHandler; bool newInstance = handler->newInstance; bool optional = handler->isOptional; if ( newTarget ) { if ( childHandler == NULL ) { childHandler = _typemap->getHandler(newTarget->className()); if ( childHandler == NULL ) { SEISCOMP_WARNING("No class handler for %s", newTarget->className()); if ( newInstance ) delete newTarget; handler->object = NULL; newTarget = NULL; childHandler = &_none; } } } else childHandler = &_none; try { if ( traverse(childHandler, child, child->children, handler->object) ) { if ( newTarget && newInstance && !memberHandler ) remaining.push_back(newTarget); } else { if ( newTarget && newInstance ) delete newTarget; newTarget = NULL; if ( optional ) SEISCOMP_INFO("Invalid %s element: ignoring", child->name); else { SEISCOMP_WARNING("%s is not optional within %s", child->name, node->name); result = false; } } } catch ( std::exception &e ) { SEISCOMP_WARNING("%s: %s", child->name, e.what()); if ( newTarget ) { if ( newInstance ) delete newTarget; if ( !optional ) { SEISCOMP_WARNING("%s is not optional within %s", child->name, node->name); result = false; } else SEISCOMP_WARNING("%s: ignoring optional member %s: invalid", node->name, child->name); newTarget = NULL; } } if ( memberHandler ) { if ( !memberHandler->finalize(target, newTarget) ) { if ( newTarget && newInstance ) remaining.push_back(newTarget); } } } handler->finalize(target, &remaining); if ( target != NULL ) { for ( ChildList::iterator it = remaining.begin(); it != remaining.end(); ++it ) if ( *it != NULL ) delete *it; } else { for ( ChildList::iterator it = remaining.begin(); it != remaining.end(); ++it ) { if ( *it != NULL ) { if ( _result == NULL ) _result = *it; else delete *it; } } } if ( !mandatory.empty() ) { std::string attribs; for ( TagSet::iterator it = mandatory.begin(); it != mandatory.end(); ++it ) { if ( it != mandatory.begin() ) attribs += ", "; attribs += *it; } SEISCOMP_WARNING("%s: missing mandatory attribute%s: %s", node->name, mandatory.size() == 1?"":"s", attribs.c_str()); return false; } return result; }