add support for parser keywords specifying to multiple deck keywords

Say hello to the complete set of well, region, field and group output
specifiers soon...
This commit is contained in:
Andreas Lauser
2014-06-11 16:28:48 +02:00
parent d820a4d435
commit 5f949c11c3
7 changed files with 205 additions and 95 deletions

View File

@@ -120,31 +120,25 @@ namespace Opm {
void Parser::addKeyword(ParserKeywordConstPtr parserKeyword) {
for (auto nameIt = parserKeyword->deckNamesBegin();
nameIt != parserKeyword->deckNamesEnd();
++nameIt)
{
m_parserKeywords[*nameIt] = parserKeyword;
}
const std::string& name = parserKeyword->getName();
dropKeyword( name );
m_parserKeywords.insert(std::make_pair(name, parserKeyword));
if (ParserKeyword::wildCardName(name))
if (ParserKeyword::wildCardName(name))
m_wildCardKeywords.insert( std::make_pair(name , parserKeyword ));
}
ParserKeywordConstPtr Parser::matchingKeyword(const std::string& name) const {
std::map<std::string, ParserKeywordConstPtr>::const_iterator iter = m_wildCardKeywords.begin();
ParserKeywordConstPtr keyword;
while (true) {
if (iter == m_wildCardKeywords.end())
break;
if ((*iter).second->matches(name)) {
keyword = (*iter).second;
break;
}
++iter;
for (auto iter = m_wildCardKeywords.begin(); iter != m_wildCardKeywords.end(); ++iter) {
if (iter->second->matches(name))
return iter->second;
}
return keyword;
return ParserKeywordConstPtr();
}
@@ -174,8 +168,7 @@ namespace Opm {
bool Parser::dropKeyword(const std::string& keyword) {
bool erase = (m_parserKeywords.erase( keyword ) == 1);
if (erase)
m_wildCardKeywords.erase( keyword );
m_wildCardKeywords.erase( keyword );
return erase;
}
@@ -407,7 +400,7 @@ namespace Opm {
}
void Parser::loadKeywordsFromDirectory(const boost::filesystem::path& directory, bool recursive, bool onlyALLCAPS8) {
void Parser::loadKeywordsFromDirectory(const boost::filesystem::path& directory, bool recursive) {
if (!boost::filesystem::exists(directory))
throw std::invalid_argument("Directory: " + directory.string() + " does not exist.");
else {
@@ -415,9 +408,9 @@ namespace Opm {
for (boost::filesystem::directory_iterator iter(directory); iter != end; iter++) {
if (boost::filesystem::is_directory(*iter)) {
if (recursive)
loadKeywordsFromDirectory(*iter, recursive, onlyALLCAPS8);
loadKeywordsFromDirectory(*iter, recursive);
} else {
if (ParserKeyword::validName(iter->path().filename().string()) || !onlyALLCAPS8) {
if (ParserKeyword::validInternalName(iter->path().filename().string())) {
if (!loadKeywordFromFile(*iter))
std::cerr << "** Warning: failed to load keyword from file:" << iter->path() << std::endl;
}

View File

@@ -60,7 +60,7 @@ namespace Opm {
void loadKeywords(const Json::JsonObject& jsonKeywords);
bool loadKeywordFromFile(const boost::filesystem::path& configFile);
void loadKeywordsFromDirectory(const boost::filesystem::path& directory , bool recursive = true, bool onlyALLCAPS8Files = true);
void loadKeywordsFromDirectory(const boost::filesystem::path& directory , bool recursive = true);
size_t size() const;
void applyUnitsToDeck(DeckPtr deck) const;
private:

View File

@@ -35,9 +35,6 @@
namespace Opm {
void ParserKeyword::commonInit(const std::string& name, ParserKeywordSizeEnum sizeType , ParserKeywordActionEnum action) {
if (!validName(name))
throw std::invalid_argument("Invalid name: " + name + "keyword must be all upper case, max 8 characters. Starting with character.");
m_isDataKeyword = false;
m_isTableCollection = false;
m_name = name;
@@ -45,6 +42,8 @@ namespace Opm {
m_record = ParserRecordPtr(new ParserRecord);
m_keywordSizeType = sizeType;
m_Description = "";
m_deckNames.insert(m_name);
}
ParserKeyword::ParserKeyword(const std::string& name, ParserKeywordSizeEnum sizeType, ParserKeywordActionEnum action) {
@@ -65,6 +64,14 @@ namespace Opm {
initSizeKeyword(sizeKeyword, sizeItem);
}
void ParserKeyword::clearDeckNames() {
m_deckNames.clear();
}
void ParserKeyword::addDeckName( const std::string& deckName ) {
m_deckNames.insert(deckName);
}
bool ParserKeyword::hasDimension() const {
return m_record->hasDimension();
}
@@ -128,6 +135,7 @@ namespace Opm {
throw std::invalid_argument("Json object is missing name: property");
initSize(jsonConfig);
initDeckNames(jsonConfig);
if (jsonConfig.has_item("items"))
addItems(jsonConfig);
@@ -138,7 +146,7 @@ namespace Opm {
if (jsonConfig.has_item("description")) {
m_Description = jsonConfig.get_string("description");
}
if ((m_keywordSizeType == FIXED && m_fixedSize == 0) || (m_action != INTERNALIZE))
return;
else {
@@ -214,19 +222,45 @@ namespace Opm {
return false;
}
bool ParserKeyword::validInternalName(const std::string& name) {
if (name.length() < 2)
return false;
else if (!std::isalpha(name[0]))
return false;
bool ParserKeyword::validName(const std::string& name) {
for (size_t i = 1; i < name.length(); i++) {
char c = name[i];
if (!isalnum(c) &&
c != '_')
{
return false;
}
}
return true;
}
bool ParserKeyword::validDeckName(const std::string& name) {
if (!validNameStart(name))
return false;
for (size_t i = 1; i < name.length(); i++) {
char c = name[i];
if (!(isupper(c) || isdigit(c)))
return wildCardName(name);
if (!isupper(c) &&
!isdigit(c) &&
c != '-' &&
c != '+' &&
c != '#')
{
return false;
}
}
return true;
}
bool ParserKeyword::hasMultipleDeckNames() const {
return m_deckNames.size() > 1;
}
void ParserKeyword::addItem(ParserItemConstPtr item) {
if (m_isDataKeyword)
@@ -246,6 +280,27 @@ namespace Opm {
throw std::invalid_argument("Keyword:" + getName() + ". When calling addDataItem() the keyword must be configured with fixed size == 1.");
}
void ParserKeyword::initDeckNames(const Json::JsonObject& jsonObject) {
if (!jsonObject.has_item("deck_names"))
return;
const Json::JsonObject namesObject = jsonObject.get_item("deck_names");
if (!namesObject.is_array())
throw std::invalid_argument("The 'deck_names' JSON item needs to be a list (keyword: '"+m_name+"')");
if (namesObject.size() > 0)
m_deckNames.clear();
for (size_t nameIdx = 0; nameIdx < namesObject.size(); ++ nameIdx) {
const Json::JsonObject nameObject = namesObject.get_array_item(nameIdx);
if (!nameObject.is_string())
throw std::invalid_argument("The items of 'deck_names' need to be strings (keyword: '"+m_name+"')");
addDeckName(nameObject.as_string());
}
}
void ParserKeyword::addItems(const Json::JsonObject& jsonConfig) {
const Json::JsonObject itemsConfig = jsonConfig.get_item("items");
if (itemsConfig.is_array()) {
@@ -402,6 +457,14 @@ namespace Opm {
return m_record->size();
}
ParserKeyword::DeckNameSet::const_iterator ParserKeyword::deckNamesBegin() const {
return m_deckNames.begin();
}
ParserKeyword::DeckNameSet::const_iterator ParserKeyword::deckNamesEnd() const {
return m_deckNames.end();
}
DeckKeywordPtr ParserKeyword::parse(RawKeywordConstPtr rawKeyword) const {
if (rawKeyword->isFinished()) {
DeckKeywordPtr keyword(new DeckKeyword(rawKeyword->getKeywordName()));
@@ -439,16 +502,12 @@ namespace Opm {
}
bool ParserKeyword::matches(const std::string& keyword) const {
size_t cmpLength = m_name.find('*');
if (cmpLength == std::string::npos)
return (keyword == m_name);
else {
if (keyword.length() < cmpLength)
return false;
return (m_name.compare( 0 , cmpLength , keyword , 0 , cmpLength) == 0);
}
bool ParserKeyword::matches(const std::string& deckKeyword) const {
size_t starPos = m_name.find('*');
if (starPos == std::string::npos)
return (m_deckNames.count(deckKeyword) > 0);
else
return (m_name.compare( 0 , starPos , deckKeyword , 0 , starPos) == 0);
}
@@ -504,6 +563,15 @@ namespace Opm {
}
os << indent << lhs << "->setDescription(\"" << getDescription() << "\");" << std::endl;
// add the deck names
os << indent << lhs << "->clearDeckNames();\n";
for (auto deckNameIt = m_deckNames.begin();
deckNameIt != m_deckNames.end();
++deckNameIt)
{
os << indent << lhs << "->addDeckName(\"" << *deckNameIt << "\");" << std::endl;
}
for (size_t i = 0; i < m_record->size(); i++) {
os << indent << "{" << std::endl;
{

View File

@@ -21,8 +21,8 @@
#include <string>
#include <iostream>
#include <memory>
#include <set>
#include <opm/json/JsonObject.hpp>
#include <opm/parser/eclipse/Parser/ParserRecord.hpp>
@@ -55,6 +55,8 @@ namespace Opm {
ParserKeyword(const Json::JsonObject& jsonConfig);
public:
typedef std::set<std::string> DeckNameSet;
/*!
* \brief Factory method to create a keyword where the number
* of items per record is defined at compile time.
@@ -94,9 +96,10 @@ namespace Opm {
*/
static ParserKeywordPtr createFromJson(const Json::JsonObject& jsonConfig);
static bool validName(const std::string& name);
static bool validInternalName(const std::string& name);
static bool validDeckName(const std::string& name);
static bool wildCardName(const std::string& name);
bool matches(const std::string& keyword) const;
bool matches(const std::string& deckKeyword) const;
bool hasDimension() const;
ParserRecordPtr getRecord() const;
const std::string& getName() const;
@@ -108,7 +111,13 @@ namespace Opm {
void setDescription(const std::string &description);
size_t numItems() const;
bool hasMultipleDeckNames() const;
void clearDeckNames();
void addDeckName( const std::string& deckName );
DeckNameSet::const_iterator deckNamesBegin() const;
DeckNameSet::const_iterator deckNamesEnd() const;
DeckKeywordPtr parse(RawKeywordConstPtr rawKeyword) const;
enum ParserKeywordSizeEnum getSizeType() const;
const std::pair<std::string,std::string>& getSizeDefinitionPair() const;
@@ -121,6 +130,7 @@ namespace Opm {
private:
std::pair<std::string,std::string> m_sizeDefinitionPair;
std::string m_name;
DeckNameSet m_deckNames;
ParserRecordPtr m_record;
enum ParserKeywordSizeEnum m_keywordSizeType;
size_t m_fixedSize;
@@ -130,6 +140,7 @@ namespace Opm {
std::string m_Description;
static bool validNameStart(const std::string& name);
void initDeckNames( const Json::JsonObject& jsonConfig );
void initData( const Json::JsonObject& jsonConfig );
void initSize( const Json::JsonObject& jsonConfig );
void initSizeKeyword( const std::string& sizeKeyword, const std::string& sizeItem);

View File

@@ -186,26 +186,31 @@ static void generateKeywordSource(const char * source_file_name , KeywordMapType
//-----------------------------------------------------------------
static void scanKeyword(const boost::filesystem::path& file , KeywordMapType& keywordMap) {
if (ParserKeyword::validName(file.filename().string())) {
Json::JsonObject * jsonKeyword;
try {
jsonKeyword = new Json::JsonObject(file);
} catch(...) {
std::cerr << "Parsing json config file: " << file.string() << " failed - keyword skipped." << std::endl;
return;
}
{
std::pair<std::string , ParserKeywordConstPtr> elm(file.filename().string() , ParserKeyword::createFromJson( *jsonKeyword ));
std::pair<std::string , std::pair<std::string , ParserKeywordConstPtr> > pair(file.string() , elm);
keywordMap.insert(pair);
}
delete jsonKeyword;
if (!ParserKeyword::validInternalName(file.filename().string())) {
std::cerr << "Warning: Ignoring incorrectly named file '" << file.string() << "'.\n";
return;
}
Json::JsonObject * jsonKeyword;
try {
jsonKeyword = new Json::JsonObject(file);
} catch(...) {
std::cerr << "Parsing json config file: " << file.string() << " failed - keyword skipped." << std::endl;
return;
}
{
ParserKeywordConstPtr parserKeyword(ParserKeyword::createFromJson( *jsonKeyword ));
if (parserKeyword->getName() != boost::filesystem::basename(file))
std::cerr << "Warning: The name '" << parserKeyword->getName() << " specified in the JSON definitions of file '" << file
<< "' does not match the file's name!\n";
std::pair<std::string , ParserKeywordConstPtr> elm(file.filename().string(), parserKeyword);
std::pair<std::string , std::pair<std::string , ParserKeywordConstPtr> > pair(file.string() , elm);
keywordMap.insert(pair);
}
delete jsonKeyword;
}
static void scanAllKeywords(const boost::filesystem::path& directory , KeywordMapType& keywordMap) {

View File

@@ -72,17 +72,40 @@ BOOST_AUTO_TEST_CASE(ParserKeyword_wildCardName) {
BOOST_CHECK_EQUAL( false , ParserKeyword::wildCardName("ABCDEFGH*"));
}
BOOST_AUTO_TEST_CASE(ParserKeyword_validName) {
BOOST_CHECK_EQUAL( true , ParserKeyword::validName("SUMMARY"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validName("MixeCase"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validName("NAMETOOLONG"));
BOOST_CHECK_EQUAL( true , ParserKeyword::validName("STRING88"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validName("88STRING"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validName("KEY.EXT"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validName("STRING~"));
BOOST_AUTO_TEST_CASE(ParserKeyword_validDeckName) {
BOOST_CHECK_EQUAL( true , ParserKeyword::validDeckName("SUMMARY"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validDeckName("MixeCase"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validDeckName("NAMETOOLONG"));
BOOST_CHECK_EQUAL( true , ParserKeyword::validDeckName("STRING88"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validDeckName("88STRING"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validDeckName("KEY.EXT"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validDeckName("STRING~"));
BOOST_CHECK_EQUAL( true , ParserKeyword::validDeckName("MINUS-"));
BOOST_CHECK_EQUAL( true , ParserKeyword::validDeckName("PLUS+"));
BOOST_CHECK_EQUAL( true , ParserKeyword::validDeckName("SHARP#"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validDeckName("-MINUS"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validDeckName("+PLUS"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validDeckName("#SHARP"));
BOOST_CHECK_EQUAL( true , ParserKeyword::validName("TVDP*"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validName("*"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validDeckName("TVDP*"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validDeckName("*"));
}
BOOST_AUTO_TEST_CASE(ParserKeyword_validInternalName) {
BOOST_CHECK_EQUAL( true , ParserKeyword::validInternalName("SUMMARY"));
BOOST_CHECK_EQUAL( true , ParserKeyword::validInternalName("MixeCase"));
BOOST_CHECK_EQUAL( true , ParserKeyword::validInternalName("NAMEISQUITELONG"));
BOOST_CHECK_EQUAL( true , ParserKeyword::validInternalName("I_have_underscores"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validInternalName("WHATABOUT+"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validInternalName("ORMINUS-"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validInternalName("NOSHARP#"));
BOOST_CHECK_EQUAL( true , ParserKeyword::validInternalName("STRING88"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validInternalName("88STRING"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validInternalName("KEY.EXT"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validInternalName("STRING~"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validInternalName("TVDP*"));
BOOST_CHECK_EQUAL( false , ParserKeyword::validInternalName("*"));
}
BOOST_AUTO_TEST_CASE(ParserKeywordMathces) {
@@ -145,6 +168,26 @@ BOOST_AUTO_TEST_CASE(ConstructFromJsonObject) {
BOOST_CHECK_EQUAL( true , parserKeyword->hasFixedSize() );
}
BOOST_AUTO_TEST_CASE(ConstructMultiNameFromJsonObject) {
const auto jsonString =
"{"
" \"name\": \"XXX\" ,"
" \"size\" : 0,"
" \"deck_names\" : ["
" \"XXA\","
" \"XXB\","
" \"XXC\""
" ]"
"}";
Json::JsonObject jsonObject(jsonString);
auto parserKeyword = ParserKeyword::createFromJson(jsonObject);
BOOST_CHECK_EQUAL("XXX" , parserKeyword->getName());
BOOST_CHECK(parserKeyword->matches("XXA"));
BOOST_CHECK(parserKeyword->matches("XXB"));
BOOST_CHECK(parserKeyword->hasMultipleDeckNames());
BOOST_CHECK(!parserKeyword->matches("XXD"));
BOOST_CHECK(!parserKeyword->matches("XXX"));
}
BOOST_AUTO_TEST_CASE(ConstructFromJsonObjectWithActionInvalidThrows) {
Json::JsonObject jsonObject("{\"name\": \"XXX\" , \"size\" : 0, \"action\" : \"WhatEver?\"}");
BOOST_CHECK_THROW(ParserKeyword::createFromJson(jsonObject) , std::invalid_argument);
@@ -153,6 +196,8 @@ BOOST_AUTO_TEST_CASE(ConstructFromJsonObjectWithActionInvalidThrows) {
BOOST_AUTO_TEST_CASE(ConstructFromJsonObjectWithAction) {
Json::JsonObject jsonObject("{\"name\": \"XXX\" , \"size\" : 0, \"action\" : \"IGNORE\"}");
ParserKeywordConstPtr parserKeyword = ParserKeyword::createFromJson(jsonObject);
BOOST_CHECK(parserKeyword->matches("XXX"));
BOOST_CHECK(!parserKeyword->hasMultipleDeckNames());
BOOST_CHECK_EQUAL( IGNORE , parserKeyword->getAction() );
}
@@ -310,22 +355,6 @@ BOOST_AUTO_TEST_CASE(ConstructFromJsonObject_WithoutDescription_DescriptionPrope
/* </Json> */
/*****************************************************************/
BOOST_AUTO_TEST_CASE(constructor_nametoolongwithfixedsize_exceptionthrown) {
std::string keyword("KEYWORDTOOLONG");
BOOST_CHECK_THROW(ParserKeyword::createFixedSized(keyword, (size_t) 100), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(constructor_nametoolong_exceptionthrown) {
std::string keyword("KEYWORDTOOLONG");
BOOST_CHECK_THROW(ParserKeyword::createDynamicSized(keyword), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(MixedCase) {
std::string keyword("KeyWord");
BOOST_CHECK_THROW(ParserKeyword::createFixedSized(keyword, (size_t) 100), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(getFixedSize_sizeObjectHasFixedSize_sizeReturned) {
ParserKeywordPtr parserKeyword = ParserKeyword::createFixedSized("JA", (size_t) 3);
BOOST_CHECK_EQUAL(3U, parserKeyword->getFixedSize());

View File

@@ -193,7 +193,7 @@ BOOST_AUTO_TEST_CASE(loadConfigFromDirectory_notRecursive_allNames) {
ParserPtr parser(new Parser(false));
BOOST_CHECK_EQUAL(false , parser->canParseKeyword("BPR"));
boost::filesystem::path configPath("testdata/config/directory1");
BOOST_CHECK_NO_THROW(parser->loadKeywordsFromDirectory( configPath, false , false));
BOOST_CHECK_NO_THROW(parser->loadKeywordsFromDirectory( configPath, false));
BOOST_CHECK(parser->canParseKeyword("WWCT"));
BOOST_CHECK_EQUAL(true , parser->canParseKeyword("BPR"));
BOOST_CHECK_EQUAL(false , parser->canParseKeyword("DIMENS"));
@@ -203,9 +203,11 @@ BOOST_AUTO_TEST_CASE(loadConfigFromDirectory_notRecursive_allNames) {
BOOST_AUTO_TEST_CASE(loadConfigFromDirectory_notRecursive_strictNames) {
ParserPtr parser(new Parser(false));
boost::filesystem::path configPath("testdata/config/directory1");
BOOST_CHECK_NO_THROW(parser->loadKeywordsFromDirectory( configPath, false , true ));
BOOST_CHECK_NO_THROW(parser->loadKeywordsFromDirectory( configPath, false));
BOOST_CHECK(parser->canParseKeyword("WWCT"));
BOOST_CHECK_EQUAL(false , parser->canParseKeyword("BPR"));
// the file name for the following keyword is "Bpr", but that
// does not matter
BOOST_CHECK_EQUAL(true , parser->canParseKeyword("BPR"));
BOOST_CHECK_EQUAL(false , parser->canParseKeyword("DIMENS"));
}
@@ -214,7 +216,7 @@ BOOST_AUTO_TEST_CASE(loadConfigFromDirectory_Recursive_allNames) {
ParserPtr parser(new Parser(false));
BOOST_CHECK_EQUAL(false , parser->canParseKeyword("BPR"));
boost::filesystem::path configPath("testdata/config/directory1");
BOOST_CHECK_NO_THROW(parser->loadKeywordsFromDirectory( configPath, true, false));
BOOST_CHECK_NO_THROW(parser->loadKeywordsFromDirectory( configPath, true));
BOOST_CHECK(parser->canParseKeyword("WWCT"));
BOOST_CHECK_EQUAL(true , parser->canParseKeyword("BPR"));
BOOST_CHECK_EQUAL(true , parser->canParseKeyword("DIMENS"));
@@ -227,7 +229,9 @@ BOOST_AUTO_TEST_CASE(loadConfigFromDirectory_default) {
boost::filesystem::path configPath("testdata/config/directory1");
BOOST_CHECK_NO_THROW(parser->loadKeywordsFromDirectory( configPath ));
BOOST_CHECK(parser->canParseKeyword("WWCT"));
BOOST_CHECK_EQUAL(false , parser->canParseKeyword("BPR"));
// the file name for the following keyword is "Bpr", but that
// does not matter
BOOST_CHECK_EQUAL(true , parser->canParseKeyword("BPR"));
BOOST_CHECK_EQUAL(true , parser->canParseKeyword("DIMENS"));
}