Interface & Factory implementation for VPD Parsers

This commit abstracts the implementation logic of different parser.
A parser factory is implemented to provide instance of required
parser based on the type of vpd file needed to be parsed.

The interface should be derived to implement any further parser logic
related to vpd.

Status: This does not add any new function, so basic testing of
VPD parsing, VPD tool and writes was performed.

Signed-off-by: Sunny Srivastava <sunnsr25@in.ibm.com>
Change-Id: I3ce1a2d6b7e8d8984fd7800132e78ab8a9a21e56
diff --git a/app.cpp b/app.cpp
index 948decd..dbdda96 100644
--- a/app.cpp
+++ b/app.cpp
@@ -1,6 +1,6 @@
 #include "args.hpp"
 #include "defines.hpp"
-#include "parser.hpp"
+#include "ipz_parser.hpp"
 #include "write.hpp"
 
 #include <exception>
@@ -8,6 +8,7 @@
 #include <iostream>
 #include <iterator>
 #include <string>
+#include <variant>
 #include <vector>
 
 int main(int argc, char** argv)
@@ -17,6 +18,8 @@
     try
     {
         using namespace openpower::vpd;
+        using namespace openpower::vpd::ipz::parser;
+
         args::Args arguments = args::parse(argc, argv);
 
         bool haveVpd = arguments.count("vpd");
@@ -45,7 +48,8 @@
                    std::istreambuf_iterator<char>());
 
         // Parse VPD
-        auto vpdStore = parse(std::move(vpd));
+        IpzVpdParser ipzParser(std::move(vpd));
+        auto vpdStore = std::move(std::get<Store>(ipzParser.parse()));
 
         if (doDump)
         {
diff --git a/const.hpp b/const.hpp
index 591043e..ac8dafe 100644
--- a/const.hpp
+++ b/const.hpp
@@ -66,6 +66,9 @@
 using namespace std::string_literals;
 constexpr auto pimPath = "/xyz/openbmc_project/inventory";
 constexpr auto pimIntf = "xyz.openbmc_project.Inventory.Manager";
+constexpr auto kwdVpdInf = "com.ibm.ipzvpd.VINI";
+constexpr auto memVpdInf = "com.ibm.ipzvpd.VINI";
+constexpr auto ipzVpdInf = "com.ibm.ipzvpd.";
 
 namespace lengths
 {
diff --git a/ibm_vpd_app.cpp b/ibm_vpd_app.cpp
index b265919..25b77f1 100644
--- a/ibm_vpd_app.cpp
+++ b/ibm_vpd_app.cpp
@@ -1,9 +1,10 @@
 #include "config.h"
 
 #include "defines.hpp"
+#include "ipz_parser.hpp"
 #include "keyword_vpd_parser.hpp"
 #include "memory_vpd_parser.hpp"
-#include "parser.hpp"
+#include "parser_factory.hpp"
 #include "utils.hpp"
 
 #include <ctype.h>
@@ -24,8 +25,10 @@
 using namespace openpower::vpd::constants;
 namespace fs = filesystem;
 using json = nlohmann::json;
+using namespace openpower::vpd::parser::factory;
 using namespace openpower::vpd::inventory;
 using namespace openpower::vpd::memory::parser;
+using namespace openpower::vpd::parser::interface;
 
 /**
  * @brief Expands location codes
@@ -309,13 +312,13 @@
  */
 template <typename T>
 static void populateDbus(const T& vpdMap, nlohmann::json& js,
-                         const string& filePath, const string& preIntrStr)
+                         const string& filePath) //, const string &preIntrStr) {
 {
     inventory::InterfaceMap interfaces;
     inventory::ObjectMap objects;
     inventory::PropertyMap prop;
 
-    bool isSystemVpd;
+    bool isSystemVpd = false;
     for (const auto& item : js["frus"][filePath])
     {
         const auto& objectPath = item["inventoryPath"];
@@ -334,12 +337,12 @@
                 for (const auto& record : vpdMap)
                 {
                     populateFruSpecificInterfaces(
-                        record.second, preIntrStr + record.first, interfaces);
+                        record.second, ipzVpdInf + record.first, interfaces);
                 }
             }
             else if constexpr (is_same<T, KeywordVpdMap>::value)
             {
-                populateFruSpecificInterfaces(vpdMap, preIntrStr, interfaces);
+                populateFruSpecificInterfaces(vpdMap, kwdVpdInf, interfaces);
             }
             if (js.find("commonInterfaces") != js.end())
             {
@@ -360,7 +363,7 @@
                         if (vpdMap.find(recordName) != vpdMap.end())
                         {
                             populateFruSpecificInterfaces(
-                                vpdMap.at(recordName), preIntrStr + recordName,
+                                vpdMap.at(recordName), ipzVpdInf + recordName,
                                 interfaces);
                         }
                     }
@@ -464,48 +467,25 @@
             return 0;
         }
 
-        Binary vpdVector(getVpdDataInVector(js, file));
-        vpdType type = vpdTypeCheck(vpdVector);
+        Binary vpdVector = getVpdDataInVector(js, file);
 
-        switch (type)
+        ParserInterface* parser =
+            ParserFactory::getParser(std::move(vpdVector));
+
+        variant<KeywordVpdMap, Store> parseResult;
+        parseResult = parser->parse();
+
+        if (auto pVal = get_if<Store>(&parseResult))
         {
-            case IPZ_VPD:
-            {
-                // Invoking IPZ Vpd Parser
-                auto vpdStore = parse(move(vpdVector));
-                const Parsed& vpdMap = vpdStore.getVpdMap();
-                string preIntrStr = "com.ibm.ipzvpd.";
-                // Write it to the inventory
-                populateDbus(vpdMap, js, file, preIntrStr);
-            }
-            break;
-
-            case KEYWORD_VPD:
-            {
-                // Creating Keyword Vpd Parser Object
-                KeywordVpdParser parserObj(move(vpdVector));
-                // Invoking KW Vpd Parser
-                const auto& kwValMap = parserObj.parseKwVpd();
-                string preIntrStr = "com.ibm.ipzvpd.VINI";
-                populateDbus(kwValMap, js, file, preIntrStr);
-            }
-            break;
-
-            case MEMORY_VPD:
-            {
-                // Get an object to call API & get the key-value map
-                memoryVpdParser vpdParser(move(vpdVector));
-                const auto& memKwValMap = vpdParser.parseMemVpd();
-
-                string preIntrStr = "com.ibm.kwvpd.KWVPD";
-                // js(define dimm sys path in js), ObjPath(define in JS)
-                populateDbus(memKwValMap, js, file, preIntrStr);
-            }
-            break;
-
-            default:
-                throw runtime_error("Invalid VPD format");
+            populateDbus(pVal->getVpdMap(), js, file);
         }
+        else if (auto pVal = get_if<KeywordVpdMap>(&parseResult))
+        {
+            populateDbus(*pVal, js, file);
+        }
+
+        // release the parser object
+        ParserFactory::freeParser(parser);
     }
     catch (exception& e)
     {
diff --git a/memory_vpd_parser.hpp b/memory_vpd_parser.hpp
deleted file mode 100644
index 18f4519..0000000
--- a/memory_vpd_parser.hpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#pragma once
-
-#include "impl.hpp"
-#include "types.hpp"
-
-namespace openpower
-{
-namespace vpd
-{
-namespace memory
-{
-namespace parser
-{
-
-class memoryVpdParser
-{
-  public:
-    /**
-     * @brief Move Constructor
-     *
-     * Move kwVpdVector to parser object's kwVpdVector
-     */
-    memoryVpdParser(Binary&& memVpdVector) : memVpd(std::move(memVpdVector))
-    {
-    }
-
-    /**
-     * @brief Destructor
-     *
-     * Delete the parser object
-     */
-    ~memoryVpdParser(){};
-
-    /**
-     * @brief Parse the memory VPD binary data.
-     *
-     * Collects and emplace the keyword-value pairs in map.
-     *
-     * @return map of keyword:value
-     */
-    inventory::KeywordVpdMap parseMemVpd();
-
-  private:
-    /**
-     */
-    inventory::KeywordVpdMap readKeywords(Binary::const_iterator iterator);
-
-    /**
-     */
-    Binary memVpd;
-};
-} // namespace parser
-} // namespace memory
-} // namespace vpd
-} // namespace openpower
\ No newline at end of file
diff --git a/meson.build b/meson.build
index affd99f..f430baf 100644
--- a/meson.build
+++ b/meson.build
@@ -41,13 +41,14 @@
 
 if get_option('ibm-parser').enabled()
         ibm_read_vpd_SOURCES = ['ibm_vpd_app.cpp',
-                                'parser.cpp',
+                                'vpd-parser/ipz_parser.cpp',
                                 'impl.cpp',
                                 'utils.cpp',
-                                'keyword_vpd_parser.cpp',
+                                'vpd-parser/keyword_vpd_parser.cpp',
                                 'vpdecc/vpdecc.c',
                                 'vpdecc/vpdecc_support.c',
-                                'memory_vpd_parser.cpp'
+                                'vpd-parser/memory_vpd_parser.cpp',
+                                'vpd-parser/parser_factory.cpp'
                                ]
 
         ibm_vpd_exe = executable(
@@ -57,6 +58,7 @@
                                         sdbusplus,
                                         phosphor_logging,
                                 ],
+                                include_directories : 'vpd-parser/',
                                 install: true,
                                 cpp_args : '-DIPZ_PARSER'
                             )
@@ -119,7 +121,7 @@
         openpower_read_vpd_SOURCES = ['app.cpp',
                                       'args.cpp',
                                       'impl.cpp',
-                                      'parser.cpp',
+                                      'vpd-parser/ipz_parser.cpp',
                                       'write.cpp',
                                       'utils.cpp',
                                       writefru_hpp,
@@ -133,6 +135,7 @@
                         sdbusplus,
                         phosphor_logging,
                 ],
+                include_directories : 'vpd-parser/',
                 install: true,
         )
 endif
diff --git a/parser.cpp b/parser.cpp
deleted file mode 100644
index 2b8da60..0000000
--- a/parser.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "parser.hpp"
-
-#include "impl.hpp"
-
-namespace openpower
-{
-namespace vpd
-{
-
-Store parse(Binary&& vpd)
-{
-    parser::Impl p(std::move(vpd));
-    Store s = p.run();
-    return s;
-}
-
-namespace keyword
-{
-namespace editor
-{
-
-void processHeader(Binary&& vpd)
-{
-    parser::Impl p(std::move(vpd));
-    p.checkVPDHeader();
-}
-
-} // namespace editor
-} // namespace keyword
-
-} // namespace vpd
-} // namespace openpower
diff --git a/parser.hpp b/parser.hpp
deleted file mode 100644
index 1379f90..0000000
--- a/parser.hpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#pragma once
-
-#include "const.hpp"
-#include "store.hpp"
-
-#include <vector>
-
-namespace openpower
-{
-namespace vpd
-{
-
-/** @brief API to parse VPD
- *
- *  @param [in] vpd - VPD in binary format
- *  @returns A Store object, which provides access to
- *           the parsed VPD.
- */
-Store parse(Binary&& vpd);
-
-namespace keyword
-{
-namespace editor
-{
-using namespace openpower::vpd::constants;
-/** @brief API to check vpd header
- *  @param [in] vpd - VPDheader in binary format
- */
-void processHeader(Binary&& vpd);
-
-} // namespace editor
-} // namespace keyword
-
-} // namespace vpd
-} // namespace openpower
diff --git a/test/ipz_parser/parser.cpp b/test/ipz_parser/parser.cpp
index 40c60e9..c9ec93b 100644
--- a/test/ipz_parser/parser.cpp
+++ b/test/ipz_parser/parser.cpp
@@ -1,9 +1,10 @@
+#include "ipz_parser.hpp"
+
 #include <cassert>
 #include <defines.hpp>
 #include <fstream>
 #include <impl.hpp>
 #include <iterator>
-#include <parser.hpp>
 #include <store.hpp>
 
 #include <gtest/gtest.h>
diff --git a/test/keyword_vpd_parser_test/kw_vpd_test.cpp b/test/keyword_vpd_parser_test/kw_vpd_test.cpp
index 115d60a..48c3961 100644
--- a/test/keyword_vpd_parser_test/kw_vpd_test.cpp
+++ b/test/keyword_vpd_parser_test/kw_vpd_test.cpp
@@ -1,4 +1,5 @@
 #include "keyword_vpd_parser.hpp"
+#include "store.hpp"
 #include "types.hpp"
 
 #include <exception>
@@ -9,6 +10,7 @@
 using namespace vpd::keyword::parser;
 using namespace openpower::vpd;
 using namespace openpower::vpd::inventory;
+using namespace std;
 
 class KeywordVpdParserTest : public ::testing::Test
 {
@@ -59,7 +61,7 @@
           0x34}},
         {"CC", {0x32, 0x44, 0x33, 0x37}}};
 
-    auto map2 = parserObj1.parseKwVpd();
+    auto map2 = std::move(get<KeywordVpdMap>(parserObj1.parse()));
     ASSERT_EQ(1, map1 == map2);
 
     // BONO TYPE VPD
@@ -81,7 +83,7 @@
             {"Z5", {0x30}},
             {"Z6", {0x41, 0x31, 0x38, 0x30, 0x30, 0x32, 0x30, 0x30}}};
 
-    map2 = parserObj2.parseKwVpd();
+    map2 = std::move(get<KeywordVpdMap>(parserObj2.parse()));
     ASSERT_EQ(1, map1 == map2);
 }
 
@@ -90,12 +92,12 @@
     // Invalid Large resource type Identifier String - corrupted at index[0]
     keywordVpdVector[0] = 0x83;
     KeywordVpdParser parserObj1(std::move(keywordVpdVector));
-    EXPECT_THROW(parserObj1.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj1.parse(), std::runtime_error);
 
     // For BONO type VPD
     bonoKwVpdVector[0] = 0x83;
     KeywordVpdParser parserObj2(std::move(bonoKwVpdVector));
-    EXPECT_THROW(parserObj2.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj2.parse(), std::runtime_error);
 }
 
 TEST_F(KeywordVpdParserTest, InvKwValTag)
@@ -103,12 +105,12 @@
     // Invalid Large resource type Vendor Defined - corrupted at index[19]
     keywordVpdVector[19] = 0x85;
     KeywordVpdParser parserObj1(std::move(keywordVpdVector));
-    EXPECT_THROW(parserObj1.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj1.parse(), std::runtime_error);
 
     // For BONO type VPD - corruputed at index[33]
     bonoKwVpdVector[33] = 0x91;
     KeywordVpdParser parserObj2(std::move(bonoKwVpdVector));
-    EXPECT_THROW(parserObj2.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj2.parse(), std::runtime_error);
 }
 
 TEST_F(KeywordVpdParserTest, InvKwValSize)
@@ -116,12 +118,12 @@
     // Badly formed keyword VPD data - corrupted at index[20]
     keywordVpdVector[20] = 0x00;
     KeywordVpdParser parserObj1(std::move(keywordVpdVector));
-    EXPECT_THROW(parserObj1.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj1.parse(), std::runtime_error);
 
     // For BONO type VPD - corruputed at index[34]
     bonoKwVpdVector[34] = 0x00;
     KeywordVpdParser parserObj2(std::move(bonoKwVpdVector));
-    EXPECT_THROW(parserObj2.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj2.parse(), std::runtime_error);
 }
 
 TEST_F(KeywordVpdParserTest, InvKwValEndTag)
@@ -129,7 +131,7 @@
     // Invalid Small resource type End - corrupted at index[177]
     keywordVpdVector[177] = 0x80;
     KeywordVpdParser parserObj1(std::move(keywordVpdVector));
-    EXPECT_THROW(parserObj1.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj1.parse(), std::runtime_error);
 }
 
 TEST_F(KeywordVpdParserTest, InvChecksum)
@@ -137,7 +139,7 @@
     // Invalid Check sum - corrupted at index[178]
     keywordVpdVector[178] = 0xb1;
     KeywordVpdParser parserObj1(std::move(keywordVpdVector));
-    EXPECT_THROW(parserObj1.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj1.parse(), std::runtime_error);
 }
 
 TEST_F(KeywordVpdParserTest, InvKwVpdEndTag)
@@ -145,12 +147,12 @@
     // Invalid Small resource type Last End Of Data - corrupted at index[179]
     keywordVpdVector[179] = 0x79;
     KeywordVpdParser parserObj1(std::move(keywordVpdVector));
-    EXPECT_THROW(parserObj1.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj1.parse(), std::runtime_error);
 
     // For BONO type VPD - corrupted at index[147]
     bonoKwVpdVector[147] = 0x79;
     KeywordVpdParser parserObj2(std::move(bonoKwVpdVector));
-    EXPECT_THROW(parserObj2.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj2.parse(), std::runtime_error);
 }
 
 TEST_F(KeywordVpdParserTest, OutOfBoundGreaterSize)
@@ -159,12 +161,12 @@
     // at index[24]
     keywordVpdVector[24] = 0x32;
     KeywordVpdParser parserObj1(std::move(keywordVpdVector));
-    EXPECT_THROW(parserObj1.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj1.parse(), std::runtime_error);
 
     // For BONO type VPD - corrupted at index[38]
     bonoKwVpdVector[38] = 0x4D;
     KeywordVpdParser parserObj2(std::move(bonoKwVpdVector));
-    EXPECT_THROW(parserObj2.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj2.parse(), std::runtime_error);
 }
 
 TEST_F(KeywordVpdParserTest, OutOfBoundLesserSize)
@@ -173,12 +175,12 @@
     // at index[24]
     keywordVpdVector[24] = 0x03;
     KeywordVpdParser parserObj1(std::move(keywordVpdVector));
-    EXPECT_THROW(parserObj1.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj1.parse(), std::runtime_error);
 
     // For BONO type VPD - corrupted at index[38]
     bonoKwVpdVector[38] = 0x04;
     KeywordVpdParser parserObj2(std::move(bonoKwVpdVector));
-    EXPECT_THROW(parserObj2.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj2.parse(), std::runtime_error);
 }
 
 TEST_F(KeywordVpdParserTest, BlankVpd)
@@ -186,12 +188,12 @@
     // Blank Kw Vpd
     keywordVpdVector.clear();
     KeywordVpdParser parserObj1(std::move(keywordVpdVector));
-    EXPECT_THROW(parserObj1.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj1.parse(), std::runtime_error);
 
     // Blank Bono Type Vpd
     bonoKwVpdVector.clear();
     KeywordVpdParser parserObj2(std::move(bonoKwVpdVector));
-    EXPECT_THROW(parserObj2.parseKwVpd(), std::runtime_error);
+    EXPECT_THROW(parserObj2.parse(), std::runtime_error);
 }
 
 int main(int argc, char** argv)
diff --git a/test/meson.build b/test/meson.build
index 3f144b9..97b5e1c 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -15,7 +15,7 @@
 gtest = dependency('gtest', main: true, disabler: true, required: build_tests)
 dependecy_list = [gtest, gmock, sdbusplus, phosphor_logging, phosphor_dbus_interfaces]
 
-configuration_inc = include_directories('..', '../vpd-manager', 'vpd-manager-test')
+configuration_inc = include_directories('..', '../vpd-manager', 'vpd-manager-test', '../vpd-parser')
 
 vpd_test = ['store/store.cpp',
             'ipz_parser/parser.cpp',
@@ -27,11 +27,13 @@
 application_src =['../impl.cpp',
                    '../vpdecc/vpdecc.c',
                    '../vpdecc/vpdecc_support.c',
-                   '../parser.cpp',
+                   '../vpd-parser/ipz_parser.cpp',
                    '../utils.cpp',
                    '../vpd-manager/reader_impl.cpp',
-                   '../keyword_vpd_parser.cpp',
-                   '../vpd-manager/editor_impl.cpp'
+                   '../vpd-parser/keyword_vpd_parser.cpp',
+                   '../vpd-manager/editor_impl.cpp',
+                   '../vpd-parser/parser_factory.cpp',
+                   '../vpd-parser/memory_vpd_parser.cpp'
                   ]
 
 foreach t : vpd_test
diff --git a/test/parser/parser.cpp b/test/parser/parser.cpp
index 139c4f2..57da82f 100644
--- a/test/parser/parser.cpp
+++ b/test/parser/parser.cpp
@@ -2,20 +2,21 @@
 #include <defines.hpp>
 #include <fstream>
 #include <iterator>
-#include <parser.hpp>
 #include <store.hpp>
+#include <vpd-parser/ipz_parser.hpp>
 
 void runTests()
 {
     using namespace openpower::vpd;
-
+    using namespace openpower::vpd::ipz::parser;
     // Test parse() API
     {
         std::ifstream vpdFile("test.vpd", std::ios::binary);
         Binary vpd((std::istreambuf_iterator<char>(vpdFile)),
                    std::istreambuf_iterator<char>());
 
-        auto vpdStore = parse(std::move(vpd));
+        IpzVpdParser ipzParser(std::move(vpd));
+        auto vpdStore = std::move(std::get<Store>(ipzParser.parse()));
 
         assert(("P012" == vpdStore.get<Record::VINI, record::Keyword::CC>()));
         assert(("2019-01-01-08:30:00" ==
diff --git a/test/vpd-manager-test/editor_test.cpp b/test/vpd-manager-test/editor_test.cpp
index c1e98b6..2f7114a 100644
--- a/test/vpd-manager-test/editor_test.cpp
+++ b/test/vpd-manager-test/editor_test.cpp
@@ -1,5 +1,5 @@
 #include "editor_impl.hpp"
-#include "parser.hpp"
+#include "ipz_parser.hpp"
 
 #include <algorithm>
 #include <nlohmann/json.hpp>
diff --git a/vpd-manager/editor_impl.cpp b/vpd-manager/editor_impl.cpp
index e5d698a..a20cd44 100644
--- a/vpd-manager/editor_impl.cpp
+++ b/vpd-manager/editor_impl.cpp
@@ -2,11 +2,17 @@
 
 #include "editor_impl.hpp"
 
-#include "parser.hpp"
+#include "ipz_parser.hpp"
+#include "parser_factory.hpp"
 #include "utils.hpp"
 
 #include "vpdecc/vpdecc.h"
 
+using namespace openpower::vpd::parser::interface;
+using namespace openpower::vpd::constants;
+using namespace openpower::vpd::parser::factory;
+using namespace openpower::vpd::ipz::parser;
+
 namespace openpower
 {
 namespace vpd
@@ -15,7 +21,6 @@
 {
 namespace editor
 {
-using namespace openpower::vpd::constants;
 
 void EditorImpl::checkPTForRecord(Binary::const_iterator& iterator,
                                   Byte ptLength)
@@ -95,7 +100,7 @@
 #else
 
     // update data in EEPROM as well. As we will not write complete file back
-    vpdFileStream.seekp(offset + thisRecord.kwDataOffset, std::ios::beg);
+    vpdFileStream.seekp(startOffset + thisRecord.kwDataOffset, std::ios::beg);
 
     iteratorToNewdata = kwdData.cbegin();
     std::copy(iteratorToNewdata, end,
@@ -187,7 +192,7 @@
     std::advance(end, thisRecord.recECCLength);
 
 #ifndef ManagerTest
-    vpdFileStream.seekp(offset + thisRecord.recECCoffset, std::ios::beg);
+    vpdFileStream.seekp(startOffset + thisRecord.recECCoffset, std::ios::beg);
     std::copy(itrToRecordECC, end,
               std::ostreambuf_iterator<char>(vpdFileStream));
 #endif
@@ -575,18 +580,17 @@
 
 void EditorImpl::updateKeyword(const Binary& kwdData)
 {
-    offset = 0;
+    startOffset = 0;
 #ifndef ManagerTest
 
     getVpdPathForCpu();
 
-    uint32_t offset = 0;
     // check if offset present?
     for (const auto& item : jsonFile["frus"][vpdFilePath])
     {
         if (item.find("offset") != item.end())
         {
-            offset = item["offset"];
+            startOffset = item["offset"];
         }
     }
 
@@ -596,7 +600,7 @@
     vpdFileStream.open(vpdFilePath,
                        std::ios::in | std::ios::out | std::ios::binary);
 
-    vpdFileStream.seekg(offset, ios_base::cur);
+    vpdFileStream.seekg(startOffset, ios_base::cur);
     vpdFileStream.read(reinterpret_cast<char*>(&completeVPDFile[0]), 65504);
     completeVPDFile.resize(vpdFileStream.gcount());
     vpdFileStream.clear(std::ios_base::eofbit);
@@ -618,24 +622,46 @@
     Byte vpdType = *iterator;
     if (vpdType == KW_VAL_PAIR_START_TAG)
     {
-        openpower::vpd::keyword::editor::processHeader(
-            std::move(completeVPDFile));
+        ParserInterface* Iparser =
+            ParserFactory::getParser(std::move(completeVPDFile));
+        IpzVpdParser* ipzParser = dynamic_cast<IpzVpdParser*>(Iparser);
 
-        // process VTOC for PTT rkwd
-        readVTOC();
+        try
+        {
+            if (ipzParser == nullptr)
+            {
+                throw std::runtime_error("Invalid cast");
+            }
 
-        // check record for keywrod
-        checkRecordForKwd();
+            ipzParser->processHeader();
+            delete ipzParser;
+            ipzParser = nullptr;
+            // ParserFactory::freeParser(Iparser);
 
-        // update the data to the file
-        updateData(kwdData);
+            // process VTOC for PTT rkwd
+            readVTOC();
 
-        // update the ECC data for the record once data has been updated
-        updateRecordECC();
+            // check record for keywrod
+            checkRecordForKwd();
+
+            // update the data to the file
+            updateData(kwdData);
+
+            // update the ECC data for the record once data has been updated
+            updateRecordECC();
 #ifndef ManagerTest
-        // update the cache once data has been updated
-        updateCache();
+            // update the cache once data has been updated
+            updateCache();
 #endif
+        }
+        catch (const std::exception& e)
+        {
+            if (ipzParser != nullptr)
+            {
+                delete ipzParser;
+            }
+            throw std::runtime_error(e.what());
+        }
         return;
     }
 }
diff --git a/vpd-manager/editor_impl.hpp b/vpd-manager/editor_impl.hpp
index d4d5598..9cf3b8a 100644
--- a/vpd-manager/editor_impl.hpp
+++ b/vpd-manager/editor_impl.hpp
@@ -47,7 +47,9 @@
     EditorImpl& operator=(const EditorImpl&) = delete;
     EditorImpl(EditorImpl&&) = delete;
     EditorImpl& operator=(EditorImpl&&) = delete;
-    ~EditorImpl() = default;
+    ~EditorImpl()
+    {
+    }
 
     /** @brief Construct EditorImpl class
      *
@@ -55,8 +57,8 @@
      */
     EditorImpl(const std::string& record, const std::string& kwd,
                Binary&& vpd) :
-        thisRecord(record, kwd),
-        vpdFile(std::move(vpd))
+        startOffset(0),
+        thisRecord(record, kwd), vpdFile(std::move(vpd))
     {
     }
 
@@ -68,7 +70,8 @@
                const std::string& record, const std::string& kwd,
                const sdbusplus::message::object_path& inventoryPath) :
         vpdFilePath(path),
-        objPath(inventoryPath), jsonFile(json), thisRecord(record, kwd)
+        objPath(inventoryPath), startOffset(0), jsonFile(json),
+        thisRecord(record, kwd)
     {
     }
 
@@ -161,7 +164,7 @@
     std::fstream vpdFileStream;
 
     // offset to get vpd data from EEPROM
-    uint32_t offset;
+    uint32_t startOffset;
 
     // file to store parsed json
     const nlohmann::json jsonFile;
diff --git a/vpd-manager/manager.cpp b/vpd-manager/manager.cpp
index 717a83a..a313e86 100644
--- a/vpd-manager/manager.cpp
+++ b/vpd-manager/manager.cpp
@@ -3,7 +3,7 @@
 #include "manager.hpp"
 
 #include "editor_impl.hpp"
-#include "parser.hpp"
+#include "ipz_parser.hpp"
 #include "reader_impl.hpp"
 #include "utils.hpp"
 
diff --git a/vpd-manager/meson.build b/vpd-manager/meson.build
index 7255dad..56b139e 100644
--- a/vpd-manager/meson.build
+++ b/vpd-manager/meson.build
@@ -1,21 +1,23 @@
-systemd = dependency('libsystemd', version : '>= 221')
+systemd = dependency('libsystemd', version: '>= 221')
 phosphor_dbus_interfaces = dependency('phosphor-dbus-interfaces')
 
-configuration_inc = include_directories('.', '../')
+configuration_inc = include_directories('.', '../', '../vpd-parser/')
 
-vpd_manager_SOURCES =[
-                        'manager_main.cpp',
-                        'manager.cpp',
-                        'server.cpp',
-                        'error.cpp',
-                        'editor_impl.cpp',
-                        'reader_impl.cpp',
-                        '../impl.cpp',
-                        '../parser.cpp',
-                        '../utils.cpp',
-                        '../vpdecc/vpdecc.c',
-                        '../vpdecc/vpdecc_support.c'
-                        ]
+vpd_manager_SOURCES =['manager_main.cpp',
+                      'manager.cpp',
+                      'server.cpp',
+                      'error.cpp',
+                      'editor_impl.cpp',
+                      'reader_impl.cpp',
+                      '../impl.cpp',
+                      '../vpd-parser/ipz_parser.cpp',
+                      '../utils.cpp',
+                      '../vpdecc/vpdecc.c',
+                      '../vpdecc/vpdecc_support.c',
+                      '../vpd-parser//keyword_vpd_parser.cpp',
+                      '../vpd-parser/memory_vpd_parser.cpp',
+                      '../vpd-parser/parser_factory.cpp'
+                     ]
 
 vpd_manager_dependencies =[sdbusplus,
                            phosphor_logging,
@@ -23,10 +25,12 @@
                            phosphor_dbus_interfaces,
                           ]
 
-vpd_manager_exe = executable('vpd-manager',
-                              vpd_manager_SOURCES,
-                              include_directories : configuration_inc,
-                              dependencies :[vpd_manager_dependencies,
-                                            ],
-                              install: true
-                            )
+vpd_manager_exe = executable(
+                 'vpd-manager',
+                 vpd_manager_SOURCES, 
+                 include_directories : configuration_inc,
+                 dependencies : [
+                                vpd_manager_dependencies,
+                                ],
+                 install : true
+                )
diff --git a/vpd-parser/ipz_parser.cpp b/vpd-parser/ipz_parser.cpp
new file mode 100644
index 0000000..5af3441
--- /dev/null
+++ b/vpd-parser/ipz_parser.cpp
@@ -0,0 +1,37 @@
+#include "ipz_parser.hpp"
+
+#include "impl.hpp"
+
+namespace openpower
+{
+namespace vpd
+{
+namespace ipz
+{
+namespace parser
+{
+using namespace openpower::vpd::parser;
+using namespace openpower::vpd::constants;
+
+std::variant<kwdVpdMap, Store> IpzVpdParser::parse()
+{
+    Impl p(std::move(vpd));
+    Store s = p.run();
+    return s;
+}
+
+void IpzVpdParser::processHeader()
+{
+    Impl p(std::move(vpd));
+    p.checkVPDHeader();
+}
+
+std::string IpzVpdParser::getInterfaceName() const
+{
+    return ipzVpdInf;
+}
+
+} // namespace parser
+} // namespace ipz
+} // namespace vpd
+} // namespace openpower
diff --git a/vpd-parser/ipz_parser.hpp b/vpd-parser/ipz_parser.hpp
new file mode 100644
index 0000000..cb8c489
--- /dev/null
+++ b/vpd-parser/ipz_parser.hpp
@@ -0,0 +1,67 @@
+#pragma once
+
+#include "const.hpp"
+#include "parser_interface.hpp"
+#include "store.hpp"
+#include "types.hpp"
+
+#include <vector>
+
+namespace openpower
+{
+namespace vpd
+{
+namespace ipz
+{
+namespace parser
+{
+
+using ParserInterface = openpower::vpd::parser::interface::ParserInterface;
+using kwdVpdMap = openpower::vpd::inventory::KeywordVpdMap;
+
+class IpzVpdParser : public ParserInterface
+{
+  public:
+    IpzVpdParser() = delete;
+    IpzVpdParser(const IpzVpdParser&) = delete;
+    IpzVpdParser& operator=(const IpzVpdParser&) = delete;
+    IpzVpdParser(IpzVpdParser&&) = delete;
+    IpzVpdParser& operator=(IpzVpdParser&&) = delete;
+    ~IpzVpdParser() = default;
+
+    /**
+     * @brief Constructor
+     */
+    IpzVpdParser(Binary&& VpdVector) : vpd(std::move(VpdVector))
+    {
+    }
+
+    /**
+     * @brief Parse the memory VPD binary data.
+     * Collects and emplace the keyword-value pairs in map.
+     *
+     * @return map of keyword:value
+     */
+    std::variant<kwdVpdMap, Store> parse();
+
+    /**
+     * @brief An api to return interface name with respect to
+     * the parser selected.
+     *
+     * @return - Interface name for that vpd type.
+     */
+    std::string getInterfaceName() const;
+
+    /** @brief API to check vpd header
+     *  @param [in] vpd - VPDheader in binary format
+     */
+    void processHeader();
+
+  private:
+    Binary vpd;
+}; // class IpzVpdParser
+
+} // namespace parser
+} // namespace ipz
+} // namespace vpd
+} // namespace openpower
diff --git a/keyword_vpd_parser.cpp b/vpd-parser/keyword_vpd_parser.cpp
similarity index 95%
rename from keyword_vpd_parser.cpp
rename to vpd-parser/keyword_vpd_parser.cpp
index 9e147b5..3d204f4 100644
--- a/keyword_vpd_parser.cpp
+++ b/vpd-parser/keyword_vpd_parser.cpp
@@ -6,16 +6,19 @@
 #include <numeric>
 #include <string>
 
+using namespace openpower::vpd::constants;
+using namespace openpower::vpd::inventory;
+using namespace std;
+using namespace openpower::vpd;
+
 namespace vpd
 {
 namespace keyword
 {
 namespace parser
 {
-using namespace openpower::vpd::constants;
-using namespace openpower::vpd::inventory;
 
-KeywordVpdMap KeywordVpdParser::parseKwVpd()
+variant<KeywordVpdMap, store> KeywordVpdParser::parse()
 {
     int kwVpdType;
     if (keywordVpdVector.empty())
@@ -207,6 +210,12 @@
         throw std::runtime_error("Badly formed VPD data");
     }
 }
+
+std::string KeywordVpdParser::getInterfaceName() const
+{
+    return kwdVpdInf;
+}
+
 } // namespace parser
 } // namespace keyword
 } // namespace vpd
diff --git a/keyword_vpd_parser.hpp b/vpd-parser/keyword_vpd_parser.hpp
similarity index 87%
rename from keyword_vpd_parser.hpp
rename to vpd-parser/keyword_vpd_parser.hpp
index f2339fa..2382a5f 100644
--- a/keyword_vpd_parser.hpp
+++ b/vpd-parser/keyword_vpd_parser.hpp
@@ -1,5 +1,6 @@
 #pragma once
 
+#include "parser_interface.hpp"
 #include "types.hpp"
 
 namespace vpd
@@ -9,6 +10,10 @@
 namespace parser
 {
 
+using ParserInterface = openpower::vpd::parser::interface::ParserInterface;
+using kwdVpdMap = openpower::vpd::inventory::KeywordVpdMap;
+using store = openpower::vpd::Store;
+
 /**
  * @class KeywordVpdParser
  * @brief Implements parser for Keyword VPD
@@ -31,7 +36,7 @@
  * 6) Validate the 'small resource type last end tag'.
  * 7) Return the keyword-value map.
  */
-class KeywordVpdParser
+class KeywordVpdParser : public ParserInterface
 {
   public:
     KeywordVpdParser() = delete;
@@ -40,7 +45,7 @@
     ~KeywordVpdParser() = default;
 
     /**
-     * @brief Move Constructor
+     * @brief Constructor
      *
      * Move kwVpdVector to parser object's kwVpdVector
      */
@@ -51,14 +56,21 @@
 
     /**
      * @brief Parse the keyword VPD binary data.
-     *
      * Calls the sub functions to emplace the
      * keyword-value pairs in map and to validate
      * certain tags and checksum data.
      *
      * @return map of keyword:value
      */
-    openpower::vpd::inventory::KeywordVpdMap parseKwVpd();
+    std::variant<kwdVpdMap, store> parse();
+
+    /**
+     * @brief An api to return interface name with respect to
+     * the parser selected.
+     *
+     * @return - Interface name for that vpd type.
+     */
+    std::string getInterfaceName() const;
 
   private:
     openpower::vpd::Binary::iterator
diff --git a/memory_vpd_parser.cpp b/vpd-parser/memory_vpd_parser.cpp
similarity index 82%
rename from memory_vpd_parser.cpp
rename to vpd-parser/memory_vpd_parser.cpp
index 0fae663..6a4c608 100644
--- a/memory_vpd_parser.cpp
+++ b/vpd-parser/memory_vpd_parser.cpp
@@ -13,11 +13,11 @@
 namespace parser
 {
 using namespace inventory;
-using namespace parser;
 using namespace constants;
 using namespace std;
+using namespace openpower::vpd::parser;
 
-KeywordVpdMap memoryVpdParser::readKeywords(Binary::const_iterator iterator)
+kwdVpdMap memoryVpdParser::readKeywords(Binary::const_iterator iterator)
 {
     KeywordVpdMap map{};
 
@@ -36,7 +36,7 @@
     return map;
 }
 
-KeywordVpdMap memoryVpdParser::parseMemVpd()
+variant<kwdVpdMap, Store> memoryVpdParser::parse()
 {
     // check if vpd file is empty
     if (memVpd.empty())
@@ -54,6 +54,11 @@
     return vpdDataMap;
 }
 
+std::string memoryVpdParser::getInterfaceName() const
+{
+    return memVpdInf;
+}
+
 } // namespace parser
 } // namespace memory
 } // namespace vpd
diff --git a/vpd-parser/memory_vpd_parser.hpp b/vpd-parser/memory_vpd_parser.hpp
new file mode 100644
index 0000000..3d47144
--- /dev/null
+++ b/vpd-parser/memory_vpd_parser.hpp
@@ -0,0 +1,67 @@
+#pragma once
+
+#include "impl.hpp"
+#include "parser_interface.hpp"
+#include "types.hpp"
+
+namespace openpower
+{
+namespace vpd
+{
+namespace memory
+{
+namespace parser
+{
+using ParserInterface = openpower::vpd::parser::interface::ParserInterface;
+using kwdVpdMap = openpower::vpd::inventory::KeywordVpdMap;
+
+class memoryVpdParser : public ParserInterface
+{
+  public:
+    memoryVpdParser() = delete;
+    memoryVpdParser(const memoryVpdParser&) = delete;
+    memoryVpdParser& operator=(const memoryVpdParser&) = delete;
+    memoryVpdParser(memoryVpdParser&&) = delete;
+    memoryVpdParser& operator=(memoryVpdParser&&) = delete;
+    ~memoryVpdParser() = default;
+
+    /**
+     * @brief Constructor
+     *
+     * Move kwVpdVector to parser object's kwVpdVector
+     */
+    memoryVpdParser(Binary&& VpdVector) : memVpd(std::move(VpdVector))
+    {
+    }
+
+    /**
+     * @brief Parse the memory VPD binary data.
+     * Collects and emplace the keyword-value pairs in map.
+     *
+     * @return map of keyword:value
+     */
+    std::variant<kwdVpdMap, Store> parse();
+
+    /**
+     * @brief An api to return interface name with respect to
+     * publish data on cache
+     *
+     * @return - Interface name for that vpd type.
+     */
+    std::string getInterfaceName() const;
+
+  private:
+    /**
+     * @brief An api to read keywords.
+     *
+     * @return- map of kwd:value
+     */
+    kwdVpdMap readKeywords(Binary::const_iterator iterator);
+
+    // vdp file to be parsed
+    Binary memVpd;
+};
+} // namespace parser
+} // namespace memory
+} // namespace vpd
+} // namespace openpower
\ No newline at end of file
diff --git a/vpd-parser/parser_factory.cpp b/vpd-parser/parser_factory.cpp
new file mode 100644
index 0000000..e31d669
--- /dev/null
+++ b/vpd-parser/parser_factory.cpp
@@ -0,0 +1,59 @@
+#include "parser_factory.hpp"
+
+#include "ipz_parser.hpp"
+#include "keyword_vpd_parser.hpp"
+#include "memory_vpd_parser.hpp"
+#include "utils.hpp"
+
+using namespace vpd::keyword::parser;
+using namespace openpower::vpd::memory::parser;
+using namespace openpower::vpd::parser::interface;
+using namespace openpower::vpd::ipz::parser;
+
+namespace openpower
+{
+namespace vpd
+{
+namespace parser
+{
+namespace factory
+{
+interface::ParserInterface* ParserFactory::getParser(Binary&& vpdVector)
+{
+    vpdType type = vpdTypeCheck(vpdVector);
+
+    switch (type)
+    {
+        case IPZ_VPD:
+        {
+            return new IpzVpdParser(std::move(vpdVector));
+        }
+
+        case KEYWORD_VPD:
+        {
+            return new KeywordVpdParser(std::move(vpdVector));
+        }
+
+        case MEMORY_VPD:
+        {
+            return new memoryVpdParser(std::move(vpdVector));
+        }
+
+        default:
+            throw std::runtime_error("Invalid VPD format");
+    }
+}
+
+void ParserFactory::freeParser(interface::ParserInterface* parser)
+{
+    if (parser)
+    {
+        delete parser;
+        parser = nullptr;
+    }
+}
+
+} // namespace factory
+} // namespace parser
+} // namespace vpd
+} // namespace openpower
diff --git a/vpd-parser/parser_factory.hpp b/vpd-parser/parser_factory.hpp
new file mode 100644
index 0000000..c66e42b
--- /dev/null
+++ b/vpd-parser/parser_factory.hpp
@@ -0,0 +1,47 @@
+#pragma once
+#include "parser_interface.hpp"
+#include "types.hpp"
+
+namespace openpower
+{
+namespace vpd
+{
+namespace parser
+{
+namespace factory
+{
+/** @class ParserFactory
+ *  @brief Factory calss to instantiate concrete parser class.
+ *
+ *  This class should be used to instantiate an instance of parser class based
+ *  on the typeof vpd file.
+ */
+
+class ParserFactory
+{
+  public:
+    ParserFactory() = delete;
+    ~ParserFactory() = delete;
+    ParserFactory(const ParserFactory&) = delete;
+    ParserFactory& operator=(const ParserFactory&) = delete;
+    ParserFactory(ParserFactory&&) = delete;
+    ParserFactory& operator=(ParserFactory&&) = delete;
+
+    /**
+     * @brief A method to get object of concrete parser class.
+     * @param[in] - vpd file to check for the type.
+     * @return - Pointer to concrete parser class object.
+     */
+    static interface::ParserInterface* getParser(Binary&& vpdVector);
+
+    /**
+     * @brief A method to delete the parser object.
+     * @param[in] - Pointer to the parser object.
+     */
+    static void freeParser(interface::ParserInterface* parser);
+}; // ParserFactory
+
+} // namespace factory
+} // namespace parser
+} // namespace vpd
+} // namespace openpower
\ No newline at end of file
diff --git a/vpd-parser/parser_interface.hpp b/vpd-parser/parser_interface.hpp
new file mode 100644
index 0000000..2f11aff
--- /dev/null
+++ b/vpd-parser/parser_interface.hpp
@@ -0,0 +1,60 @@
+#pragma once
+
+#include "store.hpp"
+#include "types.hpp"
+
+#include <variant>
+
+namespace openpower
+{
+namespace vpd
+{
+namespace parser
+{
+namespace interface
+{
+using kwdVpdMap = openpower::vpd::inventory::KeywordVpdMap;
+
+/** @class ParserInterface
+ *  @brief Interface class for vpd parsers.
+ *
+ *  Any concrete parser class, implementing the parser logic needs to
+ *  derive from this interface class and ovverride the methods declared
+ *  in this class.
+ */
+class ParserInterface
+{
+  public:
+    /**
+     * @brief An api to implement parsing logic for VPD file.
+     * Needs to be implemented by all the class deriving from
+     * parser inerface.
+     *
+     * @return parsed format for vpd data, depending upon the
+     * parsing logic.
+     */
+    virtual std::variant<kwdVpdMap, Store> parse() = 0;
+
+    /**
+     * @brief An api to return interface name which will hold the
+     * data on cache.
+     * Needs to be implemented by all the class deriving fronm
+     * parser inerface
+     *
+     * @return - Interface name for that vpd type.
+     */
+    virtual std::string getInterfaceName() const = 0;
+    // virtual void test() = 0;
+
+    /**
+     * @brief Virtual destructor for the interface.
+     */
+    virtual ~ParserInterface()
+    {
+    }
+
+}; // class Parserinterface
+} // namespace interface
+} // namespace parser
+} // namespace vpd
+} // namespace openpower