/** @name internal_aggregate_engine.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 AggregateEngine

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


   4/27/1999  Initial creation

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

#define UIMA_ENGINE_MAIN_CPP


/* ----------------------------------------------------------------------- */
/*       Include dependencies                                              */
/* ----------------------------------------------------------------------- */

#include "uima/pragmas.hpp" //must be included first to disable warnings
#include "uima/annotator_timing.hpp"
#include "uima/engine.hpp"

#include "uima/internal_aggregate_engine.hpp"
#include "uima/internal_fspromoter.hpp"
#include "uima/resmgr.hpp"
#include "uima/comp_ids.h"
#include "uima/err_ids.h"
#include "uima/annotator_mgr.hpp"
#include "uima/internal_casimpl.hpp"

#include "uima/macros.h"
#include "uima/trace.hpp"
#include "uima/consoleui.hpp"

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

namespace uima {

  namespace internal {

    static const char *        gs_cpszReservedPrefix = _TEXT("UIMA");


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

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

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

    /*
    Most of the implementations required by uima::internal::EngineBase
    directly call the ASB.
    */


    TyErrorId AggregateEngine::init2(util::Trace & rclTrace)
    /* ----------------------------------------------------------------------- */
    {
      TyErrorId               utErrorId = UIMA_ERR_NONE;

      try {
        /* now, after all the general init and config has been done,
           we can init the annotator manager which will init all annotators */
        utErrorId = iv_annotatorMgr.launchInit();
        if (utErrorId != UIMA_ERR_NONE) {
          /* since the init failed, we must deinit all annotators in order
             to release all user allocated stuff */
          (void) iv_annotatorMgr.launchDeInit();   /* ignore this RC */
          return(utErrorId);
        }

        /* at this point, everything is fine and the engine is up and running! */

      }
      /* we need to catch any unexpected exceptions from init */
      catch (Exception & rclException) {
        rclTrace.dump(_TEXT("UIMACPP exception during init"));
        rclTrace.dump(_TEXT("UIMACPP exception id"), rclException.getErrorInfo().getErrorId());
        rclTrace.dump(_TEXT("UIMACPP exception name"), rclException.getName());
        rclTrace.dump(_TEXT("UIMACPP exception message"), rclException.getErrorInfo().getMessage().asString().c_str());
        getAnnotatorContext().getLogger().logError(rclException.getErrorInfo());
        return(logError(rclTrace, rclException.getErrorInfo().getErrorId()));
      }
#ifdef NDEBUG
      catch (...) {
        /* this should never occur!!! */
        rclTrace.dump(_TEXT("Unexpected unknown exception"));
        assertWithMsg(false, _TEXT("Unexpected unknown exception in init()"));   //lint !e506: Constant value Boolean
        return(logError(rclTrace, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION));   /* in case the assert() is no longer here */
      }
#endif
      return(utErrorId);
    }


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


    AggregateEngine::AggregateEngine(AnnotatorContext & rANC, bool bOwnsANC,
                                     bool bOwnsTAESpecififer,
                                     uima::internal::CASDefinition & casDefs, bool ownsCasDefs) :
        EngineBase(rANC, bOwnsANC, bOwnsTAESpecififer, casDefs, ownsCasDefs),
        iv_annotatorMgr(*this) {
      util::Trace             clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);

      clTrace.dump(_TEXT("UIMACPP Version"), AggregateEngine::getVersionInfo());
      clTrace.dump(_TEXT("UIMACPP Level"), AggregateEngine::getLevelInfo());
      assert(iv_state == EngineState::enEngineState_readyForInit);

#ifndef NDEBUG

      /* taph 18.10.2001: this code can be useful if you want to debug
         UIMACPP in an environment where you can't start the debugger directly
         e.g. if UIMACPP is called from Java.
         The programm will wait in the loop below which gives you time to
         attach the debugger to the (Java) process and start debugging.
      */
      util::Location tempDir;
      util::Filename clLockfileName(tempDir.getAsCString(), "uimacpplock","lck");
      clLockfileName.normalizeAbsolute();
      if (clLockfileName.isExistent()) {
        cout << "In AggregateEngine Ctor: Debug Lockfile detected." << endl;
        cout << "Halting UIMACPP execution until " << clLockfileName.getAsCString() <<  " is deleted/renamed..." << endl;
        do {
          apr_sleep(3000000);             // 3 seconds
        } while (clLockfileName.isExistent());
        cout << "Continuing..." << endl;
      }
#endif

    }



    AggregateEngine::~AggregateEngine(void)
    /* ----------------------------------------------------------------------- */
    {
      util::Trace             clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      destroyIfNeeded();

    }



    TyErrorId AggregateEngine::initializeImpl(AnalysisEngineDescription const & ) {
      util::Trace             clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      TyErrorId               utErrorId = UIMA_ERR_NONE;

      /* continue with the rest of init() */
      utErrorId = init2(clTrace);
      if (utErrorId != UIMA_ERR_NONE) {
        return(logError(clTrace, utErrorId));
      }

      return(logError(clTrace, utErrorId));
    }


    TyErrorId AggregateEngine::reinitTypeSystemImpl() {
      util::Trace             clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      return iv_annotatorMgr.launchReinitTypeSystem();
    }


    TyErrorId AggregateEngine::destroyImpl(void) {
      util::Trace             clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      return iv_annotatorMgr.launchDeInit();
    }


    TyErrorId AggregateEngine::processImpl(CAS & cas, ResultSpecification const & crResultSpec) {
      util::Trace             clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      return iv_annotatorMgr.launchProcessDocument(cas, crResultSpec );
    }


    TyErrorId AggregateEngine::reconfigureImpl(void) {
      util::Trace             clTrace(util::enTraceDetailMedium, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      return iv_annotatorMgr.launchConfig();
    }

    TyErrorId AggregateEngine::batchProcessCompleteImpl(void) {
      util::Trace             clTrace(util::enTraceDetailMedium, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      return iv_annotatorMgr.launchCollectionProcessComplete();
    }

    TyErrorId AggregateEngine::collectionProcessCompleteImpl(void) {
      util::Trace             clTrace(util::enTraceDetailMedium, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      return iv_annotatorMgr.launchCollectionProcessComplete();
    }

    bool AggregateEngine::hasNextImpl() {
      return false;
    }

    CAS & AggregateEngine::nextImpl() {
      UIMA_EXC_THROW_NEW(ExcInvalidRequest,
                         UIMA_ERR_NOT_YET_IMPLEMENTED,
                         UIMA_MSG_ID_EXC_INVALID_CALL_TO_NEXT,
                         UIMA_MSG_ID_EXC_INVALID_CALL_TO_NEXT,
                         ErrorInfo::unrecoverable);
    }

    int AggregateEngine::getCasInstancesRequiredImpl() {
      return 0;
    }


    /* ----------------------------------------------------------------------- */
    /*       Static functions                                                  */
    /* ----------------------------------------------------------------------- */

#ifdef UIMA_DEBUG_ANNOTATOR_TIMING

    size_t
    AggregateEngine::getNbrOfAnnotators( void ) const {
      return iv_annotatorMgr.getNbrOfAnnotators();
    }

    icu::UnicodeString const &
    AggregateEngine::getAnnotatorName( size_t uiAnnotatorIndex  ) const {
      // it is not easy to find the names for the delegate engines
      // given only their position in the flow
      AnalysisEngineMetaData const * pMetaData =
        getAnnotatorContext().getTaeSpecifier().getAnalysisEngineMetaData();
      assert(EXISTS(pMetaData));
      FlowConstraints const * pFlow = pMetaData->getFlowConstraints();
      assert(EXISTS(pFlow));
      return pFlow->getNodes()[uiAnnotatorIndex];
    }

    uima::Timer
    AggregateEngine::getAnnotatorTimer( size_t uAnnotatorIndex,  EnAnnotatorTimer enAnnotatorTimer) const {
      return iv_annotatorMgr.getAnnotatorTimer(uAnnotatorIndex, enAnnotatorTimer);
    }


    void AggregateEngine::displayTimingData(util::ConsoleUI const & rConsole, bool bVerbose) const {
      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;
      size_t                  i;


      // first sum up times to get totals
      for ( i = 0; i < getNbrOfAnnotators(); ++i ) {
        dTotalLoadTime           += getAnnotatorTimer(i, enLoadAnnotatorTime).getAccumulatedTime();
        dTotalInitTime           += getAnnotatorTimer(i, enInitAnnotatorTime).getAccumulatedTime();
        dTotalDeInitTime         += getAnnotatorTimer(i, enDeinitAnnotatorTime).getAccumulatedTime();
        dTotalConfigTime         += getAnnotatorTimer(i, enConfigAnnotatorTime).getAccumulatedTime();
        dTotalProcessDocumentTime+= getAnnotatorTimer(i, enProcessAnnotatorTime).getAccumulatedTime();
      }                                            /* e-o-for */
      dTotalAnnotatorTime = dTotalLoadTime + dTotalInitTime + dTotalDeInitTime + dTotalConfigTime + dTotalProcessDocumentTime;

      rConsole.formatHeader("Overall annotator timing data");
      rConsole.format("Total time spent in annotators",       uima::Timer::timeString(dTotalAnnotatorTime).c_str());
      if (bVerbose) {
        rConsole.format("- library-load time",     uima::Timer::timeString(dTotalLoadTime).c_str());
        rConsole.format("- initialize time",       uima::Timer::timeString(dTotalInitTime).c_str());
        rConsole.format("- reconfigure time",      uima::Timer::timeString(dTotalConfigTime).c_str());
        rConsole.format("- process time",          uima::Timer::timeString(dTotalProcessDocumentTime).c_str());
      }

      // now dump the individual, total  and relative times
      rConsole.header("Individual annotator timing data (% for this annotator)");
      for ( i = 0; i < getNbrOfAnnotators(); ++i ) {
        string str;
        UnicodeStringRef uref(getAnnotatorName(i));
        uref.extract(str);
        rConsole.format(str.c_str(),  getAnnotatorTimer(i, enTotalAnnotatorTime).timeAndPercentString(dTotalAnnotatorTime).c_str());
        if (bVerbose) {
          rConsole.format("- library load time",     getAnnotatorTimer(i, enLoadAnnotatorTime).timeAndPercentString(dTotalLoadTime).c_str());
          rConsole.format("- initialize time",       getAnnotatorTimer(i, enInitAnnotatorTime).timeAndPercentString(dTotalInitTime).c_str());
          rConsole.format("- reconfigure time",      getAnnotatorTimer(i, enConfigAnnotatorTime).timeAndPercentString(dTotalConfigTime).c_str());
          rConsole.format("- process time",          getAnnotatorTimer(i, enProcessAnnotatorTime).timeAndPercentString(dTotalProcessDocumentTime).c_str());
          rConsole.newline();
        }
      }                                            /* e-o-for */
    }

#endif //UIMA_DEBUG_ANNOTATOR_TIMING

  }

} // namespace uima

/* <EOF> */


