protected function import( array $products, array $data, array $mapping, array $types,
		\Aimeos\Controller\Common\Product\Import\Csv\Processor\Iface $processor, $strict )
	{
		$items = [];
		$errors = 0;
		$context = $this->getContext();
		$manager = \Aimeos\MShop::create( $context, 'product' );
		$indexManager = \Aimeos\MShop::create( $context, 'index' );

		foreach( $data as $code => $list )
		{
			$manager->begin();

			try
			{
				$code = trim( $code );

				if( isset( $products[$code] ) ) {
					$product = $products[$code];
				} else {
					$product = $manager->createItem();
				}

				$map = $this->getMappedChunk( $list, $mapping );

				if( isset( $map[0] ) )
				{
					$map = $map[0]; // there can only be one chunk for the base product data
					$map['product.type'] = $this->getValue( $map, 'product.type', 'default' );

					if( !in_array( $map['product.type'], $types ) )
					{
						$msg = sprintf( 'Invalid product type "%1$s"', $map['product.type'] );
						throw new \Aimeos\Controller\Jobs\Exception( $msg );
					}

					$product = $manager->saveItem( $product->fromArray( $map, true ) );

					$list = $processor->process( $product, $list );

					$product = $manager->saveItem( $product );
					$items[$product->getId()] = $product;
				}

				$manager->commit();
			}
			catch( \Exception $e )
			{
				$manager->rollback();

				$msg = sprintf( 'Unable to import product with code "%1$s": %2$s', $code, $e->getMessage() );
				$context->getLogger()->log( $msg );

				$errors++;
			}

			if( $strict && !empty( $list ) ) {
				$context->getLogger()->log( 'Not imported: ' . print_r( $list, true ) );
			}
		}

		$indexManager->rebuildIndex( $items );

		return $errors;
	}