TuringPtr generateTM(const std::string& fileName) {
    TiXmlDocument doc;
    std::string path = DATADIR + fileName;
    if(!doc.LoadFile(path.c_str()))
    {
        throw std::runtime_error("Error generating TM from XML: File not found!");
    }
    TiXmlElement* root = doc.FirstChildElement();
    std::string rootName;
    if(root == NULL)
    {
        throw std::runtime_error("Error generating TM from XML: Failed to load file: No root element.");
        doc.Clear();
    }
    rootName = root->Value();
    if (rootName != "TM") {
        throw std::runtime_error("Error generating TM from XML: Not a Turing Machine XML file!");
    }

    std::set<char> alphabet;
    std::set<char> tapeAlphabet;
    bool allFound = false;
    char blank = 0;
    for(TiXmlElement* elem = root->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement()) {  //find  alphabets and blank symbol
        std::string elemName = elem->Value();
        if (elemName == "InputAlphabet") {
            for(TiXmlElement* elemOfSigma = elem->FirstChildElement(); elemOfSigma != NULL; elemOfSigma = elemOfSigma->NextSiblingElement()) {
                std::string elemOfSigmaName = elemOfSigma->Value();
                if (elemOfSigmaName == "symbol") {
                    TiXmlNode* e = elemOfSigma->FirstChild();
                    TiXmlText* text = e->ToText();
                    if(text == NULL)
                        continue;
                    std::string t = text->Value();
                    if (t.size() != 1)
                        throw std::runtime_error("Error generating TM from XML: One input symbol per node please");
                    alphabet.insert(t.front());
                }
            }
        }
        if (elemName == "TapeAlphabet") {
            for(TiXmlElement* elemOfGamma = elem->FirstChildElement(); elemOfGamma != NULL; elemOfGamma = elemOfGamma->NextSiblingElement()) {
                std::string elemOfGammaName = elemOfGamma->Value();
                if (elemOfGammaName == "symbol") {
                    TiXmlNode* e = elemOfGamma->FirstChild();
                    TiXmlText* text = e->ToText();
                    if(text == NULL)
                        continue;
                    std::string t = text->Value();
                    if (t.size() != 1) {
                        throw std::runtime_error("Error generating TM from XML: One input symbol per node please");
                    }
                    tapeAlphabet.insert(t.front());
                }
            }
        }
        if (elemName == "Blank") {
            TiXmlNode* e = elem->FirstChild();
            TiXmlText* text = e->ToText();
            if(text == NULL)
                continue;
            std::string t = text->Value();
            if (t.size() != 1) {
                 throw std::runtime_error("Error generating TM from XML: One blank symbol please");
            }
            blank = t.front();
        }
        if (tapeAlphabet.size() && alphabet.size() && blank) { //All arguments necessary to construct TM found
            allFound = true;
            break;
        }
    }
    if (!allFound) {
         throw std::runtime_error("Error generating TM from XML: Alphabet, tape alphabet or blank symbol missing!");
        return nullptr;
    }
    TuringPtr TM(new TuringMachine(alphabet, tapeAlphabet, blank));

    for(TiXmlElement* elem = root->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement()) {  //find  alphabets and blank symbol
        std::string elemName = elem->Value();
        if (elemName == "States") {
            const char* attr = elem->Attribute("storage");
            bool hasStorage = false;
            std::vector<std::vector<char>> storages;
            if (attr) {
                std::string statesAttr(attr);
                if (statesAttr == "true")
                    hasStorage = true;
            }
            if (hasStorage) {
                for(TiXmlElement* elemOfQ = elem->FirstChildElement(); elemOfQ != NULL; elemOfQ = elemOfQ->NextSiblingElement()) {
                    std::string elemOfQName = elemOfQ->Value();
                    if (elemOfQName == "storage") {
                        if (elemOfQ->FirstChild() == NULL) {
                            storages.push_back(std::vector<char> ());
                            continue;
                        }
                        TiXmlNode* e = elemOfQ->FirstChild();
                        TiXmlText* text = e->ToText();
                        if(text == NULL)
                            continue;
                        std::string t = text->Value();
                        std::vector<char> thisStorage;
                        for (auto i : t)
                            thisStorage.push_back(i);
                        storages.push_back(thisStorage);
                    }
                }
            }
            for(TiXmlElement* elemOfQ = elem->FirstChildElement(); elemOfQ != NULL; elemOfQ = elemOfQ->NextSiblingElement()) {
                bool isStarting = false;
                bool isAccepting = false;
                std::string elemOfQName = elemOfQ->Value();
                if (elemOfQName == "state") {
                    const char* attr = elemOfQ->Attribute("start");
                    if (attr) {
                        std::string stateAttr(attr);
                        if (stateAttr == "true")
                            isStarting = true;
                    }
                    attr = elemOfQ->Attribute("accept");
                    if (attr) {
                        std::string stateAttr(attr);
                        if (stateAttr == "true")
                            isAccepting = true;
                    }
                    if (elemOfQ->FirstChild() == NULL) {
                         throw std::runtime_error("Error generating TM from XML: State without name");
                    }
                    TiXmlNode* e = elemOfQ->FirstChild();
                    TiXmlText* text = e->ToText();
                    if(text == NULL)
                        continue;
                    std::string t = text->Value();
                    if (!hasStorage)
                        TM->addState(t, isStarting, isAccepting);
                    else
                        for (auto i : storages)
                            TM->addState(t, isStarting, isAccepting, i);
                }
            }
        }
        if (elemName == "Transitions") {
            for(TiXmlElement* elemOfDelta = elem->FirstChildElement(); elemOfDelta != NULL; elemOfDelta = elemOfDelta->NextSiblingElement()) {
                std::string elemOfDeltaName = elemOfDelta->Value();
                if (elemOfDeltaName == "transition") {
                    std::string from = "";
                    std::string to = "";
                    std::vector<char> fromStorage;
                    std::vector<char> toStorage;
                    std::vector<char> read;
                    std::vector<char> write;
                    Direction dir = U;
                    for(TiXmlElement* elemOfTransition = elemOfDelta->FirstChildElement(); elemOfTransition != NULL; elemOfTransition = elemOfTransition->NextSiblingElement()) {
                        std::string elemOfTransitionName = elemOfTransition->Value();
                        if (elemOfTransitionName == "from") {
                            if (elemOfTransition->FirstChild() == NULL) {
                                continue;
                            }
                            TiXmlNode* e = elemOfTransition->FirstChild();
                            TiXmlText* text = e->ToText();
                            if(text == NULL)
                                continue;
                            std::string t = text->Value();
                            from = t;
                        }
                        if (elemOfTransitionName == "to") {
                            if (elemOfTransition->FirstChild() == NULL) {
                                continue;
                            }
                            TiXmlNode* e = elemOfTransition->FirstChild();
                            TiXmlText* text = e->ToText();
                            if(text == NULL)
                                continue;
                            std::string t = text->Value();
                            to = t;
                        }
                        if (elemOfTransitionName == "fromStorage") {
                            if (elemOfTransition->FirstChild() == NULL) {
                                continue;
                            }
                            TiXmlNode* e = elemOfTransition->FirstChild();
                            TiXmlText* text = e->ToText();
                            if(text == NULL)
                                continue;
                            std::string t = text->Value();
                            for (auto i : t)
                                fromStorage.push_back(i);
                        }
                        if (elemOfTransitionName == "toStorage") {
                            if (elemOfTransition->FirstChild() == NULL) {
                                continue;
                            }
                            TiXmlNode* e = elemOfTransition->FirstChild();
                            TiXmlText* text = e->ToText();
                            if(text == NULL)
                                continue;
                            std::string t = text->Value();
                            for (auto i : t)
                                toStorage.push_back(i);
                        }
                        if (elemOfTransitionName == "read") {
                            if (elemOfTransition->FirstChild() == NULL) {
                                continue;
                            }
                            TiXmlNode* e = elemOfTransition->FirstChild();
                            TiXmlText* text = e->ToText();
                            if(text == NULL)
                                continue;
                            std::string t = text->Value();
                            for (auto i : t)
                                read.push_back(i);
                        }
                        if (elemOfTransitionName == "write") {
                            if (elemOfTransition->FirstChild() == NULL) {
                                continue;
                            }
                            TiXmlNode* e = elemOfTransition->FirstChild();
                            TiXmlText* text = e->ToText();
                            if(text == NULL)
                                continue;
                            std::string t = text->Value();
                            for (auto i : t)
                                write.push_back(i);
                        }
                        if (elemOfTransitionName == "dir") {
                            if (elemOfTransition->FirstChild() == NULL) {
                                continue;
                            }
                            TiXmlNode* e = elemOfTransition->FirstChild();
                            TiXmlText* text = e->ToText();
                            if(text == NULL)
                                continue;
                            std::string t = text->Value();
                            if (t == "L")
                                dir = L;
                            else if (t == "R")
                                dir = R;
                            else
                                throw std::runtime_error("Error generating TM from XML: invalid direction" );
                        }
                    }
                    if (from.size() && to.size() && read.size() && write.size() && (dir == L || dir == R))
                        TM->addTransition(from, to, read, write, dir, fromStorage, toStorage);
                    else
                         throw std::runtime_error("Error generating TM from XML: Incomplete transition");
                }
            }

        }

    }
    for(TiXmlElement* elem = root->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement()) {  //find  alphabets and blank symbol
        std::string elemName = elem->Value();
        if (elemName == "StartState") {
            std::string stateName = "";
            std::vector<char> storage;
            for(TiXmlElement* elemOfSS = elem->FirstChildElement(); elemOfSS != NULL; elemOfSS = elemOfSS->NextSiblingElement()) {
                std::string elemOfSSName = elemOfSS->Value();
                if (elemOfSSName == "name") {
                    if (elemOfSS->FirstChild() == NULL) {
                        continue;
                    }
                    TiXmlNode* e = elemOfSS->FirstChild();
                    TiXmlText* text = e->ToText();
                    if(text == NULL)
                        continue;
                    stateName = text->Value();
                }
                if (elemOfSSName == "storage") {
                    if (elemOfSS->FirstChild() == NULL) {
                        continue;
                    }
                    TiXmlNode* e = elemOfSS->FirstChild();
                    TiXmlText* text = e->ToText();
                    if(text == NULL)
                        continue;
                    std::string t = text->Value();

                    for (auto i : t)
                        storage.push_back(i);
                }
            }
            if (stateName.size() != 0) {
                if (storage.size() == 0)
                    TM->indicateStartState(stateName);
                else
                    TM->indicateStartState(stateName, storage);
            }
            else
                throw std::runtime_error("Error generating TM from XML: No name for start state specified");
        }
        if (elemName == "AcceptingStates") {
            for(TiXmlElement* elemOfAccepting = elem->FirstChildElement(); elemOfAccepting != NULL; elemOfAccepting = elemOfAccepting->NextSiblingElement()) {
                std::string elemOfAcceptingName = elemOfAccepting->Value();
                if (elemOfAcceptingName == "state") {
                    std::string stateName = "";
                    std::vector<char> storage;
                    for(TiXmlElement* elemOfAccState = elemOfAccepting->FirstChildElement(); elemOfAccState != NULL; elemOfAccState = elemOfAccState->NextSiblingElement()) {
                        std::string elemOfAccStateName = elemOfAccState->Value();
                        if (elemOfAccStateName == "name") {
                            if (elemOfAccState->FirstChild() == NULL) {
                                continue;
                            }
                            TiXmlNode* e = elemOfAccState->FirstChild();
                            TiXmlText* text = e->ToText();
                            if(text == NULL)
                                continue;
                            stateName = text->Value();
                        }
                        if (elemOfAccStateName == "storage") {
                            if (elemOfAccState->FirstChild() == NULL) {
                                continue;
                            }
                            TiXmlNode* e = elemOfAccState->FirstChild();
                            TiXmlText* text = e->ToText();
                            if(text == NULL)
                                continue;
                            std::string t = text->Value();

                            for (auto i : t)
                                storage.push_back(i);
                        }
                    }
                    if (stateName.size() != 0) {
                        if (storage.size() == 0)
                            TM->indicateAcceptingState(stateName);
                        else
                            TM->indicateAcceptingState(stateName, storage);

                    }
                    else
                        throw std::runtime_error("Error generating TM from XML: No name for accepting state specified");
                }
            }
        }
    }
    return TM;
}
/*
 * Retrieve a specific instance given an object path
 */
wbem::framework::Instance* wbem::support::DiagnosticCompletionRecordFactory::getInstance(
		framework::ObjectPath &path, framework::attribute_names_t &attributes)
throw (wbem::framework::Exception)
{
	LogEnterExit logging(__FUNCTION__, __FILE__, __LINE__);

	// create the instance, initialize with attributes from the path
	framework::Instance *pInstance = new framework::Instance(path);
	try
	{
		checkAttributes(attributes);

		// gather results
		bool diagFound = false;
		wbem::support::diagnosticResults_t results;
		DiagnosticLogFactory::gatherDiagnosticResults(&results);

		// match the instance ID
		framework::Attribute instanceID = path.getKeyValue(INSTANCEID_KEY);
		for (diagnosticResults_t::iterator iter = results.begin(); iter != results.end(); iter++)
		{
			struct diagnosticResult diag = *iter;
			std::stringstream instanceIdStr;
			instanceIdStr << DIAGNOSTICCOMPLETION_INSTANCEID << diag.id;
			if (instanceID.stringValue() == instanceIdStr.str())
			{
				diagFound = true;

				// ServiceName = Diagnostic Test Name
				if (containsAttribute(SERVICENAME_KEY, attributes))
				{
					std::string testName;
					switch (diag.type)
					{
						case EVENT_TYPE_DIAG_QUICK:
							testName = NVDIMMDIAGNOSTIC_TEST_QUICK;
							break;
						case EVENT_TYPE_DIAG_PLATFORM_CONFIG:
							testName = NVDIMMDIAGNOSTIC_TEST_PLATFORM;
							break;
						case EVENT_TYPE_DIAG_PM_META:
							testName = NVDIMMDIAGNOSTIC_TEST_STORAGE;
							break;
						case EVENT_TYPE_DIAG_SECURITY:
							testName = NVDIMMDIAGNOSTIC_TEST_SECURITY;
							break;
						case EVENT_TYPE_DIAG_FW_CONSISTENCY:
							testName = NVDIMMDIAGNOSTIC_TEST_SETTING;
							break;
						default:
							testName = "Unknown";
							break;
					}
					framework::Attribute serviceNameAttr(testName, false);
					pInstance->setAttribute(SERVICENAME_KEY, serviceNameAttr, attributes);
				}

				// ManagedElementName - Intel NVDIMM + UUID
				if (containsAttribute(MANAGEDELEMENTNAME_KEY, attributes))
				{
					std::string elementName = "";
					if (diag.device_uid)
					{
						NVM_UID uid_str;
						uid_copy(diag.device_uid, uid_str);
						elementName = wbem::physical_asset::NVDIMM_ELEMENTNAME_prefix + uid_str;
					}

					framework::Attribute dimmAttr(elementName, false);
					pInstance->setAttribute(MANAGEDELEMENTNAME_KEY, dimmAttr, attributes);
				}

				// CreationTimeStamp - record time stamp
				if (containsAttribute(CREATIONTIMESTAMP_KEY, attributes))
				{
					framework::Attribute timeAttr(diag.time,
									wbem::framework::DATETIME_SUBTYPE_DATETIME, false);
					pInstance->setAttribute(CREATIONTIMESTAMP_KEY, timeAttr, attributes);
				}

				// ErrorCode - Array of diagnostic result messages
				if (containsAttribute(ERRORCODE_KEY, attributes))
				{
					framework::Attribute msgsAttr(diag.messages, false);
					pInstance->setAttribute(ERRORCODE_KEY, msgsAttr, attributes);
				}

				// CompletionState - Combined result of diagnostic
				if (containsAttribute(COMPLETIONSTATE_KEY, attributes))
				{
					std::string stateStr;
					switch (diag.result)
					{
						case DIAGNOSTIC_RESULT_OK:
							stateStr = "OK";
							break;
						case DIAGNOSTIC_RESULT_WARNING:
							stateStr = "Warning";
							break;
						case DIAGNOSTIC_RESULT_FAILED:
							stateStr = "Failed";
							break;
						case DIAGNOSTIC_RESULT_ABORTED:
							stateStr = "Aborted";
							break;
						case DIAGNOSTIC_RESULT_UNKNOWN:
						default:
							stateStr = "Unknown";
							break;
					}
					framework::Attribute stateAttr((NVM_UINT16)diag.result, stateStr, false);
					pInstance->setAttribute(COMPLETIONSTATE_KEY, stateAttr, attributes);
				}

				break;
			} // end record found
		} // for

		if (!diagFound)
		{
			throw framework::ExceptionBadParameter(INSTANCEID_KEY.c_str());
		}
	}
	catch (framework::Exception) // clean up and re-throw
	{
		delete pInstance;
		throw;
	}

	return pInstance;
}