diff --git a/app/code/Magento/AdvancedPricingImportExport/Model/Indexer/Product/Price/Plugin/Import.php b/app/code/Magento/AdvancedPricingImportExport/Model/Indexer/Product/Price/Plugin/Import.php
index d1b94795ecb3283a7af902fd6561c65aa3332db9..d9991e65504c9ccf9f415dadc7c3888306943257 100644
--- a/app/code/Magento/AdvancedPricingImportExport/Model/Indexer/Product/Price/Plugin/Import.php
+++ b/app/code/Magento/AdvancedPricingImportExport/Model/Indexer/Product/Price/Plugin/Import.php
@@ -40,7 +40,7 @@ class Import extends \Magento\Catalog\Model\Indexer\Product\Price\Plugin\Abstrac
     /**
      * Get price indexer
      *
-     * @return \Magento\Indexer\Model\IndexerInterface
+     * @return \Magento\Framework\Indexer\IndexerInterface
      */
     protected function getPriceIndexer()
     {
diff --git a/app/code/Magento/AdvancedPricingImportExport/Test/Unit/Model/Indexer/Product/Price/Plugin/ImportTest.php b/app/code/Magento/AdvancedPricingImportExport/Test/Unit/Model/Indexer/Product/Price/Plugin/ImportTest.php
index f12d4026ef829992e130ef794ecb43f34a1f99f9..d9e22043ccc577cf91a703cd99f06748dc8b3a06 100644
--- a/app/code/Magento/AdvancedPricingImportExport/Test/Unit/Model/Indexer/Product/Price/Plugin/ImportTest.php
+++ b/app/code/Magento/AdvancedPricingImportExport/Test/Unit/Model/Indexer/Product/Price/Plugin/ImportTest.php
@@ -11,7 +11,7 @@ use \Magento\AdvancedPricingImportExport\Model\Indexer\Product\Price\Plugin\Impo
 class ImportTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Indexer\Model\IndexerInterface |\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerInterface |\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexer;
 
@@ -27,7 +27,7 @@ class ImportTest extends \PHPUnit_Framework_TestCase
 
     public function setUp()
     {
-        $this->indexer = $this->getMockForAbstractClass('\Magento\Indexer\Model\IndexerInterface', [], '', false);
+        $this->indexer = $this->getMockForAbstractClass('\Magento\Framework\Indexer\IndexerInterface', [], '', false);
         $this->import = $this->getMock(
             '\Magento\AdvancedPricingImportExport\Model\Indexer\Product\Price\Plugin\Import',
             ['getPriceIndexer', 'invalidateIndexer'],
diff --git a/app/code/Magento/Catalog/Model/Category.php b/app/code/Magento/Catalog/Model/Category.php
index a36f20f4f699e40a7acc4d0609fa06239e50c768..7c745801c12c9106db67885d5c1c97728253356f 100644
--- a/app/code/Magento/Catalog/Model/Category.php
+++ b/app/code/Magento/Catalog/Model/Category.php
@@ -210,7 +210,7 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements
     /** @var UrlFinderInterface */
     protected $urlFinder;
 
-    /** @var \Magento\Indexer\Model\IndexerRegistry */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
     protected $indexerRegistry;
 
     /**
@@ -240,7 +240,7 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements
      * @param Indexer\Category\Flat\State $flatState
      * @param \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator
      * @param UrlFinderInterface $urlFinder
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      * @param CategoryRepositoryInterface $categoryRepository
      * @param \Magento\Framework\Model\Resource\AbstractResource $resource
      * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
@@ -264,7 +264,7 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements
         Indexer\Category\Flat\State $flatState,
         \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator,
         UrlFinderInterface $urlFinder,
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         CategoryRepositoryInterface $categoryRepository,
         \Magento\Framework\Model\Resource\AbstractResource $resource = null,
         \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
diff --git a/app/code/Magento/Catalog/Model/Indexer/AbstractFlatState.php b/app/code/Magento/Catalog/Model/Indexer/AbstractFlatState.php
index ee3f56b70d965639b28d298b3356eb4f926cd437..1787ff1cf66c642e2a4c9a6d88250a43eb66178b 100644
--- a/app/code/Magento/Catalog/Model/Indexer/AbstractFlatState.php
+++ b/app/code/Magento/Catalog/Model/Indexer/AbstractFlatState.php
@@ -29,17 +29,17 @@ abstract class AbstractFlatState
      */
     protected $isAvailable;
 
-    /** @var \Magento\Indexer\Model\IndexerRegistry */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
     protected $indexerRegistry;
 
     /**
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      * @param bool $isAvailable
      */
     public function __construct(
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         $isAvailable = false
     ) {
         $this->scopeConfig = $scopeConfig;
diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/AffectCache.php b/app/code/Magento/Catalog/Model/Indexer/Category/AffectCache.php
index 124424648050de9216a216c51ed877de2a96bd16..6e8f57f37bd99c1e920d238718e0f10693dc127d 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Category/AffectCache.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Category/AffectCache.php
@@ -12,26 +12,26 @@ namespace Magento\Catalog\Model\Indexer\Category;
 class AffectCache
 {
     /**
-     * @var \Magento\Indexer\Model\CacheContext
+     * @var \Magento\Framework\Indexer\CacheContext
      */
     protected $context;
 
     /**
-     * @param \Magento\Indexer\Model\CacheContext $context
+     * @param \Magento\Framework\Indexer\CacheContext $context
      */
     public function __construct(
-        \Magento\Indexer\Model\CacheContext $context
+        \Magento\Framework\Indexer\CacheContext $context
     ) {
         $this->context = $context;
     }
 
     /**
-     * @param \Magento\Indexer\Model\ActionInterface $subject
+     * @param \Magento\Framework\Indexer\ActionInterface $subject
      * @param array $ids
      * @return array
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function beforeExecute(\Magento\Indexer\Model\ActionInterface $subject, $ids)
+    public function beforeExecute(\Magento\Framework\Indexer\ActionInterface $subject, $ids)
     {
         $this->context->registerEntities(\Magento\Catalog\Model\Category::CACHE_TAG, $ids);
         return [$ids];
diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/Flat.php b/app/code/Magento/Catalog/Model/Indexer/Category/Flat.php
index 16f10216ed945e1f9b6b6973d19db1d92a91b96c..fa3bc07ac3f643ae758f98cce0b3f74e65eb3683 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Category/Flat.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Category/Flat.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Catalog\Model\Indexer\Category;
 
-class Flat implements \Magento\Indexer\Model\ActionInterface, \Magento\Framework\Mview\ActionInterface
+class Flat implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
 {
     /**
      * @var \Magento\Catalog\Model\Indexer\Category\Flat\Action\FullFactory
@@ -17,18 +17,18 @@ class Flat implements \Magento\Indexer\Model\ActionInterface, \Magento\Framework
      */
     protected $rowsActionFactory;
 
-    /** @var \Magento\Indexer\Model\IndexerRegistry */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
     protected $indexerRegistry;
 
     /**
      * @param Flat\Action\FullFactory $fullActionFactory
      * @param Flat\Action\RowsFactory $rowsActionFactory
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      */
     public function __construct(
         Flat\Action\FullFactory $fullActionFactory,
         Flat\Action\RowsFactory $rowsActionFactory,
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
     ) {
         $this->fullActionFactory = $fullActionFactory;
         $this->rowsActionFactory = $rowsActionFactory;
diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/Flat/Plugin/StoreGroup.php b/app/code/Magento/Catalog/Model/Indexer/Category/Flat/Plugin/StoreGroup.php
index 29c42f6e15773a78d551505d910aa6ad163f7a3e..8ef69f4fb5d9642f71d5b1776b51ded75137bfaa 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Category/Flat/Plugin/StoreGroup.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Category/Flat/Plugin/StoreGroup.php
@@ -7,7 +7,7 @@ namespace Magento\Catalog\Model\Indexer\Category\Flat\Plugin;
 
 class StoreGroup
 {
-    /** @var \Magento\Indexer\Model\IndexerRegistry */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
     protected $indexerRegistry;
 
     /**
@@ -16,11 +16,11 @@ class StoreGroup
     protected $state;
 
     /**
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      * @param \Magento\Catalog\Model\Indexer\Category\Flat\State $state
      */
     public function __construct(
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         \Magento\Catalog\Model\Indexer\Category\Flat\State $state
     ) {
         $this->indexerRegistry = $indexerRegistry;
diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/Flat/System/Config/Mode.php b/app/code/Magento/Catalog/Model/Indexer/Category/Flat/System/Config/Mode.php
index eac2cb0d79b333c4149fbc6cfc5b7d372c64e13a..df01da1a9cf773a6ac32d8021596a436b34abbac 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Category/Flat/System/Config/Mode.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Category/Flat/System/Config/Mode.php
@@ -13,14 +13,14 @@ class Mode extends \Magento\Framework\App\Config\Value
     /** @var \Magento\Indexer\Model\Indexer\State */
     protected $indexerState;
 
-    /** @var \Magento\Indexer\Model\IndexerRegistry */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
     protected $indexerRegistry;
 
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $config
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      * @param \Magento\Indexer\Model\Indexer\State $indexerState
      * @param \Magento\Framework\Model\Resource\AbstractResource $resource
      * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
@@ -30,7 +30,7 @@ class Mode extends \Magento\Framework\App\Config\Value
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Framework\App\Config\ScopeConfigInterface $config,
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         \Magento\Indexer\Model\Indexer\State $indexerState,
         \Magento\Framework\Model\Resource\AbstractResource $resource = null,
         \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
@@ -62,7 +62,7 @@ class Mode extends \Magento\Framework\App\Config\Value
         if ((bool)$this->getValue() != (bool)$this->getOldValue()) {
             if ((bool)$this->getValue()) {
                 $this->indexerState->loadByIndexer(\Magento\Catalog\Model\Indexer\Category\Flat\State::INDEXER_ID);
-                $this->indexerState->setStatus(\Magento\Indexer\Model\Indexer\State::STATUS_INVALID);
+                $this->indexerState->setStatus(\Magento\Framework\Indexer\StateInterface::STATUS_INVALID);
                 $this->indexerState->save();
             } else {
                 $this->indexerRegistry->get(\Magento\Catalog\Model\Indexer\Category\Flat\State::INDEXER_ID)
diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/Product.php b/app/code/Magento/Catalog/Model/Indexer/Category/Product.php
index 78c0e84fa7993b0024acfb207207d77baa5a9981..fcd29869abe727ec81f5bf429887509eba9a7725 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Category/Product.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Category/Product.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Catalog\Model\Indexer\Category;
 
-class Product implements \Magento\Indexer\Model\ActionInterface, \Magento\Framework\Mview\ActionInterface
+class Product implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
 {
     /**
      * Indexer ID in configuration
@@ -22,18 +22,18 @@ class Product implements \Magento\Indexer\Model\ActionInterface, \Magento\Framew
      */
     protected $rowsActionFactory;
 
-    /** @var \Magento\Indexer\Model\IndexerRegistry */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
     protected $indexerRegistry;
 
     /**
      * @param Product\Action\FullFactory $fullActionFactory
      * @param Product\Action\RowsFactory $rowsActionFactory
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      */
     public function __construct(
         Product\Action\FullFactory $fullActionFactory,
         Product\Action\RowsFactory $rowsActionFactory,
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
     ) {
         $this->fullActionFactory = $fullActionFactory;
         $this->rowsActionFactory = $rowsActionFactory;
diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/Product/Plugin/StoreGroup.php b/app/code/Magento/Catalog/Model/Indexer/Category/Product/Plugin/StoreGroup.php
index ef9def13549270f2eb72db01f47d370be1cc574f..c8b79bc66877bdd6f49130f88160b162ee97e1af 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Category/Product/Plugin/StoreGroup.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Category/Product/Plugin/StoreGroup.php
@@ -7,13 +7,13 @@ namespace Magento\Catalog\Model\Indexer\Category\Product\Plugin;
 
 class StoreGroup
 {
-    /** @var \Magento\Indexer\Model\IndexerRegistry */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
     protected $indexerRegistry;
 
     /**
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      */
-    public function __construct(\Magento\Indexer\Model\IndexerRegistry $indexerRegistry)
+    public function __construct(\Magento\Framework\Indexer\IndexerRegistry $indexerRegistry)
     {
         $this->indexerRegistry = $indexerRegistry;
     }
diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/Product/Processor.php b/app/code/Magento/Catalog/Model/Indexer/Category/Product/Processor.php
index 704cfb685c2870c3595a5f45adf93533cee1ac7a..612b8ac6d5476b3ea52d6b66b0f5cc7b23007526 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Category/Product/Processor.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Category/Product/Processor.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Catalog\Model\Indexer\Category\Product;
 
-class Processor extends \Magento\Indexer\Model\Indexer\AbstractProcessor
+class Processor extends \Magento\Framework\Indexer\AbstractProcessor
 {
     /**
      * Indexer ID
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/AffectCache.php b/app/code/Magento/Catalog/Model/Indexer/Product/AffectCache.php
index 5e997400ec23e0725b745c0f0b359d92e9ccdfe4..37cbca1907735dcca9f98f207c7135dddef02173 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/AffectCache.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/AffectCache.php
@@ -12,26 +12,26 @@ namespace Magento\Catalog\Model\Indexer\Product;
 class AffectCache
 {
     /**
-     * @var \Magento\Indexer\Model\CacheContext $context
+     * @var \Magento\Framework\Indexer\CacheContext $context
      */
     protected $context;
 
     /**
-     * @param \Magento\Indexer\Model\CacheContext $context
+     * @param \Magento\Framework\Indexer\CacheContext $context
      */
     public function __construct(
-        \Magento\Indexer\Model\CacheContext $context
+        \Magento\Framework\Indexer\CacheContext $context
     ) {
         $this->context = $context;
     }
 
     /**
-     * @param \Magento\Indexer\Model\ActionInterface $subject
+     * @param \Magento\Framework\Indexer\ActionInterface $subject
      * @param array $ids
      * @return array
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function beforeExecute(\Magento\Indexer\Model\ActionInterface $subject, $ids)
+    public function beforeExecute(\Magento\Framework\Indexer\ActionInterface $subject, $ids)
     {
         $this->context->registerEntities(\Magento\Catalog\Model\Product::CACHE_TAG, $ids);
         return [$ids];
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Category.php b/app/code/Magento/Catalog/Model/Indexer/Product/Category.php
index f90f86f8f0bff53107f42825f1b9f7f5fe9fd000..ed268cf8997f94bee6d81583dba73130b8ffcb05 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Category.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Category.php
@@ -15,12 +15,12 @@ class Category extends \Magento\Catalog\Model\Indexer\Category\Product
     /**
      * @param \Magento\Catalog\Model\Indexer\Category\Product\Action\FullFactory $fullActionFactory
      * @param Category\Action\RowsFactory $rowsActionFactory
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      */
     public function __construct(
         \Magento\Catalog\Model\Indexer\Category\Product\Action\FullFactory $fullActionFactory,
         Category\Action\RowsFactory $rowsActionFactory,
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
     ) {
         parent::__construct($fullActionFactory, $rowsActionFactory, $indexerRegistry);
     }
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Category/Processor.php b/app/code/Magento/Catalog/Model/Indexer/Product/Category/Processor.php
index e99442ef43fe34513ab7e69742e2e34aab80469c..dcefc5953cefda964d48629ea8e991ff1b1daf3f 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Category/Processor.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Category/Processor.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Catalog\Model\Indexer\Product\Category;
 
-class Processor extends \Magento\Indexer\Model\Indexer\AbstractProcessor
+class Processor extends \Magento\Framework\Indexer\AbstractProcessor
 {
     /**
      * Indexer ID
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Eav.php b/app/code/Magento/Catalog/Model/Indexer/Product/Eav.php
index 54ca94657d5e13caf318c13eab81a1c023fa5ad3..a87a4e5e82e6cbf56275523ee38bb7149d8c1945 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Eav.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Eav.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Catalog\Model\Indexer\Product;
 
-class Eav implements \Magento\Indexer\Model\ActionInterface, \Magento\Framework\Mview\ActionInterface
+class Eav implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
 {
     /**
      * @var \Magento\Catalog\Model\Indexer\Product\Eav\Action\Row
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Eav/Processor.php b/app/code/Magento/Catalog/Model/Indexer/Product/Eav/Processor.php
index 1799d549499fd74498d69a1206abf81587382548..598d96d2f86ac2abcd6c88b9feba2ff7b0f06bdc 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Eav/Processor.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Eav/Processor.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Catalog\Model\Indexer\Product\Eav;
 
-class Processor extends \Magento\Indexer\Model\Indexer\AbstractProcessor
+class Processor extends \Magento\Framework\Indexer\AbstractProcessor
 {
     /**
      * Indexer ID
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat.php
index 82a9203d9a3286f097c7666ecd5d0b6341fc12d7..d151b98af56f6ea2f1d72a685b1434bb8565e4cb 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Catalog\Model\Indexer\Product;
 
-class Flat implements \Magento\Indexer\Model\ActionInterface, \Magento\Framework\Mview\ActionInterface
+class Flat implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
 {
     /**
      * @var \Magento\Catalog\Model\Indexer\Product\Flat\Action\Row
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Processor.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Processor.php
index e7181ba7098b43d3831cf46776c51dc657c7ba91..0e0238b3a6dd5ca6f2dc1ba313b4c7c6eac5b21e 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Processor.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Processor.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Catalog\Model\Indexer\Product\Flat;
 
-class Processor extends \Magento\Indexer\Model\Indexer\AbstractProcessor
+class Processor extends \Magento\Framework\Indexer\AbstractProcessor
 {
     /**
      * Indexer ID
@@ -18,11 +18,11 @@ class Processor extends \Magento\Indexer\Model\Indexer\AbstractProcessor
     protected $_state;
 
     /**
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      * @param State $state
      */
     public function __construct(
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         \Magento\Catalog\Model\Indexer\Product\Flat\State $state
     ) {
         parent::__construct($indexerRegistry);
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/State.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/State.php
index 1680f2d72e57a4cf7a5f5b34de68fe3511f7cc80..4afcfcd52947a0d746e63eb9ef89092c274f6942 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/State.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/State.php
@@ -24,13 +24,13 @@ class State extends \Magento\Catalog\Model\Indexer\AbstractFlatState
 
     /**
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      * @param \Magento\Catalog\Helper\Product\Flat\Indexer $flatIndexerHelper
      * @param bool $isAvailable
      */
     public function __construct(
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         \Magento\Catalog\Helper\Product\Flat\Indexer $flatIndexerHelper,
         $isAvailable = false
     ) {
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/System/Config/Mode.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/System/Config/Mode.php
index fddf5015b841c3ca9d7070d8d7ed393c74d2dd97..a0206fc2b43905d47f246532dec33ad5efc7703b 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/System/Config/Mode.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/System/Config/Mode.php
@@ -66,7 +66,7 @@ class Mode extends \Magento\Framework\App\Config\Value
         if ((bool)$this->getValue() != (bool)$this->getOldValue()) {
             if ((bool)$this->getValue()) {
                 $this->indexerState->loadByIndexer(\Magento\Catalog\Model\Indexer\Product\Flat\Processor::INDEXER_ID);
-                $this->indexerState->setStatus(\Magento\Indexer\Model\Indexer\State::STATUS_INVALID);
+                $this->indexerState->setStatus(\Magento\Framework\Indexer\StateInterface::STATUS_INVALID);
                 $this->indexerState->save();
             } else {
                 $this->_productFlatIndexerProcessor->getIndexer()->setScheduled(false);
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price.php
index 8b060e4813a8968fbc86510f6478ed14d7950310..f8d80ad185e47834c8eda31f1de5944f18e9fcf9 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Price.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Catalog\Model\Indexer\Product;
 
-class Price implements \Magento\Indexer\Model\ActionInterface, \Magento\Framework\Mview\ActionInterface
+class Price implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
 {
     /**
      * @var \Magento\Catalog\Model\Indexer\Product\Price\Action\Row
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Plugin/AbstractPlugin.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/Plugin/AbstractPlugin.php
index b22b4cc2c25611c35c50eb904af680113f5621c2..68a7ff84a1a92e570c225e083977b511f11679c2 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Plugin/AbstractPlugin.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/Plugin/AbstractPlugin.php
@@ -7,13 +7,13 @@ namespace Magento\Catalog\Model\Indexer\Product\Price\Plugin;
 
 abstract class AbstractPlugin
 {
-    /** @var \Magento\Indexer\Model\IndexerRegistry */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
     protected $indexerRegistry;
 
     /**
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      */
-    public function __construct(\Magento\Indexer\Model\IndexerRegistry $indexerRegistry)
+    public function __construct(\Magento\Framework\Indexer\IndexerRegistry $indexerRegistry)
     {
         $this->indexerRegistry = $indexerRegistry;
     }
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Processor.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/Processor.php
index 4fa565b61104184316aeb35905aa2494d811fa48..e416fefb15cabfff56a00a99ae1b86de17ead661 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Processor.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/Processor.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Catalog\Model\Indexer\Product\Price;
 
-class Processor extends \Magento\Indexer\Model\Indexer\AbstractProcessor
+class Processor extends \Magento\Framework\Indexer\AbstractProcessor
 {
     /**
      * Indexer ID
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/System/Config/PriceScope.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/System/Config/PriceScope.php
index 596495c247e91dfb3e729835e2e6e268f702ddad..42e27c7bd3e0d3f5f27e434ffa3a5ba131311651 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/System/Config/PriceScope.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/System/Config/PriceScope.php
@@ -10,14 +10,14 @@ namespace Magento\Catalog\Model\Indexer\Product\Price\System\Config;
  */
 class PriceScope extends \Magento\Framework\App\Config\Value
 {
-    /** @var \Magento\Indexer\Model\IndexerRegistry */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
     protected $indexerRegistry;
 
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $config
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      * @param \Magento\Framework\Model\Resource\AbstractResource $resource
      * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
      * @param array $data
@@ -26,7 +26,7 @@ class PriceScope extends \Magento\Framework\App\Config\Value
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Framework\App\Config\ScopeConfigInterface $config,
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         \Magento\Framework\Model\Resource\AbstractResource $resource = null,
         \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
         array $data = []
diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php
index d37dee90cbfa375b7b056616d7f13331d6d18e04..dd0f5ec4ead4f93ae5a12313ada595359471ef03 100644
--- a/app/code/Magento/Catalog/Model/Product.php
+++ b/app/code/Magento/Catalog/Model/Product.php
@@ -216,7 +216,7 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements
      */
     protected $_filesystem;
 
-    /** @var \Magento\Indexer\Model\IndexerRegistry */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
     protected $indexerRegistry;
 
     /**
@@ -344,7 +344,7 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements
      * @param Resource\Product\Collection $resourceCollection
      * @param \Magento\Framework\Data\CollectionFactory $collectionFactory
      * @param \Magento\Framework\Filesystem $filesystem
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      * @param Indexer\Product\Flat\Processor $productFlatIndexerProcessor
      * @param Indexer\Product\Price\Processor $productPriceIndexerProcessor
      * @param Indexer\Product\Eav\Processor $productEavIndexerProcessor
@@ -383,7 +383,7 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements
         Resource\Product\Collection $resourceCollection,
         \Magento\Framework\Data\CollectionFactory $collectionFactory,
         \Magento\Framework\Filesystem $filesystem,
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         \Magento\Catalog\Model\Indexer\Product\Flat\Processor $productFlatIndexerProcessor,
         \Magento\Catalog\Model\Indexer\Product\Price\Processor $productPriceIndexerProcessor,
         \Magento\Catalog\Model\Indexer\Product\Eav\Processor $productEavIndexerProcessor,
diff --git a/app/code/Magento/Catalog/Model/Product/Action.php b/app/code/Magento/Catalog/Model/Product/Action.php
index 3bc9a563dca08ee68941ee0323b83573a102af13..b9ef8e4baa4a9d00cdbf0c91da47134aaa7e5d26 100644
--- a/app/code/Magento/Catalog/Model/Product/Action.php
+++ b/app/code/Magento/Catalog/Model/Product/Action.php
@@ -22,7 +22,7 @@ class Action extends \Magento\Framework\Model\AbstractModel
      */
     protected $_productWebsiteFactory;
 
-    /** @var \Magento\Indexer\Model\IndexerRegistry */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
     protected $indexerRegistry;
 
     /**
@@ -39,7 +39,7 @@ class Action extends \Magento\Framework\Model\AbstractModel
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param WebsiteFactory $productWebsiteFactory
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      * @param \Magento\Eav\Model\Config $eavConfig
      * @param \Magento\Catalog\Model\Indexer\Product\Eav\Processor $productEavIndexerProcessor
      * @param \Magento\Framework\Model\Resource\AbstractResource $resource
@@ -50,7 +50,7 @@ class Action extends \Magento\Framework\Model\AbstractModel
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Catalog\Model\Product\WebsiteFactory $productWebsiteFactory,
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         \Magento\Eav\Model\Config $eavConfig,
         \Magento\Catalog\Model\Indexer\Product\Eav\Processor $productEavIndexerProcessor,
         \Magento\Framework\Model\Resource\AbstractResource $resource = null,
diff --git a/app/code/Magento/Catalog/Model/Resource/Category/Flat.php b/app/code/Magento/Catalog/Model/Resource/Category/Flat.php
index a6975725dfa8a3482d1785c2084e1c7b0ffa6063..645bd4478b93fa6816ed51c2e159228798c7968a 100644
--- a/app/code/Magento/Catalog/Model/Resource/Category/Flat.php
+++ b/app/code/Magento/Catalog/Model/Resource/Category/Flat.php
@@ -82,7 +82,7 @@ class Flat extends \Magento\Indexer\Model\Resource\AbstractResource
      * Class constructor
      *
      * @param \Magento\Framework\Model\Resource\Db\Context $context
-     * @param \Magento\Indexer\Model\Indexer\Table\StrategyInterface $tableStrategy
+     * @param \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy
      * @param \Magento\Catalog\Model\CategoryFactory $categoryFactory
      * @param CollectionFactory $categoryCollectionFactory
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -92,7 +92,7 @@ class Flat extends \Magento\Indexer\Model\Resource\AbstractResource
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
-        \Magento\Indexer\Model\Indexer\Table\StrategyInterface $tableStrategy,
+        \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy,
         \Magento\Catalog\Model\CategoryFactory $categoryFactory,
         \Magento\Catalog\Model\Resource\Category\CollectionFactory $categoryCollectionFactory,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
diff --git a/app/code/Magento/Catalog/Model/Resource/Product/Indexer/AbstractIndexer.php b/app/code/Magento/Catalog/Model/Resource/Product/Indexer/AbstractIndexer.php
index 606d91cf415fe5e4d85ba3e6a581b862f9a0764e..50e0a9c789ba80baaf7b55fb7e6bf09078d67e65 100644
--- a/app/code/Magento/Catalog/Model/Resource/Product/Indexer/AbstractIndexer.php
+++ b/app/code/Magento/Catalog/Model/Resource/Product/Indexer/AbstractIndexer.php
@@ -23,13 +23,13 @@ abstract class AbstractIndexer extends \Magento\Indexer\Model\Resource\AbstractR
      * Class constructor
      *
      * @param \Magento\Framework\Model\Resource\Db\Context $context
-     * @param \Magento\Indexer\Model\Indexer\Table\StrategyInterface $tableStrategy
+     * @param \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy
      * @param \Magento\Eav\Model\Config $eavConfig
      * @param string $connectionName
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
-        \Magento\Indexer\Model\Indexer\Table\StrategyInterface $tableStrategy,
+        \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy,
         \Magento\Eav\Model\Config $eavConfig,
         $connectionName = null
     ) {
diff --git a/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Eav/AbstractEav.php b/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Eav/AbstractEav.php
index eb664cc8d7bf5d016475df1e8d93f05181bff59a..83041be40e9f9386e5fd254724f753e380f909d3 100644
--- a/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Eav/AbstractEav.php
+++ b/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Eav/AbstractEav.php
@@ -23,14 +23,14 @@ abstract class AbstractEav extends \Magento\Catalog\Model\Resource\Product\Index
      * Construct
      *
      * @param \Magento\Framework\Model\Resource\Db\Context $context
-     * @param \Magento\Indexer\Model\Indexer\Table\StrategyInterface $tableStrategy
+     * @param \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy
      * @param \Magento\Eav\Model\Config $eavConfig
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param string $connectionName
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
-        \Magento\Indexer\Model\Indexer\Table\StrategyInterface $tableStrategy,
+        \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy,
         \Magento\Eav\Model\Config $eavConfig,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         $connectionName = null
diff --git a/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Eav/Source.php b/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Eav/Source.php
index 1fc02a3f2fed7303b36006fb6390260e6859ef0f..804be08a5b521fc36513b01d48dff0d51bdb1aed 100644
--- a/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Eav/Source.php
+++ b/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Eav/Source.php
@@ -25,7 +25,7 @@ class Source extends AbstractEav
      * Construct
      *
      * @param \Magento\Framework\Model\Resource\Db\Context $context
-     * @param \Magento\Indexer\Model\Indexer\Table\StrategyInterface $tableStrategy
+     * @param \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy
      * @param \Magento\Eav\Model\Config $eavConfig
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Catalog\Model\Resource\Helper $resourceHelper
@@ -33,7 +33,7 @@ class Source extends AbstractEav
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
-        \Magento\Indexer\Model\Indexer\Table\StrategyInterface $tableStrategy,
+        \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy,
         \Magento\Eav\Model\Config $eavConfig,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Catalog\Model\Resource\Helper $resourceHelper,
diff --git a/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Price/DefaultPrice.php b/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Price/DefaultPrice.php
index a38e1787038e300ddbbe1b4593cabc42087069d1..e1ff4568ae04fdec31ce2787b0f91c8d36cee751 100644
--- a/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Price/DefaultPrice.php
+++ b/app/code/Magento/Catalog/Model/Resource/Product/Indexer/Price/DefaultPrice.php
@@ -45,7 +45,7 @@ class DefaultPrice extends \Magento\Catalog\Model\Resource\Product\Indexer\Abstr
      * Class constructor
      *
      * @param \Magento\Framework\Model\Resource\Db\Context $context
-     * @param \Magento\Indexer\Model\Indexer\Table\StrategyInterface $tableStrategy
+     * @param \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy
      * @param \Magento\Eav\Model\Config $eavConfig
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Module\Manager $moduleManager
@@ -53,7 +53,7 @@ class DefaultPrice extends \Magento\Catalog\Model\Resource\Product\Indexer\Abstr
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
-        \Magento\Indexer\Model\Indexer\Table\StrategyInterface $tableStrategy,
+        \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy,
         \Magento\Eav\Model\Config $eavConfig,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\Module\Manager $moduleManager,
@@ -67,7 +67,7 @@ class DefaultPrice extends \Magento\Catalog\Model\Resource\Product\Indexer\Abstr
     /**
      * Get Table strategy
      *
-     * @return \Magento\Indexer\Model\Indexer\Table\StrategyInterface
+     * @return \Magento\Framework\Indexer\Table\StrategyInterface
      */
     public function getTableStrategy()
     {
diff --git a/app/code/Magento/Catalog/Plugin/Model/Product/Action/UpdateAttributesFlushCache.php b/app/code/Magento/Catalog/Plugin/Model/Product/Action/UpdateAttributesFlushCache.php
index 22133ccc921a18fe7e62c4ef658390f2c75a2a91..37e418217f30c6c659c6605fa4d8175c02c5eb46 100644
--- a/app/code/Magento/Catalog/Plugin/Model/Product/Action/UpdateAttributesFlushCache.php
+++ b/app/code/Magento/Catalog/Plugin/Model/Product/Action/UpdateAttributesFlushCache.php
@@ -7,7 +7,7 @@ namespace Magento\Catalog\Plugin\Model\Product\Action;
 
 use Magento\Catalog\Model\Product;
 use Magento\Catalog\Model\Product\Action;
-use Magento\Indexer\Model\CacheContext;
+use Magento\Framework\Indexer\CacheContext;
 use Magento\Framework\Event\ManagerInterface as EventManager;
 
 class UpdateAttributesFlushCache
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryTest.php
index cf4fbe668a4fbbf20d62598bd85ec25eb9d5a6a3..e8a165f8baac1be9e8f0da0e68a488433e42a77b 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryTest.php
@@ -61,10 +61,10 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Catalog\Model\Indexer\Category\Flat\State|\PHPUnit_Framework_MockObject_MockObject */
     protected $flatState;
 
-    /** @var \Magento\Indexer\Model\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject */
+    /** @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject */
     protected $flatIndexer;
 
-    /** @var \Magento\Indexer\Model\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject */
+    /** @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject */
     protected $productIndexer;
 
     /** @var \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator|\PHPUnit_Framework_MockObject_MockObject */
@@ -76,7 +76,7 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Framework\Model\Resource\AbstractResource|\PHPUnit_Framework_MockObject_MockObject */
     protected $resource;
 
-    /** @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject */
     protected $indexerRegistry;
 
     /**
@@ -140,8 +140,8 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->flatState = $this->getMock('Magento\Catalog\Model\Indexer\Category\Flat\State', [], [], '', false);
-        $this->flatIndexer = $this->getMock('Magento\Indexer\Model\IndexerInterface');
-        $this->productIndexer = $this->getMock('Magento\Indexer\Model\IndexerInterface');
+        $this->flatIndexer = $this->getMock('Magento\Framework\Indexer\IndexerInterface');
+        $this->productIndexer = $this->getMock('Magento\Framework\Indexer\IndexerInterface');
         $this->categoryUrlPathGenerator = $this->getMock(
             'Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator',
             [],
@@ -157,7 +157,7 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->indexerRegistry = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistry = $this->getMock('Magento\Framework\Indexer\IndexerRegistry', ['get'], [], '', false);
 
         $this->metadataServiceMock = $this->getMock('\Magento\Catalog\Api\CategoryAttributeRepositoryInterface');
         $this->attributeValueFactory = $this->getMockBuilder('Magento\Framework\Api\AttributeValueFactory')
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/AffectCacheTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/AffectCacheTest.php
index 5200af2d484a8b80765da1a2b76b13f012db81fe..f7d937162e87ad73cf7aeeda9576b3c97c872400 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/AffectCacheTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/AffectCacheTest.php
@@ -16,12 +16,12 @@ class AffectCacheTest extends \PHPUnit_Framework_TestCase
     protected $plugin;
 
     /**
-     * @var \Magento\Indexer\Model\CacheContext|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\CacheContext|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $contextMock;
 
     /**
-     * @var \Magento\Indexer\Model\ActionInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\ActionInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $subjectMock;
 
@@ -30,9 +30,9 @@ class AffectCacheTest extends \PHPUnit_Framework_TestCase
      */
     public function setUp()
     {
-        $this->subjectMock = $this->getMockForAbstractClass('Magento\Indexer\Model\ActionInterface',
+        $this->subjectMock = $this->getMockForAbstractClass('Magento\Framework\Indexer\ActionInterface',
             [], '', false, true, true, []);
-        $this->contextMock = $this->getMock('Magento\Indexer\Model\CacheContext',
+        $this->contextMock = $this->getMock('Magento\Framework\Indexer\CacheContext',
             [], [], '', false);
         $this->plugin = new \Magento\Catalog\Model\Indexer\Category\AffectCache($this->contextMock);
     }
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/Plugin/StoreGroupTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/Plugin/StoreGroupTest.php
index def1e5bf393f2569517c6e6140f139eaedb748dc..f0cca672ff9ac7ea76de02d59125067ef863a70f 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/Plugin/StoreGroupTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/Plugin/StoreGroupTest.php
@@ -10,7 +10,7 @@ use \Magento\Catalog\Model\Indexer\Category\Flat\Plugin\StoreGroup;
 class StoreGroupTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Indexer\Model\IndexerInterface
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Indexer\IndexerInterface
      */
     protected $indexerMock;
 
@@ -30,7 +30,7 @@ class StoreGroupTest extends \PHPUnit_Framework_TestCase
     protected $subjectMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -47,7 +47,7 @@ class StoreGroupTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->indexerMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\IndexerInterface',
+            'Magento\Framework\Indexer\IndexerInterface',
             [],
             '',
             false,
@@ -75,7 +75,13 @@ class StoreGroupTest extends \PHPUnit_Framework_TestCase
             return false;
         };
 
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
 
         $this->model = new StoreGroup($this->indexerRegistryMock, $this->stateMock);
     }
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/Plugin/StoreViewTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/Plugin/StoreViewTest.php
index 7847dd46f004708f7e27b953356a2bc0f40fab27..dfe07e9870b63d8badefd69fc9b0e76101cc51e4 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/Plugin/StoreViewTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/Plugin/StoreViewTest.php
@@ -10,7 +10,7 @@ use \Magento\Catalog\Model\Indexer\Category\Flat\Plugin\StoreView;
 class StoreViewTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Indexer\Model\IndexerInterface
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Indexer\IndexerInterface
      */
     protected $indexerMock;
 
@@ -25,7 +25,7 @@ class StoreViewTest extends \PHPUnit_Framework_TestCase
     protected $model;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -42,7 +42,7 @@ class StoreViewTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->indexerMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\IndexerInterface',
+            'Magento\Framework\Indexer\IndexerInterface',
             [],
             '',
             false,
@@ -61,7 +61,13 @@ class StoreViewTest extends \PHPUnit_Framework_TestCase
             return false;
         };
         $this->subjectMock = $this->getMock('Magento\Store\Model\Resource\Store', [], [], '', false);
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
         $this->model = new StoreView($this->indexerRegistryMock, $this->stateMock);
     }
 
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/StateTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/StateTest.php
index d1504bd77dc8eccc4c47b235bce43412551bafc9..6b36ba41a5459c827ae8e6b05db61bfc926a208f 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/StateTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/StateTest.php
@@ -18,12 +18,12 @@ class StateTest extends \PHPUnit_Framework_TestCase
     protected $scopeConfigMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $flatIndexerMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -32,7 +32,7 @@ class StateTest extends \PHPUnit_Framework_TestCase
         $this->scopeConfigMock = $this->getMockForAbstractClass('Magento\Framework\App\Config\ScopeConfigInterface');
 
         $this->flatIndexerMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\IndexerInterface',
+            'Magento\Framework\Indexer\IndexerInterface',
             [],
             '',
             false,
@@ -41,7 +41,13 @@ class StateTest extends \PHPUnit_Framework_TestCase
             ['getId', 'getState', '__wakeup']
         );
 
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
     }
 
     public function testIsFlatEnabled()
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/System/Config/ModeTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/System/Config/ModeTest.php
index cfc71fb65953df1362d7e6aa073bb79f31c2d675..3fc50823e08ec134b99533338ec4a5caa3307495 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/System/Config/ModeTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Flat/System/Config/ModeTest.php
@@ -23,12 +23,12 @@ class ModeTest extends \PHPUnit_Framework_TestCase
     protected $indexerStateMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistry;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $flatIndexer;
 
@@ -42,9 +42,9 @@ class ModeTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->indexerRegistry = $this->getMock('Magento\Indexer\Model\IndexerRegistry', [], [], '', false);
+        $this->indexerRegistry = $this->getMock('Magento\Framework\Indexer\IndexerRegistry', [], [], '', false);
 
-        $this->flatIndexer = $this->getMock('Magento\Indexer\Model\IndexerInterface');
+        $this->flatIndexer = $this->getMock('Magento\Framework\Indexer\IndexerInterface');
 
         $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
         $this->model = $objectManager->getObject(
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/FlatTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/FlatTest.php
index 8dae8ec6e214d8413aa0f65c903039981fb1abe3..124823fbd7ab0a7216303b32e4d62e3ae8cfd16b 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/FlatTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/FlatTest.php
@@ -23,12 +23,12 @@ class FlatTest extends \PHPUnit_Framework_TestCase
     protected $rowsMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -51,7 +51,7 @@ class FlatTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->indexerMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\IndexerInterface',
+            'Magento\Framework\Indexer\IndexerInterface',
             [],
             '',
             false,
@@ -60,7 +60,13 @@ class FlatTest extends \PHPUnit_Framework_TestCase
             ['getId', 'load', 'isInvalid', 'isWorking', '__wakeup']
         );
 
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
 
         $this->model = new \Magento\Catalog\Model\Indexer\Category\Flat(
             $this->fullMock,
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Product/Plugin/StoreGroupTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Product/Plugin/StoreGroupTest.php
index 8ccc466199bb51c3735377127cb3a762f922a827..aded427157724fb106339824727ce42e52c18e0a 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Product/Plugin/StoreGroupTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Product/Plugin/StoreGroupTest.php
@@ -10,7 +10,7 @@ use \Magento\Catalog\Model\Indexer\Category\Product\Plugin\StoreGroup;
 class StoreGroupTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Indexer\Model\IndexerInterface
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Indexer\IndexerInterface
      */
     protected $indexerMock;
 
@@ -25,7 +25,7 @@ class StoreGroupTest extends \PHPUnit_Framework_TestCase
     protected $subject;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -37,7 +37,7 @@ class StoreGroupTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->indexerMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\IndexerInterface',
+            'Magento\Framework\Indexer\IndexerInterface',
             [],
             '',
             false,
@@ -46,7 +46,13 @@ class StoreGroupTest extends \PHPUnit_Framework_TestCase
             ['getId', 'getState', '__wakeup']
         );
         $this->subject = $this->getMock('Magento\Store\Model\Resource\Group', [], [], '', false);
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
 
         $this->model = new StoreGroup($this->indexerRegistryMock);
     }
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Product/Plugin/StoreViewTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Product/Plugin/StoreViewTest.php
index f8bef7dd200dac2cf6bfb15253d0da36c1ad951f..1114bc4a8a83814375aa35ad2901ef9669c0af7d 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Product/Plugin/StoreViewTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/Product/Plugin/StoreViewTest.php
@@ -10,7 +10,7 @@ use \Magento\Catalog\Model\Indexer\Category\Product\Plugin\StoreView;
 class StoreViewTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Indexer\Model\IndexerInterface
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Indexer\IndexerInterface
      */
     protected $indexerMock;
 
@@ -25,7 +25,7 @@ class StoreViewTest extends \PHPUnit_Framework_TestCase
     protected $model;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -37,7 +37,7 @@ class StoreViewTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->indexerMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\IndexerInterface',
+            'Magento\Framework\Indexer\IndexerInterface',
             [],
             '',
             false,
@@ -46,7 +46,13 @@ class StoreViewTest extends \PHPUnit_Framework_TestCase
             ['getId', 'getState', '__wakeup']
         );
         $this->subject = $this->getMock('Magento\Store\Model\Resource\Group', [], [], '', false);
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
 
         $this->model = new StoreView($this->indexerRegistryMock);
     }
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/ProductTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/ProductTest.php
index 92eaed39e9977f7f4c9fdf79a883ae0d606cdf9b..45b3b9fdb5d5e5c8422a5e16c2b386a63b1137fa 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/ProductTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Category/ProductTest.php
@@ -23,12 +23,12 @@ class ProductTest extends \PHPUnit_Framework_TestCase
     protected $rowsMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -51,7 +51,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->indexerMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\IndexerInterface',
+            'Magento\Framework\Indexer\IndexerInterface',
             [],
             '',
             false,
@@ -60,7 +60,13 @@ class ProductTest extends \PHPUnit_Framework_TestCase
             ['getId', 'load', 'isInvalid', 'isWorking', '__wakeup']
         );
 
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
 
         $this->model = new \Magento\Catalog\Model\Indexer\Category\Product(
             $this->fullMock,
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/AffectCacheTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/AffectCacheTest.php
index ed64b28b39e09cf56f3a8e17c84f1e34124a87c2..394237d8474b7f00d518902bf7cf2856b8b53642 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/AffectCacheTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/AffectCacheTest.php
@@ -16,12 +16,12 @@ class AffectCacheTest extends \PHPUnit_Framework_TestCase
     protected $plugin;
 
     /**
-     * @var \Magento\Indexer\Model\CacheContext|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\CacheContext|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $contextMock;
 
     /**
-     * @var \Magento\Indexer\Model\ActionInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\ActionInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $subjectMock;
 
@@ -30,9 +30,9 @@ class AffectCacheTest extends \PHPUnit_Framework_TestCase
      */
     public function setUp()
     {
-        $this->subjectMock = $this->getMockForAbstractClass('Magento\Indexer\Model\ActionInterface',
+        $this->subjectMock = $this->getMockForAbstractClass('Magento\Framework\Indexer\ActionInterface',
             [], '', false, true, true, []);
-        $this->contextMock = $this->getMock('Magento\Indexer\Model\CacheContext',
+        $this->contextMock = $this->getMock('Magento\Framework\Indexer\CacheContext',
             [], [], '', false);
         $this->plugin = new \Magento\Catalog\Model\Indexer\Product\AffectCache($this->contextMock);
     }
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/CategoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/CategoryTest.php
index e5f77d3e03c97d75561cfaf3a6bdd136161f8f9f..4429d6f5093aa382a57022f58cf7a2159ebea430 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/CategoryTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/CategoryTest.php
@@ -23,12 +23,12 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
     protected $rowsMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -51,7 +51,7 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->indexerMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\IndexerInterface',
+            'Magento\Framework\Indexer\IndexerInterface',
             [],
             '',
             false,
@@ -60,7 +60,13 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
             ['getId', 'load', 'isInvalid', 'isWorking', '__wakeup']
         );
 
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
 
         $this->model = new \Magento\Catalog\Model\Indexer\Product\Category(
             $this->fullMock,
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/ProcessorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/ProcessorTest.php
index 3a93d36e0d29246033bf26e283258f1afd8b03f5..ba7dc020a55769575df2a793938a76ab05cf699c 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/ProcessorTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/ProcessorTest.php
@@ -28,7 +28,7 @@ class ProcessorTest extends \PHPUnit_Framework_TestCase
     protected $_stateMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -52,7 +52,13 @@ class ProcessorTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
         $this->_model = $this->_objectManager->getObject('Magento\Catalog\Model\Indexer\Product\Flat\Processor', [
             'indexerRegistry' => $this->indexerRegistryMock,
             'state'  => $this->_stateMock
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/System/Config/ModeTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/System/Config/ModeTest.php
index 95699536643f3e5725448b268a27f272ac96ec84..60d324c26f557af8af479f45ae236f4b1b52f60b 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/System/Config/ModeTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/System/Config/ModeTest.php
@@ -170,7 +170,7 @@ class ModeTest extends \PHPUnit_Framework_TestCase
         $this->indexerStateMock->expects($this->never())->method('save');
 
         $indexerMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\IndexerInterface',
+            'Magento\Framework\Indexer\IndexerInterface',
             [],
             '',
             false,
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Plugin/CustomerGroupTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Plugin/CustomerGroupTest.php
index 3af8c6cba916c604727a6b6acb129b9d4ecc6d1a..f448c1f174053dc32968e7a0160e6d7c793ce1ee 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Plugin/CustomerGroupTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Plugin/CustomerGroupTest.php
@@ -26,7 +26,7 @@ class CustomerGroupTest extends \PHPUnit_Framework_TestCase
     protected $_subjectMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -46,7 +46,7 @@ class CustomerGroupTest extends \PHPUnit_Framework_TestCase
             false
         );
         $indexerMock->expects($this->once())->method('invalidate');
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock('Magento\Framework\Indexer\IndexerRegistry', ['get'], [], '', false);
         $this->indexerRegistryMock->expects($this->once())
             ->method('get')
             ->with(\Magento\Catalog\Model\Indexer\Product\Price\Processor::INDEXER_ID)
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/System/Config/PriceScopeTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/System/Config/PriceScopeTest.php
index bced5a0626683ad7c2e27082fb909cc9f48a63d9..49dcd0ead296f6db7e036afff1a124049afee6fc 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/System/Config/PriceScopeTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/System/Config/PriceScopeTest.php
@@ -23,7 +23,7 @@ class PriceScopeTest extends \PHPUnit_Framework_TestCase
     protected $_indexerMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -38,7 +38,13 @@ class PriceScopeTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
 
         $contextMock = $this->getMock('Magento\Framework\Model\Context', [], [], '', false);
         $registryMock = $this->getMock('Magento\Framework\Registry', [], [], '', false);
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/ActionTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/ActionTest.php
index c172b705c3e8054016b4b14b59a48f05cdaa7e01..448f6d43f24c87e68a551160cafd89e799cdb6e8 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Product/ActionTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/ActionTest.php
@@ -43,7 +43,7 @@ class ActionTest extends \PHPUnit_Framework_TestCase
     protected $eavAttribute;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -101,7 +101,13 @@ class ActionTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
 
         $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
         $this->model = $objectManager->getObject(
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php
index 9549a2bc97886de40905712fc293b49ece2b3a8b..97f42ea1d09ab40dba23ae24684f516fb520b74d 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php
@@ -44,7 +44,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
     protected $stockItemFactoryMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $categoryIndexerMock;
 
@@ -99,7 +99,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
     private $website;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -168,7 +168,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
      */
     public function setUp()
     {
-        $this->categoryIndexerMock = $this->getMockForAbstractClass('\Magento\Indexer\Model\IndexerInterface');
+        $this->categoryIndexerMock = $this->getMockForAbstractClass('\Magento\Framework\Indexer\IndexerInterface');
 
         $this->moduleManager = $this->getMock(
             'Magento\Framework\Module\Manager',
@@ -269,7 +269,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
         $storeManager->expects($this->any())
             ->method('getWebsite')
             ->will($this->returnValue($this->website));
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock('Magento\Framework\Indexer\IndexerRegistry', ['get'], [], '', false);
         $this->categoryRepository = $this->getMock('Magento\Catalog\Api\CategoryRepositoryInterface');
 
         $this->_catalogProduct = $this->getMock(
diff --git a/app/code/Magento/Catalog/Test/Unit/Plugin/Model/Product/Action/UpdateAttributesFlushCacheTest.php b/app/code/Magento/Catalog/Test/Unit/Plugin/Model/Product/Action/UpdateAttributesFlushCacheTest.php
index 3d70aac87798ac25f787812fa5ce1b0460ada648..7a0804081ac7f6d2819ac2880539caa54c50b4f8 100644
--- a/app/code/Magento/Catalog/Test/Unit/Plugin/Model/Product/Action/UpdateAttributesFlushCacheTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Plugin/Model/Product/Action/UpdateAttributesFlushCacheTest.php
@@ -17,7 +17,7 @@ class UpdateAttributesFlushCacheTest extends \PHPUnit_Framework_TestCase
 
         $productActionMock = $this->getMock('Magento\Catalog\Model\Product\Action', [], [], '', false);
 
-        $cacheContextMock = $this->getMock('Magento\Indexer\Model\CacheContext', [], [], '', false);
+        $cacheContextMock = $this->getMock('Magento\Framework\Indexer\CacheContext', [], [], '', false);
         $cacheContextMock->expects($this->once())
             ->method('registerEntities')
             ->with(Product::CACHE_TAG, $productIds);
diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml
index 9e71f84526077f0dd7a69dc9fd35c35608bd986f..e52c7c305a8256842bf931e952fbaadeb9304bc5 100644
--- a/app/code/Magento/Catalog/etc/di.xml
+++ b/app/code/Magento/Catalog/etc/di.xml
@@ -267,7 +267,7 @@
     </type>
     <type name="Magento\Catalog\Model\Indexer\Product\Price\Processor">
         <arguments>
-            <argument name="indexer" xsi:type="object" shared="false">Magento\Indexer\Model\IndexerInterface</argument>
+            <argument name="indexer" xsi:type="object" shared="false">Magento\Framework\Indexer\IndexerInterface</argument>
         </arguments>
     </type>
     <type name="Magento\Catalog\Model\Indexer\Product\Flat">
diff --git a/app/code/Magento/Catalog/etc/indexer.xml b/app/code/Magento/Catalog/etc/indexer.xml
index 0b2c706d94e6b55fba19edce31b0215aabf10585..9d47564852fb75bc0954bddbdafbbb4f4687af72 100644
--- a/app/code/Magento/Catalog/etc/indexer.xml
+++ b/app/code/Magento/Catalog/etc/indexer.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Indexer/etc/indexer.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Indexer/etc/indexer.xsd">
     <indexer id="catalog_product_flat" view_id="catalog_product_flat" class="Magento\Catalog\Model\Indexer\Product\Flat">
         <title translate="true">Product Flat Data</title>
         <description translate="true">Reorganize EAV product structure to flat structure</description>
diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php
index d188b9d3315fecc93c738d5d521ea98b53998b10..e9a3d4ef3af48b973f4bbc1e05b02a6c272b589b 100644
--- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php
@@ -475,7 +475,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
     protected $dateTime;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry
+     * @var \Magento\Framework\Indexer\IndexerRegistry
      */
     protected $indexerRegistry;
 
@@ -579,7 +579,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
      * @param DateTime $dateTime
      * @param \Psr\Log\LoggerInterface $logger
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      * @param Product\StoreResolver $storeResolver
      * @param Product\SkuProcessor $skuProcessor
      * @param Product\CategoryProcessor $categoryProcessor
@@ -615,7 +615,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
         DateTime $dateTime,
         \Psr\Log\LoggerInterface $logger,
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         Product\StoreResolver $storeResolver,
         Product\SkuProcessor $skuProcessor,
         Product\CategoryProcessor $categoryProcessor,
diff --git a/app/code/Magento/CatalogImportExport/Model/Indexer/Product/Price/Plugin/Import.php b/app/code/Magento/CatalogImportExport/Model/Indexer/Product/Price/Plugin/Import.php
index 573130b8f6b9dab4de1b857a3d8c01a6978da6aa..92601218057e544b3bbb759425b1061cc43301ff 100644
--- a/app/code/Magento/CatalogImportExport/Model/Indexer/Product/Price/Plugin/Import.php
+++ b/app/code/Magento/CatalogImportExport/Model/Indexer/Product/Price/Plugin/Import.php
@@ -27,7 +27,7 @@ class Import extends \Magento\Catalog\Model\Indexer\Product\Price\Plugin\Abstrac
     /**
      * Get price indexer
      *
-     * @return \Magento\Indexer\Model\IndexerInterface
+     * @return \Magento\Framework\Indexer\IndexerInterface
      */
     protected function getPriceIndexer()
     {
diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php
index d9a7920de0e7983e47ef35b62965840f4e6f08e2..7161180b355b0d92b437248850b912b04026df93 100644
--- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php
+++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php
@@ -120,7 +120,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
     /** @var  \Magento\Framework\Stdlib\DateTime\TimezoneInterface|\PHPUnit_Framework_MockObject_MockObject */
     protected $_localeDate;
 
-    /** @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject  */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject  */
     protected $indexerRegistry;
 
     /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject  */
@@ -271,7 +271,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
                 ->disableOriginalConstructor()
                 ->getMock();
         $this->indexerRegistry =
-            $this->getMockBuilder('\Magento\Indexer\Model\IndexerRegistry')
+            $this->getMockBuilder('\Magento\Framework\Indexer\IndexerRegistry')
                 ->disableOriginalConstructor()
                 ->getMock();
         $this->_logger =
diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Indexer/Product/Price/Plugin/ImportTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Indexer/Product/Price/Plugin/ImportTest.php
index 7a3de72fa291e4ba90a1041d73a7dc5db04baa6d..facc5632db4b3c4bb6693dab4977a7e4f72afe1c 100644
--- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Indexer/Product/Price/Plugin/ImportTest.php
+++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Indexer/Product/Price/Plugin/ImportTest.php
@@ -23,7 +23,7 @@ class ImportTest extends \PHPUnit_Framework_TestCase
     protected $_indexerMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -39,7 +39,7 @@ class ImportTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->indexerRegistryMock = $this->getMock(
-            'Magento\Indexer\Model\IndexerRegistry',
+            'Magento\Framework\Indexer\IndexerRegistry',
             ['get'],
             [],
             '',
diff --git a/app/code/Magento/CatalogImportExport/composer.json b/app/code/Magento/CatalogImportExport/composer.json
index 8f11d20528b36f2896f22895c2f099ea603e7d6e..9a6011863f5fa89f657542e63f85740a0eff5645 100644
--- a/app/code/Magento/CatalogImportExport/composer.json
+++ b/app/code/Magento/CatalogImportExport/composer.json
@@ -6,7 +6,6 @@
         "magento/module-catalog": "1.0.0-beta",
         "magento/module-eav": "1.0.0-beta",
         "magento/module-import-export": "1.0.0-beta",
-        "magento/module-indexer": "1.0.0-beta",
         "magento/module-store": "1.0.0-beta",
         "magento/module-tax": "1.0.0-beta",
         "magento/module-catalog-inventory": "1.0.0-beta",
diff --git a/app/code/Magento/CatalogInventory/Model/Indexer/Stock.php b/app/code/Magento/CatalogInventory/Model/Indexer/Stock.php
index 0bbbd6cb544b3321dd0ec20e6886fdf1eea7addf..b17fd8eba2d590c52fc312a087667633eb1afceb 100644
--- a/app/code/Magento/CatalogInventory/Model/Indexer/Stock.php
+++ b/app/code/Magento/CatalogInventory/Model/Indexer/Stock.php
@@ -8,7 +8,7 @@
 
 namespace Magento\CatalogInventory\Model\Indexer;
 
-class Stock implements \Magento\Indexer\Model\ActionInterface, \Magento\Framework\Mview\ActionInterface
+class Stock implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
 {
     /**
      * @var \Magento\CatalogInventory\Model\Indexer\Stock\Action\Row
diff --git a/app/code/Magento/CatalogInventory/Model/Indexer/Stock/AbstractAction.php b/app/code/Magento/CatalogInventory/Model/Indexer/Stock/AbstractAction.php
index a4bb358e3b5dd13a224a74dd94cab1143c0242ff..7faea3bfcc83ca239530c154c04d9035b0c622bb 100644
--- a/app/code/Magento/CatalogInventory/Model/Indexer/Stock/AbstractAction.php
+++ b/app/code/Magento/CatalogInventory/Model/Indexer/Stock/AbstractAction.php
@@ -56,7 +56,7 @@ abstract class AbstractAction
     protected $_isNeedUseIdxTable = false;
 
     /**
-     * @var \Magento\Indexer\Model\CacheContext
+     * @var \Magento\Framework\Indexer\CacheContext
      */
     private $cacheContext;
 
@@ -70,14 +70,14 @@ abstract class AbstractAction
      * @param Resource $resource
      * @param \Magento\CatalogInventory\Model\Resource\Indexer\StockFactory $indexerFactory
      * @param \Magento\Catalog\Model\Product\Type $catalogProductType
-     * @param \Magento\Indexer\Model\CacheContext $cacheContext
+     * @param \Magento\Framework\Indexer\CacheContext $cacheContext
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      */
     public function __construct(
         Resource $resource,
         \Magento\CatalogInventory\Model\Resource\Indexer\StockFactory $indexerFactory,
         \Magento\Catalog\Model\Product\Type $catalogProductType,
-        \Magento\Indexer\Model\CacheContext $cacheContext,
+        \Magento\Framework\Indexer\CacheContext $cacheContext,
         \Magento\Framework\Event\ManagerInterface $eventManager
     ) {
         $this->_resource = $resource;
diff --git a/app/code/Magento/CatalogInventory/Model/Indexer/Stock/Processor.php b/app/code/Magento/CatalogInventory/Model/Indexer/Stock/Processor.php
index b4432bcd6554e3176d8a26ee1351788f169fd0bb..05ebd1ba89daaf33741a0c0f49f3e6cdbac1d1b4 100644
--- a/app/code/Magento/CatalogInventory/Model/Indexer/Stock/Processor.php
+++ b/app/code/Magento/CatalogInventory/Model/Indexer/Stock/Processor.php
@@ -8,7 +8,7 @@
 
 namespace Magento\CatalogInventory\Model\Indexer\Stock;
 
-class Processor extends \Magento\Indexer\Model\Indexer\AbstractProcessor
+class Processor extends \Magento\Framework\Indexer\AbstractProcessor
 {
     /**
      * Indexer ID
diff --git a/app/code/Magento/CatalogInventory/Model/Resource/Indexer/Stock/DefaultStock.php b/app/code/Magento/CatalogInventory/Model/Resource/Indexer/Stock/DefaultStock.php
index 08a751fd77f61df2cf0a3344eade4e309e7e3ed3..c9d979962eb2575f547d6dde2b938ee85af2231f 100644
--- a/app/code/Magento/CatalogInventory/Model/Resource/Indexer/Stock/DefaultStock.php
+++ b/app/code/Magento/CatalogInventory/Model/Resource/Indexer/Stock/DefaultStock.php
@@ -36,14 +36,14 @@ class DefaultStock extends \Magento\Catalog\Model\Resource\Product\Indexer\Abstr
      * Class constructor
      *
      * @param \Magento\Framework\Model\Resource\Db\Context $context
-     * @param \Magento\Indexer\Model\Indexer\Table\StrategyInterface $tableStrategy
+     * @param \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy
      * @param \Magento\Eav\Model\Config $eavConfig
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param string $connectionName
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
-        \Magento\Indexer\Model\Indexer\Table\StrategyInterface $tableStrategy,
+        \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy,
         \Magento\Eav\Model\Config $eavConfig,
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         $connectionName = null
diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Indexer/Stock/Plugin/StoreGroupTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Indexer/Stock/Plugin/StoreGroupTest.php
index d9ce970227043dbb6f759b749ef75c920673f8e5..096919b3dc9d40f89d4ff1fdaff256a60a91b074 100644
--- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Indexer/Stock/Plugin/StoreGroupTest.php
+++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Indexer/Stock/Plugin/StoreGroupTest.php
@@ -17,7 +17,7 @@ class StoreGroupTest extends \PHPUnit_Framework_TestCase
     protected $_model;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $_indexerMock;
 
diff --git a/app/code/Magento/CatalogInventory/composer.json b/app/code/Magento/CatalogInventory/composer.json
index 35cb2e22f35f3ccaad26c4b7cb940693c678c9a3..5e222e8917bf02bcc3905c1991699e5210272cb1 100644
--- a/app/code/Magento/CatalogInventory/composer.json
+++ b/app/code/Magento/CatalogInventory/composer.json
@@ -7,7 +7,6 @@
         "magento/module-store": "1.0.0-beta",
         "magento/module-catalog": "1.0.0-beta",
         "magento/module-customer": "1.0.0-beta",
-        "magento/module-indexer": "1.0.0-beta",
         "magento/module-eav": "1.0.0-beta",
         "magento/module-quote": "1.0.0-beta",
         "magento/framework": "1.0.0-beta",
diff --git a/app/code/Magento/CatalogInventory/etc/indexer.xml b/app/code/Magento/CatalogInventory/etc/indexer.xml
index 3ee2f839950d159e9628e34fe57751cfcd019a65..80b1c5f4faa8e2a7a3fa5b8177a6b69983f1c88c 100644
--- a/app/code/Magento/CatalogInventory/etc/indexer.xml
+++ b/app/code/Magento/CatalogInventory/etc/indexer.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Indexer/etc/indexer.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Indexer/etc/indexer.xsd">
     <indexer id="cataloginventory_stock" view_id="cataloginventory_stock" class="Magento\CatalogInventory\Model\Indexer\Stock">
         <title translate="true">Stock</title>
         <description translate="true">Index stock</description>
diff --git a/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php b/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php
index 74f2f984cdd199cb31f380b1d765cf29589f612c..acb979d5205a3608b2917a7ac31ea378c3f185b2 100644
--- a/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php
+++ b/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php
@@ -6,7 +6,7 @@
 namespace Magento\CatalogRule\Model\Indexer;
 
 use Magento\Framework\Mview\ActionInterface as MviewActionInterface;
-use Magento\Indexer\Model\ActionInterface as IndexerActionInterface;
+use Magento\Framework\Indexer\ActionInterface as IndexerActionInterface;
 use Magento\Framework\DataObject\IdentityInterface as IdentityInterface;
 
 abstract class AbstractIndexer implements IndexerActionInterface, MviewActionInterface, IdentityInterface
diff --git a/app/code/Magento/CatalogRule/Model/Indexer/Product/ProductRuleProcessor.php b/app/code/Magento/CatalogRule/Model/Indexer/Product/ProductRuleProcessor.php
index c930f7cf21bb3389a41b5148ac9145346394b46d..912b900b47569c8e034bb4a5e49ee930c3c0e465 100644
--- a/app/code/Magento/CatalogRule/Model/Indexer/Product/ProductRuleProcessor.php
+++ b/app/code/Magento/CatalogRule/Model/Indexer/Product/ProductRuleProcessor.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\CatalogRule\Model\Indexer\Product;
 
-use Magento\Indexer\Model\Indexer\AbstractProcessor;
+use Magento\Framework\Indexer\AbstractProcessor;
 
 class ProductRuleProcessor extends AbstractProcessor
 {
diff --git a/app/code/Magento/CatalogRule/Model/Indexer/Rule/RuleProductProcessor.php b/app/code/Magento/CatalogRule/Model/Indexer/Rule/RuleProductProcessor.php
index 4eab6e156aa83bcdad15b97422273690dc3b26be..27319c5422a203186b3977354f7c31803ca3b810 100644
--- a/app/code/Magento/CatalogRule/Model/Indexer/Rule/RuleProductProcessor.php
+++ b/app/code/Magento/CatalogRule/Model/Indexer/Rule/RuleProductProcessor.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\CatalogRule\Model\Indexer\Rule;
 
-use Magento\Indexer\Model\Indexer\AbstractProcessor;
+use Magento\Framework\Indexer\AbstractProcessor;
 
 class RuleProductProcessor extends AbstractProcessor
 {
diff --git a/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php b/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php
index 285429e8af8727b07319c44fa252c0eba5782052..dbf6958530ac87af19504c393fc8fae0765b7d08 100644
--- a/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php
+++ b/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php
@@ -207,7 +207,7 @@ class RuleTest extends \PHPUnit_Framework_TestCase
      */
     public function testAfterDelete()
     {
-        $indexer = $this->getMock('\Magento\Indexer\Model\IndexerInterface');
+        $indexer = $this->getMock('\Magento\Framework\Indexer\IndexerInterface');
         $indexer->expects($this->once())->method('invalidate');
         $this->_ruleProductProcessor->expects($this->once())->method('getIndexer')->will($this->returnValue($indexer));
         $this->rule->afterDelete();
@@ -221,7 +221,7 @@ class RuleTest extends \PHPUnit_Framework_TestCase
     public function testAfterUpdate()
     {
         $this->rule->isObjectNew(false);
-        $indexer = $this->getMock('\Magento\Indexer\Model\IndexerInterface');
+        $indexer = $this->getMock('\Magento\Framework\Indexer\IndexerInterface');
         $indexer->expects($this->once())->method('invalidate');
         $this->_ruleProductProcessor->expects($this->once())->method('getIndexer')->will($this->returnValue($indexer));
         $this->rule->afterSave();
@@ -242,7 +242,7 @@ class RuleTest extends \PHPUnit_Framework_TestCase
     {
         $this->rule->setData('website_ids', []);
         $this->rule->isObjectNew($isObjectNew);
-        $indexer = $this->getMock('\Magento\Indexer\Model\IndexerInterface');
+        $indexer = $this->getMock('\Magento\Framework\Indexer\IndexerInterface');
         $indexer->expects($this->any())->method('invalidate');
         $this->_ruleProductProcessor->expects($this->any())->method('getIndexer')->will($this->returnValue($indexer));
 
diff --git a/app/code/Magento/CatalogRule/composer.json b/app/code/Magento/CatalogRule/composer.json
index 6984fa5d748fc208074ee52353d1f01c79f763d3..fc76a727f7fee7844a69bf69b0cdfd758e0fc91b 100644
--- a/app/code/Magento/CatalogRule/composer.json
+++ b/app/code/Magento/CatalogRule/composer.json
@@ -9,7 +9,6 @@
         "magento/module-customer": "1.0.0-beta",
         "magento/module-backend": "1.0.0-beta",
         "magento/module-eav": "1.0.0-beta",
-        "magento/module-indexer": "1.0.0-beta",
         "magento/module-import-export": "1.0.0-beta",
         "magento/framework": "1.0.0-beta",
         "magento/magento-composer-installer": "*"
diff --git a/app/code/Magento/CatalogRule/etc/indexer.xml b/app/code/Magento/CatalogRule/etc/indexer.xml
index 7d59dfb6d839134cd672ea102a62eaff880a9adb..b957d9c66400429f1b987966ef941c09859a5a85 100644
--- a/app/code/Magento/CatalogRule/etc/indexer.xml
+++ b/app/code/Magento/CatalogRule/etc/indexer.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Indexer/etc/indexer.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Indexer/etc/indexer.xsd">
     <indexer id="catalogrule_rule" view_id="catalogrule_rule" class="Magento\CatalogRule\Model\Indexer\Rule\RuleProductIndexer">
         <title translate="true">Catalog Rule Product</title>
         <description translate="true">Indexed rule/product association</description>
diff --git a/app/code/Magento/CatalogSearch/Model/Adminhtml/System/Config/Backend/Engine.php b/app/code/Magento/CatalogSearch/Model/Adminhtml/System/Config/Backend/Engine.php
index eb1f48340c3fffa285954b8c6e66ddc690dc0bd2..12cc44bc6c2013ffc65cc8cfbcd6854d98f21256 100644
--- a/app/code/Magento/CatalogSearch/Model/Adminhtml/System/Config/Backend/Engine.php
+++ b/app/code/Magento/CatalogSearch/Model/Adminhtml/System/Config/Backend/Engine.php
@@ -10,14 +10,14 @@ namespace Magento\CatalogSearch\Model\Adminhtml\System\Config\Backend;
  */
 class Engine extends \Magento\Framework\App\Config\Value
 {
-    /** @var \Magento\Indexer\Model\IndexerRegistry */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
     protected $indexerRegistry;
 
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $config
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      * @param \Magento\Framework\Model\Resource\AbstractResource $resource
      * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
      * @param array $data
@@ -26,7 +26,7 @@ class Engine extends \Magento\Framework\App\Config\Value
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Framework\App\Config\ScopeConfigInterface $config,
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         \Magento\Framework\Model\Resource\AbstractResource $resource = null,
         \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
         array $data = []
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php
index 1e043eda14bbf2b0956e76a8b7f754810dc5952b..385758d0abf3c60b0ba15c202c5690cc206dadf6 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php
@@ -11,7 +11,7 @@ use \Magento\Framework\Search\Request\Config as SearchRequestConfig;
 use Magento\Framework\Search\Request\DimensionFactory;
 use Magento\Store\Model\StoreManagerInterface;
 
-class Fulltext implements \Magento\Indexer\Model\ActionInterface, \Magento\Framework\Mview\ActionInterface
+class Fulltext implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
 {
     /**
      * Indexer ID in configuration
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/Full.php b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/Full.php
index fd56848f0ef04d56925c820d6ed70bf8de0a14f9..d5db6951990865ee1df04b673f00548b9fd910fc 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/Full.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/Full.php
@@ -107,7 +107,7 @@ class Full
     protected $engine;
 
     /**
-     * @var \Magento\Framework\IndexerInterface
+     * @var \Magento\Framework\Indexer\SaveHandler\IndexerInterface
      */
     protected $indexHandler;
 
@@ -168,7 +168,7 @@ class Full
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
      * @param \Magento\CatalogSearch\Model\Resource\Fulltext $fulltextResource
      * @param \Magento\Framework\Search\Request\DimensionFactory $dimensionFactory
-     * @param \Magento\Indexer\Model\ConfigInterface $indexerConfig
+     * @param \Magento\Framework\Indexer\ConfigInterface $indexerConfig
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
@@ -188,7 +188,7 @@ class Full
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
         \Magento\CatalogSearch\Model\Resource\Fulltext $fulltextResource,
         \Magento\Framework\Search\Request\DimensionFactory $dimensionFactory,
-        \Magento\Indexer\Model\ConfigInterface $indexerConfig
+        \Magento\Framework\Indexer\ConfigInterface $indexerConfig
     ) {
         $this->resource = $resource;
         $this->connection = $resource->getConnection();
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Plugin/AbstractPlugin.php b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Plugin/AbstractPlugin.php
index 586b386257c40a2efa2b68aac7436793e74f639d..921be59221e1a032075411f4319a666dbc69f605 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Plugin/AbstractPlugin.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Plugin/AbstractPlugin.php
@@ -9,14 +9,14 @@ use Magento\CatalogSearch\Model\Indexer\Fulltext;
 
 abstract class AbstractPlugin
 {
-    /** @var \Magento\Indexer\Model\IndexerRegistry */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
     protected $indexerRegistry;
 
     /**
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      */
     public function __construct(
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
     ) {
         $this->indexerRegistry = $indexerRegistry;
     }
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Plugin/Attribute.php b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Plugin/Attribute.php
index 8aaf8e1e6b41dfacad4c2437474b2fea8b921f3e..3be577512eaab2e9eab29dfd1ef1516e595d5d55 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Plugin/Attribute.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Plugin/Attribute.php
@@ -15,11 +15,11 @@ class Attribute extends AbstractPlugin
     private $config;
 
     /**
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      * @param \Magento\Framework\Search\Request\Config $config
      */
     public function __construct(
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         \Magento\Framework\Search\Request\Config $config
     ) {
         parent::__construct($indexerRegistry); // TODO: Change the autogenerated stub
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Store.php b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Store.php
index f429417a5be318db7aa305221f6c4515316bb1e0..a74de05ce636ec5f1ff9ab0369e9824fcbbe0c4b 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Store.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Store.php
@@ -8,7 +8,7 @@ namespace Magento\CatalogSearch\Model\Indexer\Fulltext;
 use Magento\CatalogSearch\Model\Indexer\Fulltext as FulltextIndexer;
 use Magento\CatalogSearch\Model\Indexer\IndexerHandlerFactory;
 use Magento\Framework\Search\Request\DimensionFactory;
-use Magento\Indexer\Model\ConfigInterface;
+use Magento\Framework\Indexer\ConfigInterface;
 
 class Store
 {
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructure.php b/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructure.php
index 47f0e9a002923d2be0aca7c8d7344d16e8e67c91..8f18d48b9db8a53b0d04e3b0182b8e8f18cd586d 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructure.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructure.php
@@ -10,9 +10,10 @@ use Magento\Framework\App\Resource;
 use Magento\Framework\DB\Adapter\AdapterInterface;
 use Magento\Framework\DB\Ddl\Table;
 use Magento\Framework\Search\Request\Dimension;
-use Magento\Indexer\Model\ScopeResolver\IndexScopeResolver;
+use Magento\Framework\Indexer\IndexStructureInterface;
+use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
 
-class IndexStructure
+class IndexStructure implements IndexStructureInterface
 {
     /**
      * @var Resource
@@ -40,7 +41,7 @@ class IndexStructure
      * @param Dimension[] $dimensions
      * @return void
      */
-    public function delete($index, array $dimensions)
+    public function delete($index, array $dimensions = [])
     {
         $tableName = $this->indexScopeResolver->resolve($index, $dimensions);
         if ($this->resource->getConnection()->isTableExists($tableName)) {
@@ -50,10 +51,12 @@ class IndexStructure
 
     /**
      * @param string $index
-     * @param Dimension[] $dimensions
+     * @param array $fields
+     * @param array $dimensions
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      * @return void
      */
-    public function create($index, array $dimensions)
+    public function create($index, array $fields, array $dimensions = [])
     {
         $this->createFulltextIndex($this->indexScopeResolver->resolve($index, $dimensions));
     }
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php b/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php
index 862f23b1cba5c13824ef2cad67a2bb7d5472da71..affc5787532c70a7d001bfe375c717a68220a61c 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php
@@ -8,11 +8,11 @@ namespace Magento\CatalogSearch\Model\Indexer;
 use Magento\Eav\Model\Config;
 use Magento\Framework\App\Resource;
 use Magento\Framework\DB\Adapter\AdapterInterface;
-use Magento\Framework\IndexerInterface;
+use Magento\Framework\Indexer\SaveHandler\IndexerInterface;
 use Magento\Framework\Search\Request\Dimension;
 use Magento\Framework\Search\Request\IndexScopeResolverInterface;
-use Magento\Indexer\Model\SaveHandler\Batch;
-use Magento\Indexer\Model\ScopeResolver\IndexScopeResolver;
+use Magento\Framework\Indexer\SaveHandler\Batch;
+use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
 
 class IndexerHandler implements IndexerInterface
 {
@@ -61,7 +61,7 @@ class IndexerHandler implements IndexerInterface
      * @param Resource|Resource $resource
      * @param Config $eavConfig
      * @param Batch $batch
-     * @param \Magento\Indexer\Model\ScopeResolver\IndexScopeResolver $indexScopeResolver
+     * @param \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver $indexScopeResolver
      * @param array $data
      * @param int $batchSize
      */
@@ -113,7 +113,7 @@ class IndexerHandler implements IndexerInterface
     public function cleanIndex($dimensions)
     {
         $this->indexStructure->delete($this->getIndexName(), $dimensions);
-        $this->indexStructure->create($this->getIndexName(), $dimensions);
+        $this->indexStructure->create($this->getIndexName(), [], $dimensions);
     }
 
     /**
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandlerFactory.php b/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandlerFactory.php
index d680cffc29ea9a9f88064416d369414799c1c2b2..9793bbcbc2c227e6f97cd8088489d7819211912a 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandlerFactory.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandlerFactory.php
@@ -6,7 +6,7 @@
 namespace Magento\CatalogSearch\Model\Indexer;
 
 use Magento\Framework\App\Config\ScopeConfigInterface;
-use Magento\Framework\IndexerInterface;
+use Magento\Framework\Indexer\SaveHandler\IndexerInterface;
 use Magento\Framework\ObjectManagerInterface;
 use Magento\Store\Model\ScopeInterface;
 
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Mview/Action.php b/app/code/Magento/CatalogSearch/Model/Indexer/Mview/Action.php
index 03f0fb14eadced11386b44cf80806db7afe29e3f..13fdbde76c11fefc5e8250034da713b2c3c232d7 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/Mview/Action.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Mview/Action.php
@@ -3,13 +3,11 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-
 namespace Magento\CatalogSearch\Model\Indexer\Mview;
 
-
 use Magento\CatalogSearch\Model\Indexer\Fulltext;
 use Magento\Framework\Mview\ActionInterface;
-use Magento\Indexer\Model\IndexerInterfaceFactory;
+use Magento\Framework\Indexer\IndexerInterfaceFactory;
 
 class Action implements ActionInterface
 {
@@ -35,7 +33,7 @@ class Action implements ActionInterface
      */
     public function execute($ids)
     {
-        /** @var \Magento\Indexer\Model\IndexerInterface $indexer */
+        /** @var \Magento\Framework\Indexer\IndexerInterface $indexer */
         $indexer = $this->indexerFactory->create()->load(Fulltext::INDEXER_ID);
         $indexer->reindexList($ids);
     }
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/ProductFieldset.php b/app/code/Magento/CatalogSearch/Model/Indexer/ProductFieldset.php
index 21b14e6f0ee30869af66ee419592a23465527329..e595fe239b4945a59030e0421c6ec88ef16f8a5a 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/ProductFieldset.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/ProductFieldset.php
@@ -10,7 +10,7 @@ use Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory;
 use Magento\Eav\Model\Config;
 use Magento\Eav\Model\Entity\Attribute;
 
-class ProductFieldset implements \Magento\Indexer\Model\FieldsetInterface
+class ProductFieldset implements \Magento\Framework\Indexer\FieldsetInterface
 {
     /**
      * @var Config
@@ -27,24 +27,16 @@ class ProductFieldset implements \Magento\Indexer\Model\FieldsetInterface
      */
     private $searchableAttributes;
     
-    /**
-     * @var string
-     */
-    private $defaultHandler;
-
     /**
      * @param Config $eavConfig
      * @param CollectionFactory $collectionFactory
-     * @param string $defaultHandler
      */
     public function __construct(
         Config $eavConfig,
-        CollectionFactory $collectionFactory,
-        $defaultHandler = 'Magento\Indexer\Model\Handler\DefaultHandler'
+        CollectionFactory $collectionFactory
     ) {
         $this->eavConfig = $eavConfig;
         $this->collectionFactory = $collectionFactory;
-        $this->defaultHandler = $defaultHandler;
     }
 
     /**
@@ -62,14 +54,6 @@ class ProductFieldset implements \Magento\Indexer\Model\FieldsetInterface
         return $data;
     }
 
-    /**
-     * {@inheritdoc}
-     */
-    public function getDefaultHandler()
-    {
-        return $this->defaultHandler;
-    }
-
     /**
      * Retrieve searchable attributes
      *
diff --git a/app/code/Magento/CatalogSearch/Model/Resource/Engine.php b/app/code/Magento/CatalogSearch/Model/Resource/Engine.php
index a3c39528a1d0f16a8e65b3cac43a0e5b94339725..86a5a16578f8514c6061e82de1ab32c16e052e70 100644
--- a/app/code/Magento/CatalogSearch/Model/Resource/Engine.php
+++ b/app/code/Magento/CatalogSearch/Model/Resource/Engine.php
@@ -27,7 +27,7 @@ class Engine implements EngineInterface
     protected $catalogProductVisibility;
 
     /**
-     * @var \Magento\Indexer\Model\ScopeResolver\IndexScopeResolver
+     * @var \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver
      */
     private $indexScopeResolver;
 
@@ -35,11 +35,11 @@ class Engine implements EngineInterface
      * Construct
      *
      * @param \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility
-     * @param \Magento\Indexer\Model\ScopeResolver\IndexScopeResolver $indexScopeResolver
+     * @param \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver $indexScopeResolver
      */
     public function __construct(
         \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility,
-        \Magento\Indexer\Model\ScopeResolver\IndexScopeResolver $indexScopeResolver
+        \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver $indexScopeResolver
     ) {
         $this->catalogProductVisibility = $catalogProductVisibility;
         $this->indexScopeResolver = $indexScopeResolver;
diff --git a/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php b/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php
index 7eeafda0441c595b85dcfde87704f86de7d86efb..4e35ffdde8e22e8828ca72bc21e743613c6cc7ea 100644
--- a/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php
+++ b/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php
@@ -15,7 +15,7 @@ use Magento\Framework\Search\Request\Dimension;
 use Magento\Framework\Search\Request\QueryInterface;
 use Magento\Framework\Search\Request\QueryInterface as RequestQueryInterface;
 use Magento\Framework\Search\RequestInterface;
-use Magento\Indexer\Model\ScopeResolver\IndexScopeResolver;
+use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
 use Magento\Store\Model\ScopeInterface;
 use Magento\Store\Model\StoreManagerInterface;
 
diff --git a/app/code/Magento/CatalogSearch/Setup/InstallData.php b/app/code/Magento/CatalogSearch/Setup/InstallData.php
index 8c758d2535440c5130e17002ffa555fbfc792f55..3779dab0fa4eebdc0f9035a43da537fa09f642b3 100644
--- a/app/code/Magento/CatalogSearch/Setup/InstallData.php
+++ b/app/code/Magento/CatalogSearch/Setup/InstallData.php
@@ -3,14 +3,12 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-
 namespace Magento\CatalogSearch\Setup;
 
-
 use Magento\Framework\Setup\InstallDataInterface;
 use Magento\Framework\Setup\ModuleContextInterface;
 use Magento\Framework\Setup\ModuleDataSetupInterface;
-use Magento\Indexer\Model\IndexerInterfaceFactory;
+use Magento\Framework\Indexer\IndexerInterfaceFactory;
 use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
 
 class InstallData implements InstallDataInterface
@@ -49,7 +47,7 @@ class InstallData implements InstallDataInterface
 
     /**
      * @param string $indexerId
-     * @return \Magento\Indexer\Model\IndexerInterface
+     * @return \Magento\Framework\Indexer\IndexerInterface
      */
     private function getIndexer($indexerId)
     {
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/AttributeTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/AttributeTest.php
index f6dd67b848ec1ef8cee5d3d87ae4c46a6d7bcd38..38d6089b6910e6bc26cdb4b50e5e3eaacc6d8e2f 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/AttributeTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/AttributeTest.php
@@ -10,7 +10,7 @@ use \Magento\CatalogSearch\Model\Indexer\Fulltext\Plugin\Attribute;
 class AttributeTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Indexer\Model\IndexerInterface
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Indexer\IndexerInterface
      */
     protected $indexerMock;
 
@@ -20,7 +20,7 @@ class AttributeTest extends \PHPUnit_Framework_TestCase
     protected $subjectMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -33,7 +33,7 @@ class AttributeTest extends \PHPUnit_Framework_TestCase
     {
         $this->subjectMock = $this->getMock('Magento\Catalog\Model\Resource\Attribute', [], [], '', false);
         $this->indexerMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\IndexerInterface',
+            'Magento\Framework\Indexer\IndexerInterface',
             [],
             '',
             false,
@@ -41,7 +41,13 @@ class AttributeTest extends \PHPUnit_Framework_TestCase
             true,
             ['getId', 'getState', '__wakeup']
         );
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
         $this->config =  $this->getMockBuilder(\Magento\Framework\Search\Request\Config::class)
             ->disableOriginalConstructor()
             ->getMock();
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/Product/ActionTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/Product/ActionTest.php
index b882cb8718aa2d4485c56fe08a16ea8e6854706f..1f4684a056df70eb3046629eab1f3579707b3612 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/Product/ActionTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/Product/ActionTest.php
@@ -8,11 +8,10 @@ namespace Magento\CatalogSearch\Test\Unit\Model\Indexer\Fulltext\Plugin\Product;
 
 use \Magento\CatalogSearch\Model\Indexer\Fulltext\Plugin\Product\Action;
 
-
 class ActionTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Indexer\Model\IndexerInterface
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Indexer\IndexerInterface
      */
     protected $indexerMock;
 
@@ -22,7 +21,7 @@ class ActionTest extends \PHPUnit_Framework_TestCase
     protected $subjectMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -36,7 +35,7 @@ class ActionTest extends \PHPUnit_Framework_TestCase
         $this->subjectMock = $this->getMock('Magento\Catalog\Model\Product\Action', [], [], '', false);
 
         $this->indexerMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\IndexerInterface',
+            'Magento\Framework\Indexer\IndexerInterface',
             [],
             '',
             false,
@@ -44,7 +43,13 @@ class ActionTest extends \PHPUnit_Framework_TestCase
             true,
             ['getId', 'getState', '__wakeup']
         );
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
 
         $this->model = new Action($this->indexerRegistryMock);
     }
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/ProductTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/ProductTest.php
index bccbe9a59ce8b3bdf6d3630c9dcbfca9cec17239..49f37b71f1a10762efbad1272b9175b920c1edc2 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/ProductTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/ProductTest.php
@@ -8,11 +8,10 @@ namespace Magento\CatalogSearch\Test\Unit\Model\Indexer\Fulltext\Plugin;
 
 use \Magento\CatalogSearch\Model\Indexer\Fulltext\Plugin\Product;
 
-
 class ProductTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Indexer\Model\IndexerInterface
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Indexer\IndexerInterface
      */
     protected $indexerMock;
 
@@ -22,7 +21,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
     protected $subjectMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -36,7 +35,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
         $this->subjectMock = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false);
 
         $this->indexerMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\IndexerInterface',
+            'Magento\Framework\Indexer\IndexerInterface',
             [],
             '',
             false,
@@ -45,7 +44,13 @@ class ProductTest extends \PHPUnit_Framework_TestCase
             ['getId', 'getState', '__wakeup']
         );
 
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
 
         $this->model = new Product($this->indexerRegistryMock);
     }
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/Store/GroupTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/Store/GroupTest.php
index 36ba1e0c83435ba3cd7362170d6a8dbd86179933..96176e560ebc5f6dbc1f0420c41b4fe190d725c6 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/Store/GroupTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/Store/GroupTest.php
@@ -10,7 +10,7 @@ use \Magento\CatalogSearch\Model\Indexer\Fulltext\Plugin\Store\Group;
 class GroupTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Indexer\Model\IndexerInterface
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Indexer\IndexerInterface
      */
     protected $indexerMock;
 
@@ -20,7 +20,7 @@ class GroupTest extends \PHPUnit_Framework_TestCase
     protected $subjectMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -33,7 +33,7 @@ class GroupTest extends \PHPUnit_Framework_TestCase
     {
         $this->subjectMock = $this->getMock('Magento\Store\Model\Resource\Group', [], [], '', false);
         $this->indexerMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\IndexerInterface',
+            'Magento\Framework\Indexer\IndexerInterface',
             [],
             '',
             false,
@@ -41,7 +41,13 @@ class GroupTest extends \PHPUnit_Framework_TestCase
             true,
             ['getId', 'getState', '__wakeup']
         );
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
         $this->model = new Group($this->indexerRegistryMock);
     }
 
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/Store/ViewTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/Store/ViewTest.php
index 7f2dddf3e3d46b1f5999936000fbb1d27f24e546..9ca5dc2c13e0ba197adc3cae87248cef9d08c645 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/Store/ViewTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/Store/ViewTest.php
@@ -10,7 +10,7 @@ use \Magento\CatalogSearch\Model\Indexer\Fulltext\Plugin\Store\View;
 class ViewTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Indexer\Model\IndexerInterface
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Indexer\IndexerInterface
      */
     protected $indexerMock;
 
@@ -20,7 +20,7 @@ class ViewTest extends \PHPUnit_Framework_TestCase
     protected $subjectMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -33,7 +33,7 @@ class ViewTest extends \PHPUnit_Framework_TestCase
     {
         $this->subjectMock = $this->getMock('Magento\Store\Model\Resource\Store', [], [], '', false);
         $this->indexerMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\IndexerInterface',
+            'Magento\Framework\Indexer\IndexerInterface',
             [],
             '',
             false,
@@ -41,7 +41,13 @@ class ViewTest extends \PHPUnit_Framework_TestCase
             true,
             ['getId', 'getState', '__wakeup']
         );
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock(
+            'Magento\Framework\Indexer\IndexerRegistry',
+            ['get'],
+            [],
+            '',
+            false
+        );
         $this->model = new View($this->indexerRegistryMock);
     }
 
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php
index e5f7b7399f58ffbc32e9e4cb64a56d98dc6ef441..8eab58800df3f7b7f5ab8af95f67fe4d90f8997c 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php
@@ -83,7 +83,7 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase
 
         $this->storeManager = $this->getMockBuilder('Magento\Store\Model\StoreManagerInterface')->getMock();
 
-        $this->scopeResolver = $this->getMockBuilder('\Magento\Indexer\Model\ScopeResolver\IndexScopeResolver')
+        $this->scopeResolver = $this->getMockBuilder('\Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver')
             ->disableOriginalConstructor()
             ->getMock();
 
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/Indexer/IndexStructureTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/Indexer/IndexStructureTest.php
index 040e80c7a005dfffc299c91c91fd7a8f161f246e..8b7bba0b04a4d989ea51d5b3200564f2eda89e46 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/Indexer/IndexStructureTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/Indexer/IndexStructureTest.php
@@ -11,12 +11,12 @@ use Magento\Framework\DB\Ddl\Table;
 use \Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
 
 /**
- * Test for \Magento\Indexer\Model\IndexStructure
+ * Test for \Magento\Framework\Indexer\IndexStructure
  */
 class IndexStructureTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Indexer\Model\ScopeResolver\IndexScopeResolver|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver|\PHPUnit_Framework_MockObject_MockObject
      */
     private $indexScopeResolver;
     /**
@@ -45,11 +45,7 @@ class IndexStructureTest extends \PHPUnit_Framework_TestCase
         $this->resource->expects($this->atLeastOnce())
             ->method('getConnection')
             ->willReturn($this->connection);
-        $this->indexScopeResolver = $this->getMockBuilder('\Magento\Indexer\Model\ScopeResolver\IndexScopeResolver')
-            ->setMethods(['resolve'])
-            ->disableOriginalConstructor()
-            ->getMock();
-        $this->flatScopeResolver = $this->getMockBuilder('\Magento\Indexer\Model\ScopeResolver\FlatScopeResolver')
+        $this->indexScopeResolver = $this->getMockBuilder('\Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver')
             ->setMethods(['resolve'])
             ->disableOriginalConstructor()
             ->getMock();
@@ -103,9 +99,9 @@ class IndexStructureTest extends \PHPUnit_Framework_TestCase
             ->method('resolve')
             ->with($index, $dimensions)
             ->willReturn($expectedTable);
-        $position = $this->mockFulltextTable($position, $expectedTable, true);
+        $this->mockFulltextTable($position, $expectedTable, true);
 
-        $this->target->create($index, $dimensions);
+        $this->target->create($index, [], $dimensions);
     }
 
     /**
diff --git a/app/code/Magento/CatalogSearch/composer.json b/app/code/Magento/CatalogSearch/composer.json
index fd495276886b8cb186be34107c739768543559d1..31a8a1a8abc71aa8c0055ca6d4ef4bab3e6c2157 100644
--- a/app/code/Magento/CatalogSearch/composer.json
+++ b/app/code/Magento/CatalogSearch/composer.json
@@ -8,7 +8,6 @@
         "magento/module-search": "1.0.0-beta",
         "magento/module-customer": "1.0.0-beta",
         "magento/module-directory": "1.0.0-beta",
-        "magento/module-indexer": "1.0.0-beta",
         "magento/module-eav": "1.0.0-beta",
         "magento/module-backend": "1.0.0-beta",
         "magento/module-theme": "1.0.0-beta",
diff --git a/app/code/Magento/CatalogSearch/etc/indexer.xml b/app/code/Magento/CatalogSearch/etc/indexer.xml
index 3efa7c7c2e401f5add3cc35adef89573df33b4a3..e86e606ea201cd889769a38578bad671bd1cf28b 100644
--- a/app/code/Magento/CatalogSearch/etc/indexer.xml
+++ b/app/code/Magento/CatalogSearch/etc/indexer.xml
@@ -5,9 +5,12 @@
  * See COPYING.txt for license details.
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Indexer/etc/indexer.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Indexer/etc/indexer.xsd">
     <indexer id="catalogsearch_fulltext" view_id="catalogsearch_fulltext" class="Magento\CatalogSearch\Model\Indexer\Fulltext">
         <title translate="true">Catalog Search</title>
         <description translate="true">Rebuild Catalog product fulltext search index</description>
+
+        <saveHandler class="Magento\CatalogSearch\Model\Indexer\IndexHandler" />
+        <structure class="Magento\CatalogSearch\Model\Indexer\IndexStructure" />
     </indexer>
 </config>
diff --git a/app/code/Magento/Cms/Model/Resource/Block/Grid/Collection.php b/app/code/Magento/Cms/Model/Resource/Block/Grid/Collection.php
index 427dbe5f1b67a3b81656831a01c1b905a9b8a3d9..7d8193c4bab998d29abdbb269733f6b923cded76 100644
--- a/app/code/Magento/Cms/Model/Resource/Block/Grid/Collection.php
+++ b/app/code/Magento/Cms/Model/Resource/Block/Grid/Collection.php
@@ -31,7 +31,8 @@ class Collection extends BlockCollection implements SearchResultInterface
      * @param string $resourceModel
      * @param string $model
      * @param string|null $connection
-     * @param \Magento\Framework\Model\Resource\Db\AbstractDb|null $resource
+     * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
+     *
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
diff --git a/app/code/Magento/Cms/Model/Resource/Page/Grid/Collection.php b/app/code/Magento/Cms/Model/Resource/Page/Grid/Collection.php
index f2df536005439c678e78c5ca9786ab21c6b2e84e..5e3cb9254b28e4a2b27368273c68ca8b4e51292d 100644
--- a/app/code/Magento/Cms/Model/Resource/Page/Grid/Collection.php
+++ b/app/code/Magento/Cms/Model/Resource/Page/Grid/Collection.php
@@ -33,6 +33,7 @@ class Collection extends PageCollection implements SearchResultInterface
      * @param string $model
      * @param null $connection
      * @param \Magento\Framework\Model\Resource\Db\AbstractDb|null $resource
+     * 
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
diff --git a/app/code/Magento/Customer/Api/AddressMetadataManagementInterface.php b/app/code/Magento/Customer/Api/AddressMetadataManagementInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..ceeb4cff8c4b6470766ff1076cc6f771e45de833
--- /dev/null
+++ b/app/code/Magento/Customer/Api/AddressMetadataManagementInterface.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Api;
+
+/**
+ * Interface for managing customer address attributes metadata.
+ */
+interface AddressMetadataManagementInterface extends MetadataManagementInterface
+{
+    const ENTITY_TYPE_ADDRESS = 'customer_address';
+}
diff --git a/app/code/Magento/Customer/Api/CustomerMetadataManagementInterface.php b/app/code/Magento/Customer/Api/CustomerMetadataManagementInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..7e20eb1693bf6ab4577d642c69fdf9e0a1ceacc2
--- /dev/null
+++ b/app/code/Magento/Customer/Api/CustomerMetadataManagementInterface.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Api;
+
+/**
+ * Interface for managing customer attributes metadata.
+ */
+interface CustomerMetadataManagementInterface extends MetadataManagementInterface
+{
+    const ENTITY_TYPE_CUSTOMER = 'customer';
+}
diff --git a/app/code/Magento/Customer/Api/Data/AttributeMetadataInterface.php b/app/code/Magento/Customer/Api/Data/AttributeMetadataInterface.php
index 988aea370ef94d5a181d734fb72783055fe52ae9..3e526093f4e09f9b4596e7399df2bbf5cd1d09ae 100644
--- a/app/code/Magento/Customer/Api/Data/AttributeMetadataInterface.php
+++ b/app/code/Magento/Customer/Api/Data/AttributeMetadataInterface.php
@@ -31,6 +31,10 @@ interface AttributeMetadataInterface extends \Magento\Framework\Api\MetadataObje
     const SYSTEM = 'system';
     const NOTE = 'note';
     const BACKEND_TYPE = 'backend_type';
+    const IS_USED_IN_GRID = 'is_used_in_grid';
+    const IS_VISIBLE_IN_GRID = 'is_visible_in_grid';
+    const IS_FILTERABLE_IN_GRID = 'is_filterable_in_grid';
+    const IS_SEARCHABLE_IN_GRID = 'is_searchable_in_grid';
     /**#@-*/
 
     /**
@@ -304,4 +308,64 @@ interface AttributeMetadataInterface extends \Magento\Framework\Api\MetadataObje
      * @return $this
      */
     public function setBackendType($backendType);
+
+    /**
+     * Whether it is used in customer grid
+     *
+     * @return bool|null
+     */
+    public function getIsUsedInGrid();
+
+    /**
+     * Whether it is visible in customer grid
+     *
+     * @return bool|null
+     */
+    public function getIsVisibleInGrid();
+
+    /**
+     * Whether it is filterable in customer grid
+     *
+     * @return bool|null
+     */
+    public function getIsFilterableInGrid();
+
+    /**
+     * Whether it is searchable in customer grid
+     *
+     * @return bool|null
+     */
+    public function getIsSearchableInGrid();
+
+    /**
+     * Set whether it is used in customer grid
+     *
+     * @param bool $isUsedInGrid
+     * @return $this
+     */
+    public function setIsUsedInGrid($isUsedInGrid);
+
+    /**
+     * Set whether it is visible in customer grid
+     *
+     * @param bool $isVisibleInGrid
+     * @return $this
+     */
+    public function setIsVisibleInGrid($isVisibleInGrid);
+
+    /**
+     * Set whether it is filterable in customer grid
+     *
+     * @param bool $isFilterableInGrid
+     * @return $this
+     */
+    public function setIsFilterableInGrid($isFilterableInGrid);
+
+    /**
+     * Set whether it is searchable in customer grid
+     *
+     * @param bool $isSearchableInGrid
+     * @return $this
+     */
+    public function setIsSearchableInGrid($isSearchableInGrid);
 }
diff --git a/app/code/Magento/Customer/Api/MetadataManagementInterface.php b/app/code/Magento/Customer/Api/MetadataManagementInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..fdf54ecc2dd7d9dead96f954e49ad88607e0f3b1
--- /dev/null
+++ b/app/code/Magento/Customer/Api/MetadataManagementInterface.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Api;
+
+use Magento\Customer\Api\Data\AttributeMetadataInterface;
+
+/**
+ * Interface for managing attributes metadata.
+ */
+interface MetadataManagementInterface
+{
+    /**
+     * Check whether attribute is searchable in admin grid and it is allowed
+     *
+     * @api
+     * @param AttributeMetadataInterface $attribute
+     * @return bool
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function canBeSearchableInGrid(AttributeMetadataInterface $attribute);
+
+    /**
+     * Check whether attribute is filterable in admin grid and it is allowed
+     *
+     * @api
+     * @param AttributeMetadataInterface $attribute
+     * @return bool
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function canBeFilterableInGrid(AttributeMetadataInterface $attribute);
+}
diff --git a/app/code/Magento/Customer/Block/Adminhtml/Customer.php b/app/code/Magento/Customer/Block/Adminhtml/Customer.php
deleted file mode 100644
index 11695be2d4406e69982dc1105f60fbe9f8487a8d..0000000000000000000000000000000000000000
--- a/app/code/Magento/Customer/Block/Adminhtml/Customer.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-/**
- * Adminhtml customers list block
- *
- * @author      Magento Core Team <core@magentocommerce.com>
- */
-namespace Magento\Customer\Block\Adminhtml;
-
-class Customer extends \Magento\Backend\Block\Widget\Grid\Container
-{
-    /**
-     * Constructor
-     *
-     * @return void
-     */
-    protected function _construct()
-    {
-        $this->_controller = 'adminhtml';
-        $this->_blockGroup = 'Magento_Customer';
-        $this->_headerText = __('Customers');
-        $this->_addButtonLabel = __('Add New Customer');
-        parent::_construct();
-    }
-}
diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/AbstractMassAction.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/AbstractMassAction.php
new file mode 100644
index 0000000000000000000000000000000000000000..94fd533646ebef4e57f841c0438e408da07121aa
--- /dev/null
+++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/AbstractMassAction.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Controller\Adminhtml\Index;
+
+use Magento\Eav\Model\Entity\Collection\AbstractCollection;
+use Magento\Framework\Controller\ResultFactory;
+use Magento\Framework\App\ResponseInterface;
+use Magento\Framework\Controller\ResultInterface;
+use Magento\Backend\App\Action\Context;
+use Magento\Ui\Component\MassAction\Filter;
+use Magento\Customer\Model\Resource\Customer\CollectionFactory;
+
+/**
+ * Class AbstractMassStatus
+ */
+abstract class AbstractMassAction extends \Magento\Backend\App\Action
+{
+    /**
+     * @var string
+     */
+    protected $redirectUrl = '*/*/index';
+
+    /**
+     * @var Filter
+     */
+    protected $filter;
+
+    /**
+     * @var CollectionFactory
+     */
+    protected $collectionFactory;
+
+    /**
+     * @param Context $context
+     * @param Filter $filter
+     * @param CollectionFactory $collectionFactory
+     */
+    public function __construct(Context $context, Filter $filter, CollectionFactory $collectionFactory)
+    {
+        parent::__construct($context);
+        $this->filter = $filter;
+        $this->collectionFactory = $collectionFactory;
+    }
+
+    /**
+     * Execute action
+     *
+     * @return \Magento\Backend\Model\View\Result\Redirect
+     * @throws \Magento\Framework\Exception\LocalizedException|\Exception
+     */
+    public function execute()
+    {
+        try {
+            $collection = $this->filter->getCollection($this->collectionFactory->create());
+            return $this->massAction($collection);
+        } catch (\Exception $e) {
+            $this->messageManager->addError($e->getMessage());
+            /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
+            $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
+            return $resultRedirect->setPath($this->redirectUrl);
+        }
+    }
+
+    /**
+     * Check the permission to Manage Customers
+     *
+     * @return bool
+     */
+    protected function _isAllowed()
+    {
+        return $this->_authorization->isAllowed('Magento_Customer::manage');
+    }
+
+    /**
+     * Return component referer url
+     * TODO: Technical dept referer url should be implement as a part of Action configuration in in appropriate way
+     *
+     * @return null|string
+     */
+    protected function getComponentRefererUrl()
+    {
+        return $this->filter->getComponentRefererUrl()?: 'customer/*/index';
+    }
+
+    /**
+     * Execute action to collection items
+     *
+     * @param AbstractCollection $collection
+     * @return ResponseInterface|ResultInterface
+     */
+    abstract protected function massAction(AbstractCollection $collection);
+}
diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Grid.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Grid.php
deleted file mode 100644
index e5839fccd0e9240330017efe61478a085a837c7a..0000000000000000000000000000000000000000
--- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Grid.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Customer\Controller\Adminhtml\Index;
-
-class Grid extends \Magento\Customer\Controller\Adminhtml\Index
-{
-    /**
-     * Customer grid action
-     *
-     * @return \Magento\Framework\View\Result\Layout
-     */
-    public function execute()
-    {
-        $resultLayout = $this->resultLayoutFactory->create();
-        return $resultLayout;
-    }
-}
diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/MassDelete.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/MassDelete.php
index 0f5a813facaddc008c380e694e16da1e9a900780..443cf7c72a5e40a1ddca07e8c9cf88df5640b5e7 100644
--- a/app/code/Magento/Customer/Controller/Adminhtml/Index/MassDelete.php
+++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/MassDelete.php
@@ -5,27 +5,58 @@
  */
 namespace Magento\Customer\Controller\Adminhtml\Index;
 
-class MassDelete extends \Magento\Customer\Controller\Adminhtml\Index
+use Magento\Backend\App\Action\Context;
+use Magento\Customer\Model\Resource\Customer\CollectionFactory;
+use Magento\Eav\Model\Entity\Collection\AbstractCollection;
+use Magento\Ui\Component\MassAction\Filter;
+use Magento\Customer\Api\CustomerRepositoryInterface;
+use Magento\Framework\Controller\ResultFactory;
+
+/**
+ * Class MassDelete
+ */
+class MassDelete extends AbstractMassAction
 {
     /**
-     * Customer mass delete action
-     *
+     * @var CustomerRepositoryInterface
+     */
+    protected $customerRepository;
+
+    /**
+     * @param Context $context
+     * @param Filter $filter
+     * @param CollectionFactory $collectionFactory
+     * @param CustomerRepositoryInterface $customerRepository
+     */
+    public function __construct(
+        Context $context,
+        Filter $filter,
+        CollectionFactory $collectionFactory,
+        CustomerRepositoryInterface $customerRepository
+    ) {
+        parent::__construct($context, $filter, $collectionFactory);
+        $this->customerRepository = $customerRepository;
+    }
+
+    /**
+     * @param AbstractCollection $collection
      * @return \Magento\Backend\Model\View\Result\Redirect
      */
-    public function execute()
+    protected function massAction(AbstractCollection $collection)
     {
-        $customerIds = $this->getRequest()->getParam('customer');
-        $customersDeleted = $this->actUponMultipleCustomers(
-            function ($customerId) {
-                $this->_customerRepository->deleteById($customerId);
-            },
-            $customerIds
-        );
+        $customersDeleted = 0;
+        foreach ($collection->getAllIds() as $customerId) {
+            $this->customerRepository->deleteById($customerId);
+            $customersDeleted++;
+        }
+
         if ($customersDeleted) {
             $this->messageManager->addSuccess(__('A total of %1 record(s) were deleted.', $customersDeleted));
         }
-        $resultRedirect = $this->resultRedirectFactory->create();
-        $resultRedirect->setPath('customer/*/index');
+        /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
+        $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
+        $resultRedirect->setPath($this->getComponentRefererUrl());
+
         return $resultRedirect;
     }
 }
diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/MassSubscribe.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/MassSubscribe.php
index 55d165504c551a302f15026245e09ccaaae10f27..0ba982ebbfa2e8bd4fe613c6367dbd950f6a8887 100644
--- a/app/code/Magento/Customer/Controller/Adminhtml/Index/MassSubscribe.php
+++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/MassSubscribe.php
@@ -5,29 +5,71 @@
  */
 namespace Magento\Customer\Controller\Adminhtml\Index;
 
-class MassSubscribe extends \Magento\Customer\Controller\Adminhtml\Index
+use Magento\Backend\App\Action\Context;
+use Magento\Ui\Component\MassAction\Filter;
+use Magento\Customer\Model\Resource\Customer\CollectionFactory;
+use Magento\Customer\Api\CustomerRepositoryInterface;
+use Magento\Newsletter\Model\SubscriberFactory;
+use Magento\Eav\Model\Entity\Collection\AbstractCollection;
+use Magento\Framework\Controller\ResultFactory;
+
+/**
+ * Class MassSubscribe
+ */
+class MassSubscribe extends AbstractMassAction
 {
+    /**
+     * @var CustomerRepositoryInterface
+     */
+    protected $customerRepository;
+
+    /**
+     * @var SubscriberFactory
+     */
+    protected $subscriberFactory;
+
+    /**
+     * @param Context $context
+     * @param Filter $filter
+     * @param CollectionFactory $collectionFactory
+     * @param CustomerRepositoryInterface $customerRepository
+     * @param SubscriberFactory $subscriberFactory
+     */
+    public function __construct(
+        Context $context,
+        Filter $filter,
+        CollectionFactory $collectionFactory,
+        CustomerRepositoryInterface $customerRepository,
+        SubscriberFactory $subscriberFactory
+    ) {
+        parent::__construct($context, $filter, $collectionFactory);
+        $this->customerRepository = $customerRepository;
+        $this->subscriberFactory = $subscriberFactory;
+    }
+
     /**
      * Customer mass subscribe action
      *
+     * @param AbstractCollection $collection
      * @return \Magento\Backend\Model\View\Result\Redirect
      */
-    public function execute()
+    protected function massAction(AbstractCollection $collection)
     {
-        $customerIds = $this->getRequest()->getParam('customer');
-        $customersUpdated = $this->actUponMultipleCustomers(
-            function ($customerId) {
-                // Verify customer exists
-                $this->_customerRepository->getById($customerId);
-                $this->_subscriberFactory->create()->subscribeCustomerById($customerId);
-            },
-            $customerIds
-        );
+        $customersUpdated = 0;
+        foreach ($collection->getAllIds() as $customerId) {
+            // Verify customer exists
+            $this->customerRepository->getById($customerId);
+            $this->subscriberFactory->create()->subscribeCustomerById($customerId);
+            $customersUpdated++;
+        }
+
         if ($customersUpdated) {
             $this->messageManager->addSuccess(__('A total of %1 record(s) were updated.', $customersUpdated));
         }
-        $resultRedirect = $this->resultRedirectFactory->create();
-        $resultRedirect->setPath('customer/*/index');
+        /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
+        $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
+        $resultRedirect->setPath($this->getComponentRefererUrl());
+
         return $resultRedirect;
     }
 }
diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/MassUnsubscribe.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/MassUnsubscribe.php
index abfc94844b33d1b45364bcd63878ce30eb646f5d..56f5c054fa6f6288b1639814e87f7e89a56f9bb1 100644
--- a/app/code/Magento/Customer/Controller/Adminhtml/Index/MassUnsubscribe.php
+++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/MassUnsubscribe.php
@@ -5,29 +5,71 @@
  */
 namespace Magento\Customer\Controller\Adminhtml\Index;
 
-class MassUnsubscribe extends \Magento\Customer\Controller\Adminhtml\Index
+use Magento\Customer\Api\CustomerRepositoryInterface;
+use Magento\Framework\Controller\ResultFactory;
+use Magento\Backend\App\Action\Context;
+use Magento\Newsletter\Model\SubscriberFactory;
+use Magento\Ui\Component\MassAction\Filter;
+use Magento\Customer\Model\Resource\Customer\CollectionFactory;
+use Magento\Eav\Model\Entity\Collection\AbstractCollection;
+
+/**
+ * Class MassUnsubscribe
+ */
+class MassUnsubscribe extends AbstractMassAction
 {
+    /**
+     * @var CustomerRepositoryInterface
+     */
+    protected $customerRepository;
+
+    /**
+     * @var SubscriberFactory
+     */
+    protected $subscriberFactory;
+
+    /**
+     * @param Context $context
+     * @param Filter $filter
+     * @param CollectionFactory $collectionFactory
+     * @param CustomerRepositoryInterface $customerRepository
+     * @param SubscriberFactory $subscriberFactory
+     */
+    public function __construct(
+        Context $context,
+        Filter $filter,
+        CollectionFactory $collectionFactory,
+        CustomerRepositoryInterface $customerRepository,
+        SubscriberFactory $subscriberFactory
+    ) {
+        parent::__construct($context, $filter, $collectionFactory);
+        $this->customerRepository = $customerRepository;
+        $this->subscriberFactory = $subscriberFactory;
+    }
+
     /**
      * Customer mass unsubscribe action
      *
+     * @param AbstractCollection $collection
      * @return \Magento\Backend\Model\View\Result\Redirect
      */
-    public function execute()
+    protected function massAction(AbstractCollection $collection)
     {
-        $customerIds = $this->getRequest()->getParam('customer');
-        $customersUpdated = $this->actUponMultipleCustomers(
-            function ($customerId) {
-                // Verify customer exists
-                $this->_customerRepository->getById($customerId);
-                $this->_subscriberFactory->create()->unsubscribeCustomerById($customerId);
-            },
-            $customerIds
-        );
+        $customersUpdated = 0;
+        foreach ($collection->getAllIds() as $customerId) {
+            // Verify customer exists
+            $this->customerRepository->getById($customerId);
+            $this->subscriberFactory->create()->unsubscribeCustomerById($customerId);
+            $customersUpdated++;
+        }
+
         if ($customersUpdated) {
             $this->messageManager->addSuccess(__('A total of %1 record(s) were updated.', $customersUpdated));
         }
-        $resultRedirect = $this->resultRedirectFactory->create();
-        $resultRedirect->setPath('customer/*/index');
+        /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
+        $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
+        $resultRedirect->setPath($this->getComponentRefererUrl());
+
         return $resultRedirect;
     }
 }
diff --git a/app/code/Magento/Customer/Model/Address.php b/app/code/Magento/Customer/Model/Address.php
index be22772a636b88dbd138ffc2ff22750ae62f8f30..c80b2aba4be32c577b6bbe9c2efa3d9429e5a673 100644
--- a/app/code/Magento/Customer/Model/Address.php
+++ b/app/code/Magento/Customer/Model/Address.php
@@ -9,6 +9,7 @@ use Magento\Customer\Api\AddressMetadataInterface;
 use Magento\Customer\Api\Data\AddressInterfaceFactory;
 use Magento\Customer\Api\Data\AddressInterface;
 use Magento\Customer\Api\Data\RegionInterfaceFactory;
+use Magento\Framework\Indexer\StateInterface;
 
 /**
  * Customer address model
@@ -41,6 +42,11 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress
      */
     protected $dataObjectHelper;
 
+    /**
+     * @var \Magento\Framework\Indexer\IndexerRegistry
+     */
+    protected $indexerRegistry;
+
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
@@ -57,9 +63,11 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress
      * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper
      * @param CustomerFactory $customerFactory
      * @param \Magento\Framework\Reflection\DataObjectProcessor $dataProcessor
-     * @param \Magento\Framework\Model\Resource\AbstractResource $resource
-     * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Model\Resource\AbstractResource|null $resource
+     * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
      * @param array $data
+     *
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
@@ -78,12 +86,14 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress
         \Magento\Framework\Api\DataObjectHelper $dataObjectHelper,
         CustomerFactory $customerFactory,
         \Magento\Framework\Reflection\DataObjectProcessor $dataProcessor,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         \Magento\Framework\Model\Resource\AbstractResource $resource = null,
         \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
         array $data = []
     ) {
         $this->dataProcessor = $dataProcessor;
         $this->_customerFactory = $customerFactory;
+        $this->indexerRegistry = $indexerRegistry;
         parent::__construct(
             $context,
             $registry,
@@ -300,4 +310,41 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress
     {
         return $this->getEntityType()->getId();
     }
+
+    /**
+     * Processing object after save data
+     *
+     * @return $this
+     */
+    public function afterSave()
+    {
+        $indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID);
+        if ($indexer->getState()->getStatus() == StateInterface::STATUS_VALID) {
+            $this->_getResource()->addCommitCallback([$this, 'reindex']);
+        }
+        return parent::afterSave();
+    }
+
+    /**
+     * Init indexing process after customer delete
+     *
+     * @return \Magento\Framework\Model\AbstractModel
+     */
+    public function afterDeleteCommit()
+    {
+        $this->reindex();
+        return parent::afterDeleteCommit();
+    }
+
+    /**
+     * Init indexing process after customer save
+     *
+     * @return void
+     */
+    public function reindex()
+    {
+        /** @var \Magento\Framework\Indexer\IndexerInterface $indexer */
+        $indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID);
+        $indexer->reindexRow($this->getCustomerId());
+    }
 }
diff --git a/app/code/Magento/Customer/Model/Attribute.php b/app/code/Magento/Customer/Model/Attribute.php
index cf87d2683af47d8d2584e53c3c409ff9897d4cea..ebb6d54bce354503c80aacfe1a415828e9416ad0 100644
--- a/app/code/Magento/Customer/Model/Attribute.php
+++ b/app/code/Magento/Customer/Model/Attribute.php
@@ -5,10 +5,15 @@
  */
 namespace Magento\Customer\Model;
 
+use Magento\Framework\Api\AttributeValueFactory;
+use Magento\Catalog\Api\Data\EavAttributeInterface;
+use Magento\Framework\Stdlib\DateTime\DateTimeFormatterInterface;
+
 /**
  * Customer attribute model
  *
  * @method int getSortOrder()
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
 class Attribute extends \Magento\Eav\Model\Attribute
 {
@@ -31,6 +36,81 @@ class Attribute extends \Magento\Eav\Model\Attribute
      */
     protected $_eventObject = 'attribute';
 
+    /**
+     * @var \Magento\Framework\Indexer\IndexerRegistry
+     */
+    protected $indexerRegistry;
+
+    /**
+     * @param \Magento\Framework\Model\Context $context
+     * @param \Magento\Framework\Registry $registry
+     * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory
+     * @param AttributeValueFactory $customAttributeFactory
+     * @param \Magento\Eav\Model\Config $eavConfig
+     * @param \Magento\Eav\Model\Entity\TypeFactory $eavTypeFactory
+     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
+     * @param \Magento\Eav\Model\Resource\Helper $resourceHelper
+     * @param \Magento\Framework\Validator\UniversalFactory $universalFactory
+     * @param \Magento\Eav\Api\Data\AttributeOptionInterfaceFactory $optionDataFactory
+     * @param \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor
+     * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper
+     * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
+     * @param \Magento\Catalog\Model\Product\ReservedAttributeList $reservedAttributeList
+     * @param \Magento\Framework\Locale\ResolverInterface $localeResolver
+     * @param DateTimeFormatterInterface $dateTimeFormatter
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Model\Resource\AbstractResource|null $resource
+     * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
+     * @param array $data
+     *
+     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
+     */
+    public function __construct(
+        \Magento\Framework\Model\Context $context,
+        \Magento\Framework\Registry $registry,
+        \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory,
+        AttributeValueFactory $customAttributeFactory,
+        \Magento\Eav\Model\Config $eavConfig,
+        \Magento\Eav\Model\Entity\TypeFactory $eavTypeFactory,
+        \Magento\Store\Model\StoreManagerInterface $storeManager,
+        \Magento\Eav\Model\Resource\Helper $resourceHelper,
+        \Magento\Framework\Validator\UniversalFactory $universalFactory,
+        \Magento\Eav\Api\Data\AttributeOptionInterfaceFactory $optionDataFactory,
+        \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor,
+        \Magento\Framework\Api\DataObjectHelper $dataObjectHelper,
+        \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
+        \Magento\Catalog\Model\Product\ReservedAttributeList $reservedAttributeList,
+        \Magento\Framework\Locale\ResolverInterface $localeResolver,
+        DateTimeFormatterInterface $dateTimeFormatter,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
+        \Magento\Framework\Model\Resource\AbstractResource $resource = null,
+        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
+        array $data = []
+    ) {
+        $this->indexerRegistry = $indexerRegistry;
+        parent::__construct(
+            $context,
+            $registry,
+            $extensionFactory,
+            $customAttributeFactory,
+            $eavConfig,
+            $eavTypeFactory,
+            $storeManager,
+            $resourceHelper,
+            $universalFactory,
+            $optionDataFactory,
+            $dataObjectProcessor,
+            $dataObjectHelper,
+            $localeDate,
+            $reservedAttributeList,
+            $localeResolver,
+            $dateTimeFormatter,
+            $resource,
+            $resourceCollection,
+            $data
+        );
+    }
+
     /**
      * Init resource model
      *
@@ -40,4 +120,65 @@ class Attribute extends \Magento\Eav\Model\Attribute
     {
         $this->_init('Magento\Customer\Model\Resource\Attribute');
     }
+
+    /**
+     * Processing object after save data
+     *
+     * @return $this
+     */
+    public function afterSave()
+    {
+        if ($this->isObjectNew() && (bool)$this->getData(EavAttributeInterface::IS_USED_IN_GRID)) {
+            $this->_getResource()->addCommitCallback([$this, 'invalidate']);
+        } elseif (!$this->isObjectNew() && $this->dataHasChangedFor(EavAttributeInterface::IS_USED_IN_GRID)) {
+            $this->_getResource()->addCommitCallback([$this, 'invalidate']);
+        }
+        return parent::afterSave();
+    }
+
+    /**
+     * Init indexing process after customer delete
+     *
+     * @return \Magento\Framework\Model\AbstractModel
+     */
+    public function afterDeleteCommit()
+    {
+        if ($this->getData(EavAttributeInterface::IS_USED_IN_GRID) == true) {
+            $this->invalidate();
+        }
+        return parent::afterDeleteCommit();
+    }
+
+    /**
+     * Init indexing process after customer save
+     *
+     * @return void
+     */
+    public function invalidate()
+    {
+        /** @var \Magento\Framework\Indexer\IndexerInterface $indexer */
+        $indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID);
+        $indexer->invalidate();
+    }
+
+    /**
+     * Check whether attribute is searchable in admin grid and it is allowed
+     *
+     * @return bool
+     */
+    public function canBeSearchableInGrid()
+    {
+        return $this->getData('is_searchable_in_grid') && in_array($this->getFrontendInput(), ['text', 'textarea']);
+    }
+
+    /**
+     * Check whether attribute is filterable in admin grid and it is allowed
+     *
+     * @return bool
+     */
+    public function canBeFilterableInGrid()
+    {
+        return $this->getData('is_filterable_in_grid')
+            && in_array($this->getFrontendInput(), ['text', 'date', 'select', 'boolean']);
+    }
 }
diff --git a/app/code/Magento/Customer/Model/AttributeMetadataConverter.php b/app/code/Magento/Customer/Model/AttributeMetadataConverter.php
index a9fc1eb30fd224344967d1f18245ef37a3d14116..01f741581a59654726490b8a9da70398ea24329c 100644
--- a/app/code/Magento/Customer/Model/AttributeMetadataConverter.php
+++ b/app/code/Magento/Customer/Model/AttributeMetadataConverter.php
@@ -109,6 +109,10 @@ class AttributeMetadataConverter
             ->setIsSystem((boolean)$attribute->getIsSystem())
             ->setIsUserDefined((boolean)$attribute->getIsUserDefined())
             ->setBackendType($attribute->getBackendType())
-            ->setSortOrder((int)$attribute->getSortOrder());
+            ->setSortOrder((int)$attribute->getSortOrder())
+            ->setIsUsedInGrid($attribute->getIsUsedInGrid())
+            ->setIsVisibleInGrid($attribute->getIsVisibleInGrid())
+            ->setIsFilterableInGrid($attribute->getIsFilterableInGrid())
+            ->setIsSearchableInGrid($attribute->getIsSearchableInGrid());
     }
 }
diff --git a/app/code/Magento/Customer/Model/Customer.php b/app/code/Magento/Customer/Model/Customer.php
index c607dcbd62f46cc3b4569c2e5a760f252315f206..dc8085e7e25fdbd767daac4b328d6c2d53419739 100644
--- a/app/code/Magento/Customer/Model/Customer.php
+++ b/app/code/Magento/Customer/Model/Customer.php
@@ -16,6 +16,7 @@ use Magento\Framework\Reflection\DataObjectProcessor;
 use Magento\Framework\Exception\EmailNotConfirmedException;
 use Magento\Framework\Exception\InvalidEmailOrPasswordException;
 use Magento\Framework\Exception\AuthenticationException;
+use Magento\Framework\Indexer\StateInterface;
 
 /**
  * Customer model
@@ -69,6 +70,8 @@ class Customer extends \Magento\Framework\Model\AbstractModel
 
     const ENTITY = 'customer';
 
+    const CUSTOMER_GRID_INDEXER_ID = 'customer_grid';
+
     /**
      * Configuration path to expiration period of reset password link
      */
@@ -198,27 +201,33 @@ class Customer extends \Magento\Framework\Model\AbstractModel
      */
     protected $metadataService;
 
+    /**
+     * @var \Magento\Framework\Indexer\IndexerRegistry
+     */
+    protected $indexerRegistry;
+
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      * @param \Magento\Eav\Model\Config $config
-     * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
+     * @param ScopeConfigInterface $scopeConfig
      * @param ResourceCustomer $resource
      * @param Share $configShare
      * @param AddressFactory $addressFactory
      * @param CollectionFactory $addressesFactory
      * @param \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder
      * @param GroupRepositoryInterface $groupRepository
-     * @param AttributeFactory $attributeFactory
      * @param \Magento\Framework\Encryption\EncryptorInterface $encryptor
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
      * @param CustomerInterfaceFactory $customerDataFactory
      * @param DataObjectProcessor $dataObjectProcessor
      * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper
      * @param CustomerMetadataInterface $metadataService
-     * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
      * @param array $data
+     *
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
@@ -239,6 +248,7 @@ class Customer extends \Magento\Framework\Model\AbstractModel
         DataObjectProcessor $dataObjectProcessor,
         \Magento\Framework\Api\DataObjectHelper $dataObjectHelper,
         \Magento\Customer\Api\CustomerMetadataInterface $metadataService,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
         array $data = []
     ) {
@@ -256,6 +266,7 @@ class Customer extends \Magento\Framework\Model\AbstractModel
         $this->customerDataFactory = $customerDataFactory;
         $this->dataObjectProcessor = $dataObjectProcessor;
         $this->dataObjectHelper = $dataObjectHelper;
+        $this->indexerRegistry = $indexerRegistry;
         parent::__construct(
             $context,
             $registry,
@@ -1069,6 +1080,43 @@ class Customer extends \Magento\Framework\Model\AbstractModel
         return parent::beforeDelete();
     }
 
+    /**
+     * Processing object after save data
+     *
+     * @return $this
+     */
+    public function afterSave()
+    {
+        $indexer = $this->indexerRegistry->get(self::CUSTOMER_GRID_INDEXER_ID);
+        if ($indexer->getState()->getStatus() == StateInterface::STATUS_VALID) {
+            $this->_getResource()->addCommitCallback([$this, 'reindex']);
+        }
+        return parent::afterSave();
+    }
+
+    /**
+     * Init indexing process after customer delete
+     *
+     * @return \Magento\Framework\Model\AbstractModel
+     */
+    public function afterDeleteCommit()
+    {
+        $this->reindex();
+        return parent::afterDeleteCommit();
+    }
+
+    /**
+     * Init indexing process after customer save
+     *
+     * @return void
+     */
+    public function reindex()
+    {
+        /** @var \Magento\Framework\Indexer\IndexerInterface $indexer */
+        $indexer = $this->indexerRegistry->get(self::CUSTOMER_GRID_INDEXER_ID);
+        $indexer->reindexRow($this->getId());
+    }
+
     /**
      * Get customer created at date timestamp
      *
diff --git a/app/code/Magento/Customer/Model/Data/AttributeMetadata.php b/app/code/Magento/Customer/Model/Data/AttributeMetadata.php
index dbf7feb726e23ba71d7bbf9dcef3b79a4433c1d7..136ea015067e8cfa8d30c06f21636e63b1f2b1d6 100644
--- a/app/code/Magento/Customer/Model/Data/AttributeMetadata.php
+++ b/app/code/Magento/Customer/Model/Data/AttributeMetadata.php
@@ -6,6 +6,8 @@
 
 namespace Magento\Customer\Model\Data;
 
+use Magento\Customer\Api\Data\AttributeMetadataInterface;
+
 /**
  * Customer attribute metadata class.
  */
@@ -334,4 +336,68 @@ class AttributeMetadata extends \Magento\Framework\Api\AbstractSimpleObject impl
     {
         return $this->setData(self::BACKEND_TYPE, $backendType);
     }
+
+    /**
+     * @inheritDoc
+     */
+    public function getIsUsedInGrid()
+    {
+        return $this->_get(self::IS_USED_IN_GRID);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function getIsVisibleInGrid()
+    {
+        return $this->_get(self::IS_VISIBLE_IN_GRID);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function getIsFilterableInGrid()
+    {
+        return $this->_get(self::IS_FILTERABLE_IN_GRID);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function getIsSearchableInGrid()
+    {
+        return $this->_get(self::IS_SEARCHABLE_IN_GRID);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function setIsUsedInGrid($isUsedInGrid)
+    {
+        return $this->setData(self::IS_USED_IN_GRID, $isUsedInGrid);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function setIsVisibleInGrid($isVisibleInGrid)
+    {
+        return $this->setData(self::IS_VISIBLE_IN_GRID, $isVisibleInGrid);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function setIsFilterableInGrid($isFilterableInGrid)
+    {
+        return $this->setData(self::IS_FILTERABLE_IN_GRID, $isFilterableInGrid);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function setIsSearchableInGrid($isSearchableInGrid)
+    {
+        return $this->setData(self::IS_SEARCHABLE_IN_GRID, $isSearchableInGrid);
+    }
 }
diff --git a/app/code/Magento/Customer/Model/Indexer/Address/AttributeProvider.php b/app/code/Magento/Customer/Model/Indexer/Address/AttributeProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..b2a607b535cc2fb7c9eeaede541057998e17e705
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Indexer/Address/AttributeProvider.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\Indexer\Address;
+
+use Magento\Customer\Model\Resource\Address\Attribute\Collection;
+use Magento\Eav\Model\Config;
+use Magento\Eav\Model\Entity\Attribute;
+
+class AttributeProvider extends \Magento\Customer\Model\Indexer\AttributeProvider
+{
+    /**
+     * EAV entity
+     */
+    const ENTITY = 'customer_address';
+
+    /**
+     * @param Config $eavConfig
+     */
+    public function __construct(
+        Config $eavConfig
+    ) {
+        parent::__construct($eavConfig);
+    }
+}
diff --git a/app/code/Magento/Customer/Model/Indexer/Attribute/Filter.php b/app/code/Magento/Customer/Model/Indexer/Attribute/Filter.php
new file mode 100644
index 0000000000000000000000000000000000000000..8c954838797bcc18a39843d803361552d6433d8f
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Indexer/Attribute/Filter.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\Indexer\Attribute;
+
+use Magento\Framework\App\Resource;
+use Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver;
+use Magento\Customer\Model\Customer;
+use Magento\Framework\Indexer\IndexerRegistry;
+use Magento\Framework\Indexer\StateInterface;
+
+class Filter
+{
+    /** @var Resource */
+    protected $resource;
+
+    /** @var FlatScopeResolver  */
+    protected $flatScopeResolver;
+
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
+    protected $indexerRegistry;
+
+    /**
+     * @param Resource $resource
+     * @param FlatScopeResolver $flatScopeResolver
+     * @param IndexerRegistry $indexerRegistry
+     */
+    public function __construct(
+        Resource $resource,
+        FlatScopeResolver $flatScopeResolver,
+        IndexerRegistry $indexerRegistry
+    ) {
+        $this->resource = $resource;
+        $this->flatScopeResolver = $flatScopeResolver;
+        $this->indexerRegistry = $indexerRegistry;
+    }
+
+    /**
+     * @param array $attributes
+     * @return array
+     */
+    public function filter(array $attributes)
+    {
+        $indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID);
+        if ($indexer->getState()->getStatus() != StateInterface::STATUS_VALID) {
+            $tableName = $this->flatScopeResolver->resolve(Customer::CUSTOMER_GRID_INDEXER_ID, []);
+            $columns = $this->resource->getConnection()->describeTable($tableName);
+
+            foreach (array_keys($attributes) as $attributeCode) {
+                if (!isset($columns[$attributeCode])) {
+                    unset($attributes[$attributeCode]);
+                }
+            }
+        }
+
+        return $attributes;
+    }
+}
diff --git a/app/code/Magento/Customer/Model/Indexer/AttributeProvider.php b/app/code/Magento/Customer/Model/Indexer/AttributeProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..53f7a695e4cd9e61d721db5d58bbd7c1fb62377e
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Indexer/AttributeProvider.php
@@ -0,0 +1,154 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\Indexer;
+
+use Magento\Customer\Model\Customer;
+use Magento\Framework\Indexer\FieldsetInterface;
+use Magento\Eav\Model\Config;
+use Magento\Customer\Model\Attribute;
+
+class AttributeProvider implements FieldsetInterface
+{
+    /**
+     * EAV entity
+     */
+    const ENTITY = Customer::ENTITY;
+
+    /**
+     * @var Attribute[]
+     */
+    protected $attributes;
+
+    /**
+     * @var Config
+     */
+    protected $eavConfig;
+
+    /**
+     * @param Config $eavConfig
+     */
+    public function __construct(
+        Config $eavConfig
+    ) {
+        $this->eavConfig = $eavConfig;
+    }
+
+    /**
+     * Add EAV attribute fields to fieldset
+     *
+     * @param array $data
+     * @return array
+     */
+    public function addDynamicData(array $data)
+    {
+        $additionalFields = $this->convert($this->getAttributes(), $data);
+        $data['fields'] = $this->merge($data['fields'], $additionalFields);
+        return $data;
+    }
+
+    /**
+     * Retrieve all attributes
+     *
+     * @return Attribute[]
+     */
+    private function getAttributes()
+    {
+        if ($this->attributes === null) {
+            $this->attributes = [];
+            $entityType = $this->eavConfig->getEntityType(static::ENTITY);
+            /** @var \Magento\Customer\Model\Attribute[] $attributes */
+            $attributes = $entityType->getAttributeCollection()->getItems();
+            /** @var \Magento\Customer\Model\Resource\Customer $entity */
+            $entity = $entityType->getEntity();
+
+            foreach ($attributes as $attribute) {
+                $attribute->setEntity($entity);
+            }
+            $this->attributes = $attributes;
+        }
+
+        return $this->attributes;
+    }
+
+    /**
+     * Convert attributes to fields
+     *
+     * @param Attribute[] $attributes
+     * @param array $fieldset
+     * @return array
+     */
+    protected function convert(array $attributes, array $fieldset)
+    {
+        $fields = [];
+        foreach ($attributes as $attribute) {
+            if (!$attribute->isStatic()) {
+                if ($attribute->getData('is_used_in_grid')) {
+                    $fields[$attribute->getName()] = [
+                        'name' => $attribute->getName(),
+                        'handler' => 'Magento\Framework\Indexer\Handler\AttributeHandler',
+                        'origin' => $attribute->getName(),
+                        'type' => $this->getType($attribute),
+                        'dataType' => $attribute->getBackendType(),
+                        'filters' => [],
+                        'entity' => static::ENTITY,
+                        'bind' => isset($fieldset['references']['customer']['to'])
+                            ? $fieldset['references']['customer']['to']
+                            : null,
+                    ];
+                }
+            } else {
+                $fields[$attribute->getName()] = [
+                    'type' => $this->getType($attribute),
+                ];
+            }
+        }
+
+        return $fields;
+    }
+
+    /**
+     * Get field type for attribute
+     *
+     * @param Attribute $attribute
+     * @return string
+     */
+    protected function getType(Attribute $attribute)
+    {
+        if ($attribute->canBeSearchableInGrid()) {
+            $type = 'searchable';
+        } elseif ($attribute->canBeFilterableInGrid()) {
+            $type = 'filterable';
+        } else {
+            $type = 'virtual';
+        }
+
+        return $type;
+    }
+
+    /**
+     * Merge fields with attribute fields
+     *
+     * @param array $dataFields
+     * @param array $searchableFields
+     * @return array
+     */
+    protected function merge(array $dataFields, array $searchableFields)
+    {
+        foreach ($searchableFields as $name => $field) {
+            if (!isset($field['name']) && !isset($dataFields[$name])) {
+                continue;
+            }
+            if (!isset($dataFields[$name])) {
+                $dataFields[$name] = [];
+            }
+            foreach ($field as $key => $value) {
+                $dataFields[$name][$key] = $value;
+            }
+        }
+
+        return $dataFields;
+    }
+}
diff --git a/app/code/Magento/Customer/Model/Metadata/AddressMetadataManagement.php b/app/code/Magento/Customer/Model/Metadata/AddressMetadataManagement.php
new file mode 100644
index 0000000000000000000000000000000000000000..3c8ae5c3284d93927729111a3975b4584775f7c9
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Metadata/AddressMetadataManagement.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\Metadata;
+
+use Magento\Customer\Api\AddressMetadataManagementInterface;
+use Magento\Customer\Api\Data\AttributeMetadataInterface;
+
+/**
+ * Service to manage customer address related custom attributes
+ */
+class AddressMetadataManagement implements AddressMetadataManagementInterface
+{
+    /**
+     * @var AttributeResolver
+     */
+    protected $attributeResolver;
+
+    /**
+     * @param AttributeResolver $attributeResolver
+     */
+    public function __construct(
+        AttributeResolver $attributeResolver
+    ) {
+        $this->attributeResolver = $attributeResolver;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function canBeSearchableInGrid(AttributeMetadataInterface $attribute)
+    {
+        return $this->attributeResolver->getModelByAttribute(self::ENTITY_TYPE_ADDRESS, $attribute)
+            ->canBeSearchableInGrid();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function canBeFilterableInGrid(AttributeMetadataInterface $attribute)
+    {
+        return $this->attributeResolver->getModelByAttribute(self::ENTITY_TYPE_ADDRESS, $attribute)
+            ->canBeFilterableInGrid();
+    }
+}
diff --git a/app/code/Magento/Customer/Model/Metadata/AttributeResolver.php b/app/code/Magento/Customer/Model/Metadata/AttributeResolver.php
new file mode 100644
index 0000000000000000000000000000000000000000..57c814f9a74bd280038646adedfb647851db0908
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Metadata/AttributeResolver.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\Metadata;
+
+use Magento\Customer\Model\Attribute;
+use Magento\Customer\Model\AttributeMetadataDataProvider;
+use Magento\Customer\Api\Data\AttributeMetadataInterface;
+use Magento\Framework\Exception\NoSuchEntityException;
+
+class AttributeResolver
+{
+    /**
+     * @var AttributeMetadataDataProvider
+     */
+    protected $attributeMetadataDataProvider;
+
+    /**
+     * @param AttributeMetadataDataProvider $attributeMetadataDataProvider
+     */
+    public function __construct(
+        AttributeMetadataDataProvider $attributeMetadataDataProvider
+    ) {
+        $this->attributeMetadataDataProvider = $attributeMetadataDataProvider;
+    }
+
+    /**
+     * Get attribute model by attribute data object
+     *
+     * @param string $entityType
+     * @param AttributeMetadataInterface $attribute
+     * @return Attribute
+     * @throws NoSuchEntityException
+     */
+    public function getModelByAttribute($entityType, AttributeMetadataInterface $attribute)
+    {
+        /** @var Attribute $model */
+        $model = $this->attributeMetadataDataProvider->getAttribute(
+            $entityType,
+            $attribute->getAttributeCode()
+        );
+        if ($model) {
+            return $model;
+        } else {
+            throw new NoSuchEntityException(
+                __(
+                    NoSuchEntityException::MESSAGE_DOUBLE_FIELDS,
+                    [
+                        'fieldName' => 'entityType',
+                        'fieldValue' => $entityType,
+                        'field2Name' => 'attributeCode',
+                        'field2Value' => $attribute->getAttributeCode(),
+                    ]
+                )
+            );
+        }
+    }
+}
diff --git a/app/code/Magento/Customer/Model/Metadata/CustomerMetadataManagement.php b/app/code/Magento/Customer/Model/Metadata/CustomerMetadataManagement.php
new file mode 100644
index 0000000000000000000000000000000000000000..67ba212dbdff84e2c0851f1bb66093cc75c83181
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Metadata/CustomerMetadataManagement.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\Metadata;
+
+use Magento\Customer\Api\CustomerMetadataManagementInterface;
+use Magento\Customer\Api\Data\AttributeMetadataInterface;
+
+/**
+ * Service to manage customer related custom attributes
+ */
+class CustomerMetadataManagement implements CustomerMetadataManagementInterface
+{
+    /**
+     * @var AttributeResolver
+     */
+    protected $attributeResolver;
+
+    /**
+     * @param AttributeResolver $attributeResolver
+     */
+    public function __construct(
+        AttributeResolver $attributeResolver
+    ) {
+        $this->attributeResolver = $attributeResolver;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function canBeSearchableInGrid(AttributeMetadataInterface $attribute)
+    {
+        return $this->attributeResolver->getModelByAttribute(self::ENTITY_TYPE_CUSTOMER, $attribute)
+            ->canBeSearchableInGrid();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function canBeFilterableInGrid(AttributeMetadataInterface $attribute)
+    {
+        return $this->attributeResolver->getModelByAttribute(self::ENTITY_TYPE_CUSTOMER, $attribute)
+            ->canBeFilterableInGrid();
+    }
+}
diff --git a/app/code/Magento/Customer/Model/Observer/Grid.php b/app/code/Magento/Customer/Model/Observer/Grid.php
new file mode 100644
index 0000000000000000000000000000000000000000..7b958a5f251b7be98638e25a017adad25a3681a3
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Observer/Grid.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\Observer;
+
+use Magento\Customer\Model\Resource\Customer\Grid as CustomerGrid;
+
+class Grid
+{
+    /**
+     * @var CustomerGrid
+     */
+    protected $customerGrid;
+
+    /**
+     * @param CustomerGrid $grid
+     */
+    public function __construct(
+        CustomerGrid $grid
+    ) {
+        $this->customerGrid = $grid;
+    }
+
+    /**
+     * @return void
+     */
+    public function syncCustomerGrid()
+    {
+        $this->customerGrid->syncCustomerGrid();
+    }
+}
diff --git a/app/code/Magento/Customer/Model/Resource/Customer/Grid.php b/app/code/Magento/Customer/Model/Resource/Customer/Grid.php
new file mode 100644
index 0000000000000000000000000000000000000000..0c216fcc6e811f489c3e93e44586a2e51d73d6a4
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Resource/Customer/Grid.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\Resource\Customer;
+
+use Magento\Framework\App\Resource;
+use Magento\Framework\Indexer\IndexerRegistry;
+use Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver;
+use Magento\Customer\Model\Customer;
+
+class Grid
+{
+    /** @var Resource */
+    protected $resource;
+
+    /**
+     * @var \Magento\Framework\Indexer\IndexerRegistry
+     */
+    protected $indexerRegistry;
+
+    /** @var FlatScopeResolver  */
+    protected $flatScopeResolver;
+
+    /**
+     * @param Resource $resource
+     * @param IndexerRegistry $indexerRegistry
+     * @param FlatScopeResolver $flatScopeResolver
+     */
+    public function __construct(
+        Resource $resource,
+        IndexerRegistry $indexerRegistry,
+        FlatScopeResolver $flatScopeResolver
+    ) {
+        $this->resource = $resource;
+        $this->indexerRegistry = $indexerRegistry;
+        $this->flatScopeResolver = $flatScopeResolver;
+    }
+
+    /**
+     * Synchronize customer grid
+     *
+     * @return void
+     */
+    public function syncCustomerGrid()
+    {
+        $indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID);
+        $customerIds = $this->getCustomerIdsForReindex();
+        if ($customerIds) {
+            $indexer->reindexList($customerIds);
+        }
+    }
+
+    /**
+     * Retrieve customer IDs for reindex
+     *
+     * @return array
+     */
+    protected function getCustomerIdsForReindex()
+    {
+        $connection = $this->resource->getConnection();
+        $gridTableName = $this->flatScopeResolver->resolve(Customer::CUSTOMER_GRID_INDEXER_ID, []);
+
+        $select = $connection->select()
+            ->from($connection->getTableName($gridTableName), 'last_visit_at')
+            ->order('last_visit_at DESC')
+            ->limit(1);
+        $lastVisitAt = $connection->query($select)->fetchColumn();
+
+        $select = $connection->select()
+            ->from($connection->getTableName('customer_log'), 'customer_id')
+            ->where('last_login_at > ?', $lastVisitAt);
+
+        $customerIds = [];
+        foreach ($connection->query($select)->fetchAll() as $row) {
+            $customerIds[] = $row['customer_id'];
+        }
+
+        return $customerIds;
+    }
+}
diff --git a/app/code/Magento/Customer/Model/Resource/Customer/Grid/ServiceCollection.php b/app/code/Magento/Customer/Model/Resource/Customer/Grid/ServiceCollection.php
deleted file mode 100644
index de8f7aa1bf3389444efd4d2341f24a33e35e9c46..0000000000000000000000000000000000000000
--- a/app/code/Magento/Customer/Model/Resource/Customer/Grid/ServiceCollection.php
+++ /dev/null
@@ -1,104 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Customer\Model\Resource\Customer\Grid;
-
-use Magento\Framework\Data\Collection\EntityFactory;
-use Magento\Customer\Api\CustomerRepositoryInterface;
-use Magento\Customer\Api\Data\CustomerInterface;
-use Magento\Framework\Api\AbstractServiceCollection;
-use Magento\Framework\Api\FilterBuilder;
-use Magento\Framework\Api\SearchCriteriaBuilder;
-use Magento\Framework\Api\SortOrderBuilder;
-
-/**
- * Customer Grid Collection backed by Services
- */
-class ServiceCollection extends AbstractServiceCollection
-{
-    /**
-     * @var CustomerRepository
-     */
-    protected $customerRepository;
-
-    /**
-     * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory
-     * @param FilterBuilder $filterBuilder
-     * @param SearchCriteriaBuilder $searchCriteriaBuilder
-     * @param CustomerRepositoryInterface $customerRepository
-     * @param SortOrderBuilder $sortOrderBuilder
-     */
-    public function __construct(
-        EntityFactory $entityFactory,
-        FilterBuilder $filterBuilder,
-        SearchCriteriaBuilder $searchCriteriaBuilder,
-        SortOrderBuilder $sortOrderBuilder,
-        CustomerRepositoryInterface $customerRepository
-    ) {
-        parent::__construct($entityFactory, $filterBuilder, $searchCriteriaBuilder, $sortOrderBuilder);
-        $this->customerRepository = $customerRepository;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function loadData($printQuery = false, $logQuery = false)
-    {
-        if (!$this->isLoaded()) {
-            $searchCriteria = $this->getSearchCriteria();
-            $searchResults = $this->customerRepository->getList($searchCriteria);
-            $this->_totalRecords = $searchResults->getTotalCount();
-            /** @var CustomerInterface[] $customers */
-            $customers = $searchResults->getItems();
-            foreach ($customers as $customer) {
-                $this->_addItem($this->createCustomerItem($customer));
-            }
-            $this->_setIsLoaded();
-        }
-        return $this;
-    }
-
-    /**
-     * Creates a collection item that represents a customer for the customer Grid.
-     *
-     * @param CustomerInterface $customer Input data for creating the item.
-     * @return \Magento\Framework\DataObject Collection item that represents a customer
-     */
-    protected function createCustomerItem(CustomerInterface $customer)
-    {
-        $customerNameParts = [
-            $customer->getPrefix(),
-            $customer->getFirstname(),
-            $customer->getMiddlename(),
-            $customer->getLastname(),
-            $customer->getSuffix(),
-        ];
-        $customerItem = new \Magento\Framework\DataObject();
-        $customerItem->setId($customer->getId());
-        $customerItem->setEntityId($customer->getId());
-        // All parts of the customer name must be displayed in the name column of the grid
-        $customerItem->setName(implode(' ', array_filter($customerNameParts)));
-        $customerItem->setEmail($customer->getEmail());
-        $customerItem->setWebsiteId($customer->getWebsiteId());
-        $customerItem->setCreatedAt($customer->getCreatedAt());
-        $customerItem->setGroupId($customer->getGroupId());
-
-        $billingAddress = null;
-        foreach ($customer->getAddresses() as $address) {
-            if ($address->isDefaultBilling()) {
-                $billingAddress = $address;
-                break;
-            }
-        }
-        if ($billingAddress !== null) {
-            $customerItem->setBillingTelephone($billingAddress->getTelephone());
-            $customerItem->setBillingPostcode($billingAddress->getPostcode());
-            $customerItem->setBillingCountryId($billingAddress->getCountryId());
-            $region = $billingAddress->getRegion() === null ? '' : $billingAddress->getRegion()->getRegion();
-            $customerItem->setBillingRegion($region);
-        }
-        return $customerItem;
-    }
-}
diff --git a/app/code/Magento/Customer/Model/Resource/Setup/PropertyMapper.php b/app/code/Magento/Customer/Model/Resource/Setup/PropertyMapper.php
index 72704aa94f9ddd5d20ce3b8dbb240891179d6ca1..f375962b7dbfc6a7f6391039a0202da22c55f3b3 100644
--- a/app/code/Magento/Customer/Model/Resource/Setup/PropertyMapper.php
+++ b/app/code/Magento/Customer/Model/Resource/Setup/PropertyMapper.php
@@ -17,6 +17,8 @@ class PropertyMapper extends PropertyMapperAbstract
      * @param array $input
      * @param int $entityTypeId
      * @return array
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function map(array $input, $entityTypeId)
     {
@@ -27,7 +29,11 @@ class PropertyMapper extends PropertyMapperAbstract
             'multiline_count' => $this->_getValue($input, 'multiline_count', 0),
             'validate_rules' => $this->_getValue($input, 'validate_rules', null),
             'data_model' => $this->_getValue($input, 'data', null),
-            'sort_order' => $this->_getValue($input, 'position', 0)
+            'sort_order' => $this->_getValue($input, 'position', 0),
+            'is_used_in_grid' => $this->_getValue($input, 'is_used_in_grid', 0),
+            'is_visible_in_grid' => $this->_getValue($input, 'is_visible_in_grid', 0),
+            'is_filterable_in_grid' => $this->_getValue($input, 'is_filterable_in_grid', 0),
+            'is_searchable_in_grid' => $this->_getValue($input, 'is_searchable_in_grid', 0),
         ];
     }
 }
diff --git a/app/code/Magento/Customer/Model/Resource/Visitor/Collection.php b/app/code/Magento/Customer/Model/Resource/Visitor/Collection.php
new file mode 100644
index 0000000000000000000000000000000000000000..bfb12448688c2250749e8e015801fea4da826b39
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Resource/Visitor/Collection.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\Resource\Visitor;
+
+class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
+{
+    /**
+     * Resource initialization
+     *
+     * @return void
+     */
+    protected function _construct()
+    {
+        $this->_init('Magento\Customer\Model\Visitor', 'Magento\Customer\Model\Resource\Visitor');
+    }
+}
diff --git a/app/code/Magento/Customer/Model/Visitor.php b/app/code/Magento/Customer/Model/Visitor.php
index 4eac407129ffede22e7003221c46e2a0b5da7d12..164490b95300572f66197a0607b433ea2150b509 100644
--- a/app/code/Magento/Customer/Model/Visitor.php
+++ b/app/code/Magento/Customer/Model/Visitor.php
@@ -6,9 +6,12 @@
 
 namespace Magento\Customer\Model;
 
+use Magento\Framework\Indexer\StateInterface;
+
 /**
  * Class Visitor
  * @package Magento\Customer\Model
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
 class Visitor extends \Magento\Framework\Model\AbstractModel
 {
@@ -59,15 +62,21 @@ class Visitor extends \Magento\Framework\Model\AbstractModel
      */
     protected $dateTime;
 
+    /**
+     * @var \Magento\Framework\Indexer\IndexerRegistry
+     */
+    protected $indexerRegistry;
+
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Framework\Session\SessionManagerInterface $session
      * @param \Magento\Framework\HTTP\Header $httpHeader
-     * @param \Magento\Framework\Model\Resource\AbstractResource $resource
-     * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Model\Resource\AbstractResource|null $resource
+     * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
      * @param array $ignoredUserAgents
      * @param array $ignores
      * @param array $data
@@ -81,6 +90,7 @@ class Visitor extends \Magento\Framework\Model\AbstractModel
         \Magento\Framework\HTTP\Header $httpHeader,
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Framework\Stdlib\DateTime $dateTime,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         \Magento\Framework\Model\Resource\AbstractResource $resource = null,
         \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
         array $ignoredUserAgents = [],
@@ -94,6 +104,7 @@ class Visitor extends \Magento\Framework\Model\AbstractModel
         $this->ignores = $ignores;
         $this->scopeConfig = $scopeConfig;
         $this->dateTime = $dateTime;
+        $this->indexerRegistry = $indexerRegistry;
     }
 
     /**
diff --git a/app/code/Magento/Customer/Setup/UpgradeData.php b/app/code/Magento/Customer/Setup/UpgradeData.php
new file mode 100644
index 0000000000000000000000000000000000000000..a93a89503a042331c97209b6f78d44d3216530e8
--- /dev/null
+++ b/app/code/Magento/Customer/Setup/UpgradeData.php
@@ -0,0 +1,196 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Customer\Setup;
+
+use Magento\Customer\Model\Customer;
+use Magento\Framework\Indexer\IndexerRegistry;
+use Magento\Framework\Setup\UpgradeDataInterface;
+use Magento\Framework\Setup\ModuleContextInterface;
+use Magento\Framework\Setup\ModuleDataSetupInterface;
+
+/**
+ * @codeCoverageIgnore
+ */
+class UpgradeData implements UpgradeDataInterface
+{
+    /**
+     * Customer setup factory
+     *
+     * @var CustomerSetupFactory
+     */
+    protected $customerSetupFactory;
+
+    /**
+     * @var IndexerRegistry
+     */
+    protected $indexerRegistry;
+
+    /**
+     * @var \Magento\Eav\Model\Config
+     */
+    protected $eavConfig;
+
+    /**
+     * @param CustomerSetupFactory $customerSetupFactory
+     * @param IndexerRegistry $indexerRegistry
+     * @param \Magento\Eav\Model\Config $eavConfig
+     */
+    public function __construct(
+        CustomerSetupFactory $customerSetupFactory,
+        IndexerRegistry $indexerRegistry,
+        \Magento\Eav\Model\Config $eavConfig
+    ) {
+        $this->customerSetupFactory = $customerSetupFactory;
+        $this->indexerRegistry = $indexerRegistry;
+        $this->eavConfig = $eavConfig;
+    }
+
+    /**
+     * {@inheritdoc}
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
+    {
+        $setup->startSetup();
+
+        if (version_compare($context->getVersion(), '2.0.1', '<')) {
+            /** @var CustomerSetup $customerSetup */
+            $customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
+
+            $entityAttributes = [
+                'customer' => [
+                    'website_id' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => true,
+                        'is_filterable_in_grid' => true,
+                        'is_searchable_in_grid' => false,
+                    ],
+                    'created_in' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => true,
+                        'is_filterable_in_grid' => false,
+                        'is_searchable_in_grid' => true,
+                    ],
+                    'email' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => true,
+                        'is_filterable_in_grid' => true,
+                        'is_searchable_in_grid' => true,
+                    ],
+                    'group_id' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => true,
+                        'is_filterable_in_grid' => true,
+                        'is_searchable_in_grid' => false,
+                    ],
+                    'dob' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => true,
+                        'is_filterable_in_grid' => true,
+                        'is_searchable_in_grid' => false,
+                    ],
+                    'taxvat' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => true,
+                        'is_filterable_in_grid' => false,
+                        'is_searchable_in_grid' => true,
+                    ],
+                    'confirmation' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => true,
+                        'is_filterable_in_grid' => true,
+                        'is_searchable_in_grid' => false,
+                    ],
+                    'created_at' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => true,
+                        'is_filterable_in_grid' => true,
+                        'is_searchable_in_grid' => false,
+                    ],
+                    'gender' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => true,
+                        'is_filterable_in_grid' => true,
+                        'is_searchable_in_grid' => false,
+                    ],
+                ],
+                'customer_address' => [
+                    'company' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => false,
+                        'is_filterable_in_grid' => false,
+                        'is_searchable_in_grid' => true,
+                    ],
+                    'street' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => false,
+                        'is_filterable_in_grid' => false,
+                        'is_searchable_in_grid' => true,
+                    ],
+                    'city' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => false,
+                        'is_filterable_in_grid' => false,
+                        'is_searchable_in_grid' => true,
+                    ],
+                    'country_id' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => true,
+                        'is_filterable_in_grid' => true,
+                        'is_searchable_in_grid' => false,
+                    ],
+                    'region' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => true,
+                        'is_filterable_in_grid' => false,
+                        'is_searchable_in_grid' => true,
+                    ],
+                    'region_id' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => false,
+                        'is_filterable_in_grid' => true,
+                        'is_searchable_in_grid' => false,
+                    ],
+                    'postcode' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => true,
+                        'is_filterable_in_grid' => true,
+                        'is_searchable_in_grid' => true,
+                    ],
+                    'telephone' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => true,
+                        'is_filterable_in_grid' => true,
+                        'is_searchable_in_grid' => true,
+                    ],
+                    'fax' => [
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => false,
+                        'is_filterable_in_grid' => false,
+                        'is_searchable_in_grid' => true,
+                    ],
+                ],
+            ];
+
+            foreach ($entityAttributes as $entityType => $attributes) {
+                foreach ($attributes as $attributeCode => $attributeData) {
+                    $attribute = $customerSetup->getEavConfig()->getAttribute($entityType, $attributeCode);
+                    foreach ($attributeData as $key => $value) {
+                        $attribute->setData($key, $value);
+                    }
+                    $attribute->save();
+                }
+            }
+        }
+
+        $indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID);
+        $indexer->reindexAll();
+        $this->eavConfig->clear();
+
+        $setup->endSetup();
+    }
+}
diff --git a/app/code/Magento/Customer/Setup/UpgradeSchema.php b/app/code/Magento/Customer/Setup/UpgradeSchema.php
index 296fd06a36a60ad59e2feea931a21169f2ff434d..933556fec7dc3273c1f692536e4e8834ee0a6de0 100644
--- a/app/code/Magento/Customer/Setup/UpgradeSchema.php
+++ b/app/code/Magento/Customer/Setup/UpgradeSchema.php
@@ -32,6 +32,53 @@ class UpgradeSchema implements UpgradeSchemaInterface
             );
         }
 
+        if (version_compare($context->getVersion(), '2.0.1', '<')) {
+            $setup->getConnection()->addColumn(
+                $setup->getTable('customer_eav_attribute'),
+                'is_used_in_grid',
+                [
+                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
+                    'unsigned' => true,
+                    'nullable' => false,
+                    'default' => '0',
+                    'comment' => 'Is Used in Grid'
+                ]
+            );
+            $setup->getConnection()->addColumn(
+                $setup->getTable('customer_eav_attribute'),
+                'is_visible_in_grid',
+                [
+                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
+                    'unsigned' => true,
+                    'nullable' => false,
+                    'default' => '0',
+                    'comment' => 'Is Visible in Grid'
+                ]
+            );
+            $setup->getConnection()->addColumn(
+                $setup->getTable('customer_eav_attribute'),
+                'is_filterable_in_grid',
+                [
+                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
+                    'unsigned' => true,
+                    'nullable' => false,
+                    'default' => '0',
+                    'comment' => 'Is Filterable in Grid'
+                ]
+            );
+            $setup->getConnection()->addColumn(
+                $setup->getTable('customer_eav_attribute'),
+                'is_searchable_in_grid',
+                [
+                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
+                    'unsigned' => true,
+                    'nullable' => false,
+                    'default' => '0',
+                    'comment' => 'Is Searchable in Grid'
+                ]
+            );
+        }
+
         $setup->endSetup();
     }
 }
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassDeleteTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassDeleteTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b59404ba8bb482e721f881ed46fbfe7a1dd1ac67
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassDeleteTest.php
@@ -0,0 +1,195 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Customer\Test\Unit\Controller\Adminhtml\Index;
+
+use Magento\Framework\App\Action\Context;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+
+/**
+ * Class MassDeleteTest
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class MassDeleteTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Customer\Controller\Adminhtml\Index\MassDelete
+     */
+    protected $massAction;
+
+    /**
+     * @var Context|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $contextMock;
+
+    /**
+     * @var \Magento\Backend\Model\View\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $resultRedirectMock;
+
+    /**
+     * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $requestMock;
+
+    /**
+     * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $responseMock;
+
+    /**
+     * @var \Magento\Framework\Message\Manager|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $messageManagerMock;
+
+    /**
+     * @var \Magento\Framework\ObjectManager\ObjectManager|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $objectManagerMock;
+
+    /**
+     * @var \Magento\Customer\Model\Resource\Customer\Collection|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerCollectionMock;
+
+    /**
+     * @var \Magento\Customer\Model\Resource\Customer\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerCollectionFactoryMock;
+
+    /**
+     * @var \Magento\Ui\Component\MassAction\Filter|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $filterMock;
+
+    /**
+     * @var \Magento\Customer\Api\CustomerRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerRepositoryMock;
+
+    public function setUp()
+    {
+        $objectManagerHelper = new ObjectManagerHelper($this);
+
+        $this->contextMock = $this->getMock('Magento\Backend\App\Action\Context', [], [], '', false);
+        $resultRedirectFactory = $this->getMock(
+            'Magento\Backend\Model\View\Result\RedirectFactory',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->responseMock = $this->getMock('Magento\Framework\App\ResponseInterface', [], [], '', false);
+        $this->requestMock = $this->getMockBuilder('Magento\Framework\App\Request\Http')
+            ->disableOriginalConstructor()->getMock();
+        $this->objectManagerMock = $this->getMock(
+            'Magento\Framework\ObjectManager\ObjectManager',
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->messageManagerMock = $this->getMock('Magento\Framework\Message\Manager', [], [], '', false);
+        $this->customerCollectionMock = $this->getMockBuilder('Magento\Customer\Model\Resource\Customer\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->customerCollectionFactoryMock =
+            $this->getMockBuilder('Magento\Customer\Model\Resource\Customer\CollectionFactory')
+                ->disableOriginalConstructor()
+                ->setMethods(['create'])
+                ->getMock();
+        $redirectMock = $this->getMockBuilder('Magento\Backend\Model\View\Result\Redirect')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $resultFactoryMock = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $resultFactoryMock->expects($this->any())
+            ->method('create')
+            ->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT)
+            ->willReturn($redirectMock);
+
+        $this->resultRedirectMock = $this->getMockBuilder('Magento\Backend\Model\View\Result\Redirect')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $resultRedirectFactory->expects($this->any())->method('create')->willReturn($this->resultRedirectMock);
+
+        $this->contextMock->expects($this->once())->method('getMessageManager')->willReturn($this->messageManagerMock);
+        $this->contextMock->expects($this->once())->method('getRequest')->willReturn($this->requestMock);
+        $this->contextMock->expects($this->once())->method('getResponse')->willReturn($this->responseMock);
+        $this->contextMock->expects($this->once())->method('getObjectManager')->willReturn($this->objectManagerMock);
+        $this->contextMock->expects($this->any())
+            ->method('getResultRedirectFactory')
+            ->willReturn($resultRedirectFactory);
+        $this->contextMock->expects($this->any())
+            ->method('getResultFactory')
+            ->willReturn($resultFactoryMock);
+
+        $this->filterMock = $this->getMock('Magento\Ui\Component\MassAction\Filter', [], [], '', false);
+        $this->filterMock->expects($this->once())
+            ->method('getCollection')
+            ->with($this->customerCollectionMock)
+            ->willReturnArgument(0);
+        $this->customerCollectionFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($this->customerCollectionMock);
+        $this->customerRepositoryMock = $this->getMockBuilder('Magento\Customer\Api\CustomerRepositoryInterface')
+            ->getMockForAbstractClass();
+        $this->massAction = $objectManagerHelper->getObject(
+            'Magento\Customer\Controller\Adminhtml\Index\MassDelete',
+            [
+                'context' => $this->contextMock,
+                'filter' => $this->filterMock,
+                'collectionFactory' => $this->customerCollectionFactoryMock,
+                'customerRepository' => $this->customerRepositoryMock,
+            ]
+        );
+    }
+
+    public function testExecute()
+    {
+        $customersIds = [10, 11, 12];
+
+        $this->customerCollectionMock->expects($this->any())
+            ->method('getAllIds')
+            ->willReturn($customersIds);
+
+        $this->customerRepositoryMock->expects($this->any())
+            ->method('deleteById')
+            ->willReturnMap([[10, true], [11, true], [12, true]]);
+
+        $this->messageManagerMock->expects($this->once())
+            ->method('addSuccess')
+            ->with(__('A total of %1 record(s) were deleted.', count($customersIds)));
+
+        $this->resultRedirectMock->expects($this->any())
+            ->method('setPath')
+            ->with('customer/*/index')
+            ->willReturnSelf();
+
+        $this->massAction->execute();
+    }
+
+    public function testExecuteWithException()
+    {
+        $customersIds = [10, 11, 12];
+
+        $this->customerCollectionMock->expects($this->any())
+            ->method('getAllIds')
+            ->willReturn($customersIds);
+
+        $this->customerRepositoryMock->expects($this->any())
+            ->method('deleteById')
+            ->willThrowException(new \Exception('Some message.'));
+
+        $this->messageManagerMock->expects($this->once())
+            ->method('addError')
+            ->with('Some message.');
+
+        $this->massAction->execute();
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassSubscribeTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassSubscribeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..eab3d880dbf9379b5697eeaf27bb51a7cfff7122
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassSubscribeTest.php
@@ -0,0 +1,211 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Customer\Test\Unit\Controller\Adminhtml\Index;
+
+use Magento\Framework\App\Action\Context;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+
+/**
+ * Class MassSubscribeTest
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class MassSubscribeTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Customer\Controller\Adminhtml\Index\MassSubscribe
+     */
+    protected $massAction;
+
+    /**
+     * @var Context|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $contextMock;
+
+    /**
+     * @var \Magento\Backend\Model\View\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $resultRedirectMock;
+
+    /**
+     * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $requestMock;
+
+    /**
+     * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $responseMock;
+
+    /**
+     * @var \Magento\Framework\Message\Manager|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $messageManagerMock;
+
+    /**
+     * @var \Magento\Framework\ObjectManager\ObjectManager|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $objectManagerMock;
+
+    /**
+     * @var \Magento\Customer\Model\Resource\Customer\Collection|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerCollectionMock;
+
+    /**
+     * @var \Magento\Customer\Model\Resource\Customer\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerCollectionFactoryMock;
+
+    /**
+     * @var \Magento\Ui\Component\MassAction\Filter|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $filterMock;
+
+    /**
+     * @var \Magento\Customer\Api\CustomerRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerRepositoryMock;
+
+    /**
+     * @var \Magento\Newsletter\Model\Subscriber|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $subscriberMock;
+
+    public function setUp()
+    {
+        $objectManagerHelper = new ObjectManagerHelper($this);
+
+        $this->contextMock = $this->getMock('Magento\Backend\App\Action\Context', [], [], '', false);
+        $resultRedirectFactory = $this->getMock(
+            'Magento\Backend\Model\View\Result\RedirectFactory',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->responseMock = $this->getMock('Magento\Framework\App\ResponseInterface', [], [], '', false);
+        $this->requestMock = $this->getMockBuilder('Magento\Framework\App\Request\Http')
+            ->disableOriginalConstructor()->getMock();
+        $this->objectManagerMock = $this->getMock(
+            'Magento\Framework\ObjectManager\ObjectManager',
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->messageManagerMock = $this->getMock('Magento\Framework\Message\Manager', [], [], '', false);
+        $this->customerCollectionMock = $this->getMockBuilder('Magento\Customer\Model\Resource\Customer\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->customerCollectionFactoryMock =
+            $this->getMockBuilder('Magento\Customer\Model\Resource\Customer\CollectionFactory')
+                ->disableOriginalConstructor()
+                ->setMethods(['create'])
+                ->getMock();
+        $redirectMock = $this->getMockBuilder('Magento\Backend\Model\View\Result\Redirect')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $resultFactoryMock = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $resultFactoryMock->expects($this->any())
+            ->method('create')
+            ->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT)
+            ->willReturn($redirectMock);
+        $this->subscriberMock = $this->getMock('Magento\Newsletter\Model\Subscriber', [], [], '', false);
+        $subscriberFactoryMock = $this->getMockBuilder('Magento\Newsletter\Model\SubscriberFactory')
+            ->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $subscriberFactoryMock->expects($this->any())
+            ->method('create')
+            ->willReturn($this->subscriberMock);
+
+        $this->resultRedirectMock = $this->getMock('Magento\Backend\Model\View\Result\Redirect', [], [], '', false);
+        $resultRedirectFactory->expects($this->any())->method('create')->willReturn($this->resultRedirectMock);
+
+        $this->contextMock->expects($this->once())->method('getMessageManager')->willReturn($this->messageManagerMock);
+        $this->contextMock->expects($this->once())->method('getRequest')->willReturn($this->requestMock);
+        $this->contextMock->expects($this->once())->method('getResponse')->willReturn($this->responseMock);
+        $this->contextMock->expects($this->once())->method('getObjectManager')->willReturn($this->objectManagerMock);
+        $this->contextMock->expects($this->any())
+            ->method('getResultRedirectFactory')
+            ->willReturn($resultRedirectFactory);
+        $this->contextMock->expects($this->any())
+            ->method('getResultFactory')
+            ->willReturn($resultFactoryMock);
+
+        $this->filterMock = $this->getMock('Magento\Ui\Component\MassAction\Filter', [], [], '', false);
+        $this->filterMock->expects($this->once())
+            ->method('getCollection')
+            ->with($this->customerCollectionMock)
+            ->willReturnArgument(0);
+        $this->customerCollectionFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($this->customerCollectionMock);
+        $this->customerRepositoryMock = $this->getMockBuilder('Magento\Customer\Api\CustomerRepositoryInterface')
+            ->getMockForAbstractClass();
+        $this->massAction = $objectManagerHelper->getObject(
+            'Magento\Customer\Controller\Adminhtml\Index\MassSubscribe',
+            [
+                'context' => $this->contextMock,
+                'filter' => $this->filterMock,
+                'collectionFactory' => $this->customerCollectionFactoryMock,
+                'customerRepository' => $this->customerRepositoryMock,
+                'subscriberFactory' => $subscriberFactoryMock,
+            ]
+        );
+    }
+
+    public function testExecute()
+    {
+        $customersIds = [10, 11, 12];
+
+        $this->customerCollectionMock->expects($this->any())
+            ->method('getAllIds')
+            ->willReturn($customersIds);
+
+        $this->customerRepositoryMock->expects($this->any())
+            ->method('getById')
+            ->willReturnMap([[10, true], [11, true], [12, true]]);
+
+        $this->subscriberMock->expects($this->any())
+            ->method('subscribeCustomerById')
+            ->willReturnMap([[10, true], [11, true], [12, true]]);
+
+        $this->messageManagerMock->expects($this->once())
+            ->method('addSuccess')
+            ->with(__('A total of %1 record(s) were updated.', count($customersIds)));
+
+        $this->resultRedirectMock->expects($this->any())
+            ->method('setPath')
+            ->with('customer/*/index')
+            ->willReturnSelf();
+
+        $this->massAction->execute();
+    }
+
+    public function testExecuteWithException()
+    {
+        $customersIds = [10, 11, 12];
+
+        $this->customerCollectionMock->expects($this->any())
+            ->method('getAllIds')
+            ->willReturn($customersIds);
+
+        $this->customerRepositoryMock->expects($this->any())
+            ->method('getById')
+            ->willThrowException(new \Exception('Some message.'));
+
+        $this->messageManagerMock->expects($this->once())
+            ->method('addError')
+            ->with('Some message.');
+
+        $this->massAction->execute();
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassUnsubscribeTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassUnsubscribeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4e167af550fbe39218095e86e56212ec3c476b30
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassUnsubscribeTest.php
@@ -0,0 +1,211 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Customer\Test\Unit\Controller\Adminhtml\Index;
+
+use Magento\Framework\App\Action\Context;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+
+/**
+ * Class MassUnsubscribeTest
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class MassUnsubscribeTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Customer\Controller\Adminhtml\Index\MassUnsubscribe
+     */
+    protected $massAction;
+
+    /**
+     * @var Context|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $contextMock;
+
+    /**
+     * @var \Magento\Backend\Model\View\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $resultRedirectMock;
+
+    /**
+     * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $requestMock;
+
+    /**
+     * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $responseMock;
+
+    /**
+     * @var \Magento\Framework\Message\Manager|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $messageManagerMock;
+
+    /**
+     * @var \Magento\Framework\ObjectManager\ObjectManager|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $objectManagerMock;
+
+    /**
+     * @var \Magento\Customer\Model\Resource\Customer\Collection|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerCollectionMock;
+
+    /**
+     * @var \Magento\Customer\Model\Resource\Customer\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerCollectionFactoryMock;
+
+    /**
+     * @var \Magento\Ui\Component\MassAction\Filter|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $filterMock;
+
+    /**
+     * @var \Magento\Customer\Api\CustomerRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerRepositoryMock;
+
+    /**
+     * @var \Magento\Newsletter\Model\Subscriber|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $subscriberMock;
+
+    public function setUp()
+    {
+        $objectManagerHelper = new ObjectManagerHelper($this);
+
+        $this->contextMock = $this->getMock('Magento\Backend\App\Action\Context', [], [], '', false);
+        $resultRedirectFactory = $this->getMock(
+            'Magento\Backend\Model\View\Result\RedirectFactory',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->responseMock = $this->getMock('Magento\Framework\App\ResponseInterface', [], [], '', false);
+        $this->requestMock = $this->getMockBuilder('Magento\Framework\App\Request\Http')
+            ->disableOriginalConstructor()->getMock();
+        $this->objectManagerMock = $this->getMock(
+            'Magento\Framework\ObjectManager\ObjectManager',
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->messageManagerMock = $this->getMock('Magento\Framework\Message\Manager', [], [], '', false);
+        $this->customerCollectionMock = $this->getMockBuilder('Magento\Customer\Model\Resource\Customer\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->customerCollectionFactoryMock =
+            $this->getMockBuilder('Magento\Customer\Model\Resource\Customer\CollectionFactory')
+                ->disableOriginalConstructor()
+                ->setMethods(['create'])
+                ->getMock();
+        $redirectMock = $this->getMockBuilder('Magento\Backend\Model\View\Result\Redirect')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $resultFactoryMock = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $resultFactoryMock->expects($this->any())
+            ->method('create')
+            ->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT)
+            ->willReturn($redirectMock);
+        $this->subscriberMock = $this->getMock('Magento\Newsletter\Model\Subscriber', [], [], '', false);
+        $subscriberFactoryMock = $this->getMockBuilder('Magento\Newsletter\Model\SubscriberFactory')
+            ->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $subscriberFactoryMock->expects($this->any())
+            ->method('create')
+            ->willReturn($this->subscriberMock);
+
+        $this->resultRedirectMock = $this->getMock('Magento\Backend\Model\View\Result\Redirect', [], [], '', false);
+        $resultRedirectFactory->expects($this->any())->method('create')->willReturn($this->resultRedirectMock);
+
+        $this->contextMock->expects($this->once())->method('getMessageManager')->willReturn($this->messageManagerMock);
+        $this->contextMock->expects($this->once())->method('getRequest')->willReturn($this->requestMock);
+        $this->contextMock->expects($this->once())->method('getResponse')->willReturn($this->responseMock);
+        $this->contextMock->expects($this->once())->method('getObjectManager')->willReturn($this->objectManagerMock);
+        $this->contextMock->expects($this->any())
+            ->method('getResultRedirectFactory')
+            ->willReturn($resultRedirectFactory);
+        $this->contextMock->expects($this->any())
+            ->method('getResultFactory')
+            ->willReturn($resultFactoryMock);
+
+        $this->filterMock = $this->getMock('Magento\Ui\Component\MassAction\Filter', [], [], '', false);
+        $this->filterMock->expects($this->once())
+            ->method('getCollection')
+            ->with($this->customerCollectionMock)
+            ->willReturnArgument(0);
+        $this->customerCollectionFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($this->customerCollectionMock);
+        $this->customerRepositoryMock = $this->getMockBuilder('Magento\Customer\Api\CustomerRepositoryInterface')
+            ->getMockForAbstractClass();
+        $this->massAction = $objectManagerHelper->getObject(
+            'Magento\Customer\Controller\Adminhtml\Index\MassUnsubscribe',
+            [
+                'context' => $this->contextMock,
+                'filter' => $this->filterMock,
+                'collectionFactory' => $this->customerCollectionFactoryMock,
+                'customerRepository' => $this->customerRepositoryMock,
+                'subscriberFactory' => $subscriberFactoryMock,
+            ]
+        );
+    }
+
+    public function testExecute()
+    {
+        $customersIds = [10, 11, 12];
+
+        $this->customerCollectionMock->expects($this->any())
+            ->method('getAllIds')
+            ->willReturn($customersIds);
+
+        $this->customerRepositoryMock->expects($this->any())
+            ->method('getById')
+            ->willReturnMap([[10, true], [11, true], [12, true]]);
+
+        $this->subscriberMock->expects($this->any())
+            ->method('unsubscribeCustomerById')
+            ->willReturnMap([[10, true], [11, true], [12, true]]);
+
+        $this->messageManagerMock->expects($this->once())
+            ->method('addSuccess')
+            ->with(__('A total of %1 record(s) were updated.', count($customersIds)));
+
+        $this->resultRedirectMock->expects($this->any())
+            ->method('setPath')
+            ->with('customer/*/index')
+            ->willReturnSelf();
+
+        $this->massAction->execute();
+    }
+
+    public function testExecuteWithException()
+    {
+        $customersIds = [10, 11, 12];
+
+        $this->customerCollectionMock->expects($this->any())
+            ->method('getAllIds')
+            ->willReturn($customersIds);
+
+        $this->customerRepositoryMock->expects($this->any())
+            ->method('getById')
+            ->willThrowException(new \Exception('Some message.'));
+
+        $this->messageManagerMock->expects($this->once())
+            ->method('addError')
+            ->with('Some message.');
+
+        $this->massAction->execute();
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Model/AttributeTest.php b/app/code/Magento/Customer/Test/Unit/Model/AttributeTest.php
index 3a73c5ece810b01fb0c36e58e6e2b2fc0f726c6e..06c6c2a3ecb2f111606d611314dbf2cbfbb304e6 100644
--- a/app/code/Magento/Customer/Test/Unit/Model/AttributeTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Model/AttributeTest.php
@@ -9,6 +9,9 @@
 namespace Magento\Customer\Test\Unit\Model;
 
 use Magento\Customer\Model\Attribute;
+use Magento\Customer\Model\Customer;
+use Magento\Eav\Api\Data\AttributeInterface;
+use Magento\Framework\Indexer\IndexerInterface;
 
 /**
  * @SuppressWarnings(PHPMD.TooManyFields)
@@ -106,6 +109,11 @@ class AttributeTest extends \PHPUnit_Framework_TestCase
      */
     private $dataObjectHelperMock;
 
+    /**
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $indexerRegistryMock;
+
     /**
      * @var \Magento\Framework\Api\ExtensionAttributesFactory|\PHPUnit_Framework_MockObject_MockObject
      */
@@ -182,6 +190,10 @@ class AttributeTest extends \PHPUnit_Framework_TestCase
             ->method('getEventDispatcher')
             ->willReturn($this->eventDispatcher);
 
+        $this->indexerRegistryMock = $this->getMockBuilder('Magento\Framework\Indexer\IndexerRegistry')
+            ->disableOriginalConstructor()
+            ->getMock();
+
         $this->attribute = new Attribute(
             $this->contextMock,
             $this->registryMock,
@@ -199,6 +211,7 @@ class AttributeTest extends \PHPUnit_Framework_TestCase
             $this->reservedAttributeListMock,
             $this->resolverMock,
             $this->dateTimeFormatter,
+            $this->indexerRegistryMock,
             $this->resourceMock
         );
     }
@@ -226,4 +239,95 @@ class AttributeTest extends \PHPUnit_Framework_TestCase
 
         $this->attribute->afterDelete();
     }
+
+    public function testInvalidate()
+    {
+        /** @var IndexerInterface|\PHPUnit_Framework_MockObject_MockObject $indexerMock */
+        $indexerMock = $this->getMockBuilder('Magento\Framework\Indexer\IndexerInterface')
+            ->getMockForAbstractClass();
+
+        $this->indexerRegistryMock->expects($this->once())
+            ->method('get')
+            ->with(Customer::CUSTOMER_GRID_INDEXER_ID)
+            ->willReturn($indexerMock);
+
+        $indexerMock->expects($this->once())
+            ->method('invalidate');
+
+        $this->attribute->invalidate();
+    }
+
+    /**
+     * @param int $isSearchableInGrid
+     * @param string $frontendInput
+     * @param bool $result
+     * @dataProvider dataProviderCanBeSearchableInGrid
+     */
+    public function testCanBeSearchableInGrid($isSearchableInGrid, $frontendInput, $result)
+    {
+        $this->attribute->setData('is_searchable_in_grid', $isSearchableInGrid);
+        $this->attribute->setData(AttributeInterface::FRONTEND_INPUT, $frontendInput);
+
+        $this->assertEquals($result, $this->attribute->canBeSearchableInGrid());
+    }
+
+    /**
+     * @return array
+     */
+    public function dataProviderCanBeSearchableInGrid()
+    {
+        return [
+            [0, 'text', false],
+            [0, 'textarea', false],
+            [1, 'text', true],
+            [1, 'textarea', true],
+            [1, 'date', false],
+            [1, 'boolean', false],
+            [1, 'select', false],
+            [1, 'media_image', false],
+            [1, 'gallery', false],
+            [1, 'multiselect', false],
+            [1, 'image', false],
+            [1, 'price', false],
+            [1, 'weight', false],
+        ];
+    }
+
+    /**
+     * @param int $isFilterableInGrid
+     * @param string $frontendInput
+     * @param bool $result
+     * @dataProvider dataProviderCanBeFilterableInGrid
+     */
+    public function testCanBeFilterableInGrid($isFilterableInGrid, $frontendInput, $result)
+    {
+        $this->attribute->setData('is_filterable_in_grid', $isFilterableInGrid);
+        $this->attribute->setData(AttributeInterface::FRONTEND_INPUT, $frontendInput);
+
+        $this->assertEquals($result, $this->attribute->canBeFilterableInGrid());
+    }
+
+    /**
+     * @return array
+     */
+    public function dataProviderCanBeFilterableInGrid()
+    {
+        return [
+            [0, 'text', false],
+            [0, 'date', false],
+            [0, 'select', false],
+            [0, 'boolean', false],
+            [1, 'text', true],
+            [1, 'date', true],
+            [1, 'select', true],
+            [1, 'boolean', true],
+            [1, 'textarea', false],
+            [1, 'media_image', false],
+            [1, 'gallery', false],
+            [1, 'multiselect', false],
+            [1, 'image', false],
+            [1, 'price', false],
+            [1, 'weight', false],
+        ];
+    }
 }
diff --git a/app/code/Magento/Customer/Test/Unit/Model/Indexer/Attribute/FilterTest.php b/app/code/Magento/Customer/Test/Unit/Model/Indexer/Attribute/FilterTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..33f3701d9a002ce2f6c929e9fc7d8a8a1723ffe0
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Model/Indexer/Attribute/FilterTest.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Model\Indexer\Attribute;
+
+use Magento\Customer\Model\Indexer\Attribute\Filter;
+use Magento\Customer\Api\Data\AttributeMetadataInterface;
+
+class FilterTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Framework\App\Resource|\PHPUnit_Framework_MockObject_MockObject */
+    protected $resource;
+
+    /** @var \Magento\Framework\DB\Adapter\AdapterInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $connection;
+
+    /** @var \Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver|\PHPUnit_Framework_MockObject_MockObject */
+    protected $flatScopeResolver;
+
+    /** @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject */
+    protected $indexerRegistry;
+
+    /** @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $indexer;
+
+    /** @var \Magento\Framework\Indexer\StateInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $indexerState;
+
+    /** @var Filter */
+    protected $model;
+
+    public function setUp()
+    {
+        $this->resource = $this->getMock('Magento\Framework\App\Resource', [], [], '', false);
+        $this->connection = $this->getMockForAbstractClass(
+            'Magento\Framework\DB\Adapter\AdapterInterface',
+            [],
+            '',
+            false
+        );
+        $this->flatScopeResolver = $this->getMock(
+            'Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->indexerRegistry = $this->getMock('Magento\Framework\Indexer\IndexerRegistry', [], [], '', false);
+        $this->indexer = $this->getMockForAbstractClass('Magento\Framework\Indexer\IndexerInterface', [], '', false);
+        $this->indexerState = $this->getMockForAbstractClass('Magento\Framework\Indexer\StateInterface', [], '', false);
+
+        $this->model = new Filter(
+            $this->resource,
+            $this->flatScopeResolver,
+            $this->indexerRegistry
+        );
+    }
+
+    public function testFilter()
+    {
+        $attributeCode = 'attribute-code';
+        $attributeCodeTwo = 'attribute-code2';
+        $tableName = 'customer_grid_flat';
+
+        $attributes = [
+            $attributeCode => [
+                AttributeMetadataInterface::ATTRIBUTE_CODE => $attributeCode,
+                AttributeMetadataInterface::FRONTEND_INPUT => 'input',
+                AttributeMetadataInterface::FRONTEND_LABEL => 'Frontend label',
+                AttributeMetadataInterface::BACKEND_TYPE => 'static',
+                AttributeMetadataInterface::OPTIONS => [],
+                AttributeMetadataInterface::IS_USED_IN_GRID => true,
+                AttributeMetadataInterface::IS_VISIBLE_IN_GRID => true,
+                AttributeMetadataInterface::IS_FILTERABLE_IN_GRID => true,
+                AttributeMetadataInterface::IS_SEARCHABLE_IN_GRID => true,
+            ],
+            $attributeCodeTwo => [
+                AttributeMetadataInterface::ATTRIBUTE_CODE => $attributeCodeTwo,
+                AttributeMetadataInterface::FRONTEND_INPUT => 'input',
+                AttributeMetadataInterface::FRONTEND_LABEL => 'Frontend label two',
+                AttributeMetadataInterface::BACKEND_TYPE => 'static',
+                AttributeMetadataInterface::OPTIONS => [],
+                AttributeMetadataInterface::IS_USED_IN_GRID => false,
+                AttributeMetadataInterface::IS_VISIBLE_IN_GRID => false,
+                AttributeMetadataInterface::IS_FILTERABLE_IN_GRID => false,
+                AttributeMetadataInterface::IS_SEARCHABLE_IN_GRID => false,
+            ]
+        ];
+
+        $this->indexerRegistry->expects($this->once())
+            ->method('get')
+            ->with(\Magento\Customer\Model\Customer::CUSTOMER_GRID_INDEXER_ID)
+            ->willReturn($this->indexer);
+        $this->indexer->expects($this->once())
+            ->method('getState')
+            ->willReturn($this->indexerState);
+        $this->indexerState->expects($this->once())
+            ->method('getStatus')
+            ->willReturn(\Magento\Framework\Indexer\StateInterface::STATUS_INVALID);
+        $this->flatScopeResolver->expects($this->once())
+            ->method('resolve')
+            ->with(\Magento\Customer\Model\Customer::CUSTOMER_GRID_INDEXER_ID, [])
+            ->willReturn($tableName);
+        $this->resource->expects($this->once())
+            ->method('getConnection')
+            ->willReturn($this->connection);
+        $this->connection->expects($this->once())
+            ->method('describeTable')
+            ->with($tableName)
+            ->willReturn([
+                'attribute-code' => ['Attribute data']
+            ]);
+
+        $this->assertArrayNotHasKey($attributeCodeTwo, $this->model->filter($attributes));
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Model/Indexer/AttributeProviderTest.php b/app/code/Magento/Customer/Test/Unit/Model/Indexer/AttributeProviderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..908a74a3b78b19686e0604dc4c21eab9b89364eb
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Model/Indexer/AttributeProviderTest.php
@@ -0,0 +1,345 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Model\Indexer;
+
+use Magento\Customer\Model\Customer;
+use Magento\Customer\Model\Indexer\AttributeProvider;
+use Magento\Eav\Model\Resource\Entity\Attribute\Collection;
+
+class AttributeProviderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Eav\Model\Config|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $eavConfig;
+
+    /**
+     * @var AttributeProvider
+     */
+    protected $object;
+
+    public function setUp()
+    {
+        $this->eavConfig = $this->getMockBuilder('Magento\Eav\Model\Config')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->object = new AttributeProvider(
+            $this->eavConfig
+        );
+    }
+
+    /**
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function testAddDynamicData()
+    {
+        $existentName = 'field';
+        $existentField = [
+            'name' => $existentName,
+            'handler' => 'handler',
+            'origin' => $existentName,
+            'type' => 'type',
+            'filters' => ['filter'],
+            'dataType' => 'data_type',
+        ];
+        $data = ['fields' => [$existentName => $existentField]];
+        $attrName = 'attrName';
+        $attrBackendType = 'b_type';
+        $attrFrontendInput = 'int';
+
+        /** @var \Magento\Eav\Model\Entity\Type|\PHPUnit_Framework_MockObject_MockObject $collectionMock $entityType */
+        $entityType = $this->getMockBuilder('Magento\Eav\Model\Entity\Type')
+            ->disableOriginalConstructor()
+            ->getMock();
+        /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */
+        $collectionMock = $this->getMockBuilder('Magento\Eav\Model\Resource\Entity\Attribute\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+        /** @var \Magento\Customer\Model\Resource\Customer|\PHPUnit_Framework_MockObject_MockObject $entity */
+        $entity = $this->getMockBuilder('Magento\Customer\Model\Resource\Customer')
+            ->disableOriginalConstructor()
+            ->getMock();
+        /** @var \Magento\Customer\Model\Attribute|\PHPUnit_Framework_MockObject_MockObject $attribute */
+        $attribute = $this->getMockBuilder('Magento\Customer\Model\Attribute')
+            ->disableOriginalConstructor()
+            ->setMethods(
+                [
+                    'setEntity',
+                    'getName',
+                    'getFrontendInput',
+                    'getBackendType',
+                    'canBeSearchableInGrid',
+                    'canBeFilterableInGrid',
+                    'getData',
+                ]
+            )
+            ->getMock();
+        $this->eavConfig->expects($this->once())
+            ->method('getEntityType')
+            ->with(Customer::ENTITY)
+            ->willReturn($entityType);
+        $entityType->expects($this->once())
+            ->method('getEntity')
+            ->willReturn($entity);
+        $entityType->expects($this->once())
+            ->method('getAttributeCollection')
+            ->willReturn($collectionMock);
+        $collectionMock->expects($this->once())
+            ->method('getItems')
+            ->willReturn([$attribute]);
+        $attribute->expects($this->once())
+            ->method('setEntity')
+            ->with($entity)
+            ->willReturnSelf();
+        $attribute->expects($this->exactly(3))
+            ->method('getName')
+            ->willReturn($attrName);
+        $attribute->expects($this->any())
+            ->method('getBackendType')
+            ->willReturn($attrBackendType);
+        $attribute->expects($this->any())
+            ->method('getFrontendInput')
+            ->willReturn($attrFrontendInput);
+        $attribute->expects($this->any())
+            ->method('canBeSearchableInGrid')
+            ->willReturn(false);
+        $attribute->expects($this->any())
+            ->method('canBeFilterableInGrid')
+            ->willReturn(false);
+        $attribute->expects($this->any())
+            ->method('getData')
+            ->willReturnMap(
+                [
+                    ['is_used_in_grid', null, true],
+                ]
+            );
+
+        $this->assertEquals(
+            ['fields' =>
+                [
+                    $existentName => $existentField,
+                    $attrName => [
+                        'name' => $attrName,
+                        'handler' => 'Magento\Framework\Indexer\Handler\AttributeHandler',
+                        'origin' => $attrName,
+                        'type' => 'virtual',
+                        'filters' => [],
+                        'dataType' => $attrBackendType,
+                        'entity' => Customer::ENTITY,
+                        'bind' => null,
+                    ],
+                ],
+            ],
+            $this->object->addDynamicData($data)
+        );
+    }
+
+    public function testAddDynamicDataWithStaticAndSearchable()
+    {
+        $existentName = 'field';
+        $existentField = [
+            'name' => $existentName,
+            'handler' => 'handler',
+            'origin' => $existentName,
+            'type' => 'searchable',
+            'filters' => ['filter'],
+            'dataType' => 'data_type',
+        ];
+        $data = ['fields' => [$existentName => $existentField]];
+        $attrName = $existentName;
+        $attrBackendType = 'static';
+        $attrFrontendInput = 'text';
+
+        /** @var \Magento\Eav\Model\Entity\Type|\PHPUnit_Framework_MockObject_MockObject $collectionMock $entityType */
+        $entityType = $this->getMockBuilder('Magento\Eav\Model\Entity\Type')
+            ->disableOriginalConstructor()
+            ->getMock();
+        /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */
+        $collectionMock = $this->getMockBuilder('Magento\Eav\Model\Resource\Entity\Attribute\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+        /** @var \Magento\Customer\Model\Resource\Customer|\PHPUnit_Framework_MockObject_MockObject $entity */
+        $entity = $this->getMockBuilder('Magento\Customer\Model\Resource\Customer')
+            ->disableOriginalConstructor()
+            ->getMock();
+        /** @var \Magento\Customer\Model\Attribute|\PHPUnit_Framework_MockObject_MockObject $attribute */
+        $attribute = $this->getMockBuilder('Magento\Customer\Model\Attribute')
+            ->disableOriginalConstructor()
+            ->setMethods(
+                [
+                    'setEntity',
+                    'getName',
+                    'getFrontendInput',
+                    'getBackendType',
+                    'canBeSearchableInGrid',
+                    'canBeFilterableInGrid',
+                    'getData',
+                ]
+            )
+            ->getMock();
+        $this->eavConfig->expects($this->once())
+            ->method('getEntityType')
+            ->with(Customer::ENTITY)
+            ->willReturn($entityType);
+        $entityType->expects($this->once())
+            ->method('getAttributeCollection')
+            ->willReturn($collectionMock);
+        $collectionMock->expects($this->once())
+            ->method('getItems')
+            ->willReturn([$attribute]);
+        $entityType->expects($this->once())
+            ->method('getEntity')
+            ->willReturn($entity);
+        $attribute->expects($this->once())
+            ->method('setEntity')
+            ->with($entity)
+            ->willReturnSelf();
+        $attribute->expects($this->any())
+            ->method('getFrontendInput')
+            ->willReturn($attrFrontendInput);
+        $attribute->expects($this->any())
+            ->method('getBackendType')
+            ->willReturn($attrBackendType);
+        $attribute->expects($this->any())
+            ->method('canBeSearchableInGrid')
+            ->willReturn(true);
+        $attribute->expects($this->never())
+            ->method('canBeFilterableInGrid');
+
+        $this->assertEquals(
+            ['fields' =>
+                [
+                    $attrName => [
+                        'name' => $attrName,
+                        'handler' => 'handler',
+                        'origin' => $attrName,
+                        'type' => 'searchable',
+                        'filters' => ['filter'],
+                        'dataType' => 'data_type',
+                    ],
+                ],
+            ],
+            $this->object->addDynamicData($data)
+        );
+    }
+
+    /**
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function testAddDynamicDataWithStaticAndFilterable()
+    {
+        $existentName = 'field';
+        $existentField = [
+            'name' => $existentName,
+            'handler' => 'handler',
+            'origin' => $existentName,
+            'type' => 'type',
+            'filters' => ['filter'],
+            'dataType' => 'data_type',
+        ];
+        $data = [
+            'fields' => [$existentName => $existentField],
+            'references' => [
+                'customer' => [
+                    'to' => 'to_field',
+                ],
+            ],
+        ];
+        $attrName = $existentName;
+        $attrBackendType = 'varchar';
+        $attrFrontendInput = 'text';
+
+        /** @var \Magento\Eav\Model\Entity\Type|\PHPUnit_Framework_MockObject_MockObject $collectionMock $entityType */
+        $entityType = $this->getMockBuilder('Magento\Eav\Model\Entity\Type')
+            ->disableOriginalConstructor()
+            ->getMock();
+        /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */
+        $collectionMock = $this->getMockBuilder('Magento\Eav\Model\Resource\Entity\Attribute\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+        /** @var \Magento\Customer\Model\Resource\Customer|\PHPUnit_Framework_MockObject_MockObject $entity */
+        $entity = $this->getMockBuilder('Magento\Customer\Model\Resource\Customer')
+            ->disableOriginalConstructor()
+            ->getMock();
+        /** @var \Magento\Customer\Model\Attribute|\PHPUnit_Framework_MockObject_MockObject $attribute */
+        $attribute = $this->getMockBuilder('Magento\Customer\Model\Attribute')
+            ->disableOriginalConstructor()
+            ->setMethods(
+                [
+                    'setEntity',
+                    'getName',
+                    'getFrontendInput',
+                    'getBackendType',
+                    'canBeSearchableInGrid',
+                    'canBeFilterableInGrid',
+                    'getData',
+                ]
+            )
+            ->getMock();
+        $this->eavConfig->expects($this->once())
+            ->method('getEntityType')
+            ->with(Customer::ENTITY)
+            ->willReturn($entityType);
+        $entityType->expects($this->once())
+            ->method('getAttributeCollection')
+            ->willReturn($collectionMock);
+        $collectionMock->expects($this->once())
+            ->method('getItems')
+            ->willReturn([$attribute]);
+        $entityType->expects($this->once())
+            ->method('getEntity')
+            ->willReturn($entity);
+        $attribute->expects($this->once())
+            ->method('setEntity')
+            ->with($entity)
+            ->willReturnSelf();
+        $attribute->expects($this->exactly(3))
+            ->method('getName')
+            ->willReturn($attrName);
+        $attribute->expects($this->any())
+            ->method('getFrontendInput')
+            ->willReturn($attrFrontendInput);
+        $attribute->expects($this->any())
+            ->method('getBackendType')
+            ->willReturn($attrBackendType);
+        $attribute->expects($this->any())
+            ->method('canBeSearchableInGrid')
+            ->willReturn(false);
+        $attribute->expects($this->any())
+            ->method('canBeFilterableInGrid')
+            ->willReturn(true);
+        $attribute->expects($this->any())
+            ->method('getData')
+            ->willReturnMap(
+                [
+                    ['is_used_in_grid', null, true],
+                ]
+            );
+
+        $this->assertEquals(
+            ['fields' =>
+                [
+                    $attrName => [
+                        'name' => $attrName,
+                        'handler' => 'Magento\Framework\Indexer\Handler\AttributeHandler',
+                        'origin' => $attrName,
+                        'type' => 'filterable',
+                        'filters' => [],
+                        'dataType' => 'varchar',
+                        'entity' => Customer::ENTITY,
+                        'bind' => 'to_field',
+                    ],
+                ],
+                'references' => [
+                    'customer' => [
+                        'to' => 'to_field',
+                    ],
+                ],
+            ],
+            $this->object->addDynamicData($data)
+        );
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Model/Metadata/AddressMetadataManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/Metadata/AddressMetadataManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..83429316dba992ebaf9db43d2b70e03a6bc79105
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Model/Metadata/AddressMetadataManagementTest.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Model\Metadata;
+
+use Magento\Customer\Api\AddressMetadataManagementInterface;
+use Magento\Customer\Model\Attribute;
+use Magento\Customer\Api\Data\AttributeMetadataInterface;
+use Magento\Customer\Model\Metadata\AddressMetadataManagement;
+
+class AddressMetadataManagementTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var AddressMetadataManagement */
+    protected $model;
+
+    /** @var \Magento\Customer\Model\Metadata\AttributeResolver|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeResolverMock;
+
+    protected function setUp()
+    {
+        $this->attributeResolverMock = $this->getMockBuilder('Magento\Customer\Model\Metadata\AttributeResolver')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->model = new AddressMetadataManagement(
+            $this->attributeResolverMock
+        );
+    }
+
+    public function testCanBeSearchableInGrid()
+    {
+        /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $attributeMock */
+        $attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface')
+            ->getMockForAbstractClass();
+
+        /** @var Attribute|\PHPUnit_Framework_MockObject_MockObject $modelMock */
+        $modelMock = $this->getMockBuilder('Magento\Customer\Model\Attribute')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->attributeResolverMock->expects($this->once())
+            ->method('getModelByAttribute')
+            ->with(AddressMetadataManagementInterface::ENTITY_TYPE_ADDRESS, $attributeMock)
+            ->willReturn($modelMock);
+
+        $modelMock->expects($this->once())
+            ->method('canBeSearchableInGrid')
+            ->willReturn(true);
+
+        $this->assertTrue($this->model->canBeSearchableInGrid($attributeMock));
+    }
+
+    public function testCanBeFilterableInGrid()
+    {
+        /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $attributeMock */
+        $attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface')
+            ->getMockForAbstractClass();
+
+        /** @var Attribute|\PHPUnit_Framework_MockObject_MockObject $modelMock */
+        $modelMock = $this->getMockBuilder('Magento\Customer\Model\Attribute')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->attributeResolverMock->expects($this->once())
+            ->method('getModelByAttribute')
+            ->with(AddressMetadataManagementInterface::ENTITY_TYPE_ADDRESS, $attributeMock)
+            ->willReturn($modelMock);
+
+        $modelMock->expects($this->once())
+            ->method('canBeFilterableInGrid')
+            ->willReturn(true);
+
+        $this->assertTrue($this->model->canBeFilterableInGrid($attributeMock));
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Model/Metadata/AttributeResolverTest.php b/app/code/Magento/Customer/Test/Unit/Model/Metadata/AttributeResolverTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0d75d83e5b067406ba5dfb28865ddc5de3a753d3
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Model/Metadata/AttributeResolverTest.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Model\Metadata;
+
+use Magento\Customer\Api\Data\AttributeMetadataInterface;
+use Magento\Customer\Model\Attribute;
+use Magento\Customer\Model\AttributeMetadataDataProvider;
+use Magento\Customer\Model\Metadata\AttributeResolver;
+
+class AttributeResolverTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var AttributeResolver */
+    protected $model;
+
+    /** @var AttributeMetadataDataProvider|\PHPUnit_Framework_MockObject_MockObject */
+    protected $metadataDataProviderMock;
+
+    protected function setUp()
+    {
+        $this->metadataDataProviderMock = $this->getMockBuilder('Magento\Customer\Model\AttributeMetadataDataProvider')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->model = new AttributeResolver(
+            $this->metadataDataProviderMock
+        );
+    }
+
+    public function testGetModelByAttribute()
+    {
+        $entityType = 'type';
+        $attributeCode = 'code';
+
+        /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $attributeMock */
+        $attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $attributeMock->expects($this->once())
+            ->method('getAttributeCode')
+            ->willReturn($attributeCode);
+
+        /** @var Attribute|\PHPUnit_Framework_MockObject_MockObject $modelMock */
+        $modelMock = $this->getMockBuilder('Magento\Customer\Model\Attribute')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->metadataDataProviderMock->expects($this->once())
+            ->method('getAttribute')
+            ->with($entityType, $attributeCode)
+            ->willReturn($modelMock);
+
+        $this->assertEquals($modelMock, $this->model->getModelByAttribute($entityType, $attributeMock));
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     * @expectedExceptionMessage No such entity with entityType = type, attributeCode = code
+     */
+    public function testGetModelByAttributeWithoutModel()
+    {
+        $entityType = 'type';
+        $attributeCode = 'code';
+
+        /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $attributeMock */
+        $attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $attributeMock->expects($this->exactly(2))
+            ->method('getAttributeCode')
+            ->willReturn($attributeCode);
+
+        $this->metadataDataProviderMock->expects($this->once())
+            ->method('getAttribute')
+            ->with($entityType, $attributeCode)
+            ->willReturn(false);
+
+        $this->model->getModelByAttribute($entityType, $attributeMock);
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Model/Metadata/CustomerMetadataManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/Metadata/CustomerMetadataManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9834470bf162ba5548cb61f02f667ffb8500f9dc
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Model/Metadata/CustomerMetadataManagementTest.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Model\Metadata;
+
+use Magento\Customer\Model\Attribute;
+use Magento\Customer\Api\Data\AttributeMetadataInterface;
+use Magento\Customer\Model\Metadata\CustomerMetadataManagement;
+
+class CustomerMetadataManagementTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var CustomerMetadataManagement */
+    protected $model;
+
+    /** @var \Magento\Customer\Model\Metadata\AttributeResolver|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeResolverMock;
+
+    protected function setUp()
+    {
+        $this->attributeResolverMock = $this->getMockBuilder('Magento\Customer\Model\Metadata\AttributeResolver')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->model = new CustomerMetadataManagement(
+            $this->attributeResolverMock
+        );
+    }
+
+    public function testCanBeSearchableInGrid()
+    {
+        /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $attributeMock */
+        $attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface')
+            ->getMockForAbstractClass();
+
+        /** @var Attribute|\PHPUnit_Framework_MockObject_MockObject $modelMock */
+        $modelMock = $this->getMockBuilder('Magento\Customer\Model\Attribute')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->attributeResolverMock->expects($this->once())
+            ->method('getModelByAttribute')
+            ->with(CustomerMetadataManagement::ENTITY_TYPE_CUSTOMER, $attributeMock)
+            ->willReturn($modelMock);
+
+        $modelMock->expects($this->once())
+            ->method('canBeSearchableInGrid')
+            ->willReturn(true);
+
+        $this->assertTrue($this->model->canBeSearchableInGrid($attributeMock));
+    }
+
+    public function testCanBeFilterableInGrid()
+    {
+        /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $attributeMock */
+        $attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface')
+            ->getMockForAbstractClass();
+
+        /** @var Attribute|\PHPUnit_Framework_MockObject_MockObject $modelMock */
+        $modelMock = $this->getMockBuilder('Magento\Customer\Model\Attribute')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->attributeResolverMock->expects($this->once())
+            ->method('getModelByAttribute')
+            ->with(CustomerMetadataManagement::ENTITY_TYPE_CUSTOMER, $attributeMock)
+            ->willReturn($modelMock);
+
+        $modelMock->expects($this->once())
+            ->method('canBeFilterableInGrid')
+            ->willReturn(true);
+
+        $this->assertTrue($this->model->canBeFilterableInGrid($attributeMock));
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Model/Resource/Customer/GridTest.php b/app/code/Magento/Customer/Test/Unit/Model/Resource/Customer/GridTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..14768adf1d50ddbd93b6844ca8b83ad797fc7ffa
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Model/Resource/Customer/GridTest.php
@@ -0,0 +1,135 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Model\Resource\Customer;
+
+use Magento\Customer\Model\Resource\Customer\Grid;
+
+class GridTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Framework\App\Resource|\PHPUnit_Framework_MockObject_MockObject */
+    protected $resource;
+
+    /** @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject */
+    protected $indexerRegistry;
+
+    /** @var \Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver|\PHPUnit_Framework_MockObject_MockObject */
+    protected $flatScopeResolver;
+
+    /** @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $indexer;
+
+    /** @var \Magento\Framework\DB\Adapter\AdapterInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $connection;
+
+    /** @var \Magento\Framework\DB\Select|\PHPUnit_Framework_MockObject_MockObject */
+    protected $select;
+
+    /** @var Grid */
+    protected $observer;
+
+    /** @var \Zend_Db_Statement_Interface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $queryResult;
+
+    public function setUp()
+    {
+        $this->resource = $this->getMock('Magento\Framework\App\Resource', [], [], '', false);
+        $this->indexerRegistry = $this->getMock('Magento\Framework\Indexer\IndexerRegistry', [], [], '', false);
+        $this->flatScopeResolver = $this->getMock(
+            'Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->indexer = $this->getMockForAbstractClass(
+            'Magento\Framework\Indexer\IndexerInterface',
+            [],
+            '',
+            false
+        );
+        $this->connection = $this->getMockForAbstractClass(
+            'Magento\Framework\DB\Adapter\AdapterInterface',
+            [],
+            '',
+            false
+        );
+        $this->select = $this->getMock('Magento\Framework\DB\Select', [], [], '', false);
+        $this->queryResult = $this->getMockForAbstractClass(
+            'Zend_Db_Statement_Interface',
+            [],
+            '',
+            false
+        );
+
+        $this->observer = new Grid(
+            $this->resource,
+            $this->indexerRegistry,
+            $this->flatScopeResolver
+        );
+    }
+
+    public function testSyncCustomerGrid()
+    {
+        $gridTable = 'customer_grid_flat';
+        $customerLogTable = 'customer_log';
+
+        $this->indexerRegistry->expects($this->once())
+            ->method('get')
+            ->with(\Magento\Customer\Model\Customer::CUSTOMER_GRID_INDEXER_ID)
+            ->willReturn($this->indexer);
+        $this->resource
+            ->expects($this->once())
+            ->method('getConnection')
+            ->willReturn($this->connection);
+        $this->flatScopeResolver
+            ->expects($this->once())
+            ->method('resolve')
+            ->with(\Magento\Customer\Model\Customer::CUSTOMER_GRID_INDEXER_ID, [])
+            ->willReturn($gridTable);
+
+        $this->connection->expects($this->exactly(2))
+            ->method('getTableName')
+            ->willReturnMap([
+                [$gridTable],
+                [$customerLogTable],
+            ]);
+
+        $this->connection->expects($this->exactly(2))
+            ->method('select')
+            ->willReturn($this->select);
+        $this->select->expects($this->exactly(2))
+            ->method('from')
+            ->willReturnSelf();
+        $this->select->expects($this->once())
+            ->method('order')
+            ->with('last_visit_at DESC')
+            ->willReturnSelf();
+        $this->select->expects($this->once())
+            ->method('limit')
+            ->with(1)
+            ->willReturnSelf();
+        $this->connection->expects($this->atLeastOnce())
+            ->method('query')
+            ->with($this->select)
+            ->willReturn($this->queryResult);
+        $this->queryResult->expects($this->once())
+            ->method('fetchColumn')
+            ->willReturn('2015-08-13 10:36:44');
+
+        $this->select->expects($this->once())
+            ->method('where')
+            ->with('last_login_at > ?', '2015-08-13 10:36:44')
+            ->willReturnSelf();
+        $this->queryResult->expects($this->once())
+            ->method('fetchAll')
+            ->willReturn([['customer_id' => 23], ['customer_id' => 65]]);
+        $this->indexer->expects($this->once())
+            ->method('reindexList')
+            ->with(['23', '65']);
+
+        $this->observer->syncCustomerGrid();
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4b0d7626492ef232810a28eddbe50016114b2768
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Ui\Component;
+
+use Magento\Customer\Ui\Component\ColumnFactory;
+
+class ColumnFactoryTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Customer\Api\Data\OptionInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeOption;
+
+    /** @var \Magento\Framework\View\Element\UiComponent\ContextInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $context;
+
+    /** @var \Magento\Framework\View\Element\UiComponentFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $componentFactory;
+
+    /** @var \Magento\Customer\Api\Data\AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeMetadata;
+
+    /** @var \Magento\Ui\Component\Listing\Columns\ColumnInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $column;
+
+    /** @var ColumnFactory */
+    protected $columnFactory;
+
+    public function setUp()
+    {
+        $this->context = $this->getMockForAbstractClass(
+            'Magento\Framework\View\Element\UiComponent\ContextInterface',
+            [],
+            '',
+            false
+        );
+        $this->componentFactory = $this->getMock(
+            'Magento\Framework\View\Element\UiComponentFactory',
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->attributeMetadata = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\Data\AttributeMetadataInterface',
+            [],
+            '',
+            false
+        );
+        $this->column = $this->getMockForAbstractClass(
+            'Magento\Ui\Component\Listing\Columns\ColumnInterface',
+            [],
+            '',
+            false
+        );
+        $this->attributeOption = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\Data\OptionInterface',
+            [],
+            '',
+            false
+        );
+
+        $this->columnFactory = new ColumnFactory($this->componentFactory);
+    }
+
+    public function testCreate()
+    {
+        $columnName = 'created_at';
+        $config = [
+            'data' => [
+                'js_config' => [
+                    'component' => 'Magento_Ui/js/grid/columns/column',
+                ],
+                'config' => [
+                    'label' => __('Label'),
+                    'dataType' => 'text',
+                    'align' => 'left',
+                    'visible' => true,
+                    'options' =>  [
+                        [
+                            'label' => 'Label',
+                            'value' => 'Value'
+                        ]
+                    ]
+                ],
+            ],
+            'context' => $this->context,
+        ];
+        $attributeData = [
+            'attribute_code' => 'billing_attribute_code',
+            'frontend_input' => 'frontend-input',
+            'frontend_label' => 'Label',
+            'backend_type' => 'backend-type',
+            'options' => [
+                [
+                    'label' => 'Label',
+                    'value' => 'Value'
+                ]
+            ],
+            'is_used_in_grid' => true,
+            'is_visible_in_grid' => true,
+            'is_filterable_in_grid' => true,
+            'is_searchable_in_grid' => true,
+        ];
+
+        $this->componentFactory->expects($this->once())
+            ->method('create')
+            ->with($columnName, 'column', $config)
+            ->willReturn($this->column);
+
+        $this->assertSame(
+            $this->column,
+            $this->columnFactory->create($attributeData, $columnName, $this->context)
+        );
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/FilterFactoryTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/FilterFactoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..18096b6de01a36e919cd06835975a9824d74d041
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/FilterFactoryTest.php
@@ -0,0 +1,107 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Ui\Component;
+
+use Magento\Customer\Ui\Component\FilterFactory;
+
+class FilterFactoryTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Customer\Api\Data\OptionInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeOption;
+
+    /** @var \Magento\Framework\View\Element\UiComponent\ContextInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $context;
+
+    /** @var \Magento\Framework\View\Element\UiComponentFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $componentFactory;
+
+    /** @var \Magento\Customer\Api\Data\AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeMetadata;
+
+    /** @var \Magento\Ui\Component\Listing\Columns\ColumnInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $filter;
+
+    /** @var FilterFactory */
+    protected $filterFactory;
+
+    protected function setUp()
+    {
+        $this->context = $this->getMockForAbstractClass(
+            'Magento\Framework\View\Element\UiComponent\ContextInterface',
+            [],
+            '',
+            false
+        );
+        $this->componentFactory = $this->getMock(
+            'Magento\Framework\View\Element\UiComponentFactory',
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->attributeMetadata = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\Data\AttributeMetadataInterface',
+            [],
+            '',
+            false
+        );
+        $this->filter = $this->getMockForAbstractClass(
+            'Magento\Ui\Component\Listing\Columns\ColumnInterface',
+            [],
+            '',
+            false
+        );
+        $this->attributeOption = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\Data\OptionInterface',
+            [],
+            '',
+            false
+        );
+
+        $this->filterFactory = new FilterFactory($this->componentFactory);
+    }
+
+    public function testCreate()
+    {
+        $filterName = 'created_at';
+        $config = [
+            'data' => [
+                'config' => [
+                    'dataScope' => $filterName,
+                    'label' => __('Label'),
+                    'options' => [['value' => 'Value', 'label' => 'Label']],
+                    'caption' => __('Select...'),
+                ],
+            ],
+            'context' => $this->context,
+        ];
+        $attributeData = [
+            'attribute_code' => $filterName,
+            'frontend_input' => 'frontend-input',
+            'frontend_label' => 'Label',
+            'backend_type' => 'backend-type',
+            'options' => [
+                [
+                    'label' => 'Label',
+                    'value' => 'Value'
+                ]
+            ],
+            'is_used_in_grid' => true,
+            'is_visible_in_grid' => true,
+            'is_filterable_in_grid' => true,
+            'is_searchable_in_grid' => true,
+        ];
+        $this->componentFactory->expects($this->once())
+            ->method('create')
+            ->with($filterName, 'filterInput', $config)
+            ->willReturn($this->filter);
+
+        $this->assertSame(
+            $this->filter,
+            $this->filterFactory->create($attributeData, $this->context)
+        );
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..fcd5ff19400e91c3d8694c177f131e3b2eb304ff
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php
@@ -0,0 +1,153 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Ui\Component\Listing;
+
+use Magento\Customer\Ui\Component\Listing\AttributeRepository;
+
+class AttributeRepositoryTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Customer\Api\CustomerMetadataManagementInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $customerMetadataManagement;
+
+    /** @var \Magento\Customer\Api\AddressMetadataManagementInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $addressMetadataManagement;
+
+    /** @var \Magento\Customer\Api\CustomerMetadataInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $customerMetadata;
+
+    /** @var \Magento\Customer\Api\AddressMetadataInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $addressMetadata;
+
+    /** @var \Magento\Customer\Api\Data\AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attribute;
+
+    /** @var \Magento\Customer\Api\Data\OptionInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $option;
+
+    /** @var \Magento\Customer\Model\Indexer\Attribute\Filter|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeFilter;
+
+    /** @var AttributeRepository */
+    protected $component;
+
+    public function setUp()
+    {
+        $this->customerMetadataManagement = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\CustomerMetadataManagementInterface',
+            [],
+            '',
+            false
+        );
+        $this->addressMetadataManagement = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\AddressMetadataManagementInterface',
+            [],
+            '',
+            false
+        );
+        $this->customerMetadata = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\CustomerMetadataInterface',
+            [],
+            '',
+            false
+        );
+        $this->addressMetadata = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\AddressMetadataInterface',
+            [],
+            '',
+            false
+        );
+        $this->attribute = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\Data\AttributeMetadataInterface',
+            [],
+            '',
+            false
+        );
+        $this->option = $this->getMock('Magento\Customer\Api\Data\OptionInterface', [], [], '', false);
+
+        $this->attributeFilter = $this->getMock('Magento\Customer\Model\Indexer\Attribute\Filter', [], [], '', false);
+
+        $this->component = new AttributeRepository(
+            $this->customerMetadataManagement,
+            $this->addressMetadataManagement,
+            $this->customerMetadata,
+            $this->addressMetadata,
+            $this->attributeFilter
+        );
+    }
+
+    public function testGetList()
+    {
+        $attributeCode = 'attribute_code';
+        $billingPrefix = 'billing_';
+
+        $this->customerMetadata->expects($this->once())
+            ->method('getAllAttributesMetadata')
+            ->willReturn([]);
+        $this->addressMetadata->expects($this->once())
+            ->method('getAllAttributesMetadata')
+            ->willReturn([$this->attribute]);
+        $this->addressMetadataManagement->expects($this->once())
+            ->method('canBeFilterableInGrid')
+            ->with($this->attribute)
+            ->willReturn(true);
+        $this->addressMetadataManagement->expects($this->once())
+            ->method('canBeSearchableInGrid')
+            ->with($this->attribute)
+            ->willReturn(true);
+        $this->attribute->expects($this->atLeastOnce())
+            ->method('getAttributeCode')
+            ->willReturn($attributeCode);
+        $this->attribute->expects($this->once())
+            ->method('getFrontendInput')
+            ->willReturn('frontend-input');
+        $this->attribute->expects($this->once())
+            ->method('getFrontendLabel')
+            ->willReturn('frontend-label');
+        $this->attribute->expects($this->once())
+            ->method('getBackendType')
+            ->willReturn('backend-type');
+        $this->attribute->expects($this->once())
+            ->method('getOptions')
+            ->willReturn([$this->option]);
+        $this->attribute->expects($this->once())
+            ->method('getIsUsedInGrid')
+            ->willReturn(true);
+        $this->attribute->expects($this->once())
+            ->method('getIsVisibleInGrid')
+            ->willReturn(true);
+        $this->option->expects($this->once())
+            ->method('getLabel')
+            ->willReturn('Label');
+        $this->option->expects($this->once())
+            ->method('getValue')
+            ->willReturn('Value');
+        $this->attributeFilter->expects($this->once())
+            ->method('filter')
+            ->willReturnArgument(0);
+
+        $this->assertEquals(
+            [
+                $billingPrefix . $attributeCode => [
+                    'attribute_code' => 'billing_attribute_code',
+                    'frontend_input' => 'frontend-input',
+                    'frontend_label' => 'frontend-label',
+                    'backend_type' => 'backend-type',
+                    'options' => [
+                        [
+                            'label' => 'Label',
+                            'value' => 'Value'
+                        ]
+                    ],
+                    'is_used_in_grid' => true,
+                    'is_visible_in_grid' => true,
+                    'is_filterable_in_grid' => true,
+                    'is_searchable_in_grid' => true,
+                ]
+            ],
+            $this->component->getList()
+        );
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/ActionsTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/ActionsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d329c4befd1f7691668bff4c166f39c6ef4c46be
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/ActionsTest.php
@@ -0,0 +1,97 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Ui\Component\Listing\Column;
+
+use Magento\Customer\Ui\Component\Listing\Column\Actions;
+
+class ActionsTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var Actions */
+    protected $component;
+
+    /** @var \Magento\Framework\View\Element\UiComponent\ContextInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $context;
+
+    /** @var \Magento\Framework\View\Element\UiComponentFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $uiComponentFactory;
+
+    /** @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $urlBuilder;
+
+    public function setup()
+    {
+        $this->context = $this->getMockForAbstractClass(
+            'Magento\Framework\View\Element\UiComponent\ContextInterface',
+            [],
+            '',
+            false
+        );
+        $this->uiComponentFactory = $this->getMock(
+            'Magento\Framework\View\Element\UiComponentFactory',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->urlBuilder = $this->getMockForAbstractClass(
+            'Magento\Framework\UrlInterface',
+            [],
+            '',
+            false
+        );
+        $this->component = new Actions(
+            $this->context,
+            $this->uiComponentFactory,
+            $this->urlBuilder
+        );
+        $this->component->setData('name', 'name');
+    }
+
+    public function testPrepareDataSource()
+    {
+        $dataSource = [
+            'data' => [
+                'items' => [
+                    [
+                        'entity_id' => 1
+                    ],
+                ]
+            ]
+        ];
+        $expectedDataSource = [
+            'data' => [
+                'items' => [
+                    [
+                        'entity_id' => 1,
+                        'name' => [
+                            'edit' => [
+                                'href' => 'http://magento.com/customer/index/edit',
+                                'label' => new \Magento\Framework\Phrase('Edit'),
+                                'hidden' => false
+                            ]
+                        ]
+                    ],
+                ]
+            ]
+        ];
+
+        $this->context->expects($this->once())
+            ->method('getFilterParam')
+            ->with('store_id')
+            ->willReturn(null);
+        $this->urlBuilder->expects($this->once())
+            ->method('getUrl')
+            ->with(
+                'customer/*/edit',
+                ['id' => 1, 'store' => null]
+            )
+            ->willReturn('http://magento.com/customer/index/edit');
+
+        $this->component->prepareDataSource($dataSource);
+
+        $this->assertEquals($expectedDataSource, $dataSource);
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/AttributeColumnTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/AttributeColumnTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ec5772d9d09b1fdc3679688fcddc0d3084cb7a63
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/AttributeColumnTest.php
@@ -0,0 +1,132 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Ui\Component\Listing\Column;
+
+use Magento\Customer\Api\CustomerMetadataInterface;
+use Magento\Customer\Ui\Component\Listing\Column\AttributeColumn;
+
+class AttributeColumnTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var AttributeColumn */
+    protected $component;
+
+    /** @var \Magento\Framework\View\Element\UiComponent\ContextInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $context;
+
+    /** @var \Magento\Framework\View\Element\UiComponentFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $uiComponentFactory;
+
+    /** @var \Magento\Customer\Ui\Component\Listing\AttributeRepository|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeRepository;
+
+    /** @var \Magento\Customer\Api\Data\AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeMetadata;
+
+    public function setup()
+    {
+        $this->context = $this->getMockForAbstractClass(
+            'Magento\Framework\View\Element\UiComponent\ContextInterface',
+            [],
+            '',
+            false
+        );
+        $this->uiComponentFactory = $this->getMock(
+            'Magento\Framework\View\Element\UiComponentFactory',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->attributeRepository = $this->getMock(
+            'Magento\Customer\Ui\Component\Listing\AttributeRepository',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->attributeMetadata = $this->getMockForAbstractClass(
+            '\Magento\Customer\Api\Data\AttributeMetadataInterface',
+            [],
+            '',
+            false
+        );
+
+        $this->component = new AttributeColumn(
+            $this->context,
+            $this->uiComponentFactory,
+            $this->attributeRepository
+        );
+        $this->component->setData('name', 'gender');
+    }
+
+    public function testPrepareDataSourceWithoutItems()
+    {
+        $dataSource = [
+            'data' => [
+
+            ]
+        ];
+        $this->attributeRepository->expects($this->never())
+            ->method('getMetadataByCode');
+
+        $this->assertNull($this->component->prepareDataSource($dataSource));
+    }
+
+    public function testPrepareDataSource()
+    {
+        $genderOptionId = 1;
+        $genderOptionLabel = 'Male';
+
+        $dataSource = [
+            'data' => [
+                'items' => [
+                    [
+                        'name' => 'testName'
+                    ],
+                    [
+                        'gender' => $genderOptionId
+                    ]
+                ]
+            ]
+        ];
+        $expectedSource = [
+            'data' => [
+                'items' => [
+                    [
+                        'name' => 'testName'
+                    ],
+                    [
+                        'gender' => $genderOptionLabel
+                    ]
+                ]
+            ]
+        ];
+
+        $this->attributeRepository->expects($this->once())
+            ->method('getMetadataByCode')
+            ->with('gender')
+            ->willReturn([
+                'attribute_code' => 'billing_attribute_code',
+                'frontend_input' => 'frontend-input',
+                'frontend_label' => 'frontend-label',
+                'backend_type' => 'backend-type',
+                'options' => [
+                    [
+                        'label' => $genderOptionLabel,
+                        'value' => $genderOptionId
+                    ]
+                ],
+                'is_used_in_grid' => true,
+                'is_visible_in_grid' => true,
+                'is_filterable_in_grid' => true,
+                'is_searchable_in_grid' => true,
+            ]);
+
+        $this->component->prepareDataSource($dataSource);
+
+        $this->assertEquals($expectedSource, $dataSource);
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..92ec5d4082f3ec5c07189eac62e418843dec489f
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/ColumnsTest.php
@@ -0,0 +1,201 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Ui\Component\Listing;
+
+use Magento\Customer\Ui\Component\Listing\Columns;
+
+class ColumnsTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Framework\View\Element\UiComponent\ContextInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $context;
+
+    /** @var \Magento\Customer\Ui\Component\ColumnFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $columnFactory;
+
+    /** @var \Magento\Customer\Ui\Component\Listing\AttributeRepository|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeRepository;
+
+    /** @var \Magento\Customer\Model\Attribute|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attribute;
+
+    /** @var \Magento\Ui\Component\Listing\Columns\ColumnInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $column;
+
+    /** @var Columns */
+    protected $component;
+
+    public function setUp()
+    {
+        $this->context = $this->getMockForAbstractClass(
+            'Magento\Framework\View\Element\UiComponent\ContextInterface',
+            [],
+            '',
+            false
+        );
+        $this->columnFactory = $this->getMock(
+            'Magento\Customer\Ui\Component\ColumnFactory',
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->attributeRepository = $this->getMock(
+            'Magento\Customer\Ui\Component\Listing\AttributeRepository',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->attribute = $this->getMock(
+            'Magento\Customer\Model\Attribute',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->column = $this->getMockForAbstractClass(
+            'Magento\Ui\Component\Listing\Columns\ColumnInterface',
+            [],
+            '',
+            false
+        );
+
+        $this->component = new Columns(
+            $this->context,
+            $this->columnFactory,
+            $this->attributeRepository
+        );
+    }
+
+    public function testPrepareWithAddColumn()
+    {
+        $attributeCode = 'attribute_code';
+
+        $this->attributeRepository->expects($this->atLeastOnce())
+            ->method('getList')
+            ->willReturn(
+                [
+                    $attributeCode => [
+                        'attribute_code' => 'billing_attribute_code',
+                        'frontend_input' => 'frontend-input',
+                        'frontend_label' => 'frontend-label',
+                        'backend_type' => 'backend-type',
+                        'options' => [
+                            [
+                                'label' => 'Label',
+                                'value' => 'Value'
+                            ]
+                        ],
+                        'is_used_in_grid' => true,
+                        'is_visible_in_grid' => true,
+                        'is_filterable_in_grid' => true,
+                        'is_searchable_in_grid' => true,
+                    ]
+                ]
+            );
+        $this->columnFactory->expects($this->once())
+            ->method('create')
+            ->willReturn($this->column);
+        $this->column->expects($this->once())
+            ->method('prepare');
+
+        $this->component->prepare();
+    }
+
+    public function testPrepareWithUpdateColumn()
+    {
+        $attributeCode = 'billing_attribute_code';
+        $backendType = 'backend-type';
+        $attributeData = [
+            'attribute_code' => 'billing_attribute_code',
+            'frontend_input' => 'frontend-input',
+            'frontend_label' => 'frontend-label',
+            'backend_type' => 'backend-type',
+            'options' => [
+                [
+                    'label' => 'Label',
+                    'value' => 'Value'
+                ]
+            ],
+            'is_used_in_grid' => true,
+            'is_visible_in_grid' => true,
+            'is_filterable_in_grid' => true,
+            'is_searchable_in_grid' => true,
+        ];
+
+        $this->attributeRepository->expects($this->atLeastOnce())
+            ->method('getList')
+            ->willReturn([$attributeCode => $attributeData]);
+        $this->columnFactory->expects($this->once())
+            ->method('create')
+            ->willReturn($this->column);
+        $this->column->expects($this->once())
+            ->method('prepare');
+        $this->column->expects($this->atLeastOnce())
+            ->method('getData')
+            ->with('config')
+            ->willReturn([]);
+        $this->column->expects($this->once())
+            ->method('setData')
+            ->with(
+                'config',
+                [
+                    'name' => $attributeCode,
+                    'dataType' => $backendType,
+                    'visible' => true
+                ]
+            );
+
+        $this->component->addColumn($attributeData, $attributeCode);
+        $this->component->prepare();
+    }
+
+    public function testPrepareWithUpdateStaticColumn()
+    {
+        $attributeCode = 'billing_attribute_code';
+        $backendType = 'static';
+        $attributeData = [
+            'attribute_code' => 'billing_attribute_code',
+            'frontend_input' => 'frontend-input',
+            'frontend_label' => 'frontend-label',
+            'backend_type' => $backendType,
+            'options' => [
+                [
+                    'label' => 'Label',
+                    'value' => 'Value'
+                ]
+            ],
+            'is_used_in_grid' => true,
+            'is_visible_in_grid' => true,
+            'is_filterable_in_grid' => true,
+            'is_searchable_in_grid' => true,
+        ];
+
+        $this->attributeRepository->expects($this->atLeastOnce())
+            ->method('getList')
+            ->willReturn([$attributeCode => $attributeData]);
+        $this->columnFactory->expects($this->once())
+            ->method('create')
+            ->willReturn($this->column);
+        $this->column->expects($this->once())
+            ->method('prepare');
+        $this->column->expects($this->atLeastOnce())
+            ->method('getData')
+            ->with('config')
+            ->willReturn([]);
+        $this->column->expects($this->once())
+            ->method('setData')
+            ->with(
+                'config',
+                [
+                    'visible' => true
+                ]
+            );
+
+        $this->component->addColumn($attributeData, $attributeCode);
+        $this->component->prepare();
+    }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/FiltersTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/FiltersTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2dc73c58104a5746ba8513e3816d646aba770240
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/FiltersTest.php
@@ -0,0 +1,135 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Test\Unit\Ui\Component\Listing;
+
+use Magento\Customer\Ui\Component\Listing\Filters;
+
+class FiltersTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Framework\View\Element\UiComponent\ContextInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $context;
+
+    /** @var \Magento\Customer\Ui\Component\FilterFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $filterFactory;
+
+    /** @var \Magento\Customer\Ui\Component\Listing\AttributeRepository|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeRepository;
+
+    /** @var \Magento\Customer\Api\Data\AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeMetadata;
+
+    /** @var \Magento\Ui\Component\Listing\Columns\ColumnInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $filter;
+
+    /** @var Filters */
+    protected $component;
+
+    public function setUp()
+    {
+        $this->context = $this->getMockForAbstractClass(
+            'Magento\Framework\View\Element\UiComponent\ContextInterface',
+            [],
+            '',
+            false
+        );
+        $this->filterFactory = $this->getMock(
+            'Magento\Customer\Ui\Component\FilterFactory',
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->attributeRepository = $this->getMock(
+            'Magento\Customer\Ui\Component\Listing\AttributeRepository',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->attributeMetadata = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\Data\AttributeMetadataInterface',
+            [],
+            '',
+            false
+        );
+        $this->filter = $this->getMockForAbstractClass(
+            'Magento\Ui\Component\Listing\Columns\ColumnInterface',
+            [],
+            '',
+            false
+        );
+
+        $this->component = new Filters(
+            $this->context,
+            $this->filterFactory,
+            $this->attributeRepository
+        );
+    }
+
+    public function testPrepare()
+    {
+        $attributeCode = 'billing_attribute_code';
+        $attributeData = [
+            'attribute_code' => $attributeCode,
+            'frontend_input' => 'frontend-input',
+            'frontend_label' => 'frontend-label',
+            'backend_type' => 'backend-type',
+            'options' => [
+                [
+                    'label' => 'Label',
+                    'value' => 'Value'
+                ]
+            ],
+            'is_used_in_grid' => true,
+            'is_visible_in_grid' => true,
+            'is_filterable_in_grid' => true,
+            'is_searchable_in_grid' => true,
+        ];
+
+        $this->attributeRepository->expects($this->atLeastOnce())
+            ->method('getList')
+            ->willReturn([$attributeCode => $attributeData]);
+        $this->filterFactory->expects($this->once())
+            ->method('create')
+            ->with($attributeData, $this->context)
+            ->willReturn($this->filter);
+        $this->filter->expects($this->once())
+            ->method('prepare');
+
+        $this->component->prepare();
+        $this->assertSame($this->filter, $this->component->getComponent($attributeCode));
+    }
+
+    public function testPrepareWithAlreadyAddedComponent()
+    {
+        $attributeCode = 'billing_attribute_code';
+        $attributeData = [
+            'attribute_code' => $attributeCode,
+            'frontend_input' => 'frontend-input',
+            'frontend_label' => 'frontend-label',
+            'backend_type' => 'backend-type',
+            'options' => [
+                [
+                    'label' => 'Label',
+                    'value' => 'Value'
+                ]
+            ],
+            'is_used_in_grid' => true,
+            'is_visible_in_grid' => true,
+            'is_filterable_in_grid' => false,
+            'is_searchable_in_grid' => true,
+        ];
+
+        $this->component->addComponent($attributeCode, $this->filter);
+
+        $this->attributeRepository->expects($this->atLeastOnce())
+            ->method('getList')
+            ->willReturn([$attributeCode => $attributeData]);
+
+        $this->component->prepare();
+        $this->assertEquals(null, $this->component->getComponent($attributeCode));
+    }
+}
diff --git a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..59a6fca610d2814db87122c56adec47078b48088
--- /dev/null
+++ b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Ui\Component;
+
+use Magento\Customer\Api\Data\AttributeMetadataInterface as AttributeMetadata;
+
+class ColumnFactory
+{
+    /**
+     * @var \Magento\Framework\View\Element\UiComponentFactory
+     */
+    protected $componentFactory;
+
+    /**
+     * @var array
+     */
+    protected $jsComponentMap = [
+        'text' => 'Magento_Ui/js/grid/columns/column',
+        'date' => 'Magento_Ui/js/grid/columns/date',
+    ];
+
+    /**
+     * @var array
+     */
+    protected $dataTypeMap = [
+        'default' => 'text',
+        'text' => 'text',
+        'boolean' => 'text',
+        'select' => 'text',
+        'multiselect' => 'text',
+        'date' => 'date',
+    ];
+
+    /**
+     * @param \Magento\Framework\View\Element\UiComponentFactory $componentFactory
+     */
+    public function __construct(
+        \Magento\Framework\View\Element\UiComponentFactory $componentFactory
+    ) {
+        $this->componentFactory = $componentFactory;
+    }
+
+    /**
+     * @param array $attributeData
+     * @param string $columnName
+     * @param \Magento\Framework\View\Element\UiComponent\ContextInterface $context
+     * @param array $config
+     * @return \Magento\Ui\Component\Listing\Columns\ColumnInterface
+     */
+    public function create(array $attributeData, $columnName, $context, array $config = [])
+    {
+        $config = array_merge([
+            'label' => __($attributeData[AttributeMetadata::FRONTEND_LABEL]),
+            'dataType' => $this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT]),
+            'align' => 'left',
+            'visible' => (bool)$attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID],
+        ], $config);
+
+        if ($attributeData[AttributeMetadata::OPTIONS]) {
+            $config['options'] = $attributeData[AttributeMetadata::OPTIONS];
+        }
+        $arguments = [
+            'data' => [
+                'js_config' => [
+                    'component' => $this->getJsComponent($config['dataType']),
+                ],
+                'config' => $config,
+            ],
+            'context' => $context,
+        ];
+        return $this->componentFactory->create($columnName, 'column', $arguments);
+    }
+
+    /**
+     * @param string $dataType
+     * @return string
+     */
+    protected function getJsComponent($dataType)
+    {
+        return $this->jsComponentMap[$dataType];
+    }
+
+    /**
+     * @param string $frontendType
+     * @return string
+     */
+    protected function getDataType($frontendType)
+    {
+        return isset($this->dataTypeMap[$frontendType])
+            ? $this->dataTypeMap[$frontendType]
+            : $this->dataTypeMap['default'];
+    }
+}
diff --git a/app/code/Magento/Customer/Ui/Component/DataProvider.php b/app/code/Magento/Customer/Ui/Component/DataProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..91a14122678c9ea128c5263a30c86bc68ce4c845
--- /dev/null
+++ b/app/code/Magento/Customer/Ui/Component/DataProvider.php
@@ -0,0 +1,119 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Ui\Component;
+
+use Magento\Customer\Api\Data\AttributeMetadataInterface;
+use Magento\Customer\Ui\Component\Listing\AttributeRepository;
+use Magento\Framework\Api\FilterBuilder;
+use Magento\Framework\Api\Search\SearchCriteriaBuilder;
+use Magento\Framework\App\RequestInterface;
+use Magento\Framework\View\Element\UiComponent\DataProvider\Reporting;
+
+class DataProvider extends \Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider
+{
+    /**
+     * @var AttributeRepository
+     */
+    private $attributeRepository;
+
+    /**
+     * @param string $name
+     * @param string $primaryFieldName
+     * @param string $requestFieldName
+     * @param Reporting $reporting
+     * @param SearchCriteriaBuilder $searchCriteriaBuilder
+     * @param RequestInterface $request
+     * @param FilterBuilder $filterBuilder
+     * @param AttributeRepository $attributeRepository
+     * @param array $meta
+     * @param array $data
+     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
+     */
+    public function __construct(
+        $name,
+        $primaryFieldName,
+        $requestFieldName,
+        Reporting $reporting,
+        SearchCriteriaBuilder $searchCriteriaBuilder,
+        RequestInterface $request,
+        FilterBuilder $filterBuilder,
+        AttributeRepository $attributeRepository,
+        array $meta = [],
+        array $data = []
+    ) {
+        $this->attributeRepository = $attributeRepository;
+        parent::__construct(
+            $name,
+            $primaryFieldName,
+            $requestFieldName,
+            $reporting,
+            $searchCriteriaBuilder,
+            $request,
+            $filterBuilder,
+            $meta,
+            $data
+        );
+    }
+
+    /**
+     * Retrieve custom attributes options
+     *
+     * @return array
+     */
+    public function getCustomAttributesOptions()
+    {
+        $attributes = [];
+        foreach ($this->attributeRepository->getList() as $attributeCode => $attributeData) {
+            if ($attributeData[AttributeMetadataInterface::BACKEND_TYPE] != 'static'
+                && $attributeData[AttributeMetadataInterface::IS_USED_IN_GRID]
+                && $attributeData[AttributeMetadataInterface::OPTIONS]
+            ) {
+                $attributes[$attributeCode] = $attributeData[AttributeMetadataInterface::OPTIONS];
+            }
+        }
+        return $attributes;
+    }
+
+    /**
+     * Retrieve attribute option label by option value
+     *
+     * @param array $attributeData
+     * @param string $value
+     * @return string
+     */
+    protected function getAttributeOptionLabelByValue(array $attributeData, $value)
+    {
+        if (empty($value)) {
+            return $value;
+        }
+        foreach ($attributeData as $option) {
+            if ($option['value'] === $value) {
+                return $option['label'];
+            }
+        }
+        return $value;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getData()
+    {
+        $data = $this->searchResultToOutput($this->getSearchResult());
+        $customAttributesOptions = $this->getCustomAttributesOptions();
+        foreach ($customAttributesOptions as $attributeCode => $attributeData) {
+            foreach ($data['items'] as &$item) {
+                if (isset($item[$attributeCode])) {
+                    $item[$attributeCode] = $this->getAttributeOptionLabelByValue(
+                        $attributeData,
+                        $item[$attributeCode]
+                    );
+                }
+            }
+        }
+        return $data;
+    }
+}
diff --git a/app/code/Magento/Customer/Ui/Component/FilterFactory.php b/app/code/Magento/Customer/Ui/Component/FilterFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..75f20f29a1cbd1829b3ddd23809f091cd5dd0023
--- /dev/null
+++ b/app/code/Magento/Customer/Ui/Component/FilterFactory.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Ui\Component;
+
+use Magento\Customer\Api\Data\AttributeMetadataInterface as AttributeMetadata;
+
+class FilterFactory
+{
+    /**
+     * @var \Magento\Framework\View\Element\UiComponentFactory
+     */
+    protected $componentFactory;
+
+    /**
+     * @var array
+     */
+    protected $filterMap = [
+        'default' => 'filterInput',
+        'select' => 'filterSelect',
+        'boolean' => 'filterSelect',
+        'multiselect' => 'filterSelect',
+        'date' => 'filterDate',
+    ];
+
+    /**
+     * @param \Magento\Framework\View\Element\UiComponentFactory $componentFactory
+     */
+    public function __construct(\Magento\Framework\View\Element\UiComponentFactory $componentFactory)
+    {
+        $this->componentFactory = $componentFactory;
+    }
+
+    /**
+     * @param array $attributeData
+     * @param \Magento\Framework\View\Element\UiComponent\ContextInterface $context
+     * @return \Magento\Ui\Component\Listing\Columns\ColumnInterface
+     */
+    public function create(array $attributeData, $context)
+    {
+        $config = [
+            'dataScope' => $attributeData[AttributeMetadata::ATTRIBUTE_CODE],
+            'label' => __($attributeData[AttributeMetadata::FRONTEND_LABEL]),
+        ];
+        if ($attributeData[AttributeMetadata::OPTIONS]) {
+            $config['options'] = $attributeData[AttributeMetadata::OPTIONS];
+            $config['caption'] = __('Select...');
+        }
+        $arguments = [
+            'data' => [
+                'config' => $config,
+            ],
+            'context' => $context,
+        ];
+
+        return $this->componentFactory->create(
+            $attributeData[AttributeMetadata::ATTRIBUTE_CODE],
+            $this->getFilterType($attributeData[AttributeMetadata::FRONTEND_INPUT]),
+            $arguments
+        );
+    }
+
+    /**
+     * @param string $frontendInput
+     * @return string
+     */
+    protected function getFilterType($frontendInput)
+    {
+        return isset($this->filterMap[$frontendInput]) ? $this->filterMap[$frontendInput] : $this->filterMap['default'];
+    }
+}
diff --git a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php
new file mode 100644
index 0000000000000000000000000000000000000000..294fa32b3e872ff1db7c71736deb1b941b615a91
--- /dev/null
+++ b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php
@@ -0,0 +1,132 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Ui\Component\Listing;
+
+use Magento\Customer\Api\CustomerMetadataInterface;
+use Magento\Customer\Api\AddressMetadataInterface;
+use Magento\Customer\Api\Data\AttributeMetadataInterface;
+use Magento\Customer\Api\CustomerMetadataManagementInterface;
+use Magento\Customer\Api\AddressMetadataManagementInterface;
+use Magento\Customer\Api\MetadataManagementInterface;
+use Magento\Customer\Model\Indexer\Attribute\Filter;
+
+class AttributeRepository
+{
+    const BILLING_ADDRESS_PREFIX = 'billing_';
+
+    /** @var [] */
+    protected $attributes;
+
+    /** @var CustomerMetadataInterface */
+    protected $customerMetadata;
+
+    /** @var AddressMetadataInterface */
+    protected $addressMetadata;
+
+    /** @var CustomerMetadataManagementInterface */
+    protected $customerMetadataManagement;
+
+    /** @var AddressMetadataManagementInterface */
+    protected $addressMetadataManagement;
+
+    /** @var Filter */
+    protected $attributeFilter;
+
+    /**
+     * @param CustomerMetadataManagementInterface $customerMetadataManagement
+     * @param AddressMetadataManagementInterface $addressMetadataManagement
+     * @param CustomerMetadataInterface $customerMetadata
+     * @param AddressMetadataInterface $addressMetadata
+     * @param Filter $attributeFiltering
+     */
+    public function __construct(
+        CustomerMetadataManagementInterface $customerMetadataManagement,
+        AddressMetadataManagementInterface $addressMetadataManagement,
+        CustomerMetadataInterface $customerMetadata,
+        AddressMetadataInterface $addressMetadata,
+        Filter $attributeFiltering
+    ) {
+        $this->customerMetadataManagement = $customerMetadataManagement;
+        $this->addressMetadataManagement = $addressMetadataManagement;
+        $this->customerMetadata = $customerMetadata;
+        $this->addressMetadata = $addressMetadata;
+        $this->attributeFilter = $attributeFiltering;
+    }
+
+    /**
+     * @return array
+     */
+    public function getList()
+    {
+        if (!$this->attributes) {
+            $this->attributes = $this->getListForEntity(
+                $this->customerMetadata->getAllAttributesMetadata(),
+                CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER,
+                $this->customerMetadataManagement
+            );
+            $this->attributes = array_merge(
+                $this->attributes,
+                $this->getListForEntity(
+                    $this->addressMetadata->getAllAttributesMetadata(),
+                    AddressMetadataInterface::ENTITY_TYPE_ADDRESS,
+                    $this->addressMetadataManagement
+                )
+            );
+        }
+
+        return $this->attributeFilter->filter($this->attributes);
+    }
+
+    /**
+     * @param AttributeMetadataInterface[] $metadata
+     * @param string $entityTypeCode
+     * @param MetadataManagementInterface $management
+     * @return array
+     */
+    protected function getListForEntity(array $metadata, $entityTypeCode, MetadataManagementInterface $management)
+    {
+        $attributes = [];
+        /** @var AttributeMetadataInterface $attribute */
+        foreach ($metadata as $attribute) {
+            $attributeCode = $attribute->getAttributeCode();
+            if ($entityTypeCode == AddressMetadataInterface::ENTITY_TYPE_ADDRESS) {
+                $attributeCode = self::BILLING_ADDRESS_PREFIX . $attribute->getAttributeCode();
+            }
+            $attributes[$attributeCode] = [
+                AttributeMetadataInterface::ATTRIBUTE_CODE => $attributeCode,
+                AttributeMetadataInterface::FRONTEND_INPUT => $attribute->getFrontendInput(),
+                AttributeMetadataInterface::FRONTEND_LABEL => $attribute->getFrontendLabel(),
+                AttributeMetadataInterface::BACKEND_TYPE => $attribute->getBackendType(),
+                AttributeMetadataInterface::OPTIONS => $this->getOptionArray($attribute->getOptions()),
+                AttributeMetadataInterface::IS_USED_IN_GRID => $attribute->getIsUsedInGrid(),
+                AttributeMetadataInterface::IS_VISIBLE_IN_GRID => $attribute->getIsVisibleInGrid(),
+                AttributeMetadataInterface::IS_FILTERABLE_IN_GRID => $management->canBeFilterableInGrid($attribute),
+                AttributeMetadataInterface::IS_SEARCHABLE_IN_GRID => $management->canBeSearchableInGrid($attribute),
+            ];
+        }
+
+        return $attributes;
+    }
+
+    protected function getOptionArray(array $options)
+    {
+        /** @var \Magento\Customer\Api\Data\OptionInterface $option */
+        foreach ($options as &$option) {
+            $option = ['label' => $option->getLabel(), 'value' => $option->getValue()];
+        }
+        return $options;
+    }
+
+
+    /**
+     * @param string $code
+     * @return []
+     */
+    public function getMetadataByCode($code)
+    {
+        return isset($this->getList()[$code]) ? $this->getList()[$code] : null;
+    }
+}
diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Column/Actions.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/Actions.php
new file mode 100644
index 0000000000000000000000000000000000000000..8d85411f99c2480b5fc861dce280e79e225068a5
--- /dev/null
+++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/Actions.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Ui\Component\Listing\Column;
+
+use Magento\Framework\View\Element\UiComponent\ContextInterface;
+use Magento\Framework\View\Element\UiComponentFactory;
+use Magento\Ui\Component\Listing\Columns\Column;
+use Magento\Framework\UrlInterface;
+
+/**
+ * Class ProductActions
+ */
+class Actions extends Column
+{
+    /**
+     * @var UrlInterface
+     */
+    protected $urlBuilder;
+
+    /**
+     * @param ContextInterface $context
+     * @param UiComponentFactory $uiComponentFactory
+     * @param UrlInterface $urlBuilder
+     * @param array $components
+     * @param array $data
+     */
+    public function __construct(
+        ContextInterface $context,
+        UiComponentFactory $uiComponentFactory,
+        UrlInterface $urlBuilder,
+        array $components = [],
+        array $data = []
+    ) {
+        $this->urlBuilder = $urlBuilder;
+        parent::__construct($context, $uiComponentFactory, $components, $data);
+    }
+
+    /**
+     * Prepare Data Source
+     *
+     * @param array $dataSource
+     * @return void
+     */
+    public function prepareDataSource(array &$dataSource)
+    {
+        if (isset($dataSource['data']['items'])) {
+            $storeId = $this->context->getFilterParam('store_id');
+
+            foreach ($dataSource['data']['items'] as &$item) {
+                $item[$this->getData('name')]['edit'] = [
+                    'href' => $this->urlBuilder->getUrl(
+                        'customer/*/edit',
+                        ['id' => $item['entity_id'], 'store' => $storeId]
+                    ),
+                    'label' => __('Edit'),
+                    'hidden' => false,
+                ];
+            }
+        }
+    }
+}
diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Column/AttributeColumn.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/AttributeColumn.php
new file mode 100644
index 0000000000000000000000000000000000000000..54985c4f9ccb9a596cefff7d2eec21f3d105f031
--- /dev/null
+++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/AttributeColumn.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Ui\Component\Listing\Column;
+
+use Magento\Framework\View\Element\UiComponent\ContextInterface;
+use Magento\Framework\View\Element\UiComponentFactory;
+use Magento\Ui\Component\Listing\Columns\Column;
+use Magento\Customer\Ui\Component\Listing\AttributeRepository;
+use Magento\Customer\Api\Data\AttributeMetadataInterface as AttributeMetadata;
+
+class AttributeColumn extends Column
+{
+    /** @var AttributeRepository */
+    protected $attributeRepository;
+
+    /**
+     * @param ContextInterface $context
+     * @param UiComponentFactory $uiComponentFactory
+     * @param AttributeRepository $attributeRepository
+     * @param array $components
+     * @param array $data
+     */
+    public function __construct(
+        ContextInterface $context,
+        UiComponentFactory $uiComponentFactory,
+        AttributeRepository $attributeRepository,
+        array $components = [],
+        array $data = []
+    ) {
+        parent::__construct($context, $uiComponentFactory, $components, $data);
+        $this->attributeRepository = $attributeRepository;
+    }
+
+    /**
+     * Prepare Data Source
+     *
+     * @param array $dataSource
+     * @return void
+     */
+    public function prepareDataSource(array &$dataSource)
+    {
+        if (!isset($dataSource['data']['items'])) {
+            return null;
+        }
+
+        $metaData = $this->attributeRepository->getMetadataByCode($this->getName());
+        if ($metaData && count($metaData[AttributeMetadata::OPTIONS])) {
+            foreach ($dataSource['data']['items'] as &$item) {
+                if (!isset($item[$this->getName()])) {
+                    continue;
+                }
+                foreach ($metaData[AttributeMetadata::OPTIONS] as $option) {
+                    if ($option['value'] == $item[$this->getName()]) {
+                        $item[$this->getName()] = $option['label'];
+                        break;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php
new file mode 100644
index 0000000000000000000000000000000000000000..2f74af7f6bd16a1e34933c6d04471aee6f036b63
--- /dev/null
+++ b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php
@@ -0,0 +1,137 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Ui\Component\Listing;
+
+use Magento\Framework\View\Element\UiComponent\ContextInterface;
+use Magento\Customer\Ui\Component\ColumnFactory;
+use Magento\Customer\Api\Data\AttributeMetadataInterface as AttributeMetadata;
+
+class Columns extends \Magento\Ui\Component\Listing\Columns
+{
+    /**
+     * @var int
+     */
+    protected $columnSortOrder;
+
+    /**
+     * @var AttributeRepository
+     */
+    protected $attributeRepository;
+
+    /**
+     * @param ContextInterface $context
+     * @param ColumnFactory $columnFactory
+     * @param AttributeRepository $attributeRepository
+     * @param array $components
+     * @param array $data
+     */
+    public function __construct(
+        ContextInterface $context,
+        ColumnFactory $columnFactory,
+        AttributeRepository $attributeRepository,
+        array $components = [],
+        array $data = []
+    ) {
+        parent::__construct($context, $components, $data);
+        $this->columnFactory = $columnFactory;
+        $this->attributeRepository = $attributeRepository;
+    }
+
+    /**
+     * @return int
+     */
+    protected function getDefaultSortOrder()
+    {
+        $max = 0;
+        foreach ($this->components as $component) {
+            $config = $component->getData('config');
+            if (isset($config['sortOrder']) && $config['sortOrder'] > $max) {
+                $max = $config['sortOrder'];
+            }
+        }
+        return ++$max;
+    }
+
+    /**
+     * Update actions column sort order
+     *
+     * @return void
+     */
+    protected function updateActionColumnSortOrder()
+    {
+        if (isset($this->components['actions'])) {
+            $component = $this->components['actions'];
+            $component->setData(
+                'config',
+                array_merge($component->getData('config'), ['sortOrder' => ++$this->columnSortOrder])
+            );
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function prepare()
+    {
+        $this->columnSortOrder = $this->getDefaultSortOrder();
+        foreach ($this->attributeRepository->getList() as $newAttributeCode => $attributeData) {
+            if (isset($this->components[$newAttributeCode])) {
+                $this->updateColumn($attributeData, $newAttributeCode);
+            } elseif (!$attributeData[AttributeMetadata::BACKEND_TYPE] != 'static'
+                && $attributeData[AttributeMetadata::IS_USED_IN_GRID]
+            ) {
+                $this->addColumn($attributeData, $newAttributeCode);
+            }
+        }
+        $this->updateActionColumnSortOrder();
+        parent::prepare();
+    }
+
+    /**
+     * @param array $attributeData
+     * @param string $columnName
+     * @return void
+     */
+    public function addColumn(array $attributeData, $columnName)
+    {
+        $config['sortOrder'] = ++$this->columnSortOrder;
+        $column = $this->columnFactory->create($attributeData, $columnName, $this->getContext(), $config);
+        $column->prepare();
+        $this->addComponent($attributeData[AttributeMetadata::ATTRIBUTE_CODE], $column);
+    }
+
+    /**
+     * @param array $attributeData
+     * @param string $newAttributeCode
+     * @return void
+     */
+    public function updateColumn(array $attributeData, $newAttributeCode)
+    {
+        $component = $this->components[$attributeData[AttributeMetadata::ATTRIBUTE_CODE]];
+
+        if ($attributeData[AttributeMetadata::BACKEND_TYPE] != 'static') {
+            if ($attributeData[AttributeMetadata::IS_USED_IN_GRID]) {
+                $config = array_merge(
+                    $component->getData('config'),
+                    [
+                        'name' => $newAttributeCode,
+                        'dataType' => $attributeData[AttributeMetadata::BACKEND_TYPE],
+                        'visible' => $attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID]
+                    ]
+                );
+                $component->setData('config', $config);
+            }
+        } else {
+            $component->setData(
+                'config',
+                array_merge(
+                    $component->getData('config'),
+                    ['visible' => $attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID]]
+                )
+            );
+        }
+    }
+}
diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Filters.php b/app/code/Magento/Customer/Ui/Component/Listing/Filters.php
new file mode 100644
index 0000000000000000000000000000000000000000..2e0816d079729756e70f826148fcb86c66fd3835
--- /dev/null
+++ b/app/code/Magento/Customer/Ui/Component/Listing/Filters.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Ui\Component\Listing;
+
+use Magento\Customer\Api\Data\AttributeMetadataInterface as AttributeMetadata;
+
+class Filters extends \Magento\Ui\Component\Filters
+{
+    /**
+     * @param \Magento\Framework\View\Element\UiComponent\ContextInterface $context
+     * @param \Magento\Customer\Ui\Component\FilterFactory $filterFactory
+     * @param AttributeRepository $attributeRepository
+     * @param array $components
+     * @param array $data
+     */
+    public function __construct(
+        \Magento\Framework\View\Element\UiComponent\ContextInterface $context,
+        \Magento\Customer\Ui\Component\FilterFactory $filterFactory,
+        \Magento\Customer\Ui\Component\Listing\AttributeRepository $attributeRepository,
+        array $components = [],
+        array $data = []
+    ) {
+        parent::__construct($context, $components, $data);
+        $this->filterFactory = $filterFactory;
+        $this->attributeRepository = $attributeRepository;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function prepare()
+    {
+        /** @var \Magento\Customer\Model\Attribute $attribute */
+        foreach ($this->attributeRepository->getList() as $attributeCode => $attributeData) {
+            if (!isset($this->components[$attributeCode])) {
+                if (!$attributeData[AttributeMetadata::BACKEND_TYPE] != 'static'
+                    && $attributeData[AttributeMetadata::IS_USED_IN_GRID]
+                    && $attributeData[AttributeMetadata::IS_FILTERABLE_IN_GRID]
+                ) {
+                    $filter = $this->filterFactory->create($attributeData, $this->getContext());
+                    $filter->prepare();
+                    $this->addComponent($attributeCode, $filter);
+                }
+            } elseif ($attributeData[AttributeMetadata::IS_USED_IN_GRID]
+                && !$attributeData[AttributeMetadata::IS_FILTERABLE_IN_GRID]
+            ) {
+                unset($this->components[$attributeCode]);
+            }
+        }
+        parent::prepare();
+    }
+}
diff --git a/app/code/Magento/Customer/etc/crontab.xml b/app/code/Magento/Customer/etc/crontab.xml
index 21b4e0f9824f599dcd5448310bce8c37a118d5ef..26f1056f2d72444afdac1a44c715fcdb72a9b3c8 100644
--- a/app/code/Magento/Customer/etc/crontab.xml
+++ b/app/code/Magento/Customer/etc/crontab.xml
@@ -11,4 +11,9 @@
             <schedule>0 0 * * *</schedule>
         </job>
     </group>
+    <group id="index">
+        <job name="update_last_visit_at" instance="Magento\Customer\Model\Observer\Grid" method="syncCustomerGrid">
+            <schedule>*/5 * * * *</schedule>
+        </job>
+    </group>
 </config>
diff --git a/app/code/Magento/Customer/etc/di.xml b/app/code/Magento/Customer/etc/di.xml
index f6197ce876ddc3c4121bd1574856f77f43af35d1..3deee7dcbfb976e58129d55da08df24aa318f276 100644
--- a/app/code/Magento/Customer/etc/di.xml
+++ b/app/code/Magento/Customer/etc/di.xml
@@ -37,6 +37,10 @@
                 type="Magento\Customer\Model\Metadata\CustomerCachedMetadata" />
     <preference for="Magento\Customer\Api\AddressMetadataInterface"
                 type="Magento\Customer\Model\Metadata\AddressCachedMetadata" />
+    <preference for="Magento\Customer\Api\CustomerMetadataManagementInterface"
+                type="Magento\Customer\Model\Metadata\CustomerMetadataManagement" />
+    <preference for="Magento\Customer\Api\AddressMetadataManagementInterface"
+                type="Magento\Customer\Model\Metadata\AddressMetadataManagement" />
     <type name="Magento\Customer\Model\Session">
         <arguments>
             <argument name="configShare" xsi:type="object">Magento\Customer\Model\Config\Share\Proxy</argument>
@@ -168,13 +172,136 @@
             <argument name="entitySnapshot" xsi:type="object">EavVersionControlSnapshot</argument>
         </arguments>
     </type>
+    <virtualType name="Magento\Customer\Model\Resource\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult">
+        <arguments>
+            <argument name="mainTable" xsi:type="string">customer_grid_flat</argument>
+            <argument name="resourceModel" xsi:type="string">Magento\Customer\Model\Resource\Customer</argument>
+        </arguments>
+    </virtualType>
     <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
         <arguments>
             <argument name="collections" xsi:type="array">
+                <item name="customer_listing_data_source" xsi:type="string">Magento\Customer\Model\Resource\Grid\Collection</item>
                 <item name="customer_online_grid_data_source" xsi:type="string">Magento\Customer\Model\Resource\Online\Grid\Collection</item>
             </argument>
         </arguments>
     </type>
+    <virtualType name="CustomerNameHandler" type="Magento\Framework\Indexer\Handler\ConcatHandler">
+        <arguments>
+            <argument name="concatExpression" xsi:type="object">CustomerNameExpression</argument>
+        </arguments>
+    </virtualType>
+    <virtualType name="ShippingAddressHandler" type="Magento\Framework\Indexer\Handler\ConcatHandler">
+        <arguments>
+            <argument name="concatExpression" xsi:type="object">ShippingAddressExpression</argument>
+        </arguments>
+    </virtualType>
+    <virtualType name="BillingAddressHandler" type="Magento\Framework\Indexer\Handler\ConcatHandler">
+        <arguments>
+            <argument name="concatExpression" xsi:type="object">BillingAddressExpression</argument>
+        </arguments>
+    </virtualType>
+    <virtualType name="LastVisitAtHandler" type="Magento\Framework\Indexer\Handler\ConcatHandler">
+        <arguments>
+            <argument name="concatExpression" xsi:type="object">LastVisitAtSubSelect</argument>
+        </arguments>
+    </virtualType>
+    <virtualType name="LastVisitAtSubSelect" type="Magento\Framework\DB\Sql\LookupExpression">
+        <arguments>
+            <argument name="targetTable" xsi:type="string">customer_visitor</argument>
+            <argument name="targetColumn" xsi:type="string">last_visit_at</argument>
+            <argument name="referenceColumns" xsi:type="array">
+                <item name="customer_id" xsi:type="array">
+                    <item name="tableAlias" xsi:type="string">e</item>
+                    <item name="columnName" xsi:type="string">entity_id</item>
+                </item>
+            </argument>
+            <argument name="sortOrder" xsi:type="array">
+                <item name="DESC" xsi:type="string">last_visit_at</item>
+            </argument>
+        </arguments>
+    </virtualType>
+    <virtualType name="CustomerNameExpression" type="Magento\Framework\DB\Sql\ConcatExpression">
+        <arguments>
+            <argument name="tableName" xsi:type="string">e</argument>
+            <argument name="columns" xsi:type="array">
+                <item name="prefix" xsi:type="array">
+                    <item name="tableAlias" xsi:type="string">e</item>
+                    <item name="columnName" xsi:type="string">prefix</item>
+                </item>
+                <item name="firstname" xsi:type="array">
+                    <item name="tableAlias" xsi:type="string">e</item>
+                    <item name="columnName" xsi:type="string">firstname</item>
+                </item>
+                <item name="middlename" xsi:type="array">
+                    <item name="tableAlias" xsi:type="string">e</item>
+                    <item name="columnName" xsi:type="string">middlename</item>
+                </item>
+                <item name="lastname" xsi:type="array">
+                    <item name="tableAlias" xsi:type="string">e</item>
+                    <item name="columnName" xsi:type="string">lastname</item>
+                </item>
+                <item name="suffix" xsi:type="array">
+                    <item name="tableAlias" xsi:type="string">e</item>
+                    <item name="columnName" xsi:type="string">suffix</item>
+                </item>
+            </argument>
+        </arguments>
+    </virtualType>
+    <virtualType name="ShippingAddressExpression" type="Magento\Framework\DB\Sql\ConcatExpression">
+        <arguments>
+            <argument name="columns" xsi:type="array">
+                <item name="prefix" xsi:type="array">
+                    <item name="tableAlias" xsi:type="string">shipping</item>
+                    <item name="columnName" xsi:type="string">street</item>
+                </item>
+                <item name="firstname" xsi:type="array">
+                    <item name="tableAlias" xsi:type="string">shipping</item>
+                    <item name="columnName" xsi:type="string">city</item>
+                </item>
+                <item name="middlename" xsi:type="array">
+                    <item name="tableAlias" xsi:type="string">shipping</item>
+                    <item name="columnName" xsi:type="string">region</item>
+                </item>
+                <item name="lastname" xsi:type="array">
+                    <item name="tableAlias" xsi:type="string">shipping</item>
+                    <item name="columnName" xsi:type="string">postcode</item>
+                </item>
+            </argument>
+        </arguments>
+    </virtualType>
+    <virtualType name="BillingAddressExpression" type="Magento\Framework\DB\Sql\ConcatExpression">
+        <arguments>
+            <argument name="columns" xsi:type="array">
+                <item name="prefix" xsi:type="array">
+                    <item name="tableAlias" xsi:type="string">billing</item>
+                    <item name="columnName" xsi:type="string">street</item>
+                </item>
+                <item name="firstname" xsi:type="array">
+                    <item name="tableAlias" xsi:type="string">billing</item>
+                    <item name="columnName" xsi:type="string">city</item>
+                </item>
+                <item name="middlename" xsi:type="array">
+                    <item name="tableAlias" xsi:type="string">billing</item>
+                    <item name="columnName" xsi:type="string">region</item>
+                </item>
+                <item name="lastname" xsi:type="array">
+                    <item name="tableAlias" xsi:type="string">billing</item>
+                    <item name="columnName" xsi:type="string">postcode</item>
+                </item>
+            </argument>
+        </arguments>
+    </virtualType>
+    <type name="Magento\Customer\Model\Indexer\AttributeProvider">
+        <arguments>
+            <argument name="collection" xsi:type="object" shared="false">Magento\Customer\Model\Resource\Attribute\Collection</argument>
+        </arguments>
+    </type>
+    <type name="Magento\Customer\Model\Indexer\Address\AttributeProvider">
+        <arguments>
+            <argument name="collection" xsi:type="object" shared="false">Magento\Customer\Model\Resource\Address\Attribute\Collection</argument>
+        </arguments>
+    </type>
     <type name="Magento\Customer\Model\Resource\Online\Grid\Collection">
         <arguments>
             <argument name="mainTable" xsi:type="string">customer_visitor</argument>
diff --git a/app/code/Magento/Customer/etc/indexer.xml b/app/code/Magento/Customer/etc/indexer.xml
new file mode 100644
index 0000000000000000000000000000000000000000..093bb0b559fe3d052d8b5bed32e3ee95f2769600
--- /dev/null
+++ b/app/code/Magento/Customer/etc/indexer.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Indexer/etc/indexer.xsd">
+    <indexer id="customer_grid" view_id="dummy" class="Magento\Framework\Indexer\Action\Entity" primary="customer">
+        <title translate="true">Customer Grid</title>
+        <description translate="true">Rebuild Customer grid index</description>
+
+        <fieldset name="customer" source="Magento\Customer\Model\Resource\Customer\Collection"
+                  provider="Magento\Customer\Model\Indexer\AttributeProvider">
+            <field name="name" xsi:type="searchable" dataType="text" handler="CustomerNameHandler"/>
+            <field name="email" xsi:type="searchable" dataType="varchar"/>
+            <field name="group_id" xsi:type="filterable" dataType="int"/>
+            <field name="created_at" xsi:type="filterable" dataType="timestamp"/>
+            <field name="website_id" xsi:type="filterable" dataType="int"/>
+            <field name="confirmation" xsi:type="filterable" dataType="int"/>
+            <field name="created_in" xsi:type="filterable" dataType="text"/>
+            <field name="dob" xsi:type="filterable" dataType="date"/>
+            <field name="gender" xsi:type="filterable" dataType="int"/>
+            <field name="taxvat" xsi:type="searchable" dataType="varchar"/>
+            <field name="last_visit_at" xsi:type="filterable" dataType="datetime" handler="LastVisitAtHandler"/>
+        </fieldset>
+
+        <fieldset name="shipping" source="Magento\Customer\Model\Resource\Address\Collection">
+            <reference fieldset="customer" from="entity_id" to="default_shipping"/>
+            <field name="full" xsi:type="searchable" dataType="text" handler="ShippingAddressHandler"/>
+        </fieldset>
+
+        <fieldset name="billing" source="Magento\Customer\Model\Resource\Address\Collection"
+                  provider="Magento\Customer\Model\Indexer\Address\AttributeProvider">
+            <reference fieldset="customer" from="entity_id" to="default_billing"/>
+            <field name="full" xsi:type="searchable" dataType="text" handler="BillingAddressHandler"/>
+            <field name="telephone" xsi:type="searchable" dataType="varchar"/>
+            <field name="postcode" xsi:type="searchable" dataType="varchar"/>
+            <field name="country_id" xsi:type="filterable" dataType="varchar"/>
+            <field name="region" xsi:type="searchable" dataType="varchar"/>
+            <field name="region_id" xsi:type="filterable" dataType="int"/>
+            <field name="street" xsi:type="searchable" dataType="varchar"/>
+            <field name="city" xsi:type="searchable" dataType="varchar"/>
+            <field name="fax" xsi:type="searchable" dataType="varchar"/>
+            <field name="vat_id" xsi:type="searchable" dataType="varchar"/>
+            <field name="company" xsi:type="searchable" dataType="varchar"/>
+        </fieldset>
+
+        <saveHandler class="Magento\Framework\Indexer\SaveHandler\Grid"/>
+        <structure class="Magento\Framework\Indexer\GridStructure"/>
+    </indexer>
+</config>
diff --git a/app/code/Magento/Customer/etc/module.xml b/app/code/Magento/Customer/etc/module.xml
index 33f923e05015b2ac6618f497ca5ea129be68bb74..2c2e69131946517742d8062d6c7f9b14290140d6 100644
--- a/app/code/Magento/Customer/etc/module.xml
+++ b/app/code/Magento/Customer/etc/module.xml
@@ -6,7 +6,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Customer" setup_version="2.0.0.1">
+    <module name="Magento_Customer" setup_version="2.0.1">
         <sequence>
             <module name="Magento_Eav"/>
             <module name="Magento_Directory"/>
diff --git a/app/code/Magento/Customer/etc/mview.xml b/app/code/Magento/Customer/etc/mview.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bdb6d2b667fb63dfa5fb39c9900a5e556ba10f38
--- /dev/null
+++ b/app/code/Magento/Customer/etc/mview.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Mview/etc/mview.xsd">
+    <view id="dummy" class="Magento\Customer\Model\Indexer\Mview\Dummy" group="indexer"/>
+</config>
diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_grid.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_grid.xml
deleted file mode 100644
index 8c0352d29311f81df89b4910450521bacc877d49..0000000000000000000000000000000000000000
--- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_grid.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0"?>
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/layout_generic.xsd">
-    <update handle="formkey"/>
-    <update handle="customer_index_grid_block"/>
-    <container name="root">
-        <block class="Magento\Backend\Block\Widget\Grid\Container" name="admin.block.customer.grid.container" template="Magento_Backend::widget/grid/container/empty.phtml"/>
-    </container>
-</layout>
diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_grid_block.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_grid_block.xml
deleted file mode 100644
index 2deaefacb01aa8309d077714fd7a684a206f7bd5..0000000000000000000000000000000000000000
--- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_grid_block.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
-    <body>
-        <referenceBlock name="admin.block.customer.grid.container">
-            <block class="Magento\Backend\Block\Widget\Grid" name="admin.block.customer.grid" as="grid">
-                <arguments>
-                    <argument name="id" xsi:type="string">customerGrid</argument>
-                    <argument name="dataSource" xsi:type="object">Magento\Customer\Model\Resource\Customer\Grid\ServiceCollection</argument>
-                    <argument name="default_sort" xsi:type="string">entity_id</argument>
-                    <argument name="default_dir" xsi:type="string">asc</argument>
-                    <argument name="save_parameters_in_session" xsi:type="boolean">true</argument>
-                    <argument name="use_ajax" xsi:type="boolean">true</argument>
-                    <argument name="grid_url" xsi:type="url" path="customer/*/grid">
-                        <param name="_current">1</param>
-                    </argument>
-                </arguments>
-                <block class="Magento\Backend\Block\Widget\Grid\Massaction" name="admin.block.customer.grid.massaction" as="grid.massaction">
-                    <arguments>
-                        <argument name="massaction_id_field" xsi:type="string">entity_id</argument>
-                        <argument name="form_field_name" xsi:type="string">customer</argument>
-                        <argument name="options" xsi:type="array">
-                            <item name="delete" xsi:type="array">
-                                <item name="label" xsi:type="string" translate="true">Delete</item>
-                                <item name="url" xsi:type="string">customer/*/massDelete</item>
-                                <item name="confirm" xsi:type="string" translate="true">Are you sure you want to delete?</item>
-                            </item>
-                            <item name="newsletter_subscribe" xsi:type="array">
-                                <item name="label" xsi:type="string" translate="true">Subscribe to Newsletter</item>
-                                <item name="url" xsi:type="string">customer/*/massSubscribe</item>
-                            </item>
-                            <item name="newsletter_unsubscribe" xsi:type="array">
-                                <item name="label" xsi:type="string" translate="true">Unsubscribe from Newsletter</item>
-                                <item name="url" xsi:type="string">customer/*/massUnsubscribe</item>
-                            </item>
-                            <item name="assign_group" xsi:type="array">
-                                <item name="label" xsi:type="string" translate="true">Assign a Customer Group</item>
-                                <item name="url" xsi:type="string">customer/*/massAssignGroup</item>
-                                <item name="block_name" xsi:type="string">grid.groups</item>
-                            </item>
-                        </argument>
-                    </arguments>
-                    <block class="Magento\Backend\Block\Widget\Grid\Massaction\Additional" name="admin.block.customer.grid.groups.massactions" as="grid.groups">
-                        <arguments>
-                            <argument name="fields" xsi:type="array">
-                                <item name="visibility" xsi:type="array">
-                                    <item name="name" xsi:type="string">group</item>
-                                    <item name="type" xsi:type="string">select</item>
-                                    <item name="class" xsi:type="string">required-entry</item>
-                                    <item name="label" xsi:type="string" translate="true">Group</item>
-                                    <item name="values" xsi:type="string">Magento\Customer\Model\Config\Source\Group</item>
-                                </item>
-                            </argument>
-                        </arguments>
-                    </block>
-                </block>
-                <block class="Magento\Backend\Block\Widget\Grid\ColumnSet" name="admin.block.customer.grid.columnSet" as="grid.columnSet">
-                    <arguments>
-                        <argument name="rowUrl" xsi:type="array">
-                            <item name="path" xsi:type="string">customer/*/edit</item>
-                            <item name="extraParamsTemplate" xsi:type="array">
-                                <item name="id" xsi:type="string">getId</item>
-                            </item>
-                        </argument>
-                    </arguments>
-                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="entity_id">
-                        <arguments>
-                            <argument name="header" xsi:type="string" translate="true">ID</argument>
-                            <argument name="type" xsi:type="string">number</argument>
-                            <argument name="id" xsi:type="string">entity_id</argument>
-                            <argument name="index" xsi:type="string">entity_id</argument>
-                        </arguments>
-                    </block>
-                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="name">
-                        <arguments>
-                            <argument name="header" xsi:type="string" translate="true">Name</argument>
-                            <argument name="index" xsi:type="string">name</argument>
-                        </arguments>
-                    </block>
-                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="email">
-                        <arguments>
-                            <argument name="header" xsi:type="string" translate="true">Email</argument>
-                            <argument name="index" xsi:type="string">email</argument>
-                        </arguments>
-                    </block>
-                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="group">
-                        <arguments>
-                            <argument name="header" xsi:type="string" translate="true">Group</argument>
-                            <argument name="index" xsi:type="string">group_id</argument>
-                            <argument name="type" xsi:type="string">options</argument>
-                            <argument name="options" xsi:type="options" model="Magento\Customer\Model\Config\Source\Group\Multiselect"/>
-                        </arguments>
-                    </block>
-                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="billing_telephone">
-                        <arguments>
-                            <argument name="header" xsi:type="string" translate="true">Phone</argument>
-                            <argument name="index" xsi:type="string">billing_telephone</argument>
-                            <argument name="column_css_class" xsi:type="string">col-phone</argument>
-                            <argument name="header_css_class" xsi:type="string">col-phone</argument>
-                        </arguments>
-                    </block>
-                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="billing_postcode">
-                        <arguments>
-                            <argument name="header" xsi:type="string" translate="true">ZIP</argument>
-                            <argument name="index" xsi:type="string">billing_postcode</argument>
-                        </arguments>
-                    </block>
-                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="billing_country_id">
-                        <arguments>
-                            <argument name="header" xsi:type="string" translate="true">Country</argument>
-                            <argument name="index" xsi:type="string">billing_country_id</argument>
-                            <argument name="type" xsi:type="string">options</argument>
-                            <argument name="options" xsi:type="options" model="Magento\Config\Model\Config\Source\Locale\Country"/>
-                        </arguments>
-                    </block>
-                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="billing_region">
-                        <arguments>
-                            <argument name="header" xsi:type="string" translate="true">State/Province</argument>
-                            <argument name="index" xsi:type="string">billing_region</argument>
-                        </arguments>
-                    </block>
-                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="customer_since">
-                        <arguments>
-                            <argument name="header" xsi:type="string" translate="true">Customer Since</argument>
-                            <argument name="type" xsi:type="string">datetime</argument>
-                            <argument name="index" xsi:type="string">created_at</argument>
-                            <argument name="gmtoffset" xsi:type="boolean">true</argument>
-                        </arguments>
-                    </block>
-                    <block class="Magento\Backend\Block\Widget\Grid\Column\Multistore" as="website_id">
-                        <arguments>
-                            <argument name="header" xsi:type="string" translate="true">Web Site</argument>
-                            <argument name="column_css_class" xsi:type="string">col-store</argument>
-                            <argument name="header_css_class" xsi:type="string">col-store</argument>
-                            <argument name="type" xsi:type="string">options</argument>
-                            <argument name="options" xsi:type="options" model="Magento\Config\Model\Config\Source\Website\AdminOptionHash"/>
-                            <argument name="index" xsi:type="string">website_id</argument>
-                        </arguments>
-                    </block>
-                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="action" acl="Magento_Customer::customer">
-                        <arguments>
-                            <argument name="id" xsi:type="string">action</argument>
-                            <argument name="header" xsi:type="string" translate="true">Action</argument>
-                            <argument name="type" xsi:type="string">action</argument>
-                            <argument name="getter" xsi:type="string">getId</argument>
-                            <argument name="filter" xsi:type="boolean">false</argument>
-                            <argument name="sortable" xsi:type="boolean">false</argument>
-                            <argument name="index" xsi:type="string">stores</argument>
-                            <argument name="is_system" xsi:type="boolean">true</argument>
-                            <argument name="actions" xsi:type="array">
-                                <item name="view_action" xsi:type="array">
-                                    <item name="caption" xsi:type="string" translate="true">Edit</item>
-                                    <item name="url" xsi:type="array">
-                                        <item name="base" xsi:type="string">customer/*/edit</item>
-                                    </item>
-                                    <item name="field" xsi:type="string">id</item>
-                                </item>
-                            </argument>
-                            <argument name="header_css_class" xsi:type="string">col-actions</argument>
-                            <argument name="column_css_class" xsi:type="string">col-actions</argument>
-                        </arguments>
-                    </block>
-                </block>
-            </block>
-        </referenceBlock>
-    </body>
-</page>
diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_index.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_index.xml
index edd047e00e5234f419cd416c1b808cda1909e7ce..b45c461ad53a8e9c886e463861d6b4217a0ea8a1 100644
--- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_index.xml
+++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_index.xml
@@ -7,11 +7,9 @@
 -->
 <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
     <update handle="formkey"/>
-    <update handle="customer_index_grid_block"/>
     <body>
         <referenceContainer name="content">
-            <block class="Magento\Customer\Block\Adminhtml\Customer" name="admin.block.customer.grid.container">
-        </block>
+            <uiComponent name="customer_listing"/>
         </referenceContainer>
     </body>
 </page>
diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5a8646470b015636ec2e90f0f03e3659dfd7c5b2
--- /dev/null
+++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml
@@ -0,0 +1,694 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Ui/etc/ui_configuration.xsd">
+    <argument name="data" xsi:type="array">
+        <item name="js_config" xsi:type="array">
+            <item name="provider" xsi:type="string">customer_listing.customer_listing_data_source</item>
+            <item name="deps" xsi:type="string">customer_listing.customer_listing_data_source</item>
+        </item>
+        <item name="spinner" xsi:type="string">customer_columns</item>
+        <item name="buttons" xsi:type="array">
+            <item name="add" xsi:type="array">
+                <item name="name" xsi:type="string">add</item>
+                <item name="label" xsi:type="string" translate="true">Add New Customer</item>
+                <item name="class" xsi:type="string">primary</item>
+                <item name="url" xsi:type="string">*/*/new</item>
+            </item>
+        </item>
+    </argument>
+    <dataSource name="customer_listing_data_source">
+        <argument name="dataProvider" xsi:type="configurableObject">
+            <argument name="class" xsi:type="string">Magento\Customer\Ui\Component\DataProvider</argument>
+            <argument name="name" xsi:type="string">customer_listing_data_source</argument>
+            <argument name="primaryFieldName" xsi:type="string">entity_id</argument>
+            <argument name="requestFieldName" xsi:type="string">id</argument>
+            <argument name="data" xsi:type="array">
+                <item name="config" xsi:type="array">
+                    <item name="update_url" xsi:type="url" path="mui/index/render"/>
+                </item>
+            </argument>
+        </argument>
+        <argument name="data" xsi:type="array">
+            <item name="js_config" xsi:type="array">
+                <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
+            </item>
+        </argument>
+    </dataSource>
+    <container name="listing_top">
+        <argument name="data" xsi:type="array">
+            <item name="config" xsi:type="array">
+                <item name="template" xsi:type="string">ui/grid/toolbar</item>
+            </item>
+        </argument>
+        <bookmark name="bookmarks">
+            <argument name="data" xsi:type="array">
+                <item name="config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/controls/bookmarks/bookmarks</item>
+                    <item name="displayArea" xsi:type="string">dataGridActions</item>
+                    <item name="storageConfig" xsi:type="array">
+                        <item name="saveUrl" xsi:type="url" path="mui/bookmark/save"/>
+                        <item name="deleteUrl" xsi:type="url" path="mui/bookmark/delete"/>
+                        <item name="namespace" xsi:type="string">customer_listing</item>
+                    </item>
+                </item>
+            </argument>
+        </bookmark>
+        <container name="columns_controls">
+            <argument name="data" xsi:type="array">
+                <item name="config" xsi:type="array">
+                    <item name="columnsData" xsi:type="array">
+                        <item name="provider" xsi:type="string">customer_listing.customer_listing.customer_columns</item>
+                    </item>
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/controls/columns</item>
+                    <item name="displayArea" xsi:type="string">dataGridActions</item>
+                </item>
+            </argument>
+        </container>
+        <exportButton name="export_button">
+            <argument name="data" xsi:type="array">
+                <item name="config" xsi:type="array">
+                    <item name="selectProvider" xsi:type="string">customer_listing.customer_listing.customer_columns.ids</item>
+                </item>
+            </argument>
+        </exportButton>
+        <filterSearch name="fulltext">
+            <argument name="data" xsi:type="array">
+                <item name="config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/search/search</item>
+                    <item name="displayArea" xsi:type="string">dataGridFilters</item>
+                    <item name="provider" xsi:type="string">customer_listing.customer_listing_data_source</item>
+                    <item name="chipsProvider" xsi:type="string">customer_listing.customer_listing.listing_top.listing_filters_chips</item>
+                    <item name="storageConfig" xsi:type="array">
+                        <item name="provider" xsi:type="string">customer_listing.customer_listing.listing_top.bookmarks</item>
+                        <item name="namespace" xsi:type="string">current.search</item>
+                    </item>
+                </item>
+            </argument>
+        </filterSearch>
+        <filters name="listing_filters" class="Magento\Customer\Ui\Component\Listing\Filters">
+            <argument name="data" xsi:type="array">
+                <item name="config" xsi:type="array">
+                    <item name="displayArea" xsi:type="string">dataGridFilters</item>
+                    <item name="dataScope" xsi:type="string">filters</item>
+                    <item name="storageConfig" xsi:type="array">
+                        <item name="provider" xsi:type="string">customer_listing.customer_listing.listing_top.bookmarks</item>
+                        <item name="namespace" xsi:type="string">current.filters</item>
+                    </item>
+                    <item name="childDefaults" xsi:type="array">
+                        <item name="provider" xsi:type="string">customer_listing.customer_listing.listing_top.listing_filters</item>
+                        <item name="imports" xsi:type="array">
+                            <item name="visible" xsi:type="string">customer_listing.customer_listing.listing_top.bookmarks:current.columns.${ $.index }.visible</item>
+                        </item>
+                    </item>
+                </item>
+            </argument>
+            <filterRange name="entity_id">
+                <argument name="data" xsi:type="array">
+                    <item name="config" xsi:type="array">
+                        <item name="dataScope" xsi:type="string">entity_id</item>
+                        <item name="label" xsi:type="string" translate="true">ID</item>
+                        <item name="childDefaults" xsi:type="array">
+                            <item name="provider" xsi:type="string">customer_listing.customer_listing.listing_top.listing_filters</item>
+                        </item>
+                    </item>
+                </argument>
+                <filterInput name="from">
+                    <argument name="data" xsi:type="array">
+                        <item name="config" xsi:type="array">
+                            <item name="dataScope" xsi:type="string">from</item>
+                            <item name="label" xsi:type="string" translate="true">from</item>
+                            <item name="placeholder" xsi:type="string" translate="true">From</item>
+                        </item>
+                    </argument>
+                </filterInput>
+                <filterInput name="to">
+                    <argument name="data" xsi:type="array">
+                        <item name="config" xsi:type="array">
+                            <item name="dataScope" xsi:type="string">to</item>
+                            <item name="label" xsi:type="string" translate="true">to</item>
+                            <item name="placeholder" xsi:type="string" translate="true">To</item>
+                        </item>
+                    </argument>
+                </filterInput>
+            </filterRange>
+            <filterInput name="name">
+                <argument name="data" xsi:type="array">
+                    <item name="config" xsi:type="array">
+                        <item name="dataScope" xsi:type="string">name</item>
+                        <item name="label" xsi:type="string" translate="true">Name</item>
+                    </item>
+                </argument>
+            </filterInput>
+            <filterInput name="email">
+                <argument name="data" xsi:type="array">
+                    <item name="config" xsi:type="array">
+                        <item name="dataScope" xsi:type="string">email</item>
+                        <item name="label" xsi:type="string" translate="true">Email</item>
+                    </item>
+                </argument>
+            </filterInput>
+            <filterSelect name="group_id">
+                <argument name="optionsProvider" xsi:type="configurableObject">
+                    <argument name="class" xsi:type="string">Magento\Customer\Model\Config\Source\Group\Multiselect</argument>
+                </argument>
+                <argument name="data" xsi:type="array">
+                    <item name="config" xsi:type="array">
+                        <item name="dataScope" xsi:type="string">group_id</item>
+                        <item name="label" xsi:type="string" translate="true">Group</item>
+                        <item name="caption" xsi:type="string" translate="true">Select...</item>
+                    </item>
+                </argument>
+            </filterSelect>
+            <filterInput name="billing_telephone">
+                <argument name="data" xsi:type="array">
+                    <item name="config" xsi:type="array">
+                        <item name="dataScope" xsi:type="string">billing_telephone</item>
+                        <item name="label" xsi:type="string" translate="true">Phone</item>
+                    </item>
+                </argument>
+            </filterInput>
+            <filterInput name="billing_postcode">
+                <argument name="data" xsi:type="array">
+                    <item name="config" xsi:type="array">
+                        <item name="dataScope" xsi:type="string">billing_postcode</item>
+                        <item name="label" xsi:type="string" translate="true">ZIP</item>
+                    </item>
+                </argument>
+            </filterInput>
+            <filterSelect name="billing_country_id">
+                <argument name="optionsProvider" xsi:type="configurableObject">
+                    <argument name="class" xsi:type="string">Magento\Directory\Model\Resource\Country\Collection</argument>
+                </argument>
+                <argument name="data" xsi:type="array">
+                    <item name="config" xsi:type="array">
+                        <item name="dataScope" xsi:type="string">billing_country_id</item>
+                        <item name="label" xsi:type="string" translate="true">Country</item>
+                        <item name="caption" xsi:type="string" translate="true">Select...</item>
+                    </item>
+                </argument>
+            </filterSelect>
+            <filterInput name="billing_region">
+                <argument name="data" xsi:type="array">
+                    <item name="config" xsi:type="array">
+                        <item name="dataScope" xsi:type="string">billing_region</item>
+                        <item name="label" xsi:type="string" translate="true">State/Province</item>
+                    </item>
+                </argument>
+            </filterInput>
+            <filterRange name="created_at" class="Magento\Ui\Component\Filters\Type\DateRange">
+                <argument name="data" xsi:type="array">
+                    <item name="config" xsi:type="array">
+                        <item name="dataScope" xsi:type="string">created_at</item>
+                        <item name="label" xsi:type="string" translate="true">Customer Since</item>
+                        <item name="childDefaults" xsi:type="array">
+                            <item name="provider" xsi:type="string">customer_listing.customer_listing.listing_top.listing_filters</item>
+                        </item>
+                    </item>
+                </argument>
+                <filterDate name="from">
+                    <argument name="data" xsi:type="array">
+                        <item name="config" xsi:type="array">
+                            <item name="dataScope" xsi:type="string">from</item>
+                            <item name="label" xsi:type="string" translate="true">From</item>
+                            <item name="placeholder" xsi:type="string" translate="true">From</item>
+                            <item name="dateFormat" xsi:type="string" translate="true">MM/dd/YYYY</item>
+                        </item>
+                    </argument>
+                </filterDate>
+                <filterDate name="to">
+                    <argument name="data" xsi:type="array">
+                        <item name="config" xsi:type="array">
+                            <item name="dataScope" xsi:type="string">to</item>
+                            <item name="label" xsi:type="string" translate="true">To</item>
+                            <item name="placeholder" xsi:type="string" translate="true">To</item>
+                            <item name="dateFormat" xsi:type="string" translate="true">MM/dd/YYYY</item>
+                        </item>
+                    </argument>
+                </filterDate>
+            </filterRange>
+            <filterSelect name="website_id">
+                <argument name="optionsProvider" xsi:type="configurableObject">
+                    <argument name="class" xsi:type="string">Magento\Config\Model\Config\Source\Website</argument>
+                </argument>
+                <argument name="data" xsi:type="array">
+                    <item name="config" xsi:type="array">
+                        <item name="dataScope" xsi:type="string">website_id</item>
+                        <item name="label" xsi:type="string" translate="true">Website</item>
+                        <item name="caption" xsi:type="string" translate="true">Select...</item>
+                    </item>
+                </argument>
+            </filterSelect>
+        </filters>
+        <massaction name="listing_massaction">
+            <argument name="data" xsi:type="array">
+                <item name="config" xsi:type="array">
+                    <item name="selectProvider" xsi:type="string">customer_listing.customer_listing.customer_columns.ids</item>
+                    <item name="displayArea" xsi:type="string">bottom</item>
+                    <item name="actions" xsi:type="array">
+                        <item name="delete" xsi:type="array">
+                            <item name="type" xsi:type="string">delete</item>
+                            <item name="label" xsi:type="string" translate="true">Delete</item>
+                            <item name="url" xsi:type="string">customer/index/massDelete</item>
+                            <item name="confirm" xsi:type="array">
+                                <item name="title" xsi:type="string" translate="true">Delete items</item>
+                                <item name="message" xsi:type="string" translate="true">Are you sure you wan't to delete selected items?</item>
+                            </item>
+                        </item>
+                        <item name="subscribe" xsi:type="array">
+                            <item name="type" xsi:type="string">subscribe</item>
+                            <item name="label" xsi:type="string" translate="true">Subscribe to Newsletter</item>
+                            <item name="url" xsi:type="string">customer/index/massSubscribe</item>
+                        </item>
+                        <item name="unsubscribe" xsi:type="array">
+                            <item name="type" xsi:type="string">unsubscribe</item>
+                            <item name="label" xsi:type="string" translate="true">Unsubscribe from Newsletter</item>
+                            <item name="url" xsi:type="string">customer/index/massUnsubscribe</item>
+                        </item>
+                    </item>
+                    <item name="indexField" xsi:type="string">entity_id</item>
+                </item>
+            </argument>
+        </massaction>
+        <paging name="listing_paging">
+            <argument name="data" xsi:type="array">
+                <item name="config" xsi:type="array">
+                    <item name="storageConfig" xsi:type="array">
+                        <item name="provider" xsi:type="string">customer_listing.customer_listing.listing_top.bookmarks</item>
+                        <item name="namespace" xsi:type="string">current.paging</item>
+                    </item>
+                    <item name="selectProvider" xsi:type="string">customer_listing.customer_listing.customer_columns.ids</item>
+                    <item name="displayArea" xsi:type="string">bottom</item>
+                    <item name="options" xsi:type="array">
+                        <item name="20" xsi:type="array">
+                            <item name="value" xsi:type="number">20</item>
+                            <item name="label" xsi:type="string" translate="true">20</item>
+                        </item>
+                        <item name="30" xsi:type="array">
+                            <item name="value" xsi:type="number">30</item>
+                            <item name="label" xsi:type="string" translate="true">30</item>
+                        </item>
+                        <item name="50" xsi:type="array">
+                            <item name="value" xsi:type="number">50</item>
+                            <item name="label" xsi:type="string" translate="true">50</item>
+                        </item>
+                        <item name="100" xsi:type="array">
+                            <item name="value" xsi:type="number">100</item>
+                            <item name="label" xsi:type="string" translate="true">100</item>
+                        </item>
+                        <item name="200" xsi:type="array">
+                            <item name="value" xsi:type="number">200</item>
+                            <item name="label" xsi:type="string" translate="true">200</item>
+                        </item>
+                    </item>
+                </item>
+            </argument>
+        </paging>
+    </container>
+    <columns name="customer_columns" class="Magento\Customer\Ui\Component\Listing\Columns">
+        <argument name="data" xsi:type="array">
+            <item name="config" xsi:type="array">
+                <item name="storageConfig" xsi:type="array">
+                    <item name="provider" xsi:type="string">customer_listing.customer_listing.listing_top.bookmarks</item>
+                    <item name="namespace" xsi:type="string">current</item>
+                </item>
+                <item name="childDefaults" xsi:type="array">
+                    <item name="fieldAction" xsi:type="array">
+                        <item name="provider" xsi:type="string">customer_listing.customer_listing.customer_columns.actions</item>
+                        <item name="target" xsi:type="string">applyAction</item>
+                        <item name="params" xsi:type="array">
+                            <item name="0" xsi:type="string">edit</item>
+                            <item name="1" xsi:type="string">${ $.$data.rowIndex }</item>
+                        </item>
+                    </item>
+                    <item name="controlVisibility" xsi:type="boolean">true</item>
+                    <item name="storageConfig" xsi:type="array">
+                        <item name="provider" xsi:type="string">customer_listing.customer_listing.listing_top.bookmarks</item>
+                        <item name="root" xsi:type="string">columns.${ $.index }</item>
+                        <item name="namespace" xsi:type="string">current.${ $.storageConfig.root }</item>
+                    </item>
+                </item>
+            </item>
+        </argument>
+        <column name="ids" class="Magento\Ui\Component\MassAction\Columns\Column">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/multiselect</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="indexField" xsi:type="string">entity_id</item>
+                    <item name="controlVisibility" xsi:type="boolean">false</item>
+                    <item name="sortOrder" xsi:type="number">10</item>
+                </item>
+            </argument>
+        </column>
+        <column name="entity_id">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="sorting" xsi:type="string">asc</item>
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">ID</item>
+                    <item name="sortOrder" xsi:type="number">20</item>
+                </item>
+            </argument>
+        </column>
+        <column name="name">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Name</item>
+                    <item name="sortOrder" xsi:type="number">30</item>
+                </item>
+            </argument>
+        </column>
+        <column name="email">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Email</item>
+                    <item name="sortOrder" xsi:type="number">40</item>
+                </item>
+            </argument>
+        </column>
+        <column name="group_id" class="Magento\Customer\Ui\Component\Listing\Column\AttributeColumn">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Group</item>
+                    <item name="sortOrder" xsi:type="number">50</item>
+                </item>
+            </argument>
+        </column>
+        <column name="billing_telephone">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Phone</item>
+                    <item name="sortOrder" xsi:type="number">60</item>
+                </item>
+            </argument>
+        </column>
+        <column name="billing_postcode">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">ZIP</item>
+                    <item name="sortOrder" xsi:type="number">70</item>
+                </item>
+            </argument>
+        </column>
+        <column name="billing_country_id" class="Magento\Customer\Ui\Component\Listing\Column\AttributeColumn">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Country</item>
+                    <item name="sortOrder" xsi:type="number">80</item>
+                </item>
+            </argument>
+        </column>
+        <column name="billing_region">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">State/Province</item>
+                    <item name="sortOrder" xsi:type="number">90</item>
+                </item>
+            </argument>
+        </column>
+        <column name="created_at">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="dataType" xsi:type="string">date</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Customer Since</item>
+                    <item name="sortOrder" xsi:type="number">100</item>
+                </item>
+            </argument>
+        </column>
+        <column name="website_id" class="Magento\Customer\Ui\Component\Listing\Column\AttributeColumn">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Web Site</item>
+                    <item name="sortOrder" xsi:type="number">110</item>
+                </item>
+            </argument>
+        </column>
+        <column name="last_visit_at" >
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="visible" xsi:type="boolean">false</item>
+                    <item name="dataType" xsi:type="string">date</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Last Logged In</item>
+                    <item name="sortOrder" xsi:type="number">120</item>
+                </item>
+            </argument>
+        </column>
+        <column name="confirmation">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="visible" xsi:type="boolean">false</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Confirmed email</item>
+                    <item name="sortOrder" xsi:type="number">130</item>
+                </item>
+            </argument>
+        </column>
+        <column name="created_in">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="visible" xsi:type="boolean">false</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Account Created in</item>
+                    <item name="sortOrder" xsi:type="number">140</item>
+                </item>
+            </argument>
+        </column>
+        <column name="billing_full">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="visible" xsi:type="boolean">false</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Billing Address</item>
+                    <item name="sortOrder" xsi:type="number">150</item>
+                </item>
+            </argument>
+        </column>
+        <column name="shipping_full">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="visible" xsi:type="boolean">false</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Shipping Address</item>
+                    <item name="sortOrder" xsi:type="number">160</item>
+                </item>
+            </argument>
+        </column>
+        <column name="dob">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="visible" xsi:type="boolean">false</item>
+                    <item name="dataType" xsi:type="string">date</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Date Of Birth</item>
+                    <item name="sortOrder" xsi:type="number">170</item>
+                </item>
+            </argument>
+        </column>
+        <column name="taxvat">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="visible" xsi:type="boolean">false</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Tax VAT Number</item>
+                    <item name="sortOrder" xsi:type="number">180</item>
+                </item>
+            </argument>
+        </column>
+        <column name="gender" class="Magento\Customer\Ui\Component\Listing\Column\AttributeColumn">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="visible" xsi:type="boolean">false</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Gender</item>
+                    <item name="sortOrder" xsi:type="number">190</item>
+                </item>
+            </argument>
+        </column>
+        <column name="billing_street">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="visible" xsi:type="boolean">false</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Street Address</item>
+                    <item name="sortOrder" xsi:type="number">200</item>
+                </item>
+            </argument>
+        </column>
+        <column name="billing_city">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="visible" xsi:type="boolean">false</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">City</item>
+                    <item name="sortOrder" xsi:type="number">210</item>
+                </item>
+            </argument>
+        </column>
+        <column name="billing_fax">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="visible" xsi:type="boolean">false</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Fax</item>
+                    <item name="sortOrder" xsi:type="number">220</item>
+                </item>
+            </argument>
+        </column>
+        <column name="billing_vat_id">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="visible" xsi:type="boolean">false</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">VAT Number</item>
+                    <item name="sortOrder" xsi:type="number">230</item>
+                </item>
+            </argument>
+        </column>
+        <column name="billing_company">
+            <argument name="data" xsi:type="array">
+                <item name="js_config" xsi:type="array">
+                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
+                </item>
+                <item name="config" xsi:type="array">
+                    <item name="sortable" xsi:type="string">true</item>
+                    <item name="visible" xsi:type="boolean">false</item>
+                    <item name="dataType" xsi:type="string">text</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Company</item>
+                    <item name="sortOrder" xsi:type="number">240</item>
+                </item>
+            </argument>
+        </column>
+        <column name="actions" class="Magento\Customer\Ui\Component\Listing\Column\Actions">
+            <argument name="data" xsi:type="array">
+                <item name="config" xsi:type="array">
+                    <item name="draggable" xsi:type="boolean">false</item>
+                    <item name="dataType" xsi:type="string">actions</item>
+                    <item name="indexField" xsi:type="string">entity_id</item>
+                    <item name="align" xsi:type="string">left</item>
+                    <item name="label" xsi:type="string" translate="true">Action</item>
+                    <item name="data_type" xsi:type="string">actions</item>
+                    <item name="filterable" xsi:type="boolean">false</item>
+                    <item name="sortable" xsi:type="boolean">false</item>
+                </item>
+            </argument>
+        </column>
+    </columns>
+</listing>
diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php
index 54018f381b4ed3729338fdcc4125cd1fdae7ce89..1efc6e8346c5d69ab088ec50279ded522dcf9eca 100644
--- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php
+++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php
@@ -1041,11 +1041,22 @@ abstract class AbstractCollection extends AbstractDb implements SourceProviderIn
      * @return string
      */
     public function getRowIdFieldName()
+    {
+        return $this->getIdFieldName();
+    }
+
+    /**
+     * Id field name getter
+     *
+     * @return string
+     */
+    public function getIdFieldName()
     {
         if ($this->_idFieldName === null) {
             $this->_setIdFieldName($this->getEntity()->getIdFieldName());
         }
-        return $this->getIdFieldName();
+
+        return $this->_idFieldName;
     }
 
     /**
diff --git a/app/code/Magento/GroupedProduct/Test/Unit/Model/ProductTest.php b/app/code/Magento/GroupedProduct/Test/Unit/Model/ProductTest.php
index 04d7f729f8c86ad5a0c85435bfa266584cf3fbb1..05149794026455a9ddce54330fd987c474326f19 100644
--- a/app/code/Magento/GroupedProduct/Test/Unit/Model/ProductTest.php
+++ b/app/code/Magento/GroupedProduct/Test/Unit/Model/ProductTest.php
@@ -42,7 +42,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
     protected $stockItemFactoryMock;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $categoryIndexerMock;
 
@@ -97,7 +97,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
     private $website;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistryMock;
 
@@ -161,7 +161,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
      */
     public function setUp()
     {
-        $this->categoryIndexerMock = $this->getMockForAbstractClass('\Magento\Indexer\Model\IndexerInterface');
+        $this->categoryIndexerMock = $this->getMockForAbstractClass('\Magento\Framework\Indexer\IndexerInterface');
 
         $this->moduleManager = $this->getMock(
             'Magento\Framework\Module\Manager',
@@ -260,7 +260,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
         $storeManager->expects($this->any())
             ->method('getWebsite')
             ->will($this->returnValue($this->website));
-        $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false);
+        $this->indexerRegistryMock = $this->getMock('Magento\Framework\Indexer\IndexerRegistry', ['get'], [], '', false);
         $this->categoryRepository = $this->getMock('Magento\Catalog\Api\CategoryRepositoryInterface');
 
         $this->_catalogProduct = $this->getMock(
diff --git a/app/code/Magento/ImportExport/Model/Import.php b/app/code/Magento/ImportExport/Model/Import.php
index 4a42c4abab403d03097b7e1c219e3175409edc45..e46e82e6abe8dec9166d15e42f99c97508ed04c8 100644
--- a/app/code/Magento/ImportExport/Model/Import.php
+++ b/app/code/Magento/ImportExport/Model/Import.php
@@ -126,7 +126,7 @@ class Import extends \Magento\ImportExport\Model\AbstractModel
     protected $_uploaderFactory;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry
+     * @var \Magento\Framework\Indexer\IndexerRegistry
      */
     protected $indexerRegistry;
 
@@ -152,7 +152,7 @@ class Import extends \Magento\ImportExport\Model\AbstractModel
      * @param FileTransferFactory $httpFactory
      * @param \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory
      * @param Source\Import\Behavior\Factory $behaviorFactory
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      * @param History $importHistoryModel
      * @param \Magento\Framework\Stdlib\DateTime\DateTime
      * @param array $data
@@ -170,7 +170,7 @@ class Import extends \Magento\ImportExport\Model\AbstractModel
         \Magento\Framework\HTTP\Adapter\FileTransferFactory $httpFactory,
         \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory,
         \Magento\ImportExport\Model\Source\Import\Behavior\Factory $behaviorFactory,
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry,
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
         \Magento\ImportExport\Model\History $importHistoryModel,
         \Magento\Framework\Stdlib\DateTime\DateTime $localeDate,
         array $data = []
diff --git a/app/code/Magento/ImportExport/Test/Unit/Helper/ReportTest.php b/app/code/Magento/ImportExport/Test/Unit/Helper/ReportTest.php
index d73b7230d9bed5a5d2244686f5e2fff6f0f2ea97..deaed0a6d0d089240e47ff475f32a85deb8ed8bb 100644
--- a/app/code/Magento/ImportExport/Test/Unit/Helper/ReportTest.php
+++ b/app/code/Magento/ImportExport/Test/Unit/Helper/ReportTest.php
@@ -152,7 +152,7 @@ class ReportTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $indexerRegistry = $this->getMock('Magento\Indexer\Model\IndexerRegistry', [], [], '', false);
+        $indexerRegistry = $this->getMock('Magento\Framework\Indexer\IndexerRegistry', [], [], '', false);
         $importHistoryModel = $this->getMock('Magento\ImportExport\Model\History', [], [], '', false);
         $localeDate = $this->getMock('Magento\Framework\Stdlib\DateTime\DateTime', [], [], '', false);
         $import = new \Magento\ImportExport\Model\Import(
diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php b/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php
index 1083fc1e15acf27587b9ca58c8907411e1fcc5ea..66b249b836222e8adfd3ac148ff60f61d344f8de 100644
--- a/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php
+++ b/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php
@@ -59,7 +59,7 @@ class ImportTest extends \PHPUnit_Framework_TestCase
     protected $_uploaderFactory;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $indexerRegistry;
 
@@ -151,7 +151,7 @@ class ImportTest extends \PHPUnit_Framework_TestCase
         $this->_behaviorFactory = $this->getMockBuilder('\Magento\ImportExport\Model\Source\Import\Behavior\Factory')
             ->disableOriginalConstructor()
             ->getMock();
-        $this->indexerRegistry = $this->getMockBuilder('\Magento\Indexer\Model\IndexerRegistry')
+        $this->indexerRegistry = $this->getMockBuilder('\Magento\Framework\Indexer\IndexerRegistry')
             ->disableOriginalConstructor()
             ->getMock();
         $this->historyModel = $this->getMockBuilder('\Magento\ImportExport\Model\History')
diff --git a/app/code/Magento/ImportExport/composer.json b/app/code/Magento/ImportExport/composer.json
index 8a19a4779907eef1fc5e5aa4be5f47e4dd58c3d3..54ca6f4265ae5a3560aa0db2f42545ff791868f4 100644
--- a/app/code/Magento/ImportExport/composer.json
+++ b/app/code/Magento/ImportExport/composer.json
@@ -6,7 +6,6 @@
         "magento/module-store": "1.0.0-beta",
         "magento/module-backend": "1.0.0-beta",
         "magento/module-eav": "1.0.0-beta",
-        "magento/module-indexer": "1.0.0-beta",
         "magento/module-media-storage": "1.0.0-beta",
         "magento/framework": "1.0.0-beta",
         "ext-ctype": "*",
diff --git a/app/code/Magento/Indexer/Block/Backend/Grid/Column/Renderer/Status.php b/app/code/Magento/Indexer/Block/Backend/Grid/Column/Renderer/Status.php
index d108b27b83fafd0637776d17cf51e817f4127a3d..a8388ea8413ff9baee4ca1767b62d7b536d16138 100644
--- a/app/code/Magento/Indexer/Block/Backend/Grid/Column/Renderer/Status.php
+++ b/app/code/Magento/Indexer/Block/Backend/Grid/Column/Renderer/Status.php
@@ -18,15 +18,15 @@ class Status extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\Abstract
         $class = '';
         $text = '';
         switch ($this->_getValue($row)) {
-            case \Magento\Indexer\Model\Indexer\State::STATUS_INVALID:
+            case \Magento\Framework\Indexer\StateInterface::STATUS_INVALID:
                 $class = 'grid-severity-critical';
                 $text = __('Reindex required');
                 break;
-            case \Magento\Indexer\Model\Indexer\State::STATUS_VALID:
+            case \Magento\Framework\Indexer\StateInterface::STATUS_VALID:
                 $class = 'grid-severity-notice';
                 $text = __('Ready');
                 break;
-            case \Magento\Indexer\Model\Indexer\State::STATUS_WORKING:
+            case \Magento\Framework\Indexer\StateInterface::STATUS_WORKING:
                 $class = 'grid-severity-major';
                 $text = __('Processing');
                 break;
diff --git a/app/code/Magento/Indexer/Console/Command/AbstractIndexerManageCommand.php b/app/code/Magento/Indexer/Console/Command/AbstractIndexerManageCommand.php
index 2c7c12a3cfc71553fccf2aaee0a4612b6b77c0fb..6af8664c62a2b07f119e479494a6b5b247af2c2b 100644
--- a/app/code/Magento/Indexer/Console/Command/AbstractIndexerManageCommand.php
+++ b/app/code/Magento/Indexer/Console/Command/AbstractIndexerManageCommand.php
@@ -9,7 +9,7 @@ use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Output\OutputInterface;
 use Symfony\Component\Console\Input\InputOption;
 use Symfony\Component\Console\Input\InputArgument;
-use Magento\Indexer\Model\IndexerInterface;
+use Magento\Framework\Indexer\IndexerInterface;
 
 /**
  * An Abstract class for all Indexer related commands.
diff --git a/app/code/Magento/Indexer/Console/Command/IndexerStatusCommand.php b/app/code/Magento/Indexer/Console/Command/IndexerStatusCommand.php
index d02ee885ee4ca15ddb844ec70c4efdde38812868..830c36d0f9f3d74368aba9374be3106e39285d82 100644
--- a/app/code/Magento/Indexer/Console/Command/IndexerStatusCommand.php
+++ b/app/code/Magento/Indexer/Console/Command/IndexerStatusCommand.php
@@ -34,13 +34,13 @@ class IndexerStatusCommand extends AbstractIndexerManageCommand
         foreach ($indexers as $indexer) {
             $status = 'unknown';
             switch ($indexer->getStatus()) {
-                case \Magento\Indexer\Model\Indexer\State::STATUS_VALID:
+                case \Magento\Framework\Indexer\StateInterface::STATUS_VALID:
                     $status = 'Ready';
                     break;
-                case \Magento\Indexer\Model\Indexer\State::STATUS_INVALID:
+                case \Magento\Framework\Indexer\StateInterface::STATUS_INVALID:
                     $status = 'Reindex required';
                     break;
-                case \Magento\Indexer\Model\Indexer\State::STATUS_WORKING:
+                case \Magento\Framework\Indexer\StateInterface::STATUS_WORKING:
                     $status = 'Processing';
                     break;
             }
diff --git a/app/code/Magento/Indexer/Controller/Adminhtml/Indexer/MassChangelog.php b/app/code/Magento/Indexer/Controller/Adminhtml/Indexer/MassChangelog.php
index e39cc3cc5fa637a878dc5f41a87459dce58b3c9a..1ea64de8b75d606f5659da9ad0698066b7d94307 100644
--- a/app/code/Magento/Indexer/Controller/Adminhtml/Indexer/MassChangelog.php
+++ b/app/code/Magento/Indexer/Controller/Adminhtml/Indexer/MassChangelog.php
@@ -21,8 +21,8 @@ class MassChangelog extends \Magento\Indexer\Controller\Adminhtml\Indexer
         } else {
             try {
                 foreach ($indexerIds as $indexerId) {
-                    /** @var \Magento\Indexer\Model\IndexerInterface $model */
-                    $model = $this->_objectManager->get('Magento\Indexer\Model\IndexerRegistry')->get($indexerId);
+                    /** @var \Magento\Framework\Indexer\IndexerInterface $model */
+                    $model = $this->_objectManager->get('Magento\Framework\Indexer\IndexerRegistry')->get($indexerId);
                     $model->setScheduled(true);
                 }
                 $this->messageManager->addSuccess(
diff --git a/app/code/Magento/Indexer/Controller/Adminhtml/Indexer/MassOnTheFly.php b/app/code/Magento/Indexer/Controller/Adminhtml/Indexer/MassOnTheFly.php
index 27def97e6b15409dea0570d99eb3372d12e21322..fecf0df7a53d7936dbe11ab55e9d6228bd52b4de 100644
--- a/app/code/Magento/Indexer/Controller/Adminhtml/Indexer/MassOnTheFly.php
+++ b/app/code/Magento/Indexer/Controller/Adminhtml/Indexer/MassOnTheFly.php
@@ -21,8 +21,8 @@ class MassOnTheFly extends \Magento\Indexer\Controller\Adminhtml\Indexer
         } else {
             try {
                 foreach ($indexerIds as $indexerId) {
-                    /** @var \Magento\Indexer\Model\IndexerInterface $model */
-                    $model = $this->_objectManager->get('Magento\Indexer\Model\IndexerRegistry')->get($indexerId);
+                    /** @var \Magento\Framework\Indexer\IndexerInterface $model */
+                    $model = $this->_objectManager->get('Magento\Framework\Indexer\IndexerRegistry')->get($indexerId);
                     $model->setScheduled(false);
                 }
                 $this->messageManager->addSuccess(
diff --git a/app/code/Magento/Indexer/Model/Action/Entity.php b/app/code/Magento/Indexer/Model/Action/Entity.php
deleted file mode 100644
index 544be3646fca8c13c073ffa67b22309630210bc0..0000000000000000000000000000000000000000
--- a/app/code/Magento/Indexer/Model/Action/Entity.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Indexer\Model\Action;
-
-use Magento\Framework\DB\Select;
-use Magento\Indexer\Model\HandlerInterface;
-
-class Entity extends Base
-{
-    /**
-     * Create select from indexer configuration
-     * @param array|int|null $ids
-     *
-     * @return Select
-     */
-    protected function prepareDataSource($ids = null)
-    {
-        $collection = $this->getPrimaryResource();
-        foreach ($this->getPrimaryFieldset()['fields'] as $field) {
-            $handler = $field['handler'];
-            /** @var HandlerInterface $handler */
-            $handler->prepareSql($collection, $field);
-        }
-        $collection->addFieldToFilter($collection->getIdFieldName(), $ids);
-
-        return $collection;
-    }
-}
diff --git a/app/code/Magento/Indexer/Model/Config.php b/app/code/Magento/Indexer/Model/Config.php
index dc67bbb4f0980a3a60f261cf8628b1e64e9e4b14..21ab6a4a6ce113fb6657e8fb36858c66af3f63c7 100644
--- a/app/code/Magento/Indexer/Model/Config.php
+++ b/app/code/Magento/Indexer/Model/Config.php
@@ -5,6 +5,8 @@
  */
 namespace Magento\Indexer\Model;
 
+use Magento\Framework\Indexer\ConfigInterface;
+
 class Config implements ConfigInterface
 {
     /**
diff --git a/app/code/Magento/Indexer/Model/Config/Data.php b/app/code/Magento/Indexer/Model/Config/Data.php
index 7c0fd646e8fbf47e951b90a880b5066f8a10c9c8..0ce139b80c729009a0222e1478deaaf187d3f400 100644
--- a/app/code/Magento/Indexer/Model/Config/Data.php
+++ b/app/code/Magento/Indexer/Model/Config/Data.php
@@ -13,13 +13,13 @@ class Data extends \Magento\Framework\Config\Data
     protected $stateCollection;
 
     /**
-     * @param \Magento\Indexer\Model\Config\Reader $reader
+     * @param \Magento\Framework\Indexer\Config\Reader $reader
      * @param \Magento\Framework\Config\CacheInterface $cache
      * @param \Magento\Indexer\Model\Resource\Indexer\State\Collection $stateCollection
      * @param string $cacheId
      */
     public function __construct(
-        \Magento\Indexer\Model\Config\Reader $reader,
+        \Magento\Framework\Indexer\Config\Reader $reader,
         \Magento\Framework\Config\CacheInterface $cache,
         \Magento\Indexer\Model\Resource\Indexer\State\Collection $stateCollection,
         $cacheId = 'indexer_config'
diff --git a/app/code/Magento/Indexer/Model/Config/SchemaLocator.php b/app/code/Magento/Indexer/Model/Config/SchemaLocator.php
deleted file mode 100644
index 861a9ab0e92851bf3f0ec34cb4ef73a041f0486e..0000000000000000000000000000000000000000
--- a/app/code/Magento/Indexer/Model/Config/SchemaLocator.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Indexer\Model\Config;
-
-class SchemaLocator implements \Magento\Framework\Config\SchemaLocatorInterface
-{
-    /**
-     * Path to corresponding XSD file with validation rules for merged config
-     *
-     * @var string
-     */
-    protected $_schema = null;
-
-    /**
-     * Path to corresponding XSD file with validation rules for separate config files
-     *
-     * @var string
-     */
-    protected $_perFileSchema = null;
-
-    /**
-     * @param \Magento\Framework\Module\Dir\Reader $moduleReader
-     */
-    public function __construct(\Magento\Framework\Module\Dir\Reader $moduleReader)
-    {
-        $etcDir = $moduleReader->getModuleDir('etc', 'Magento_Indexer');
-        $this->_schema = $etcDir . '/indexer_merged.xsd';
-        $this->_perFileSchema = $etcDir . '/indexer.xsd';
-    }
-
-    /**
-     * Get path to merged config schema
-     *
-     * @return string|null
-     */
-    public function getSchema()
-    {
-        return $this->_schema;
-    }
-
-    /**
-     * Get path to pre file validation schema
-     *
-     * @return string|null
-     */
-    public function getPerFileSchema()
-    {
-        return $this->_perFileSchema;
-    }
-}
diff --git a/app/code/Magento/Indexer/Model/Handler/DefaultHandler.php b/app/code/Magento/Indexer/Model/Handler/DefaultHandler.php
deleted file mode 100644
index 365e02ef455ba811629db94eb07fe4bd4718faf8..0000000000000000000000000000000000000000
--- a/app/code/Magento/Indexer/Model/Handler/DefaultHandler.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Indexer\Model\Handler;
-
-use Magento\Framework\App\Resource\SourceProviderInterface;
-use Magento\Indexer\Model\HandlerInterface;
-
-class DefaultHandler implements HandlerInterface
-{
-    /**
-     * @param SourceProviderInterface $source
-     * @param array $fieldInfo
-     * @return void
-     */
-    public function prepareSql(SourceProviderInterface $source, $fieldInfo)
-    {
-        $source->addFieldToSelect(
-            isset($fieldInfo['origin']) ? $fieldInfo['origin'] :  $fieldInfo['name'],
-            $fieldInfo['name']
-        );
-    }
-
-    /**
-     * @param SourceProviderInterface $source
-     * @param array $fieldInfo
-     * @return void
-     */
-    public function prepareData(SourceProviderInterface $source, $fieldInfo)
-    {
-        new \Exception('Not implemented yet');
-    }
-}
diff --git a/app/code/Magento/Indexer/Model/Indexer.php b/app/code/Magento/Indexer/Model/Indexer.php
index 43436f1ce1041f29fe007ef5439e20c20e62194e..3dcc39608ac0b27d0bfb55d16bc5f9318f86b763 100644
--- a/app/code/Magento/Indexer/Model/Indexer.php
+++ b/app/code/Magento/Indexer/Model/Indexer.php
@@ -5,7 +5,18 @@
  */
 namespace Magento\Indexer\Model;
 
-class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
+use Magento\Framework\Indexer\ActionFactory;
+use Magento\Framework\Indexer\ActionInterface;
+use Magento\Framework\Indexer\ConfigInterface;
+use Magento\Framework\Indexer\IndexerInterface as IdxInterface;
+use Magento\Framework\Indexer\IndexStructureInterface;
+use Magento\Framework\Indexer\StateInterface;
+use Magento\Framework\Indexer\StructureFactory;
+
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class Indexer extends \Magento\Framework\DataObject implements IdxInterface
 {
     /**
      * @var string
@@ -22,6 +33,11 @@ class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
      */
     protected $actionFactory;
 
+    /**
+     * @var StructureFactory
+     */
+    protected $structureFactory;
+
     /**
      * @var \Magento\Framework\Mview\ViewInterface
      */
@@ -45,6 +61,7 @@ class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
     /**
      * @param ConfigInterface $config
      * @param ActionFactory $actionFactory
+     * @param StructureFactory $structureFactory
      * @param \Magento\Framework\Mview\ViewInterface $view
      * @param Indexer\StateFactory $stateFactory
      * @param Indexer\CollectionFactory $indexersFactory
@@ -53,6 +70,7 @@ class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
     public function __construct(
         ConfigInterface $config,
         ActionFactory $actionFactory,
+        StructureFactory $structureFactory,
         \Magento\Framework\Mview\ViewInterface $view,
         Indexer\StateFactory $stateFactory,
         Indexer\CollectionFactory $indexersFactory,
@@ -60,6 +78,7 @@ class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
     ) {
         $this->config = $config;
         $this->actionFactory = $actionFactory;
+        $this->structureFactory = $structureFactory;
         $this->view = $view;
         $this->stateFactory = $stateFactory;
         $this->indexersFactory = $indexersFactory;
@@ -192,7 +211,7 @@ class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
      * Fill indexer data from config
      *
      * @param string $indexerId
-     * @return IndexerInterface
+     * @return IdxInterface
      * @throws \InvalidArgumentException
      */
     public function load($indexerId)
@@ -224,7 +243,7 @@ class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
     /**
      * Return related state object
      *
-     * @return Indexer\State
+     * @return StateInterface
      */
     public function getState()
     {
@@ -238,10 +257,10 @@ class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
     /**
      * Set indexer state object
      *
-     * @param Indexer\State $state
-     * @return IndexerInterface
+     * @param StateInterface $state
+     * @return IdxInterface
      */
-    public function setState(Indexer\State $state)
+    public function setState(StateInterface $state)
     {
         $this->state = $state;
         return $this;
@@ -280,7 +299,7 @@ class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
      */
     public function isValid()
     {
-        return $this->getState()->getStatus() == Indexer\State::STATUS_VALID;
+        return $this->getState()->getStatus() == StateInterface::STATUS_VALID;
     }
 
     /**
@@ -290,7 +309,7 @@ class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
      */
     public function isInvalid()
     {
-        return $this->getState()->getStatus() == Indexer\State::STATUS_INVALID;
+        return $this->getState()->getStatus() == StateInterface::STATUS_INVALID;
     }
 
     /**
@@ -300,7 +319,7 @@ class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
      */
     public function isWorking()
     {
-        return $this->getState()->getStatus() == Indexer\State::STATUS_WORKING;
+        return $this->getState()->getStatus() == StateInterface::STATUS_WORKING;
     }
 
     /**
@@ -311,7 +330,7 @@ class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
     public function invalidate()
     {
         $state = $this->getState();
-        $state->setStatus(Indexer\State::STATUS_INVALID);
+        $state->setStatus(StateInterface::STATUS_INVALID);
         $state->save();
     }
 
@@ -352,7 +371,26 @@ class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
      */
     protected function getActionInstance()
     {
-        return $this->actionFactory->create($this->getActionClass(), ['data' => $this->getData()]);
+        return $this->actionFactory->create(
+            $this->getActionClass(),
+            [
+                'indexStructure' => $this->getStructureInstance(),
+                'data' => $this->getData(),
+            ]
+        );
+    }
+
+    /**
+     * Return indexer structure instance
+     *
+     * @return IndexStructureInterface
+     */
+    protected function getStructureInstance()
+    {
+        if (!$this->getData('structure')) {
+            return null;
+        }
+        return $this->structureFactory->create($this->getData('structure'));
     }
 
     /**
@@ -363,20 +401,20 @@ class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
      */
     public function reindexAll()
     {
-        if ($this->getState()->getStatus() != Indexer\State::STATUS_WORKING) {
+        if ($this->getState()->getStatus() != StateInterface::STATUS_WORKING) {
             $state = $this->getState();
-            $state->setStatus(Indexer\State::STATUS_WORKING);
+            $state->setStatus(StateInterface::STATUS_WORKING);
             $state->save();
             if ($this->getView()->isEnabled()) {
                 $this->getView()->suspend();
             }
             try {
                 $this->getActionInstance()->executeFull();
-                $state->setStatus(Indexer\State::STATUS_VALID);
+                $state->setStatus(StateInterface::STATUS_VALID);
                 $state->save();
                 $this->getView()->resume();
             } catch (\Exception $exception) {
-                $state->setStatus(Indexer\State::STATUS_INVALID);
+                $state->setStatus(StateInterface::STATUS_INVALID);
                 $state->save();
                 $this->getView()->resume();
                 throw $exception;
@@ -398,7 +436,7 @@ class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
 
     /**
      * Regenerate rows in index by ID list
-     *
+     *5
      * @param int[] $ids
      * @return void
      */
diff --git a/app/code/Magento/Indexer/Model/Indexer/Collection.php b/app/code/Magento/Indexer/Model/Indexer/Collection.php
index 5a6c05d25b02015eb11ff545f12459316a8709cd..32fbf14b1ca63b61a90a10d6622ea3f914979f00 100644
--- a/app/code/Magento/Indexer/Model/Indexer/Collection.php
+++ b/app/code/Magento/Indexer/Model/Indexer/Collection.php
@@ -12,10 +12,10 @@ class Collection extends \Magento\Framework\Data\Collection
      *
      * @var string
      */
-    protected $_itemObjectClass = 'Magento\Indexer\Model\IndexerInterface';
+    protected $_itemObjectClass = 'Magento\Framework\Indexer\IndexerInterface';
 
     /**
-     * @var \Magento\Indexer\Model\ConfigInterface
+     * @var \Magento\Framework\Indexer\ConfigInterface
      */
     protected $config;
 
@@ -26,12 +26,12 @@ class Collection extends \Magento\Framework\Data\Collection
 
     /**
      * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
-     * @param \Magento\Indexer\Model\ConfigInterface $config
+     * @param \Magento\Framework\Indexer\ConfigInterface $config
      * @param \Magento\Indexer\Model\Resource\Indexer\State\CollectionFactory $statesFactory
      */
     public function __construct(
         \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
-        \Magento\Indexer\Model\ConfigInterface $config,
+        \Magento\Framework\Indexer\ConfigInterface $config,
         \Magento\Indexer\Model\Resource\Indexer\State\CollectionFactory $statesFactory
     ) {
         $this->config = $config;
@@ -53,7 +53,7 @@ class Collection extends \Magento\Framework\Data\Collection
         if (!$this->isLoaded()) {
             $states = $this->statesFactory->create();
             foreach (array_keys($this->config->getIndexers()) as $indexerId) {
-                /** @var \Magento\Indexer\Model\IndexerInterface $indexer */
+                /** @var \Magento\Framework\Indexer\IndexerInterface $indexer */
                 $indexer = $this->getNewEmptyItem();
                 $indexer->load($indexerId);
                 foreach ($states->getItems() as $state) {
diff --git a/app/code/Magento/Indexer/Model/Indexer/State.php b/app/code/Magento/Indexer/Model/Indexer/State.php
index f386d5ca9cdbd13c37797e9898e891c350df1987..0937cce28dee5ae180405d74fbd51c1e606797d4 100644
--- a/app/code/Magento/Indexer/Model/Indexer/State.php
+++ b/app/code/Magento/Indexer/Model/Indexer/State.php
@@ -5,24 +5,10 @@
  */
 namespace Magento\Indexer\Model\Indexer;
 
-/**
- * @method string getIndexerId()
- * @method \Magento\Indexer\Model\Indexer\State setIndexerId($value)
- * @method string getStatus()
- * @method string getUpdated()
- * @method \Magento\Indexer\Model\Indexer\State setUpdated($value)
- */
-class State extends \Magento\Framework\Model\AbstractModel
-{
-    /**
-     * Indexer statuses
-     */
-    const STATUS_WORKING = 'working';
-
-    const STATUS_VALID = 'valid';
-
-    const STATUS_INVALID = 'invalid';
+use Magento\Framework\Indexer\StateInterface;
 
+class State extends \Magento\Framework\Model\AbstractModel implements StateInterface
+{
     /**
      * Prefix of model events names
      *
@@ -57,6 +43,58 @@ class State extends \Magento\Framework\Model\AbstractModel
         parent::__construct($context, $registry, $resource, $resourceCollection, $data);
     }
 
+    /**
+     * Return indexer id
+     *
+     * @return string
+     */
+    public function getIndexerId()
+    {
+        return parent::getIndexerId();
+    }
+
+    /**
+     * Set indexer id
+     *
+     * @param string $value
+     * @return $this
+     */
+    public function setIndexerId($value)
+    {
+        return parent::setIndexerId($value);
+    }
+
+    /**
+     * Return status
+     *
+     * @return string
+     */
+    public function getStatus()
+    {
+        return parent::getStatus();
+    }
+
+    /**
+     * Return updated
+     *
+     * @return string
+     */
+    public function getUpdated()
+    {
+        return parent::getUpdated();
+    }
+
+    /**
+     * Set updated
+     *
+     * @param string $value
+     * @return $this
+     */
+    public function setUpdated($value)
+    {
+        return parent::setUpdated($value);
+    }
+
     /**
      * Fill object with state data by view ID
      *
diff --git a/app/code/Magento/Indexer/Model/Message/Invalid.php b/app/code/Magento/Indexer/Model/Message/Invalid.php
index bc8da0010fd826d90904adad7150c0ef556090d9..33ffc5020c7de78255690937852a2bd987dd6ba4 100644
--- a/app/code/Magento/Indexer/Model/Message/Invalid.php
+++ b/app/code/Magento/Indexer/Model/Message/Invalid.php
@@ -31,7 +31,7 @@ class Invalid implements \Magento\Framework\Notification\MessageInterface
     {
         /** @var \Magento\Indexer\Model\Indexer $indexer */
         foreach ($this->collection->getItems() as $indexer) {
-            if ($indexer->getStatus() == \Magento\Indexer\Model\Indexer\State::STATUS_INVALID) {
+            if ($indexer->getStatus() == \Magento\Framework\Indexer\StateInterface::STATUS_INVALID) {
                 return true;
             }
         }
diff --git a/app/code/Magento/Indexer/Model/Processor.php b/app/code/Magento/Indexer/Model/Processor.php
index 98cdfb46dd7bdb13a41da1a49843afd1b2973336..dec0175102273febdb8bd985009e23198020643a 100644
--- a/app/code/Magento/Indexer/Model/Processor.php
+++ b/app/code/Magento/Indexer/Model/Processor.php
@@ -5,6 +5,9 @@
  */
 namespace Magento\Indexer\Model;
 
+use Magento\Framework\Indexer\ConfigInterface;
+use Magento\Framework\Indexer\IndexerInterface;
+
 class Processor
 {
     /**
diff --git a/app/code/Magento/Indexer/Model/Processor/Handler.php b/app/code/Magento/Indexer/Model/Processor/Handler.php
index 653c28f80e3b82cb9017be44e405946015d6a0d2..23ce8c24b3fed4e60e38f7e3dd222ec3c7dbb177 100644
--- a/app/code/Magento/Indexer/Model/Processor/Handler.php
+++ b/app/code/Magento/Indexer/Model/Processor/Handler.php
@@ -5,8 +5,8 @@
  */
 namespace Magento\Indexer\Model\Processor;
 
-use Magento\Indexer\Model\HandlerInterface;
-use Magento\Indexer\Model\HandlerPool;
+use Magento\Framework\Indexer\HandlerInterface;
+use Magento\Framework\Indexer\HandlerPool;
 
 class Handler
 {
diff --git a/app/code/Magento/Indexer/Model/Processor/InvalidateCache.php b/app/code/Magento/Indexer/Model/Processor/InvalidateCache.php
index df397b3f720fd5cd0746dad8fd9c5ed10ed51767..5347b9e0760059f3b62b92c637906fda59792ff1 100644
--- a/app/code/Magento/Indexer/Model/Processor/InvalidateCache.php
+++ b/app/code/Magento/Indexer/Model/Processor/InvalidateCache.php
@@ -12,7 +12,7 @@ namespace Magento\Indexer\Model\Processor;
 class InvalidateCache
 {
     /**
-     * @var \Magento\Indexer\Model\CacheContext
+     * @var \Magento\Framework\Indexer\CacheContext
      */
     protected $context;
 
@@ -27,12 +27,12 @@ class InvalidateCache
     protected $moduleManager;
 
     /**
-     * @param \Magento\Indexer\Model\CacheContext $context
+     * @param \Magento\Framework\Indexer\CacheContext $context
      * @param \Magento\Framework\Event\Manager $eventManager
      * @param \Magento\Framework\Module\Manager $moduleManager
      */
     public function __construct(
-        \Magento\Indexer\Model\CacheContext $context,
+        \Magento\Framework\Indexer\CacheContext $context,
         \Magento\Framework\Event\Manager $eventManager,
         \Magento\Framework\Module\Manager $moduleManager
     ) {
diff --git a/app/code/Magento/Indexer/Model/Resource/AbstractResource.php b/app/code/Magento/Indexer/Model/Resource/AbstractResource.php
index 9f7cc10532d3dd8ccc102f50cf680a8acd90c2ff..24c2e537b0def14789cf0aea7347ce029ce3bae0 100644
--- a/app/code/Magento/Indexer/Model/Resource/AbstractResource.php
+++ b/app/code/Magento/Indexer/Model/Resource/AbstractResource.php
@@ -19,7 +19,7 @@ abstract class AbstractResource extends \Magento\Framework\Model\Resource\Db\Abs
     /**
      * Constructor
      *
-     * @var \Magento\Indexer\Model\Indexer\Table\StrategyInterface
+     * @var \Magento\Framework\Indexer\Table\StrategyInterface
      */
     protected $tableStrategy;
 
@@ -27,12 +27,12 @@ abstract class AbstractResource extends \Magento\Framework\Model\Resource\Db\Abs
      * Class constructor
      *
      * @param \Magento\Framework\Model\Resource\Db\Context $context
-     * @param \Magento\Indexer\Model\Indexer\Table\StrategyInterface $tableStrategy
+     * @param \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy
      * @param string $connectionName
      */
     public function __construct(
         \Magento\Framework\Model\Resource\Db\Context $context,
-        \Magento\Indexer\Model\Indexer\Table\StrategyInterface $tableStrategy,
+        \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy,
         $connectionName = null
     ) {
         $this->tableStrategy = $tableStrategy;
diff --git a/app/code/Magento/Indexer/Setup/InstallData.php b/app/code/Magento/Indexer/Setup/InstallData.php
index c2fbcace85baab25b813277d566e588cf39e903b..c2ea10a8261755af7777ed017420671b8ccb1a21 100644
--- a/app/code/Magento/Indexer/Setup/InstallData.php
+++ b/app/code/Magento/Indexer/Setup/InstallData.php
@@ -8,10 +8,11 @@ namespace Magento\Indexer\Setup;
 
 use Magento\Framework\Encryption\Encryptor;
 use Magento\Framework\Encryption\EncryptorInterface;
+use Magento\Framework\Indexer\StateInterface;
 use Magento\Framework\Json\EncoderInterface;
 use Magento\Framework\Setup\ModuleContextInterface;
 use Magento\Framework\Setup\ModuleDataSetupInterface;
-use Magento\Indexer\Model\ConfigInterface;
+use Magento\Framework\Indexer\ConfigInterface;
 use Magento\Indexer\Model\Resource\Indexer\State\CollectionFactory;
 use Magento\Indexer\Model\Indexer\State;
 use Magento\Indexer\Model\Indexer\StateFactory;
@@ -100,7 +101,7 @@ class InstallData implements InstallDataInterface
                 $state = $this->stateFactory->create();
                 $state->loadByIndexer($indexerId);
                 $state->setHashConfig($hash);
-                $state->setStatus(State::STATUS_INVALID);
+                $state->setStatus(StateInterface::STATUS_INVALID);
                 $state->save();
             }
         }
diff --git a/app/code/Magento/Indexer/Setup/Recurring.php b/app/code/Magento/Indexer/Setup/Recurring.php
index e453e18bc7d9f798e66962af468f3351c06a6720..845a14cb4b0bdd1f9f246003bbd69d7e544240a0 100644
--- a/app/code/Magento/Indexer/Setup/Recurring.php
+++ b/app/code/Magento/Indexer/Setup/Recurring.php
@@ -8,11 +8,12 @@ namespace Magento\Indexer\Setup;
 
 use Magento\Framework\Encryption\Encryptor;
 use Magento\Framework\Encryption\EncryptorInterface;
+use Magento\Framework\Indexer\StateInterface;
 use Magento\Framework\Json\EncoderInterface;
 use Magento\Framework\Setup\InstallSchemaInterface;
 use Magento\Framework\Setup\ModuleContextInterface;
 use Magento\Framework\Setup\SchemaSetupInterface;
-use Magento\Indexer\Model\ConfigInterface;
+use Magento\Framework\Indexer\ConfigInterface;
 use Magento\Indexer\Model\Indexer\State;
 use Magento\Indexer\Model\Indexer\StateFactory;
 use Magento\Indexer\Model\Resource\Indexer\State\CollectionFactory;
@@ -94,7 +95,7 @@ class Recurring implements InstallSchemaInterface
 
             if (isset($stateIndexers[$indexerId])) {
                 if ($stateIndexers[$indexerId]->getHashConfig() != $expectedHashConfig) {
-                    $stateIndexers[$indexerId]->setStatus(State::STATUS_INVALID);
+                    $stateIndexers[$indexerId]->setStatus(StateInterface::STATUS_INVALID);
                     $stateIndexers[$indexerId]->setHashConfig($expectedHashConfig);
                     $stateIndexers[$indexerId]->save();
                 }
@@ -103,7 +104,7 @@ class Recurring implements InstallSchemaInterface
                 $state = $this->stateFactory->create();
                 $state->loadByIndexer($indexerId);
                 $state->setHashConfig($expectedHashConfig);
-                $state->setStatus(State::STATUS_INVALID);
+                $state->setStatus(StateInterface::STATUS_INVALID);
                 $state->save();
             }
         }
diff --git a/app/code/Magento/Indexer/Test/Unit/Block/Backend/Grid/Column/Renderer/StatusTest.php b/app/code/Magento/Indexer/Test/Unit/Block/Backend/Grid/Column/Renderer/StatusTest.php
index 699e5dcd63621cf75789027147d330f606cd707f..7fee908bf92c267765128d93e6447840c0027f6b 100644
--- a/app/code/Magento/Indexer/Test/Unit/Block/Backend/Grid/Column/Renderer/StatusTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Block/Backend/Grid/Column/Renderer/StatusTest.php
@@ -37,15 +37,15 @@ class StatusTest extends \PHPUnit_Framework_TestCase
     {
         return [
             'set1' => [
-                [\Magento\Indexer\Model\Indexer\State::STATUS_INVALID],
+                [\Magento\Framework\Indexer\StateInterface::STATUS_INVALID],
                 ['class' => 'grid-severity-critical', 'text' => 'Reindex required']
             ],
             'set2' => [
-                [\Magento\Indexer\Model\Indexer\State::STATUS_VALID],
+                [\Magento\Framework\Indexer\StateInterface::STATUS_VALID],
                 ['class' => 'grid-severity-notice', 'text' => 'Ready']
             ],
             'set3' => [
-                [\Magento\Indexer\Model\Indexer\State::STATUS_WORKING],
+                [\Magento\Framework\Indexer\StateInterface::STATUS_WORKING],
                 ['class' => 'grid-severity-major', 'text' => 'Processing']
             ]
         ];
diff --git a/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerStatusCommandTest.php b/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerStatusCommandTest.php
index 198dd451da12be308189854e68dd39d557c18a92..7b82d38805260ae455f56b1d21d09e2c420f3d90 100644
--- a/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerStatusCommandTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerStatusCommandTest.php
@@ -26,19 +26,19 @@ class IndexerStatusCommandTest extends AbstractIndexerCommandCommonSetup
         $indexerOne
             ->expects($this->once())
             ->method('getStatus')
-            ->willReturn(\Magento\Indexer\Model\Indexer\State::STATUS_VALID);
+            ->willReturn(\Magento\Framework\Indexer\StateInterface::STATUS_VALID);
         $indexerTwo = $this->getMock('Magento\Indexer\Model\Indexer', [], [], '', false);
         $indexerTwo->expects($this->once())->method('getTitle')->willReturn('Title_indexerTwo');
         $indexerTwo
             ->expects($this->once())
             ->method('getStatus')
-            ->willReturn(\Magento\Indexer\Model\Indexer\State::STATUS_INVALID);
+            ->willReturn(\Magento\Framework\Indexer\StateInterface::STATUS_INVALID);
         $indexerThree = $this->getMock('Magento\Indexer\Model\Indexer', [], [], '', false);
         $indexerThree->expects($this->once())->method('getTitle')->willReturn('Title_indexerThree');
         $indexerThree
             ->expects($this->once())
             ->method('getStatus')
-            ->willReturn(\Magento\Indexer\Model\Indexer\State::STATUS_WORKING);
+            ->willReturn(\Magento\Framework\Indexer\StateInterface::STATUS_WORKING);
         $indexerFour = $this->getMock('Magento\Indexer\Model\Indexer', [], [], '', false);
         $indexerFour->expects($this->once())->method('getTitle')->willReturn('Title_indexerFour');
         $collection
diff --git a/app/code/Magento/Indexer/Test/Unit/Controller/Adminhtml/Indexer/MassChangelogTest.php b/app/code/Magento/Indexer/Test/Unit/Controller/Adminhtml/Indexer/MassChangelogTest.php
index 2b1b3a14280138bb27b32aa72f6457b08e6a1463..133a763f8312dc014bd94662bfcd087767c0260e 100644
--- a/app/code/Magento/Indexer/Test/Unit/Controller/Adminhtml/Indexer/MassChangelogTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Controller/Adminhtml/Indexer/MassChangelogTest.php
@@ -57,7 +57,7 @@ class MassChangelogTest extends \PHPUnit_Framework_TestCase
     protected $messageManager;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry
+     * @var \Magento\Framework\Indexer\IndexerRegistry
      */
     protected $indexReg;
 
@@ -83,6 +83,7 @@ class MassChangelogTest extends \PHPUnit_Framework_TestCase
 
     /**
      * Set up test
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
      */
     protected function setUp()
     {
@@ -144,7 +145,13 @@ class MassChangelogTest extends \PHPUnit_Framework_TestCase
         $this->session->expects($this->any())->method('setIsUrlNotice')->willReturn($this->objectManager);
         $this->actionFlag = $this->getMock('\Magento\Framework\App\ActionFlag', ['get'], [], '', false);
         $this->actionFlag->expects($this->any())->method("get")->willReturn($this->objectManager);
-        $this->objectManager = $this->getMock('Magento\Framework\TestFramework\Unit\Helper\ObjectManager', ['get'], [], '', false);
+        $this->objectManager = $this->getMock(
+            'Magento\Framework\TestFramework\Unit\Helper\ObjectManager',
+            ['get'],
+            [],
+            '',
+            false
+        );
         $this->request = $this->getMockForAbstractClass(
             '\Magento\Framework\App\RequestInterface',
             ['getParam', 'getRequest'],
@@ -164,7 +171,7 @@ class MassChangelogTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->indexReg = $this->getMock(
-            'Magento\Indexer\Model\IndexerRegistry',
+            'Magento\Framework\Indexer\IndexerRegistry',
             ['get', 'setScheduled'],
             [],
             '',
@@ -200,10 +207,10 @@ class MassChangelogTest extends \PHPUnit_Framework_TestCase
         } else {
 
             $this->objectManager->expects($this->any())
-                ->method('get')->with('Magento\Indexer\Model\IndexerRegistry')
+                ->method('get')->with('Magento\Framework\Indexer\IndexerRegistry')
                 ->will($this->returnValue($this->indexReg));
             $indexerInterface = $this->getMockForAbstractClass(
-                'Magento\Indexer\Model\IndexerInterface',
+                'Magento\Framework\Indexer\IndexerInterface',
                 ['setScheduled'],
                 '',
                 false
diff --git a/app/code/Magento/Indexer/Test/Unit/Controller/Adminhtml/Indexer/MassOnTheFlyTest.php b/app/code/Magento/Indexer/Test/Unit/Controller/Adminhtml/Indexer/MassOnTheFlyTest.php
index 3dbf8a5ee79765f5a2b4942e672eabc5ec0e2e09..c535ed59f686f9b9c915dc8fb0f8d05815f999d9 100644
--- a/app/code/Magento/Indexer/Test/Unit/Controller/Adminhtml/Indexer/MassOnTheFlyTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Controller/Adminhtml/Indexer/MassOnTheFlyTest.php
@@ -57,7 +57,7 @@ class MassOnTheFlyTest extends \PHPUnit_Framework_TestCase
     protected $messageManager;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry
+     * @var \Magento\Framework\Indexer\IndexerRegistry
      */
     protected $indexReg;
 
@@ -83,6 +83,7 @@ class MassOnTheFlyTest extends \PHPUnit_Framework_TestCase
 
     /**
      * Set up test
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
      */
     protected function setUp()
     {
@@ -144,7 +145,13 @@ class MassOnTheFlyTest extends \PHPUnit_Framework_TestCase
         $this->session->expects($this->any())->method('setIsUrlNotice')->willReturn($this->objectManager);
         $this->actionFlag = $this->getMock('\Magento\Framework\App\ActionFlag', ['get'], [], '', false);
         $this->actionFlag->expects($this->any())->method("get")->willReturn($this->objectManager);
-        $this->objectManager = $this->getMock('Magento\Framework\TestFramework\Unit\Helper\ObjectManager', ['get'], [], '', false);
+        $this->objectManager = $this->getMock(
+            'Magento\Framework\TestFramework\Unit\Helper\ObjectManager',
+            ['get'],
+            [],
+            '',
+            false
+        );
         $this->request = $this->getMockForAbstractClass(
             '\Magento\Framework\App\RequestInterface',
             ['getParam', 'getRequest'],
@@ -164,7 +171,7 @@ class MassOnTheFlyTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->indexReg = $this->getMock(
-            'Magento\Indexer\Model\IndexerRegistry',
+            'Magento\Framework\Indexer\IndexerRegistry',
             ['get', 'setScheduled'],
             [],
             '',
@@ -200,10 +207,10 @@ class MassOnTheFlyTest extends \PHPUnit_Framework_TestCase
         } else {
 
             $this->objectManager->expects($this->any())
-                ->method('get')->with('Magento\Indexer\Model\IndexerRegistry')
+                ->method('get')->with('Magento\Framework\Indexer\IndexerRegistry')
                 ->will($this->returnValue($this->indexReg));
             $indexerInterface = $this->getMockForAbstractClass(
-                'Magento\Indexer\Model\IndexerInterface',
+                'Magento\Framework\Indexer\IndexerInterface',
                 ['setScheduled'],
                 '',
                 false
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/CacheContextTest.php b/app/code/Magento/Indexer/Test/Unit/Model/CacheContextTest.php
index 0baef4bd4b7f38c2d997c1535e34aae36db64c84..47bd79ccf4b617d9a8dcbd2d198f95098da093a4 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/CacheContextTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Model/CacheContextTest.php
@@ -9,7 +9,7 @@ namespace Magento\Indexer\Test\Unit\Model;
 class CacheContextTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Indexer\Model\CacheContext
+     * @var \Magento\Framework\Indexer\CacheContext
      */
     protected $context;
 
@@ -18,7 +18,7 @@ class CacheContextTest extends \PHPUnit_Framework_TestCase
      */
     public function setUp()
     {
-        $this->context = new \Magento\Indexer\Model\CacheContext();
+        $this->context = new \Magento\Framework\Indexer\CacheContext();
     }
 
     /**
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/Config/DataTest.php b/app/code/Magento/Indexer/Test/Unit/Model/Config/DataTest.php
index c8955b355b11ede222f84e284bedf9b17bdf7118..3cd17862c88ad9c76eb11a84c3eab0558397e114 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/Config/DataTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Model/Config/DataTest.php
@@ -13,7 +13,7 @@ class DataTest extends \PHPUnit_Framework_TestCase
     protected $model;
 
     /**
-     * @var \Magento\Indexer\Model\Config\Reader|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\Config\Reader|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $reader;
 
@@ -39,7 +39,7 @@ class DataTest extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
-        $this->reader = $this->getMock('Magento\Indexer\Model\Config\Reader', ['read'], [], '', false);
+        $this->reader = $this->getMock('Magento\Framework\Indexer\Config\Reader', ['read'], [], '', false);
         $this->cache = $this->getMockForAbstractClass(
             'Magento\Framework\Config\CacheInterface',
             [],
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/Indexer/AbstractProcessorStub.php b/app/code/Magento/Indexer/Test/Unit/Model/Indexer/AbstractProcessorStub.php
index e32ab2ee334eccd9b6f87b24fc6e91a379595fa1..2e5b9b8d7369c980674bac46c77ade9dd0280589 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/Indexer/AbstractProcessorStub.php
+++ b/app/code/Magento/Indexer/Test/Unit/Model/Indexer/AbstractProcessorStub.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Indexer\Test\Unit\Model\Indexer;
 
-class AbstractProcessorStub extends \Magento\Indexer\Model\Indexer\AbstractProcessor
+class AbstractProcessorStub extends \Magento\Framework\Indexer\AbstractProcessor
 {
     /**
      * Indexer ID
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/Indexer/AbstractProcessorTest.php b/app/code/Magento/Indexer/Test/Unit/Model/Indexer/AbstractProcessorTest.php
index b81648a476650d27aa15813aa5c870e5430b9bc5..49e233c29fcbcf39dc563433fcb079c4be64aa8c 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/Indexer/AbstractProcessorTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Model/Indexer/AbstractProcessorTest.php
@@ -15,14 +15,14 @@ class AbstractProcessorTest extends \PHPUnit_Framework_TestCase
     protected $model;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $_indexerRegistryMock;
 
     protected function setUp()
     {
         $this->_indexerRegistryMock = $this->getMock(
-            '\Magento\Indexer\Model\IndexerRegistry',
+            '\Magento\Framework\Indexer\IndexerRegistry',
             ['isScheduled', 'get', 'reindexRow', 'reindexList', 'reindexAll', 'invalidate'],
             [],
             '',
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/Indexer/CollectionTest.php b/app/code/Magento/Indexer/Test/Unit/Model/Indexer/CollectionTest.php
index fc0136fa578e9b19625263e1c0a0d628fd2e865c..0cb275394d37b6f3238dc0c7a09327aae67432dc 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/Indexer/CollectionTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Model/Indexer/CollectionTest.php
@@ -18,7 +18,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
             ['create']
         )->getMock();
 
-        $config = $this->getMockBuilder('Magento\Indexer\Model\ConfigInterface')->getMock();
+        $config = $this->getMockBuilder('Magento\Framework\Indexer\ConfigInterface')->getMock();
 
         $statesFactory = $this->getMockBuilder(
             'Magento\Indexer\Model\Resource\Indexer\State\CollectionFactory'
@@ -53,7 +53,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
         )->method(
             'create'
         )->with(
-            'Magento\Indexer\Model\IndexerInterface'
+            'Magento\Framework\Indexer\IndexerInterface'
         )->will(
             $this->returnValue($indexer)
         );
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/IndexerTest.php b/app/code/Magento/Indexer/Test/Unit/Model/IndexerTest.php
index 2b79e1e4b69864fae79c74a39233c7027ab59d16..62004ab2d92cef84e96e5dce4e42b52ea7980041 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/IndexerTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Model/IndexerTest.php
@@ -5,6 +5,7 @@
  */
 namespace Magento\Indexer\Test\Unit\Model;
 
+use Magento\Framework\Indexer\StateInterface;
 use Magento\Indexer\Model\Indexer\State;
 
 class IndexerTest extends \PHPUnit_Framework_TestCase
@@ -15,12 +16,12 @@ class IndexerTest extends \PHPUnit_Framework_TestCase
     protected $model;
 
     /**
-     * @var \Magento\Indexer\Model\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $configMock;
 
     /**
-     * @var \Magento\Indexer\Model\ActionFactory|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\ActionFactory|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $actionFactoryMock;
 
@@ -42,7 +43,7 @@ class IndexerTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->configMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\ConfigInterface',
+            'Magento\Framework\Indexer\ConfigInterface',
             [],
             '',
             false,
@@ -51,7 +52,7 @@ class IndexerTest extends \PHPUnit_Framework_TestCase
             ['getIndexer']
         );
         $this->actionFactoryMock = $this->getMock(
-            'Magento\Indexer\Model\ActionFactory',
+            'Magento\Framework\Indexer\ActionFactory',
             ['create'],
             [],
             '',
@@ -80,9 +81,16 @@ class IndexerTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
+        $structureFactory = $this->getMockBuilder('Magento\Framework\Indexer\StructureFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+
+        /** @var \Magento\Framework\Indexer\StructureFactory $structureFactory */
         $this->model = new \Magento\Indexer\Model\Indexer(
             $this->configMock,
             $this->actionFactoryMock,
+            $structureFactory,
             $this->viewMock,
             $this->stateFactoryMock,
             $this->indexFactoryMock
@@ -219,7 +227,7 @@ class IndexerTest extends \PHPUnit_Framework_TestCase
         $this->viewMock->expects($this->once())->method('resume');
 
         $actionMock = $this->getMock(
-            'Magento\Indexer\Model\ActionInterface',
+            'Magento\Framework\Indexer\ActionInterface',
             ['executeFull', 'executeList', 'executeRow'],
             [],
             '',
@@ -267,7 +275,7 @@ class IndexerTest extends \PHPUnit_Framework_TestCase
         $this->viewMock->expects($this->once())->method('resume');
 
         $actionMock = $this->getMock(
-            'Magento\Indexer\Model\ActionInterface',
+            'Magento\Framework\Indexer\ActionInterface',
             ['executeFull', 'executeList', 'executeRow'],
             [],
             '',
@@ -392,7 +400,7 @@ class IndexerTest extends \PHPUnit_Framework_TestCase
 
     public function testGetStatus()
     {
-        $status = State::STATUS_WORKING;
+        $status = StateInterface::STATUS_WORKING;
         $stateMock = $this->getMock(
             '\Magento\Indexer\Model\Indexer\State',
             ['load', 'getStatus'],
@@ -432,9 +440,9 @@ class IndexerTest extends \PHPUnit_Framework_TestCase
     public function statusDataProvider()
     {
         return [
-            ['isValid', State::STATUS_VALID],
-            ['isInvalid', State::STATUS_INVALID],
-            ['isWorking', State::STATUS_WORKING]
+            ['isValid', StateInterface::STATUS_VALID],
+            ['isInvalid', StateInterface::STATUS_INVALID],
+            ['isWorking', StateInterface::STATUS_WORKING]
         ];
     }
 
@@ -449,7 +457,7 @@ class IndexerTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->stateFactoryMock->expects($this->once())->method('create')->will($this->returnValue($stateMock));
-        $stateMock->expects($this->once())->method('setStatus')->with(State::STATUS_INVALID)->will(
+        $stateMock->expects($this->once())->method('setStatus')->with(StateInterface::STATUS_INVALID)->will(
             $this->returnSelf()
         );
         $stateMock->expects($this->once())->method('save')->will($this->returnSelf());
@@ -468,7 +476,7 @@ class IndexerTest extends \PHPUnit_Framework_TestCase
             false
         );
         $actionMock = $this->getMock(
-            'Magento\Indexer\Model\ActionInterface',
+            'Magento\Framework\Indexer\ActionInterface',
             ['executeFull', 'executeList', 'executeRow'],
             [],
             '',
@@ -501,7 +509,7 @@ class IndexerTest extends \PHPUnit_Framework_TestCase
             false
         );
         $actionMock = $this->getMock(
-            'Magento\Indexer\Model\ActionInterface',
+            'Magento\Framework\Indexer\ActionInterface',
             ['executeFull', 'executeList', 'executeRow'],
             [],
             '',
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/Message/InvalidTest.php b/app/code/Magento/Indexer/Test/Unit/Model/Message/InvalidTest.php
index b4d8c0152f8bb01ecf8be93e8bc47f017a19babe..2beb3acf5e21f54e5a05b5d7db52777c5e689882 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/Message/InvalidTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Model/Message/InvalidTest.php
@@ -48,7 +48,7 @@ class InvalidTest extends \PHPUnit_Framework_TestCase
     public function testDisplayMessage()
     {
         $this->indexerMock->expects($this->any())->method('getStatus')->with()
-            ->willReturn(\Magento\Indexer\Model\Indexer\State::STATUS_INVALID);
+            ->willReturn(\Magento\Framework\Indexer\StateInterface::STATUS_INVALID);
 
         $this->assertTrue($this->model->isDisplayed());
     }
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/Processor/InvalidateCacheTest.php b/app/code/Magento/Indexer/Test/Unit/Model/Processor/InvalidateCacheTest.php
index 90c5606b85da7ec8612250701c9adfbc9d075742..6fc692c1f7d9776680ae0f8b16e0d6da5c199959 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/Processor/InvalidateCacheTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Model/Processor/InvalidateCacheTest.php
@@ -18,14 +18,14 @@ class InvalidateCacheTest extends \PHPUnit_Framework_TestCase
     /**
      * Mock for context
      *
-     * @var \Magento\Indexer\Model\CacheContext|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\CacheContext|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $contextMock;
 
     /**
      * Subject mock
      *
-     * @var \Magento\Indexer\Model\ActionInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\ActionInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $subjectMock;
 
@@ -49,7 +49,7 @@ class InvalidateCacheTest extends \PHPUnit_Framework_TestCase
     public function setUp()
     {
         $this->subjectMock = $this->getMock('Magento\Indexer\Model\Processor', [], [], '', false);
-        $this->contextMock = $this->getMock('Magento\Indexer\Model\CacheContext', [], [], '', false);
+        $this->contextMock = $this->getMock('Magento\Framework\Indexer\CacheContext', [], [], '', false);
         $this->eventManagerMock = $this->getMock('Magento\Framework\Event\Manager', [], [], '', false);
         $this->moduleManager = $this->getMock('Magento\Framework\Module\Manager', [], [], '', false);
         $this->plugin = new \Magento\Indexer\Model\Processor\InvalidateCache(
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/ProcessorTest.php b/app/code/Magento/Indexer/Test/Unit/Model/ProcessorTest.php
index 6db69a068ae6ca20d31e98d4c37d41965fdab649..f72d10cbb7ca5c93f22698c6fdb3e874f0d25fef 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/ProcessorTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Model/ProcessorTest.php
@@ -5,6 +5,7 @@
  */
 namespace Magento\Indexer\Test\Unit\Model;
 
+use Magento\Framework\Indexer\StateInterface;
 use Magento\Indexer\Model\Indexer\State;
 
 class ProcessorTest extends \PHPUnit_Framework_TestCase
@@ -15,7 +16,7 @@ class ProcessorTest extends \PHPUnit_Framework_TestCase
     protected $model;
 
     /**
-     * @var \Magento\Indexer\Model\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $configMock;
 
@@ -37,7 +38,7 @@ class ProcessorTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->configMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\ConfigInterface',
+            'Magento\Framework\Indexer\ConfigInterface',
             [],
             '',
             false,
@@ -91,7 +92,7 @@ class ProcessorTest extends \PHPUnit_Framework_TestCase
         )->method(
             'getStatus'
         )->will(
-            $this->returnValue(State::STATUS_INVALID)
+            $this->returnValue(StateInterface::STATUS_INVALID)
         );
         $indexer1Mock = $this->getMock(
             'Magento\Indexer\Model\Indexer',
@@ -115,7 +116,7 @@ class ProcessorTest extends \PHPUnit_Framework_TestCase
         )->method(
             'getStatus'
         )->will(
-            $this->returnValue(State::STATUS_VALID)
+            $this->returnValue(StateInterface::STATUS_VALID)
         );
         $indexer2Mock = $this->getMock(
             'Magento\Indexer\Model\Indexer',
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/Resource/AbstractResourceTest.php b/app/code/Magento/Indexer/Test/Unit/Model/Resource/AbstractResourceTest.php
index 723adf8d62997c601df8636d14598450b1df4cdd..728b20681528cbd4d9546643c256c8f80d911198 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/Resource/AbstractResourceTest.php
+++ b/app/code/Magento/Indexer/Test/Unit/Model/Resource/AbstractResourceTest.php
@@ -18,7 +18,7 @@ class AbstractResourceTest extends \PHPUnit_Framework_TestCase
     protected $_resourceMock;
 
     /**
-     * @var \Magento\Indexer\Model\Indexer\Table\StrategyInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\Table\StrategyInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $_tableStrategyInterface;
 
@@ -30,7 +30,7 @@ class AbstractResourceTest extends \PHPUnit_Framework_TestCase
             ->getMock();
 
         $this->_tableStrategyInterface = $this->getMock(
-            'Magento\Indexer\Model\Indexer\Table\StrategyInterface',
+            'Magento\Framework\Indexer\Table\StrategyInterface',
             [],
             [],
             '',
diff --git a/app/code/Magento/Indexer/etc/di.xml b/app/code/Magento/Indexer/etc/di.xml
index 0c2eafb8a9e01f5bd22831c1171aec4df49b7fb2..b3b3275dbed8c8a54ba5f4a654aa084865d64609 100644
--- a/app/code/Magento/Indexer/etc/di.xml
+++ b/app/code/Magento/Indexer/etc/di.xml
@@ -8,10 +8,10 @@
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
     <preference for="Magento\Framework\Mview\View\State\CollectionInterface" type="Magento\Indexer\Model\Resource\Mview\View\State\Collection" />
     <preference for="Magento\Framework\Mview\View\StateInterface" type="Magento\Indexer\Model\Mview\View\State" />
-    <preference for="Magento\Indexer\Model\ConfigInterface" type="Magento\Indexer\Model\Config" />
-    <preference for="Magento\Indexer\Model\IndexerInterface" type="Magento\Indexer\Model\Indexer" />
-    <preference for="Magento\Indexer\Model\Indexer\Table\StrategyInterface" type="Magento\Indexer\Model\Indexer\Table\Strategy" />
-    <type name="Magento\Indexer\Model\Indexer\Table\StrategyInterface" shared="false" />
+    <preference for="Magento\Framework\Indexer\ConfigInterface" type="Magento\Indexer\Model\Config" />
+    <preference for="Magento\Framework\Indexer\IndexerInterface" type="Magento\Indexer\Model\Indexer" />
+    <preference for="Magento\Framework\Indexer\Table\StrategyInterface" type="Magento\Framework\Indexer\Table\Strategy" />
+    <type name="Magento\Framework\Indexer\Table\StrategyInterface" shared="false" />
     <type name="Magento\Indexer\Model\Indexer">
         <arguments>
             <argument name="view" xsi:type="object" shared="false">Magento\Framework\Mview\View</argument>
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Pdfdocs.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Pdfdocs.php
index 53dc90c91e2ed2ed012b9930cee501758de8957a..5b6e80aa8520309899d1c0632b5506cbb15e0a5e 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Pdfdocs.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Pdfdocs.php
@@ -78,6 +78,7 @@ class Pdfdocs extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassActi
      * @param InvoiceCollectionFactory $invoiceCollectionFactory
      * @param CreditmemoCollectionFactory $creditmemoCollectionFactory
      * @param OrderCollectionFactory $orderCollectionFactory
+     *
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Pdfshipments.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Pdfshipments.php
index 4c9b57a55558a8c0539f296c4ca3725bb5dcbce9..292eb6eadf11c02586dfab70b7feabfd20ac0578 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Pdfshipments.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Pdfshipments.php
@@ -17,7 +17,6 @@ use Magento\Sales\Model\Resource\Order\Shipment\CollectionFactory as ShipmentCol
 use Magento\Sales\Model\Resource\Order\CollectionFactory;
 
 /**
- * Class Pdfshipments
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
 class Pdfshipments extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassAction
diff --git a/app/code/Magento/Sales/Model/Resource/Grid/Collection.php b/app/code/Magento/Sales/Model/Resource/Grid/Collection.php
index 57d2d31060dcf63be012dc8851efb777452d8c09..041a27003ee90eb3c64040cee83c3cbf421f2c3f 100644
--- a/app/code/Magento/Sales/Model/Resource/Grid/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Grid/Collection.php
@@ -33,6 +33,7 @@ class Collection extends AbstractCollection implements SearchResultInterface
      * @param string $model
      * @param string|null $connection
      * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
+     *
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml
index c9f6758153c87762c1e3538ecf51913905ef5a1c..db861ca057aeaa5b04ec63f1f39ee76c4d652e08 100644
--- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml
+++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml
@@ -65,19 +65,6 @@
             <argument name="data" xsi:type="array">
                 <item name="config" xsi:type="array">
                     <item name="selectProvider" xsi:type="string">sales_order_creditmemo_grid.sales_order_creditmemo_grid.sales_order_creditmemo_columns.ids</item>
-                    <item name="displayArea" xsi:type="string">dataGridActions</item>
-                    <item name="options" xsi:type="array">
-                        <item name="cvs" xsi:type="array">
-                            <item name="value" xsi:type="string">csv</item>
-                            <item name="label" xsi:type="string" translate="true">CSV</item>
-                            <item name="url" xsi:type="string">mui/export/gridToCsv</item>
-                        </item>
-                        <item name="xml" xsi:type="array">
-                            <item name="value" xsi:type="string">xml</item>
-                            <item name="label" xsi:type="string" translate="true">Excel XML</item>
-                            <item name="url" xsi:type="string">mui/export/gridToCsv</item>
-                        </item>
-                    </item>
                 </item>
             </argument>
         </exportButton>
diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml
index df77cdd12091db44b14cf1ad6e4451121844ac9e..efae39c0634ca0427f119da5b99868b98f7f8e21 100644
--- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml
+++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml
@@ -73,19 +73,6 @@
             <argument name="data" xsi:type="array">
                 <item name="config" xsi:type="array">
                     <item name="selectProvider" xsi:type="string">sales_order_grid.sales_order_grid.sales_order_columns.ids</item>
-                    <item name="displayArea" xsi:type="string">dataGridActions</item>
-                    <item name="options" xsi:type="array">
-                        <item name="cvs" xsi:type="array">
-                            <item name="value" xsi:type="string">csv</item>
-                            <item name="label" xsi:type="string" translate="true">CSV</item>
-                            <item name="url" xsi:type="string">mui/export/gridToCsv</item>
-                        </item>
-                        <item name="xml" xsi:type="array">
-                            <item name="value" xsi:type="string">xml</item>
-                            <item name="label" xsi:type="string" translate="true">Excel XML</item>
-                            <item name="url" xsi:type="string">mui/export/gridToCsv</item>
-                        </item>
-                    </item>
                 </item>
             </argument>
         </exportButton>
diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_invoice_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_invoice_grid.xml
index 072539d481891b55cd7400c6f6ad8569f2559333..ad8b0d2a1f114fa89657f2f58f154fb9b3111113 100644
--- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_invoice_grid.xml
+++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_invoice_grid.xml
@@ -65,19 +65,6 @@
             <argument name="data" xsi:type="array">
                 <item name="config" xsi:type="array">
                     <item name="selectProvider" xsi:type="string">sales_order_invoice_grid.sales_order_invoice_grid.sales_order_invoice_columns.ids</item>
-                    <item name="displayArea" xsi:type="string">dataGridActions</item>
-                    <item name="options" xsi:type="array">
-                        <item name="cvs" xsi:type="array">
-                            <item name="value" xsi:type="string">csv</item>
-                            <item name="label" xsi:type="string" translate="true">CSV</item>
-                            <item name="url" xsi:type="string">mui/export/gridToCsv</item>
-                        </item>
-                        <item name="xml" xsi:type="array">
-                            <item name="value" xsi:type="string">xml</item>
-                            <item name="label" xsi:type="string" translate="true">Excel XML</item>
-                            <item name="url" xsi:type="string">mui/export/gridToCsv</item>
-                        </item>
-                    </item>
                 </item>
             </argument>
         </exportButton>
diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml
index 45ca566605822fc63496486374817beab555700f..5d18e373a00786b02e422b35fb40273e3752c505 100644
--- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml
+++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml
@@ -65,19 +65,6 @@
             <argument name="data" xsi:type="array">
                 <item name="config" xsi:type="array">
                     <item name="selectProvider" xsi:type="string">sales_order_shipment_grid.sales_order_shipment_grid.sales_order_shipment_columns.ids</item>
-                    <item name="displayArea" xsi:type="string">dataGridActions</item>
-                    <item name="options" xsi:type="array">
-                        <item name="cvs" xsi:type="array">
-                            <item name="value" xsi:type="string">csv</item>
-                            <item name="label" xsi:type="string" translate="true">CSV</item>
-                            <item name="url" xsi:type="string">mui/export/gridToCsv</item>
-                        </item>
-                        <item name="xml" xsi:type="array">
-                            <item name="value" xsi:type="string">xml</item>
-                            <item name="label" xsi:type="string" translate="true">Excel XML</item>
-                            <item name="url" xsi:type="string">mui/export/gridToCsv</item>
-                        </item>
-                    </item>
                 </item>
             </argument>
         </exportButton>
diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml
index 15b85280df3aa9f35d79069d7dd18d1e73b97010..ba4ad84692d97bc940578eb4ed7141e476ac10cb 100644
--- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml
+++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml
@@ -68,19 +68,6 @@
             <argument name="data" xsi:type="array">
                 <item name="config" xsi:type="array">
                     <item name="selectProvider" xsi:type="string">sales_order_view_creditmemo_grid.sales_order_view_creditmemo_grid.sales_order_view_creditmemo_columns.ids</item>
-                    <item name="displayArea" xsi:type="string">dataGridActions</item>
-                    <item name="options" xsi:type="array">
-                        <item name="cvs" xsi:type="array">
-                            <item name="value" xsi:type="string">csv</item>
-                            <item name="label" xsi:type="string" translate="true">CSV</item>
-                            <item name="url" xsi:type="string">sales/creditmemo/exportCsv</item>
-                        </item>
-                        <item name="xml" xsi:type="array">
-                            <item name="value" xsi:type="string">xml</item>
-                            <item name="label" xsi:type="string" translate="true">Excel XML</item>
-                            <item name="url" xsi:type="string">sales/creditmemo/exportExcel</item>
-                        </item>
-                    </item>
                 </item>
             </argument>
         </exportButton>
diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_invoice_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_invoice_grid.xml
index a194c0b37dc5eecec6a958ecaa2a2851d54f2bed..beb1b3caad9248033257fbe6a109e816fa798dea 100644
--- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_invoice_grid.xml
+++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_invoice_grid.xml
@@ -68,19 +68,6 @@
             <argument name="data" xsi:type="array">
                 <item name="config" xsi:type="array">
                     <item name="selectProvider" xsi:type="string">sales_order_view_invoice_grid.sales_order_view_invoice_grid.sales_order_view_invoice_columns.ids</item>
-                    <item name="displayArea" xsi:type="string">dataGridActions</item>
-                    <item name="options" xsi:type="array">
-                        <item name="cvs" xsi:type="array">
-                            <item name="value" xsi:type="string">csv</item>
-                            <item name="label" xsi:type="string" translate="true">CSV</item>
-                            <item name="url" xsi:type="string">mui/export/gridToCsv</item>
-                        </item>
-                        <item name="xml" xsi:type="array">
-                            <item name="value" xsi:type="string">xml</item>
-                            <item name="label" xsi:type="string" translate="true">Excel XML</item>
-                            <item name="url" xsi:type="string">mui/export/gridToCsv</item>
-                        </item>
-                    </item>
                 </item>
             </argument>
         </exportButton>
diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml
index 46fa0fc448aaabb7450c1e19e3c4dc677e005eb8..3fb4fbfe9c5dbb4c7118f6931d8fdd1b0b271b0e 100644
--- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml
+++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml
@@ -68,19 +68,6 @@
             <argument name="data" xsi:type="array">
                 <item name="config" xsi:type="array">
                     <item name="selectProvider" xsi:type="string">sales_order_view_shipment_grid.sales_order_view_shipment_grid.sales_order_view_shipment_columns.ids</item>
-                    <item name="displayArea" xsi:type="string">dataGridActions</item>
-                    <item name="options" xsi:type="array">
-                        <item name="cvs" xsi:type="array">
-                            <item name="value" xsi:type="string">csv</item>
-                            <item name="label" xsi:type="string" translate="true">CSV</item>
-                            <item name="url" xsi:type="string">mui/export/gridToCsv</item>
-                        </item>
-                        <item name="xml" xsi:type="array">
-                            <item name="value" xsi:type="string">xml</item>
-                            <item name="label" xsi:type="string" translate="true">Excel XML</item>
-                            <item name="url" xsi:type="string">mui/export/gridToCsv</item>
-                        </item>
-                    </item>
                 </item>
             </argument>
         </exportButton>
diff --git a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/MassPrintShippingLabel.php b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/MassPrintShippingLabel.php
index 027d8eeec6e7d7d89f1e91b19bcb0956e2095cc8..9db8516006b8e737fb6ac251e4c8898011324dd6 100644
--- a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/MassPrintShippingLabel.php
+++ b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/MassPrintShippingLabel.php
@@ -19,7 +19,6 @@ use Magento\Framework\Controller\ResultInterface;
 use Magento\Sales\Model\Resource\Order\CollectionFactory;
 
 /**
- * Class MassPrintShippingLabel
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
 class MassPrintShippingLabel extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassAction
diff --git a/app/code/Magento/Theme/view/adminhtml/page_layout/admin-1column.xml b/app/code/Magento/Theme/view/adminhtml/page_layout/admin-1column.xml
index f99d3f101fcbb03b08ef65e0d14a80696ea29f52..f71333df72624bd5873e5bc03d60be900a360c73 100644
--- a/app/code/Magento/Theme/view/adminhtml/page_layout/admin-1column.xml
+++ b/app/code/Magento/Theme/view/adminhtml/page_layout/admin-1column.xml
@@ -30,7 +30,7 @@
                         <container name="page.messages" as="page.messages"/>
                     </container>
                     <container name="page.main.container" as="page_main_container" htmlId="page:main-container" htmlTag="div" htmlClass="page-columns">
-                        <container name="admin.scope.col.wrap" as="admin-scope-col-wrap" htmlTag="div" htmlClass="admin__scope-old"> <!-- ToDo UI: remove this wrapper remove with old styles removal -->
+                        <container name="admin.scope.col.wrap" as="admin-scope-col-wrap" htmlTag="div" htmlClass="admin__old"> <!-- ToDo UI: remove this wrapper remove with old styles removal -->
                             <container name="main.col" as="main-col" htmlId="container" htmlTag="div" htmlClass="main-col">
                                 <container name="content" as="content"/>
                             </container>
diff --git a/app/code/Magento/Ui/Component/Filters/Type/AbstractFilter.php b/app/code/Magento/Ui/Component/Filters/Type/AbstractFilter.php
index b4381a4dbecdebeead9f3c20bdcf159705d5e873..02b8767c3e263d3d03d27e34441be4d58fdad407 100644
--- a/app/code/Magento/Ui/Component/Filters/Type/AbstractFilter.php
+++ b/app/code/Magento/Ui/Component/Filters/Type/AbstractFilter.php
@@ -38,7 +38,7 @@ abstract class AbstractFilter extends AbstractComponent
     protected $uiComponentFactory;
 
     /**
-     * @var \Magento\Framework\Api\FilterBuilder
+     * @var FilterBuilder
      */
     protected $filterBuilder;
 
diff --git a/app/code/Magento/Ui/Controller/Adminhtml/Export/GridToCsv.php b/app/code/Magento/Ui/Controller/Adminhtml/Export/GridToCsv.php
index 93be6f46466ff8fedad29fa8d8b495945e4b191d..158f90512c6a195bcca90c28b36a83e22b48e7c6 100644
--- a/app/code/Magento/Ui/Controller/Adminhtml/Export/GridToCsv.php
+++ b/app/code/Magento/Ui/Controller/Adminhtml/Export/GridToCsv.php
@@ -7,7 +7,6 @@ namespace Magento\Ui\Controller\Adminhtml\Export;
 
 use Magento\Backend\App\Action;
 use Magento\Backend\App\Action\Context;
-use Magento\Framework\View\Element\UiComponentFactory;
 use Magento\Ui\Model\Export\ConvertToCsv;
 use Magento\Framework\App\Response\Http\FileFactory;
 
@@ -16,11 +15,6 @@ use Magento\Framework\App\Response\Http\FileFactory;
  */
 class GridToCsv extends Action
 {
-    /**
-     * @var UiComponentFactory
-     */
-    protected $factory;
-
     /**
      * @var ConvertToCsv
      */
@@ -33,18 +27,15 @@ class GridToCsv extends Action
 
     /**
      * @param Context $context
-     * @param UiComponentFactory $factory
      * @param ConvertToCsv $converter
      * @param FileFactory $fileFactory
      */
     public function __construct(
         Context $context,
-        UiComponentFactory $factory,
         ConvertToCsv $converter,
         FileFactory $fileFactory
     ) {
         parent::__construct($context);
-        $this->factory = $factory;
         $this->converter = $converter;
         $this->fileFactory = $fileFactory;
     }
@@ -58,6 +49,5 @@ class GridToCsv extends Action
     public function execute()
     {
         return $this->fileFactory->create('export.csv', $this->converter->getCsvFile(), 'var');
-
     }
 }
diff --git a/app/code/Magento/Ui/Controller/Adminhtml/Export/GridToXml.php b/app/code/Magento/Ui/Controller/Adminhtml/Export/GridToXml.php
new file mode 100644
index 0000000000000000000000000000000000000000..f4de9d2da2b875fa5d45caf2a7f017dafe3c72b2
--- /dev/null
+++ b/app/code/Magento/Ui/Controller/Adminhtml/Export/GridToXml.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Ui\Controller\Adminhtml\Export;
+
+use Magento\Backend\App\Action;
+use Magento\Backend\App\Action\Context;
+use Magento\Ui\Model\Export\ConvertToXml;
+use Magento\Framework\App\Response\Http\FileFactory;
+
+/**
+ * Class Render
+ */
+class GridToXml extends Action
+{
+    /**
+     * @var ConvertToXml
+     */
+    protected $converter;
+
+    /**
+     * @var FileFactory
+     */
+    protected $fileFactory;
+
+    /**
+     * @param Context $context
+     * @param ConvertToXml $converter
+     * @param FileFactory $fileFactory
+     */
+    public function __construct(
+        Context $context,
+        ConvertToXml $converter,
+        FileFactory $fileFactory
+    ) {
+        parent::__construct($context);
+        $this->converter = $converter;
+        $this->fileFactory = $fileFactory;
+    }
+
+    /**
+     * Export data provider to XML
+     *
+     * @throws \Magento\Framework\Exception\LocalizedException
+     * @return \Magento\Framework\App\ResponseInterface
+     */
+    public function execute()
+    {
+        return $this->fileFactory->create('export.xml', $this->converter->getXmlFile(), 'var');
+    }
+}
diff --git a/app/code/Magento/Ui/Model/Export/ConvertToCsv.php b/app/code/Magento/Ui/Model/Export/ConvertToCsv.php
index 450ba515e3fc1b02c66f6baf7ebfec492a5a6472..9094805896dcb303348edcde2b62f1a824e81489 100644
--- a/app/code/Magento/Ui/Model/Export/ConvertToCsv.php
+++ b/app/code/Magento/Ui/Model/Export/ConvertToCsv.php
@@ -6,11 +6,10 @@
 namespace Magento\Ui\Model\Export;
 
 use Magento\Framework\App\Filesystem\DirectoryList;
+use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Filesystem;
+use Magento\Framework\Filesystem\Directory\WriteInterface;
 use Magento\Ui\Component\MassAction\Filter;
-use Magento\Framework\View\Element\UiComponentInterface;
-use Magento\Framework\Api\Search\DocumentInterface;
-use Magento\Framework\Data\OptionSourceInterface;
-use Magento\Ui\Component\Filters\Type\Select;
 
 /**
  * Class ConvertToCsv
@@ -18,212 +17,56 @@ use Magento\Ui\Component\Filters\Type\Select;
 class ConvertToCsv
 {
     /**
-     * @var \Magento\Framework\Filesystem\Directory\WriteInterface
+     * @var WriteInterface
      */
     protected $directory;
 
     /**
-     * @var Filter
+     * @var MetadataProvider
      */
-    protected $filter;
+    protected $metadataProvider;
 
     /**
-     * @var array
-     */
-    protected $columns;
-
-    /**
-     * @param \Magento\Framework\Filesystem $filesystem
+     * @param Filesystem $filesystem
      * @param Filter $filter
+     * @param MetadataProvider $metadataProvider
      */
     public function __construct(
-        \Magento\Framework\Filesystem $filesystem,
-        Filter $filter
+        Filesystem $filesystem,
+        Filter $filter,
+        MetadataProvider $metadataProvider
     ) {
         $this->filter = $filter;
         $this->directory = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR);
-    }
-
-    /**
-     * Returns Columns component
-     *
-     * @param UiComponentInterface $component
-     * @return UiComponentInterface
-     * @throws \Exception
-     */
-    protected function getColumnsComponent(UiComponentInterface $component)
-    {
-        foreach ($component->getChildComponents() as $childComponent) {
-            if ($childComponent instanceof \Magento\Ui\Component\Listing\Columns) {
-                return $childComponent;
-            }
-        }
-        throw new \Exception('No columns found');
-    }
-
-    /**
-     * Returns columns list
-     *
-     * @param UiComponentInterface $component
-     * @return UiComponentInterface[]
-     */
-    protected function getColumns(UiComponentInterface $component)
-    {
-        if (!isset($this->columns[$component->getName()])) {
-            $columns = $this->getColumnsComponent($component);
-            foreach ($columns->getChildComponents() as $column) {
-                $this->columns[$component->getName()][$column->getName()] = $column;
-            }
-        }
-        return $this->columns[$component->getName()];
-    }
-
-    /**
-     * Retrieve Headers row array for Export
-     *
-     * @param UiComponentInterface $component
-     * @return string[]
-     */
-    protected function getHeaders(UiComponentInterface $component)
-    {
-        $row = [];
-        foreach ($this->getColumns($component) as $column) {
-            if ($column->getData('config/label')) {
-                $row[] = $column->getData('config/label');
-            }
-        }
-        return $row;
-    }
-
-    /**
-     * Returns DB fields list
-     *
-     * @param UiComponentInterface $component
-     * @return array
-     */
-    protected function getFields(UiComponentInterface $component)
-    {
-        $row = [];
-        foreach ($this->getColumns($component) as $column) {
-            if ($column->getData('config/label')) {
-                $row[] = $column->getName();
-            }
-        }
-        return $row;
-    }
-
-    /**
-     * Returns row data
-     *
-     * @param DocumentInterface $document
-     * @param array $fields
-     * @param array $options
-     * @return array
-     */
-    protected function getRowData(DocumentInterface $document, $fields, $options)
-    {
-        $row = [];
-        foreach ($fields as $column) {
-            if (isset($options[$column])) {
-                $key = $document->getCustomAttribute($column)->getValue();
-                if (isset($options[$column][$key])) {
-                    $row[] = $options[$column][$key];
-                }
-                $row[] = '';
-            } else {
-                $row[] = $document->getCustomAttribute($column)->getValue();
-            }
-        }
-        return $row;
-    }
-
-    /**
-     * Returns complex option
-     *
-     * @param array $list
-     * @param string $label
-     * @param array $output
-     * @return void
-     */
-    protected function getComplexLabel($list, $label, &$output)
-    {
-        foreach ($list as $item) {
-            if (!is_array($item['value'])) {
-                $output[$item['value']] = $label . $item['label'];
-            } else {
-                $this->getComplexLabel($item['value'], $label . $item['label'], $output);
-            }
-        }
-    }
-
-    /**
-     * Returns array of Select options
-     *
-     * @param Select $filter
-     * @return array
-     */
-    protected function getFilterOptions(Select $filter)
-    {
-        $options = [];
-        foreach ($filter->getOptionProvider()->toOptionArray() as $option) {
-            if (!is_array($option['value'])) {
-                $options[$option['value']] = $option['label'];
-            } else {
-                $this->getComplexLabel(
-                    $option['value'],
-                    $option['label'],
-                    $options
-                );
-            }
-        }
-        return $options;
-    }
-    /**
-     * Returns Filters with options
-     *
-     * @return array
-     */
-    protected function getOptions()
-    {
-        $options = [];
-        $component = $this->filter->getComponent();
-        $childComponents = $component->getChildComponents();
-        $listingTop = $childComponents['listing_top'];
-        foreach ($listingTop->getChildComponents() as $child) {
-            if ($child instanceof \Magento\Ui\Component\Filters) {
-                foreach ($child->getChildComponents() as $filter) {
-                    if ($filter instanceof Select) {
-                        $options[$filter->getName()] = $this->getFilterOptions($filter);
-                    }
-                }
-            }
-        }
-        return $options;
+        $this->metadataProvider = $metadataProvider;
     }
 
     /**
      * Returns CSV file
      *
      * @return array
-     * @throws \Magento\Framework\Exception\LocalizedException
+     * @throws LocalizedException
      */
     public function getCsvFile()
     {
-        $options = $this->getOptions();
         $component = $this->filter->getComponent();
+
         $name = md5(microtime());
         $file = 'export/'. $component->getName() . $name . '.csv';
+
         $this->filter->prepareComponent($component);
         $this->filter->applySelectionOnTargetProvider();
+
         $searchResult = $component->getContext()->getDataProvider()->getSearchResult();
+        $fields = $this->metadataProvider->getFields($component);
+        $options = $this->metadataProvider->getOptions();
+
         $this->directory->create('export');
         $stream = $this->directory->openFile($file, 'w+');
-
-        $fields = $this->getFields($component);
         $stream->lock();
-        $stream->writeCsv($this->getHeaders($component));
+        $stream->writeCsv($this->metadataProvider->getHeaders($component));
         foreach ($searchResult->getItems() as $document) {
-            $stream->writeCsv($this->getRowData($document, $fields, $options));
+            $stream->writeCsv($this->metadataProvider->getRowData($document, $fields, $options));
         }
         $stream->unlock();
         $stream->close();
diff --git a/app/code/Magento/Ui/Model/Export/ConvertToXml.php b/app/code/Magento/Ui/Model/Export/ConvertToXml.php
new file mode 100644
index 0000000000000000000000000000000000000000..b1d943eeea863506cd7ed634f03577132ea18215
--- /dev/null
+++ b/app/code/Magento/Ui/Model/Export/ConvertToXml.php
@@ -0,0 +1,156 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Ui\Model\Export;
+
+use Magento\Framework\Api\Search\DocumentInterface;
+use Magento\Framework\Api\Search\SearchResultInterface;
+use Magento\Framework\App\Filesystem\DirectoryList;
+use Magento\Framework\Convert\Excel;
+use Magento\Framework\Convert\ExcelFactory;
+use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Filesystem;
+use Magento\Framework\Filesystem\Directory\WriteInterface;
+use Magento\Ui\Component\MassAction\Filter;
+
+/**
+ * Class ConvertToXml
+ */
+class ConvertToXml
+{
+    /**
+     * @var WriteInterface
+     */
+    protected $directory;
+
+    /**
+     * @var MetadataProvider
+     */
+    protected $metadataProvider;
+
+    /**
+     * @var ExcelFactory
+     */
+    protected $excelFactory;
+
+    /**
+     * @var array
+     */
+    protected $options;
+
+    /**
+     * @var SearchResultIteratorFactory
+     */
+    protected $iteratorFactory;
+
+    /**
+     * @var array
+     */
+    protected $fields;
+
+    /**
+     * @param Filesystem $filesystem
+     * @param Filter $filter
+     * @param MetadataProvider $metadataProvider
+     * @param ExcelFactory $excelFactory
+     * @param SearchResultIteratorFactory $iteratorFactory
+     */
+    public function __construct(
+        Filesystem $filesystem,
+        Filter $filter,
+        MetadataProvider $metadataProvider,
+        ExcelFactory $excelFactory,
+        SearchResultIteratorFactory $iteratorFactory
+    ) {
+        $this->filter = $filter;
+        $this->directory = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR);
+        $this->metadataProvider = $metadataProvider;
+        $this->excelFactory = $excelFactory;
+        $this->iteratorFactory = $iteratorFactory;
+    }
+
+    /**
+     * Returns Filters with options
+     *
+     * @return array
+     */
+    protected function getOptions()
+    {
+        if (!$this->options) {
+            $this->options = $this->metadataProvider->getOptions();
+        }
+        return $this->options;
+    }
+
+    /**
+     * Returns DB fields list
+     *
+     * @return array
+     */
+    protected function getFields()
+    {
+        if (!$this->fields) {
+            $component = $this->filter->getComponent();
+            $this->fields = $this->metadataProvider->getFields($component);
+        }
+        return $this->fields;
+    }
+
+    /**
+     * Returns row data
+     *
+     * @param DocumentInterface $document
+     * @return array
+     */
+    public function getRowData(DocumentInterface $document)
+    {
+        return $this->metadataProvider->getRowData($document, $this->getFields(), $this->getOptions());
+    }
+
+    /**
+     * Returns XML file
+     *
+     * @return array
+     * @throws LocalizedException
+     */
+    public function getXmlFile()
+    {
+        $component = $this->filter->getComponent();
+
+        $name = md5(microtime());
+        $file = 'export/'. $component->getName() . $name . '.xml';
+
+        $this->filter->prepareComponent($component);
+        $this->filter->applySelectionOnTargetProvider();
+
+        /** @var SearchResultInterface $searchResult */
+        $searchResult = $component->getContext()->getDataProvider()->getSearchResult();
+
+        /** @var SearchResultIterator $searchResultIterator */
+        $searchResultIterator = $this->iteratorFactory->create(['items' => $searchResult->getItems()]);
+
+        /** @var Excel $excel */
+        $excel = $this->excelFactory->create([
+            'iterator' => $searchResultIterator,
+            'rowCallback'=> [$this, 'getRowData'],
+        ]);
+
+        $this->directory->create('export');
+        $stream = $this->directory->openFile($file, 'w+');
+        $stream->lock();
+
+        $excel->setDataHeader($this->metadataProvider->getHeaders($component));
+        $excel->write($stream, $component->getName() . '.xml');
+
+        $stream->unlock();
+        $stream->close();
+
+        return [
+            'type' => 'filename',
+            'value' => $file,
+            'rm' => true  // can delete file after use
+        ];
+    }
+}
diff --git a/app/code/Magento/Ui/Model/Export/MetadataProvider.php b/app/code/Magento/Ui/Model/Export/MetadataProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..e9a95e914ed72647f5c11c575d33f721d30504fa
--- /dev/null
+++ b/app/code/Magento/Ui/Model/Export/MetadataProvider.php
@@ -0,0 +1,194 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Ui\Model\Export;
+
+use Magento\Framework\Api\Search\DocumentInterface;
+use Magento\Framework\View\Element\UiComponentInterface;
+use Magento\Ui\Component\Filters;
+use Magento\Ui\Component\Filters\Type\Select;
+use Magento\Ui\Component\Listing\Columns;
+use Magento\Ui\Component\MassAction\Filter;
+
+class MetadataProvider
+{
+    /**
+     * @var Filter
+     */
+    protected $filter;
+
+    /**
+     * @var array
+     */
+    protected $columns;
+
+    /**
+     * @param Filter $filter
+     */
+    public function __construct(
+        Filter $filter
+    ) {
+        $this->filter = $filter;
+    }
+
+    /**
+     * Returns Columns component
+     *
+     * @param UiComponentInterface $component
+     * @return UiComponentInterface
+     * @throws \Exception
+     */
+    protected function getColumnsComponent(UiComponentInterface $component)
+    {
+        foreach ($component->getChildComponents() as $childComponent) {
+            if ($childComponent instanceof Columns) {
+                return $childComponent;
+            }
+        }
+        throw new \Exception('No columns found');
+    }
+
+    /**
+     * Returns columns list
+     *
+     * @param UiComponentInterface $component
+     * @return UiComponentInterface[]
+     */
+    protected function getColumns(UiComponentInterface $component)
+    {
+        if (!isset($this->columns[$component->getName()])) {
+            $columns = $this->getColumnsComponent($component);
+            foreach ($columns->getChildComponents() as $column) {
+                $this->columns[$component->getName()][$column->getName()] = $column;
+            }
+        }
+        return $this->columns[$component->getName()];
+    }
+
+    /**
+     * Retrieve Headers row array for Export
+     *
+     * @param UiComponentInterface $component
+     * @return string[]
+     */
+    public function getHeaders(UiComponentInterface $component)
+    {
+        $row = [];
+        foreach ($this->getColumns($component) as $column) {
+            if ($column->getData('config/label')) {
+                $row[] = $column->getData('config/label');
+            }
+        }
+        return $row;
+    }
+
+    /**
+     * Returns DB fields list
+     *
+     * @param UiComponentInterface $component
+     * @return array
+     */
+    public function getFields(UiComponentInterface $component)
+    {
+        $row = [];
+        foreach ($this->getColumns($component) as $column) {
+            if ($column->getData('config/label')) {
+                $row[] = $column->getName();
+            }
+        }
+        return $row;
+    }
+
+    /**
+     * Returns row data
+     *
+     * @param DocumentInterface $document
+     * @param array $fields
+     * @param array $options
+     * @return array
+     */
+    public function getRowData(DocumentInterface $document, $fields, $options)
+    {
+        $row = [];
+        foreach ($fields as $column) {
+            if (isset($options[$column])) {
+                $key = $document->getCustomAttribute($column)->getValue();
+                if (isset($options[$column][$key])) {
+                    $row[] = $options[$column][$key];
+                } else {
+                    $row[] = '';
+                }
+            } else {
+                $row[] = $document->getCustomAttribute($column)->getValue();
+            }
+        }
+        return $row;
+    }
+
+    /**
+     * Returns complex option
+     *
+     * @param array $list
+     * @param string $label
+     * @param array $output
+     * @return void
+     */
+    protected function getComplexLabel($list, $label, &$output)
+    {
+        foreach ($list as $item) {
+            if (!is_array($item['value'])) {
+                $output[$item['value']] = $label . $item['label'];
+            } else {
+                $this->getComplexLabel($item['value'], $label . $item['label'], $output);
+            }
+        }
+    }
+
+    /**
+     * Returns array of Select options
+     *
+     * @param Select $filter
+     * @return array
+     */
+    protected function getFilterOptions(Select $filter)
+    {
+        $options = [];
+        foreach ($filter->getData('config/options') as $option) {
+            if (!is_array($option['value'])) {
+                $options[$option['value']] = $option['label'];
+            } else {
+                $this->getComplexLabel(
+                    $option['value'],
+                    $option['label'],
+                    $options
+                );
+            }
+        }
+        return $options;
+    }
+
+    /**
+     * Returns Filters with options
+     *
+     * @return array
+     */
+    public function getOptions()
+    {
+        $options = [];
+        $component = $this->filter->getComponent();
+        $childComponents = $component->getChildComponents();
+        $listingTop = $childComponents['listing_top'];
+        foreach ($listingTop->getChildComponents() as $child) {
+            if ($child instanceof Filters) {
+                foreach ($child->getChildComponents() as $filter) {
+                    if ($filter instanceof Select) {
+                        $options[$filter->getName()] = $this->getFilterOptions($filter);
+                    }
+                }
+            }
+        }
+        return $options;
+    }
+}
diff --git a/app/code/Magento/Ui/Model/Export/SearchResultIterator.php b/app/code/Magento/Ui/Model/Export/SearchResultIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..aa584c3f7e7e370f7bc87fdf8b6dcb4480f81389
--- /dev/null
+++ b/app/code/Magento/Ui/Model/Export/SearchResultIterator.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Ui\Model\Export;
+
+class SearchResultIterator implements \Iterator
+{
+    /**
+     * @var array
+     */
+    protected $items;
+
+    /**
+     * @param array $items
+     */
+    public function __construct(
+        array $items
+    ) {
+        $this->items = $items;
+    }
+
+    /**
+     * @return array|mixed
+     */
+    public function current()
+    {
+        return current($this->items);
+    }
+
+    /**
+     * @return int|mixed
+     */
+    public function key()
+    {
+        return key($this->items);
+    }
+
+    /**
+     * @return void
+     */
+    public function next()
+    {
+        next($this->items);
+    }
+
+    /**
+     * @return void
+     */
+    public function rewind()
+    {
+        reset($this->items);
+    }
+
+    /**
+     * @return bool
+     */
+    public function valid()
+    {
+        return (bool)$this->key();
+    }
+}
diff --git a/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Export/GridToCsvTest.php b/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Export/GridToCsvTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ad295672a6cad88dc5ab4bf3c3c0c918a28c467d
--- /dev/null
+++ b/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Export/GridToCsvTest.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Ui\Test\Unit\Controller\Adminhtml\Export;
+
+use Magento\Backend\App\Action\Context;
+use Magento\Framework\App\Response\Http\FileFactory;
+use Magento\Ui\Controller\Adminhtml\Export\GridToCsv;
+use Magento\Ui\Model\Export\ConvertToCsv;
+
+class GridToCsvTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var GridToCsv
+     */
+    protected $controller;
+
+    /**
+     * @var Context | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $context;
+
+    /**
+     * @var ConvertToCsv | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $converter;
+
+    /**
+     * @var FileFactory | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $fileFactory;
+
+    public function setUp()
+    {
+        $this->context = $this->getMockBuilder('Magento\Backend\App\Action\Context')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->converter = $this->getMockBuilder('Magento\Ui\Model\Export\ConvertToCsv')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->fileFactory = $this->getMockBuilder('Magento\Framework\App\Response\Http\FileFactory')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->controller = new GridToCsv(
+            $this->context,
+            $this->converter,
+            $this->fileFactory
+        );
+    }
+
+    public function testExecute()
+    {
+        $content = 'test';
+
+        $this->converter->expects($this->once())
+            ->method('getCsvFile')
+            ->willReturn($content);
+
+        $this->fileFactory->expects($this->once())
+            ->method('create')
+            ->with('export.csv', $content, 'var')
+            ->willReturn($content);
+
+        $this->assertEquals($content, $this->controller->execute());
+    }
+}
diff --git a/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Export/GridToXmlTest.php b/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Export/GridToXmlTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..427a14e42dd40a12b50d211f991a00751290f8d3
--- /dev/null
+++ b/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Export/GridToXmlTest.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Ui\Test\Unit\Controller\Adminhtml\Export;
+
+use Magento\Backend\App\Action\Context;
+use Magento\Framework\App\Response\Http\FileFactory;
+use Magento\Ui\Controller\Adminhtml\Export\GridToXml;
+use Magento\Ui\Model\Export\ConvertToXml;
+
+class GridToXmlTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var GridToXml
+     */
+    protected $controller;
+
+    /**
+     * @var Context | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $context;
+
+    /**
+     * @var ConvertToXml | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $converter;
+
+    /**
+     * @var FileFactory | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $fileFactory;
+
+    public function setUp()
+    {
+        $this->context = $this->getMockBuilder('Magento\Backend\App\Action\Context')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->converter = $this->getMockBuilder('Magento\Ui\Model\Export\ConvertToXml')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->fileFactory = $this->getMockBuilder('Magento\Framework\App\Response\Http\FileFactory')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->controller = new GridToXml(
+            $this->context,
+            $this->converter,
+            $this->fileFactory
+        );
+    }
+
+    public function testExecute()
+    {
+        $content = 'test';
+
+        $this->converter->expects($this->once())
+            ->method('getXmlFile')
+            ->willReturn($content);
+
+        $this->fileFactory->expects($this->once())
+            ->method('create')
+            ->with('export.xml', $content, 'var')
+            ->willReturn($content);
+
+        $this->assertEquals($content, $this->controller->execute());
+    }
+}
diff --git a/app/code/Magento/Ui/Test/Unit/Model/Export/ConvertToCsvTest.php b/app/code/Magento/Ui/Test/Unit/Model/Export/ConvertToCsvTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f54a9343b0b240ed5d1b388cdaf01e312a149e26
--- /dev/null
+++ b/app/code/Magento/Ui/Test/Unit/Model/Export/ConvertToCsvTest.php
@@ -0,0 +1,236 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Ui\Test\Unit\Model\Export;
+
+use Magento\Framework\App\Filesystem\DirectoryList;
+use Magento\Framework\Filesystem;
+use Magento\Framework\Filesystem\Directory\WriteInterface as DirectoryWriteInterface;
+use Magento\Framework\Filesystem\File\WriteInterface as FileWriteInterface;
+use Magento\Framework\View\Element\UiComponentInterface;
+use Magento\Ui\Component\MassAction\Filter;
+use Magento\Ui\Model\Export\ConvertToCsv;
+use Magento\Ui\Model\Export\MetadataProvider;
+
+class ConvertToCsvTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var ConvertToCsv
+     */
+    protected $model;
+
+    /**
+     * @var DirectoryWriteInterface | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $directory;
+
+    /**
+     * @var Filesystem | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $filesystem;
+
+    /**
+     * @var Filter | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $filter;
+
+    /**
+     * @var MetadataProvider | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $metadataProvider;
+
+    /**
+     * @var FileWriteInterface | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $stream;
+
+    /**
+     * @var UiComponentInterface | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $component;
+
+    public function setUp()
+    {
+        $this->directory = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\WriteInterface')
+            ->getMockForAbstractClass();
+
+        $this->filesystem = $this->getMockBuilder('Magento\Framework\Filesystem')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->filesystem->expects($this->any())
+            ->method('getDirectoryWrite')
+            ->with(DirectoryList::VAR_DIR)
+            ->willReturn($this->directory);
+
+        $this->filter = $this->getMockBuilder('Magento\Ui\Component\MassAction\Filter')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->metadataProvider = $this->getMockBuilder('Magento\Ui\Model\Export\MetadataProvider')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->component = $this->getMockBuilder('Magento\Framework\View\Element\UiComponentInterface')
+            ->getMockForAbstractClass();
+
+        $this->stream = $this->getMockBuilder('Magento\Framework\Filesystem\File\WriteInterface')
+            ->setMethods([
+                'lock',
+                'unlock',
+                'close',
+            ])
+            ->getMockForAbstractClass();
+
+        $this->model = new ConvertToCsv(
+            $this->filesystem,
+            $this->filter,
+            $this->metadataProvider
+        );
+    }
+
+    public function testGetCsvFile()
+    {
+        $componentName = 'component_name';
+        $data = ['data_value'];
+
+        $document = $this->getMockBuilder('Magento\Framework\Api\Search\DocumentInterface')
+            ->getMockForAbstractClass();
+
+        $this->mockComponent($componentName, [$document]);
+        $this->mockFilter();
+        $this->mockDirectory();
+
+        $this->stream->expects($this->once())
+            ->method('lock')
+            ->willReturnSelf();
+        $this->stream->expects($this->once())
+            ->method('unlock')
+            ->willReturnSelf();
+        $this->stream->expects($this->once())
+            ->method('close')
+            ->willReturnSelf();
+        $this->stream->expects($this->any())
+            ->method('writeCsv')
+            ->with($data)
+            ->willReturnSelf();
+
+        $this->metadataProvider->expects($this->once())
+            ->method('getOptions')
+            ->willReturn([]);
+        $this->metadataProvider->expects($this->once())
+            ->method('getHeaders')
+            ->with($this->component)
+            ->willReturn($data);
+        $this->metadataProvider->expects($this->once())
+            ->method('getFields')
+            ->with($this->component)
+            ->willReturn([]);
+        $this->metadataProvider->expects($this->once())
+            ->method('getRowData')
+            ->with($document, [], [])
+            ->willReturn($data);
+
+        $result = $this->model->getCsvFile();
+        $this->assertTrue(is_array($result));
+        $this->assertArrayHasKey('type', $result);
+        $this->assertArrayHasKey('value', $result);
+        $this->assertArrayHasKey('rm', $result);
+        $this->assertContains($componentName, $result);
+        $this->assertContains('.csv', $result);
+    }
+
+    /**
+     * @param array $expected
+     */
+    protected function mockStream($expected)
+    {
+        $this->stream = $this->getMockBuilder('Magento\Framework\Filesystem\File\WriteInterface')
+            ->setMethods([
+                'lock',
+                'unlock',
+                'close',
+            ])
+            ->getMockForAbstractClass();
+
+        $this->stream->expects($this->once())
+            ->method('lock')
+            ->willReturnSelf();
+        $this->stream->expects($this->once())
+            ->method('unlock')
+            ->willReturnSelf();
+        $this->stream->expects($this->once())
+            ->method('close')
+            ->willReturnSelf();
+        $this->stream->expects($this->once())
+            ->method('writeCsv')
+            ->with($expected)
+            ->willReturnSelf();
+    }
+
+    /**
+     * @param string $componentName
+     * @param array $items
+     */
+    protected function mockComponent($componentName, $items)
+    {
+        $context = $this->getMockBuilder('Magento\Framework\View\Element\UiComponent\ContextInterface')
+            ->setMethods(['getDataProvider'])
+            ->getMockForAbstractClass();
+
+        $dataProvider = $this->getMockBuilder(
+            'Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface'
+        )
+            ->setMethods(['getSearchResult'])
+            ->getMockForAbstractClass();
+
+        $searchResult = $this->getMockBuilder('Magento\Framework\Api\Search\SearchResultInterface')
+            ->setMethods(['getItems'])
+            ->getMockForAbstractClass();
+
+        $this->component->expects($this->any())
+            ->method('getName')
+            ->willReturn($componentName);
+        $this->component->expects($this->once())
+            ->method('getContext')
+            ->willReturn($context);
+
+        $context->expects($this->once())
+            ->method('getDataProvider')
+            ->willReturn($dataProvider);
+
+        $dataProvider->expects($this->once())
+            ->method('getSearchResult')
+            ->willReturn($searchResult);
+
+        $searchResult->expects($this->once())
+            ->method('getItems')
+            ->willReturn($items);
+    }
+
+    protected function mockFilter()
+    {
+        $this->filter->expects($this->once())
+            ->method('getComponent')
+            ->willReturn($this->component);
+        $this->filter->expects($this->once())
+            ->method('prepareComponent')
+            ->with($this->component)
+            ->willReturnSelf();
+        $this->filter->expects($this->once())
+            ->method('applySelectionOnTargetProvider')
+            ->willReturnSelf();
+    }
+
+    protected function mockDirectory()
+    {
+        $this->directory->expects($this->once())
+            ->method('create')
+            ->with('export')
+            ->willReturnSelf();
+        $this->directory->expects($this->once())
+            ->method('openFile')
+            ->willReturn($this->stream);
+    }
+}
diff --git a/app/code/Magento/Ui/Test/Unit/Model/Export/ConvertToXmlTest.php b/app/code/Magento/Ui/Test/Unit/Model/Export/ConvertToXmlTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b4eb36b5c4a5631ffce5aef6a7e323a15b27b3e4
--- /dev/null
+++ b/app/code/Magento/Ui/Test/Unit/Model/Export/ConvertToXmlTest.php
@@ -0,0 +1,280 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Ui\Test\Unit\Model\Export;
+
+use Magento\Framework\App\Filesystem\DirectoryList;
+use Magento\Framework\Convert\ExcelFactory;
+use Magento\Framework\Filesystem;
+use Magento\Framework\Filesystem\Directory\WriteInterface as DirectoryWriteInterface;
+use Magento\Framework\Filesystem\File\WriteInterface as FileWriteInterface;
+use Magento\Framework\View\Element\UiComponentInterface;
+use Magento\Ui\Component\MassAction\Filter;
+use Magento\Ui\Model\Export\ConvertToXml;
+use Magento\Ui\Model\Export\MetadataProvider;
+use Magento\Ui\Model\Export\SearchResultIteratorFactory;
+
+class ConvertToXmlTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var ConvertToXml
+     */
+    protected $model;
+
+    /**
+     * @var Filesystem | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $filesystem;
+
+    /**
+     * @var Filter | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $filter;
+
+    /**
+     * @var MetadataProvider | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $metadataProvider;
+
+    /**
+     * @var ExcelFactory | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $excelFactory;
+
+    /**
+     * @var SearchResultIteratorFactory | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $iteratorFactory;
+
+    /**
+     * @var DirectoryWriteInterface | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $directory;
+
+    /**
+     * @var FileWriteInterface | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $stream;
+
+    /**
+     * @var UiComponentInterface | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $component;
+
+    public function setUp()
+    {
+        $this->directory = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\WriteInterface')
+            ->getMockForAbstractClass();
+
+        $this->filesystem = $this->getMockBuilder('Magento\Framework\Filesystem')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->filesystem->expects($this->any())
+            ->method('getDirectoryWrite')
+            ->with(DirectoryList::VAR_DIR)
+            ->willReturn($this->directory);
+
+        $this->filter = $this->getMockBuilder('Magento\Ui\Component\MassAction\Filter')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->metadataProvider = $this->getMockBuilder('Magento\Ui\Model\Export\MetadataProvider')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->excelFactory = $this->getMockBuilder('Magento\Framework\Convert\ExcelFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+
+        $this->iteratorFactory = $this->getMockBuilder('Magento\Ui\Model\Export\SearchResultIteratorFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+
+        $this->component = $this->getMockBuilder('Magento\Framework\View\Element\UiComponentInterface')
+            ->getMockForAbstractClass();
+
+        $this->stream = $this->getMockBuilder('Magento\Framework\Filesystem\File\WriteInterface')
+            ->setMethods([
+                'lock',
+                'unlock',
+                'close',
+            ])
+            ->getMockForAbstractClass();
+
+        $this->model = new ConvertToXml(
+            $this->filesystem,
+            $this->filter,
+            $this->metadataProvider,
+            $this->excelFactory,
+            $this->iteratorFactory
+        );
+    }
+
+    public function testGetRowData()
+    {
+        $data = ['data_value'];
+
+        $document = $this->getMockBuilder('Magento\Framework\Api\Search\DocumentInterface')
+            ->getMockForAbstractClass();
+
+        $this->metadataProvider->expects($this->once())
+            ->method('getRowData')
+            ->with($document, [], [])
+            ->willReturn($data);
+        $this->metadataProvider->expects($this->once())
+            ->method('getFields')
+            ->with($this->component)
+            ->willReturn([]);
+        $this->metadataProvider->expects($this->once())
+            ->method('getOptions')
+            ->willReturn([]);
+
+        $this->filter->expects($this->once())
+            ->method('getComponent')
+            ->willReturn($this->component);
+
+        $result = $this->model->getRowData($document);
+        $this->assertEquals($data, $result);
+    }
+
+    public function testGetXmlFile()
+    {
+        $componentName = 'component_name';
+
+        $this->mockComponent($componentName);
+        $this->mockStream();
+        $this->mockFilter();
+        $this->mockDirectory();
+        $this->mockExcel($componentName);
+
+        $this->metadataProvider->expects($this->once())
+            ->method('getHeaders')
+            ->with($this->component)
+            ->willReturn([]);
+
+        $result = $this->model->getXmlFile();
+        $this->assertTrue(is_array($result));
+        $this->assertArrayHasKey('type', $result);
+        $this->assertArrayHasKey('value', $result);
+        $this->assertArrayHasKey('rm', $result);
+        $this->assertContains($componentName, $result);
+        $this->assertContains('.xml', $result);
+    }
+
+    protected function mockStream()
+    {
+        $this->stream->expects($this->once())
+            ->method('lock')
+            ->willReturnSelf();
+        $this->stream->expects($this->once())
+            ->method('unlock')
+            ->willReturnSelf();
+        $this->stream->expects($this->once())
+            ->method('close')
+            ->willReturnSelf();
+    }
+
+    /**
+     * @param string $componentName
+     */
+    protected function mockExcel($componentName)
+    {
+        $searchResultIterator = $this->getMockBuilder('Magento\Ui\Model\Export\SearchResultIterator')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $excel = $this->getMockBuilder('Magento\Framework\Convert\Excel')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->iteratorFactory->expects($this->once())
+            ->method('create')
+            ->with(['items' => []])
+            ->willReturn($searchResultIterator);
+
+        $this->excelFactory->expects($this->once())
+            ->method('create')
+            ->with([
+                'iterator' => $searchResultIterator,
+                'rowCallback' => [$this->model, 'getRowData'],
+            ])
+            ->willReturn($excel);
+
+        $excel->expects($this->once())
+            ->method('setDataHeader')
+            ->with([])
+            ->willReturnSelf();
+        $excel->expects($this->once())
+            ->method('write')
+            ->with($this->stream, $componentName . '.xml')
+            ->willReturnSelf();
+    }
+
+    /**
+     * @param string $componentName
+     */
+    protected function mockComponent($componentName)
+    {
+        $context = $this->getMockBuilder('Magento\Framework\View\Element\UiComponent\ContextInterface')
+            ->setMethods(['getDataProvider'])
+            ->getMockForAbstractClass();
+
+        $dataProvider = $this->getMockBuilder(
+            'Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface'
+        )
+            ->setMethods(['getSearchResult'])
+            ->getMockForAbstractClass();
+
+        $searchResult = $this->getMockBuilder('Magento\Framework\Api\Search\SearchResultInterface')
+            ->setMethods(['getItems'])
+            ->getMockForAbstractClass();
+
+        $this->component->expects($this->any())
+            ->method('getName')
+            ->willReturn($componentName);
+        $this->component->expects($this->once())
+            ->method('getContext')
+            ->willReturn($context);
+
+        $context->expects($this->once())
+            ->method('getDataProvider')
+            ->willReturn($dataProvider);
+
+        $dataProvider->expects($this->once())
+            ->method('getSearchResult')
+            ->willReturn($searchResult);
+
+        $searchResult->expects($this->once())
+            ->method('getItems')
+            ->willReturn([]);
+    }
+
+    protected function mockFilter()
+    {
+        $this->filter->expects($this->once())
+            ->method('getComponent')
+            ->willReturn($this->component);
+        $this->filter->expects($this->once())
+            ->method('prepareComponent')
+            ->with($this->component)
+            ->willReturnSelf();
+        $this->filter->expects($this->once())
+            ->method('applySelectionOnTargetProvider')
+            ->willReturnSelf();
+    }
+
+    protected function mockDirectory()
+    {
+        $this->directory->expects($this->once())
+            ->method('create')
+            ->with('export')
+            ->willReturnSelf();
+        $this->directory->expects($this->once())
+            ->method('openFile')
+            ->willReturn($this->stream);
+    }
+}
diff --git a/app/code/Magento/Ui/Test/Unit/Model/Export/MetadataProviderTest.php b/app/code/Magento/Ui/Test/Unit/Model/Export/MetadataProviderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9b86aae40d279e8a2670405c2befb2875857d644
--- /dev/null
+++ b/app/code/Magento/Ui/Test/Unit/Model/Export/MetadataProviderTest.php
@@ -0,0 +1,290 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Ui\Test\Unit\Model\Export;
+
+use Magento\Ui\Component\MassAction\Filter;
+use Magento\Ui\Model\Export\MetadataProvider;
+
+class MetadataProviderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var MetadataProvider
+     */
+    protected $model;
+
+    /**
+     * @var Filter | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $filter;
+
+    public function setUp()
+    {
+        $this->filter = $this->getMockBuilder('Magento\Ui\Component\MassAction\Filter')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->model = new MetadataProvider(
+            $this->filter
+        );
+    }
+
+    public function testGetHeaders()
+    {
+        $componentName = 'component_name';
+        $columnName = 'column_name';
+        $columnLabel = 'column_label';
+
+        $component = $this->prepareColumns($componentName, $columnName, $columnLabel);
+
+        $result = $this->model->getHeaders($component);
+        $this->assertTrue(is_array($result));
+        $this->assertCount(1, $result);
+        $this->assertEquals($columnLabel, $result[0]);
+    }
+
+    public function testGetFields()
+    {
+        $componentName = 'component_name';
+        $columnName = 'column_name';
+        $columnLabel = 'column_label';
+
+        $component = $this->prepareColumns($componentName, $columnName, $columnLabel);
+
+        $result = $this->model->getFields($component);
+        $this->assertTrue(is_array($result));
+        $this->assertCount(1, $result);
+        $this->assertEquals($columnName, $result[0]);
+    }
+
+    /**
+     * @param $componentName
+     * @param $columnName
+     * @param $columnLabel
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function prepareColumns($componentName, $columnName, $columnLabel)
+    {
+        $component = $this->getMockBuilder('Magento\Framework\View\Element\UiComponentInterface')
+            ->getMockForAbstractClass();
+
+        $columns = $this->getMockBuilder('Magento\Ui\Component\Listing\Columns')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $column = $this->getMockBuilder('Magento\Ui\Component\Listing\Columns\Column')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $component->expects($this->any())
+            ->method('getName')
+            ->willReturn($componentName);
+        $component->expects($this->once())
+            ->method('getChildComponents')
+            ->willReturn([$columns]);
+
+        $columns->expects($this->once())
+            ->method('getChildComponents')
+            ->willReturn([$column]);
+
+        $column->expects($this->any())
+            ->method('getName')
+            ->willReturn($columnName);
+        $column->expects($this->any())
+            ->method('getData')
+            ->with('config/label')
+            ->willReturn($columnLabel);
+        return $component;
+    }
+
+    /**
+     * @param string $key
+     * @param array $fields
+     * @param array $options
+     * @param array $expected
+     * @dataProvider getRowDataProvider
+     */
+    public function testGetRowData($key, $fields, $options, $expected)
+    {
+        $document = $this->getMockBuilder('Magento\Framework\Api\Search\DocumentInterface')
+            ->getMockForAbstractClass();
+
+        $attribute = $this->getMockBuilder('Magento\Framework\Api\AttributeInterface')
+            ->getMockForAbstractClass();
+
+        $document->expects($this->once())
+            ->method('getCustomAttribute')
+            ->with($fields[0])
+            ->willReturn($attribute);
+
+        $attribute->expects($this->once())
+            ->method('getValue')
+            ->willReturn($key);
+
+        $result = $this->model->getRowData($document, $fields, $options);
+        $this->assertTrue(is_array($result));
+        $this->assertCount(1, $result);
+        $this->assertEquals($expected, $result);
+    }
+
+    /**
+     * @return array
+     */
+    public function getRowDataProvider()
+    {
+        return [
+            [
+                'key' => 'key_1',
+                'fields' => ['column'],
+                'options' => [
+                    'column' => [
+                        'key_1' => 'value_1',
+                    ],
+                ],
+                'expected' => [
+                    'value_1',
+                ],
+            ],
+            [
+                'key' => 'key_2',
+                'fields' => ['column'],
+                'options' => [
+                    'column' => [
+                        'key_1' => 'value_1',
+                    ],
+                ],
+                'expected' => [
+                    '',
+                ],
+            ],
+            [
+                'key' => 'key_1',
+                'fields' => ['column'],
+                'options' => [],
+                'expected' => [
+                    'key_1',
+                ],
+            ],
+        ];
+    }
+
+    /**
+     * @param string $filter
+     * @param array $options
+     * @param array $expected
+     * @dataProvider getOptionsDataProvider
+     */
+    public function testGetOptions($filter, $options, $expected)
+    {
+        $component = $this->getMockBuilder('Magento\Framework\View\Element\UiComponentInterface')
+            ->getMockForAbstractClass();
+
+        $childComponent = $this->getMockBuilder('Magento\Framework\View\Element\UiComponentInterface')
+            ->getMockForAbstractClass();
+
+        $filters = $this->getMockBuilder('Magento\Ui\Component\Filters')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $select = $this->getMockBuilder('Magento\Ui\Component\Filters\Type\Select')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->filter->expects($this->once())
+            ->method('getComponent')
+            ->willReturn($component);
+
+        $component->expects($this->once())
+            ->method('getChildComponents')
+            ->willReturn(['listing_top' => $childComponent]);
+
+        $childComponent->expects($this->once())
+            ->method('getChildComponents')
+            ->willReturn([$filters]);
+
+        $filters->expects($this->once())
+            ->method('getChildComponents')
+            ->willReturn([$select]);
+
+        $select->expects($this->any())
+            ->method('getName')
+            ->willReturn($filter);
+        $select->expects($this->any())
+            ->method('getData')
+            ->with('config/options')
+            ->willReturn($options);
+
+        $result = $this->model->getOptions();
+        $this->assertTrue(is_array($result));
+        $this->assertCount(1, $result);
+        $this->assertEquals($expected, $result);
+    }
+
+    /**
+     * @return array
+     */
+    public function getOptionsDataProvider()
+    {
+        return [
+            [
+                'filter' => 'filter_name',
+                'options' => [
+                    [
+                        'value' => 'value_1',
+                        'label' => 'label_1',
+                    ]
+                ],
+                'expected' => [
+                    'filter_name' => [
+                        'value_1' => 'label_1',
+                    ],
+                ],
+            ],
+            [
+                'filter' => 'filter_name',
+                'options' => [
+                    [
+                        'value' => [
+                            [
+                                'value' => 'value_2',
+                                'label' => 'label_2',
+                            ],
+                        ],
+                        'label' => 'label_1',
+                    ]
+                ],
+                'expected' => [
+                    'filter_name' => [
+                        'value_2' => 'label_1label_2',
+                    ],
+                ],
+            ],
+            [
+                'filter' => 'filter_name',
+                'options' => [
+                    [
+                        'value' => [
+                            [
+                                'value' => [
+                                    [
+                                        'value' => 'value_3',
+                                        'label' => 'label_3',
+                                    ]
+                                ],
+                                'label' => 'label_2',
+                            ],
+                        ],
+                        'label' => 'label_1',
+                    ]
+                ],
+                'expected' => [
+                    'filter_name' => [
+                        'value_3' => 'label_1label_2label_3',
+                    ],
+                ],
+            ],
+        ];
+    }
+}
diff --git a/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml b/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml
index 0444e19e30edfcee3fe252168f7f6a718067f058..75349c69df7ac71f61a7effcd3c84f89922b6041 100755
--- a/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml
+++ b/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml
@@ -283,6 +283,21 @@
             <item name="js_config" xsi:type="array">
                 <item name="component" xsi:type="string">Magento_Ui/js/grid/export</item>
             </item>
+            <item name="config" xsi:type="array">
+                <item name="displayArea" xsi:type="string">dataGridActions</item>
+                <item name="options" xsi:type="array">
+                    <item name="cvs" xsi:type="array">
+                        <item name="value" xsi:type="string">csv</item>
+                        <item name="label" xsi:type="string" translate="true">CSV</item>
+                        <item name="url" xsi:type="string">mui/export/gridToCsv</item>
+                    </item>
+                    <item name="xml" xsi:type="array">
+                        <item name="value" xsi:type="string">xml</item>
+                        <item name="label" xsi:type="string" translate="true">Excel XML</item>
+                        <item name="url" xsi:type="string">mui/export/gridToXml</item>
+                    </item>
+                </item>
+            </item>
         </argument>
     </exportButton>
 </components>
diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressMetadataTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressMetadataTest.php
index 22b3c02f692894363ff87734eb8864791f45d854..566c2159129933a6f92e9b1d2039279b9c91830a 100644
--- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressMetadataTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressMetadataTest.php
@@ -61,23 +61,27 @@ class AddressMetadataTest extends WebapiAbstract
             Address::POSTCODE => [
                 Address::POSTCODE,
                 [
-                    AttributeMetadata::ATTRIBUTE_CODE => 'postcode',
                     AttributeMetadata::FRONTEND_INPUT => 'text',
                     AttributeMetadata::INPUT_FILTER => '',
                     AttributeMetadata::STORE_LABEL => 'Zip/Postal Code',
+                    AttributeMetadata::MULTILINE_COUNT => 0,
                     AttributeMetadata::VALIDATION_RULES => [],
                     AttributeMetadata::VISIBLE => true,
                     AttributeMetadata::REQUIRED => false,
-                    AttributeMetadata::MULTILINE_COUNT => 0,
                     AttributeMetadata::DATA_MODEL => 'Magento\Customer\Model\Attribute\Data\Postcode',
                     AttributeMetadata::OPTIONS => [],
                     AttributeMetadata::FRONTEND_CLASS => '',
+                    AttributeMetadata::USER_DEFINED => false,
+                    AttributeMetadata::SORT_ORDER => 110,
                     AttributeMetadata::FRONTEND_LABEL => 'Zip/Postal Code',
                     AttributeMetadata::NOTE => '',
                     AttributeMetadata::SYSTEM => true,
-                    AttributeMetadata::USER_DEFINED => false,
                     AttributeMetadata::BACKEND_TYPE => 'static',
-                    AttributeMetadata::SORT_ORDER => 110
+                    AttributeMetadata::IS_USED_IN_GRID => true,
+                    AttributeMetadata::IS_VISIBLE_IN_GRID => true,
+                    AttributeMetadata::IS_FILTERABLE_IN_GRID => true,
+                    AttributeMetadata::IS_SEARCHABLE_IN_GRID => true,
+                    AttributeMetadata::ATTRIBUTE_CODE => 'postcode',
                 ],
             ]
         ];
diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerMetadataTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerMetadataTest.php
index 21a80b605d33b9781aefd4f7d64760c37f91570b..02f0f13f95d34d2c4bfac455b09b604117c7b753 100644
--- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerMetadataTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerMetadataTest.php
@@ -62,39 +62,43 @@ class CustomerMetadataTest extends WebapiAbstract
             Customer::FIRSTNAME => [
                 Customer::FIRSTNAME,
                 [
-                    AttributeMetadata::ATTRIBUTE_CODE   => 'firstname',
                     AttributeMetadata::FRONTEND_INPUT   => 'text',
                     AttributeMetadata::INPUT_FILTER     => '',
                     AttributeMetadata::STORE_LABEL      => 'First Name',
+                    AttributeMetadata::MULTILINE_COUNT  => 0,
                     AttributeMetadata::VALIDATION_RULES => [
                         ['name' => 'min_text_length', 'value' => 1],
                         ['name' => 'max_text_length', 'value' => 255],
                     ],
                     AttributeMetadata::VISIBLE          => true,
                     AttributeMetadata::REQUIRED         => true,
-                    AttributeMetadata::MULTILINE_COUNT  => 0,
                     AttributeMetadata::DATA_MODEL       => '',
                     AttributeMetadata::OPTIONS          => [],
                     AttributeMetadata::FRONTEND_CLASS   => ' required-entry',
+                    AttributeMetadata::USER_DEFINED     => false,
+                    AttributeMetadata::SORT_ORDER       => 40,
                     AttributeMetadata::FRONTEND_LABEL   => 'First Name',
                     AttributeMetadata::NOTE             => '',
                     AttributeMetadata::SYSTEM           => true,
-                    AttributeMetadata::USER_DEFINED     => false,
                     AttributeMetadata::BACKEND_TYPE     => 'static',
-                    AttributeMetadata::SORT_ORDER       => 40
+                    AttributeMetadata::IS_USED_IN_GRID  => '',
+                    AttributeMetadata::IS_VISIBLE_IN_GRID => '',
+                    AttributeMetadata::IS_FILTERABLE_IN_GRID => '',
+                    AttributeMetadata::IS_SEARCHABLE_IN_GRID => '',
+                    AttributeMetadata::ATTRIBUTE_CODE   => 'firstname',
+
                 ],
             ],
             Customer::GENDER => [
                 Customer::GENDER,
                 [
-                    AttributeMetadata::ATTRIBUTE_CODE   => 'gender',
                     AttributeMetadata::FRONTEND_INPUT   => 'select',
                     AttributeMetadata::INPUT_FILTER     => '',
                     AttributeMetadata::STORE_LABEL      => 'Gender',
+                    AttributeMetadata::MULTILINE_COUNT  => 0,
                     AttributeMetadata::VALIDATION_RULES => [],
                     AttributeMetadata::VISIBLE          => false,
                     AttributeMetadata::REQUIRED         => false,
-                    AttributeMetadata::MULTILINE_COUNT  => 0,
                     AttributeMetadata::DATA_MODEL       => '',
                     AttributeMetadata::OPTIONS          => [
                         ['label' => '', 'value' => ''],
@@ -102,37 +106,46 @@ class CustomerMetadataTest extends WebapiAbstract
                         ['label' => 'Female', 'value' => '2'],
                     ],
                     AttributeMetadata::FRONTEND_CLASS   => '',
+                    AttributeMetadata::USER_DEFINED     => false,
+                    AttributeMetadata::SORT_ORDER       => 110,
                     AttributeMetadata::FRONTEND_LABEL   => 'Gender',
                     AttributeMetadata::NOTE             => '',
                     AttributeMetadata::SYSTEM           => false,
-                    AttributeMetadata::USER_DEFINED     => false,
                     AttributeMetadata::BACKEND_TYPE     => 'static',
-                    AttributeMetadata::SORT_ORDER       => 110
+                    AttributeMetadata::IS_USED_IN_GRID  => true,
+                    AttributeMetadata::IS_VISIBLE_IN_GRID => true,
+                    AttributeMetadata::IS_FILTERABLE_IN_GRID => true,
+                    AttributeMetadata::IS_SEARCHABLE_IN_GRID => '',
+                    AttributeMetadata::ATTRIBUTE_CODE   => 'gender',
                 ],
             ],
             Customer::WEBSITE_ID => [
                 Customer::WEBSITE_ID,
                 [
-                    AttributeMetadata::ATTRIBUTE_CODE   => 'website_id',
                     AttributeMetadata::FRONTEND_INPUT   => 'select',
                     AttributeMetadata::INPUT_FILTER     => '',
                     AttributeMetadata::STORE_LABEL      => 'Associate to Website',
+                    AttributeMetadata::MULTILINE_COUNT  => 0,
                     AttributeMetadata::VALIDATION_RULES => [],
                     AttributeMetadata::VISIBLE          => true,
                     AttributeMetadata::REQUIRED         => true,
-                    AttributeMetadata::MULTILINE_COUNT  => 0,
                     AttributeMetadata::DATA_MODEL       => '',
                     AttributeMetadata::OPTIONS          => [
                         ['label' => 'Admin', 'value' => '0'],
                         ['label' => 'Main Website', 'value' => '1'],
                     ],
                     AttributeMetadata::FRONTEND_CLASS   => ' required-entry',
+                    AttributeMetadata::USER_DEFINED     => false,
+                    AttributeMetadata::SORT_ORDER       => 10,
                     AttributeMetadata::FRONTEND_LABEL   => 'Associate to Website',
                     AttributeMetadata::NOTE             => '',
                     AttributeMetadata::SYSTEM           => true,
-                    AttributeMetadata::USER_DEFINED     => false,
                     AttributeMetadata::BACKEND_TYPE     => 'static',
-                    AttributeMetadata::SORT_ORDER       => 10
+                    AttributeMetadata::IS_USED_IN_GRID  => true,
+                    AttributeMetadata::IS_VISIBLE_IN_GRID => true,
+                    AttributeMetadata::IS_FILTERABLE_IN_GRID => true,
+                    AttributeMetadata::IS_SEARCHABLE_IN_GRID => '',
+                    AttributeMetadata::ATTRIBUTE_CODE   => 'website_id',
                 ],
             ]
         ];
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/CustomerGrid.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/CustomerGrid.php
index 4db5cf7a13f08193310c6845369e0c7104002506..143aea42acbd08eca136bee3a9aaaed90b5b2c85 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/CustomerGrid.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/CustomerGrid.php
@@ -6,14 +6,14 @@
 
 namespace Magento\Customer\Test\Block\Adminhtml;
 
-use Magento\Backend\Test\Block\Widget\Grid as AbstractGrid;
+use Magento\Ui\Test\Block\Adminhtml\DataGrid;
 
 /**
  * Class CustomerGrid
  * Backend customer grid
  *
  */
-class CustomerGrid extends AbstractGrid
+class CustomerGrid extends DataGrid
 {
     /**
      * Selector for action option select
@@ -29,13 +29,13 @@ class CustomerGrid extends AbstractGrid
      */
     protected $filters = [
         'name' => [
-            'selector' => '#customerGrid_filter_name',
+            'selector' => '.admin__data-grid-filters input[name*=name]',
         ],
         'email' => [
-            'selector' => '#customerGrid_filter_email',
+            'selector' => '.admin__data-grid-filters input[name*=email]',
         ],
         'group' => [
-            'selector' => '#customerGrid_filter_group',
+            'selector' => '.admin__data-grid-filters select[name*=group_id]',
             'input' => 'select',
         ],
     ];
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php
index 2d8f5faf09f8860b6d20b3e5a08bdc2ca5b21c0f..0d8ca0ccb63bb3b21eab5ec2b9aa0bd7a5c58309 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php
@@ -120,14 +120,22 @@ class Curl extends AbstractCurl implements CustomerInterface
      */
     protected function getCustomerId($email)
     {
-        $url = $_ENV['app_backend_url'] . 'customer/index/grid/filter/' . $this->encodeFilter(['email' => $email]);
+        $url = $_ENV['app_backend_url'] . 'mui/index/render/';
+        $data = [
+            'namespace' => 'customer_listing',
+            'filters' => [
+                'placeholder' => true,
+                'email' => $email
+            ],
+            'isAjax' => true
+        ];
         $curl = new BackendDecorator(new CurlTransport(), $this->_configuration);
 
-        $curl->write(CurlInterface::GET, $url, '1.0');
+        $curl->write(CurlInterface::POST, $url, '1.0', [], $data);
         $response = $curl->read();
         $curl->close();
 
-        preg_match('/data-column="entity_id"[^>]*>\s*([0-9]+)\s*</', $response, $match);
+        preg_match('/customer_listing_data_source.+items.+"entity_id":"(\d+)"/', $response, $match);
         return empty($match[1]) ? null : $match[1];
     }
 
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/Adminhtml/CustomerIndex.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/Adminhtml/CustomerIndex.xml
index f9ffc10bcee200ab1399206e93a0a89392fd4550..ee3fb870a3e8463d68c72641128c9d9e55e9a99d 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/Adminhtml/CustomerIndex.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/Adminhtml/CustomerIndex.xml
@@ -9,6 +9,6 @@
   <page name="CustomerIndex" area="Adminhtml" mca="customer/index" module="Magento_Customer">
     <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator="#messages" strategy="css selector"/>
     <block name="pageActionsBlock" class="Magento\Backend\Test\Block\GridPageActions" locator=".page-main-actions" strategy="css selector"/>
-    <block name="customerGridBlock" class="Magento\Customer\Test\Block\Adminhtml\CustomerGrid" locator="#customerGrid" strategy="css selector"/>
+    <block name="customerGridBlock" class="Magento\Customer\Test\Block\Adminhtml\CustomerGrid" locator=".admin__data-grid-outer-wrap" strategy="css selector"/>
   </page>
 </config>
diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/TypeTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/TypeTest.php
index fbf6e31bde66ee28693c2860defe67109b8d8b0c..d58a2c767a30c3921053836c17e88d3199b345c6 100644
--- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/TypeTest.php
+++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/TypeTest.php
@@ -19,7 +19,7 @@ class TypeTest extends \PHPUnit_Framework_TestCase
     /**
      * Full reindex
      *
-     * @var \Magento\Indexer\Model\IndexerInterface
+     * @var \Magento\Framework\Indexer\IndexerInterface
      */
     protected $indexer;
 
@@ -39,8 +39,8 @@ class TypeTest extends \PHPUnit_Framework_TestCase
     {
         $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
 
-        /** @var \Magento\Indexer\Model\IndexerRegistry $indexerRegistry */
-        $indexerRegistry = $this->objectManager->create('\Magento\Indexer\Model\IndexerRegistry');
+        /** @var \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry */
+        $indexerRegistry = $this->objectManager->create('\Magento\Framework\Indexer\IndexerRegistry');
         $this->indexer =  $indexerRegistry->get('catalogsearch_fulltext');
 
         $this->resource = $this->objectManager->get('Magento\Framework\App\Resource');
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Category/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Category/ProductTest.php
index c00277e7a8678bac67fad3327abfa1cd101dbd43..d95e25740a0607a14a8334d7fe49562301ff1746 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Category/ProductTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Category/ProductTest.php
@@ -17,7 +17,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
     const DEFAULT_ROOT_CATEGORY = 2;
 
     /**
-     * @var \Magento\Indexer\Model\IndexerInterface
+     * @var \Magento\Framework\Indexer\IndexerInterface
      */
     protected $indexer;
 
@@ -28,7 +28,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
-        /** @var \Magento\Indexer\Model\IndexerInterface indexer */
+        /** @var \Magento\Framework\Indexer\IndexerInterface indexer */
         $this->indexer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
             'Magento\Indexer\Model\Indexer'
         );
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/FlatTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/FlatTest.php
index f1a3d2ae598007a9282b0aa2a4b8fe7c49ac5011..0cd782e244401cc1d0a060e418cb80c7bf442844 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/FlatTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/FlatTest.php
@@ -78,7 +78,7 @@ class FlatTest extends \PHPUnit_Framework_TestCase
      */
     public function testReindexAll()
     {
-        /** @var  $indexer \Magento\Indexer\Model\IndexerInterface */
+        /** @var  $indexer \Magento\Framework\Indexer\IndexerInterface */
         $indexer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
             'Magento\Indexer\Model\Indexer'
         );
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/enable_reindex_schedule.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/enable_reindex_schedule.php
index bd3446ce56de43f5aa7834939382400d7e39840c..cc06391fd1f96eb7a14356c4f0f90fc643801bf9 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/_files/enable_reindex_schedule.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/enable_reindex_schedule.php
@@ -4,7 +4,7 @@
  * See COPYING.txt for license details.
  */
 
-/* @var \Magento\Indexer\Model\IndexerInterface $model */
-$model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Indexer\Model\IndexerRegistry')
+/* @var \Magento\Framework\Indexer\IndexerInterface $model */
+$model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Indexer\IndexerRegistry')
     ->get('catalogsearch_fulltext');
 $model->setScheduled(true);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/enable_reindex_schedule_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/enable_reindex_schedule_rollback.php
index 7990287681a4869d829e2b02a475575e881608ba..77aefe8f867b6b35ecf971fbc06550c3a9ac8371 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/_files/enable_reindex_schedule_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/enable_reindex_schedule_rollback.php
@@ -4,7 +4,7 @@
  * See COPYING.txt for license details.
  */
 
-/* @var \Magento\Indexer\Model\IndexerInterface $model */
-$model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Indexer\Model\IndexerRegistry')
+/* @var \Magento\Framework\Indexer\IndexerInterface $model */
+$model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Indexer\IndexerRegistry')
     ->get('catalogsearch_fulltext');
 $model->setScheduled(false);
diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/FulltextTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/FulltextTest.php
index f0dd6a8901dd0c4fbc2abf859aaa1f1e7c0504c0..d74e750cf109ebcd232d3c9d588f273f112f359b 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/FulltextTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/FulltextTest.php
@@ -16,7 +16,7 @@ use Magento\TestFramework\Helper\Bootstrap;
 class FulltextTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Indexer\Model\IndexerInterface
+     * @var \Magento\Framework\Indexer\IndexerInterface
      */
     protected $indexer;
 
@@ -72,7 +72,7 @@ class FulltextTest extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
-        /** @var \Magento\Indexer\Model\IndexerInterface indexer */
+        /** @var \Magento\Framework\Indexer\IndexerInterface indexer */
         $this->indexer = Bootstrap::getObjectManager()->create(
             'Magento\Indexer\Model\Indexer'
         );
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php
index c92d3bd491c8f4d3e31eacce3d0c9edefaf5bb91..b5e408cacc28a88dccc09bf857377493a4c7e7d7 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php
@@ -521,21 +521,6 @@ class IndexTest extends \Magento\TestFramework\TestCase\AbstractBackendControlle
         );
     }
 
-    /**
-     * @magentoDataFixture Magento/Customer/_files/customer_sample.php
-     */
-    public function testGridAction()
-    {
-        $this->dispatch('backend/customer/index/grid');
-
-        $body = $this->getResponse()->getBody();
-
-        $this->assertContains('test firstname test lastname', $body);
-        $this->assertContains('customer@example.com', $body);
-        $this->assertContains('+7000000001', $body);
-        $this->assertContains('United States', $body);
-    }
-
     /**
      * @magentoDataFixture Magento/Customer/_files/customer_sample.php
      */
@@ -569,7 +554,7 @@ class IndexTest extends \Magento\TestFramework\TestCase\AbstractBackendControlle
         $this->assertNull($subscriberFactory->create()->loadByCustomerId(1)->getSubscriberStatus());
         $this->assertNull($subscriberFactory->create()->loadByCustomerId(2)->getSubscriberStatus());
         // Setup
-        $this->getRequest()->setParam('customer', [1, 2]);
+        $this->getRequest()->setPostValue('selected', [1, 2])->setPostValue('namespace', 'customer_listing');
 
         // Test
         $this->dispatch('backend/customer/index/massSubscribe');
@@ -595,73 +580,22 @@ class IndexTest extends \Magento\TestFramework\TestCase\AbstractBackendControlle
      */
     public function testMassSubscriberActionNoSelection()
     {
+        $this->getRequest()->setPostValue('namespace', 'customer_listing');
         $this->dispatch('backend/customer/index/massSubscribe');
 
         $this->assertRedirect($this->stringContains('customer/index'));
         $this->assertSessionMessages(
-            $this->equalTo(['Please select customer(s).']),
-            \Magento\Framework\Message\MessageInterface::TYPE_ERROR
-        );
-    }
-
-    /**
-     * @magentoDbIsolation enabled
-     */
-    public function testMassSubscriberActionInvalidId()
-    {
-        $this->getRequest()->setParam('customer', [4200]);
-
-        $this->dispatch('backend/customer/index/massSubscribe');
-
-        $this->assertRedirect($this->stringContains('customer/index'));
-        $this->assertSessionMessages(
-            $this->equalTo(['No such entity with customerId = 4200']),
+            $this->equalTo(['Please select item(s).']),
             \Magento\Framework\Message\MessageInterface::TYPE_ERROR
         );
     }
 
-    /**
-     * @magentoDataFixture Magento/Customer/_files/two_customers.php
-     */
-    public function testMassSubscriberActionPartialUpdate()
-    {
-        // Pre-condition
-        /** @var \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory */
-        $subscriberFactory = Bootstrap::getObjectManager()->get('Magento\Newsletter\Model\SubscriberFactory');
-        $this->assertNull($subscriberFactory->create()->loadByCustomerId(1)->getSubscriberStatus());
-        $this->assertNull($subscriberFactory->create()->loadByCustomerId(2)->getSubscriberStatus());
-        // Setup
-        $this->getRequest()->setParam('customer', [1, 4200, 2]);
-
-        // Test
-        $this->dispatch('backend/customer/index/massSubscribe');
-
-        // Assertions
-        $this->assertRedirect($this->stringContains('customer/index'));
-        $this->assertSessionMessages(
-            $this->equalTo(['A total of 2 record(s) were updated.']),
-            \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS
-        );
-        $this->assertSessionMessages(
-            $this->equalTo(['No such entity with customerId = 4200']),
-            \Magento\Framework\Message\MessageInterface::TYPE_ERROR
-        );
-        $this->assertEquals(
-            Subscriber::STATUS_SUBSCRIBED,
-            $subscriberFactory->create()->loadByCustomerId(1)->getSubscriberStatus()
-        );
-        $this->assertEquals(
-            Subscriber::STATUS_SUBSCRIBED,
-            $subscriberFactory->create()->loadByCustomerId(2)->getSubscriberStatus()
-        );
-    }
-
     /**
      * @magentoDataFixture Magento/Customer/_files/customer.php
      */
     public function testMassDeleteAction()
     {
-        $this->getRequest()->setPostValue('customer', [1]);
+        $this->getRequest()->setPostValue('selected', [1])->setPostValue('namespace', 'customer_listing');
         $this->dispatch('backend/customer/index/massDelete');
         $this->assertSessionMessages(
             $this->equalTo(['A total of 1 record(s) were deleted.']),
@@ -670,45 +604,16 @@ class IndexTest extends \Magento\TestFramework\TestCase\AbstractBackendControlle
         $this->assertRedirect($this->stringContains('customer/index'));
     }
 
-    /**
-     * @magentoDbIsolation enabled
-     */
-    public function testInvalidIdMassDeleteAction()
-    {
-        $this->getRequest()->setPostValue('customer', [1]);
-        $this->dispatch('backend/customer/index/massDelete');
-        $this->assertSessionMessages(
-            $this->equalTo(['No such entity with customerId = 1']),
-            \Magento\Framework\Message\MessageInterface::TYPE_ERROR
-        );
-    }
-
     /**
      * Valid group Id but no customer Ids specified
      * @magentoDbIsolation enabled
      */
     public function testMassDeleteActionNoCustomerIds()
     {
+        $this->getRequest()->setPostValue('namespace', 'customer_listing');
         $this->dispatch('backend/customer/index/massDelete');
         $this->assertSessionMessages(
-            $this->equalTo(['Please select customer(s).']),
-            \Magento\Framework\Message\MessageInterface::TYPE_ERROR
-        );
-    }
-
-    /**
-     * @magentoDataFixture Magento/Customer/_files/two_customers.php
-     */
-    public function testMassDeleteActionPartialUpdate()
-    {
-        $this->getRequest()->setPostValue('customer', [1, 999, 2, 9999]);
-        $this->dispatch('backend/customer/index/massDelete');
-        $this->assertSessionMessages(
-            $this->equalTo(['A total of 2 record(s) were deleted.']),
-            \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS
-        );
-        $this->assertSessionMessages(
-            $this->equalTo(['No such entity with customerId = 999', 'No such entity with customerId = 9999']),
+            $this->equalTo(['Please select item(s).']),
             \Magento\Framework\Message\MessageInterface::TYPE_ERROR
         );
     }
@@ -794,7 +699,7 @@ class IndexTest extends \Magento\TestFramework\TestCase\AbstractBackendControlle
         $subscriberFactory = Bootstrap::getObjectManager()->get('Magento\Newsletter\Model\SubscriberFactory');
         $subscriberFactory->create()->subscribeCustomerById(1);
         $subscriberFactory->create()->subscribeCustomerById(2);
-        $this->getRequest()->setParam('customer', [1, 2]);
+        $this->getRequest()->setPostValue('selected', [1, 2])->setPostValue('namespace', 'customer_listing');
 
         // Ensure secret key is disabled (subscription status notification emails turn it off)
         $this->_objectManager->get('Magento\Backend\Model\UrlInterface')->turnOffSecretKey();
@@ -823,69 +728,16 @@ class IndexTest extends \Magento\TestFramework\TestCase\AbstractBackendControlle
      */
     public function testMassUnsubscriberActionNoSelection()
     {
+        $this->getRequest()->setPostValue('namespace', 'customer_listing');
         $this->dispatch('backend/customer/index/massUnsubscribe');
 
         $this->assertRedirect($this->stringContains('customer/index'));
         $this->assertSessionMessages(
-            $this->equalTo(['Please select customer(s).']),
-            \Magento\Framework\Message\MessageInterface::TYPE_ERROR
-        );
-    }
-
-    /**
-     * @magentoDbIsolation enabled
-     */
-    public function testMassUnsubscriberActionInvalidId()
-    {
-        $this->getRequest()->setParam('customer', [4200]);
-
-        $this->dispatch('backend/customer/index/massUnsubscribe');
-
-        $this->assertRedirect($this->stringContains('customer/index'));
-        $this->assertSessionMessages(
-            $this->equalTo(['No such entity with customerId = 4200']),
+            $this->equalTo(['Please select item(s).']),
             \Magento\Framework\Message\MessageInterface::TYPE_ERROR
         );
     }
 
-    /**
-     * @magentoDataFixture Magento/Customer/_files/two_customers.php
-     */
-    public function testMassUnsubscriberActionPartialUpdate()
-    {
-        // Setup
-        /** @var \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory */
-        $subscriberFactory = Bootstrap::getObjectManager()->get('Magento\Newsletter\Model\SubscriberFactory');
-        $subscriberFactory->create()->subscribeCustomerById(1);
-        $subscriberFactory->create()->subscribeCustomerById(2);
-        $this->getRequest()->setParam('customer', [1, 4200, 2]);
-
-        // Ensure secret key is disabled (subscription status notification emails turn it off)
-        $this->_objectManager->get('Magento\Backend\Model\UrlInterface')->turnOffSecretKey();
-
-        // Test
-        $this->dispatch('backend/customer/index/massUnsubscribe');
-
-        // Assertions
-        $this->assertRedirect($this->stringContains('customer/index'));
-        $this->assertSessionMessages(
-            $this->equalTo(['A total of 2 record(s) were updated.']),
-            \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS
-        );
-        $this->assertSessionMessages(
-            $this->equalTo(['No such entity with customerId = 4200']),
-            \Magento\Framework\Message\MessageInterface::TYPE_ERROR
-        );
-        $this->assertEquals(
-            Subscriber::STATUS_UNSUBSCRIBED,
-            $subscriberFactory->create()->loadByCustomerId(1)->getSubscriberStatus()
-        );
-        $this->assertEquals(
-            Subscriber::STATUS_UNSUBSCRIBED,
-            $subscriberFactory->create()->loadByCustomerId(2)->getSubscriberStatus()
-        );
-    }
-
     /**
      * @magentoDataFixture Magento/Customer/_files/customer.php
      * @magentoDataFixture Magento/Customer/_files/customer_address.php
diff --git a/dev/tests/integration/testsuite/Magento/Indexer/Model/Config/ConverterTest.php b/dev/tests/integration/testsuite/Magento/Indexer/Model/Config/ConverterTest.php
index 1bc92eaab653a3d6e48261e49715f9d70114fa5f..ca2af2c25806fc02d9a9e1f6b9b28b44e238bd68 100644
--- a/dev/tests/integration/testsuite/Magento/Indexer/Model/Config/ConverterTest.php
+++ b/dev/tests/integration/testsuite/Magento/Indexer/Model/Config/ConverterTest.php
@@ -8,14 +8,14 @@ namespace Magento\Indexer\Model\Config;
 class ConverterTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Indexer\Model\Config\Converter
+     * @var \Magento\Framework\Indexer\Config\Converter
      */
     protected $model;
 
     protected function setUp()
     {
         $this->model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-            ->create('\Magento\Indexer\Model\Config\Converter');
+            ->create('Magento\Framework\Indexer\Config\Converter');
     }
 
     public function testConverter()
diff --git a/dev/tests/integration/testsuite/Magento/Indexer/Model/Config/_files/indexer.xml b/dev/tests/integration/testsuite/Magento/Indexer/Model/Config/_files/indexer.xml
index b83f645c9cd2bc66670c4d7d21307b2620ee114c..35b252ec984c9bd26f0152db0b5173a773f21c01 100644
--- a/dev/tests/integration/testsuite/Magento/Indexer/Model/Config/_files/indexer.xml
+++ b/dev/tests/integration/testsuite/Magento/Indexer/Model/Config/_files/indexer.xml
@@ -6,7 +6,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:noNamespaceSchemaLocation="../../../../../../../../../app/code/Magento/Indexer/etc/indexer.xsd">
+        xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/Indexer/etc/indexer.xsd">
     <indexer id="catalogsearch_fulltext" view_id="catalogsearch_fulltext"
              class="Magento\CatalogSearch\Model\Indexer\Fulltext"
              primary="first">
@@ -16,21 +16,15 @@
 
         <fieldset name="first" source="MagentoModule\ServiceClassOrRepositoryClass"
                   provider="Magento\Indexer\Model\Fieldset\ProductFieldset">
-
             <field name="title_alias" origin="title" xsi:type="searchable" dataType="text">
                 <filter class="Magento\Framework\Search\Index\Filter\LowercaseFilter"/>
             </field>
             <field name="identifier" xsi:type="filterable" handler="Magento\Framework\Search\Index\Handler"/>
-
         </fieldset>
 
         <fieldset name="second" source="MagentoModule\ServiceClassOrRepositoryClass">
-
             <reference fieldset="first" from="id_field" to="second_entity_id"/>
-            <reference fieldset="first" from="id_field2" to="second_entity_id2"/>
-
             <field name="title" xsi:type="searchable"/>
-
         </fieldset>
 
         <saveHandler class="Magento\Cms\Model\Indexer\StoreResource"/>
diff --git a/dev/tests/integration/testsuite/Magento/Indexer/Model/Config/_files/result.php b/dev/tests/integration/testsuite/Magento/Indexer/Model/Config/_files/result.php
index 4c3adbe825801a39a721909a9cba2dd62b164871..1ea56303ff15adc9598ecf0ea79db47759362bc1 100644
--- a/dev/tests/integration/testsuite/Magento/Indexer/Model/Config/_files/result.php
+++ b/dev/tests/integration/testsuite/Magento/Indexer/Model/Config/_files/result.php
@@ -66,19 +66,10 @@ return [
                             [
                                 'first' =>
                                     [
-                                        0 =>
-                                            [
-                                                'fieldset' => 'first',
-                                                'from' => 'id_field',
-                                                'to' => 'second_entity_id',
-                                            ],
-                                        1 =>
-                                            [
-                                                'fieldset' => 'first',
-                                                'from' => 'id_field2',
-                                                'to' => 'second_entity_id2',
-                                            ],
-                                    ],
+                                        'fieldset' => 'first',
+                                        'from' => 'id_field',
+                                        'to' => 'second_entity_id',
+                                    ]
                             ],
                     ],
                 ],
diff --git a/dev/tests/integration/testsuite/Magento/Test/Integrity/Modular/IndexerConfigFilesTest.php b/dev/tests/integration/testsuite/Magento/Test/Integrity/Modular/IndexerConfigFilesTest.php
index 525fc6af48d6f59f8bc17850dcf4be2f2e717f97..944cf845014547aa7cbf553086e071c90a841a93 100644
--- a/dev/tests/integration/testsuite/Magento/Test/Integrity/Modular/IndexerConfigFilesTest.php
+++ b/dev/tests/integration/testsuite/Magento/Test/Integrity/Modular/IndexerConfigFilesTest.php
@@ -30,8 +30,8 @@ class IndexerConfigFilesTest extends \PHPUnit_Framework_TestCase
         $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
             'Magento\Framework\Filesystem'
         );
-        $this->schemeFile = $filesystem->getDirectoryRead(DirectoryList::APP)
-            ->getAbsolutePath('code/Magento/Indexer/etc/indexer.xsd');
+        $this->schemeFile = $filesystem->getDirectoryRead(DirectoryList::ROOT)
+            ->getAbsolutePath('lib/internal/Magento/Framework/Indexer/etc/indexer.xsd');
     }
 
     /**
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/ConfigTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/ConfigTest.php
index 6c1aed921ece0828dbf53785852596f939249021..7b8c37e437e2f18b607a42a4bc25610b32d4b93d 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/ConfigTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/ConfigTest.php
@@ -19,7 +19,7 @@ class ConfigTest extends \Magento\TestFramework\Integrity\AbstractConfig
      */
     protected function _getXsd()
     {
-        return '/app/code/Magento/Indexer/etc/indexer_merged.xsd';
+        return '/lib/internal/Magento/Framework/Indexer/etc/indexer_merged.xsd';
     }
 
     /**
@@ -69,7 +69,7 @@ class ConfigTest extends \Magento\TestFramework\Integrity\AbstractConfig
      */
     protected function _getFileXsd()
     {
-        return '/app/code/Magento/Indexer/etc/indexer.xsd';
+        return '/lib/internal/Magento/Framework/Indexer/etc/indexer.xsd';
     }
 
     /**
@@ -79,6 +79,6 @@ class ConfigTest extends \Magento\TestFramework\Integrity\AbstractConfig
      */
     protected function _getXmlName()
     {
-        return '/app/code/Magento/Indexer/etc/indexer.xml';
+        return '/lib/internal/Magento/Framework/Indexer/etc/indexer.xml';
     }
 }
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/invalid.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/invalid.xml
index c7095a028730b0871dd9d8b8787cf7187b62c682..5479440317f6fb7778275e3bd2173d7c650b75ad 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/invalid.xml
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/invalid.xml
@@ -7,7 +7,7 @@
  * See COPYING.txt for license details.
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../app/code/Magento/Indexer/etc/indexer_merged.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/Indexer/etc/indexer_merged.xsd">
     <indexer id="indexer_0" view_id="catalogsearch_fulltext" class="NotAClass">
         <title translate="true">Test Indexer Declaration</title>
         <description translate="true">Invalid provider attribute value</description>
@@ -23,19 +23,19 @@
     <indexer id="indexer_11" view_id="catalogsearch_fulltext_11" class="Magento\CatalogSearch\Model\Indexer\Fulltext">
         <title translate="true">Test Indexer Declaration</title>
         <description translate="true">Empty fields</description>
-        <fieldset provider="Magento\Framework\Search\Index\Fieldset\Default" name="default"/>
+        <fieldset source="Collection" provider="Magento\Framework\Search\Index\Fieldset\Default" name="default"/>
     </indexer>
     <indexer id="indexer_1" view_id="catalogsearch_fulltext_1" class="Magento\CatalogSearch\Model\Indexer\Fulltext">
         <title translate="true">Test Indexer Declaration</title>
         <description translate="true">Invalid handler attribute value</description>
-        <fieldset provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
+        <fieldset source="Collection" provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
             <field name="visibility" handler="Magento\Framework\Search\Index\Field\Handler\Class" xsi:type="filterable" dataType="int" />
         </fieldset>
     </indexer>
     <indexer id="indexer_2" view_id="catalogsearch_fulltext_2" class="Magento\CatalogSearch\Model\Indexer\Fulltext">
         <title translate="true">Test Indexer Declaration</title>
         <description translate="true">Duplicate field declaration</description>
-        <fieldset provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
+        <fieldset source="Collection" provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
             <field name="visibility" handler="defaultHandler" xsi:type="filterable" dataType="int" />
             <field name="visibility" handler="defaultHandler">
                 <filter class="Magento\Framework\Search\Index\Filter\StopWordsFilter"/>
@@ -45,42 +45,42 @@
     <indexer id="indexer_3" view_id="catalogsearch_fulltext_3" class="Magento\CatalogSearch\Model\Indexer\Fulltext">
         <title translate="true">Test Indexer Declaration</title>
         <description translate="true">Invalid source attribute value</description>
-        <fieldset provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
+        <fieldset source="Collection" provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
             <field name="visibility" handler="defaultHandler"/>
         </fieldset>
     </indexer>
     <indexer id="indexer_4" view_id="catalogsearch_fulltext_4" class="Magento\CatalogSearch\Model\Indexer\Fulltext">
         <title translate="true">Test Indexer Declaration</title>
         <description translate="true">Invalid field handler attribute value</description>
-        <fieldset provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
+        <fieldset source="Collection" provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
             <field name="visibility" handler="handler" xsi:type="filterable" dataType="int"/>
         </fieldset>
     </indexer>
     <indexer id="indexer_5" view_id="catalogsearch_fulltext_5" class="Magento\CatalogSearch\Model\Indexer\Fulltext">
         <title translate="true">Test Indexer Declaration</title>
         <description translate="true">Invalid field type</description>
-        <fieldset provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
+        <fieldset source="Collection" provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
             <field name="visibility" handler="defaultHandler" xsi:type="any"/>
         </fieldset>
     </indexer>
     <indexer id="indexer_6" view_id="catalogsearch_fulltext_6" class="Magento\CatalogSearch\Model\Indexer\Fulltext">
         <title translate="true">Test Indexer Declaration</title>
         <description translate="true">No dataType attribute for 'filterable' type field</description>
-        <fieldset provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
+        <fieldset source="Collection" provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
             <field name="visibility" handler="defaultHandler" xsi:type="filterable"/>
         </fieldset>
     </indexer>
     <indexer id="indexer_12" view_id="catalogsearch_fulltext_12" class="Magento\CatalogSearch\Model\Indexer\Fulltext">
         <title translate="true">Test Indexer Declaration</title>
         <description translate="true">Invalid field dataType attribute value</description>
-        <fieldset provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
+        <fieldset source="Collection" provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
             <field name="visibility" handler="defaultHandler" xsi:type="filterable" dataType="string"/>
         </fieldset>
     </indexer>
     <indexer id="indexer_13" view_id="catalogsearch_fulltext_13" class="Magento\CatalogSearch\Model\Indexer\Fulltext">
         <title translate="true">Test Indexer Declaration</title>
         <description translate="true">No dataType attribute for 'filterable' type field</description>
-        <fieldset provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
+        <fieldset source="Collection" provider="Magento\Framework\Search\Index\Fieldset\Default" name="default">
             <field name="visibility" handler="defaultHandler" xsi:type="filterable"/>
         </fieldset>
     </indexer>
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/valid.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/valid.xml
index 3d9143fbfbceff70b9a6263b0c29be640ad99894..0bd5f82c64f2345de3804728f057461f97c5775f 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/valid.xml
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/valid.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../app/code/Magento/Indexer/etc/indexer_merged.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/Indexer/etc/indexer_merged.xsd">
     <indexer id="indexer_1" view_id="catalogsearch_fulltext" class="Magento\CatalogSearch\Model\Indexer\Fulltext">
         <title translate="true">Test Indexer Declaration 1</title>
         <description translate="true">Test Indexer Declaration 1</description>
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/valid_partial.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/valid_partial.xml
index 913bf102f90cf57cfec56bc164642e82a5784b2c..3945fb13a058bf40a27bfb604c9cdd4d5371bbb6 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/valid_partial.xml
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/valid_partial.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../app/code/Magento/Indexer/etc/indexer.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/Indexer/etc/indexer.xsd">
     <indexer id="indexer_1" view_id="catalogsearch_fulltext" class="Magento\CatalogSearch\Model\Indexer\Fulltext">
         <title translate="true">Test Indexer Declaration 1</title>
         <description translate="true">Test Indexer Declaration 1</description>
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
index 6c134ffed5ebf9392ae582e580f148314844cbfd..d0a34092894b3deaafb63d6c9ed4d5c45e22b3f8 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
@@ -2433,6 +2433,14 @@ return [
     ['getThumbnailSize', 'Magento\ProductAlert\Block\Email\AbstractEmail'],
     ['getThumbnailUrl', 'Magento\ProductAlert\Block\Email\AbstractEmail'],
     ['getProductThumbnail', 'Magento\Checkout\Block\Cart\Item\Renderer'],
+    ['getColumnsComponent', 'Magento\Ui\Model\Export\ConvertToCsv', 'Magento\Ui\Model\Export\MetadataProvider::getColumnsComponent'],
+    ['getColumns', 'Magento\Ui\Model\Export\ConvertToCsv', 'Magento\Ui\Model\Export\MetadataProvider::getColumns'],
+    ['getHeaders', 'Magento\Ui\Model\Export\ConvertToCsv', 'Magento\Ui\Model\Export\MetadataProvider::getHeaders'],
+    ['getFields', 'Magento\Ui\Model\Export\ConvertToCsv', 'Magento\Ui\Model\Export\MetadataProvider::getFields'],
+    ['getRowData', 'Magento\Ui\Model\Export\ConvertToCsv', 'Magento\Ui\Model\Export\MetadataProvider::getRowData'],
+    ['getComplexLabel', 'Magento\Ui\Model\Export\ConvertToCsv', 'Magento\Ui\Model\Export\MetadataProvider::getComplexLabel'],
+    ['getFilterOptions', 'Magento\Ui\Model\Export\ConvertToCsv', 'Magento\Ui\Model\Export\MetadataProvider::getFilterOptions'],
+    ['getOptions', 'Magento\Ui\Model\Export\ConvertToCsv', 'Magento\Ui\Model\Export\MetadataProvider::getOptions'],
     [
         'generateSimpleProducts',
         'Magento\ConfigurableProduct\Model\Product\Type\Configurable',
diff --git a/lib/internal/Magento/Framework/Api/Search/SearchCriteriaBuilder.php b/lib/internal/Magento/Framework/Api/Search/SearchCriteriaBuilder.php
index 7d7d1f5bd2baf1ffd71f09a2e772461f13928b0f..a81600418ad77092bf9933ad958628015819d0f6 100644
--- a/lib/internal/Magento/Framework/Api/Search/SearchCriteriaBuilder.php
+++ b/lib/internal/Magento/Framework/Api/Search/SearchCriteriaBuilder.php
@@ -8,7 +8,6 @@ namespace Magento\Framework\Api\Search;
 
 use Magento\Framework\Api\AbstractSimpleObjectBuilder;
 use Magento\Framework\Api\ObjectFactory;
-use Magento\Framework\Api\SortOrder;
 use Magento\Framework\Api\SortOrderBuilder;
 
 /**
diff --git a/lib/internal/Magento/Framework/App/Resource/SourcePool.php b/lib/internal/Magento/Framework/App/Resource/SourceFactory.php
similarity index 88%
rename from lib/internal/Magento/Framework/App/Resource/SourcePool.php
rename to lib/internal/Magento/Framework/App/Resource/SourceFactory.php
index f4ef9edecbfe7ca6f308a3a56fce04650598016f..bfc9da15dcb8e690dd42fd175d448c39421a8541 100644
--- a/lib/internal/Magento/Framework/App/Resource/SourcePool.php
+++ b/lib/internal/Magento/Framework/App/Resource/SourceFactory.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Framework\App\Resource;
 
-class SourcePool
+class SourceFactory
 {
     /**
      * @var \Magento\Framework\ObjectManagerInterface
@@ -27,9 +27,9 @@ class SourcePool
      * @throws \InvalidArgumentException
      * @return SourceProviderInterface
      */
-    public function get($className)
+    public function create($className)
     {
-        $source = $this->objectManager->get($className);
+        $source = $this->objectManager->create($className);
         if (!$source instanceof SourceProviderInterface) {
             throw new \InvalidArgumentException(
                 $className . ' doesn\'t implement \Magento\Framework\App\Resource\SourceProviderInterface'
diff --git a/lib/internal/Magento/Framework/Convert/ExcelFactory.php b/lib/internal/Magento/Framework/Convert/ExcelFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..116da103109628b6f7aebeacf593985e2f197d05
--- /dev/null
+++ b/lib/internal/Magento/Framework/Convert/ExcelFactory.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Convert;
+
+use Magento\Framework\ObjectManagerInterface;
+
+class ExcelFactory
+{
+    /**
+     * @var ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    /**
+     * @var string
+     */
+    protected $instanceName;
+
+    /**
+     * @param ObjectManagerInterface $objectManager
+     * @param string $instanceName
+     */
+    public function __construct(
+        ObjectManagerInterface $objectManager,
+        $instanceName = '\\Magento\\Framework\\Convert\\Excel'
+    ) {
+        $this->objectManager = $objectManager;
+        $this->instanceName = $instanceName;
+    }
+
+    /**
+     * Create class instance with specified parameters
+     *
+     * @param array $data
+     * @return \Magento\Framework\Convert\Excel
+     */
+    public function create(array $data = [])
+    {
+        return $this->objectManager->create($this->instanceName, $data);
+    }
+}
diff --git a/lib/internal/Magento/Framework/Convert/Test/Unit/ExcelFactoryTest.php b/lib/internal/Magento/Framework/Convert/Test/Unit/ExcelFactoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..de7e50558b32991f924c91bf34128e5f69a2bb07
--- /dev/null
+++ b/lib/internal/Magento/Framework/Convert/Test/Unit/ExcelFactoryTest.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Convert\Test\Unit;
+
+use Magento\Framework\Convert\ExcelFactory;
+use Magento\Framework\ObjectManagerInterface;
+
+class ExcelFactoryTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var ExcelFactory
+     */
+    protected $model;
+
+    /**
+     * @var ObjectManagerInterface | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = $this->getMockBuilder('Magento\Framework\ObjectManagerInterface')
+            ->setMethods(['create'])
+            ->getMockForAbstractClass();
+
+        $this->model = new ExcelFactory(
+            $this->objectManager
+        );
+    }
+
+    public function testCreate()
+    {
+        $excel = $this->getMockBuilder('Magento\Framework\Convert\Excel')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->objectManager->expects($this->once())
+            ->method('create')
+            ->with('\\Magento\\Framework\\Convert\\Excel', [])
+            ->willReturn($excel);
+
+        $this->assertInstanceOf('Magento\Framework\Convert\Excel', $this->model->create());
+    }
+}
diff --git a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
index 2ab2fdf21be1b47d12ed86a47aad5ac33d5bb165..041d7d35b977f21a20d8c135c66a299c0d4c6014 100644
--- a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
+++ b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
@@ -1973,8 +1973,10 @@ class Mysql extends \Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface
             implode(",\n", $sqlFragment),
             implode(" ", $tableOptions)
         );
+        $result = $this->query($sql);
+        $this->resetDdlCache($table->getName(), $table->getSchema());
 
-        return $this->query($sql);
+        return $result;
     }
 
     /**
@@ -2379,7 +2381,7 @@ class Mysql extends \Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface
         $table = $this->quoteIdentifier($this->_getTableName($tableName, $schemaName));
         $query = 'DROP TABLE IF EXISTS ' . $table;
         $this->query($query);
-
+        $this->resetDdlCache($tableName, $schemaName);
         return true;
     }
 
diff --git a/lib/internal/Magento/Framework/DB/SubSelect.php b/lib/internal/Magento/Framework/DB/SubSelect.php
new file mode 100644
index 0000000000000000000000000000000000000000..7f23f9eb4a368147bda0ebcc57ce80d3b6293f9e
--- /dev/null
+++ b/lib/internal/Magento/Framework/DB/SubSelect.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\DB;
+
+use Magento\Framework\App\Resource;
+use Magento\Framework\DB\Adapter\AdapterInterface;
+
+/**
+ * Class Concat
+ */
+class SubSelect extends \Zend_Db_Expr
+{
+    /**
+     * @var string
+     */
+    protected $table;
+
+    /**
+     * @var string[]
+     */
+    protected $columns;
+
+    /**
+     * @var string
+     */
+    protected $originColumn;
+
+    /**
+     * @var string
+     */
+    protected $targetColumn;
+
+    /**
+     * @var \Magento\Framework\App\Resource
+     */
+    protected $resource;
+
+    /**
+     * @var string
+     */
+    protected $connectionName;
+
+    /**
+     * @var AdapterInterface
+     */
+    protected $connection;
+
+    /**
+     * @param Resource $resource
+     * @param string $connectionName
+     * @param string $table
+     * @param string[] $columns
+     * @param string $originColumn
+     * @param string $targetColumn
+     */
+    public function __construct(
+        Resource $resource,
+        $table,
+        array $columns,
+        $originColumn,
+        $targetColumn,
+        $connectionName = Resource::DEFAULT_CONNECTION
+    ) {
+        $this->resource = $resource;
+        $this->connectionName = $connectionName;
+        $this->table = $table;
+        $this->columns = $columns;
+        $this->originColumn = $originColumn;
+        $this->targetColumn = $targetColumn;
+    }
+
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        $select = $this->getConnection()->select()->from(
+            $this->resource->getTableName($this->table),
+            array_values($this->columns)
+        )->where(
+            sprintf(
+                '%s = %s',
+                $this->getConnection()->quoteIdentifier($this->originColumn),
+                $this->getConnection()->quoteIdentifier($this->targetColumn)
+            )
+        )->limit(1);
+        return sprintf('(%s)', $select);
+    }
+
+    /**
+     * Returns connection
+     *
+     * @return AdapterInterface
+     */
+    protected function getConnection()
+    {
+        if (!$this->connection) {
+            $this->connection = $this->resource->getConnection($this->connectionName);
+        }
+        return $this->connection;
+    }
+}
diff --git a/app/code/Magento/Indexer/Model/Indexer/AbstractProcessor.php b/lib/internal/Magento/Framework/Indexer/AbstractProcessor.php
similarity index 85%
rename from app/code/Magento/Indexer/Model/Indexer/AbstractProcessor.php
rename to lib/internal/Magento/Framework/Indexer/AbstractProcessor.php
index 1a00ab15aa0bd7ac1b27ccdf2169b3d55c64b17b..f9bfebb770026cd1ea8e6b47f2820ef2a260b763 100644
--- a/app/code/Magento/Indexer/Model/Indexer/AbstractProcessor.php
+++ b/lib/internal/Magento/Framework/Indexer/AbstractProcessor.php
@@ -6,7 +6,7 @@
  * See COPYING.txt for license details.
  */
 
-namespace Magento\Indexer\Model\Indexer;
+namespace Magento\Framework\Indexer;
 
 abstract class AbstractProcessor
 {
@@ -15,14 +15,14 @@ abstract class AbstractProcessor
      */
     const INDEXER_ID = '';
 
-    /** @var \Magento\Indexer\Model\IndexerRegistry */
+    /** @var \Magento\Framework\Indexer\IndexerRegistry */
     protected $indexerRegistry;
 
     /**
-     * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+     * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
      */
     public function __construct(
-        \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
+        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
     ) {
         $this->indexerRegistry = $indexerRegistry;
     }
@@ -30,7 +30,7 @@ abstract class AbstractProcessor
     /**
      * Get indexer
      *
-     * @return \Magento\Indexer\Model\IndexerInterface
+     * @return \Magento\Framework\Indexer\IndexerInterface
      */
     public function getIndexer()
     {
diff --git a/app/code/Magento/Indexer/Model/Action/Base.php b/lib/internal/Magento/Framework/Indexer/Action/Base.php
similarity index 69%
rename from app/code/Magento/Indexer/Model/Action/Base.php
rename to lib/internal/Magento/Framework/Indexer/Action/Base.php
index 1ea7dc7fdf9560ef59856bbeae43701c5ae25780..44628589c4c5b58be93bce1b472896d9856297ee 100644
--- a/app/code/Magento/Indexer/Model/Action/Base.php
+++ b/lib/internal/Magento/Framework/Indexer/Action/Base.php
@@ -3,21 +3,21 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model\Action;
+namespace Magento\Framework\Indexer\Action;
 
 use Magento\Framework\App\Resource as AppResource;
 use Magento\Framework\App\Resource\SourceProviderInterface;
 use Magento\Framework\DB\Adapter\AdapterInterface;
 use Magento\Framework\DB\Ddl\Table;
-use Magento\Framework\IndexerInterface;
+use Magento\Framework\Indexer\SaveHandler\IndexerInterface;
 use Magento\Framework\Stdlib\StringUtils as StdString;
-use Magento\Indexer\Model\ActionInterface;
-use Magento\Indexer\Model\FieldsetPool;
-use Magento\Indexer\Model\HandlerPool;
-use Magento\Indexer\Model\IndexStructure;
-use Magento\Indexer\Model\SaveHandlerFactory;
-use Magento\Framework\App\Resource\SourcePool;
-use Magento\Indexer\Model\HandlerInterface;
+use Magento\Framework\Indexer\ActionInterface;
+use Magento\Framework\Indexer\FieldsetPool;
+use Magento\Framework\Indexer\HandlerPool;
+use Magento\Framework\Indexer\IndexStructureInterface;
+use Magento\Framework\Indexer\SaveHandlerFactory;
+use Magento\Framework\App\Resource\SourceFactory;
+use Magento\Framework\Indexer\HandlerInterface;
 
 /**
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -80,9 +80,9 @@ class Base implements ActionInterface
     protected $searchColumns;
 
     /**
-     * @var SourcePool
+     * @var SourceFactory
      */
-    protected $sourcePool;
+    protected $sourceFactory;
 
     /**
      * @var HandlerPool
@@ -100,7 +100,7 @@ class Base implements ActionInterface
     protected $string;
 
     /**
-     * @var IndexStructure
+     * @var IndexStructureInterface
      */
     protected $indexStructure;
 
@@ -119,30 +119,35 @@ class Base implements ActionInterface
      */
     protected $saveHandler;
 
+    /**
+     * @var string
+     */
+    protected $tableAlias = 'main_table';
+
     /**
      * @param AppResource $resource
-     * @param SourcePool $sourcePool
+     * @param SourceFactory $sourceFactory
      * @param HandlerPool $handlerPool
      * @param SaveHandlerFactory $saveHandlerFactory
      * @param FieldsetPool $fieldsetPool
      * @param StdString $string
-     * @param IndexStructure $indexStructure
+     * @param IndexStructureInterface $indexStructure
      * @param array $data
      */
     public function __construct(
         AppResource $resource,
-        SourcePool $sourcePool,
+        SourceFactory $sourceFactory,
         HandlerPool $handlerPool,
         SaveHandlerFactory $saveHandlerFactory,
         FieldsetPool $fieldsetPool,
         StdString $string,
-        IndexStructure $indexStructure,
+        IndexStructureInterface $indexStructure,
         $data = []
     ) {
         $this->connection = $resource->getConnection();
         $this->fieldsetPool = $fieldsetPool;
         $this->data = $data;
-        $this->sourcePool = $sourcePool;
+        $this->sourceFactory = $sourceFactory;
         $this->handlerPool = $handlerPool;
         $this->saveHandlerFactory = $saveHandlerFactory;
         $this->string = $string;
@@ -155,12 +160,13 @@ class Base implements ActionInterface
      * @param null|int|array $ids
      * @return void
      */
-    protected function execute($ids = null)
+    protected function execute(array $ids = [])
     {
         $this->prepareFields();
-        $this->indexStructure->delete($this->getTableName());
-        $this->indexStructure->create($this->getTableName(), $this->filterable);
-        $this->getSaveHandler()->cleanIndex([]);
+        if (!count($ids)) {
+            $this->getSaveHandler()->cleanIndex([]);
+        }
+        $this->getSaveHandler()->deleteIndex([], new \ArrayObject($ids));
         $this->getSaveHandler()->saveIndex([], $this->prepareDataSource($ids));
     }
 
@@ -193,7 +199,7 @@ class Base implements ActionInterface
      */
     public function executeRow($id)
     {
-        $this->execute($id);
+         $this->execute([$id]);
     }
 
     /**
@@ -202,9 +208,9 @@ class Base implements ActionInterface
      * @param array|int|null $ids
      * @return SourceProviderInterface
      */
-    protected function prepareDataSource($ids = null)
+    protected function prepareDataSource(array $ids = [])
     {
-        return $ids === null
+        return !count($ids)
             ? $this->createResultCollection()
             : $this->createResultCollection()->addFieldToFilter($this->getPrimaryResource()->getIdFieldname(), $ids);
     }
@@ -227,7 +233,13 @@ class Base implements ActionInterface
     protected function getSaveHandler()
     {
         if ($this->saveHandler === null) {
-            $this->saveHandler = $this->saveHandlerFactory->create($this->data['saveHandler'], ['data' => $this->data]);
+            $this->saveHandler = $this->saveHandlerFactory->create(
+                $this->data['saveHandler'],
+                [
+                    'indexStructure' => $this->indexStructure,
+                    'data' => $this->data,
+                ]
+            );
         }
         return $this->saveHandler;
     }
@@ -265,15 +277,15 @@ class Base implements ActionInterface
             if (isset($fieldset['references'])) {
                 foreach ($fieldset['references'] as $reference) {
                     $source = $fieldset['source'];
-                    $referenceSource = $this->data['fieldsets'][$reference['fieldset']]['source'];
                     /** @var SourceProviderInterface $source */
-                    /** @var SourceProviderInterface $referenceSource */
                     $currentEntityName = $source->getMainTable();
-                    $select->joinInner(
-                        $currentEntityName,
+                    $alias = $this->getPrimaryFieldset()['name'] == $reference['fieldset']
+                        ? $this->tableAlias
+                        : $reference['fieldset'];
+                    $select->joinLeft(
+                        [$fieldset['name'] => $currentEntityName],
                         new \Zend_Db_Expr(
-                            $referenceSource->getMainTable() . '.' . $reference['from']
-                            . '=' . $currentEntityName . '.' . $reference['to']
+                            $fieldset['name'] . '.' . $reference['from'] . '=' . $alias . '.' . $reference['to']
                         ),
                         null
                     );
@@ -282,7 +294,11 @@ class Base implements ActionInterface
             foreach ($fieldset['fields'] as $field) {
                 $handler = $field['handler'];
                 /** @var HandlerInterface $handler */
-                $handler->prepareSql($fieldset['source'], $field);
+                $handler->prepareSql(
+                    $this->getPrimaryResource(),
+                    $this->getPrimaryFieldset()['name'] == $fieldset['name'] ? $this->tableAlias : $fieldset['name'],
+                    $field
+                );
             }
         }
 
@@ -297,12 +313,21 @@ class Base implements ActionInterface
     protected function prepareFields()
     {
         foreach ($this->data['fieldsets'] as $fieldsetName => $fieldset) {
-            $this->data['fieldsets'][$fieldsetName]['source'] = $this->sourcePool->get($fieldset['source']);
-            if (isset($fieldset['class'])) {
-                $fieldsetObject = $this->fieldsetPool->get($fieldset['class']);
-                $this->data['fieldsets'][$fieldsetName] = $fieldsetObject->addDynamicData($fieldset);
+            $this->data['fieldsets'][$fieldsetName]['source'] = $this->sourceFactory->create($fieldset['source']);
+            if (isset($fieldset['provider'])) {
+                $fieldsetObject = $this->fieldsetPool->get($fieldset['provider']);
+                $this->data['fieldsets'][$fieldsetName] =
+                    $fieldsetObject->addDynamicData($this->data['fieldsets'][$fieldsetName]);
             }
-            foreach ($fieldset['fields'] as $fieldName => $field) {
+            foreach ($this->data['fieldsets'][$fieldsetName]['fields'] as $fieldName => $field) {
+                $this->data['fieldsets'][$fieldsetName]['fields'][$fieldName]['origin'] =
+                    $this->data['fieldsets'][$fieldsetName]['fields'][$fieldName]['origin']
+                        ?: $this->data['fieldsets'][$fieldsetName]['fields'][$fieldName]['name'];
+                if ($fieldsetName != 0) {
+                    $this->data['fieldsets'][$fieldsetName]['fields'][$fieldName]['name'] =
+                        $this->data['fieldsets'][$fieldsetName]['name'] . '_'
+                        . $this->data['fieldsets'][$fieldsetName]['fields'][$fieldName]['name'];
+                }
                 $this->saveFieldByType($field);
                 $this->data['fieldsets'][$fieldsetName]['fields'][$fieldName]['handler'] =
                     $this->handlerPool->get($field['handler']);
diff --git a/lib/internal/Magento/Framework/Indexer/Action/Dummy.php b/lib/internal/Magento/Framework/Indexer/Action/Dummy.php
new file mode 100644
index 0000000000000000000000000000000000000000..ca29e99d07fab30ee64a5c4fbee70ef3941e9d80
--- /dev/null
+++ b/lib/internal/Magento/Framework/Indexer/Action/Dummy.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Indexer\Action;
+
+use Magento\Framework\Indexer\ActionInterface;
+use Magento\Framework\Mview\ActionInterface as MviewActionInterface;
+
+class Dummy implements ActionInterface, MviewActionInterface
+{
+    /**
+     * Execute full indexation
+     *
+     * @return void
+     */
+    public function executeFull()
+    {
+    }
+
+    /**
+     * Execute partial indexation by ID list
+     *
+     * @param int[] $ids
+     * @return void
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function executeList(array $ids)
+    {
+    }
+
+    /**
+     * Execute partial indexation by ID
+     *
+     * @param int $id
+     * @return void
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function executeRow($id)
+    {
+    }
+
+    /**
+     * Execute materialization on ids entities
+     *
+     * @param int[] $ids
+     * @return void
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function execute($ids)
+    {
+    }
+}
diff --git a/lib/internal/Magento/Framework/Indexer/Action/Entity.php b/lib/internal/Magento/Framework/Indexer/Action/Entity.php
new file mode 100644
index 0000000000000000000000000000000000000000..fb415fc0164c692e5630c60db41aaf2f96c7a941
--- /dev/null
+++ b/lib/internal/Magento/Framework/Indexer/Action/Entity.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Indexer\Action;
+
+use Magento\Framework\App\Resource\SourceProviderInterface;
+
+class Entity extends Base
+{
+    /**
+     * @var string
+     */
+    protected $tableAlias = 'e';
+
+    /**
+     * Prepare select query
+     *
+     * @param array|int|null $ids
+     * @return SourceProviderInterface
+     */
+    protected function prepareDataSource(array $ids = [])
+    {
+        return !count($ids)
+            ? $this->createResultCollection()
+            : $this->createResultCollection()->addFieldToFilter($this->getPrimaryResource()->getRowIdFieldName(), $ids);
+    }
+}
diff --git a/app/code/Magento/Indexer/Model/ActionFactory.php b/lib/internal/Magento/Framework/Indexer/ActionFactory.php
similarity index 84%
rename from app/code/Magento/Indexer/Model/ActionFactory.php
rename to lib/internal/Magento/Framework/Indexer/ActionFactory.php
index d0c703a3ee4826162bc5f6da3e00d15345a257c2..38e61d5dc3fd7245fcccc5f0792a2059378d96c2 100644
--- a/app/code/Magento/Indexer/Model/ActionFactory.php
+++ b/lib/internal/Magento/Framework/Indexer/ActionFactory.php
@@ -3,7 +3,9 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model;
+namespace Magento\Framework\Indexer;
+
+use Magento\Framework\Indexer\ActionInterface;
 
 class ActionFactory
 {
@@ -33,7 +35,7 @@ class ActionFactory
         $action = $this->objectManager->create($className, $arguments);
         if (!$action instanceof ActionInterface) {
             throw new \InvalidArgumentException(
-                $className . ' doesn\'t implement \Magento\Indexer\Model\ActionInterface'
+                $className . ' doesn\'t implement \Magento\Framework\Indexer\ActionInterface'
             );
         }
 
diff --git a/app/code/Magento/Indexer/Model/ActionInterface.php b/lib/internal/Magento/Framework/Indexer/ActionInterface.php
similarity index 93%
rename from app/code/Magento/Indexer/Model/ActionInterface.php
rename to lib/internal/Magento/Framework/Indexer/ActionInterface.php
index a26fcf1ff2925fa5281fcfb7e8da2efbef4bd245..b62bb11d37226d55a3e020606e35d10a8e0194d8 100644
--- a/app/code/Magento/Indexer/Model/ActionInterface.php
+++ b/lib/internal/Magento/Framework/Indexer/ActionInterface.php
@@ -3,7 +3,7 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model;
+namespace Magento\Framework\Indexer;
 
 /**
  * @api
diff --git a/app/code/Magento/Indexer/Model/CacheContext.php b/lib/internal/Magento/Framework/Indexer/CacheContext.php
similarity index 97%
rename from app/code/Magento/Indexer/Model/CacheContext.php
rename to lib/internal/Magento/Framework/Indexer/CacheContext.php
index fa82505a090c91a1ec9cb05745cdf739b4d86257..54ead2476ddd6d2df053f439f45631bd243707c2 100644
--- a/app/code/Magento/Indexer/Model/CacheContext.php
+++ b/lib/internal/Magento/Framework/Indexer/CacheContext.php
@@ -3,7 +3,7 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model;
+namespace Magento\Framework\Indexer;
 
 /**
  * Class Context
diff --git a/app/code/Magento/Indexer/Model/Config/Converter.php b/lib/internal/Magento/Framework/Indexer/Config/Converter.php
similarity index 94%
rename from app/code/Magento/Indexer/Model/Config/Converter.php
rename to lib/internal/Magento/Framework/Indexer/Config/Converter.php
index 59aab2ae5688bc393d2e1b30d539982d0f00f2a4..5b441b97b3ee469d03847fc099ed0cb5bde0dfca 100644
--- a/app/code/Magento/Indexer/Model/Config/Converter.php
+++ b/lib/internal/Magento/Framework/Indexer/Config/Converter.php
@@ -3,7 +3,7 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model\Config;
+namespace Magento\Framework\Indexer\Config;
 
 use Magento\Framework\Config\ConverterInterface;
 
@@ -133,7 +133,7 @@ class Converter implements ConverterInterface
                         ['references'][$this->getAttributeValue($childNode, 'fieldset')]
                             : [];
                     $data['fieldsets'][$this->getAttributeValue($node, 'name')]['references']
-                    [$this->getAttributeValue($childNode, 'fieldset')][] = [
+                    [$this->getAttributeValue($childNode, 'fieldset')] = [
                         'fieldset' => $this->getAttributeValue($childNode, 'fieldset'),
                         'from'     => $this->getAttributeValue($childNode, 'from'),
                         'to'       => $this->getAttributeValue($childNode, 'to'),
@@ -211,7 +211,7 @@ class Converter implements ConverterInterface
     {
         $value = $node->nodeValue;
         if ($this->getAttributeValue($node, 'translate') == 'true') {
-            $value = __($value);
+            $value = new \Magento\Framework\Phrase($value);
         }
         return $value;
     }
@@ -224,14 +224,16 @@ class Converter implements ConverterInterface
      */
     protected function sorting($data)
     {
-        usort($data['fieldsets'], function ($current, $parent) {
-            if (!isset($current['references']) || isset($parent['references'][$current['name']])) {
+        usort($data['fieldsets'], function ($current, $parent) use ($data) {
+            if (!isset($current['references']) && $data['primary'] == $current['name']
+                || isset($parent['references'][$current['name']])
+            ) {
                 return -1;
-            }
-            if (!isset($parent['references']) || isset($current['references'][$parent['name']])) {
+            } elseif (!isset($parent['references']) || isset($current['references'][$parent['name']])) {
                 return 1;
+            } else {
+                return 0;
             }
-            return 0;
         });
         return $data;
     }
diff --git a/app/code/Magento/Indexer/Model/Config/Reader.php b/lib/internal/Magento/Framework/Indexer/Config/Reader.php
similarity index 87%
rename from app/code/Magento/Indexer/Model/Config/Reader.php
rename to lib/internal/Magento/Framework/Indexer/Config/Reader.php
index 93e337ba4903e717e9dcf7d185d2698500e87194..85eaa19c6de46c577a721d5be918f4cbb5778bac 100644
--- a/app/code/Magento/Indexer/Model/Config/Reader.php
+++ b/lib/internal/Magento/Framework/Indexer/Config/Reader.php
@@ -3,11 +3,8 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model\Config;
+namespace Magento\Framework\Indexer\Config;
 
-/**
- * @codeCoverageIgnore
- */
 class Reader extends \Magento\Framework\Config\Reader\Filesystem
 {
     /**
@@ -32,11 +29,13 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem
      * @param array $idAttributes
      * @param string $domDocumentClass
      * @param string $defaultScope
+     *
+     * @codeCoverageIgnore
      */
     public function __construct(
         \Magento\Framework\Config\FileResolverInterface $fileResolver,
-        \Magento\Indexer\Model\Config\Converter $converter,
-        \Magento\Indexer\Model\Config\SchemaLocator $schemaLocator,
+        \Magento\Framework\Indexer\Config\Converter $converter,
+        \Magento\Framework\Indexer\Config\SchemaLocator $schemaLocator,
         \Magento\Framework\Config\ValidationStateInterface $validationState,
         $fileName = 'indexer.xml',
         $idAttributes = [],
diff --git a/lib/internal/Magento/Framework/Indexer/Config/SchemaLocator.php b/lib/internal/Magento/Framework/Indexer/Config/SchemaLocator.php
new file mode 100644
index 0000000000000000000000000000000000000000..e6fffe6aa191feca8406d4b09708ade4cbd2a84b
--- /dev/null
+++ b/lib/internal/Magento/Framework/Indexer/Config/SchemaLocator.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Indexer\Config;
+
+use Magento\Framework\Config\SchemaLocatorInterface;
+
+class SchemaLocator implements SchemaLocatorInterface
+{
+    /**
+     * Get path to merged config schema
+     *
+     * @return string|null
+     */
+    public function getSchema()
+    {
+        return realpath(__DIR__ . '/../etc/') . '/indexer_merged.xsd';
+    }
+
+    /**
+     * Get path to pre file validation schema
+     *
+     * @return string|null
+     */
+    public function getPerFileSchema()
+    {
+        return realpath(__DIR__ . '/../etc/') . '/indexer.xsd';
+    }
+}
diff --git a/app/code/Magento/Indexer/Model/ConfigInterface.php b/lib/internal/Magento/Framework/Indexer/ConfigInterface.php
similarity index 91%
rename from app/code/Magento/Indexer/Model/ConfigInterface.php
rename to lib/internal/Magento/Framework/Indexer/ConfigInterface.php
index ce73150846dfd82a53ed669c59baf2c2f97f6d05..2ee055aca58ed950dec05ee0ded0de3e97160d0d 100644
--- a/app/code/Magento/Indexer/Model/ConfigInterface.php
+++ b/lib/internal/Magento/Framework/Indexer/ConfigInterface.php
@@ -3,7 +3,7 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model;
+namespace Magento\Framework\Indexer;
 
 interface ConfigInterface
 {
diff --git a/app/code/Magento/Indexer/Model/FieldsetInterface.php b/lib/internal/Magento/Framework/Indexer/FieldsetInterface.php
similarity index 68%
rename from app/code/Magento/Indexer/Model/FieldsetInterface.php
rename to lib/internal/Magento/Framework/Indexer/FieldsetInterface.php
index 751ede88fdf5d2ab89a39c6eff08763c4ec1f313..92673daa14ab535a2039be07e2ee60cdec45cec7 100644
--- a/app/code/Magento/Indexer/Model/FieldsetInterface.php
+++ b/lib/internal/Magento/Framework/Indexer/FieldsetInterface.php
@@ -3,18 +3,15 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model;
+namespace Magento\Framework\Indexer;
 
 interface FieldsetInterface
 {
     /**
+     * Add additional fields to fieldset
+     *
      * @param array $data
      * @return array
      */
     public function addDynamicData(array $data);
-
-    /**
-     * @return string
-     */
-    public function getDefaultHandler();
 }
diff --git a/app/code/Magento/Indexer/Model/FieldsetPool.php b/lib/internal/Magento/Framework/Indexer/FieldsetPool.php
similarity index 86%
rename from app/code/Magento/Indexer/Model/FieldsetPool.php
rename to lib/internal/Magento/Framework/Indexer/FieldsetPool.php
index 72e6be790bfcedda3994a7c8a9c719deac1b9047..86066fc110bc4accf02355be1396d6490b476059 100644
--- a/app/code/Magento/Indexer/Model/FieldsetPool.php
+++ b/lib/internal/Magento/Framework/Indexer/FieldsetPool.php
@@ -3,7 +3,7 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model;
+namespace Magento\Framework\Indexer;
 
 use Magento\Framework\ObjectManagerInterface;
 
@@ -34,7 +34,7 @@ class FieldsetPool
         $handler = $this->objectManager->get($fieldsetClass);
         if (!$handler instanceof FieldsetInterface) {
             throw new \InvalidArgumentException(
-                $fieldsetClass . ' doesn\'t implement \Magento\Indexer\Model\FieldsetInterface'
+                $fieldsetClass . ' doesn\'t implement \Magento\Framework\Indexer\FieldsetInterface'
             );
         }
         return $handler;
diff --git a/app/code/Magento/Indexer/Model/FilterInterface.php b/lib/internal/Magento/Framework/Indexer/FilterInterface.php
similarity index 84%
rename from app/code/Magento/Indexer/Model/FilterInterface.php
rename to lib/internal/Magento/Framework/Indexer/FilterInterface.php
index b2d5e39abcc36d81a3ff198cb5bb5d497e8f6035..e7d7cfd98b34b8200d8e19d46227c99eff961adf 100644
--- a/app/code/Magento/Indexer/Model/FilterInterface.php
+++ b/lib/internal/Magento/Framework/Indexer/FilterInterface.php
@@ -3,7 +3,7 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model;
+namespace Magento\Framework\Indexer;
 
 interface FilterInterface
 {
diff --git a/lib/internal/Magento/Framework/Indexer/GridStructure.php b/lib/internal/Magento/Framework/Indexer/GridStructure.php
new file mode 100644
index 0000000000000000000000000000000000000000..e7116fe3f0ef6ca24431a38867bbaeff44ecd719
--- /dev/null
+++ b/lib/internal/Magento/Framework/Indexer/GridStructure.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Indexer;
+
+use Magento\Framework\App\Resource;
+use Magento\Framework\DB\Ddl\Table;
+use Magento\Framework\Search\Request\Dimension;
+use Magento\Framework\DB\Adapter\AdapterInterface;
+use Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver;
+
+class GridStructure implements IndexStructureInterface
+{
+    /**
+     * @var Resource
+     */
+    private $resource;
+    /**
+     * @var FlatScopeResolver
+     */
+    private $flatScopeResolver;
+
+    /**
+     * @var array
+     */
+    protected $columnTypesMap = [
+        'varchar'    => ['type' => Table::TYPE_TEXT, 'size' => 255],
+        'mediumtext' => ['type' => Table::TYPE_TEXT, 'size' => 16777216],
+        'text'       => ['type' => Table::TYPE_TEXT, 'size' => 65536],
+        'int'        => ['type' => Table::TYPE_INTEGER, 'size' => null],
+        'date'       => ['type' => Table::TYPE_DATE, 'size' => null],
+        'datetime'   => ['type' => Table::TYPE_DATETIME, 'size' => null],
+        'timestamp'  => ['type' => Table::TYPE_TIMESTAMP, 'size' => null],
+    ];
+
+    /**
+     * @param Resource|Resource $resource
+     * @param FlatScopeResolver $flatScopeResolver
+     * @param array $columnTypesMap
+     */
+    public function __construct(
+        Resource $resource,
+        FlatScopeResolver $flatScopeResolver,
+        array $columnTypesMap = []
+    ) {
+        $this->resource = $resource;
+        $this->flatScopeResolver = $flatScopeResolver;
+        $this->columnTypesMap = array_merge($this->columnTypesMap, $columnTypesMap);
+    }
+
+    /**
+     * @param string $index
+     * @param Dimension[] $dimensions
+     * @return void
+     */
+    public function delete($index, array $dimensions = [])
+    {
+        $adapter = $this->getAdapter();
+        $tableName = $this->flatScopeResolver->resolve($index, $dimensions);
+        if ($adapter->isTableExists($tableName)) {
+            $adapter->dropTable($tableName);
+        }
+    }
+
+    /**
+     * @param string $index
+     * @param array $fields
+     * @param Dimension[] $dimensions
+     * @return void
+     */
+    public function create($index, array $fields, array $dimensions = [])
+    {
+        $this->createFlatTable($this->flatScopeResolver->resolve($index, $dimensions), $fields);
+    }
+
+    /**
+     * @param string $tableName
+     * @param array $fields
+     * @throws \Zend_Db_Exception
+     * @return void
+     */
+    protected function createFlatTable($tableName, array $fields)
+    {
+        $adapter = $this->getAdapter();
+        $table = $adapter->newTable($tableName);
+        $table->addColumn(
+            'entity_id',
+            Table::TYPE_INTEGER,
+            10,
+            ['unsigned' => true, 'nullable' => false, 'primary' => true],
+            'Entity ID'
+        );
+        $searchableFields = [];
+        foreach ($fields as $field) {
+            if ($field['type'] === 'searchable') {
+                $searchableFields[] = $field['name'];
+            }
+            $columnMap = isset($field['dataType']) && isset($this->columnTypesMap[$field['dataType']])
+                ? $this->columnTypesMap[$field['dataType']]
+                : ['type' => $field['dataType'], 'size' => isset($field['size']) ? $field['size'] : null];
+            $name = $field['name'];
+            $type = $columnMap['type'];
+            $size = $columnMap['size'];
+            if ($field['type'] === 'filterable') {
+                $table->addIndex(
+                    $this->resource->getIdxName($tableName, $name, AdapterInterface::INDEX_TYPE_INDEX),
+                    $name,
+                    AdapterInterface::INDEX_TYPE_INDEX
+                );
+            }
+            $table->addColumn($name, $type, $size);
+        }
+        $adapter->createTable($table);
+        $adapter->addIndex(
+            $tableName,
+            $this->resource->getIdxName(
+                $tableName,
+                $searchableFields,
+                AdapterInterface::INDEX_TYPE_FULLTEXT
+            ),
+            $searchableFields,
+            AdapterInterface::INDEX_TYPE_FULLTEXT
+        );
+    }
+
+    /**
+     * @return false|AdapterInterface
+     */
+    private function getAdapter()
+    {
+        $adapter = $this->resource->getConnection('write');
+        return $adapter;
+    }
+}
diff --git a/lib/internal/Magento/Framework/Indexer/Handler/AttributeHandler.php b/lib/internal/Magento/Framework/Indexer/Handler/AttributeHandler.php
new file mode 100644
index 0000000000000000000000000000000000000000..602c264ad7a1da61a3559fccfe5ca2eef4b6990e
--- /dev/null
+++ b/lib/internal/Magento/Framework/Indexer/Handler/AttributeHandler.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Indexer\Handler;
+
+use Magento\Framework\App\Resource\SourceProviderInterface;
+use Magento\Framework\Indexer\HandlerInterface;
+
+class AttributeHandler implements HandlerInterface
+{
+    /**
+     * Prepare SQL for field and add it to collection
+     *
+     * @param SourceProviderInterface $source
+     * @param string $alias
+     * @param array $fieldInfo
+     * @return void
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function prepareSql(SourceProviderInterface $source, $alias, $fieldInfo)
+    {
+        if (isset($fieldInfo['bind'])) {
+            $source->joinAttribute(
+                $fieldInfo['name'],
+                $fieldInfo['entity'] . '/' . $fieldInfo['origin'],
+                $fieldInfo['bind'],
+                null,
+                'left'
+            );
+        } else {
+            $source->addAttributeToSelect($fieldInfo['origin'], 'left');
+        }
+    }
+}
diff --git a/lib/internal/Magento/Framework/Indexer/Handler/ConcatHandler.php b/lib/internal/Magento/Framework/Indexer/Handler/ConcatHandler.php
new file mode 100644
index 0000000000000000000000000000000000000000..18f1db4d7663d40af7068fa12bfdae29bf7bb866
--- /dev/null
+++ b/lib/internal/Magento/Framework/Indexer/Handler/ConcatHandler.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Indexer\Handler;
+
+use Magento\Framework\Indexer\HandlerInterface;
+use Magento\Framework\App\Resource\SourceProviderInterface;
+
+class ConcatHandler implements HandlerInterface
+{
+    /**
+     * @var \Magento\Framework\DB\ConcatExpression
+     */
+    protected $concatExpression;
+
+    /**
+     * @param \Zend_Db_Expr $concatExpression
+     */
+    public function __construct(
+        \Zend_Db_Expr $concatExpression
+    ) {
+        $this->concatExpression = $concatExpression;
+    }
+
+    /**
+     * Prepare SQL for field and add it to collection
+     *
+     * @param SourceProviderInterface $source
+     * @param string $alias
+     * @param array $fieldInfo
+     * @return void
+     */
+    public function prepareSql(SourceProviderInterface $source, $alias, $fieldInfo)
+    {
+        $source->getSelect()->columns([$fieldInfo['name'] => $this->concatExpression]);
+    }
+}
diff --git a/lib/internal/Magento/Framework/Indexer/Handler/DefaultHandler.php b/lib/internal/Magento/Framework/Indexer/Handler/DefaultHandler.php
new file mode 100644
index 0000000000000000000000000000000000000000..a053db4bef817cf4ebc1f26c5dbc9532ba3bcdb2
--- /dev/null
+++ b/lib/internal/Magento/Framework/Indexer/Handler/DefaultHandler.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Indexer\Handler;
+
+use Magento\Framework\App\Resource\SourceProviderInterface;
+use Magento\Framework\Indexer\HandlerInterface;
+
+class DefaultHandler implements HandlerInterface
+{
+    /**
+     * @param SourceProviderInterface $source
+     * @param string $alias
+     * @param array $fieldInfo
+     * @return void
+     */
+    public function prepareSql(SourceProviderInterface $source, $alias, $fieldInfo)
+    {
+        $source->getSelect()->columns($fieldInfo['origin'] . ' AS ' . $fieldInfo['name'], $alias);
+    }
+}
diff --git a/app/code/Magento/Indexer/Model/HandlerInterface.php b/lib/internal/Magento/Framework/Indexer/HandlerInterface.php
similarity index 61%
rename from app/code/Magento/Indexer/Model/HandlerInterface.php
rename to lib/internal/Magento/Framework/Indexer/HandlerInterface.php
index 72d2a39c9e4341c27f4b4bb3503167d9bb9ad8f0..05a334c788f589a49f65e0c8903a1a6bbd9666e2 100644
--- a/app/code/Magento/Indexer/Model/HandlerInterface.php
+++ b/lib/internal/Magento/Framework/Indexer/HandlerInterface.php
@@ -3,23 +3,19 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model;
+namespace Magento\Framework\Indexer;
 
 use Magento\Framework\App\Resource\SourceProviderInterface;
 
 interface HandlerInterface
 {
     /**
+     * Prepare SQL for field and add it to collection
+     *
      * @param SourceProviderInterface $source
+     * @param string $alias
      * @param array $fieldInfo
      * @return void
      */
-    public function prepareSql(SourceProviderInterface $source, $fieldInfo);
-
-    /**
-     * @param SourceProviderInterface $source
-     * @param array $fieldInfo
-     * @return void
-     */
-    public function prepareData(SourceProviderInterface $source, $fieldInfo);
+    public function prepareSql(SourceProviderInterface $source, $alias, $fieldInfo);
 }
diff --git a/app/code/Magento/Indexer/Model/HandlerPool.php b/lib/internal/Magento/Framework/Indexer/HandlerPool.php
similarity index 80%
rename from app/code/Magento/Indexer/Model/HandlerPool.php
rename to lib/internal/Magento/Framework/Indexer/HandlerPool.php
index f26301c87df506000f067ad28bd0ff740314ac6a..97cd9787d8fe1e79a1741108cff9c3d7e02c8efa 100644
--- a/app/code/Magento/Indexer/Model/HandlerPool.php
+++ b/lib/internal/Magento/Framework/Indexer/HandlerPool.php
@@ -3,8 +3,9 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model;
+namespace Magento\Framework\Indexer;
 
+use Magento\Framework\Indexer\Handler\DefaultHandler;
 use Magento\Framework\ObjectManagerInterface;
 
 class HandlerPool
@@ -21,11 +22,11 @@ class HandlerPool
 
     /**
      * @param ObjectManagerInterface $objectManager
-     * @param HandlerInterface $defaultHandler
+     * @param DefaultHandler $defaultHandler
      */
     public function __construct(
         ObjectManagerInterface $objectManager,
-        HandlerInterface $defaultHandler
+        DefaultHandler $defaultHandler
     ) {
         $this->defaultHandler = $defaultHandler;
         $this->objectManager = $objectManager;
@@ -47,7 +48,7 @@ class HandlerPool
         $handler = $this->objectManager->get($handlerClass);
         if (!$handler instanceof HandlerInterface) {
             throw new \InvalidArgumentException(
-                $handlerClass . ' doesn\'t implement \Magento\Indexer\Model\HandlerInterface'
+                $handlerClass . ' doesn\'t implement \Magento\Framework\Indexer\HandlerInterface'
             );
         }
 
diff --git a/app/code/Magento/Indexer/Model/IndexStructure.php b/lib/internal/Magento/Framework/Indexer/IndexStructure.php
similarity index 89%
rename from app/code/Magento/Indexer/Model/IndexStructure.php
rename to lib/internal/Magento/Framework/Indexer/IndexStructure.php
index ca65108f330f10b0676ea26ee8a6e50e52e083d3..f07090e5e821a888f2d9c1d22eeb3d4a9e34abd7 100644
--- a/app/code/Magento/Indexer/Model/IndexStructure.php
+++ b/lib/internal/Magento/Framework/Indexer/IndexStructure.php
@@ -4,24 +4,23 @@
  * See COPYING.txt for license details.
  */
 
-namespace Magento\Indexer\Model;
-
+namespace Magento\Framework\Indexer;
 
 use Magento\Framework\App\Resource;
 use Magento\Framework\DB\Adapter\AdapterInterface;
 use Magento\Framework\DB\Ddl\Table;
 use Magento\Framework\Search\Request\Dimension;
-use Magento\Indexer\Model\ScopeResolver\FlatScopeResolver;
-use Magento\Indexer\Model\ScopeResolver\IndexScopeResolver;
+use Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver;
+use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
 
-class IndexStructure
+class IndexStructure implements IndexStructureInterface
 {
     /**
      * @var Resource
      */
     private $resource;
     /**
-     * @var \Magento\Indexer\Model\ScopeResolver\IndexScopeResolver
+     * @var \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver
      */
     private $indexScopeResolver;
     /**
@@ -41,7 +40,7 @@ class IndexStructure
     /**
      * @param Resource|Resource $resource
      * @param IndexScopeResolver $indexScopeResolver
-     * @param \Magento\Indexer\Model\ScopeResolver\FlatScopeResolver $flatScopeResolver
+     * @param \Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver $flatScopeResolver
      * @param array $columnTypesMap
      */
     public function __construct(
@@ -69,15 +68,15 @@ class IndexStructure
 
     /**
      * @param string $index
-     * @param array $filterFields
+     * @param array $fields
      * @param Dimension[] $dimensions
      * @return void
      */
-    public function create($index, array $filterFields, array $dimensions = [])
+    public function create($index, array $fields, array $dimensions = [])
     {
         $this->createFulltextIndex($this->indexScopeResolver->resolve($index, $dimensions));
-        if ($filterFields) {
-            $this->createFlatIndex($this->flatScopeResolver->resolve($index, $dimensions), $filterFields);
+        if ($fields) {
+            $this->createFlatIndex($this->flatScopeResolver->resolve($index, $dimensions), $fields);
         }
     }
 
diff --git a/lib/internal/Magento/Framework/Indexer/IndexStructureInterface.php b/lib/internal/Magento/Framework/Indexer/IndexStructureInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..0afff912eba273d58ad6bcb498bd9efa4898d5eb
--- /dev/null
+++ b/lib/internal/Magento/Framework/Indexer/IndexStructureInterface.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Indexer;
+
+use Magento\Framework\Search\Request\Dimension;
+
+interface IndexStructureInterface
+{
+    /**
+     * @param string $index
+     * @param Dimension[] $dimensions
+     * @return void
+     */
+    public function delete($index, array $dimensions = []);
+
+    /**
+     * @param string $index
+     * @param array $fields
+     * @param Dimension[] $dimensions
+     * @return void
+     */
+    public function create($index, array $fields, array $dimensions = []);
+}
diff --git a/app/code/Magento/Indexer/Model/IndexerInterface.php b/lib/internal/Magento/Framework/Indexer/IndexerInterface.php
similarity index 94%
rename from app/code/Magento/Indexer/Model/IndexerInterface.php
rename to lib/internal/Magento/Framework/Indexer/IndexerInterface.php
index 35251f383f587665d28d76d687a1ebb0880d091e..82c1eae6a5a1ce368ed85c0efb92177537848e7a 100644
--- a/app/code/Magento/Indexer/Model/IndexerInterface.php
+++ b/lib/internal/Magento/Framework/Indexer/IndexerInterface.php
@@ -3,7 +3,7 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model;
+namespace Magento\Framework\Indexer;
 
 interface IndexerInterface
 {
@@ -82,17 +82,17 @@ interface IndexerInterface
     /**
      * Return related state object
      *
-     * @return Indexer\State
+     * @return StateInterface
      */
     public function getState();
 
     /**
      * Set indexer state object
      *
-     * @param Indexer\State $state
+     * @param StateInterface $state
      * @return IndexerInterface
      */
-    public function setState(Indexer\State $state);
+    public function setState(StateInterface $state);
 
     /**
      * Check whether indexer is run by schedule
diff --git a/app/code/Magento/Indexer/Model/IndexerRegistry.php b/lib/internal/Magento/Framework/Indexer/IndexerRegistry.php
similarity index 91%
rename from app/code/Magento/Indexer/Model/IndexerRegistry.php
rename to lib/internal/Magento/Framework/Indexer/IndexerRegistry.php
index da1b70fdc7922abcf9a56b10d866b11449368680..14dfddc4d7c5a1471c71036d19f2783682df13d7 100644
--- a/app/code/Magento/Indexer/Model/IndexerRegistry.php
+++ b/lib/internal/Magento/Framework/Indexer/IndexerRegistry.php
@@ -3,7 +3,7 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model;
+namespace Magento\Framework\Indexer;
 
 class IndexerRegistry
 {
@@ -34,7 +34,7 @@ class IndexerRegistry
     public function get($indexerId)
     {
         if (!isset($this->indexers[$indexerId])) {
-            $this->indexers[$indexerId] = $this->objectManager->create('Magento\Indexer\Model\IndexerInterface')
+            $this->indexers[$indexerId] = $this->objectManager->create('Magento\Framework\Indexer\IndexerInterface')
                 ->load($indexerId);
         }
         return $this->indexers[$indexerId];
diff --git a/lib/internal/Magento/Framework/Indexer/README.md b/lib/internal/Magento/Framework/Indexer/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..aa392d2facdbf0c9729cede8c0c226888280a3b6
--- /dev/null
+++ b/lib/internal/Magento/Framework/Indexer/README.md
@@ -0,0 +1 @@
+A library for indexing processing
diff --git a/app/code/Magento/Indexer/Model/SaveHandler/Batch.php b/lib/internal/Magento/Framework/Indexer/SaveHandler/Batch.php
similarity index 93%
rename from app/code/Magento/Indexer/Model/SaveHandler/Batch.php
rename to lib/internal/Magento/Framework/Indexer/SaveHandler/Batch.php
index 68c3d20bda20cbafeb982fa7924443f79f52526a..5f432356d3d1b1f27a8f146464c280073f7859df 100644
--- a/app/code/Magento/Indexer/Model/SaveHandler/Batch.php
+++ b/lib/internal/Magento/Framework/Indexer/SaveHandler/Batch.php
@@ -3,7 +3,7 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model\SaveHandler;
+namespace Magento\Framework\Indexer\SaveHandler;
 
 class Batch
 {
diff --git a/lib/internal/Magento/Framework/Indexer/SaveHandler/Grid.php b/lib/internal/Magento/Framework/Indexer/SaveHandler/Grid.php
new file mode 100644
index 0000000000000000000000000000000000000000..2f7136cb812ab511de87e0fef32234816427362b
--- /dev/null
+++ b/lib/internal/Magento/Framework/Indexer/SaveHandler/Grid.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Indexer\SaveHandler;
+
+use Magento\Framework\Search\Request\Dimension;
+
+class Grid extends IndexerHandler
+{
+    /**
+     * @var string[]
+     */
+    protected $dataTypes = ['searchable', 'filterable', 'virtual'];
+
+    /**
+     * {@inheritdoc}
+     */
+    public function saveIndex($dimensions, \Traversable $documents)
+    {
+        foreach ($this->batch->getItems($documents, $this->batchSize) as $batchDocuments) {
+            $this->insertDocumentsForFilterable($batchDocuments, $dimensions);
+        }
+    }
+
+    /**
+     * @param array $documents
+     * @param Dimension[] $dimensions
+     * @return void
+     */
+    protected function insertDocumentsForFilterable(array $documents, array $dimensions)
+    {
+        $onDuplicate = [];
+        foreach ($this->fields as $field) {
+            if (in_array($field['type'], $this->dataTypes)) {
+                $onDuplicate[] = $field['name'];
+            }
+        }
+
+        $this->connection->insertOnDuplicate(
+            $this->getTableName($this->dataTypes[1], $dimensions),
+            $this->prepareFilterableFields($documents),
+            $onDuplicate
+        );
+    }
+
+    /**
+     * @param array $documents
+     * @return array
+     */
+    protected function prepareFilterableFields(array $documents)
+    {
+        $insertDocuments = [];
+        foreach ($documents as $entityId => $document) {
+            $documentFlat = ['entity_id' => $entityId];
+            foreach ($this->fields as $field) {
+                if (in_array($field['type'], $this->dataTypes)) {
+                    $documentFlat[$field['name']] = $document[$field['name']];
+                }
+            }
+            $insertDocuments[] = $documentFlat;
+        }
+        return $insertDocuments;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function deleteIndex($dimensions, \Traversable $ids)
+    {
+        foreach ($this->batch->getItems($ids, $this->batchSize) as $batchIds) {
+            $this->connection->delete(
+                $this->getTableName('filterable', $dimensions),
+                ['entity_id IN(?)' => $batchIds]
+            );
+        }
+    }
+}
diff --git a/app/code/Magento/Indexer/Model/SaveHandler/IndexerHandler.php b/lib/internal/Magento/Framework/Indexer/SaveHandler/IndexerHandler.php
similarity index 80%
rename from app/code/Magento/Indexer/Model/SaveHandler/IndexerHandler.php
rename to lib/internal/Magento/Framework/Indexer/SaveHandler/IndexerHandler.php
index 235a9548fbf2a09879a080145286279f985e4f58..cabda6c830c61373cc752a7f72d7e345521909ed 100644
--- a/app/code/Magento/Indexer/Model/SaveHandler/IndexerHandler.php
+++ b/lib/internal/Magento/Framework/Indexer/SaveHandler/IndexerHandler.php
@@ -3,75 +3,76 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model\SaveHandler;
+namespace Magento\Framework\Indexer\SaveHandler;
 
 use Magento\Framework\App\Resource;
 use Magento\Framework\DB\Adapter\AdapterInterface;
-use Magento\Framework\IndexerInterface;
-use Magento\Indexer\Model\IndexStructure;
 use Magento\Framework\Search\Request\Dimension;
 use Magento\Framework\Search\Request\IndexScopeResolverInterface;
-use Magento\Indexer\Model\ScopeResolver\FlatScopeResolver;
-use Magento\Indexer\Model\ScopeResolver\IndexScopeResolver;
+use Magento\Framework\Indexer\IndexStructureInterface;
+use Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver;
+use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
+use Magento\Framework\Indexer\SaveHandler\Batch;
 
 class IndexerHandler implements IndexerInterface
 {
     /**
      * @var string[]
      */
-    private $dataTypes = ['searchable', 'filterable'];
+    protected $dataTypes = ['searchable', 'filterable'];
 
     /**
-     * @var IndexStructure
+     * @var IndexStructureInterface
      */
-    private $indexStructure;
+    protected $indexStructure;
 
     /**
      * @var array
      */
-    private $data;
+    protected $data;
 
     /**
      * @var array
      */
-    private $fields;
+    protected $fields;
 
     /**
      * @var Resource|Resource
      */
-    private $resource;
+    protected $resource;
 
     /**
      * @var Batch
      */
-    private $batch;
+    protected $batch;
 
     /**
      * @var int
      */
-    private $batchSize;
+    protected $batchSize;
 
     /**
      * @var IndexScopeResolverInterface[]
      */
-    private $scopeResolvers;
+    protected $scopeResolvers;
 
     /**
+     * @param IndexStructureInterface $indexStructure
      * @var AdapterInterface
      */
-    private $connection;
+    protected $connection;
 
     /**
-     * @param IndexStructure $indexStructure
+     * @param IndexStructureInterface $indexStructure
      * @param Resource $resource
      * @param Batch $batch
-     * @param \Magento\Indexer\Model\ScopeResolver\IndexScopeResolver $indexScopeResolver
-     * @param \Magento\Indexer\Model\ScopeResolver\FlatScopeResolver $flatScopeResolver
+     * @param \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver $indexScopeResolver
+     * @param \Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver $flatScopeResolver
      * @param array $data
      * @param int $batchSize
      */
     public function __construct(
-        IndexStructure $indexStructure,
+        IndexStructureInterface $indexStructure,
         Resource $resource,
         Batch $batch,
         IndexScopeResolver $indexScopeResolver,
@@ -138,7 +139,7 @@ class IndexerHandler implements IndexerInterface
      * @param Dimension[] $dimensions
      * @return string
      */
-    private function getTableName($dataType, $dimensions)
+    protected function getTableName($dataType, $dimensions)
     {
         return $this->scopeResolvers[$dataType]->resolve($this->getIndexName(), $dimensions);
     }
@@ -146,7 +147,7 @@ class IndexerHandler implements IndexerInterface
     /**
      * @return string
      */
-    private function getIndexName()
+    protected function getIndexName()
     {
         return $this->data['indexer_id'];
     }
@@ -170,7 +171,7 @@ class IndexerHandler implements IndexerInterface
      * @param Dimension[] $dimensions
      * @return void
      */
-    private function insertDocumentsForFilterable(array $documents, array $dimensions)
+    protected function insertDocumentsForFilterable(array $documents, array $dimensions)
     {
         $onDuplicate = [];
         foreach ($this->fields as $field) {
@@ -190,7 +191,7 @@ class IndexerHandler implements IndexerInterface
      * @param array $documents
      * @return array
      */
-    private function prepareFilterableFields(array $documents)
+    protected function prepareFilterableFields(array $documents)
     {
         $insertDocuments = [];
         foreach ($documents as $entityId => $document) {
@@ -233,7 +234,7 @@ class IndexerHandler implements IndexerInterface
     private function prepareFields()
     {
         foreach ($this->data['fieldsets'] as $fieldset) {
-            $this->fields = array_merge($this->fields, $fieldset['fields']);
+            $this->fields = array_merge($this->fields, array_values($fieldset['fields']));
         }
     }
 }
diff --git a/lib/internal/Magento/Framework/IndexerInterface.php b/lib/internal/Magento/Framework/Indexer/SaveHandler/IndexerInterface.php
similarity index 95%
rename from lib/internal/Magento/Framework/IndexerInterface.php
rename to lib/internal/Magento/Framework/Indexer/SaveHandler/IndexerInterface.php
index b321e7693feaf58eac4798049b45575a6d31d817..457ce3374d9ed6990a2af9a2352fd425105e4474 100644
--- a/lib/internal/Magento/Framework/IndexerInterface.php
+++ b/lib/internal/Magento/Framework/Indexer/SaveHandler/IndexerInterface.php
@@ -7,7 +7,7 @@
 /**
  * Index Engine Interface
  */
-namespace Magento\Framework;
+namespace Magento\Framework\Indexer\SaveHandler;
 
 use Magento\Framework\Search\Request\Dimension;
 
diff --git a/app/code/Magento/Indexer/Model/SaveHandlerFactory.php b/lib/internal/Magento/Framework/Indexer/SaveHandlerFactory.php
similarity index 86%
rename from app/code/Magento/Indexer/Model/SaveHandlerFactory.php
rename to lib/internal/Magento/Framework/Indexer/SaveHandlerFactory.php
index e9a215eb86880ce8e41209069c6ec052ee5d3fed..c8e490a87fa63bd3f6e580aa6b6bffdbf5079c16 100644
--- a/app/code/Magento/Indexer/Model/SaveHandlerFactory.php
+++ b/lib/internal/Magento/Framework/Indexer/SaveHandlerFactory.php
@@ -3,10 +3,11 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model;
+namespace Magento\Framework\Indexer;
 
+use Magento\Framework\Indexer\IndexerInterface;
 use Magento\Framework\ObjectManagerInterface;
-use Magento\Framework\IndexerInterface as SaveHandlerInterface;
+use Magento\Framework\Indexer\SaveHandler\IndexerInterface as SaveHandlerInterface;
 
 class SaveHandlerFactory
 {
diff --git a/app/code/Magento/Indexer/Model/ScopeResolver/FlatScopeResolver.php b/lib/internal/Magento/Framework/Indexer/ScopeResolver/FlatScopeResolver.php
similarity index 89%
rename from app/code/Magento/Indexer/Model/ScopeResolver/FlatScopeResolver.php
rename to lib/internal/Magento/Framework/Indexer/ScopeResolver/FlatScopeResolver.php
index 8e415be17131e8340e5ccbc0b30722469dc825ca..dfa7fd69d498ec01126f7ff411dc6f14824448fa 100644
--- a/app/code/Magento/Indexer/Model/ScopeResolver/FlatScopeResolver.php
+++ b/lib/internal/Magento/Framework/Indexer/ScopeResolver/FlatScopeResolver.php
@@ -4,11 +4,10 @@
  * See COPYING.txt for license details.
  */
 
-namespace Magento\Indexer\Model\ScopeResolver;
+namespace Magento\Framework\Indexer\ScopeResolver;
 
 use Magento\Framework\Search\Request\Dimension;
 use Magento\Framework\Search\Request\IndexScopeResolverInterface;
-use Magento\Indexer\Model\ScopeResolver\IndexScopeResolver;
 
 class FlatScopeResolver implements IndexScopeResolverInterface
 {
diff --git a/app/code/Magento/Indexer/Model/ScopeResolver/IndexScopeResolver.php b/lib/internal/Magento/Framework/Indexer/ScopeResolver/IndexScopeResolver.php
similarity index 97%
rename from app/code/Magento/Indexer/Model/ScopeResolver/IndexScopeResolver.php
rename to lib/internal/Magento/Framework/Indexer/ScopeResolver/IndexScopeResolver.php
index 696d6af0041b2dd1695b56b5a49c08a7f21ca7ce..a5f1a4657670b3f6ed265b9b4d29388bcb09d1e6 100644
--- a/app/code/Magento/Indexer/Model/ScopeResolver/IndexScopeResolver.php
+++ b/lib/internal/Magento/Framework/Indexer/ScopeResolver/IndexScopeResolver.php
@@ -4,8 +4,7 @@
  * See COPYING.txt for license details.
  */
 
-namespace Magento\Indexer\Model\ScopeResolver;
-
+namespace Magento\Framework\Indexer\ScopeResolver;
 
 use Magento\Framework\App\Resource;
 use Magento\Framework\App\ScopeResolverInterface;
diff --git a/lib/internal/Magento/Framework/Indexer/StateInterface.php b/lib/internal/Magento/Framework/Indexer/StateInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..cb755ed97818803adb7a41e317799e40ac371e4b
--- /dev/null
+++ b/lib/internal/Magento/Framework/Indexer/StateInterface.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Indexer;
+
+interface StateInterface
+{
+    /**
+     * Indexer statuses
+     */
+    const STATUS_WORKING = 'working';
+    const STATUS_VALID = 'valid';
+    const STATUS_INVALID = 'invalid';
+
+    /**
+     * Return indexer id
+     *
+     * @return string
+     */
+    public function getIndexerId();
+
+    /**
+     * Set indexer id
+     *
+     * @param string $value
+     * @return $this
+     */
+    public function setIndexerId($value);
+
+    /**
+     * Return status
+     *
+     * @return string
+     */
+    public function getStatus();
+
+    /**
+     * Return updated
+     *
+     * @return string
+     */
+    public function getUpdated();
+
+    /**
+     * Set updated
+     *
+     * @param string $value
+     * @return $this
+     */
+    public function setUpdated($value);
+
+    /**
+     * Fill object with state data by view ID
+     *
+     * @param string $indexerId
+     * @return $this
+     */
+    public function loadByIndexer($indexerId);
+
+    /**
+     * Status setter
+     *
+     * @param string $status
+     * @return $this
+     */
+    public function setStatus($status);
+}
diff --git a/lib/internal/Magento/Framework/Indexer/StructureFactory.php b/lib/internal/Magento/Framework/Indexer/StructureFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..ae1dc0c1cd8dcc2e0c2333b045086df77a8824df
--- /dev/null
+++ b/lib/internal/Magento/Framework/Indexer/StructureFactory.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Indexer;
+
+use Magento\Framework\Indexer\IndexStructureInterface;
+
+class StructureFactory
+{
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    /**
+     * @param \Magento\Framework\ObjectManagerInterface $objectManager
+     */
+    public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager)
+    {
+        $this->objectManager = $objectManager;
+    }
+
+    /**
+     * Get structure class instance by class name
+     *
+     * @param string $className
+     * @param [] $arguments
+     * @throws \InvalidArgumentException
+     * @return IndexStructureInterface
+     */
+    public function create($className, $arguments = [])
+    {
+        $structure = $this->objectManager->create($className, $arguments);
+        if (!$structure instanceof IndexStructureInterface) {
+            throw new \InvalidArgumentException(
+                $className . ' doesn\'t implement \Magento\Framework\Indexer\IndexStructureInterface'
+            );
+        }
+
+        return $structure;
+    }
+}
diff --git a/app/code/Magento/Indexer/Model/Indexer/Table/Strategy.php b/lib/internal/Magento/Framework/Indexer/Table/Strategy.php
similarity index 96%
rename from app/code/Magento/Indexer/Model/Indexer/Table/Strategy.php
rename to lib/internal/Magento/Framework/Indexer/Table/Strategy.php
index 2d6c154a2a707879fc47cd6bd5720806b2e96733..6abcfb1c6afdcecacd8df418fa1162ea829b16fa 100644
--- a/app/code/Magento/Indexer/Model/Indexer/Table/Strategy.php
+++ b/lib/internal/Magento/Framework/Indexer/Table/Strategy.php
@@ -3,7 +3,7 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Model\Indexer\Table;
+namespace Magento\Framework\Indexer\Table;
 
 /**
  * Class Strategy
diff --git a/app/code/Magento/Indexer/Model/Indexer/Table/StrategyInterface.php b/lib/internal/Magento/Framework/Indexer/Table/StrategyInterface.php
similarity index 95%
rename from app/code/Magento/Indexer/Model/Indexer/Table/StrategyInterface.php
rename to lib/internal/Magento/Framework/Indexer/Table/StrategyInterface.php
index c1693ceb44cd47f8a7d7e7de2649e6264985ad77..842a811034b65d28f5adfee9af2fb99eccef6892 100644
--- a/app/code/Magento/Indexer/Model/Indexer/Table/StrategyInterface.php
+++ b/lib/internal/Magento/Framework/Indexer/Table/StrategyInterface.php
@@ -4,7 +4,7 @@
  * See COPYING.txt for license details.
  */
 
-namespace Magento\Indexer\Model\Indexer\Table;
+namespace Magento\Framework\Indexer\Table;
 
 /**
  * Interface StrategyInterface
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/ActionFactoryTest.php b/lib/internal/Magento/Framework/Indexer/Test/Unit/ActionFactoryTest.php
similarity index 69%
rename from app/code/Magento/Indexer/Test/Unit/Model/ActionFactoryTest.php
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/ActionFactoryTest.php
index 0aa4997661a3c58b6c6d5e4ab26be211d997e7df..d8dd5d817a0f1e4e55ae0f4f284e72a306e4ac76 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/ActionFactoryTest.php
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/ActionFactoryTest.php
@@ -3,12 +3,12 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Test\Unit\Model;
+namespace Magento\Framework\Indexer\Test\Unit;
 
 class ActionFactoryTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Indexer\Model\ActionFactory|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\ActionFactory|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $model;
 
@@ -20,12 +20,12 @@ class ActionFactoryTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->objectManagerMock = $this->getMock('Magento\Framework\ObjectManagerInterface');
-        $this->model = new \Magento\Indexer\Model\ActionFactory($this->objectManagerMock);
+        $this->model = new \Magento\Framework\Indexer\ActionFactory($this->objectManagerMock);
     }
 
     /**
      * @expectedException \InvalidArgumentException
-     * @expectedExceptionMessage NotAction doesn't implement \Magento\Indexer\Model\ActionInterface
+     * @expectedExceptionMessage NotAction doesn't implement \Magento\Framework\Indexer\ActionInterface
      */
     public function testGetWithException()
     {
@@ -40,16 +40,16 @@ class ActionFactoryTest extends \PHPUnit_Framework_TestCase
     public function testCreate()
     {
         $actionInterfaceMock = $this->getMockForAbstractClass(
-            'Magento\Indexer\Model\ActionInterface',
+            'Magento\Framework\Indexer\ActionInterface',
             [],
             '',
             false
         );
         $this->objectManagerMock->expects($this->once())
             ->method('create')
-            ->with('Magento\Indexer\Model\ActionInterface', [])
+            ->with('Magento\Framework\Indexer\ActionInterface', [])
             ->willReturn($actionInterfaceMock);
-        $this->model->create('Magento\Indexer\Model\ActionInterface');
-        $this->assertInstanceOf('Magento\Indexer\Model\ActionInterface', $actionInterfaceMock);
+        $this->model->create('Magento\Framework\Indexer\ActionInterface');
+        $this->assertInstanceOf('Magento\Framework\Indexer\ActionInterface', $actionInterfaceMock);
     }
 }
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/Config/ConverterTest.php b/lib/internal/Magento/Framework/Indexer/Test/Unit/Config/ConverterTest.php
similarity index 60%
rename from app/code/Magento/Indexer/Test/Unit/Model/Config/ConverterTest.php
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/Config/ConverterTest.php
index 3be90c1459b5a6f773450d9debaf86cf673d2e2d..ac0061f25579865275d290f4563f1f4fa3ecfe97 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/Config/ConverterTest.php
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/Config/ConverterTest.php
@@ -3,23 +3,23 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Test\Unit\Model\Config;
+namespace Magento\Framework\Indexer\Test\Unit\Config;
 
 class ConverterTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Indexer\Model\Config\Converter|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\Config\Converter|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $_model;
 
     protected function setUp()
     {
-        $this->_model = new \Magento\Indexer\Model\Config\Converter();
+        $this->_model = new \Magento\Framework\Indexer\Config\Converter();
     }
 
     public function testConvert()
     {
-        $data = include __DIR__ . '/../../_files/indexer_config.php';
+        $data = include __DIR__ . '/../_files/indexer_config.php';
         $dom = new \DOMDocument();
         $dom->loadXML($data['inputXML']);
 
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/Config/ReaderTest.php b/lib/internal/Magento/Framework/Indexer/Test/Unit/Config/ReaderTest.php
similarity index 69%
rename from app/code/Magento/Indexer/Test/Unit/Model/Config/ReaderTest.php
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/Config/ReaderTest.php
index 15125405ac0026a72d4f870a1be6fe38c55b1dd8..266ddc2ae61ce697deaad008a2da32a0d206c1a0 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/Config/ReaderTest.php
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/Config/ReaderTest.php
@@ -3,17 +3,17 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Test\Unit\Model\Config;
+namespace Magento\Framework\Indexer\Test\Unit\Config;
 
 class ReaderTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Indexer\Model\Config\Reader
+     * @var \Magento\Framework\Indexer\Config\Reader
      */
     protected $_model;
 
     /**
-     * @var \Magento\Indexer\Model\Config\Converter|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\Config\Converter|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $_converter;
 
@@ -32,34 +32,14 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
             false
         );
 
-        $this->_converter = $this->getMock('Magento\Indexer\Model\Config\Converter', ['convert']);
-
-        $moduleReader = $this->getMock(
-            'Magento\Framework\Module\Dir\Reader',
-            ['getModuleDir'],
-            [],
-            '',
-            false
-        );
-        $moduleReader->expects(
-            $this->once()
-        )->method(
-            'getModuleDir'
-        )->with(
-            'etc',
-            'Magento_Indexer'
-        )->will(
-            $this->returnValue('stub')
-        );
-        $schemaLocator = new \Magento\Indexer\Model\Config\SchemaLocator($moduleReader);
-
+        $this->_converter = $this->getMock('Magento\Framework\Indexer\Config\Converter', ['convert']);
         $validationState = $this->getMock('Magento\Framework\Config\ValidationStateInterface');
         $validationState->expects($this->once())->method('isValidated')->will($this->returnValue(false));
 
-        $this->_model = new \Magento\Indexer\Model\Config\Reader(
+        $this->_model = new \Magento\Framework\Indexer\Config\Reader(
             $this->_fileResolverMock,
             $this->_converter,
-            $schemaLocator,
+            new \Magento\Framework\Indexer\Config\SchemaLocator(),
             $validationState
         );
     }
@@ -82,7 +62,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
 
         $constraint = function (\DOMDocument $actual) use ($expectedFile) {
             try {
-                $expected = file_get_contents(__DIR__ . '/../../_files/' . $expectedFile);
+                $expected = file_get_contents(__DIR__ . '/../_files/' . $expectedFile);
                 \PHPUnit_Framework_Assert::assertXmlStringEqualsXmlString($expected, $actual->saveXML());
                 return true;
             } catch (\PHPUnit_Framework_AssertionFailedError $e) {
@@ -111,15 +91,15 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
         return [
             [
                 [
-                    'indexer_one.xml' => file_get_contents(__DIR__ . '/../../_files/indexer_one.xml'),
-                    'indexer_two.xml' => file_get_contents(__DIR__ . '/../../_files/indexer_two.xml'),
+                    'indexer_one.xml' => file_get_contents(__DIR__ . '/../_files/indexer_one.xml'),
+                    'indexer_two.xml' => file_get_contents(__DIR__ . '/../_files/indexer_two.xml'),
                 ],
                 'indexer_merged_one.xml',
             ],
             [
                 [
-                    'indexer_one.xml' => file_get_contents(__DIR__ . '/../../_files/indexer_one.xml'),
-                    'indexer_three.xml' => file_get_contents(__DIR__ . '/../../_files/indexer_three.xml'),
+                    'indexer_one.xml' => file_get_contents(__DIR__ . '/../_files/indexer_one.xml'),
+                    'indexer_three.xml' => file_get_contents(__DIR__ . '/../_files/indexer_three.xml'),
                 ],
                 'indexer_merged_two.xml'
             ]
diff --git a/lib/internal/Magento/Framework/Indexer/Test/Unit/GridStructureTest.php b/lib/internal/Magento/Framework/Indexer/Test/Unit/GridStructureTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..bf1ea53a8e9e4259323ce92266f9c28f9ab4c75b
--- /dev/null
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/GridStructureTest.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Indexer\Test\Unit;
+
+use Magento\Framework\Indexer\GridStructure;
+use Magento\Framework\DB\Adapter\AdapterInterface;
+use Magento\Framework\DB\Ddl\Table;
+
+class GridStructureTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\App\Resource|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $resource;
+
+    /**
+     * @var \Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $flatScopeResolver;
+
+    /**
+     * @var \Magento\Framework\DB\Adapter\AdapterInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $connection;
+
+    /**
+     * @var GridStructure
+     */
+    protected $object;
+
+    public function setUp()
+    {
+        $this->connection = $this->getMockBuilder('Magento\Framework\DB\Adapter\AdapterInterface')
+            ->getMock();
+        $this->resource = $this->getMockBuilder('Magento\Framework\App\Resource')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->flatScopeResolver = $this->getMockBuilder('Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->resource->expects($this->any())
+            ->method('getConnection')
+            ->with('write')
+            ->willReturn($this->connection);
+        $this->object = new GridStructure(
+            $this->resource,
+            $this->flatScopeResolver
+        );
+    }
+
+    public function testDelete()
+    {
+        $index = 'index';
+        $table = 'index_table';
+
+        $this->flatScopeResolver->expects($this->once())
+            ->method('resolve')
+            ->with($index, [])
+            ->willReturn($table);
+        $this->connection->expects($this->once())
+            ->method('isTableExists')
+            ->with($table)
+            ->willReturn(true);
+        $this->connection->expects($this->once())
+            ->method('dropTable')
+            ->with($table);
+
+        $this->object->delete($index);
+    }
+
+    public function testCreate()
+    {
+        $index = 'index';
+        $fields = [
+            [
+                'type'     => 'searchable',
+                'name'     => 'field',
+                'dataType' => 'int'
+            ]
+        ];
+        $tableName = 'index_table';
+        $idxName = 'idxName';
+
+        $table = $this->getMockBuilder('Magento\Framework\DB\Ddl\Table')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->flatScopeResolver->expects($this->once())
+            ->method('resolve')
+            ->with($index, [])
+            ->willReturn($tableName);
+        $this->connection->expects($this->once())
+            ->method('newTable')
+            ->with($tableName)
+            ->willReturn($table);
+        $table->expects($this->any())
+            ->method('addColumn')
+            ->willReturnMap(
+                [
+                    ['entity_id', Table::TYPE_INTEGER, 10, ['unsigned' => true, 'nullable' => false], 'Entity ID'],
+                    ['field', Table::TYPE_INTEGER, null]
+                ]
+            );
+        $this->connection->expects($this->once())
+            ->method('createTable')
+            ->with($table);
+        $this->resource->expects($this->once())
+            ->method('getIdxName')
+            ->with($tableName, ['field'], AdapterInterface::INDEX_TYPE_FULLTEXT)
+            ->willReturn($idxName);
+        $this->connection->expects($this->once())
+            ->method('addIndex')
+            ->with($tableName, $idxName, ['field'], AdapterInterface::INDEX_TYPE_FULLTEXT);
+        $this->object->create($index, $fields);
+    }
+}
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/IndexStructureTest.php b/lib/internal/Magento/Framework/Indexer/Test/Unit/IndexStructureTest.php
similarity index 94%
rename from app/code/Magento/Indexer/Test/Unit/Model/IndexStructureTest.php
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/IndexStructureTest.php
index f29bee9349055fcb6744139c900ded7f0d12fbc1..2325db5c326f2a4f5d0ab720222485aa643935d9 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/IndexStructureTest.php
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/IndexStructureTest.php
@@ -4,7 +4,7 @@
  * See COPYING.txt for license details.
  */
 
-namespace Magento\Indexer\Test\Unit\Model;
+namespace Magento\Framework\Indexer\Test\Unit;
 
 use Magento\Framework\App\Resource;
 use Magento\Framework\DB\Adapter\AdapterInterface;
@@ -12,17 +12,17 @@ use Magento\Framework\DB\Ddl\Table;
 use \Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
 
 /**
- * Test for \Magento\Indexer\Model\IndexStructure
+ * Test for \Magento\Framework\Indexer\IndexStructure
  */
 class IndexStructureTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Indexer\Model\ScopeResolver\IndexScopeResolver|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver|\PHPUnit_Framework_MockObject_MockObject
      */
     private $indexScopeResolver;
 
     /**
-     * @var \Magento\Indexer\Model\ScopeResolver\FlatScopeResolver|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver|\PHPUnit_Framework_MockObject_MockObject
      */
     private $flatScopeResolver;
 
@@ -37,7 +37,7 @@ class IndexStructureTest extends \PHPUnit_Framework_TestCase
     private $connectionInterface;
 
     /**
-     * @var \Magento\Indexer\Model\IndexStructure
+     * @var \Magento\Framework\Indexer\IndexStructure
      */
     private $target;
 
@@ -53,11 +53,11 @@ class IndexStructureTest extends \PHPUnit_Framework_TestCase
         $this->resource->expects($this->atLeastOnce())
             ->method('getConnection')
             ->willReturn($this->connectionInterface);
-        $this->indexScopeResolver = $this->getMockBuilder('\Magento\Indexer\Model\ScopeResolver\IndexScopeResolver')
+        $this->indexScopeResolver = $this->getMockBuilder('\Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver')
             ->setMethods(['resolve'])
             ->disableOriginalConstructor()
             ->getMock();
-        $this->flatScopeResolver = $this->getMockBuilder('\Magento\Indexer\Model\ScopeResolver\FlatScopeResolver')
+        $this->flatScopeResolver = $this->getMockBuilder('\Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver')
             ->setMethods(['resolve'])
             ->disableOriginalConstructor()
             ->getMock();
@@ -65,7 +65,7 @@ class IndexStructureTest extends \PHPUnit_Framework_TestCase
         $objectManager = new ObjectManager($this);
 
         $this->target = $objectManager->getObject(
-            '\Magento\Indexer\Model\IndexStructure',
+            '\Magento\Framework\Indexer\IndexStructure',
             [
                 'resource' => $this->resource,
                 'indexScopeResolver' => $this->indexScopeResolver,
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/IndexerRegistryTest.php b/lib/internal/Magento/Framework/Indexer/Test/Unit/IndexerRegistryTest.php
similarity index 76%
rename from app/code/Magento/Indexer/Test/Unit/Model/IndexerRegistryTest.php
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/IndexerRegistryTest.php
index 5d2c8c278b75a34c56b2bc6dddb9681101326e63..f9794eae4b46754b613fc0de4cfe1b6081db1563 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/IndexerRegistryTest.php
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/IndexerRegistryTest.php
@@ -3,23 +3,23 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Test\Unit\Model;
+namespace Magento\Framework\Indexer\Test\Unit;
 
 class IndexerRegistryTest extends \PHPUnit_Framework_TestCase
 {
     public function testGetCreatesIndexerInstancesAndReusesExistingOnes()
     {
-        $firstIndexer = $this->getMock('Magento\Indexer\Model\IndexerInterface');
+        $firstIndexer = $this->getMock('Magento\Framework\Indexer\IndexerInterface');
         $firstIndexer->expects($this->once())->method('load')->with('first-indexer')->willReturnSelf();
 
-        $secondIndexer = $this->getMock('Magento\Indexer\Model\IndexerInterface');
+        $secondIndexer = $this->getMock('Magento\Framework\Indexer\IndexerInterface');
         $secondIndexer->expects($this->once())->method('load')->with('second-indexer')->willReturnSelf();
 
         $objectManager = $this->getMock('Magento\Framework\ObjectManagerInterface');
         $objectManager->expects($this->at(0))->method('create')->willReturn($firstIndexer);
         $objectManager->expects($this->at(1))->method('create')->willReturn($secondIndexer);
 
-        $unit = new \Magento\Indexer\Model\IndexerRegistry($objectManager);
+        $unit = new \Magento\Framework\Indexer\IndexerRegistry($objectManager);
         $this->assertSame($firstIndexer, $unit->get('first-indexer'));
         $this->assertSame($secondIndexer, $unit->get('second-indexer'));
         $this->assertSame($firstIndexer, $unit->get('first-indexer'));
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/ScopeResolver/IndexScopeResolverTest.php b/lib/internal/Magento/Framework/Indexer/Test/Unit/ScopeResolver/IndexScopeResolverTest.php
similarity index 93%
rename from app/code/Magento/Indexer/Test/Unit/Model/ScopeResolver/IndexScopeResolverTest.php
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/ScopeResolver/IndexScopeResolverTest.php
index a64005d658ebac18cc46d6cdaf3f1b300c44c54e..b34a4e1bd47f7518da898af536ca75fbdcad51f6 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/ScopeResolver/IndexScopeResolverTest.php
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/ScopeResolver/IndexScopeResolverTest.php
@@ -4,13 +4,13 @@
  * See COPYING.txt for license details.
  */
 
-namespace Magento\Indexer\Test\Unit\Model\ScopeResolver;
+namespace Magento\Framework\Indexer\Test\Unit\ScopeResolver;
 
 use Magento\Framework\Search\Request\Dimension;
 use \Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
 
 /**
- * Test for \Magento\Indexer\Model\ScopeResolver\IndexScopeResolver
+ * Test for \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver
  */
 class IndexScopeResolverTest extends \PHPUnit_Framework_TestCase
 {
@@ -25,7 +25,7 @@ class IndexScopeResolverTest extends \PHPUnit_Framework_TestCase
     private $resource;
 
     /**
-     * @var \Magento\Indexer\Model\ScopeResolver\IndexScopeResolver
+     * @var \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver
      */
     private $target;
 
@@ -45,7 +45,7 @@ class IndexScopeResolverTest extends \PHPUnit_Framework_TestCase
         $objectManager = new ObjectManager($this);
 
         $this->target = $objectManager->getObject(
-            '\Magento\Indexer\Model\ScopeResolver\IndexScopeResolver',
+            '\Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver',
             [
                 'resource' => $this->resource,
                 'scopeResolver' => $this->scopeResolver
diff --git a/app/code/Magento/Indexer/Test/Unit/Model/Indexer/Table/StrategyTest.php b/lib/internal/Magento/Framework/Indexer/Test/Unit/StrategyTest.php
similarity index 92%
rename from app/code/Magento/Indexer/Test/Unit/Model/Indexer/Table/StrategyTest.php
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/StrategyTest.php
index 6aed194580dc6f9168d2f9bde635f315180daafe..fd4f9a1da1300d135f681edd4e766669e35b86d0 100644
--- a/app/code/Magento/Indexer/Test/Unit/Model/Indexer/Table/StrategyTest.php
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/StrategyTest.php
@@ -3,7 +3,7 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Test\Unit\Model\Indexer\Table;
+namespace Magento\Framework\Indexer\Test\Unit;
 
 /**
  * Class StrategyTest
@@ -14,7 +14,7 @@ class StrategyTest extends \PHPUnit_Framework_TestCase
     /**
      * Strategy object
      *
-     * @var \Magento\Indexer\Model\Indexer\Table\Strategy
+     * @var \Magento\Framework\Indexer\Table\Strategy
      */
     protected $_model;
 
@@ -37,7 +37,7 @@ class StrategyTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->_model = new \Magento\Indexer\Model\Indexer\Table\Strategy(
+        $this->_model = new \Magento\Framework\Indexer\Table\Strategy(
             $this->_resourceMock
         );
     }
diff --git a/app/code/Magento/Indexer/Test/Unit/XsdTest.php b/lib/internal/Magento/Framework/Indexer/Test/Unit/XsdTest.php
similarity index 86%
rename from app/code/Magento/Indexer/Test/Unit/XsdTest.php
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/XsdTest.php
index a72ab7f201444ff7d178d69f4477378a6e166a4c..8f94183c530f790c372e85b9dd319d9a45c3acb6 100644
--- a/app/code/Magento/Indexer/Test/Unit/XsdTest.php
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/XsdTest.php
@@ -3,7 +3,7 @@
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Indexer\Test\Unit;
+namespace Magento\Framework\Indexer\Test\Unit;
 
 class XsdTest extends \PHPUnit_Framework_TestCase
 {
@@ -20,7 +20,7 @@ class XsdTest extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
-        $this->_xsdSchema = BP . '/app/code/Magento/Indexer/etc/indexer.xsd';
+        $this->_xsdSchema = BP . '/lib/internal/Magento/Framework/Indexer/etc/indexer.xsd';
         $this->_xsdValidator = new \Magento\Framework\TestFramework\Unit\Utility\XsdValidator();
     }
 
@@ -32,7 +32,7 @@ class XsdTest extends \PHPUnit_Framework_TestCase
     public function testSchemaCorrectlyIdentifiesInvalidXml($xmlString, $expectedError)
     {
         $actualError = $this->_xsdValidator->validate(
-            BP . '/app/code/Magento/Indexer/etc/indexer_merged.xsd',
+            BP . '/lib/internal/Magento/Framework/Indexer/etc/indexer_merged.xsd',
             $xmlString
         );
         $this->assertEquals($expectedError, $actualError);
diff --git a/app/code/Magento/Indexer/Test/Unit/_files/indexer_config.php b/lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_config.php
similarity index 100%
rename from app/code/Magento/Indexer/Test/Unit/_files/indexer_config.php
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_config.php
diff --git a/app/code/Magento/Indexer/Test/Unit/_files/indexer_merged_one.xml b/lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_merged_one.xml
similarity index 91%
rename from app/code/Magento/Indexer/Test/Unit/_files/indexer_merged_one.xml
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_merged_one.xml
index cd39a7d6866c2f5c322baf9f74e09d68b3d8bb75..d886f7bfb04f944c24409ad8dcbc202e5dd27c0a 100644
--- a/app/code/Magento/Indexer/Test/Unit/_files/indexer_merged_one.xml
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_merged_one.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../app/code/Magento/Indexer/etc/indexer.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../etc/indexer.xsd">
     <indexer id="indexer_internal_name_one" view_id="view_one" class="Index\Class\Name\One">
         <title translate="true">Indexer public name one</title>
         <description translate="true">Indexer public description one</description>
diff --git a/app/code/Magento/Indexer/Test/Unit/_files/indexer_merged_two.xml b/lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_merged_two.xml
similarity index 88%
rename from app/code/Magento/Indexer/Test/Unit/_files/indexer_merged_two.xml
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_merged_two.xml
index a5061cce1c00ff3794232ca9d2f26c1b1924109d..546d8a46627c3e19aa1a241554743ab6fbe7b3b8 100644
--- a/app/code/Magento/Indexer/Test/Unit/_files/indexer_merged_two.xml
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_merged_two.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../app/code/Magento/Indexer/etc/indexer.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../etc/indexer.xsd">
     <indexer id="indexer_internal_name_one" view_id="view_two" class="Index\Class\Name\Two">
         <title translate="true">Indexer public name two</title>
         <description translate="true">Indexer public description two</description>
diff --git a/app/code/Magento/Indexer/Test/Unit/_files/indexer_one.xml b/lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_one.xml
similarity index 83%
rename from app/code/Magento/Indexer/Test/Unit/_files/indexer_one.xml
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_one.xml
index 734fe4b11352de9eef59ea31d198d4b585013e90..eff97c9480a84c27202a38ce15efdd67f32a770d 100644
--- a/app/code/Magento/Indexer/Test/Unit/_files/indexer_one.xml
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_one.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../app/code/Magento/Indexer/etc/indexer.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../etc/indexer.xsd">
     <indexer id="indexer_internal_name_one" view_id="view_one" class="Index\Class\Name\One">
         <title translate="true">Indexer public name one</title>
         <description translate="true">Indexer public description one</description>
diff --git a/app/code/Magento/Indexer/Test/Unit/_files/indexer_three.xml b/lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_three.xml
similarity index 88%
rename from app/code/Magento/Indexer/Test/Unit/_files/indexer_three.xml
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_three.xml
index a5061cce1c00ff3794232ca9d2f26c1b1924109d..546d8a46627c3e19aa1a241554743ab6fbe7b3b8 100644
--- a/app/code/Magento/Indexer/Test/Unit/_files/indexer_three.xml
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_three.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../app/code/Magento/Indexer/etc/indexer.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../etc/indexer.xsd">
     <indexer id="indexer_internal_name_one" view_id="view_two" class="Index\Class\Name\Two">
         <title translate="true">Indexer public name two</title>
         <description translate="true">Indexer public description two</description>
diff --git a/app/code/Magento/Indexer/Test/Unit/_files/indexer_two.xml b/lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_two.xml
similarity index 88%
rename from app/code/Magento/Indexer/Test/Unit/_files/indexer_two.xml
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_two.xml
index 879b5bc8d0d11c8cb9cf71381173f5c193c2d510..80e8743d1a23ef149a4d880041f68624ecc9c96a 100644
--- a/app/code/Magento/Indexer/Test/Unit/_files/indexer_two.xml
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/_files/indexer_two.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../app/code/Magento/Indexer/etc/indexer.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../etc/indexer.xsd">
     <indexer id="indexer_internal_name_two" view_id="view_two" class="Index\Class\Name\Two">
         <title translate="true">Indexer public name two</title>
         <description translate="true">Indexer public description two</description>
diff --git a/app/code/Magento/Indexer/Test/Unit/_files/invalidIndexerXmlArray.php b/lib/internal/Magento/Framework/Indexer/Test/Unit/_files/invalidIndexerXmlArray.php
similarity index 100%
rename from app/code/Magento/Indexer/Test/Unit/_files/invalidIndexerXmlArray.php
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/_files/invalidIndexerXmlArray.php
diff --git a/app/code/Magento/Indexer/Test/Unit/_files/valid_indexer.xml b/lib/internal/Magento/Framework/Indexer/Test/Unit/_files/valid_indexer.xml
similarity index 88%
rename from app/code/Magento/Indexer/Test/Unit/_files/valid_indexer.xml
rename to lib/internal/Magento/Framework/Indexer/Test/Unit/_files/valid_indexer.xml
index 135e59783b6a01b17cd6bbfce7c87ba2d5482cfa..904ba16ef833fbacdc8c1208ab4a40154263225b 100644
--- a/app/code/Magento/Indexer/Test/Unit/_files/valid_indexer.xml
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/_files/valid_indexer.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../app/code/Magento/Indexer/etc/indexer.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../etc/indexer.xsd">
     <indexer id="indexer_internal_name" view_id="view01" class="Index\Class\Name">
         <title translate="true">Indexer public name</title>
         <description translate="true">Indexer public description</description>
diff --git a/app/code/Magento/Indexer/etc/indexer.xsd b/lib/internal/Magento/Framework/Indexer/etc/indexer.xsd
similarity index 92%
rename from app/code/Magento/Indexer/etc/indexer.xsd
rename to lib/internal/Magento/Framework/Indexer/etc/indexer.xsd
index 05dcaca0008a3b9310e4b16896d52435a08345f0..fa6e0f7afd4ebfe51fdea9c5d85e945be1bb5a95 100644
--- a/app/code/Magento/Indexer/etc/indexer.xsd
+++ b/lib/internal/Magento/Framework/Indexer/etc/indexer.xsd
@@ -27,7 +27,17 @@
 
     <xs:group name="fieldset">
         <xs:choice>
-            <xs:element name="fieldset" type="fieldsetType"/>
+            <xs:element name="fieldset" type="fieldsetType">
+                <xs:unique name="uniqueField">
+                    <xs:annotation>
+                        <xs:documentation>
+                            Field name must be unique in one fieldset.
+                        </xs:documentation>
+                    </xs:annotation>
+                    <xs:selector xpath=".//fieldset/field"/>
+                    <xs:field xpath="@name"/>
+                </xs:unique>
+            </xs:element>
         </xs:choice>
     </xs:group>
 
@@ -187,6 +197,9 @@
             <xs:enumeration value="varchar" />
             <xs:enumeration value="text" />
             <xs:enumeration value="mediumtext" />
+            <xs:enumeration value="timestamp" />
+            <xs:enumeration value="datetime" />
+            <xs:enumeration value="date" />
         </xs:restriction>
     </xs:simpleType>
 
@@ -239,14 +252,5 @@
             <xs:selector xpath=".//fieldset"/>
             <xs:field xpath="@name"/>
         </xs:unique>
-        <xs:unique name="uniqueField">
-            <xs:annotation>
-                <xs:documentation>
-                    Field name must be unique in one fieldset.
-                </xs:documentation>
-            </xs:annotation>
-            <xs:selector xpath=".//fieldset/field"/>
-            <xs:field xpath="@name"/>
-        </xs:unique>
     </xs:element>
 </xs:schema>
diff --git a/app/code/Magento/Indexer/etc/indexer_merged.xsd b/lib/internal/Magento/Framework/Indexer/etc/indexer_merged.xsd
similarity index 97%
rename from app/code/Magento/Indexer/etc/indexer_merged.xsd
rename to lib/internal/Magento/Framework/Indexer/etc/indexer_merged.xsd
index 385a07c884cdae5b5558ded2a36154c0fd4550da..fb60fd6d096e21b417b7c4183e2d110d4499783c 100644
--- a/app/code/Magento/Indexer/etc/indexer_merged.xsd
+++ b/lib/internal/Magento/Framework/Indexer/etc/indexer_merged.xsd
@@ -122,9 +122,9 @@
                 Fieldset of field declaration.
             </xs:documentation>
         </xs:annotation>
-        <xs:sequence>
+        <xs:sequence minOccurs="0">
             <xs:element type="referenceType" name="reference" minOccurs="0" maxOccurs="unbounded" />
-            <xs:element name="field" type="fieldType" minOccurs="1" maxOccurs="unbounded"/>
+            <xs:element name="field" type="fieldType" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
         <xs:attribute name="source" type="classType" use="required"/>
         <xs:attribute name="provider" type="classType" use="optional"/>
@@ -187,6 +187,9 @@
             <xs:enumeration value="varchar" />
             <xs:enumeration value="text" />
             <xs:enumeration value="mediumtext" />
+            <xs:enumeration value="timestamp" />
+            <xs:enumeration value="datetime" />
+            <xs:enumeration value="date" />
         </xs:restriction>
     </xs:simpleType>
 
diff --git a/lib/internal/Magento/Framework/Mview/etc/mview.xsd b/lib/internal/Magento/Framework/Mview/etc/mview.xsd
index e96024d92f2b7f53c160ab0a417a87f7022a2d97..320a57a0af46e2551077f08d2f73c5ebea308c0a 100644
--- a/lib/internal/Magento/Framework/Mview/etc/mview.xsd
+++ b/lib/internal/Magento/Framework/Mview/etc/mview.xsd
@@ -30,7 +30,7 @@
             </xs:documentation>
         </xs:annotation>
         <xs:sequence>
-            <xs:element name="subscriptions" type="subscriptionsType">
+            <xs:element minOccurs="0" name="subscriptions" type="subscriptionsType">
                 <xs:unique name="uniqueSubscriptionsTable">
                     <xs:annotation>
                         <xs:documentation>
diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php
index 847206787efe46acd1bf54a7b4d281eea6361cab..c05969298ef80b265378b8e48f69dfaea6a1cd32 100644
--- a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php
+++ b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php
@@ -15,7 +15,6 @@ use Magento\Framework\Api\Filter;
  */
 class FulltextFilter implements FilterApplierInterface
 {
-
     /**
      * Returns list of columns from fulltext index (doesn't support more then one FTI per table)
      *
diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/SearchResult.php b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/SearchResult.php
index 9fa1308c4acbb58b7adbeaa49d3caddbd0610f9d..48f6384aa21170feedb9ae0ac891cb0a11ef48a4 100644
--- a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/SearchResult.php
+++ b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/SearchResult.php
@@ -93,6 +93,7 @@ class SearchResult extends AbstractCollection implements Api\Search\SearchResult
     /**
      * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria
      * @return $this
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function setSearchCriteria(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria)
     {
diff --git a/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php
index 2c1888d848eabefe9a7c015ac908736ef4241ed9..f7267a3cb002a3c48f267ea3a7c4333bd67d5aa5 100755
--- a/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php
+++ b/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php
@@ -144,7 +144,7 @@ class UiComponentFactory extends DataObject
                 $identifier,
                 $bundleComponents[$identifier]
             );
-            $componentArguments = array_merge($componentArguments, $arguments);
+            $componentArguments = array_replace_recursive($componentArguments, $arguments);
             if (!isset($componentArguments['context'])) {
                 $componentArguments['context'] = $this->contextFactory->create([
                     'namespace' => $identifier
@@ -164,7 +164,10 @@ class UiComponentFactory extends DataObject
             $componentArguments['components'] = $components;
 
             /** @var \Magento\Framework\View\Element\UiComponentInterface $component */
-            $component = $this->objectManager->create($className, array_merge($componentArguments, $arguments));
+            $component = $this->objectManager->create(
+                $className,
+                array_replace_recursive($componentArguments, $arguments)
+            );
 
             return $component;
         } else {
diff --git a/setup/src/Magento/Setup/Console/Command/GenerateFixturesCommand.php b/setup/src/Magento/Setup/Console/Command/GenerateFixturesCommand.php
index e61ca8a3c7df09a9115bd62bfb10d17158cd1f56..83efcb06b178dea211de890e7f6c00ae28a12023 100644
--- a/setup/src/Magento/Setup/Console/Command/GenerateFixturesCommand.php
+++ b/setup/src/Magento/Setup/Console/Command/GenerateFixturesCommand.php
@@ -84,8 +84,8 @@ class GenerateFixturesCommand extends Command
             /** @var $config \Magento\Indexer\Model\Config */
             $config = $fixtureModel->getObjectManager()->get('Magento\Indexer\Model\Config');
             $indexerListIds = $config->getIndexers();
-            /** @var $indexerRegistry \Magento\Indexer\Model\IndexerRegistry */
-            $indexerRegistry = $fixtureModel->getObjectManager()->create('Magento\Indexer\Model\IndexerRegistry');
+            /** @var $indexerRegistry \Magento\Framework\Indexer\IndexerRegistry */
+            $indexerRegistry = $fixtureModel->getObjectManager()->create('Magento\Framework\Indexer\IndexerRegistry');
             $indexersState = [];
             foreach ($indexerListIds as $indexerId) {
                 $indexer = $indexerRegistry->get($indexerId['indexer_id']);
diff --git a/setup/src/Magento/Setup/Module/Di/Code/Reader/Type.php b/setup/src/Magento/Setup/Module/Di/Code/Reader/Type.php
index a2ea1d3bf1df1e2979b3b3d83b7a2d1614e31f18..f4dfb16ad65da01bcf2dd48d4b2864c5373cd6d8 100644
--- a/setup/src/Magento/Setup/Module/Di/Code/Reader/Type.php
+++ b/setup/src/Magento/Setup/Module/Di/Code/Reader/Type.php
@@ -17,7 +17,11 @@ class Type
      */
     public function isConcrete($type)
     {
-        $instance = new \ReflectionClass($type);
+        try {
+            $instance = new \ReflectionClass($type);
+        } catch (\ReflectionException $e) {
+            return false;
+        }
         return !$instance->isAbstract() && !$instance->isInterface();
     }
 }