-
Notifications
You must be signed in to change notification settings - Fork 17
Support for Aggregate CAS Multiplier #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
1232506
50ddfb0
5d4f657
280b444
6d30b20
8aa5919
d579898
0d635ca
0adb05c
3d4086f
5f7ae16
f5d045b
e3f1b33
2034217
d49a58e
88ba14a
f89eb88
5966b78
df7bf0c
ce9cd6c
7cd9ab9
e07c09f
d4588ba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -103,6 +103,8 @@ namespace uima { | |
| launchDeInit(); | ||
| } | ||
| assert( iv_vecEntries.empty() ); | ||
| if (iv_pFlowController) | ||
| delete iv_pFlowController; | ||
|
|
||
| } | ||
|
|
||
|
|
@@ -152,12 +154,21 @@ namespace uima { | |
| assert(iv_vecEntries.empty()); | ||
|
|
||
| AnnotatorContext & rANC = iv_pEngine->getAnnotatorContext(); | ||
|
|
||
| AnalysisEngineDescription const & crTAESpecifier = rANC.getTaeSpecifier(); // this method must be added | ||
|
|
||
| const AnalysisEngineMetaData* pEngineMetadata = crTAESpecifier.getAnalysisEngineMetaData(); | ||
| assert( ! crTAESpecifier.isPrimitive() ); | ||
| //BSIvector < icu::UnicodeString > const & crVecEngineNames = crTAESpecifier.getAnalysisEngineMetaData()->getFixedFlow()->getNodes(); | ||
| vector < icu::UnicodeString > const & crVecEngineNames = crTAESpecifier.getAnalysisEngineMetaData()->getFlowConstraints()->getNodes(); | ||
|
|
||
| // FIXME: This shouldn't have been necessary since FlowContrainst::getFlowContraintsType | ||
| // should have been const in the first place | ||
| auto flowContraints = CONST_CAST(FlowConstraints *, pEngineMetadata->getFlowConstraints()); | ||
| if (flowContraints->getFlowConstraintsType() == FlowConstraints::FIXED) { | ||
| iv_pFlowController = new FixedFlowController; | ||
| iv_pFlowController->initialize(rANC); | ||
| } | ||
|
|
||
| if (const OperationalProperties* operationalProps = pEngineMetadata->getOperationalProperties()) | ||
| iv_bOutputNewCases = operationalProps->getOutputsNewCASes(); | ||
| vector < icu::UnicodeString > const & crVecEngineNames = flowContraints->getNodes(); | ||
|
|
||
| // for all engines in the flow | ||
| size_t ui; | ||
|
|
@@ -431,11 +442,7 @@ namespace uima { | |
| return bHasTOF; | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
| TyErrorId AnnotatorManager::launchProcessDocument(CAS & cas, ResultSpecification const & crResultSpec) { | ||
| TyErrorId AnnotatorManager::processCapabilityLanguageFlow(CAS &cas, ResultSpecification const &crResultSpec) { | ||
| /* | ||
| This works as follows: | ||
| The passes result spec is copied and for each delegate AE, it is determined | ||
|
|
@@ -486,27 +493,13 @@ namespace uima { | |
| bool requiresTCas=true; | ||
|
|
||
| if (cas.isBackwardCompatibleCas()) { | ||
| tcas = &cas; | ||
| } | ||
| //this populates the tofsToBeRemoved vector so always call it | ||
| callEngine = shouldEngineBeCalled(*pCapContainer, | ||
| resSpec, | ||
| cas.getDocumentAnnotation().getLanguage(), | ||
| tofsToBeRemoved); | ||
| //check the FlowConstraintType specified in the aggregate engine | ||
| //if CapabilityLanguageFlow whether engine is called is | ||
| //determined by shouldEngineBeCalled() | ||
| AnnotatorContext & rANC = iv_pEngine->getAnnotatorContext(); | ||
| AnalysisEngineDescription const & crTAESpecifier = rANC.getTaeSpecifier(); | ||
| FlowConstraints const * pFlow = crTAESpecifier.getAnalysisEngineMetaData()->getFlowConstraints(); | ||
| FlowConstraints * flow = CONST_CAST(FlowConstraints *, pFlow); | ||
| FlowConstraints::EnFlowType flowType = flow->getFlowConstraintsType(); | ||
|
|
||
| //if FixedFlow specified all engines are always called so reset callEngine is true | ||
| if (flowType == FlowConstraints::FIXED) { | ||
| callEngine=true; | ||
| } | ||
|
|
||
| tcas = &cas; | ||
| } | ||
| //this populates the tofsToBeRemoved vector so always call it | ||
| callEngine = shouldEngineBeCalled(*pCapContainer, | ||
| resSpec, | ||
| cas.getDocumentAnnotation().getLanguage(), | ||
| tofsToBeRemoved); | ||
|
|
||
| if ( callEngine ) { | ||
|
|
||
|
|
@@ -583,7 +576,186 @@ namespace uima { | |
| } | ||
|
|
||
| UIMA_ANNOTATOR_TIMING(iv_clTimerLaunchProcess.stop()); | ||
| return(utRetVal); | ||
| return utRetVal; | ||
| } | ||
|
|
||
| CAS *AnnotatorManager::processUntilNextOutputCas() { | ||
| unique_ptr<Flow> flow{}; | ||
| while (true) { | ||
| CAS *currentCas = nullptr; | ||
| Step nextStep; | ||
| flow = nullptr; | ||
|
|
||
| // get a cas from the stack | ||
| if (casIterStack.empty()) | ||
| return nullptr; | ||
|
|
||
| StackFrame &frame = casIterStack.top(); | ||
| try { | ||
| if (frame.casMultiplier && frame.casMultiplier->hasNext()) { | ||
| currentCas = &frame.casMultiplier->next(); | ||
| // compute flow for newly produced CAS | ||
| flow = frame.originalFlow->newCasProduced(*currentCas, frame.lastEngineKey); | ||
| } | ||
| } catch (Exception &exception) { | ||
| if (!frame.originalFlow->continueOnFailure(frame.lastEngineKey /* ,exception */)) | ||
| throw; | ||
| } | ||
|
|
||
| if (!currentCas) { | ||
| // if there is no more output CASes from the stack, take the original CAS that was processed by | ||
| // the CAS Multiplier and continue with its flow | ||
| currentCas = frame.originalCas; | ||
| flow = std::move(frame.originalFlow); | ||
| currentCas->setCurrentComponentInfo(nullptr); | ||
| casIterStack.pop(); | ||
| } | ||
|
|
||
| activeCASes.insert(currentCas); | ||
mac-op marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| if (nextStep.getType() == Step::StepType::UNSPECIFIED) { | ||
| nextStep = flow->next(); // get the next step for the current flow | ||
| } | ||
|
|
||
| while (nextStep.getType() != Step::StepType::FINALSTEP) { | ||
| if (nextStep.getType() == Step::StepType::SIMPLESTEP) { | ||
| // find the AE specified by the step | ||
| const icu::UnicodeString &nextAEKey = nextStep.getSimpleStep()->getEngineName(); | ||
| auto it = std::find_if(iv_vecEntries.begin(), iv_vecEntries.end(), | ||
| [&, nextAEKey](const EngineEntry &entry) { | ||
| return entry.iv_pEngine->getAnnotatorContext().iv_AnCKey == nextAEKey; | ||
| }); | ||
|
|
||
| if (it != iv_vecEntries.end()) { | ||
| AnalysisEngine *nextAE = it->iv_pEngine; | ||
| CAS *outputCas = nullptr; | ||
|
|
||
| // call process one the AE and see if it has produced a new CAS | ||
| try { | ||
| CASIterator casIter = nextAE->processAndOutputNewCASes(*currentCas); | ||
| if (casIter.hasNext()) | ||
| outputCas = &casIter.next(); | ||
| } catch (Exception &e) { | ||
| if (!flow->continueOnFailure(nextAEKey)) | ||
| throw; | ||
| } | ||
|
|
||
| if (outputCas) { | ||
| // new CAS is output so put the current components on the stack so we can process | ||
| // the other output CASes and original CASes later | ||
| std::unique_ptr<Flow> nextFlow = flow->newCasProduced(*outputCas, nextAEKey); | ||
| casIterStack.push({nextAE, currentCas, std::move(flow), nextAEKey}); | ||
| flow = std::move(nextFlow); | ||
| currentCas = outputCas; | ||
| activeCASes.insert(currentCas); | ||
| } else { | ||
| // No new CASes are output, this CAS is done being processed by the current engine. | ||
| currentCas->setCurrentComponentInfo(nullptr); | ||
| } | ||
| } else { | ||
| UIMA_EXC_THROW_NEW(EngineProcessingException, | ||
| UIMA_ERR_USER_ANNOTATOR_COULD_NOT_PROCESS, | ||
| UIMA_MSG_ID_EXCON_PROCESSING_CAS, | ||
| ErrorMessage(UIMA_MSG_ID_LITERAL_STRING, "Unknown Delegate Key " + nextAEKey), | ||
| ErrorInfo::unrecoverable); | ||
| } | ||
| } else if (nextStep.getType() == Step::StepType::PARALLELSTEP) { | ||
| // TODO: ParallelStep not supported yet | ||
| UIMA_EXC_THROW_NEW(NotYetImplementedException, | ||
| UIMA_ERR_NOT_YET_IMPLEMENTED, | ||
| UIMA_MSG_ID_EXC_NOT_YET_IMPLEMENTED, | ||
| ErrorMessage(UIMA_MSG_ID_LITERAL_STRING, "Parallel Step not supported yet"), | ||
| ErrorInfo::unrecoverable | ||
| ); | ||
| } else { | ||
| UIMA_EXC_THROW_NEW(EngineProcessingException, | ||
| UIMA_ERR_USER_ANNOTATOR_COULD_NOT_PROCESS, | ||
| UIMA_MSG_ID_EXCON_PROCESSING_CAS, | ||
| ErrorMessage(UIMA_MSG_ID_LITERAL_STRING, "Unknown Step Type"), | ||
| ErrorInfo::unrecoverable); | ||
| } | ||
|
|
||
| nextStep = flow->next(); | ||
| } | ||
|
|
||
| const FinalStep *finalStep = nextStep.getFinalStep(); | ||
| activeCASes.erase(currentCas); | ||
| if (currentCas == inputCas) { | ||
| if (finalStep->getForceDropCAS()) { | ||
| // Not allowed to drop the input CAS so something must have gone wrong | ||
| UIMA_EXC_THROW_NEW(EngineProcessingException, | ||
| UIMA_ERR_USER_ANNOTATOR_COULD_NOT_PROCESS, | ||
| UIMA_MSG_ID_EXCON_PROCESSING_CAS, | ||
| ErrorMessage(UIMA_MSG_ID_LITERAL_STRING, "Illegal CAS drop"), | ||
| ErrorInfo::unrecoverable); | ||
| } | ||
| return nullptr; | ||
| } | ||
|
|
||
| if (iv_bOutputNewCases && !finalStep->getForceDropCAS()) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to double check I'm understanding the code correctly, this is where the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes the finalStep will determine if that CAS is dropped or not. In this instance that finalStep is constructed by the FixedFlowController and FixedFlowObject, and the default action in the FixedFlowController is DROP_IF_NEW_CAS_PRODUCED |
||
| return currentCas; | ||
| currentCas->release(); | ||
| } | ||
| } | ||
|
|
||
| bool AnnotatorManager::hasNext() { | ||
| if (!nextCas) | ||
| nextCas = processUntilNextOutputCas(); | ||
| return nextCas != nullptr; | ||
| } | ||
|
|
||
| CAS & AnnotatorManager::next() { | ||
| CAS* result = nextCas; | ||
| if (!result) | ||
| result = processUntilNextOutputCas(); | ||
| if (!result) { | ||
| UIMA_EXC_THROW_NEW(Exception, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't this call also
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No when it is returned to the caller/user they will call |
||
| UIMA_ERR_USER_ANNOTATOR_COULD_NOT_PROCESS, | ||
| UIMA_MSG_ID_EXCON_PROCESSING_CAS, | ||
| ErrorMessage(UIMA_MSG_ID_LITERAL_STRING, "There is not next() available."), | ||
| ErrorInfo::unrecoverable); | ||
| } | ||
| nextCas = nullptr; | ||
| return *result; | ||
| } | ||
|
|
||
| void AnnotatorManager::release() { | ||
| while (!casIterStack.empty()) { | ||
| StackFrame& frame = casIterStack.top(); | ||
| frame.originalFlow->aborted(); | ||
| casIterStack.pop(); | ||
| } | ||
| for (CAS *cas : activeCASes) { | ||
| if (cas != inputCas) | ||
| cas->release(); | ||
| } | ||
|
|
||
| activeCASes.clear(); | ||
| } | ||
|
|
||
|
|
||
| TyErrorId AnnotatorManager::launchProcessDocument(CAS &cas, ResultSpecification const &crResultSpec) { | ||
| //if engine uses Capability Language Flow | ||
| // TODO: Turn this logic and processCapabilityLanguageFlow into a separate CapabilityLanguageFlowController class that inherits from FlowController | ||
| AnnotatorContext &rANC = iv_pEngine->getAnnotatorContext(); | ||
| AnalysisEngineDescription const &crTAESpecifier = rANC.getTaeSpecifier(); | ||
| FlowConstraints const *pFlow = crTAESpecifier.getAnalysisEngineMetaData()->getFlowConstraints(); | ||
| FlowConstraints *flow = CONST_CAST(FlowConstraints *, pFlow); | ||
|
|
||
| // Process according to capability language specifications | ||
| if (flow->getFlowConstraintsType() == FlowConstraints::CAPABILITYLANGUAGE) | ||
| return processCapabilityLanguageFlow(cas, crResultSpec); | ||
|
|
||
| inputCas = &cas; | ||
|
|
||
| casIterStack.push({nullptr, inputCas, iv_pFlowController->computeFlow(*inputCas), {}}); | ||
| try { | ||
| nextCas = processUntilNextOutputCas(); | ||
| } catch (...) { | ||
| release(); | ||
| throw; | ||
| } | ||
| return UIMA_ERR_NONE; | ||
| } | ||
|
|
||
| #ifdef UIMA_DEBUG_ANNOTATOR_TIMING | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.