| /******************************************************************************* | |
| * Copyright (c) 2015 - 2016 fortiss GmbH, 2018 TU Wien/ACIN | |
| * This program and the accompanying materials are made available under the | |
| * terms of the Eclipse Public License 2.0 which is available at | |
| * http://www.eclipse.org/legal/epl-2.0. | |
| * | |
| * SPDX-License-Identifier: EPL-2.0 | |
| * | |
| * Contributors: | |
| * Alois Zoitl | |
| * - initial implementation and rework communication infrastructure | |
| * Martin Jobst - adapt for LUA integration | |
| * Martin Melik Merkumians | |
| * - implementation for checkForActionEquivalentState | |
| *******************************************************************************/ | |
| #include "fbcontainer.h" | |
| #include "funcbloc.h" | |
| using namespace forte::core; | |
| EMGMResponse checkForActionEquivalentState(const CFunctionBlock &paFB, const EMGMCommandType paCommand){ | |
| CFunctionBlock::E_FBStates currentState = paFB.getState(); | |
| switch (paCommand){ | |
| case cg_nMGM_CMD_Stop: | |
| return (CFunctionBlock::e_KILLED == currentState) ? e_RDY : e_INVALID_STATE; | |
| break; | |
| case cg_nMGM_CMD_Kill: | |
| return (CFunctionBlock::e_STOPPED == currentState || CFunctionBlock::e_IDLE == currentState) ? e_RDY : e_INVALID_STATE; | |
| break; | |
| default: | |
| break; | |
| } | |
| return e_INVALID_STATE; | |
| } | |
| CFBContainer::CFBContainer(CStringDictionary::TStringId paContainerName, CFBContainer *paParent) : | |
| mContainerName(paContainerName), mParent(paParent) { | |
| } | |
| CFBContainer::~CFBContainer() { | |
| for (TFunctionBlockList::Iterator itRunner(mFunctionBlocks.begin()); itRunner != mFunctionBlocks.end(); ++itRunner) { | |
| CTypeLib::deleteFB(*itRunner); | |
| } | |
| mFunctionBlocks.clearAll(); | |
| for (TFBContainerList::Iterator itRunner(mSubContainers.begin()); itRunner != mSubContainers.end(); ++itRunner) { | |
| delete (*itRunner); | |
| } | |
| mSubContainers.clearAll(); | |
| } | |
| EMGMResponse CFBContainer::addFB(CFunctionBlock* pa_poFuncBlock){ | |
| EMGMResponse eRetVal = e_INVALID_OBJECT; | |
| if(0 != pa_poFuncBlock){ | |
| mFunctionBlocks.pushBack(pa_poFuncBlock); | |
| eRetVal = e_RDY; | |
| } | |
| return eRetVal; | |
| } | |
| EMGMResponse CFBContainer::createFB(forte::core::TNameIdentifier::CIterator &paNameListIt, CStringDictionary::TStringId paTypeName, CResource *paRes){ | |
| EMGMResponse retval = e_INVALID_STATE; | |
| if(paNameListIt.isLastEntry()){ | |
| // test if the container does not contain any FB or a container with the same name | |
| if((0 == getFB(*paNameListIt)) && (0 == getFBContainer(*paNameListIt))){ | |
| CFunctionBlock *newFB = CTypeLib::createFB(*paNameListIt, paTypeName, paRes); | |
| if(0 != newFB){ | |
| //we could create a FB now add it to the list of contained FBs | |
| mFunctionBlocks.pushBack(newFB); | |
| retval = e_RDY; | |
| } | |
| else{ | |
| retval = CTypeLib::getLastError(); | |
| } | |
| } | |
| } | |
| else{ | |
| //we have more than one name in the fb name list. Find or create the container and hand the create command to this container. | |
| CFBContainer *childCont = findOrCreateContainer(*paNameListIt); | |
| if(0 != childCont){ | |
| //remove the container from the name list | |
| ++paNameListIt; | |
| retval = childCont->createFB(paNameListIt, paTypeName, paRes); | |
| } | |
| } | |
| return retval; | |
| } | |
| EMGMResponse CFBContainer::deleteFB(forte::core::TNameIdentifier::CIterator &paNameListIt){ | |
| EMGMResponse retval = e_NO_SUCH_OBJECT; | |
| if(!paNameListIt.isLastEntry()){ | |
| //we have more than one name in the fb name list. Find or create the container and hand the create command to this container. | |
| CFBContainer *childCont = findOrCreateContainer(*paNameListIt); | |
| if(0 != childCont){ | |
| //remove the container from the name list | |
| ++paNameListIt; | |
| retval = childCont->deleteFB(paNameListIt); | |
| } | |
| } | |
| else{ | |
| CStringDictionary::TStringId fBNameId = *paNameListIt; | |
| if((CStringDictionary::scm_nInvalidStringId != fBNameId) && (!mFunctionBlocks.isEmpty())){ | |
| TFunctionBlockList::Iterator itRunner = mFunctionBlocks.begin(); | |
| TFunctionBlockList::Iterator itRefNode = mFunctionBlocks.end(); | |
| while(itRunner != mFunctionBlocks.end()){ | |
| if(fBNameId == (*itRunner)->getInstanceNameId()){ | |
| if((*itRunner)->isCurrentlyDeleteable()){ | |
| CTypeLib::deleteFB(*itRunner); | |
| if(itRefNode == mFunctionBlocks.end()){ | |
| //we have the first entry in the list | |
| mFunctionBlocks.popFront(); | |
| } | |
| else{ | |
| mFunctionBlocks.eraseAfter(itRefNode); | |
| } | |
| retval = e_RDY; | |
| } | |
| else{ | |
| retval = e_INVALID_STATE; | |
| } | |
| break; | |
| } | |
| itRefNode = itRunner; | |
| ++itRunner; | |
| } | |
| } | |
| } | |
| return retval; | |
| } | |
| CFunctionBlock *CFBContainer::getFB(CStringDictionary::TStringId paFBName) { | |
| CFunctionBlock *retVal = 0; | |
| if(CStringDictionary::scm_nInvalidStringId != paFBName){ | |
| for(TFunctionBlockList::Iterator it = mFunctionBlocks.begin(); it != mFunctionBlocks.end(); | |
| ++it){ | |
| if(paFBName == ((*(*it)).getInstanceNameId())){ | |
| retVal = (*it); | |
| break; | |
| } | |
| } | |
| } | |
| return retVal; | |
| } | |
| CFunctionBlock* CFBContainer::getContainedFB(forte::core::TNameIdentifier::CIterator &paNameListIt) { | |
| if(!paNameListIt.isLastEntry()){ | |
| //we have more than one name in the fb name list. Find or create the container and hand the create command to this container. | |
| CFBContainer *childCont = getFBContainer(*paNameListIt); | |
| if(0 != childCont){ | |
| //remove the container from the name list | |
| ++paNameListIt; | |
| return childCont->getContainedFB(paNameListIt); | |
| } | |
| } | |
| return getFB(*paNameListIt); | |
| } | |
| CFBContainer *CFBContainer::getFBContainer(CStringDictionary::TStringId paContainerName) { | |
| CFBContainer *retVal = 0; | |
| if(CStringDictionary::scm_nInvalidStringId != paContainerName){ | |
| for(TFBContainerList::Iterator it = mSubContainers.begin(); it != mSubContainers.end(); | |
| ++it){ | |
| if(paContainerName == ((*(*it)).getName())){ | |
| retVal = (*it); | |
| break; | |
| } | |
| } | |
| } | |
| return retVal; | |
| } | |
| CFBContainer *CFBContainer::findOrCreateContainer(CStringDictionary::TStringId paContainerName){ | |
| CFBContainer *retVal = getFBContainer(paContainerName); | |
| if(0 == retVal && 0 == getFB(paContainerName)) { | |
| //the container with the given name does not exist but only create it if there is no FB with the same name. | |
| retVal = new CFBContainer(paContainerName, this); | |
| mSubContainers.pushBack(retVal); | |
| } | |
| return retVal; | |
| } | |
| EMGMResponse CFBContainer::changeContainedFBsExecutionState(EMGMCommandType paCommand){ | |
| EMGMResponse retVal = e_RDY; | |
| for(TFBContainerList::Iterator it(mSubContainers.begin()); | |
| ((it != mSubContainers.end()) && (e_RDY == retVal)); | |
| ++it){ | |
| retVal = (*it)->changeContainedFBsExecutionState(paCommand); | |
| } | |
| if(e_RDY == retVal){ | |
| for(TFunctionBlockList::Iterator itRunner(mFunctionBlocks.begin()); | |
| ((itRunner != mFunctionBlocks.end()) && (e_RDY == retVal)); | |
| ++itRunner){ | |
| retVal = (*itRunner)->changeFBExecutionState(paCommand); | |
| if(e_RDY != retVal) { | |
| retVal = checkForActionEquivalentState(*(*itRunner), paCommand); | |
| } | |
| } | |
| } | |
| return retVal; | |
| } |