/******************************************************************************* | |
* 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; | |
} |