GSoC Table Style Family: insertByName, replaceByName, removeByName

- also implements SwXTextTableStyle::replaceByName

- some refactorization
  + use std::unique_ptr

- fixes some bugs:
 + posible nullptr dereference in tblafmt.cxx
 + SwXTextTableStyle::getName() returned translated name
 + remvoed unnecesary SetXObject in Cell Style Family replacebyName

- tests

Change-Id: Idd25d54695ab5a4bdd4daf7ebf37b05fbc2366e7
Reviewed-on: https://gerrit.libreoffice.org/26578
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
diff --git a/sw/inc/tblafmt.hxx b/sw/inc/tblafmt.hxx
index fc698ef..0eb799a 100644
--- a/sw/inc/tblafmt.hxx
+++ b/sw/inc/tblafmt.hxx
@@ -343,6 +343,7 @@ public:

    void InsertAutoFormat(size_t i, std::unique_ptr<SwTableAutoFormat> pFormat);
    void EraseAutoFormat(size_t i);
    void EraseAutoFormat(const OUString& rName);
    std::unique_ptr<SwTableAutoFormat> ReleaseAutoFormat(size_t i);

    /// Find table style with the provided name, return nullptr when not found.
diff --git a/sw/inc/unostyle.hxx b/sw/inc/unostyle.hxx
index 07311e8..cc24073 100644
--- a/sw/inc/unostyle.hxx
+++ b/sw/inc/unostyle.hxx
@@ -254,12 +254,16 @@ class SwXTextTableStyle : public cppu::WeakImplHelper
<
    css::style::XStyle,
    css::beans::XPropertySet,
    css::container::XNameAccess,
    css::container::XNameContainer,
    css::lang::XServiceInfo
>
{
    SwDocShell* m_pDocShell;
    OUString m_sTableAutoFormatName;
    SwTableAutoFormat* m_pTableAutoFormat;
    /// Stores SwTableAutoFormat when this is not a physical style.
    std::unique_ptr<SwTableAutoFormat> m_pTableAutoFormat_Impl;
    /// If true, then it points to a core object, if false, then this is a created, but not-yet-inserted format.
    bool m_bPhysical;

    enum {
        FIRST_ROW_STYLE = 0,
@@ -282,12 +286,21 @@ class SwXTextTableStyle : public cppu::WeakImplHelper
        STYLE_COUNT
    };

    SwTableAutoFormat* GetTableAutoFormat();
    /// Fills m_aCellStyles with SwXTextCellStyles pointing to children of this style.
    void UpdateCellStylesMapping();
    static const CellStyleNameMap& GetCellStyleNameMap();
    css::uno::Reference<css::style::XStyle> m_aCellStyles[STYLE_COUNT];
public:
    SwXTextTableStyle(SwDocShell* pDocShell, SwTableAutoFormat* pTableAutoFormat);
    /// Create non physical style
    SwXTextTableStyle(SwDocShell* pDocShell, const OUString& rTableAutoFormatName);

    /// This function looks for a SwTableAutoFormat with given name. Returns nullptr if could not be found.
    static SwTableAutoFormat* GetTableAutoFormat(SwDocShell* pDocShell, const OUString& sName);
    /// Returns box format assigned to this style
    SwTableAutoFormat* GetTableFormat();
    void SetPhysical();

    //XStyle
    virtual sal_Bool SAL_CALL isUserDefined() throw (css::uno::RuntimeException, std::exception) override;
    virtual sal_Bool SAL_CALL isInUse() throw (css::uno::RuntimeException, std::exception) override;
@@ -312,6 +325,11 @@ public:
    virtual css::uno::Sequence<OUString> SAL_CALL getElementNames() throw(css::uno::RuntimeException, std::exception) override;
    virtual sal_Bool SAL_CALL hasByName(const OUString& rName) throw(css::uno::RuntimeException, std::exception) override;

    //XNameContainer
    virtual void SAL_CALL insertByName(const OUString& rName, const css::uno::Any& aElement) throw(css::lang::IllegalArgumentException, css::container::ElementExistException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) override;
    virtual void SAL_CALL replaceByName(const OUString& rName, const css::uno::Any& aElement) throw(css::lang::IllegalArgumentException, css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) override;
    virtual void SAL_CALL removeByName(const OUString& rName) throw(css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) override;

    //XElementAccess
    virtual css::uno::Type SAL_CALL getElementType() throw(css::uno::RuntimeException, std::exception) override;
    virtual sal_Bool SAL_CALL hasElements() throw(css::uno::RuntimeException, std::exception) override;
@@ -335,15 +353,17 @@ class SwXTextCellStyle : public cppu::WeakImplHelper
{
    SwDocShell* m_pDocShell;
    SwBoxAutoFormat* m_pBoxAutoFormat;
    OUString m_sParentStyle; // used when style is physical
    OUString m_sName;   // used when style is not physical
    bool m_bPhysical; // delete a m_pBoxAutoFormat when changing from false to true!
    /// Stores SwBoxAutoFormat when this is not a physical style.
    std::shared_ptr<SwBoxAutoFormat> m_pBoxAutoFormat_Impl;
    OUString m_sParentStyle;
    OUString m_sName;
    /// If true, then it points to a core object, if false, then this is a created, but not-yet-inserted format.
    bool m_bPhysical;

 public:
    SwXTextCellStyle(SwDocShell* pDocShell, SwBoxAutoFormat* pBoxAutoFormat, const OUString& sParentStyle);
    /// Create non physical style
    SwXTextCellStyle(SwDocShell* pDocShell, const OUString& sName);
    virtual ~SwXTextCellStyle();

    /**
    * This function looks for a SwBoxAutoFormat with given name. Parses the name and returns parent name.
@@ -355,7 +375,10 @@ class SwXTextCellStyle : public cppu::WeakImplHelper
    static SwBoxAutoFormat* GetBoxAutoFormat(SwDocShell* pDocShell, const OUString& sName, OUString* pParentName = nullptr);
    /// returns box format assigned to this style
    SwBoxAutoFormat* GetBoxFormat();
    /// Sets the addres of SwBoxAutoFormat this style is bound to. Usable only when style is physical.
    void SetBoxFormat(SwBoxAutoFormat* pBoxFormat);
    void SetPhysical();
    bool IsPhysical();

    //XStyle
    virtual sal_Bool SAL_CALL isUserDefined() throw (css::uno::RuntimeException, std::exception) override;
diff --git a/sw/qa/python/check_styles.py b/sw/qa/python/check_styles.py
index 144082a..372455e 100644
--- a/sw/qa/python/check_styles.py
+++ b/sw/qa/python/check_styles.py
@@ -171,6 +171,7 @@ class CheckStyle(unittest.TestCase):
        vEmptyDocStyles = ['Default Style']
        self.__test_StyleFamily(xTableStyles, vEmptyDocStyles, "SwXTextTableStyle")
        self.__test_StyleFamilyIndex(xTableStyles, vEmptyDocStyles, "SwXTextTableStyle")
        self.__test_StyleFamilyInsert(xDoc, xTableStyles, vEmptyDocStyles, "com.sun.star.style.TableStyle", "com.sun.star.style.CharacterStyle")
        for sStyleName in vEmptyDocStyles:
            self.assertIsNotNone(xTableStyles.getByName(sStyleName))
        #check SwXTextCellStyles
@@ -184,7 +185,6 @@ class CheckStyle(unittest.TestCase):
        xDoc.dispose()

    def test_tableStyleIsInUse(self):
        # extend when TableStyle insertByName comes
        xDoc = CheckStyle._uno.openEmptyWriterDoc()
        xBodyText = xDoc.getText()
        xCursor = xBodyText.createTextCursor()
@@ -201,6 +201,14 @@ class CheckStyle(unittest.TestCase):
        xTable.setPropertyValue("TableTemplateName", "")
        self.assertFalse(xDefaultTableStyle.isInUse())
        self.assertFalse(xDefaultCellStyle.isInUse())
        xTableStyle = xDoc.createInstance("com.sun.star.style.TableStyle")
        self.assertFalse(xTableStyle.isInUse())
        xDoc.StyleFamilies.getByName("TableStyles").insertByName("Test Table Style", xTableStyle)
        self.assertFalse(xTableStyle.isInUse())
        xTable.setPropertyValue("TableTemplateName", "Test Table Style")
        self.assertTrue(xTableStyle.isInUse())
        xTable.setPropertyValue("TableTemplateName", "")
        self.assertFalse(xTableStyle.isInUse())
        xDoc.dispose()

    def test_CellFamily(self):
@@ -210,7 +218,25 @@ class CheckStyle(unittest.TestCase):
        self.__test_StyleFamily(xCellStyles, vEmptyDocStyles, "SwXTextCellStyle")
        self.__test_StyleFamilyIndex(xCellStyles, vEmptyDocStyles, "SwXTextCellStyle")
        self.__test_StyleFamilyInsert(xDoc, xCellStyles, vEmptyDocStyles, "com.sun.star.style.CellStyle", "com.sun.star.style.CharacterStyle")
        #add more tests when TableStyles will support insertByName
        xTableStyle = xDoc.createInstance("com.sun.star.style.TableStyle")
        xCellStyle = xTableStyle.getByName("first-row")
        xDoc.StyleFamilies.getByName("TableStyles").insertByName("Test Table Style", xTableStyle)
        self.assertEqual(xTableStyle.getByName("first-row"), xCellStyle)
        self.assertEqual(xTableStyle.getByName("first-row"), xDoc.StyleFamilies.getByName("TableStyles").getByName("Test Table Style").getByName("first-row"))
        #replaceByName
        with self.assertRaises(NoSuchElementException):
            xTableStyle.replaceByName("foobarbaz", xCellStyle)
        xCellStyle = xDoc.createInstance("com.sun.star.style.CellStyle")
        with self.assertRaises(IllegalArgumentException):       #replace with not inserted cell style
            xTableStyle.replaceByName("first-row", xCellStyle)
        xTableStyle2 = xDoc.createInstance("com.sun.star.style.TableStyle")
        with self.assertRaises(IllegalArgumentException):       #replace with other family style
            xTableStyle.replaceByName("first-row", xTableStyle2)
        with self.assertRaises(IllegalArgumentException):       #replace with already assigned cell style
            xTableStyle.replaceByName("first-row", xTableStyle2.getByName("first-row"))
        xDoc.StyleFamilies.getByName("CellStyles").insertByName("Test Cell Style", xCellStyle)
        xTableStyle.replaceByName("first-row", xCellStyle)
        self.assertEqual(xTableStyle.getByName("first-row"), xCellStyle)
        xDoc.dispose()

if __name__ == '__main__':
diff --git a/sw/source/core/doc/tblafmt.cxx b/sw/source/core/doc/tblafmt.cxx
index 481f65f..66202a1 100644
--- a/sw/source/core/doc/tblafmt.cxx
+++ b/sw/source/core/doc/tblafmt.cxx
@@ -930,20 +930,19 @@ void SwTableAutoFormat::StoreTableProperties(const SwTable &table)

bool SwTableAutoFormat::FirstRowEndColumnIsRow()
{
    return *aBoxAutoFormat[3] == *aBoxAutoFormat[2];
    return GetBoxFormat(3) == GetBoxFormat(2);
}

bool SwTableAutoFormat::FirstRowStartColumnIsRow()
{
    return *aBoxAutoFormat[0] == *aBoxAutoFormat[1];
    return GetBoxFormat(0) == GetBoxFormat(1);
}
bool SwTableAutoFormat::LastRowEndColumnIsRow()
{
    return *aBoxAutoFormat[15] == *aBoxAutoFormat[14];
    return GetBoxFormat(14) == GetBoxFormat(15);
}
bool SwTableAutoFormat::LastRowStartColumnIsRow()
{
    return *aBoxAutoFormat[12] == *aBoxAutoFormat[13];
    return GetBoxFormat(12) == GetBoxFormat(13);
}

bool SwTableAutoFormat::Load( SvStream& rStream, const SwAfVersions& rVersions )
@@ -1156,6 +1155,20 @@ void SwTableAutoFormatTable::EraseAutoFormat(size_t const i)
    m_pImpl->m_AutoFormats.erase(m_pImpl->m_AutoFormats.begin() + i);
}

void SwTableAutoFormatTable::EraseAutoFormat(const OUString& rName)
{
    for (auto iter = m_pImpl->m_AutoFormats.begin();
         iter != m_pImpl->m_AutoFormats.end(); ++iter)
    {
        if ((*iter)->GetName() == rName)
        {
            m_pImpl->m_AutoFormats.erase(iter);
            return;
        }
    }
    SAL_INFO("sw.core", "SwTableAutoFormatTable::EraseAutoFormat, SwTableAutoFormat with given name not found");
}

std::unique_ptr<SwTableAutoFormat> SwTableAutoFormatTable::ReleaseAutoFormat(size_t const i)
{
    auto const iter(m_pImpl->m_AutoFormats.begin() + i);
@@ -1406,11 +1419,12 @@ void SwCellStyleTable::AddBoxFormat(const SwBoxAutoFormat& rBoxFormat, const OUS

void SwCellStyleTable::RemoveBoxFormat(const OUString& sName)
{
    for (size_t i=0; i < m_aCellStyles.size(); ++i)
    for (auto iter = m_aCellStyles.begin(); iter != m_aCellStyles.end(); ++iter)
    {
        if (m_aCellStyles[i].first == sName)
        if (iter->first == sName)
        {
            m_aCellStyles.erase(m_aCellStyles.begin() + i);
            delete iter->second;
            m_aCellStyles.erase(iter);
            return;
        }
    }
diff --git a/sw/source/core/unocore/unostyle.cxx b/sw/source/core/unocore/unostyle.cxx
index 4ea2f08..87e3c55 100644
--- a/sw/source/core/unocore/unostyle.cxx
+++ b/sw/source/core/unocore/unostyle.cxx
@@ -918,6 +918,18 @@ void XStyleFamily::insertByName(const OUString& rName, const uno::Any& rElement)
        m_pDocShell->GetDoc()->GetCellStyles().AddBoxFormat(*pNewStyle->GetBoxFormat(), sStyleName);
        pNewStyle->SetPhysical();
    }
    else if (nsSwGetPoolIdFromName::GET_POOLID_TABSTYLE == m_rEntry.m_aPoolId)
    {
        // handle table style
        uno::Reference<style::XStyle> xStyle = rElement.get<uno::Reference<style::XStyle>>();
        SwXTextTableStyle* pNewStyle = dynamic_cast<SwXTextTableStyle*>(xStyle.get());
        if (!pNewStyle)
            throw lang::IllegalArgumentException();

        pNewStyle->setName(sStyleName); // insertByName sets the element name
        m_pDocShell->GetDoc()->GetTableStyles().AddAutoFormat(*pNewStyle->GetTableFormat());
        pNewStyle->SetPhysical();
    }
    else
    {
        uno::Reference<lang::XUnoTunnel> xStyleTunnel = rElement.get<uno::Reference<lang::XUnoTunnel>>();
@@ -974,14 +986,25 @@ void XStyleFamily::replaceByName(const OUString& rName, const uno::Any& rElement
            if (!pStyleToReplaceWith)
                throw lang::IllegalArgumentException();

            // copy box style by value
            *pBoxAutoFormat = *pStyleToReplaceWith->GetBoxFormat();
            pStyleToReplaceWith->setName(rName);
            *pBoxAutoFormat = *pStyleToReplaceWith->GetBoxFormat();
            pStyleToReplaceWith->SetPhysical();
            // box assign operator does not copy reference to a xobject, we need to set it manually
            uno::Reference<style::XStyle> xCellStyle(pStyleToReplaceWith);
            pBoxAutoFormat->SetXObject(xCellStyle);
            // to handle unassigned styles, because their names aren't generated automatically
        }
    }
    else if (nsSwGetPoolIdFromName::GET_POOLID_TABSTYLE == m_rEntry.m_aPoolId)
    {
        // handle table styles
        SwTableAutoFormat* pTableAutoFormat = SwXTextTableStyle::GetTableAutoFormat(m_pDocShell, rName);
        if (pTableAutoFormat)
        {
            uno::Reference<style::XStyle> xStyle = rElement.get<uno::Reference<style::XStyle>>();
            SwXTextTableStyle* pStyleToReplaceWith = dynamic_cast<SwXTextTableStyle*>(xStyle.get());
            if (!pStyleToReplaceWith)
                throw lang::IllegalArgumentException();

            pStyleToReplaceWith->setName(rName);
            *pTableAutoFormat = *pStyleToReplaceWith->GetTableFormat();
            pStyleToReplaceWith->SetPhysical();
        }
    }
    else
@@ -1021,6 +1044,11 @@ void XStyleFamily::removeByName(const OUString& rName) throw( container::NoSuchE
        // handle cell style
        m_pDocShell->GetDoc()->GetCellStyles().RemoveBoxFormat(rName);
    }
    else if (nsSwGetPoolIdFromName::GET_POOLID_TABSTYLE == m_rEntry.m_aPoolId)
    {
        // handle table style
        m_pDocShell->GetDoc()->GetTableStyles().EraseAutoFormat(rName);
    }
    else
        m_pBasePool->Remove(pBase);
}
@@ -4320,50 +4348,35 @@ uno::Sequence< beans::PropertyValue > SwXAutoStyle::getProperties() throw (uno::
    return aRet;
}

SwXTextTableStyle::SwXTextTableStyle(SwDocShell* pDocShell, const OUString& rTableAutoFormatName) :
    m_pDocShell(pDocShell), m_sTableAutoFormatName(rTableAutoFormatName)
SwXTextTableStyle::SwXTextTableStyle(SwDocShell* pDocShell, SwTableAutoFormat* pTableAutoFormat) :
    m_pDocShell(pDocShell), m_pTableAutoFormat(pTableAutoFormat), m_pTableAutoFormat_Impl(nullptr), m_bPhysical(true)
{
    SwTableAutoFormat *pAutoFormat = GetTableAutoFormat();
    UpdateCellStylesMapping();
}

    if (pAutoFormat)
    {
        const std::vector<sal_Int32> aTableTemplateMap = SwTableAutoFormat::GetTableTemplateMap();
        assert(aTableTemplateMap.size() == STYLE_COUNT && "can not map SwTableAutoFormat to a SwXTextTableStyle");
        for (sal_Int32 i=0; i<STYLE_COUNT; ++i)
        {
            SwBoxAutoFormat* pBoxFormat = &pAutoFormat->GetBoxFormat(aTableTemplateMap[i]);
            uno::Reference<style::XStyle> xCellStyle(pBoxFormat->GetXObject(), uno::UNO_QUERY);
            if (!xCellStyle.is())
            {
                xCellStyle.set(new SwXTextCellStyle(m_pDocShell, pBoxFormat, m_sTableAutoFormatName));
                pBoxFormat->SetXObject(xCellStyle);
            }
            m_aCellStyles[i] = xCellStyle;
        }
    }
SwXTextTableStyle::SwXTextTableStyle(SwDocShell* pDocShell, const OUString& rTableAutoFormatName) :
    m_pDocShell(pDocShell), m_pTableAutoFormat_Impl(new SwTableAutoFormat(rTableAutoFormatName)), m_bPhysical(false)
{
    m_pTableAutoFormat = m_pTableAutoFormat_Impl.get();
    UpdateCellStylesMapping();
}

uno::Reference<style::XStyle> SwXTextTableStyle::CreateXTextTableStyle(SwDocShell* pDocShell, const OUString& rTableAutoFormatName)
{
    SolarMutexGuard aGuard;
    uno::Reference<style::XStyle> xTextTableStyle;
    const size_t nStyles = pDocShell->GetDoc()->GetTableStyles().size();
    for(size_t i=0; i < nStyles; ++i)
    SwTableAutoFormat* pAutoFormat = GetTableAutoFormat(pDocShell, rTableAutoFormatName);
    if (pAutoFormat && pAutoFormat->GetName() == rTableAutoFormatName)
    {
        SwTableAutoFormat* pAutoFormat = &pDocShell->GetDoc()->GetTableStyles()[i];
        if (pAutoFormat->GetName() == rTableAutoFormatName)
        xTextTableStyle.set(pAutoFormat->GetXObject(), uno::UNO_QUERY);
        if (!xTextTableStyle.is())
        {
            xTextTableStyle.set(pAutoFormat->GetXObject(), uno::UNO_QUERY);
            if (!xTextTableStyle.is())
            {
                xTextTableStyle.set(new SwXTextTableStyle(pDocShell, rTableAutoFormatName));
                pAutoFormat->SetXObject(xTextTableStyle);
            }
            break;
            xTextTableStyle.set(new SwXTextTableStyle(pDocShell, pAutoFormat));
            pAutoFormat->SetXObject(xTextTableStyle);
        }
    }

    // If corresponding AutoFormat doesn't exist create a XStyle but don't register it.
    // If corresponding AutoFormat doesn't exist create a non physical style.
    if (!xTextTableStyle.is())
    {
        xTextTableStyle.set(new SwXTextTableStyle(pDocShell, rTableAutoFormatName));
@@ -4373,17 +4386,21 @@ uno::Reference<style::XStyle> SwXTextTableStyle::CreateXTextTableStyle(SwDocShel
    return xTextTableStyle;
}

SwTableAutoFormat* SwXTextTableStyle::GetTableAutoFormat()
void SwXTextTableStyle::UpdateCellStylesMapping()
{
    const size_t nStyles = m_pDocShell->GetDoc()->GetTableStyles().size();
    for(size_t i=0; i < nStyles; ++i)
    const std::vector<sal_Int32> aTableTemplateMap = SwTableAutoFormat::GetTableTemplateMap();
    assert(aTableTemplateMap.size() == STYLE_COUNT && "can not map SwTableAutoFormat to a SwXTextTableStyle");
    for (sal_Int32 i=0; i<STYLE_COUNT; ++i)
    {
        SwTableAutoFormat* pAutoFormat = &m_pDocShell->GetDoc()->GetTableStyles()[i];
        if (pAutoFormat->GetName() == m_sTableAutoFormatName)
            return pAutoFormat;
        SwBoxAutoFormat* pBoxFormat = &m_pTableAutoFormat->GetBoxFormat(aTableTemplateMap[i]);
        uno::Reference<style::XStyle> xCellStyle(pBoxFormat->GetXObject(), uno::UNO_QUERY);
        if (!xCellStyle.is())
        {
            xCellStyle.set(new SwXTextCellStyle(m_pDocShell, pBoxFormat, m_pTableAutoFormat->GetName()));
            pBoxFormat->SetXObject(xCellStyle);
        }
        m_aCellStyles[i] = xCellStyle;
    }
    SAL_WARN("sw.uno", "lost SwTableAutoFormat and SwXTextTableStyle integrity");
    return nullptr;
}

const CellStyleNameMap& SwXTextTableStyle::GetCellStyleNameMap()
@@ -4415,12 +4432,66 @@ const CellStyleNameMap& SwXTextTableStyle::GetCellStyleNameMap()
    return aMap;
}

SwTableAutoFormat* SwXTextTableStyle::GetTableFormat()
{
    return m_pTableAutoFormat;
}

SwTableAutoFormat* SwXTextTableStyle::GetTableAutoFormat(SwDocShell* pDocShell, const OUString& sName)
{
    const size_t nStyles = pDocShell->GetDoc()->GetTableStyles().size();
    for(size_t i=0; i < nStyles; ++i)
    {
        SwTableAutoFormat* pAutoFormat = &pDocShell->GetDoc()->GetTableStyles()[i];
        if (pAutoFormat->GetName() == sName)
        {
            return pAutoFormat;
        }
    }
    // not found
    return nullptr;
}

void SwXTextTableStyle::SetPhysical()
{
    if (!m_bPhysical)
    {
        // find table format in doc
        SwTableAutoFormat* pTableAutoFormat = GetTableAutoFormat(m_pDocShell, m_pTableAutoFormat->GetName());
        if (pTableAutoFormat)
        {
            m_bPhysical = true;
            /// take care of children, make SwXTextCellStyles use new core SwBoxAutoFormats
            const std::vector<sal_Int32> aTableTemplateMap = SwTableAutoFormat::GetTableTemplateMap();
            for (size_t i=0; i<aTableTemplateMap.size(); ++i)
            {
                SwBoxAutoFormat* pOldBoxFormat = &m_pTableAutoFormat->GetBoxFormat(aTableTemplateMap[i]);
                uno::Reference<style::XStyle> xCellStyle(pOldBoxFormat->GetXObject(), uno::UNO_QUERY);
                if (!xCellStyle.is())
                {
                    SwXTextCellStyle* pStyle = dynamic_cast<SwXTextCellStyle*>(xCellStyle.get());
                    SwBoxAutoFormat* pNewBoxFormat = &pTableAutoFormat->GetBoxFormat(aTableTemplateMap[i]);
                    pStyle->SetBoxFormat(pNewBoxFormat);
                    pNewBoxFormat->SetXObject(uno::Reference<style::XStyle>(xCellStyle));
                }
            }
            m_pTableAutoFormat_Impl = nullptr;
            m_pTableAutoFormat = pTableAutoFormat;
            m_pTableAutoFormat->SetXObject(uno::Reference<style::XStyle>(this));
        }
        else
            SAL_WARN("sw.uno", "setting style physical, but SwTableAutoFormat in document not found");
    }
    else
        SAL_WARN("sw.uno", "calling SetPhysical on a physical SwXTextTableStyle");
}

// XStyle
sal_Bool SAL_CALL SwXTextTableStyle::isUserDefined() throw (uno::RuntimeException, std::exception)
{
    SolarMutexGuard aGuard;
    // only first style is not user defined
    if (m_pDocShell->GetDoc()->GetTableStyles()[0].GetName() == m_sTableAutoFormatName)
    if (m_pDocShell->GetDoc()->GetTableStyles()[0].GetName() == m_pTableAutoFormat->GetName())
        return false;

    return true;
@@ -4429,6 +4500,9 @@ sal_Bool SAL_CALL SwXTextTableStyle::isUserDefined() throw (uno::RuntimeExceptio
sal_Bool SAL_CALL SwXTextTableStyle::isInUse() throw (uno::RuntimeException, std::exception)
{
    SolarMutexGuard aGuard;
    if (!m_bPhysical)
        return false;

    uno::Reference<text::XTextTablesSupplier> xTablesSupp(m_pDocShell->GetModel(), uno::UNO_QUERY);
    if (!xTablesSupp.is())
        return false;
@@ -4444,7 +4518,7 @@ sal_Bool SAL_CALL SwXTextTableStyle::isInUse() throw (uno::RuntimeException, std
        xTables->getByIndex(i) >>= xTablePropertySet;
        OUString sTableTemplateName;
        if (xTablePropertySet.is() && (xTablePropertySet->getPropertyValue("TableTemplateName") >>= sTableTemplateName)
            && sTableTemplateName == m_sTableAutoFormatName)
            && sTableTemplateName == m_pTableAutoFormat->GetName())
            return true;
    }

@@ -4464,29 +4538,14 @@ OUString SAL_CALL SwXTextTableStyle::getName() throw(uno::RuntimeException, std:
{
    SolarMutexGuard aGuard;
    OUString sProgName;
    SwStyleNameMapper::FillProgName(m_sTableAutoFormatName, sProgName, nsSwGetPoolIdFromName::GET_POOLID_TABSTYLE, true);
    return m_sTableAutoFormatName;
    SwStyleNameMapper::FillProgName(m_pTableAutoFormat->GetName(), sProgName, nsSwGetPoolIdFromName::GET_POOLID_TABSTYLE, true);
    return sProgName;
}

void SAL_CALL SwXTextTableStyle::setName(const OUString& rName) throw(uno::RuntimeException, std::exception)
{
    SolarMutexGuard aGuard;
    const size_t nStyles = m_pDocShell->GetDoc()->GetTableStyles().size();
    for(size_t i=0; i < nStyles; ++i)
    {
        SwTableAutoFormat* pAutoFormat = &m_pDocShell->GetDoc()->GetTableStyles()[i];
        if (pAutoFormat->GetName() == rName)
        {
            SAL_INFO("sw.uno", "SwXTextTableStyle with given name already exists");
            return;
        }
    }

    SwTableAutoFormat* pAutoFormat = GetTableAutoFormat();
    if (pAutoFormat)
        pAutoFormat->SetName(rName);

    m_sTableAutoFormatName = rName;
    m_pTableAutoFormat->SetName(rName);
}

//XPropertySet
@@ -4505,20 +4564,17 @@ css::uno::Any SAL_CALL SwXTextTableStyle::getPropertyValue(const OUString& rProp
{
    SolarMutexGuard aGuard;
    bool bIsRow = false;
    SwTableAutoFormat* pFormat = GetTableAutoFormat();
    if (pFormat)
    {
        if (rPropertyName == UNO_NAME_TABLE_FIRST_ROW_END_COLUMN)
            bIsRow = pFormat->FirstRowEndColumnIsRow();
        else if (rPropertyName == UNO_NAME_TABLE_FIRST_ROW_START_COLUMN)
            bIsRow = pFormat->FirstRowStartColumnIsRow();
        else if (rPropertyName == UNO_NAME_TABLE_LAST_ROW_END_COLUMN)
            bIsRow = pFormat->LastRowEndColumnIsRow();
        else if (rPropertyName == UNO_NAME_TABLE_LAST_ROW_START_COLUMN)
            bIsRow = pFormat->LastRowStartColumnIsRow();
        else
            throw css::beans::UnknownPropertyException();
    }

    if (rPropertyName == UNO_NAME_TABLE_FIRST_ROW_END_COLUMN)
        bIsRow = m_pTableAutoFormat->FirstRowEndColumnIsRow();
    else if (rPropertyName == UNO_NAME_TABLE_FIRST_ROW_START_COLUMN)
        bIsRow = m_pTableAutoFormat->FirstRowStartColumnIsRow();
    else if (rPropertyName == UNO_NAME_TABLE_LAST_ROW_END_COLUMN)
        bIsRow = m_pTableAutoFormat->LastRowEndColumnIsRow();
    else if (rPropertyName == UNO_NAME_TABLE_LAST_ROW_START_COLUMN)
        bIsRow = m_pTableAutoFormat->LastRowStartColumnIsRow();
    else
        throw css::beans::UnknownPropertyException();

    return uno::makeAny(bIsRow ? OUString("row") : OUString("column"));
}
@@ -4569,6 +4625,53 @@ sal_Bool SAL_CALL SwXTextTableStyle::hasByName(const OUString& rName) throw(css:
    return iter != rMap.end();
}

//XNameContainer
void SAL_CALL SwXTextTableStyle::insertByName(const OUString& /*Name*/, const uno::Any& /*Element*/) throw(lang::IllegalArgumentException, container::ElementExistException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
{
    SAL_WARN("sw.uno", "not implemented");
}

void SAL_CALL SwXTextTableStyle::replaceByName(const OUString& rName, const uno::Any& rElement) throw(lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
{
    SolarMutexGuard aGuard;
    const CellStyleNameMap& rMap = GetCellStyleNameMap();
    CellStyleNameMap::const_iterator iter = rMap.find(rName);
    if(iter == rMap.end())
        throw container::NoSuchElementException();
    const sal_Int32 nCellStyle = iter->second;

    uno::Reference<style::XStyle> xStyle = rElement.get<uno::Reference<style::XStyle>>();
    if (!xStyle.is())
        throw lang::IllegalArgumentException();

    SwXTextCellStyle* pStyleToReplaceWith = dynamic_cast<SwXTextCellStyle*>(xStyle.get());
    // replace only with physical ...
    if (pStyleToReplaceWith && !pStyleToReplaceWith->IsPhysical())
        throw lang::IllegalArgumentException();

    // ... unassigned cell styles
    if (!m_pDocShell->GetDoc()->GetCellStyles().GetBoxFormat(xStyle->getName()))
        throw lang::IllegalArgumentException();

    const auto& rTableTemplateMap = SwTableAutoFormat::GetTableTemplateMap();
    const sal_Int32 nBoxFormat = rTableTemplateMap[nCellStyle];

    // move SwBoxAutoFormat to dest. SwTableAutoFormat
    m_pTableAutoFormat->SetBoxFormat(*pStyleToReplaceWith->GetBoxFormat(), nBoxFormat);
    // make SwXTextCellStyle use new, moved SwBoxAutoFormat
    pStyleToReplaceWith->SetBoxFormat(&m_pTableAutoFormat->GetBoxFormat(nBoxFormat));
    m_pTableAutoFormat->GetBoxFormat(nBoxFormat).SetXObject(xStyle);
    // remove unassigned SwBoxAutoFormat, which is not anymore in use anyways
    m_pDocShell->GetDoc()->GetCellStyles().RemoveBoxFormat(xStyle->getName());
    // make this SwXTextTableStyle use new SwXTextCellStyle
    m_aCellStyles[nCellStyle] = xStyle;
}

void SAL_CALL SwXTextTableStyle::removeByName(const OUString& /*Name*/) throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
{
    SAL_WARN("sw.uno", "not implemented");
}

//XElementAccess
uno::Type SAL_CALL SAL_CALL SwXTextTableStyle::getElementType() throw(uno::RuntimeException, std::exception)
{
@@ -4598,20 +4701,20 @@ css::uno::Sequence<OUString> SAL_CALL SwXTextTableStyle::getSupportedServiceName

// SwXTextCellStyle
SwXTextCellStyle::SwXTextCellStyle(SwDocShell* pDocShell, SwBoxAutoFormat* pBoxAutoFormat, const OUString& sParentStyle) :
    m_pDocShell(pDocShell), m_pBoxAutoFormat(pBoxAutoFormat), m_sParentStyle(sParentStyle), m_bPhysical(true)
    m_pDocShell(pDocShell),
    m_pBoxAutoFormat(pBoxAutoFormat),
    m_pBoxAutoFormat_Impl(nullptr),
    m_sParentStyle(sParentStyle),
    m_bPhysical(true)
{ }

SwXTextCellStyle::SwXTextCellStyle(SwDocShell* pDocShell, const OUString& sName) :
    m_pDocShell(pDocShell), m_sName(sName), m_bPhysical(false)
    m_pDocShell(pDocShell),
    m_pBoxAutoFormat_Impl(new SwBoxAutoFormat()),
    m_sName(sName),
    m_bPhysical(false)
{
    // m_bPhysical=false will help to take care deleting it
    m_pBoxAutoFormat = new SwBoxAutoFormat();
}

SwXTextCellStyle::~SwXTextCellStyle()
{
     if (!m_bPhysical)
         delete m_pBoxAutoFormat;
    m_pBoxAutoFormat = m_pBoxAutoFormat_Impl.get();
}

SwBoxAutoFormat* SwXTextCellStyle::GetBoxFormat()
@@ -4619,15 +4722,23 @@ SwBoxAutoFormat* SwXTextCellStyle::GetBoxFormat()
    return m_pBoxAutoFormat;
}

void SwXTextCellStyle::SetBoxFormat(SwBoxAutoFormat* pBoxFormat)
{
    if (m_bPhysical)
        m_pBoxAutoFormat = pBoxFormat;
    else
        SAL_INFO("sw.uno", "trying to call SwXTextCellStyle::SetBoxFormat on non physical style");
}

void SwXTextCellStyle::SetPhysical()
{
    if (!m_bPhysical)
    {
        m_bPhysical = true;
        delete m_pBoxAutoFormat;
        SwBoxAutoFormat* pBoxAutoFormat = GetBoxAutoFormat(m_pDocShell, m_sName, &m_sParentStyle);
        if (pBoxAutoFormat)
        {
            m_bPhysical = true;
            m_pBoxAutoFormat_Impl = nullptr;
            m_pBoxAutoFormat = pBoxAutoFormat;
            m_pBoxAutoFormat->SetXObject(uno::Reference<style::XStyle>(this));
        }
@@ -4638,6 +4749,11 @@ void SwXTextCellStyle::SetPhysical()
        SAL_WARN("sw.uno", "calling SetPhysical on a physical SwXTextCellStyle");
}

bool SwXTextCellStyle::IsPhysical()
{
    return m_bPhysical;
}

SwBoxAutoFormat* SwXTextCellStyle::GetBoxAutoFormat(SwDocShell* pDocShell, const OUString& sName, OUString* pParentName)
{
    if (sName.isEmpty())