/*
Copyright (C) 2000-2004
Code contributed by Greg Collecutt, Joseph Hope and Paul Cochrane
This file is part of xmds.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
$Id: xmdsutils.cc,v 1.14 2004/07/13 05:29:38 paultcochrane Exp $
*/
/*! @file xmdsutils.cc
@brief Utility classes and methods
More detailed explanation...
*/
#include<xmlbasics.h>
#include<dom3.h>
#include<xmdsutils.h>
#include<string>
extern bool debugFlag;
//#define DEBUG 0
// ******************************************************************************
// ******************************************************************************
// xmdsException
// ******************************************************************************
// ******************************************************************************
// ******************************************************************************
xmdsException::xmdsException() :
myNode(0),
myErrorMessage("") {
};
// ******************************************************************************
xmdsException::xmdsException(
const char *const yourErrorMessage) :
myNode(0),
myErrorMessage(yourErrorMessage) {
};
// ******************************************************************************
xmdsException::xmdsException(
const Node *const yourNode,
const char *const yourErrorMessage) :
myNode(yourNode),
myErrorMessage(yourErrorMessage) {
};
// ******************************************************************************
const char* xmdsException::getError() {
char s2[256];
s[0]=0;
const Node* nextNode=myNode;
if(nextNode != 0) {
sprintf(s2,"In element '%s',\n",nextNode->nodeName()->c_str());
strcat(s,s2);
nextNode=nextNode->parentNode();
}
while(nextNode != 0) {
sprintf(s2," which is within element '%s',\n",nextNode->nodeName()->c_str());
strcat(s,s2);
nextNode=nextNode->parentNode();
}
sprintf(s2,"\nthe following error occurred:\n %s\n",myErrorMessage);
strcat(s,s2);
return s;
};
// ******************************************************************************
// ******************************************************************************
// xmdsUtility public
// ******************************************************************************
// ******************************************************************************
long nxmdsUtilitys=0; //!< Number of xmds utility objects
// ******************************************************************************
xmdsUtility::xmdsUtility() {
if(debugFlag) {
nxmdsUtilitys++;
printf("xmdsUtility::xmdsUtility\n");
printf("nxmdsUtilitys=%li\n",nxmdsUtilitys);
}
};
// ******************************************************************************
xmdsUtility::~xmdsUtility() {
if(debugFlag) {
nxmdsUtilitys--;
printf("xmdsUtility::~xmdsUtility\n");
printf("nxmdsUtilitys=%li\n",nxmdsUtilitys);
}
};
// ******************************************************************************
// ******************************************************************************
// xmdsUtility protected
// ******************************************************************************
// ******************************************************************************
// ******************************************************************************
char* xmdsUtility::errorMessage() const {
return myErrorMessage;
};
// ******************************************************************************
void xmdsUtility::getAssignmentStrings(
const Element *const inElement,
const XMLString& ofName,
const bool& required,
const unsigned long& n2get,
list<XMLString>& outList) {
if(debugFlag) {
printf("xmdsUtility::getAssignmentStrings\n");
}
outList.clear();
// note that if an element is found, then the routine will throw an exception
// if n2get items aren't found within, except that passing n2get=0 will escape
// this behaviour
const NodeList* candidateElements = inElement->getElementsByTagName(ofName,0);
if(candidateElements->length()==0) {
if(required) {
sprintf(myErrorMessage,"Element '%s' not found",ofName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
else {
return;
}
}
if(candidateElements->length()==1) {
const Node* nextNode = candidateElements->item(0);
parseXMLString(nextNode,candidateElements->item(0)->textContent(0),outList);
if(n2get!=0) {
// check that numbers of requested items match
if(outList.size()!=n2get) {
sprintf(myErrorMessage, "%li strings wanted but %li found",n2get,(long)outList.size());
throw xmdsException(nextNode,myErrorMessage);
}
}
}
else {
sprintf(myErrorMessage,"Multiple Elements '%s' found",ofName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
};
// ******************************************************************************
void xmdsUtility::getAssignmentBools(
const Element *const inElement,
const XMLString& ofName,
const bool& required,
const unsigned long& n2get,
list<bool>& outList) {
if(debugFlag) {
printf("xmdsUtility::getAssignmentBools\n");
}
// note that if an element is found, then the routine will throw an exception
// if n2get items aren't found withn, except that passing n2get=0 will escape
// this behaviour
outList.clear();
const NodeList* candidateElements = inElement->getElementsByTagName(ofName,0);
if(candidateElements->length()==0) {
if(required) {
sprintf(myErrorMessage,"Element '%s' not found",ofName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
else {
return;
}
}
if(candidateElements->length()==1) {
list<XMLString> myOutList;
const Node* nextNode = candidateElements->item(0);
parseXMLString(nextNode,candidateElements->item(0)->textContent(0),myOutList);
for(list<XMLString>::const_iterator pXMLString = myOutList.begin(); pXMLString != myOutList.end(); pXMLString++) {
if(*pXMLString=="yes") {
outList.push_back(1);
}
else if(*pXMLString=="no") {
outList.push_back(0);
}
else {
throw xmdsException(nextNode,"'yes' or 'no' expected");
}
}
if(n2get!=0) {
// check that numbers of requested items match
if(outList.size()!=n2get) {
sprintf(myErrorMessage,"%li 'yes'/'no' wanted but %li found",n2get,(long)outList.size());
throw xmdsException(nextNode,myErrorMessage);
}
}
}
else {
sprintf(myErrorMessage,"Multiple Elements '%s' found",ofName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
};
// ******************************************************************************
void xmdsUtility::getAssignmentULongs(
const Element *const inElement,
const XMLString& ofName,
const bool& required,
const unsigned long& n2get,
list<unsigned long>& outList) {
if(debugFlag) {
printf("xmdsUtility::getAssignmentLongs\n");
}
// note that if an element is found, then the routine will throw an exception
// if n2get items aren't found withn, except that passing n2get=0 will escape
// this behaviour
outList.clear();
const NodeList* candidateElements = inElement->getElementsByTagName(ofName,0);
if(candidateElements->length()==0) {
if(required) {
sprintf(myErrorMessage,"Element '%s' not found",ofName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
else {
return;
}
}
if(candidateElements->length()==1) {
list<XMLString> myOutList;
const Node* nextNode = candidateElements->item(0);
parseXMLString(nextNode,candidateElements->item(0)->textContent(0),myOutList);
for(list<XMLString>::const_iterator pXMLString = myOutList.begin(); pXMLString != myOutList.end(); pXMLString++) {
unsigned long nextULong;
if(pXMLString->asULong(nextULong)) {
outList.push_back(nextULong);
}
else {
throw xmdsException(nextNode,"invalid positive integer");
}
}
if(n2get!=0) {
// check that numbers of requested items match
if(outList.size()!=n2get) {
sprintf(myErrorMessage,"%li integers wanted but %li found",n2get,(long)outList.size());
throw xmdsException(nextNode,myErrorMessage);
}
}
}
else {
sprintf(myErrorMessage,"Multiple Elements '%s' found",ofName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
};
// ******************************************************************************
void xmdsUtility::getAssignmentDoubles(
const Element *const inElement,
const XMLString& ofName,
const bool& required,
const unsigned long& n2get,
list<double>& outList) {
if(debugFlag) {
printf("xmdsUtility::getAssignmentDoubles\n");
}
// note that if an element is found, then the routine will throw an exception
// if n2get items aren't found withn, except that passing n2get=0 will escape
// this behaviour
outList.clear();
const NodeList* candidateElements = inElement->getElementsByTagName(ofName,0);
if(candidateElements->length()==0) {
if(required) {
sprintf(myErrorMessage,"Element '%s' not found",ofName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
else {
return;
}
}
if(candidateElements->length()==1) {
list<XMLString> myOutList;
const Node* nextNode = candidateElements->item(0);
parseXMLString(nextNode,candidateElements->item(0)->textContent(0),myOutList);
for(list<XMLString>::const_iterator pXMLString = myOutList.begin(); pXMLString != myOutList.end(); pXMLString++) {
double nextdouble;
if(pXMLString->asDouble(nextdouble)) {
outList.push_back(nextdouble);
}
else {
throw xmdsException(nextNode,"invalid floating point format");
}
}
if(n2get!=0) {
// check that numbers of requested items match
if(outList.size()!=n2get) {
sprintf(myErrorMessage,"%li reals wanted but %li found",n2get,(long)outList.size());
throw xmdsException(nextNode,myErrorMessage);
}
}
}
else {
sprintf(myErrorMessage,"Multiple Elements '%s' found",ofName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
};
// ******************************************************************************
void xmdsUtility::getAssignmentDomains(
const Element *const inElement,
const XMLString& ofName,
const bool& required,
const unsigned long& n2get,
list<domainStruct>& outList) {
if(debugFlag) {
printf("xmdsUtility::getAssignmentDomains\n");
}
// note that if an element is found, then the routine will throw an exception
// if n2get items aren't found withn, except that passing n2get=0 will escape
// this behaviour
outList.clear();
const NodeList* candidateElements = inElement->getElementsByTagName(ofName,0);
if(candidateElements->length()==0) {
if(required) {
sprintf(myErrorMessage,"Element '%s' not found",ofName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
else {
return;
}
}
if(candidateElements->length()==1) {
list<XMLString> myPairsList;
const Node* nextNode = candidateElements->item(0);
parseXMLString(nextNode,candidateElements->item(0)->textContent(0),myPairsList);
if(n2get!=0) {
// check that numbers of requested items match
if(myPairsList.size() != n2get) {
sprintf(myErrorMessage,"%li domain pairs wanted but %li found",n2get,(long)myPairsList.size());
throw xmdsException(nextNode,myErrorMessage);
}
}
for(list<XMLString>::const_iterator pXMLString = myPairsList.begin(); pXMLString != myPairsList.end(); pXMLString++) {
list<XMLString> myDoublesList;
parseXMLString(nextNode,&*pXMLString,myDoublesList);
if(myDoublesList.size() != 2) {
throw xmdsException(nextNode,"bracketed pairs of reals expected");
}
domainStruct nextDomain;
list<XMLString>::const_iterator pXMLString2;
pXMLString2 = myDoublesList.begin();
if(!pXMLString2->asDouble(nextDomain.begin)) {
throw xmdsException(nextNode,"invalid floating point format");
}
pXMLString2++;
if(!pXMLString2->asDouble(nextDomain.end)) {
throw xmdsException(nextNode,"invalid floating point format");
}
if(nextDomain.end<=nextDomain.begin) {
throw xmdsException(nextNode,"domain ends must be > begins");
}
outList.push_back(nextDomain);
}
}
else {
sprintf(myErrorMessage,"Multiple Elements '%s' found",ofName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
};
// ******************************************************************************
void xmdsUtility::getAttributeStrings(
const Element *const inElement,
const XMLString& ofElementName,
const XMLString& ofAttrName,
const bool& required,
XMLString& outString) {
if(debugFlag) {
printf("xmdsUtility::getAttributeStrings\n");
}
outString = EMPTY_STRING;
const NodeList* candidateElements = inElement->getElementsByTagName(ofElementName,0);
// this code is a bit weird as it was grabbed from getAssignmentStrings, and so
// don't really need this next test
// @todo Need to clean up this function so that required boolean means the right thing
// Namely that the attribute is required, atm we're checking if the element (tag)
// is required
// Really not happy with how the attribute parsing code is going
// this looks like it needs a bit of work to knock it into some proper shape,
// what we've got here is too much of a hack on top of getAssignmentStrings and
// a decent amount of thought needs to go into the implementation
if(candidateElements->length()==0) {
if(required) {
sprintf(myErrorMessage,"Element '%s' not found",ofElementName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
else {
return;
}
}
if(candidateElements->length()==1) {
const Node* nextNode = candidateElements->item(0);
const NamedNodeMap* attrNodeMap = nextNode->attributes();
if (attrNodeMap->length() > 0) {
const Node* attrNode = attrNodeMap->getNamedItem(ofAttrName);
if (attrNode != 0) {
outString = attrNode->nodeValue()->c_str();
}
// if the attribute isn't found, and it's required, barf
else if ((attrNode == 0) && required) {
sprintf(myErrorMessage,"Attribute '%s' not found",ofAttrName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
else {
outString = EMPTY_STRING;
}
}
}
else {
sprintf(myErrorMessage,"Multiple Elements '%s' found",ofElementName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
};
// ******************************************************************************
void xmdsUtility::getAttributeBools(
const Element *const inElement,
const XMLString& ofElementName,
const XMLString& ofAttrName,
const bool& required,
bool& outBool) {
if(debugFlag) {
printf("xmdsUtility::getAttributeBools\n");
}
outBool = false;
const NodeList* candidateElements = inElement->getElementsByTagName(ofElementName,0);
if (debugFlag) {
printf("xmdsUtility::getAttributeBools : candidateElements->length = %ld\n",candidateElements->length());
}
if(candidateElements->length()==0) {
if(required) {
sprintf(myErrorMessage,"Element '%s' not found",ofElementName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
else {
return;
}
}
if(candidateElements->length()==1) { // we only want one such tag
const Node* nextNode = candidateElements->item(0); // grab the tag's node
const NamedNodeMap* attrNodeMap = nextNode->attributes(); // grab the attributes of the tag as a map
if (debugFlag) {
printf("xmdsUtility::getAttributeBools : attrNodeMap->length = %ld\n",attrNodeMap->length());
}
if (attrNodeMap->length() > 0) {
const Node* attrNode = attrNodeMap->getNamedItem(ofAttrName); // get the node with the name ofAttrName
if (attrNode != 0) {
// then compare the value with 'yes' and 'no'
const string boolString = static_cast <string>(attrNode->nodeValue()->c_str());
if (debugFlag) {
printf("xmdsUtility::getAttributeBools : boolString = %s\n", boolString.c_str());
}
if (boolString == "yes") {
outBool = true;
}
else if (boolString == "no") {
outBool = false;
}
else {
throw xmdsException(nextNode, "'yes' or 'no' expected");
}
}
}
}
else {
sprintf(myErrorMessage,"Multiple Elements '%s' found",ofElementName.c_str());
throw xmdsException(inElement,myErrorMessage);
}
if (debugFlag) {
printf("xmdsUtility::getAttributeBools : outBool = %d\n",outBool);
}
};
// ******************************************************************************
unsigned long xmdsUtility::spaceList2ULong(
const list<bool>& spaceList) const {
if(debugFlag) {
printf("xmdsUtility::spaceList2ULong\n");
}
unsigned long space=0;
unsigned long two2n=1;
for(list<bool>::const_iterator pBool = spaceList.begin(); pBool != spaceList.end(); pBool++) {
if(*pBool) {
space += two2n;
}
two2n *= 2;
}
return space;
};
// ******************************************************************************
// ******************************************************************************
// xmdsUtility private
// ******************************************************************************
// ******************************************************************************
// ******************************************************************************
void xmdsUtility::parseXMLString(
const Node *const inNode,
const XMLString *const inString,
list<XMLString>& outXMLStringList) {
if(debugFlag) {
printf("xmdsUtility::parseXMLString\n");
}
outXMLStringList.clear();
if(inString->length()==0) {
return;
}
XMLString copyInString = *inString;
// begin by replacing all commas and semicolons with spaces
unsigned long i=0;
while(i<copyInString.length()) {
if((copyInString.data(i)==',')|(copyInString.data(i)==';')) {
copyInString.replaceData(i,1," ");
}
i++;
}
// now mark all begins and ends
list<unsigned long> begins;
list<unsigned long> ends;
long bracketLevel=0;
i=0;
char lastChar=0x20;
while(i<copyInString.length()) {
if(copyInString.data(i)=='(') {
if(bracketLevel==0) {
begins.push_back(i+1);
}
bracketLevel++;
}
else if(copyInString.data(i)==')') {
bracketLevel--;
if(bracketLevel==0) {
ends.push_back(i);
}
}
else if(bracketLevel==0) {
if(!XMLChar::isWhiteSpace(copyInString.data(i))&(XMLChar::isWhiteSpace(lastChar)|(lastChar==')'))) {
begins.push_back(i);
}
else if(XMLChar::isWhiteSpace(copyInString.data(i))&!(XMLChar::isWhiteSpace(lastChar)|(lastChar==')'))) {
ends.push_back(i);
}
}
lastChar=copyInString.data(i);
i++;
}
if(bracketLevel !=0 ) {
throw xmdsException(inNode,"Imbalanced bracketing");
}
if(!(XMLChar::isWhiteSpace(lastChar)|(lastChar==')'))) {
ends.push_back(i);
}
list<unsigned long>::const_iterator pbegin = begins.begin();
list<unsigned long>::const_iterator pend = ends.begin();
while(pbegin != begins.end()) {
XMLString subString;
copyInString.subString(subString,*pbegin,*pend);
outXMLStringList.push_back(subString);
pbegin++;
pend++;
}
};
syntax highlighted by Code2HTML, v. 0.9.1