/** @name annotator_mgr.cpp
-----------------------------------------------------------------------------

 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.

-----------------------------------------------------------------------------

   Description: This file contains class AnnotatorManager (ASB in UIMA)

-----------------------------------------------------------------------------



-------------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/*       Include dependencies                                              */
/* ----------------------------------------------------------------------- */
#include "uima/pragmas.hpp"

//#define DEBUG_VERBOSE
#include "uima/macros.h"
#include "uima/annotator_mgr.hpp"
#include "uima/strconvert.hpp"
#include "uima/annotator.hpp"
///#include "uima/annotator_file.hpp"
#include "uima/comp_ids.h"
#include "uima/internal_aggregate_engine.hpp"
#include "uima/internal_primitive_engine.hpp"
#include "uima/log.hpp"
#include "uima/err_ids.h"
#include "uima/msg.h"

#include "uima/annotator_context.hpp"
#include "uima/cas.hpp"

#include "uima/trace.hpp"
#include "uima/assertmsg.h"

#include "uima/engine.hpp"
#include "uima/result_specification.hpp"
#include "uima/internal_capability_container.hpp"
#include "uima/casdefinition.hpp"
#include "uima/lowlevel_typesystem.hpp"

/* ----------------------------------------------------------------------- */
/*       Constants                                                         */
/* ----------------------------------------------------------------------- */

#define UIMA_ANNOTATOR_MGR_DEFAULT_PROCESS_UNSUPPORTED_LANGUAGES   false
#define UIMA_ANNOTATOR_MGR_DEFAULT_IGNORE_PROCESSDOCUMENT_ERRORS   false
#define UIMA_ANNOTATOR_MGR_DEFAULT_PREVENT_DUPLICATE_TARGET_TYPES  true

/* ----------------------------------------------------------------------- */
/*       Forward declarations                                              */
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/*       Types / Classes                                                   */
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/*       Private Implementation                                            */
/* ----------------------------------------------------------------------- */

namespace uima {

  namespace internal {

    /* ----------------------------------------------------------------------- */
    /*       Implementation                                                    */
    /* ----------------------------------------------------------------------- */

    AnnotatorManager::AnnotatorManager(internal::AggregateEngine & rEngine) :
        iv_pEngine(& rEngine),
        iv_vecEntries(),
        iv_bIsInitialized(false),
        iv_uiNbrOfDocsProcessed(0)
        /* ----------------------------------------------------------------------- */{
      ;
    }

    AnnotatorManager::~AnnotatorManager(void)
    /* ----------------------------------------------------------------------- */{
      util::Trace                 clTrace(util::enTraceDetailHigh, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ANNOTATOR_MGR);

      if (! iv_vecEntries.empty() ) {
        launchDeInit();
      }
      assert( iv_vecEntries.empty() );

    }


#ifdef DEBUG_VERBOSE
    void printCapabilityContainer(ostream & os, uima::Language const & crLanguage, uima::internal::CapabilityContainer const & crCapContainer) {
      os << " Language: " << crLanguage.asString() << endl;
      os << " CapContainer: "  << endl;

      internal::CapabilityContainer & nonConstCAP = (internal::CapabilityContainer &) crCapContainer;
      internal::CapabilityContainer::TySetTypeOrFeatures const & outTOFs = nonConstCAP.getOutputTypeOrFeatures( crLanguage );
      internal::CapabilityContainer::TySetTypeOrFeatures::const_iterator citTOFS;
      for (citTOFS = outTOFs.begin(); citTOFS != outTOFs.end(); ++citTOFS) {
        if ( (*citTOFS).isType() ) {
          os << "  type: " ;
        } else {
          os << " feat: ";
        }
        os << (*citTOFS).getName() << endl;
      }

    }

#endif

    bool containsTOF(TypeOrFeature const & crTOF, uima::Language const & crLanguage, uima::internal::CapabilityContainer const & crCapContainer) {
      internal::CapabilityContainer & nonConstCAP = (internal::CapabilityContainer &) crCapContainer;
      internal::CapabilityContainer::TySetTypeOrFeatures const & outTOFs = nonConstCAP.getOutputTypeOrFeatures( crLanguage );
      internal::CapabilityContainer::TySetTypeOrFeatures::const_iterator citTOFS;
      for (citTOFS = outTOFs.begin(); citTOFS != outTOFs.end(); ++citTOFS) {
        if (crTOF == (*citTOFS) ) {
          return true;
        }
      }
      return false;
    }



    TyErrorId AnnotatorManager::launchInit()
    /* ----------------------------------------------------------------------- */{
      util::Trace                 clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ANNOTATOR_MGR);
      UIMA_ANNOTATOR_TIMING(iv_clTimerLaunchInit.start());
      TyErrorId               utErrorId = UIMA_ERR_NONE;

      assert( !iv_bIsInitialized );
      assert(iv_vecEntries.empty());

      AnnotatorContext & rANC = iv_pEngine->getAnnotatorContext();

      AnalysisEngineDescription const & crTAESpecifier = rANC.getTaeSpecifier(); // this method must be added

      assert( ! crTAESpecifier.isPrimitive() );
      //BSIvector < icu::UnicodeString > const & crVecEngineNames = crTAESpecifier.getAnalysisEngineMetaData()->getFixedFlow()->getNodes();
      vector < icu::UnicodeString > const & crVecEngineNames = crTAESpecifier.getAnalysisEngineMetaData()->getFlowConstraints()->getNodes();

      // for all engines in the flow
      size_t ui;
      for (ui=0; ui<crVecEngineNames.size(); ++ui) {

        icu::UnicodeString const & crEngineName = crVecEngineNames[ui];
//         clTrace.dump(_TEXT("Delegate name"), crEngineName);

        AnnotatorContext * pDelegateANC = rANC.getDelegate(crEngineName);
        ErrorInfo errInfo;
        // create a delegate TAE which owns neither the ANC, nor the TAESpecifier, nor the CAS definition
        AnalysisEngine * pEngine = Framework::createAnalysisEngine(*pDelegateANC,
                                       false,
                                       false,
                                       iv_pEngine->getCASDefinition(),
                                       false,
                                       errInfo);
        utErrorId = errInfo.getErrorId();
        if (utErrorId != UIMA_ERR_NONE) {
          assert( pEngine == NULL );
          iv_pEngine->getAnnotatorContext().getLogger().logError(errInfo);
          return utErrorId;
        }
        assert( EXISTS(pEngine) );

        EngineEntry entry;
        entry.iv_pEngine = pEngine;

        // create a capability container for each engine (the cap. container is used for faster lookup)
        uima::internal::CapabilityContainer * pCapContainer = new internal::CapabilityContainer();
        assert( EXISTS(pCapContainer) );
        entry.iv_pCapabilityContainer = pCapContainer;

        vector<Capability*> const & crCapabilities = pDelegateANC->getTaeSpecifier().getAnalysisEngineMetaData()->getCapabilites();

        UIMA_TPRINT("-------------------------------------------------");
        UIMA_TPRINT("Engine name: " << crEngineName);
        UIMA_TPRINT("number of capabilities: " << crCapabilities.size());
        pCapContainer->init(crCapabilities, iv_pEngine->getCASDefinition().getTypeSystem() );

#ifdef DEBUG_VERBOSE
        /*
                 UIMA_TPRINT("capabilities:");
                 vector<Capability*>::const_iterator cit;
                 for (cit = crCapabilities.begin(); cit != crCapabilities.end(); ++cit) {
                    Capability* cap = (*cit);
                    vector<icu::UnicodeString> const & outCapT = cap->getCapabilityTypes(Capability::OUTPUT);
                    size_t i;
                    for (i=0; i<outCapT.size(); ++i) {
                       UIMA_TPRINT("  type: " << outCapT[i]);
                    }

                    vector<icu::UnicodeString> const & outCapF = cap->getCapabilityFeatures(Capability::OUTPUT);
                    for (i=0; i<outCapF.size(); ++i) {
                       UIMA_TPRINT("  feat: " << outCapF[i]);
                    }

                    vector<icu::UnicodeString> const  & suppLangs = cap->getSupportedLanguages();
                    for (i=0; i<suppLangs.size(); ++i) {
                       UIMA_TPRINT("  lang: " << suppLangs[i]);
                    }

                 }
        */
        UIMA_TPRINT("cap container for fr");
        printCapabilityContainer(cout, uima::Language("fr"), *pCapContainer);
        UIMA_TPRINT("  is like dump ? " << pCapContainer->hasEmptyOutputTypeOrFeatures(uima::Language("en") ));
#endif

        /* add to set of delegate TAEs as managed by the AnnotatorManager */
        iv_vecEntries.insert(iv_vecEntries.end(), entry);
      }

      UIMA_ANNOTATOR_TIMING(iv_clTimerLaunchInit.stop());

      iv_bIsInitialized = true;
      return(utErrorId);
    }


    TyErrorId AnnotatorManager::launchDeInit()
    /* ----------------------------------------------------------------------- */{
      util::Trace                 clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ANNOTATOR_MGR);
      TyAnnotatorEntries::reverse_iterator it;           /* deinit must be performed in reverse order! */
      TyErrorId               utErrorId = UIMA_ERR_NONE;
      TyErrorId               utRetVal = UIMA_ERR_NONE;

#ifdef UIMA_DEBUG_ANNOTATOR_TIMING
      if (clTrace.isEnabled() && iv_uiNbrOfDocsProcessed > 0) {
        dumpTimingData();
      }
#endif

      /* iterate through ALL Annotators in reverse order */
      for (it = iv_vecEntries.rbegin(); !(it == iv_vecEntries.rend()); ++it) {
        EngineEntry & rEntry =  (*it);
        AnalysisEngine * pEngine = rEntry.iv_pEngine;
        assert(EXISTS(pEngine));
        if (pEngine->isInitialized()) {
          /* use the annotator */
          utErrorId = pEngine->destroy();
          if (utErrorId != UIMA_ERR_NONE) {
            clTrace.dump(_TEXT("Error"), (long) utErrorId);
            utRetVal = utErrorId;                     /* I know, this overwrites a previous error */
          }
          /* we do not return in the case of an error as we want to be sure that
             ALL annotators will be deinitialized */
        }
      } /* e-o-for */
      for (it = iv_vecEntries.rbegin(); !(it == iv_vecEntries.rend()); ++it) {
        EngineEntry & rEntry =  (*it);
        AnalysisEngine * pEngine = rEntry.iv_pEngine;
        assert(EXISTS(pEngine));
        internal::CapabilityContainer * pCapContainer = rEntry.iv_pCapabilityContainer;
        assert(EXISTS(pCapContainer));
        delete pEngine;
        delete pCapContainer;
      }

      iv_vecEntries.clear();
      return(utRetVal);
    }


    TyErrorId AnnotatorManager::launchReinitTypeSystem() {
      util::Trace                 clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ANNOTATOR_MGR);
      size_t ui;
      TyErrorId               utErrorId = UIMA_ERR_NONE;
      TyErrorId               utRetVal = UIMA_ERR_NONE;

      for (ui=0; ui<iv_vecEntries.size(); ++ui) {
        uima::internal::EngineBase & engine = uima::internal::EngineBase::promoteEngine( * iv_vecEntries[ui].iv_pEngine );
        utErrorId = engine.reinitTypeSystem();
        if (utErrorId != UIMA_ERR_NONE) {
          clTrace.dump(_TEXT("Error in launchReinitTypeSystem()"), (long) utErrorId);
          utRetVal = utErrorId;                        /* I know, this overwrites a previous error */
        }
        // create new capability containers
        assert( EXISTS(iv_vecEntries[ui].iv_pCapabilityContainer) );
        delete iv_vecEntries[ui].iv_pCapabilityContainer;

        uima::internal::CapabilityContainer * capContainer = new uima::internal::CapabilityContainer();
        assert( EXISTS(capContainer) );
        capContainer->init( engine.getAnalysisEngineMetaData().getCapabilites(),
                            engine.getCASDefinition().getTypeSystem() );

        iv_vecEntries[ui].iv_pCapabilityContainer = capContainer;

      }
      return utRetVal;
    }

    TyErrorId AnnotatorManager::launchConfig()
    /* ----------------------------------------------------------------------- */{
      util::Trace                 clTrace(util::enTraceDetailMedium, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ANNOTATOR_MGR);
      TyAnnotatorEntries::iterator it;
      TyErrorId               utErrorId = UIMA_ERR_NONE;
      TyErrorId               utRetVal = UIMA_ERR_NONE;

      assert(iv_bIsInitialized);
      /* iterate through ALL Annotators */
      assert(!iv_vecEntries.empty());
      for (it = iv_vecEntries.begin(); it != iv_vecEntries.end(); ++it) {
        EngineEntry & rEntry =  (*it);
        AnalysisEngine * pEngine = rEntry.iv_pEngine;
        assert(EXISTS(pEngine));

//         clTrace.dump(_TEXT("Annotator"), pEngine->getSymbolicName().c_str());
        /* use the annotator */
        utErrorId = pEngine->reconfigure();
        if (utErrorId != UIMA_ERR_NONE) {
          clTrace.dump(_TEXT("Error"), (long) utErrorId);
          utRetVal = utErrorId;                        /* I know, this overwrites a previous error */
        }
        /* eben if an error occurs, we give all others a chance to reconfig */
      } /* e-o-for */
      return(utRetVal);
    }



    TyErrorId AnnotatorManager::launchBatchProcessComplete() {
      util::Trace                  clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ANNOTATOR_MGR);
      size_t ui;
      TyErrorId               utErrorId = UIMA_ERR_NONE;
      TyErrorId               utRetVal = UIMA_ERR_NONE;

      for (ui=0; ui<iv_vecEntries.size(); ++ui) {
        uima::internal::EngineBase & engine = uima::internal::EngineBase::promoteEngine( * iv_vecEntries[ui].iv_pEngine );
        utErrorId = engine.batchProcessComplete();
        if (utErrorId != UIMA_ERR_NONE) {
          clTrace.dump(_TEXT("Error in launchBatchProcessComplete()"), (long) utErrorId);
          utRetVal = utErrorId;                        /* I know, this overwrites a previous error */
        }
      }
      return utRetVal;
    }


    TyErrorId AnnotatorManager::launchCollectionProcessComplete() {
      util::Trace                  clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ANNOTATOR_MGR);
      size_t ui;
      TyErrorId               utErrorId = UIMA_ERR_NONE;
      TyErrorId               utRetVal = UIMA_ERR_NONE;

      for (ui=0; ui<iv_vecEntries.size(); ++ui) {
        uima::internal::EngineBase & engine = uima::internal::EngineBase::promoteEngine( * iv_vecEntries[ui].iv_pEngine );
        utErrorId = engine.collectionProcessComplete();
        if (utErrorId != UIMA_ERR_NONE) {
          clTrace.dump(_TEXT("Error in launchCollectionProcessComplete()"), (long) utErrorId);
          utRetVal = utErrorId;                        /* I know, this overwrites a previous error */
        }
      }
      return utRetVal;
    }





    bool AnnotatorManager::shouldEngineBeCalled(uima::internal::CapabilityContainer const & crCapContainer,
        ResultSpecification const & rResultSpec,
        Language const & crLanguage,
        vector<TypeOrFeature> & rTOFSToBeRemoved) {
      util::Trace                 clTrace(util::enTraceDetailHigh, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ANNOTATOR_MGR);

#ifdef DEBUG_VERBOSE
      UIMA_TPRINT("CapContainer:");
      printCapabilityContainer(cout, crLanguage, crCapContainer);
      rResultSpec.print(cout);

      /*
      uima::Language unspecLang(Language::UNSPECIFIED);

      internal::CapabilityContainer & nonConstCAP = (internal::CapabilityContainer &) crCapContainer;
      internal::CapabilityContainer::TySetTypeOrFeatures const & outTOFs = nonConstCAP.getOutputTypeOrFeatures( unspecLang );
      internal::CapabilityContainer::TySetTypeOrFeatures::const_iterator citTOFS;
      UIMA_TPRINT("Capabilities for unspecified language");
      for (citTOFS = outTOFs.begin(); citTOFS != outTOFs.end(); ++citTOFS) {
         UIMA_TPRINT("  " << (*citTOFS).getName() );
      }
      */
#endif

      // treat dump-like annotators for this language specially
      if (crCapContainer.hasEmptyOutputTypeOrFeatures( crLanguage )) {
        return true;
      }

      ResultSpecification::TyTypeOrFeatureSTLSet const & crTOFSet = rResultSpec.getTypeOrFeatureSTLSet();
      bool bHasTOF = false;
      ResultSpecification::TyTypeOrFeatureSTLSet::const_iterator cit;
      for (cit = crTOFSet.begin(); cit != crTOFSet.end(); ++cit) {
        TypeOrFeature const & crTOF = (*cit);
        assert( (*cit).isValid() );
        assert( crTOF.isValid() );
        assert( rResultSpec.contains( crTOF ) );

        UIMA_TPRINT("  TOF Name: " << crTOF.getName());

        if (crCapContainer.hasOutputTypeOrFeature(crTOF, crLanguage)) {
          assert( containsTOF(crTOF, crLanguage, crCapContainer) );
          UIMA_TPRINT( "    in capability" );
          bHasTOF = true;
          rTOFSToBeRemoved.push_back(crTOF);
        } else {
          assert( ! containsTOF(crTOF, crLanguage, crCapContainer) );
          UIMA_TPRINT("     not in capability");
        }
      }
      return bHasTOF;
    }





    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);

      //get the CAS View
      tcas = &cas;
      if (cas.isBackwardCompatibleCas() ) {
        tcas = cas.getView(cas.getSofa(iv_pEngine->getAnnotatorContext().mapToSofaID(CAS::NAME_DEFAULT_TEXT_SOFA)));
      }

      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=false;
        if ( EXISTS(tcas) ) {

          //this populates the tofsToBeRemoved vector so always call it
          callEngine = shouldEngineBeCalled(*pCapContainer,
                                            resSpec,
                                            tcas->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 = true;
              break;
            }
          }

          if (requiresTCas) {
            if (!EXISTS(tcas)) {
              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);
    }

#ifdef UIMA_DEBUG_ANNOTATOR_TIMING
    void AnnotatorManager::dumpTimingData( void ) const
      /* ----------------------------------------------------------------------- */ {
      util::Trace                 clTrace(util::enTraceDetailMedium, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_TIMING);

      if (clTrace.isEnabled() && iv_uiNbrOfDocsProcessed > 0) {
        TyAnnotatorEntries::const_iterator it;
        string                 strTemp;
        double                  dTotalLoadTime            = (double)0.0;
        double                  dTotalInitTime            = (double)0.0;
        double                  dTotalDeInitTime          = (double)0.0;
        double                  dTotalConfigTime          = (double)0.0;
        double                  dTotalProcessDocumentTime = (double)0.0;
        double                  dTotalAnnotatorTime          = (double)0.0;

        assert(iv_bIsInitialized);
        assert(!iv_vecEntries.empty());
        // first sum up times to get totals
        for (it = iv_vecEntries.begin(); it != iv_vecEntries.end(); ++it) {
          EngineEntry const & rEntry = (*it);
          AnalysisEngine * pEngine = rEntry.iv_pEngine;

          dTotalLoadTime           += pEngine->getLoadTimer().getAccumulatedTime();
          dTotalInitTime           += pEngine->getInitTimer().getAccumulatedTime();
          dTotalDeInitTime         += pEngine->getDeInitTimer().getAccumulatedTime();
          dTotalConfigTime         += pEngine->getConfigTimer().getAccumulatedTime();
          dTotalProcessDocumentTime+= pEngine->getProcessDocumentTimer().getAccumulatedTime();
        }                                            /* e-o-for */
        dTotalAnnotatorTime = dTotalLoadTime + dTotalInitTime + dTotalDeInitTime + dTotalConfigTime + dTotalProcessDocumentTime;

        clTrace.dump(_TEXT("Total timing data"));
        long2String((long)iv_uiNbrOfDocsProcessed, strTemp);
        clTrace.dump(_TEXT("  Documents processed "), strTemp.c_str());
        clTrace.dump(_TEXT("  Total annotator time   "), Timer::timeString(dTotalAnnotatorTime).c_str());
        assert(iv_uiNbrOfDocsProcessed > 0);
        assert(dTotalAnnotatorTime > 0);
        // we have to make sure our values stay in range for very quick processing times
        strTemp = " > FLT_MAX ";
        if (dTotalAnnotatorTime > FLT_MIN) {                                            // use FLT_MIN instead of DBL_MIN to have some buffer
          double               dThroughput = iv_uiNbrOfDocsProcessed / dTotalAnnotatorTime;

          if (dThroughput < FLT_MAX) {
            double2String(dThroughput, (size_t)1, strTemp);
          }
        }
        clTrace.dump(_TEXT("  Total throughput     "), (strTemp + " docs/sec").c_str());
        clTrace.dump(_TEXT("  PlgMgr init time     "), iv_clTimerLaunchInit.timeString().c_str());
        clTrace.dump(_TEXT("  PlgMgr process time  "), iv_clTimerLaunchProcess.timeString().c_str());
        clTrace.dump(_TEXT("- Load Time            "), Timer::timeString(dTotalLoadTime).c_str());
        clTrace.dump(_TEXT("- Init Time            "), Timer::timeString(dTotalInitTime).c_str());
        clTrace.dump(_TEXT("- Config Time          "), Timer::timeString(dTotalConfigTime).c_str());
        clTrace.dump(_TEXT("- ProcessDocument Time "), Timer::timeString(dTotalProcessDocumentTime).c_str());
        clTrace.dump(_TEXT("- DeInit Time          "), Timer::timeString(dTotalDeInitTime).c_str());

        // now dump the individual, total  and relative times
        for (it = iv_vecEntries.begin(); it != iv_vecEntries.end(); ++it) {
          EngineEntry const & rEntry =  (*it);
          AnalysisEngine * pEngine = rEntry.iv_pEngine;

          assert(EXISTS(pEngine));
          clTrace.dump(_TEXT("Timing data for engine "));
          clTrace.dump(_TEXT("- Load Time            "), pEngine->getLoadTimer().timeAndPercentString(dTotalLoadTime).c_str());
          clTrace.dump(_TEXT("- Init Time            "), pEngine->getInitTimer().timeAndPercentString(dTotalInitTime).c_str());
          clTrace.dump(_TEXT("- Config Time          "), pEngine->getConfigTimer().timeAndPercentString(dTotalConfigTime).c_str());
          clTrace.dump(_TEXT("- ProcessDocument Time "), pEngine->getProcessDocumentTimer().timeAndPercentString(dTotalProcessDocumentTime).c_str());
          clTrace.dump(_TEXT("- DeInit Time          "), pEngine->getDeInitTimer().timeAndPercentString(dTotalDeInitTime).c_str());
        }                                            /* e-o-for */
      }
    }

    size_t
    AnnotatorManager::getNbrOfAnnotators( void ) const {
      return iv_vecEntries.size();
    }

    Timer
    AnnotatorManager::getAnnotatorTimer( size_t uiAnnotatorIndex,  size_t uiAnnotatorTimer) const {
      if (uiAnnotatorIndex >= iv_vecEntries.size()) {
        return iv_clTimerLaunchProcess;
      }
      assert(uiAnnotatorTimer < internal::AggregateEngine::enNumberOfAnnotatorTimerEnums);
      internal::AggregateEngine::EnAnnotatorTimer enAnnotatorTimer = (internal::AggregateEngine::EnAnnotatorTimer)uiAnnotatorTimer;
      EngineEntry const & rEntry = iv_vecEntries[uiAnnotatorIndex];
      AnalysisEngine * pEngine = rEntry.iv_pEngine;
      switch (enAnnotatorTimer) {
      case internal::AggregateEngine::enLoadAnnotatorTime    :
        return pEngine->getLoadTimer();
      case internal::AggregateEngine::enInitAnnotatorTime    :
        return pEngine->getInitTimer();
      case internal::AggregateEngine::enConfigAnnotatorTime  :
        return pEngine->getConfigTimer();
      case internal::AggregateEngine::enProcessAnnotatorTime :
        return pEngine->getProcessDocumentTimer();
      case internal::AggregateEngine::enDeinitAnnotatorTime  :
        return pEngine->getDeInitTimer();
      case internal::AggregateEngine::enTotalAnnotatorTime   :
        return(pEngine->getLoadTimer() +
               pEngine->getInitTimer() +
               pEngine->getConfigTimer() +
               pEngine->getProcessDocumentTimer() +
               pEngine->getDeInitTimer());
      default:
        assert(false);
      }
      assert(false);
      return iv_clTimerLaunchProcess; // to satisfy compiler: never reached
    }


#endif //UIMA_DEBUG_ANNOTATOR_TIMING


  }

}

/* <EOF> */




