You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/3rd/VTK7.1/source/VTK-7.1.1/Utilities/MetaIO/vtkmetaio/metaCommand.cxx

2457 lines
68 KiB
C++

/*============================================================================
MetaIO
Copyright 2000-2010 Insight Software Consortium
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifdef _MSC_VER
#pragma warning(disable:4702)
#endif
#include "metaUtils.h"
#include "metaCommand.h"
#include <stdio.h>
#include <string.h>
#include <string>
#if (METAIO_USE_NAMESPACE)
namespace METAIO_NAMESPACE {
#endif
#ifdef METAIO_USE_LIBXML2
#include <libxml/xmlwriter.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <libxml/tree.h>
#endif
MetaCommand::
MetaCommand()
{
m_HelpCallBack = NULL;
m_OptionVector.clear();
m_Version = "Not defined";
m_Date = "Not defined";
m_Name = "";
m_Author = "Not defined";
m_Description = "";
m_Acknowledgments = "";
m_Category = "";
m_ParsedOptionVector.clear();
m_Verbose = true;
m_FailOnUnrecognizedOption = false;
m_GotXMLFlag = false;
m_DisableDeprecatedWarnings = false;
}
/** Extract the date from a CVS Date keyword/value pair. */
METAIO_STL::string MetaCommand::
ExtractDateFromCVS(METAIO_STL::string date)
{
METAIO_STL::string newdate;
for(int i=7;i<(int)date.size()-1;i++)
{
newdate += date[i];
}
return newdate.c_str();
}
void MetaCommand::DisableDeprecatedWarnings()
{
m_DisableDeprecatedWarnings = true;
}
void MetaCommand::
SetDateFromCVS(METAIO_STL::string cvsDate)
{
this->SetDate( this->ExtractDateFromCVS( cvsDate ).c_str() );
}
/** Extract the version from a CVS Revision keyword/value pair. */
METAIO_STL::string MetaCommand::
ExtractVersionFromCVS(METAIO_STL::string version)
{
METAIO_STL::string newversion;
for(int i=11;i<(int)version.size()-1;i++)
{
newversion += version[i];
}
return newversion.c_str();
}
void MetaCommand::
SetVersionFromCVS(METAIO_STL::string cvsVersion)
{
this->SetVersion( this->ExtractVersionFromCVS( cvsVersion ).c_str() );
}
/** */
bool MetaCommand::
SetOption(Option option)
{
// need to add some tests here to check if the option is not defined yet
m_OptionVector.push_back(option);
return true;
}
bool MetaCommand::
SetOption(METAIO_STL::string name,
METAIO_STL::string shortTag,
bool required,
METAIO_STL::string description,
METAIO_STL::vector<Field> fields)
{
// need to add some tests here to check if the option is not defined yet
// Short tag can be empty as long as the long tag is defined.
// This is checked in the Parse() command
/*if(tag == "")
{
METAIO_STREAM::cout << "Tag cannot be empty : use AddField() instead."
<< METAIO_STREAM::endl;
return false;
}*/
if(!m_DisableDeprecatedWarnings && shortTag.size()>1)
{
METAIO_STREAM::cout << "Warning: as of August 23, 2007 MetaCommand::SetOption()"
<< " is expecting a shortTag of exactly one character."
<< " You should use the SetOptionLongTag(optionName,longTagName)"
<< " if you want to use a longer tag. The longtag will be"
<< " refered as --LongTag and the short tag as -ShortTag."
<< " Replace -" << shortTag.c_str()
<< " by --" << shortTag.c_str()
<< METAIO_STREAM::endl;
}
Option option;
option.name = name;
option.tag = shortTag;
option.longtag = "";
option.fields = fields;
option.required = required;
option.description = description;
option.userDefined = false;
option.complete = false;
m_OptionVector.push_back(option);
return true;
}
bool MetaCommand::
SetOption(METAIO_STL::string name,
METAIO_STL::string shortTag,
bool required,
METAIO_STL::string description,
TypeEnumType type,
METAIO_STL::string defVal,
DataEnumType externalData)
{
// need to add some tests here to check if the option is not defined yet
// Short tag can be empty as long as the long tag is defined.
// This is checked in the Parse() command
/*
if(tag == "")
{
METAIO_STREAM::cout << "Tag cannot be empty : use AddField() instead."
<< METAIO_STREAM::endl;
return false;
}*/
if(!m_DisableDeprecatedWarnings && shortTag.size()>1)
{
METAIO_STREAM::cout << "Warning: as of August 23, 2007 MetaCommand::SetOption() "
<< " is expecting a shortTag of exactly one character."
<< " You should use the SetOptionLongTag(optionName,longTagName)"
<< " if you want to use a longer tag. The longtag will be "
<< " refered as --LongTag and the short tag as -ShortTag "
<< " Replace -" << shortTag.c_str()
<< " by --" << shortTag.c_str()
<< METAIO_STREAM::endl;
}
Option option;
option.tag = shortTag;
option.longtag = "";
option.name = name;
option.required = required;
option.description = description;
option.userDefined = false;
option.complete = false;
// Create a field without description as a flag
Field field;
if(type == LIST)
{
field.name = "NumberOfValues";
}
else
{
field.name = name;
}
field.externaldata = externalData;
field.type = type;
field.value = defVal;
field.userDefined = false;
field.required = true;
field.rangeMin = "";
field.rangeMax = "";
option.fields.push_back(field);
m_OptionVector.push_back(option);
return true;
}
/** Add a field */
bool MetaCommand::
AddField(METAIO_STL::string name,
METAIO_STL::string description,
TypeEnumType type,
DataEnumType externalData,
METAIO_STL::string rangeMin,
METAIO_STL::string rangeMax)
{
// need to add some tests here to check if the option is not defined yet
Option option;
option.tag = "";
option.longtag = "";
// Create a field without description with the specified type
Field field;
field.name = name;
field.type = type;
field.required = true;
field.userDefined = false;
field.externaldata = externalData;
field.rangeMin = rangeMin;
field.rangeMax = rangeMax;
option.fields.push_back(field);
option.required = true;
option.name = name;
option.description = description;
option.userDefined = false;
option.complete = false;
m_OptionVector.push_back(option);
return true;
}
/** For backward compatibility */
bool MetaCommand::
AddField(METAIO_STL::string name,
METAIO_STL::string description,
TypeEnumType type,
bool externalData)
{
if(externalData)
{
return this->AddField(name,description,type,DATA_IN);
}
else
{
return this->AddField(name,description,type,DATA_NONE);
}
}
/** Collect all the information until the next tag
* \warning this function works only if the field is of type String */
void MetaCommand::
SetOptionComplete(METAIO_STL::string optionName,
bool complete)
{
OptionVector::iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
if((*it).name == optionName)
{
(*it).complete = complete;
return;
}
it++;
}
}
/** Add a field to a given an option */
bool MetaCommand::
AddOptionField(METAIO_STL::string optionName,
METAIO_STL::string name,
TypeEnumType type,
bool required,
METAIO_STL::string defVal,
METAIO_STL::string description,
DataEnumType externalData)
{
OptionVector::iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
if((*it).name == optionName)
{
// Create a field without description with the specified type
Field field;
field.name = name;
field.type = type;
field.required = required;
field.value = defVal;
field.description = description;
field.userDefined = false;
field.externaldata = externalData;
field.rangeMin = "";
field.rangeMax = "";
// If this is the first field in the list we replace the current field
if((*it).fields[0].type == FLAG)
{
(*it).fields[0] = field;
}
else
{
(*it).fields.push_back(field);
}
return true;
}
it++;
}
return false;
}
/** Set the range of an option */
bool MetaCommand::
SetOptionRange(METAIO_STL::string optionName,
METAIO_STL::string name,
METAIO_STL::string rangeMin,
METAIO_STL::string rangeMax)
{
OptionVector::iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
if((*it).name == optionName)
{
METAIO_STL::vector<Field> & fields = (*it).fields;
METAIO_STL::vector<Field>::iterator itField = fields.begin();
while(itField != fields.end())
{
if((*itField).name == name)
{
(*itField).rangeMin = rangeMin;
(*itField).rangeMax = rangeMax;
return true;
}
itField++;
}
}
it++;
}
return false;
}
/** Set the range of an option */
bool MetaCommand::
SetOptionEnumerations(METAIO_STL::string optionName,
METAIO_STL::string name,
METAIO_STL::string optionEnums)
{
OptionVector::iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
if((*it).name == optionName)
{
METAIO_STL::vector<Field> & fields = (*it).fields;
METAIO_STL::vector<Field>::iterator itField = fields.begin();
while(itField != fields.end())
{
if((*itField).name == name)
{
(*itField).rangeMin = optionEnums;
return true;
}
itField++;
}
}
it++;
}
return false;
}
/** Return the value of the option as a boolean */
bool MetaCommand::
GetValueAsBool(METAIO_STL::string optionName,
METAIO_STL::string fieldName)
{
METAIO_STL::string fieldname = fieldName;
if(fieldName == "")
{
fieldname = optionName;
}
OptionVector::const_iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
if((*it).name == optionName)
{
METAIO_STL::vector<Field>::const_iterator itField = (*it).fields.begin();
while(itField != (*it).fields.end())
{
if((*itField).name == fieldname)
{
if((*itField).value == "true"
|| (*itField).value == "1"
|| (*itField).value == "True"
|| (*itField).value == "TRUE"
)
{
return true;
}
return false;
}
itField++;
}
}
it++;
}
return false;
}
/** Return the value of the option as a bool */
bool MetaCommand::
GetValueAsBool(Option option,
METAIO_STL::string fieldName)
{
METAIO_STL::string fieldname = fieldName;
if(fieldName == "")
{
fieldname = option.name;
}
METAIO_STL::vector<Field>::const_iterator itField = option.fields.begin();
while(itField != option.fields.end())
{
if((*itField).name == fieldname)
{
if((*itField).value == "true"
|| (*itField).value == "1"
|| (*itField).value == "True"
|| (*itField).value == "TRUE"
)
{
return true;
}
return false;
}
itField++;
}
return 0;
}
/** Return the value of the option as a float */
float MetaCommand::
GetValueAsFloat(METAIO_STL::string optionName,
METAIO_STL::string fieldName)
{
METAIO_STL::string fieldname = fieldName;
if(fieldName == "")
{
fieldname = optionName;
}
OptionVector::const_iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
if((*it).name == optionName)
{
METAIO_STL::vector<Field>::const_iterator itField = (*it).fields.begin();
while(itField != (*it).fields.end())
{
if((*itField).name == fieldname)
{
return (float)atof((*itField).value.c_str());
}
itField++;
}
}
it++;
}
return 0;
}
/** Return the value of the option as a float */
float MetaCommand::
GetValueAsFloat(Option option,
METAIO_STL::string fieldName)
{
METAIO_STL::string fieldname = fieldName;
if(fieldName == "")
{
fieldname = option.name;
}
METAIO_STL::vector<Field>::const_iterator itField = option.fields.begin();
while(itField != option.fields.end())
{
if((*itField).name == fieldname)
{
return (float)atof((*itField).value.c_str());
}
itField++;
}
return 0;
}
/** Return the value of the option as a int */
int MetaCommand::
GetValueAsInt(METAIO_STL::string optionName,
METAIO_STL::string fieldName)
{
METAIO_STL::string fieldname = fieldName;
if(fieldName == "")
{
fieldname = optionName;
}
OptionVector::const_iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
if((*it).name == optionName)
{
METAIO_STL::vector<Field>::const_iterator itField = (*it).fields.begin();
while(itField != (*it).fields.end())
{
if((*itField).name == fieldname)
{
return atoi((*itField).value.c_str());
}
itField++;
}
}
it++;
}
return 0;
}
/** Return the value of the option as a int */
int MetaCommand::
GetValueAsInt(Option option,
METAIO_STL::string fieldName)
{
METAIO_STL::string fieldname = fieldName;
if(fieldName == "")
{
fieldname = option.name;
}
METAIO_STL::vector<Field>::const_iterator itField = option.fields.begin();
while(itField != option.fields.end())
{
if((*itField).name == fieldname)
{
return atoi((*itField).value.c_str());
}
itField++;
}
return 0;
}
/** Return the value of the option as a string */
METAIO_STL::string MetaCommand::
GetValueAsString(METAIO_STL::string optionName,
METAIO_STL::string fieldName)
{
METAIO_STL::string fieldname = fieldName;
if(fieldName == "")
{
fieldname = optionName;
}
OptionVector::const_iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
if((*it).name == optionName)
{
METAIO_STL::vector<Field>::const_iterator itField = (*it).fields.begin();
while(itField != (*it).fields.end())
{
if((*itField).name == fieldname)
{
return (*itField).value;
}
itField++;
}
}
it++;
}
return "";
}
/** Return the value of the option as a string */
METAIO_STL::string MetaCommand::
GetValueAsString(Option option,
METAIO_STL::string fieldName)
{
METAIO_STL::string fieldname = fieldName;
if(fieldName == "")
{
fieldname = option.name;
}
METAIO_STL::vector<Field>::const_iterator itField = option.fields.begin();
while(itField != option.fields.end())
{
if((*itField).name == fieldname)
{
return (*itField).value;
}
itField++;
}
return "";
}
/** Return the value of the option as a list of strings */
METAIO_STL::list<METAIO_STL::string> MetaCommand::
GetValueAsList( Option option )
{
METAIO_STL::list<METAIO_STL::string> results;
results.clear();
METAIO_STL::vector<Field>::const_iterator itField = option.fields.begin();
itField++;
while(itField != option.fields.end())
{
results.push_back((*itField).value);
itField++;
}
return results;
}
METAIO_STL::list< METAIO_STL::string > MetaCommand::
GetValueAsList( METAIO_STL::string optionName )
{
OptionVector::const_iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
if((*it).name == optionName)
{
return this->GetValueAsList( *it );
}
it++;
}
METAIO_STL::list< METAIO_STL::string > empty;
empty.clear();
return empty;
}
bool MetaCommand::
GetOptionWasSet(Option option)
{
if(option.userDefined)
{
return true;
}
return false;
}
bool MetaCommand::
GetOptionWasSet( METAIO_STL::string optionName)
{
OptionVector::const_iterator it = m_ParsedOptionVector.begin();
while(it != m_ParsedOptionVector.end())
{
if((*it).name == optionName)
{
return true;
}
it++;
}
return false;
}
/** List the current options */
void MetaCommand::
ListOptions()
{
OptionVector::const_iterator it = m_OptionVector.begin();
int i=0;
while(it != m_OptionVector.end())
{
METAIO_STREAM::cout << "Option #" << i << METAIO_STREAM::endl;
METAIO_STREAM::cout << " Name: " << (*it).name.c_str()
<< METAIO_STREAM::endl;
if((*it).tag.size() > 0)
{
METAIO_STREAM::cout << " Tag: " << (*it).tag.c_str()
<< METAIO_STREAM::endl;
}
if((*it).longtag.size() > 0)
{
METAIO_STREAM::cout << " LongTag: " << (*it).longtag.c_str()
<< METAIO_STREAM::endl;
}
METAIO_STREAM::cout << " Description: " << (*it).description.c_str()
<< METAIO_STREAM::endl;
if((*it).required)
{
METAIO_STREAM::cout << " Required: true" << METAIO_STREAM::endl;
}
else
{
METAIO_STREAM::cout << " Required: false" << METAIO_STREAM::endl;
}
METAIO_STREAM::cout << " Number of expeted values: "
<< (*it).fields.size()
<< METAIO_STREAM::endl;
METAIO_STL::vector<Field>::const_iterator itField = (*it).fields.begin();
while(itField != (*it).fields.end())
{
METAIO_STREAM::cout << " Field Name: " << (*itField).name.c_str()
<< METAIO_STREAM::endl;
METAIO_STREAM::cout << " Description: "
<< (*itField).description.c_str()
<< METAIO_STREAM::endl;
METAIO_STREAM::cout << " Type: "
<< this->TypeToString((*itField).type).c_str()
<< METAIO_STREAM::endl;
METAIO_STREAM::cout << " Value: " << (*itField).value.c_str()
<< METAIO_STREAM::endl;
if( (*itField).type == ENUM )
{
METAIO_STREAM::cout << " Enum list: "
<< (*itField).rangeMin.c_str()
<< METAIO_STREAM::endl;
}
else
{
METAIO_STREAM::cout << " RangeMin: "
<< (*itField).rangeMin.c_str()
<< METAIO_STREAM::endl;
METAIO_STREAM::cout << " RangeMax: "
<< (*itField).rangeMax.c_str()
<< METAIO_STREAM::endl;
}
if((*itField).externaldata)
{
METAIO_STREAM::cout << " External Data: true"
<< METAIO_STREAM::endl;
}
else
{
METAIO_STREAM::cout << " External Data: false"
<< METAIO_STREAM::endl;
}
if((*itField).required)
{
METAIO_STREAM::cout << " Required: true" << METAIO_STREAM::endl;
}
else
{
METAIO_STREAM::cout << " Required: false" << METAIO_STREAM::endl;
}
if((*itField).userDefined)
{
METAIO_STREAM::cout << " User Defined: true" << METAIO_STREAM::endl;
}
else
{
METAIO_STREAM::cout << " User Defined: false" << METAIO_STREAM::endl;
}
itField++;
}
METAIO_STREAM::cout << METAIO_STREAM::endl;
i++;
it++;
}
if(m_HelpCallBack != NULL)
{
m_HelpCallBack();
}
}
/** List the current options in xml format */
void MetaCommand::ListOptionsXML()
{
OptionVector::const_iterator it = m_OptionVector.begin();
int i=0;
while(it != m_OptionVector.end())
{
METAIO_STREAM::cout << "<option>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << "<number>" << i << "</number>"
<< METAIO_STREAM::endl;
METAIO_STREAM::cout << "<name>" << (*it).name.c_str() << "</name>"
<< METAIO_STREAM::endl;
METAIO_STREAM::cout << "<tag>" << (*it).tag.c_str() << "</tag>"
<< METAIO_STREAM::endl;
METAIO_STREAM::cout << "<longtag>" << (*it).longtag.c_str() << "</longtag>"
<< METAIO_STREAM::endl;
METAIO_STREAM::cout << "<description>" << (*it).description.c_str()
<< "</description>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << "<required>";
if((*it).required)
{
METAIO_STREAM::cout << "1</required>" << METAIO_STREAM::endl;
}
else
{
METAIO_STREAM::cout << "0</required>" << METAIO_STREAM::endl;
}
METAIO_STREAM::cout << "<nvalues>" << (*it).fields.size() << "</nvalues>"
<< METAIO_STREAM::endl;
METAIO_STL::vector<Field>::const_iterator itField = (*it).fields.begin();
while(itField != (*it).fields.end())
{
METAIO_STREAM::cout << "<field>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << "<name>" << (*itField).name.c_str() << "</name>"
<< METAIO_STREAM::endl;
METAIO_STREAM::cout << "<description>" << (*itField).description.c_str()
<< "</description>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << "<type>"
<< this->TypeToString((*itField).type).c_str()
<< "</type>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << "<value>" << (*itField).value.c_str()
<< "</value>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << "<external>";
if((*itField).externaldata == DATA_IN)
{
METAIO_STREAM::cout << "1</external>" << METAIO_STREAM::endl;
}
else if((*itField).externaldata == DATA_OUT)
{
METAIO_STREAM::cout << "2</external>" << METAIO_STREAM::endl;
}
else
{
METAIO_STREAM::cout << "0</external>" << METAIO_STREAM::endl;
}
METAIO_STREAM::cout << "<required>";
if((*itField).required)
{
METAIO_STREAM::cout << "1</required>" << METAIO_STREAM::endl;
}
else
{
METAIO_STREAM::cout << "0</required>" << METAIO_STREAM::endl;
}
METAIO_STREAM::cout << "</field>" << METAIO_STREAM::endl;
itField++;
}
METAIO_STREAM::cout << "</option>" << METAIO_STREAM::endl;
i++;
it++;
}
}
/** Used by ListOptionsSlicerXML */
void MetaCommand::WriteXMLOptionToCout(METAIO_STL::string optionName,
unsigned int & index)
{
OptionVector::const_iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
if(!strcmp((*it).name.c_str(),optionName.c_str()))
{
break;
}
it++;
}
METAIO_STL::vector<Field>::const_iterator itField = (*it).fields.begin();
METAIO_STL::string optionType = "";
if((*itField).type == MetaCommand::STRING
&& ( (*itField).externaldata == MetaCommand::DATA_IN
|| (*itField).externaldata == MetaCommand::DATA_OUT))
{
optionType = "image";
}
else if((*itField).type == MetaCommand::FLAG)
{
optionType = "boolean";
}
else if((*itField).type == MetaCommand::INT)
{
optionType = "integer";
}
else if((*itField).type == MetaCommand::ENUM)
{
optionType = "string-enumeration";
}
else
{
optionType = this->TypeToString((*itField).type).c_str();
}
METAIO_STREAM::cout << "<" << optionType.c_str()
<< ">" << METAIO_STREAM::endl;
METAIO_STREAM::cout << "<name>" << (*it).name.c_str() << "</name>"
<< METAIO_STREAM::endl;
// Label is the description for now
METAIO_STL::string label = (*it).label;
if(label.size()==0)
{
label = (*it).name;
}
METAIO_STREAM::cout << "<label>" << label.c_str() << "</label>"
<< METAIO_STREAM::endl;
METAIO_STREAM::cout << "<description>" << (*it).description.c_str()
<< "</description>" << METAIO_STREAM::endl;
if((*it).tag.size()>0) // use the single by default flag if any
{
METAIO_STREAM::cout << "<flag>" << (*it).tag.c_str() << "</flag>"
<< METAIO_STREAM::endl;
}
else if((*it).longtag.size()>0)
{
METAIO_STREAM::cout << "<longflag>" << (*it).longtag.c_str() << "</longflag>"
<< METAIO_STREAM::endl;
}
else
{
METAIO_STREAM::cout << "<index>" << index << "</index>" << METAIO_STREAM::endl;
index++;
}
if((*itField).value.size()>0)
{
METAIO_STREAM::cout << "<default>" << (*itField).value.c_str() << "</default>"
<< METAIO_STREAM::endl;
}
if((*itField).externaldata == MetaCommand::DATA_IN)
{
METAIO_STREAM::cout << "<channel>input</channel>" << METAIO_STREAM::endl;
}
else if((*itField).externaldata == MetaCommand::DATA_OUT)
{
METAIO_STREAM::cout << "<channel>output</channel>" << METAIO_STREAM::endl;
}
if((*itField).type == MetaCommand::ENUM)
{
METAIO_STL::vector< METAIO_STL::string > enumVector;
MET_StringToVector< METAIO_STL::string>( (*itField).rangeMin, enumVector );
METAIO_STL::vector< METAIO_STL::string >::iterator itenum;
itenum = enumVector.begin();
while(itenum != enumVector.end() )
{
METAIO_STREAM::cout << "<element>" << (*itenum).c_str() << "</element>"
<< METAIO_STREAM::endl;
++itenum;
}
}
// Write out the closing tag
METAIO_STREAM::cout << "</" << optionType.c_str()
<< ">" << METAIO_STREAM::endl;
}
/** List the current options in Slicer's xml format (www.slicer.org) */
void MetaCommand::ListOptionsSlicerXML()
{
METAIO_STREAM::cout << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << "<executable>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << " <category>" << m_Category.c_str() << "</category>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << " <title>" << m_Name.c_str() << "</title>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << " <description>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << " " << m_Description.c_str() << METAIO_STREAM::endl;
METAIO_STREAM::cout << " </description>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << " <version>" << m_Version.c_str() << "</version>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << " <contributor>" << m_Author.c_str() << "</contributor>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << " <documentation-url></documentation-url>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << " <license></license>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << " <acknowledgements>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << " " << m_Acknowledgments.c_str() << METAIO_STREAM::endl;
METAIO_STREAM::cout << " </acknowledgements>" << METAIO_STREAM::endl;
// Organize by group first
// Keep a list of options
unsigned int index=0;
METAIO_STL::vector<METAIO_STL::string> GroupedOptionVector;
ParameterGroupVector::const_iterator itGroup = m_ParameterGroup.begin();
while(itGroup != m_ParameterGroup.end())
{
if( (*itGroup).advanced == true )
{
METAIO_STREAM::cout << " <parameters advanced=\"true\">" << METAIO_STREAM::endl;
}
else
{
METAIO_STREAM::cout << " <parameters>" << METAIO_STREAM::endl;
}
METAIO_STREAM::cout << " <label>" << (*itGroup).name.c_str()
<< "</label>" << METAIO_STREAM::endl;
if((*itGroup).description.size() == 0)
{
METAIO_STREAM::cout << " <description>" << (*itGroup).name.c_str()
<< "</description>" << METAIO_STREAM::endl;
}
else
{
METAIO_STREAM::cout << " <description>" << (*itGroup).description.c_str()
<< "</description>" << METAIO_STREAM::endl;
}
METAIO_STL::vector<METAIO_STL::string>::const_iterator itOption = (*itGroup).options.begin();
while(itOption != (*itGroup).options.end())
{
this->WriteXMLOptionToCout(*itOption,index);
GroupedOptionVector.push_back(*itOption);
itOption++;
}
METAIO_STREAM::cout << " </parameters>" << METAIO_STREAM::endl;
itGroup++;
}
// Then take the remaining options
if(m_OptionVector.size()>GroupedOptionVector.size())
{
METAIO_STREAM::cout << " <parameters>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << " <label>IO</label>" << METAIO_STREAM::endl;
METAIO_STREAM::cout << " <description>Input/output parameters</description>" << METAIO_STREAM::endl;
OptionVector::const_iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
bool optionIsGrouped = false;
METAIO_STL::vector<METAIO_STL::string>::const_iterator itGroupedOption = GroupedOptionVector.begin();
while(itGroupedOption != GroupedOptionVector.end())
{
if(!strcmp((*itGroupedOption).c_str(),(*it).name.c_str()))
{
optionIsGrouped = true;
break;
}
itGroupedOption++;
}
if(!optionIsGrouped)
{
this->WriteXMLOptionToCout((*it).name.c_str(),index);
}
it++;
} // end loop option
METAIO_STREAM::cout << " </parameters>" << METAIO_STREAM::endl;
} // end m_OptionVector.size()>GroupedOptionVector.size()
METAIO_STREAM::cout << "</executable>" << METAIO_STREAM::endl;
}
/** Internal small XML parser */
METAIO_STL::string MetaCommand::
GetXML(const char* buffer, const char* desc, unsigned long pos)
{
METAIO_STL::string begin = "<";
begin += desc;
begin += ">";
METAIO_STL::string end = "</";
end += desc;
end += ">";
METAIO_STL::string buf = buffer;
long int posb = static_cast<long int>(buf.find(begin,pos));
if(posb == -1)
{
return "";
}
long int pose = static_cast<long int>(buf.find(end,posb));
if(pose == -1)
{
return "";
}
return buf.substr(posb+begin.size(),pose-posb-begin.size());
}
/** Given an XML buffer fill in the command line arguments */
bool MetaCommand::
ParseXML(const char* buffer)
{
m_OptionVector.clear();
METAIO_STL::string buf = this->GetXML(buffer,"option",0);
long pos = 0;
while(buf.size() > 0)
{
Option option;
option.name = this->GetXML(buf.c_str(),"name",0);
option.tag = this->GetXML(buf.c_str(),"tag",0);
option.longtag = this->GetXML(buf.c_str(),"longtag",0);
option.description = this->GetXML(buf.c_str(),"description",0);
if(atoi(this->GetXML(buf.c_str(),"required",0).c_str()) == 0)
{
option.required = false;
}
else
{
option.required = true;
}
unsigned int n = atoi(this->GetXML(buf.c_str(),"nvalues",0).c_str());
// Now check the fields
long posF = static_cast<long>(buf.find("<field>"));
for(unsigned int i=0;i<n;i++)
{
METAIO_STL::string f = this->GetXML(buf.c_str(),"field",posF);
Field field;
field.userDefined = false;
field.name = this->GetXML(f.c_str(),"name",0);
field.description = this->GetXML(f.c_str(),"description",0);
field.value = this->GetXML(f.c_str(),"value",0);
field.type = this->StringToType(this->GetXML(f.c_str(),"type",0).c_str());
if(atoi(this->GetXML(f.c_str(),"external",0).c_str()) == 0)
{
field.externaldata = DATA_NONE;
}
else
{
if(atoi(this->GetXML(f.c_str(),"external",0).c_str()) == 1)
{
field.externaldata = DATA_IN;
}
else
{
field.externaldata = DATA_OUT;
}
}
if(atoi(this->GetXML(f.c_str(),"required",0).c_str()) == 0)
{
field.required = false;
}
else
{
field.required = true;
}
option.fields.push_back(field);
posF += static_cast<long>(f.size()+8);
}
m_OptionVector.push_back(option);
pos += static_cast<long>(buf.size()+17);
buf = this->GetXML(buffer,"option",pos);
}
return true;
}
/** List the current options */
void MetaCommand::
ListOptionsSimplified(bool extended)
{
if(extended)
{
METAIO_STREAM::cout << " System tags: " << METAIO_STREAM::endl
<< " [ -v ] or [ -h ]"
<< METAIO_STREAM::endl
<< " = List options in short format"
<< METAIO_STREAM::endl
<< " [ -V ] or [ -H ]"
<< METAIO_STREAM::endl
<< " = List options in long format"
<< METAIO_STREAM::endl
<< " [ -vxml ] or [ -hxml ] or [ -exportXML ]"
<< METAIO_STREAM::endl
<< " = List options in xml format for BatchMake"
<< METAIO_STREAM::endl
<< " [ --xml ]"
<< METAIO_STREAM::endl
<< " = List options in xml format for Slicer"
<< METAIO_STREAM::endl
<< " [ -vgad ] or [ -hgad ] or [ -exportGAD ]"
<< METAIO_STREAM::endl
<< " = List options in Grid Application Description format"
<< METAIO_STREAM::endl
<< " [ -version ]"
<< METAIO_STREAM::endl
<< " = return the version number"
<< METAIO_STREAM::endl
<< " [ -date ]"
<< METAIO_STREAM::endl
<< " = return the cvs checkout date"
#ifdef METAIO_USE_LIBXML2
<< METAIO_STREAM::endl
<< " [ --loadArguments filename ]"
<< " = load the arguments from an XML file"
#endif
<< METAIO_STREAM::endl;
}
int count = 0;
int ntags = 0;
int nfields = 0;
OptionVector::const_iterator it;
it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
if((*it).tag.size() > 0 || (*it).longtag.size() > 0)
{
ntags++;
}
else
{
nfields++;
}
++it;
}
while(count<2)
{
if(count == 0)
{
if(ntags > 0)
{
METAIO_STREAM::cout << " Command tags: "
<< METAIO_STREAM::endl;
}
else
{
count++;
}
}
if(count == 1)
{
if(nfields > 0)
{
METAIO_STREAM::cout << " Command fields: "
<< METAIO_STREAM::endl;
}
else
{
count++;
}
}
count++;
it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
if( (count == 1 && ( (*it).tag.size() > 0 || (*it).longtag.size() > 0 ))
|| (count == 2 && ( (*it).tag.size() == 0 && (*it).longtag.size() == 0 )) )
{
if(!(*it).required)
{
METAIO_STREAM::cout << " [ ";
}
else
{
METAIO_STREAM::cout << " ";
}
if((*it).tag.size() > 0)
{
METAIO_STREAM::cout << "-" << (*it).tag.c_str() << " ";
}
if((*it).longtag.size() > 0)
{
METAIO_STREAM::cout << "--" << (*it).longtag.c_str() << " ";
}
METAIO_STL::vector<Field>::const_iterator itField =
(*it).fields.begin();
while(itField != (*it).fields.end())
{
// only display the type if it's not a FLAG
if((*itField).type != FLAG)
{
if((*itField).required)
{
METAIO_STREAM::cout << "< ";
}
else
{
METAIO_STREAM::cout << "[ ";
}
METAIO_STREAM::cout << (*itField).name.c_str();
if((*itField).required)
{
METAIO_STREAM::cout << " > ";
}
else
{
METAIO_STREAM::cout << " ] ";
}
}
itField++;
}
if(!(*it).required)
{
METAIO_STREAM::cout << "]";
}
METAIO_STREAM::cout << METAIO_STREAM::endl;
if((*it).description.size()>0)
{
METAIO_STREAM::cout << " = " << (*it).description.c_str();
METAIO_STREAM::cout << METAIO_STREAM::endl;
itField = (*it).fields.begin();
while(itField != (*it).fields.end())
{
if((*itField).description.size() > 0
|| (*itField).value.size() > 0)
{
METAIO_STREAM::cout << " With: "
<< (*itField).name.c_str();
if((*itField).description.size() > 0)
{
METAIO_STREAM::cout << " = " << (*itField).description.c_str();
}
if((*itField).value.size() > 0)
{
METAIO_STREAM::cout << " (Default = "
<< (*itField).value.c_str() << ")";
}
METAIO_STREAM::cout << METAIO_STREAM::endl;
}
itField++;
}
}
}
it++;
}
}
if(m_HelpCallBack != NULL)
{
m_HelpCallBack();
}
}
/** Get the option by "-"+tag
* or by "--"+longtag */
bool MetaCommand::
OptionExistsByMinusTag(METAIO_STL::string minusTag)
{
OptionVector::const_iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
METAIO_STL::string tagToSearch = "-";
tagToSearch += (*it).tag;
METAIO_STL::string longtagToSearch = "--";
longtagToSearch += (*it).longtag;
METAIO_STL::string longtagToSearchBackwardCompatible = "-";
longtagToSearchBackwardCompatible += (*it).longtag;
// WARNING: This is for backward compatibility but a warning
// is going to be thrown if used so that people can adjust
if(tagToSearch == minusTag
|| longtagToSearch == minusTag
|| longtagToSearchBackwardCompatible == minusTag
)
{
return true;
}
it++;
}
return false;
}
/** Get the option by "-"+tag
* or by "--"+longtag */
MetaCommand::Option * MetaCommand::
GetOptionByMinusTag(METAIO_STL::string minusTag)
{
OptionVector::iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
METAIO_STL::string tagToSearch = "-";
tagToSearch += (*it).tag;
METAIO_STL::string longtagToSearch = "--";
longtagToSearch += (*it).longtag;
METAIO_STL::string longtagToSearchBackwardCompatible = "-";
longtagToSearchBackwardCompatible += (*it).longtag;
// WARNING: This is for backward compatibility but a warning
// is going to be thrown if used so that people can adjust
if(tagToSearch == minusTag
|| longtagToSearch == minusTag
|| longtagToSearchBackwardCompatible == minusTag
)
{
return &(*it);
}
it++;
}
return NULL;
}
/** Get the option by tag */
MetaCommand::Option * MetaCommand::
GetOptionByTag(METAIO_STL::string tag)
{
OptionVector::iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
if((*it).tag == tag || (*it).longtag == tag)
{
return &(*it);
}
it++;
}
return NULL;
}
/** Return the option id. i.e the position in the vector */
long MetaCommand::
GetOptionId(Option* option)
{
OptionVector::iterator it = m_OptionVector.begin();
unsigned long i = 0;
while(it != m_OptionVector.end())
{
if(&(*it) == option)
{
return i;
}
i++;
it++;
}
return -1;
}
/** Export the current command line arguments to a Grid Application
* Description file */
bool MetaCommand::
ExportGAD(bool dynamic)
{
METAIO_STREAM::cout << "Exporting GAD file...";
OptionVector options = m_OptionVector;
if(dynamic)
{
options = m_ParsedOptionVector;
}
if(m_Name=="")
{
METAIO_STREAM::cout << "Set the name of the application using SetName()"
<< METAIO_STREAM::endl;
return false;
}
METAIO_STL::string filename = m_Name;
filename += ".gad.xml";
METAIO_STREAM::ofstream file;
#ifdef __sgi
file.open(filename.c_str(), METAIO_STREAM::ios::out);
#else
file.open(filename.c_str(), METAIO_STREAM::ios::binary
| METAIO_STREAM::ios::out);
#endif
if(!file.rdbuf()->is_open())
{
METAIO_STREAM::cout << "Cannot open file for writing: "
<< filename.c_str() << METAIO_STREAM::endl;
return false;
}
file << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" << METAIO_STREAM::endl;
file << "<gridApplication" << METAIO_STREAM::endl;
file << "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
<< METAIO_STREAM::endl;
file << "xsi:noNamespaceSchemaLocation=\"grid-application-description.xsd\""
<< METAIO_STREAM::endl;
file << "name=\"" << m_Name.c_str() << "\"" << METAIO_STREAM::endl;
file << "description=\"" << m_Description.c_str() << "\">"
<< METAIO_STREAM::endl;
file << "<applicationComponent name=\"Client\" remoteExecution=\"true\">"
<< METAIO_STREAM::endl;
file << "<componentActionList>" << METAIO_STREAM::endl;
file << METAIO_STREAM::endl;
unsigned int order = 1;
// Write out the input data to be transfered
OptionVector::const_iterator it = options.begin();
while(it != options.end())
{
METAIO_STL::vector<Field>::const_iterator itFields = (*it).fields.begin();
while(itFields != (*it).fields.end())
{
if((*itFields).externaldata == DATA_IN)
{
file << " <componentAction type=\"DataRelocation\" order=\"" << order
<< "\">" << METAIO_STREAM::endl;
file << " <parameter name=\"Name\" value=\""
<< (*itFields).name.c_str()
<<"\"/>" << METAIO_STREAM::endl;
file << " <parameter name=\"Host\" value=\"hostname\"/>"
<< METAIO_STREAM::endl;
file << " <parameter name=\"Description\" value=\""
<< (*itFields).description.c_str() << "\"/>"
<< METAIO_STREAM::endl;
file << " <parameter name=\"Direction\" value=\"In\"/>"
<< METAIO_STREAM::endl;
file << " <parameter name=\"Protocol\" value=\"gsiftp\"/>"
<< METAIO_STREAM::endl;
file << " <parameter name=\"SourceDataPath\" value=\""
<< (*itFields).value.c_str() << "\"/>" << METAIO_STREAM::endl;
METAIO_STL::string datapath = (*itFields).value;
long int slash = static_cast<long int>(datapath.find_last_of("/"));
if(slash>0)
{
datapath = datapath.substr(slash+1,datapath.size()-slash-1);
}
slash = static_cast<long int>(datapath.find_last_of("\\"));
if(slash>0)
{
datapath = datapath.substr(slash+1,datapath.size()-slash-1);
}
file << " <parameter name=\"DestDataPath\" value=\""
<< datapath.c_str() << "\"/>" << METAIO_STREAM::endl;
file << " </componentAction>" << METAIO_STREAM::endl;
file << METAIO_STREAM::endl;
order++;
}
itFields++;
}
it++;
}
file << " <componentAction type=\"JobSubmission\" order=\"" << order << "\">"
<< METAIO_STREAM::endl;
file << " <parameter name=\"Executable\" value=\""
<< m_ExecutableName.c_str() << "\"/>" << METAIO_STREAM::endl;
file << " <parameter name=\"Arguments\" value=\"";
// Write out the command line arguments
it = options.begin();
while(it != options.end())
{
if(it != options.begin())
{
file << " ";
}
file << "{" << (*it).name.c_str() << "}";
it++;
}
file << "\"/>" << METAIO_STREAM::endl;
// Write out the arguments that are not data
it = options.begin();
while(it != options.end())
{
// Find if this is a non data field
bool isData = false;
METAIO_STL::vector<Field>::const_iterator itFields = (*it).fields.begin();
while(itFields != (*it).fields.end())
{
if((*itFields).externaldata != DATA_NONE)
{
isData = true;
break;
}
itFields++;
}
if(isData)
{
it++;
continue;
}
file << " <group name=\"" << (*it).name.c_str();
file << "\" syntax=\"";
if((*it).tag.size()>0)
{
file << "-" << (*it).tag.c_str() << " ";
}
itFields = (*it).fields.begin();
while(itFields != (*it).fields.end())
{
if(itFields != (*it).fields.begin())
{
file << " ";
}
file << "{" << (*it).name.c_str() << (*itFields).name.c_str() << "}";
itFields++;
}
file << "\"";
if(!(*it).required)
{
file << " optional=\"true\"";
// Add if the option was selected
if((*it).userDefined)
{
file << " selected=\"true\"";
}
else
{
file << " selected=\"false\"";
}
}
file << ">" << METAIO_STREAM::endl;
// Now writes the value of the arguments
itFields = (*it).fields.begin();
while(itFields != (*it).fields.end())
{
file << " <argument name=\"" << (*it).name.c_str()
<< (*itFields).name.c_str();
file << "\" value=\"" << (*itFields).value.c_str();
file << "\" type=\"" << this->TypeToString((*itFields).type).c_str();
file << "\"";
if((*itFields).rangeMin != "")
{
file << " rangeMin=\"" << (*itFields).rangeMin.c_str() << "\"";
}
if((*itFields).rangeMax != "")
{
file << " rangeMax=\"" << (*itFields).rangeMax.c_str() << "\"";
}
file << "/>" << METAIO_STREAM::endl;
itFields++;
}
file << " </group>" << METAIO_STREAM::endl;
it++;
}
file << " </componentAction>" << METAIO_STREAM::endl;
order++;
file << METAIO_STREAM::endl;
// Write out the input data to be transfered
it = options.begin();
while(it != options.end())
{
METAIO_STL::vector<Field>::const_iterator itFields = (*it).fields.begin();
while(itFields != (*it).fields.end())
{
if((*itFields).externaldata == DATA_OUT)
{
file << " <componentAction type=\"DataRelocation\" order=\"" << order
<< "\">" << METAIO_STREAM::endl;
file << " <parameter name=\"Name\" Value=\""
<< (*itFields).name.c_str()
<<"\"/>" << METAIO_STREAM::endl;
file << " <parameter name=\"Host\" Value=\"hostname\"/>"
<< METAIO_STREAM::endl;
file << " <parameter name=\"Description\" value=\""
<< (*itFields).description.c_str() << "\"/>"
<< METAIO_STREAM::endl;
file << " <parameter name=\"Direction\" value=\"Out\"/>"
<< METAIO_STREAM::endl;
file << " <parameter name=\"Protocol\" value=\"gsiftp\"/>"
<< METAIO_STREAM::endl;
METAIO_STL::string datapath = (*itFields).value;
long int slash = static_cast<long int>(datapath.find_last_of("/"));
if(slash>0)
{
datapath = datapath.substr(slash+1,datapath.size()-slash-1);
}
slash = static_cast<long int>(datapath.find_last_of("\\"));
if(slash>0)
{
datapath = datapath.substr(slash+1,datapath.size()-slash-1);
}
file << " <parameter name=\"SourceDataPath\" value=\""
<< datapath.c_str() << "\"/>" << METAIO_STREAM::endl;
file << " <parameter name=\"DestDataPath\" value=\""
<< (*itFields).value.c_str() << "\"/>" << METAIO_STREAM::endl;
file << " </componentAction>" << METAIO_STREAM::endl;
file << METAIO_STREAM::endl;
order++;
}
itFields++;
}
it++;
}
file << " </componentActionList>" << METAIO_STREAM::endl;
file << " </applicationComponent>" << METAIO_STREAM::endl;
file << "</gridApplication>" << METAIO_STREAM::endl;
file.close();
METAIO_STREAM::cout << "done" << METAIO_STREAM::endl;
return true;
}
/** Parse the command line */
bool MetaCommand::Parse(int argc, char* argv[])
{
m_GotXMLFlag = false;
m_ExecutableName = argv[0];
long int slash = static_cast<long int>(m_ExecutableName.find_last_of("/"));
if(slash>0)
{
m_ExecutableName = m_ExecutableName.substr(slash+1,
m_ExecutableName.size()-slash-1);
}
slash = static_cast<long int>(m_ExecutableName.find_last_of("\\"));
if(slash>0)
{
m_ExecutableName = m_ExecutableName.substr(slash+1,
m_ExecutableName.size()-slash-1);
}
// Fill in the results
m_ParsedOptionVector.clear();
bool inArgument = false;
METAIO_STL::string tag = "";
METAIO_STL::string args;
unsigned int currentField = 0; // current field position
int currentOption = 0; // id of the option to fill
unsigned int valuesRemaining=0;
unsigned int optionalValuesRemaining=0;
bool isComplete = false; // check if the option should be parse until
// the next tag is found
METAIO_STL::string completeString = "";
bool exportGAD = false;
for(unsigned int i=1;i<(unsigned int)argc;i++)
{
if(!strcmp(argv[i],"-V") || !strcmp(argv[i],"-H"))
{
METAIO_STREAM::cout << "Usage : " << argv[0] << METAIO_STREAM::endl;
this->ListOptions();
return true;
}
// List the options if using -v
if(!strcmp(argv[i],"-v") || !strcmp(argv[i],"-h"))
{
METAIO_STREAM::cout << "Usage : " << argv[0] << METAIO_STREAM::endl;
this->ListOptionsSimplified();
return true;
}
// List the options if using -v
if(!strcmp(argv[i],"--loadArguments"))
{
if((i+1)>=(unsigned int)argc)
{
METAIO_STREAM::cout << "--loadArguments expected a filename as argument"
<< METAIO_STREAM::endl;
return false;
}
this->LoadArgumentsFromXML(argv[i+1]);
i++;
continue;
}
if(!strcmp(argv[i],"-vxml")
|| !strcmp(argv[i],"-hxml")
|| !strcmp(argv[i],"-exportXML")
|| !strcmp(argv[i],"--vxml")
|| !strcmp(argv[i],"--hxml")
|| !strcmp(argv[i],"--exportXML"))
{
this->ListOptionsXML();
continue;
}
if(!strcmp(argv[i],"--xml") )
{
this->ListOptionsSlicerXML();
m_GotXMLFlag = true;
return false;
}
if(!strcmp(argv[i],"-version"))
{
METAIO_STREAM::cout << "Version: " << m_Version.c_str()
<< METAIO_STREAM::endl;
continue;
}
if(!strcmp(argv[i],"-date"))
{
METAIO_STREAM::cout << "Date: " << m_Date.c_str()
<< METAIO_STREAM::endl;
continue;
}
if(!strcmp(argv[i],"-exportGAD")
|| !strcmp(argv[i],"-vgad")
|| !strcmp(argv[i],"-hgad"))
{
this->ExportGAD();
exportGAD = true;
continue;
}
// If this is a tag
if(argv[i][0] == '-' && (atof(argv[i])==0) && (strlen(argv[i])>1))
{
// if we have a tag before the expected values we throw an exception
if(valuesRemaining!=0)
{
if(!isComplete)
{
if(optionalValuesRemaining >0)
{
valuesRemaining = 0;
m_OptionVector[currentOption].userDefined = true;
m_ParsedOptionVector.push_back(m_OptionVector[currentOption]);
}
else
{
METAIO_STREAM::cout << "Found tag " << argv[i]
<< " before end of value list!"
<< METAIO_STREAM::endl;
return false;
}
}
else
{
m_OptionVector[currentOption].fields[0].value = completeString;
m_OptionVector[currentOption].fields[0].userDefined = true;
m_OptionVector[currentOption].userDefined = true;
m_ParsedOptionVector.push_back(m_OptionVector[currentOption]);
valuesRemaining = 0;
}
}
inArgument = false;
// New tag so we add the previous values to the tag
tag = argv[i];
// Check if the tag is in the list
if(this->OptionExistsByMinusTag(tag))
{
inArgument = true;
// We check the number of mandatory and optional values for
// this tag
METAIO_STL::vector<Field>::const_iterator fIt =
this->GetOptionByMinusTag(tag)->fields.begin();
while(fIt != this->GetOptionByMinusTag(tag)->fields.end())
{
if(!(*fIt).required)
{
optionalValuesRemaining++;
}
valuesRemaining++;
fIt++;
}
currentOption = this->GetOptionId(this->GetOptionByMinusTag(tag));
if(currentOption < 0)
{
METAIO_STREAM::cout << "Error processing tag " << tag.c_str()
<< ". Tag exists but cannot find its Id."
<< METAIO_STREAM::endl;
}
else
{
isComplete = m_OptionVector[currentOption].complete;
if(m_OptionVector[currentOption].fields[0].type == FLAG)
{
// the tag exists by default
m_OptionVector[currentOption].fields[0].value = "true";
valuesRemaining = 0;
optionalValuesRemaining = 0;
inArgument = false;
}
else if(m_OptionVector[currentOption].fields[0].type == LIST)
{
inArgument = true;
unsigned int valuesInList = (int)atoi(argv[++i]);
m_OptionVector[currentOption].fields[0].value = argv[i];
valuesRemaining += valuesInList-1;
char optName[255];
for(unsigned int j=0; j<valuesInList; j++)
{
sprintf(optName, "%03u", j);
this->AddOptionField( m_OptionVector[currentOption].name,
optName, STRING );
}
}
args = "";
}
}
else
{
if(m_Verbose)
{
METAIO_STREAM::cout << "The tag " << tag.c_str()
<< " is not a valid argument : skipping this tag"
<< METAIO_STREAM::endl;
}
if(m_FailOnUnrecognizedOption)
{
return false;
}
}
if(inArgument)
{
i++;
}
}
else if(!inArgument) // If this is a field
{
// Look for the field to add
OptionVector::iterator it = m_OptionVector.begin();
unsigned long pos = 0;
bool found = false;
while(it != m_OptionVector.end())
{
if((pos >= currentField) && ((*it).tag=="" && (*it).longtag==""))
{
currentOption = pos;
valuesRemaining = static_cast<unsigned int>((*it).fields.size());
found = true;
break;
}
pos++;
it++;
}
if(!found && m_Verbose)
{
METAIO_STREAM::cout
<< "Too many arguments specified in your command line! "
<< "Skipping extra argument: " << argv[i]
<< METAIO_STREAM::endl;
}
inArgument=true;
currentField=currentOption+1;
}
// We collect the values
if(isComplete && (int)i<argc)
{
if(completeString.size()==0)
{
completeString = argv[i];
}
else
{
completeString += " ";
completeString += argv[i];
}
}
else if(inArgument && i<(unsigned int)argc && (valuesRemaining>0))
{
// We check that the current value is not a tag.
// This might be the case when we have optional fields
if(this->OptionExistsByMinusTag(argv[i]) && optionalValuesRemaining>0)
{
valuesRemaining = 0;
optionalValuesRemaining = 0;
i--; // the outter loop will take care of incrementing it.
}
else if(currentOption >=0 && currentOption <(int)(m_OptionVector.size()))
{
unsigned long s = static_cast<unsigned long>(
m_OptionVector[currentOption].fields.size());
// We change the value only if this is not a tag
if(this->OptionExistsByMinusTag(argv[i]))
{
METAIO_STREAM::cout << "Option "
<< m_OptionVector[currentOption].name.c_str()
<< " expect a value and got tag: " << argv[i]
<< METAIO_STREAM::endl;
this->ListOptionsSimplified(false);
return false;
}
m_OptionVector[currentOption].fields[s-(valuesRemaining)].value = argv[i];
m_OptionVector[currentOption].fields[s-(valuesRemaining)].userDefined =
true;
if(!m_OptionVector[currentOption].fields[s-(valuesRemaining)].required)
{
optionalValuesRemaining--;
}
valuesRemaining--;
}
else if(valuesRemaining>0)
{
valuesRemaining--;
}
}
else if(valuesRemaining==optionalValuesRemaining
&& i==(unsigned int)argc && (optionalValuesRemaining>0))
// if this is the last argument and all the remaining values are optionals
{
if(this->OptionExistsByMinusTag(argv[i-1]) )
{
valuesRemaining = 0;
optionalValuesRemaining = 0;
}
}
if(valuesRemaining == 0)
{
inArgument = false;
m_OptionVector[currentOption].userDefined = true;
m_ParsedOptionVector.push_back(m_OptionVector[currentOption]);
}
} // end loop command line arguments
if(isComplete) // If we are still in the isComplete mode we add the option
{
m_OptionVector[currentOption].fields[0].value = completeString;
m_OptionVector[currentOption].fields[0].userDefined = true;
m_OptionVector[currentOption].userDefined = true;
m_ParsedOptionVector.push_back(m_OptionVector[currentOption]);
valuesRemaining = 0;
}
if(optionalValuesRemaining >0 && optionalValuesRemaining==valuesRemaining)
{
valuesRemaining = 0;
m_OptionVector[currentOption].userDefined = true;
m_ParsedOptionVector.push_back(m_OptionVector[currentOption]);
}
if(valuesRemaining>0)
{
METAIO_STREAM::cout << "Not enough parameters for "
<< m_OptionVector[currentOption].name.c_str()
<< METAIO_STREAM::endl;
METAIO_STREAM::cout << "Usage: " << argv[0] << METAIO_STREAM::endl;
this->ListOptionsSimplified(false);
return false;
}
// Check if the options with required arguments are defined
OptionVector::iterator it = m_OptionVector.begin();
bool requiredAndNotDefined = false;
while(it != m_OptionVector.end())
{
if((*it).required)
{
// First check if the option is actually defined
if(!(*it).userDefined)
{
METAIO_STREAM::cout << "Option " << (*it).name.c_str()
<< " is required but not defined"
<< METAIO_STREAM::endl;
requiredAndNotDefined = true;
it++;
continue;
}
// Check if the values are defined
METAIO_STL::vector<Field>::const_iterator itFields = (*it).fields.begin();
bool defined = true;
while(itFields != (*it).fields.end())
{
if((*itFields).value == "")
{
defined = false;
}
itFields++;
}
if(!defined)
{
if((*it).tag.size()>0 || (*it).longtag.size()>0)
{
METAIO_STREAM::cout << "Field " << (*it).tag.c_str()
<< " is required but not defined"
<< METAIO_STREAM::endl;
}
else
{
METAIO_STREAM::cout << "Field " << (*it).name.c_str()
<< " is required but not defined"
<< METAIO_STREAM::endl;
}
requiredAndNotDefined = true;
}
}
it++;
}
if(requiredAndNotDefined)
{
//METAIO_STREAM::cout << "Command: " << argv[0] << METAIO_STREAM::endl;
this->ListOptionsSimplified(false);
return false;
}
// Check if the values are in range (if the range is defined)
OptionVector::iterator itParsed = m_ParsedOptionVector.begin();
bool valueInRange = true;
while(itParsed != m_ParsedOptionVector.end())
{
METAIO_STL::vector<Field>::const_iterator itFields = (*itParsed).fields
.begin();
while(itFields != (*itParsed).fields.end())
{
// Check only if this is a number
if(((*itFields).type == INT ||
(*itFields).type == FLOAT ||
(*itFields).type == CHAR)
&& ((*itFields).value != "")
)
{
// Check the range min
if(
(((*itFields).rangeMin != "")
&& (atof((*itFields).rangeMin.c_str())
> atof((*itFields).value.c_str())))
||
(((*itFields).rangeMax != "")
&& (atof((*itFields).rangeMax.c_str())
< atof((*itFields).value.c_str())))
)
{
METAIO_STREAM::cout << (*itParsed).name.c_str()
<< "." << (*itFields).name.c_str()
<< " : Value (" << (*itFields).value.c_str() << ") "
<< "is not in the range [" << (*itFields).rangeMin.c_str()
<< "," << (*itFields).rangeMax.c_str()
<< "]" << METAIO_STREAM::endl;
valueInRange = false;
}
}
itFields++;
}
itParsed++;
}
if(!valueInRange)
{
return false;
}
// If everything is ok
if(exportGAD)
{
this->ExportGAD(true);
return false; // prevent from running the application
}
return true;
}
/** Return the string representation of a type */
METAIO_STL::string MetaCommand::TypeToString(TypeEnumType type)
{
switch(type)
{
case INT:
return "int";
case FLOAT:
return "float";
case STRING:
return "string";
case LIST:
return "list";
case FLAG:
return "flag";
case BOOL:
return "boolean";
case IMAGE:
return "image";
case FILE:
return "file";
case ENUM:
return "enum";
case CHAR:
default:
return "not defined";
}
}
/** Return a type given a string */
MetaCommand::TypeEnumType MetaCommand::StringToType(const char* type)
{
if(!strcmp(type,"int"))
{
return INT;
}
else if(!strcmp(type,"float"))
{
return FLOAT;
}
else if(!strcmp(type,"string"))
{
return STRING;
}
else if(!strcmp(type,"list"))
{
return LIST;
}
else if(!strcmp(type,"flag"))
{
return FLAG;
}
else if(!strcmp(type,"bool"))
{
return BOOL;
}
else if(!strcmp(type,"image"))
{
return IMAGE;
}
else if(!strcmp(type,"enum"))
{
return ENUM;
}
else if(!strcmp(type,"file"))
{
return FILE;
}
return INT; // by default
}
/** Set the long flag for the option */
bool MetaCommand::SetOptionLongTag(METAIO_STL::string optionName,
METAIO_STL::string longTag)
{
OptionVector::iterator itOption = m_OptionVector.begin();
while(itOption != m_OptionVector.end())
{
if(!strcmp((*itOption).name.c_str(),optionName.c_str()))
{
(*itOption).longtag = longTag;
return true;
}
itOption++;
}
return false;
}
/** Set the label for the option */
bool MetaCommand::SetOptionLabel(METAIO_STL::string optionName,
METAIO_STL::string label)
{
OptionVector::iterator itOption = m_OptionVector.begin();
while(itOption != m_OptionVector.end())
{
if(!strcmp((*itOption).name.c_str(),optionName.c_str()))
{
(*itOption).label = label;
return true;
}
itOption++;
}
return false;
}
/** Set the group for a field or an option
* If the group doesn't exist it is automatically created. */
bool MetaCommand::SetParameterGroup(METAIO_STL::string optionName,
METAIO_STL::string groupName,
METAIO_STL::string groupDescription,
bool advanced
)
{
// Check if the group exists
ParameterGroup* group = NULL;
ParameterGroupVector::iterator it = m_ParameterGroup.begin();
while(it != m_ParameterGroup.end())
{
if(!strcmp((*it).name.c_str(),groupName.c_str()))
{
group = &(*it);
}
it++;
}
bool optionExists = false;
unsigned int index = 0;
OptionVector::const_iterator itOption = m_OptionVector.begin();
while(itOption != m_OptionVector.end())
{
if(!strcmp((*itOption).name.c_str(),optionName.c_str()))
{
optionExists = true;
break;
}
index++;
itOption++;
}
if(!optionExists)
{
METAIO_STREAM::cout << "The option " << optionName.c_str()
<< " doesn't exist" << METAIO_STREAM::endl;
return false;
}
if(!group)
{
ParameterGroup pgroup;
pgroup.name = groupName;
pgroup.description = groupDescription;
pgroup.advanced = advanced;
pgroup.options.push_back(optionName);
m_ParameterGroup.push_back(pgroup);
}
else
{
group->options.push_back(optionName);
}
return true;
}
/** Load arguments from XML file */
bool MetaCommand::LoadArgumentsFromXML(const char* filename,
bool createMissingArguments)
{
#ifdef METAIO_USE_LIBXML2
xmlDocPtr doc;
xmlNodePtr cur;
doc = xmlParseFile(filename);
if (doc == NULL )
{
METAIO_STREAM::cerr << "Cannot parse XML file" << METAIO_STREAM::endl;
return false;
}
cur = xmlDocGetRootElement(doc);
if (cur == NULL)
{
METAIO_STREAM::cerr << "XML document is empty" << METAIO_STREAM::endl;
xmlFreeDoc(doc);
return false;
}
if (xmlStrcmp(cur->name, (const xmlChar *) "MetaCommand"))
{
METAIO_STREAM::cerr << "document of the wrong type. Root node shoule be MetaCommand" << METAIO_STREAM::endl;
xmlFreeDoc(doc);
return false;
}
xmlCleanupParser();
// Simple parsing (two levels hierarchy)
cur = cur->children;
while(cur)
{
xmlNodePtr child = cur->children;
if(child)
{
xmlNodePtr subargument = child->next;
while(subargument)
{
xmlNodePtr subargumentChild = subargument->children;
if(subargumentChild && subargumentChild->content)
{
this->SetOptionValue((const char*)cur->name,
(const char*)subargument->name,
(const char*)subargumentChild->content,
createMissingArguments
);
}
subargument = subargument->next;
}
if(child->content)
{
this->SetOptionValue((const char*)cur->name,
(const char*)cur->name,
(const char*)child->content,
createMissingArguments);
}
}
cur = cur->next;
}
xmlFreeDoc(doc);
#else
METAIO_STREAM::cout << "LoadArguments(" << filename << ") requires libxml2" << METAIO_STREAM::endl;
if(createMissingArguments)
{
}
#endif
return true;
}
/** Set the value of an option or a field
* This is used when importing command line arguments
* from XML */
bool MetaCommand::SetOptionValue(const char* optionName,
const char* name,
const char* value,
bool createMissingArgument)
{
OptionVector::iterator it = m_OptionVector.begin();
while(it != m_OptionVector.end())
{
if((*it).name == optionName)
{
(*it).userDefined = true;
METAIO_STL::vector<Field> & fields = (*it).fields;
METAIO_STL::vector<Field>::iterator itField = fields.begin();
while(itField != fields.end())
{
if((*itField).name == name)
{
(*itField).userDefined = true;
(*itField).value = value;
return true;
}
itField++;
}
}
it++;
}
if(createMissingArgument)
{
Option option;
option.tag = "";
option.longtag = optionName;
option.name = optionName;
option.required = false;
option.description = "";
option.userDefined = true;
option.complete = false;
Field field;
field.name = name;
field.externaldata = DATA_NONE;
field.type = STRING;
field.value = value;
field.userDefined = true;
field.required = false;
field.rangeMin = "";
field.rangeMax = "";
option.fields.push_back(field);
m_OptionVector.push_back(option);
}
return false;
}
#if (METAIO_USE_NAMESPACE)
};
#endif