/**
  * Starts to run the import
  * @param array( SQLIImportItem ) $aImportItems
  * @throws SQLIImportBaseException
  * @throws ezcConfigurationNoConfigException
  */
 public function runImport(array $aImportItems)
 {
     // First check if an import is already running
     if (SQLIImportToken::importIsRunning()) {
         throw new SQLIImportBaseException('Another import is already running. Aborting...', SQLIImportBaseException::IMPORT_ALREADY_RUNNING);
     }
     $this->token = SQLIImportToken::registerNewImport();
     $this->handlePerformanceSettings();
     if (empty($aImportItems)) {
         // If no source handler is provided, consider processing all source handlers available
         $aImportItems = $this->importINI->variable('ImportSettings', 'AvailableSourceHandlers');
     }
     // Process import items one by one
     for ($i = 0, $iMax = count($aImportItems); $i < $iMax; ++$i) {
         try {
             if (!$aImportItems[$i] instanceof SQLIImportItem) {
                 throw new SQLIImportRuntimeException('Invalid import item !');
             }
             // Update status for import item
             $aImportItems[$i]->setAttribute('status', SQLIImportItem::STATUS_RUNNING);
             $aImportItems[$i]->store();
             $this->currentImportItem = $aImportItems[$i];
             // First check if this handler has all needed configuration
             $handler = $aImportItems[$i]->attribute('handler');
             $handlerSection = $handler . '-HandlerSettings';
             if (!$this->importINI->hasSection($handlerSection)) {
                 // Check INI Section
                 throw new ezcConfigurationNoConfigException('Error : Handler "' . $handler . '" does not have proper config section in sqliimport.ini !');
             }
             if (!$this->importINI->hasVariable($handlerSection, 'ClassName')) {
                 // Check if ClassName is properly defined
                 throw new ezcConfigurationNoConfigException('Error : ClassName not defined for "' . $handler . '" in sqliimport.ini !');
             }
             // Default values
             $handlerClassName = $this->importINI->variable($handlerSection, 'ClassName');
             $handlerEnabled = true;
             $debug = false;
             $defaultParentNodeID = $this->importINI->variable('ImportSettings', 'DefaultParentNodeID');
             $streamTimeout = $this->importINI->variable('ImportSettings', 'StreamTimeout');
             if ($this->importINI->hasVariable($handlerSection, 'Enabled')) {
                 $handlerEnabled = $this->importINI->variable($handlerSection, 'Enabled') === 'true';
             }
             if ($this->importINI->hasVariable($handlerSection, 'Debug')) {
                 $debug = $this->importINI->variable($handlerSection, 'Debug') === 'enabled';
             }
             if ($this->importINI->hasVariable($handlerSection, 'DefaultParentNodeID')) {
                 $localParentNodeID = $this->importINI->variable($handlerSection, 'DefaultParentNodeID');
                 $defaultParentNodeID = is_int($localParentNodeID) ? (int) $localParentNode : $defaultParentNodeID;
             }
             if ($this->importINI->hasVariable($handlerSection, 'StreamTimeout')) {
                 $streamTimeout = (int) $this->importINI->variable($handlerSection, 'StreamTimeout');
             }
             // Check $defaultParentNodeID and throw an exception if not consistent
             $parentNode = eZContentObjectTreeNode::fetch($defaultParentNodeID, false, false);
             if (!$parentNode) {
                 throw new SQLIImportRuntimeException('Error : invalid DefaultParentNodeID ( ' . $defaultParentNodeID . ' )');
             }
             unset($parentNode);
             // Check handler class validity
             if (!class_exists($handlerClassName)) {
                 throw new SQLIImportRuntimeException('Error : invalid handler class "' . $handlerClassName . '". Did you regenerate autolads ?');
             }
             // ####################################
             // ##### IMPORT HANDLER PROCESSING
             // ####################################
             // Instantiate the handler with appropriate options and process it.
             // Handler must implement ISQLIImportHandler and extend SQLIImportAbstractHandler
             $handlerOptions = $aImportItems[$i]->attribute('options');
             $importHandler = new $handlerClassName($handlerOptions);
             if (!$importHandler instanceof ISQLIImportHandler || !$importHandler instanceof SQLIImportAbstractHandler) {
                 throw new SQLIImportRuntimeException('Error : invalid handler "' . $handlerClassName . '". Must implement ISQLIImportHandler and extend SQLIImportAbstractHandler.');
             }
             $importHandler->handlerConfArray = $this->importINI->group($handlerSection);
             $importHandler->initialize();
             // Get process length to calculate advancement percentage to track advancement
             $processLength = $importHandler->getProcessLength();
             $percentageAdvancementStep = 100 / $processLength;
             $handlerName = $importHandler->getHandlerName();
             $handlerIdentifier = $importHandler->getHandlerIdentifier();
             // Progress bar implementation
             $progressBarOptions = array('emptyChar' => ' ', 'barChar' => '=');
             $progressBar = new ezcConsoleProgressbar($this->output, $processLength, $progressBarOptions);
             $progressBar->start();
             $this->cli->warning('Now processing "' . $handlerName . '" handler.');
             $isInterrupted = false;
             while ($row = $importHandler->getNextRow()) {
                 try {
                     $progressBar->advance();
                     $startTime = time();
                     $importHandler->process($row);
                 } catch (Exception $e) {
                     SQLIImportLogger::logError('An error occurred during "' . $handlerIdentifier . '" import process : ' . $e->getMessage());
                 }
                 $aImportItems[$i]->updateProgress($percentageAdvancementStep, $importHandler->getProgressionNotes());
                 // Now calculate process time for this iteration
                 $endTime = time();
                 $diffTime = $endTime - $startTime;
                 $oldProcessTime = $aImportItems[$i]->attribute('process_time');
                 $aImportItems[$i]->setAttribute('process_time', $oldProcessTime + $diffTime);
                 $aImportItems[$i]->store(array('process_time'));
                 // Interruption handling
                 if ($aImportItems[$i]->isInterrupted()) {
                     $this->cli->notice();
                     SQLIImportLogger::logNotice('Interruption has been requested for current import ! Cleaning and aborting process...');
                     $isInterrupted = true;
                     break;
                 }
             }
             $importHandler->cleanup();
             $progressBar->finish();
             $this->cli->notice();
             unset($importHandler);
             if (!$isInterrupted) {
                 $aImportItems[$i]->setAttribute('status', SQLIImportItem::STATUS_COMPLETED);
                 $aImportItems[$i]->setAttribute('percentage', 100);
                 // Force percentage to 100%
                 $aImportItems[$i]->store();
             }
             // ####################################
             // ##### END IMPORT HANDLER PROCESSING
             // ####################################
         } catch (Exception $e) {
             SQLIImportLogger::logError($e->getMessage());
             $aImportItems[$i]->setAttribute('status', SQLIImportItem::STATUS_FAILED);
             $aImportItems[$i]->store();
             if (isset($importHandler)) {
                 $importHandler->cleanup();
                 unset($importHandler);
             }
             continue;
         }
     }
 }