TyErrorId AnnotatorManager::launchProcessDocument()

in src/framework/annotator_mgr.cpp [438:587]


    TyErrorId AnnotatorManager::launchProcessDocument(CAS & cas, ResultSpecification const & crResultSpec) {
      /*
      This works as follows:
      The passes result spec is copied and for each delegate AE, it is determined
      (via shouldEngineBeCalled()) which TOFs of the result spec should be passed to the
      TAE (if it should be called at all). After the call to the delegate, those TOFs are
      removed from the copied result spec. At the end, this result spec is then empty (ideally).

      Note that for this to work, you have to add all needed intermediate results to the process()
      call on the TAE even if those are not the results the application is interested in.
      E.g., if I have a tokenizer and a summarizer and my aplication is only interested in summaries,
      it nonetheless must sepcify that it needs tokens, sentences, and paragraphs because this is what
      the summarizer needs as input.
      */
      util::Trace                 clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ANNOTATOR_MGR);
      UIMA_ANNOTATOR_TIMING(iv_clTimerLaunchProcess.start());
      TyAnnotatorEntries::iterator it;
      TyErrorId               utErrorId = UIMA_ERR_NONE;
      TyErrorId               utRetVal = UIMA_ERR_NONE;
      assert( EXISTS(iv_pEngine) );
      size_t                     uiNbrOfSkippedAnnotators = 0;
      CAS * tcas=NULL;

      // copy the result spec
      ResultSpecification resSpec = crResultSpec;

      ++iv_uiNbrOfDocsProcessed;
      assert(iv_bIsInitialized);

      assert(!iv_vecEntries.empty());
      for (it = iv_vecEntries.begin(); it != iv_vecEntries.end(); ++it) {
        EngineEntry & rEntry =  (*it);
        AnalysisEngine * pEngine = rEntry.iv_pEngine;
        uima::internal::CapabilityContainer * pCapContainer = rEntry.iv_pCapabilityContainer;
        assert(EXISTS(pEngine));
        assert(EXISTS(pCapContainer));

#ifdef DEBUG_VERBOSE
        UIMA_TPRINT("=========================================");
        UIMA_TPRINT("----------- ResultSpec before process():");
        resSpec.print(cout);
#endif

        UIMA_TRACE_STREAM_ARG(clTrace, "ASB checks engine", pEngine->getAnalysisEngineMetaData().getName() );

        UIMA_TPRINT("--------- Checking annotator: " << pEngine->getAnalysisEngineMetaData().getName());
        vector<TypeOrFeature> tofsToBeRemoved;
        bool callEngine=true;
        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;
          }
        

        if ( callEngine ) {

          UIMA_TPRINT("----------- engine will be processed");
          UIMA_TRACE_STREAM(clTrace, "Engine will be called");

          // create ResultSpec for annotator
          // this must be done because an annotator should only be called with the result spec
          // that its XML file indicates.
          ResultSpecification annResSpec;
          vector<TypeOrFeature>::const_iterator citTOF;
          for (citTOF = tofsToBeRemoved.begin(); citTOF != tofsToBeRemoved.end(); ++citTOF) {
            assert( (*citTOF).isValid() );
            annResSpec.add(*citTOF);
            UIMA_TRACE_STREAM_ARG(clTrace, "    engine is called with result spec", (*citTOF).getName() );
          }

          /// does engine expect a TCas
          //AEs that declare at least one input or output SofA should be sent the base CAS.
          //Otherwise they must be sent a TCAS.
          const AnalysisEngineMetaData::TyVecpCapabilities & vecCap = pEngine->getAnalysisEngineMetaData().getCapabilites();
          AnalysisEngineMetaData::TyVecpCapabilities::const_iterator itCap;
          for (size_t i=0; i < vecCap.size(); i++) {
            Capability * cap = vecCap.at(i);
            Capability::TyVecCapabilitySofas inputSofa = cap->getCapabilitySofas(Capability::INPUTSOFA);
            Capability::TyVecCapabilitySofas outputSofa = cap->getCapabilitySofas(Capability::OUTPUTSOFA);
            if (inputSofa.size() > 0 || outputSofa.size() > 0) {
              requiresTCas = false;
              break;
            }
          }

          if (requiresTCas) {
	    SofaFS defSofa = cas.getSofa(pEngine->getAnnotatorContext().mapToSofaID(CAS::NAME_DEFAULT_TEXT_SOFA));
	    if (!defSofa.isValid()) {
	      //TODO: throw exception
	      cerr << "could not get default text sofa " << endl;
	      return 99;
	    }
	    tcas = cas.getView(defSofa);
	    utErrorId = pEngine->process(*tcas, annResSpec);
          } else {
            utErrorId = ((AnalysisEngine*) pEngine)->process(cas, annResSpec);
          }

          if (utErrorId != UIMA_ERR_NONE) {
            clTrace.dump(_TEXT("Error"), (long) utErrorId);
            utRetVal = utErrorId;                  /* I know, this overwrites a previous error */
          } else {
            // now remove TOFs from ResultSpec
            vector<TypeOrFeature>::const_iterator citTOF;
            for (citTOF = tofsToBeRemoved.begin(); citTOF != tofsToBeRemoved.end(); ++citTOF) {
              assert( (*citTOF).isValid() );
              resSpec.remove(*citTOF);
            }
          }
        } else {
          assert( tofsToBeRemoved.empty() );
          UIMA_TPRINT("----------- engine will *not* be processed");
          ++uiNbrOfSkippedAnnotators;
        }
      }                                               /* e-o-for */
      /* in case there was no error but not any annotator which generates a target type
         has been caled for process, we have an error */
      UIMA_TPRINT("Annotators skipped due to unsupport lang: " << uiNbrOfSkippedAnnotators);
      UIMA_TPRINT("Overall number of annotators: " << iv_vecEntries.size() );

      if (   (utRetVal == UIMA_ERR_NONE)
             && (uiNbrOfSkippedAnnotators > 0)
             && (uiNbrOfSkippedAnnotators == iv_vecEntries.size())
             && (crResultSpec.getSize() > 0) ) {
        // utRetVal = UIMA_ERR_ANNOTATOR_MGR_LANG_NOT_SUPPORTED_FOR_ANNOTATOR;
        iv_pEngine->getAnnotatorContext().getLogger().logWarning("All annotators skipped (maybe unsupported language)");
      }

      UIMA_ANNOTATOR_TIMING(iv_clTimerLaunchProcess.stop());
      return(utRetVal);
    }