/*
* Copyright (c) 2008-2010 University of Utah and the Flux Group.
*
* {{{EMULAB-LICENSE
*
* This file is part of the Emulab network testbed software.
*
* This file is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this file. If not, see .
*
* }}}
*/
#ifdef WITH_XML
#include "xmlhelpers.h"
#include "xstr.h"
#include
#include
const XMLCh* getChildValue(const DOMElement *tag, const char *name) {
DOMNodeList *list = tag->getElementsByTagName(XStr(name).x());
if (list->getLength() != 1) {
throw "Incorrect number of child elements in getChildValue()";
} else {
return dynamic_cast(list->item(0))->getFirstChild()->getNodeValue();
}
}
/* This will only work if there is only one element with that tag within the root
* It is the callers responsibility to ensure that this is the case before calling this function
*/
void setChildValue(const DOMElement* parent, const char* tag, const char* value)
{
DOMElement* ele = getElementByTagName (parent, tag);
if (ele == NULL)
throw "Error finding tag in parent in setChildValue ()";
else
ele->getFirstChild()->setNodeValue (XStr(value).x());
}
DOMElement* getNodeByName (const DOMElement *root, const char* name)
{
DOMNodeList *list = root -> getElementsByTagName(XStr("node").x());
for (unsigned int i = 0; i < list -> getLength() ; ++i)
{
DOMElement *ele = dynamic_cast(list->item(i));
if (strcmp(XStr(ele->getAttribute(XStr("name").x())).c(),name) == 0)
return ele;
}
return NULL;
}
DOMElement* getElementByAttributeValue (const DOMElement* root, const char* tag, const char* attribute_name, const char* attribute_value)
{
DOMNodeList *list = root -> getElementsByTagName(XStr(tag).x());
for (unsigned int i = 0; i < list -> getLength() ; ++i)
{
DOMElement *ele = dynamic_cast(list->item(i));
if (strcmp(XStr(ele->getAttribute(XStr(attribute_name).x())).c(),attribute_value) == 0)
return ele;
}
return NULL;
}
DOMElement* getElementByAttributeValue (vector roots, const char* tag, const char* attribute_name, const char* attribute_value)
{
for (vector::iterator it = roots.begin(); it != roots.end(); ++it)
{
DOMNodeList *list = (*it)->getElementsByTagName(XStr(tag).x());
for (unsigned int i = 0; i < list -> getLength() ; ++i)
{
DOMElement *ele = dynamic_cast(list->item(i));
if (strcmp(XStr(ele->getAttribute(XStr(attribute_name).x())).c(),attribute_value) == 0)
return ele;
}
}
return NULL;
}
vector getElementsByAttributeValue (const DOMElement* root, const char* tag, const char* attribute_name, const char* attribute_value)
{
DOMNodeList *list = root -> getElementsByTagName(XStr(tag).x());
vector elements;
for (unsigned int i = 0; i < list -> getLength() ; ++i)
{
DOMElement *ele = dynamic_cast(list->item(i));
if (strcmp(XStr(ele->getAttribute(XStr(attribute_name).x())).c(),attribute_value) == 0)
elements.push_back(ele);
}
return elements;
}
vector getElementsHavingAttribute(const DOMElement* root, const char* tag, const char* attribute_name)
{
DOMNodeList* list = root->getElementsByTagName(XStr(tag).x());
vector elements;
for (unsigned int i = 0; i < list->getLength(); ++i)
{
DOMElement* ele = dynamic_cast(list->item(i));
if (ele->hasAttribute(XStr(attribute_name).x()))
elements.push_back(ele);
}
return elements;
}
/* This will only work if there is only one element with that tag within the root
* It is the callers responsibility to ensure that this is the case before calling this function
*/
DOMElement* getElementByTagName (const DOMElement* root, const char* tag)
{
DOMNodeList *list = root -> getElementsByTagName(XStr(tag).x());
if (list->getLength() != 1) {
throw "More than one child with this tag in getElementByTagName()";
} else {
return dynamic_cast(list->item(0));
}
}
/* Returns the nth interface in a link (can be used for a node as well only if n is 0 */
DOMElement* getNthInterface (const DOMElement* root, int n)
{
DOMNodeList* interfaces = root->getElementsByTagName(XStr("interface").x());
if (interfaces->getLength() <= n) {
throw "Too few interfaces found";
}
return (dynamic_cast(interfaces->item(n)));
}
/*
* TODO: Better error handling
*/
bool hasChildTag(const DOMElement *tag, const char *name) {
return (tag->getElementsByTagName(XStr(name).x())->getLength() > 0);
}
int parse_fds_xml(const DOMElement *tag, node_fd_set *fd_set) {
DOMNodeList *fds = tag->getElementsByTagName(XStr("fd").x());
for (int i = 0; i < fds->getLength(); i++)
{
DOMElement *elt = dynamic_cast(fds->item(i));
XStr fd_name (elt->getAttribute(XStr("fd_name").x()));
XStr fd_weight (elt->getAttribute(XStr("fd_weight").x()));
bool violatable = elt->hasAttribute(XStr("violatable").x());
featuredesire::fd_type fd_type;
if (elt->hasAttribute(XStr("local_operator").x()))
{
/*
* Right now, there is only one type of local feature
*/
fd_type = featuredesire::FD_TYPE_LOCAL_ADDITIVE;
}
else if (elt->hasAttribute(XStr("global_operator").x()))
{
XStr fd_operator(elt->getAttribute(XStr("global_operator").x()));
if (fd_operator == "OnceOnly") {
fd_type = featuredesire::FD_TYPE_GLOBAL_ONE_IS_OKAY;
} else {
fd_type = featuredesire::FD_TYPE_GLOBAL_MORE_THAN_ONE;
}
}
else {
fd_type = featuredesire::FD_TYPE_NORMAL;
}
fd_set->push_front(tb_node_featuredesire(fd_name.c(), fd_weight.d(),
violatable, fd_type));
}
return fds->getLength();
}
/*
* TODO: Better error handling
*/
node_interface_pair parse_interface_xml(const DOMElement *tag) {
const XMLCh* node_name = tag->getAttribute(XStr("node_name").x());
const XMLCh* interface_name = tag->getAttribute(XStr("interface_name").x());
node_interface_pair rv(node_name,interface_name);
return rv;
}
/* Parse the features and desires on a virtual node */
int parse_fds_vnode_xml (const DOMElement *tag, node_fd_set *fd_set)
{
DOMNodeList *fds = tag->getElementsByTagName(XStr("fd").x());
for (int i = 0; i < fds->getLength(); i++)
{
DOMElement *elt = dynamic_cast(fds->item(i));
XStr fd_name (elt->getAttribute(XStr("fd_name").x()));
XStr fd_weight (elt->getAttribute(XStr("fd_weight").x()));
bool violatable = elt->hasAttribute(XStr("violatable").x());
featuredesire::fd_type fd_type;
if (elt->hasAttribute(XStr("local_operator").x())) {
/*
* Right now, there is only one type of local feature
*/
fd_type = featuredesire::FD_TYPE_LOCAL_ADDITIVE;
} else if (elt->hasAttribute(XStr("global_operator").x())) {
XStr fd_operator(elt->getAttribute(XStr("global_operator").x()));
if (fd_operator == "OnceOnly") {
fd_type = featuredesire::FD_TYPE_GLOBAL_ONE_IS_OKAY;
} else {
fd_type = featuredesire::FD_TYPE_GLOBAL_MORE_THAN_ONE;
}
} else {
fd_type = featuredesire::FD_TYPE_NORMAL;
}
tb_node_featuredesire node_fd (fd_name.c(), fd_weight.d(), violatable, fd_type);
node_fd.add_desire_user(fd_weight.d());
fd_set->push_front(node_fd);
}
return fds->getLength();
}
interface_spec parse_interface_rspec_xml(const DOMElement *tag)
{
interface_spec rv =
{
string(XStr(tag->getAttribute(XStr("virtual_node_id").x())).c()),
string(XStr(tag->getAttribute(XStr("virtual_interface_id").x())).c()),
string(XStr(find_urn(tag, "component_node"))),
string(XStr(tag->getAttribute(XStr("component_interface_id").x())).c())
};
return rv;
}
component_spec parse_component_spec (const DOMElement *elt) {
component_spec rv = {string(""), string(""), string(""), string("")};
rv.component_manager_uuid = string(XStr(find_urn(elt, "component_manager")));
if (elt->hasAttribute(XStr("component_name").x()))
rv.component_name = string (XStr(elt->getAttribute(XStr("component_name").x())).c());
rv.component_uuid = string(XStr(find_urn(elt, "component")));
if (elt->hasAttribute(XStr("sliver_uuid").x()))
rv.sliver_uuid = string (XStr(elt->getAttribute(XStr("sliver_uuid").x())).c());
return rv;
}
XMLCh const * find_urn(const xercesc::DOMElement* element,
string const & prefix)
{
string uuid = prefix + "_uuid";
string urn = prefix + "_urn";
if (element->hasAttribute(XStr(uuid.c_str()).x()))
{
return element->getAttribute(XStr(uuid.c_str()).x());
}
else //if (element->hasAttribute(XStr(urn.c_str()).x()))
{
return element->getAttribute(XStr(urn.c_str()).x());
}
}
// Check if the component spec is present. We check if the aggregate UUID and the component UUID are both present
bool hasComponentSpec (DOMElement* elt)
{
return ((elt->hasAttribute(XStr("component_manager_uuid").x())
|| elt->hasAttribute(XStr("component_manager_urn").x()))
&& (elt->hasAttribute(XStr("component_uuid").x())
|| elt->hasAttribute(XStr("component_urn").x())));
}
#endif