/** * @file * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) * @copyright Simplified BSD * * @cond * This program is free software: you can redistribute it and/or modify * it under the terms of the FreeBSD license as published by the FreeBSD * project. * * 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. * * You should have received a copy of the FreeBSD license along with this * program. If not, see . * @endcond */ #ifndef FLATSTATEIDENTIFIER_H_E9534AF9 #define FLATSTATEIDENTIFIER_H_E9534AF9 #include "uscxml/Common.h" #include "uscxml/Convenience.h" #include "uscxml/DOMUtils.h" #include #include #include #include #include #include namespace uscxml { class USCXML_API FlatStateIdentifier { public: operator bool() const { return stateId.length() > 0; } bool operator<( const FlatStateIdentifier& other) const { return stateId < other.stateId; } FlatStateIdentifier(const Arabica::XPath::NodeSet& activeStates, const Arabica::XPath::NodeSet& alreadyEnteredStates, const std::map >& historyStates) { for (int i = 0; i < activeStates.size(); i++) { active.push_back(ATTR_CAST(activeStates[i], "id")); } for (int i = 0; i < alreadyEnteredStates.size(); i++) { const Arabica::DOM::NodeList& children = alreadyEnteredStates[i].getChildNodes(); bool isRelevant = false; for (int j = 0; j < children.getLength(); j++) { if (children.item(j).getNodeType() != Arabica::DOM::Node_base::ELEMENT_NODE) continue; if (iequals(LOCALNAME_CAST(children.item(j)), "data") || iequals(LOCALNAME_CAST(children.item(j)), "datamodel")) { isRelevant = true; break; } } if (isRelevant) visited.push_back(ATTR_CAST(alreadyEnteredStates[i], "id")); } std::map >::const_iterator histIter; for (histIter = historyStates.begin(); histIter != historyStates.end(); histIter++) { for (int i = 0; i < histIter->second.size(); i++) { histories[histIter->first].push_back(ATTR_CAST(histIter->second[i], "id")); } } initStateId(); } FlatStateIdentifier(const std::list& active, const std::list& visited, const std::map >& histories) : active(active), visited(visited), histories(histories) { initStateId(); } static std::string toStateId(const std::list active, const std::list visited = std::list(), const std::map > histories = std::map >()) { FlatStateIdentifier tmp(active, visited, histories); return tmp.getStateId(); } static std::string toStateId(const Arabica::XPath::NodeSet activeStates, const Arabica::XPath::NodeSet alreadyEnteredStates = Arabica::XPath::NodeSet(), const std::map > historyStates = std::map >()) { FlatStateIdentifier tmp(activeStates, alreadyEnteredStates, historyStates); return tmp.getStateId(); } FlatStateIdentifier(const std::string& identifier) : stateId(identifier) { std::string parsedName; // parse unique state identifier std::stringstream elemNameSS(identifier); std::string section; while(std::getline(elemNameSS, section, ';')) { if (boost::starts_with(section, "active:{")) { // active:{s0,s1,s2} std::stringstream stateSS(section.substr(8, section.size() - 9)); std::string state; while(std::getline(stateSS, state, ',')) { size_t closingBracketPos = state.find("}"); if (closingBracketPos != std::string::npos) { state = state.substr(0, closingBracketPos); } boost::trim(state); if (state.length() > 0) { active.push_back(state); } } } else if (boost::starts_with(section, "visited:{")) { // entered:{s0,s1,s2} std::stringstream stateSS(section.substr(9, section.size() - 10)); std::string state; while(std::getline(stateSS, state, ',')) { size_t closingBracketPos = state.find("}"); if (closingBracketPos != std::string::npos) { state = state.substr(0, closingBracketPos); } boost::trim(state); if (state.length() > 0) { visited.push_back(state); } } } else if (boost::starts_with(section, "history:{")) { // history:{h0:{s1,s2},h1:{s2,s3}} std::string histEntries(section.substr(9, section.length() - 10)); std::string state; size_t start = 0; size_t history = 0; while((history = histEntries.find(":", start)) != std::string::npos) { std::string histName = histEntries.substr(start, history - start); history++; size_t end = histEntries.find("}", start); if (end == std::string::npos) continue; std::stringstream stateSS(histEntries.substr(history + 1, end - history - 1)); std::string state; while(std::getline(stateSS, state, ',')) { size_t closingBracketPos = state.find("}"); if (closingBracketPos != std::string::npos) { state = state.substr(0, closingBracketPos); } boost::trim(state); if (state.length() > 0) { histories[histName].push_back(state); } } start = end + 2; } } } initStateId(); } const std::string& getStateId() const { return stateId; } const std::list& getActive() const { return active; } const std::string& getFlatActive() const { return flatActive; } const std::string& getFlatHistory() const { return flatHistories; } const std::list& getVisited() const { return visited; } const std::string& getFlatVisited() const { return flatVisited; } const std::map > & getHistory() const { return histories; } const std::map > getHistorySets() { std::map > histSet; std::map >::const_iterator histIter = histories.begin(); while(histIter != histories.end()) { histSet[histIter->first].insert(histIter->second.begin(), histIter->second.end()); histIter++; } return histSet; } protected: std::list active; std::list visited; std::map > histories; std::string flatActive; std::string flatVisited; std::string flatHistories; std::string stateId; void initStateId() { std::stringstream stateIdSS; std::string seperator; std::stringstream flatActiveSS; flatActiveSS << "active:{"; for (std::list::const_iterator actIter = active.begin(); actIter != active.end(); actIter++) { flatActiveSS << seperator << *actIter; seperator = ","; } flatActiveSS << "}"; flatActive = flatActiveSS.str(); stateIdSS << flatActive; if (visited.size() > 0) { std::stringstream flatVisitedSS; seperator = ""; flatVisitedSS << "visited:{"; for (std::list::const_iterator visitIter = visited.begin(); visitIter != visited.end(); visitIter++) { flatVisitedSS << seperator << *visitIter; seperator = ","; } flatVisitedSS << "}"; flatVisited = flatVisitedSS.str(); stateIdSS << ";" << flatVisited; } if (histories.size() > 0) { std::stringstream flatHistorySS; seperator = ""; flatHistorySS << "history:{"; for (std::map >::const_iterator histIter = histories.begin(); histIter != histories.end(); histIter++) { flatHistorySS << seperator << histIter->first << ":{"; seperator = ","; std::string itemSeperator; for (std::list::const_iterator histItemIter = histIter->second.begin(); histItemIter != histIter->second.end(); histItemIter++) { flatHistorySS << itemSeperator << *histItemIter; itemSeperator = ","; } flatHistorySS << "}"; } flatHistorySS << "}"; flatHistories = flatHistorySS.str(); stateIdSS << ";" << flatHistories; } stateId = stateIdSS.str(); } #if 0 std::string activeId() { std::stringstream activeSS; activeSS << "active-"; for (std::list::const_iterator activeIter = active.begin(); activeIter != active.end(); activeIter++) { activeSS << *activeIter << "-"; } return activeSS.str(); } #endif }; } #endif /* end of include guard: FLATSTATEIDENTIFIER_H_E9534AF9 */