<commit_before>#include "XPathWrapper.hpp"

#include <vector>
#include <cassert>

#if defined(XALAN_OLD_STREAM_HEADERS)
#include <iostream.h>
#else
#include <iostream>
#endif

#include <framework/MemBufInputSource.hpp>
#include <framework/URLInputSource.hpp>
#include <parsers/DOMParser.hpp>
#include <util/PlatformUtils.hpp>

#include <XalanDOM/XalanDocument.hpp>
#include <XalanDOM/XalanElement.hpp>

#include <PlatformSupport/DirectoryEnumerator.hpp>
#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/STLHelper.hpp>

#include <DOMSupport/DOMServices.hpp>

#include <XPath/XObjectFactoryDefault.hpp>
#include <XPath/XPath.hpp>
#include <XPath/XPathEnvSupportDefault.hpp>
#include <XPath/XPathExecutionContextDefault.hpp>
#include <XPath/XPathInit.hpp>
#include <XPath/XPathProcessorImpl.hpp>
#include <XPath/XPathFactoryDefault.hpp>
#include <XPath/ElementPrefixResolverProxy.hpp>

#include <XalanSourceTree/XalanSourceTreeDOMSupport.hpp>
#include <XalanSourceTree/XalanSourceTreeParserLiaison.hpp>

#if !defined(XALAN_NO_NAMESPACES)
using std::cerr;
using std::endl;
using std::vector;
#endif

////////////////////////////////////////////////////

// the implementation class, that does all calls to XPath and Xerces
class XPathWrapperImpl
{
public:

	XPathWrapper::CharVectorTypeVectorType
	evaluate(
		const CharVectorType&	xml,
		const CharVectorType&	context,
		const CharVectorType&	expr)
	{
		//initialize Xerces...
		try
		{
			XMLPlatformUtils::Initialize();
		}
		catch(const XMLException&)
		{
			cerr << "XMLPlatformUtils::Initialize() failed!" << endl;

			throw;
		}

		XPathWrapper::CharVectorTypeVectorType	theResultList;

		{
			// Initialize the XPath subsystem...
			XPathInit						theInit;

			// We'll use these to parse the XML file.
			XalanSourceTreeDOMSupport		theDOMSupport;
			XalanSourceTreeParserLiaison	theLiaison(theDOMSupport);

			// Hook the two together...
			theDOMSupport.setParserLiaison(&theLiaison);

			XalanElement*	rootElem = 0;

			try
			{
				// parse XML and get root element
				MemBufInputSource inStream((XMLByte*)c_str(xml), xml.size(), "foo", false);

				XalanDocument* const	doc = theLiaison.parseXMLStream(inStream);
				assert(doc != 0);

				rootElem = doc->getDocumentElement();
				assert(rootElem != 0);
			}
			catch(const XMLException&)
			{
				cerr << "Caught XMLExecption..." << endl;

				throw;
			}

			// configure the objects needed for XPath to work with the Xerces DOM
			XPathEnvSupportDefault			theEnvSupport;
			XObjectFactoryDefault			theXObjectFactory;
			XPathExecutionContextDefault	theExecutionContext(theEnvSupport, theDOMSupport, theXObjectFactory);
			XPathFactoryDefault				theXPathFactory;
			XPathProcessorImpl				theXPathProcessor;

			try
			{
				// first get the context nodeset
				XPath* const	contextXPath = theXPathFactory.create();

				theXPathProcessor.initXPath(*contextXPath,
											TranscodeFromLocalCodePage(context),
											ElementPrefixResolverProxy(rootElem, theEnvSupport, theDOMSupport),
											theEnvSupport);

	   			XObjectPtr	xObj =
					contextXPath->execute(rootElem,
										  ElementPrefixResolverProxy(rootElem, theEnvSupport, theDOMSupport),
										  theExecutionContext);

				const NodeRefListBase&	contextNodeList = xObj->nodeset();

				const unsigned int	theLength =
						contextNodeList.getLength();

				if (theLength == 0)
				{
						cerr << "Warning -- No nodes matched the location path \""
							 << context
							 << "\"."
							 << endl
							 << "Execution cannot continue..."
							 << endl
							 << endl;
				}
				else
				{
					if (theLength > 1)
					{
						cerr << "Warning -- More than one node matched the location path \""
							 << context
							 << "\"."
							 << endl
							 << "The first node matched will be used as the context node."
							 << endl
							 << endl;
					}

					// and now get the result of the primary xpath expression
					XPath* const	xpath = theXPathFactory.create();
					theXPathProcessor.initXPath(*xpath,
												TranscodeFromLocalCodePage(expr),
												ElementPrefixResolverProxy(rootElem, theEnvSupport, theDOMSupport),
												theEnvSupport);

					xObj = xpath->execute(contextNodeList.item(0),
										  ElementPrefixResolverProxy(rootElem, theEnvSupport, theDOMSupport),
										  theExecutionContext);

					// now encode the results.  For all types but nodelist, we'll just convert it to a string
					// but, for nodelist, we'll convert each node to a string and return a list of them
					switch (xObj->getType())
					{
						case XObject::eTypeNodeSet:
						{
							const NodeRefListBase& nodeset = xObj->nodeset();
							size_t len = nodeset.getLength();

							for (size_t i=0; i<len; i++)
							{
								XalanNode* const	node = nodeset.item(i);
								XalanDOMString		str;

								const int theType = node->getNodeType();

								if (theType == XalanNode::COMMENT_NODE ||
									theType == XalanNode::PROCESSING_INSTRUCTION_NODE)
									str = node->getNodeValue();
								else if (theType == XalanNode::ELEMENT_NODE)
									str = node->getNodeName();
								else
									DOMServices::getNodeData(*node, str);

								theResultList.push_back(TranscodeToLocalCodePage(str));
							}

							break;
						}

						default:
						{
							theResultList.push_back(TranscodeToLocalCodePage(xObj->str()));

							break;
						}
					}
				}
			}
			catch(const XMLException&)
			{
				cerr << "Caught XMLExecption..." << endl;

				throw;
			}

			// Shut down Xerces...
			XMLPlatformUtils::Initialize();
		}

		return theResultList;
	}
};

////////////////////////////////////////////////////

// The public XPathWrapper methods just delegate to our impl class

XPathWrapper::XPathWrapper() :
	pImpl(new XPathWrapperImpl())
{
}

XPathWrapper::~XPathWrapper()
{
	delete pImpl;
}

XPathWrapper::CharVectorTypeVectorType
XPathWrapper::evaluate(
		const CharVectorType&	xml,
		const CharVectorType&	context,
		const CharVectorType&	path)
{
	return pImpl->evaluate(xml, context, path);
}

<commit_msg>Fixed include file.<commit_after>#include "XPathWrapper.hpp"

#include <vector>
#include <cassert>

#if defined(XALAN_OLD_STREAM_HEADERS)
#include <iostream.h>
#else
#include <iostream>
#endif

#include <framework/MemBufInputSource.hpp>
#include <framework/URLInputSource.hpp>
#include <parsers/DOMParser.hpp>
#include <util/PlatformUtils.hpp>

#include <Include/STLHelper.hpp>

#include <XalanDOM/XalanDocument.hpp>
#include <XalanDOM/XalanElement.hpp>

#include <PlatformSupport/DirectoryEnumerator.hpp>
#include <PlatformSupport/DOMStringHelper.hpp>

#include <DOMSupport/DOMServices.hpp>

#include <XPath/XObjectFactoryDefault.hpp>
#include <XPath/XPath.hpp>
#include <XPath/XPathEnvSupportDefault.hpp>
#include <XPath/XPathExecutionContextDefault.hpp>
#include <XPath/XPathInit.hpp>
#include <XPath/XPathProcessorImpl.hpp>
#include <XPath/XPathFactoryDefault.hpp>
#include <XPath/ElementPrefixResolverProxy.hpp>

#include <XalanSourceTree/XalanSourceTreeDOMSupport.hpp>
#include <XalanSourceTree/XalanSourceTreeParserLiaison.hpp>

#if !defined(XALAN_NO_NAMESPACES)
using std::cerr;
using std::endl;
using std::vector;
#endif

////////////////////////////////////////////////////

// the implementation class, that does all calls to XPath and Xerces
class XPathWrapperImpl
{
public:

	XPathWrapper::CharVectorTypeVectorType
	evaluate(
		const CharVectorType&	xml,
		const CharVectorType&	context,
		const CharVectorType&	expr)
	{
		//initialize Xerces...
		try
		{
			XMLPlatformUtils::Initialize();
		}
		catch(const XMLException&)
		{
			cerr << "XMLPlatformUtils::Initialize() failed!" << endl;

			throw;
		}

		XPathWrapper::CharVectorTypeVectorType	theResultList;

		{
			// Initialize the XPath subsystem...
			XPathInit						theInit;

			// We'll use these to parse the XML file.
			XalanSourceTreeDOMSupport		theDOMSupport;
			XalanSourceTreeParserLiaison	theLiaison(theDOMSupport);

			// Hook the two together...
			theDOMSupport.setParserLiaison(&theLiaison);

			XalanElement*	rootElem = 0;

			try
			{
				// parse XML and get root element
				MemBufInputSource inStream((XMLByte*)c_str(xml), xml.size(), "foo", false);

				XalanDocument* const	doc = theLiaison.parseXMLStream(inStream);
				assert(doc != 0);

				rootElem = doc->getDocumentElement();
				assert(rootElem != 0);
			}
			catch(const XMLException&)
			{
				cerr << "Caught XMLExecption..." << endl;

				throw;
			}

			// configure the objects needed for XPath to work with the Xerces DOM
			XPathEnvSupportDefault			theEnvSupport;
			XObjectFactoryDefault			theXObjectFactory;
			XPathExecutionContextDefault	theExecutionContext(theEnvSupport, theDOMSupport, theXObjectFactory);
			XPathFactoryDefault				theXPathFactory;
			XPathProcessorImpl				theXPathProcessor;

			try
			{
				// first get the context nodeset
				XPath* const	contextXPath = theXPathFactory.create();

				theXPathProcessor.initXPath(*contextXPath,
											TranscodeFromLocalCodePage(context),
											ElementPrefixResolverProxy(rootElem, theEnvSupport, theDOMSupport),
											theEnvSupport);

	   			XObjectPtr	xObj =
					contextXPath->execute(rootElem,
										  ElementPrefixResolverProxy(rootElem, theEnvSupport, theDOMSupport),
										  theExecutionContext);

				const NodeRefListBase&	contextNodeList = xObj->nodeset();

				const unsigned int	theLength =
						contextNodeList.getLength();

				if (theLength == 0)
				{
						cerr << "Warning -- No nodes matched the location path \""
							 << context
							 << "\"."
							 << endl
							 << "Execution cannot continue..."
							 << endl
							 << endl;
				}
				else
				{
					if (theLength > 1)
					{
						cerr << "Warning -- More than one node matched the location path \""
							 << context
							 << "\"."
							 << endl
							 << "The first node matched will be used as the context node."
							 << endl
							 << endl;
					}

					// and now get the result of the primary xpath expression
					XPath* const	xpath = theXPathFactory.create();
					theXPathProcessor.initXPath(*xpath,
												TranscodeFromLocalCodePage(expr),
												ElementPrefixResolverProxy(rootElem, theEnvSupport, theDOMSupport),
												theEnvSupport);

					xObj = xpath->execute(contextNodeList.item(0),
										  ElementPrefixResolverProxy(rootElem, theEnvSupport, theDOMSupport),
										  theExecutionContext);

					// now encode the results.  For all types but nodelist, we'll just convert it to a string
					// but, for nodelist, we'll convert each node to a string and return a list of them
					switch (xObj->getType())
					{
						case XObject::eTypeNodeSet:
						{
							const NodeRefListBase& nodeset = xObj->nodeset();
							size_t len = nodeset.getLength();

							for (size_t i=0; i<len; i++)
							{
								XalanNode* const	node = nodeset.item(i);
								XalanDOMString		str;

								const int theType = node->getNodeType();

								if (theType == XalanNode::COMMENT_NODE ||
									theType == XalanNode::PROCESSING_INSTRUCTION_NODE)
									str = node->getNodeValue();
								else if (theType == XalanNode::ELEMENT_NODE)
									str = node->getNodeName();
								else
									DOMServices::getNodeData(*node, str);

								theResultList.push_back(TranscodeToLocalCodePage(str));
							}

							break;
						}

						default:
						{
							theResultList.push_back(TranscodeToLocalCodePage(xObj->str()));

							break;
						}
					}
				}
			}
			catch(const XMLException&)
			{
				cerr << "Caught XMLExecption..." << endl;

				throw;
			}

			// Shut down Xerces...
			XMLPlatformUtils::Initialize();
		}

		return theResultList;
	}
};

////////////////////////////////////////////////////

// The public XPathWrapper methods just delegate to our impl class

XPathWrapper::XPathWrapper() :
	pImpl(new XPathWrapperImpl())
{
}

XPathWrapper::~XPathWrapper()
{
	delete pImpl;
}

XPathWrapper::CharVectorTypeVectorType
XPathWrapper::evaluate(
		const CharVectorType&	xml,
		const CharVectorType&	context,
		const CharVectorType&	path)
{
	return pImpl->evaluate(xml, context, path);
}

<|endoftext|>


<commit_before>#include "USRFindingAction.h"
#include "gtest/gtest.h"
#include "clang/Tooling/Tooling.h"
#include <stdio.h>
#include <set>
#include <map>
#include <vector>

namespace clang {
namespace rename {
namespace test {

// Determines if the symbol group invariants hold. To recap, those invariants
// are:
//  (1) All symbols in the same symbol group share the same USR.
//  (2) Two symbols from two different groups do not share the same USR.
static void testOffsetGroups(const char *Code,
                             const std::vector<std::vector<unsigned>> Groups) {
  std::set<std::string> AllUSRs, CurrUSR;

  for (const auto &Group : Groups) {
    // Groups the invariants do not hold then the value of USR is also invalid,
    // but at that point the test has already failed and USR ceases to be
    // useful.
    std::string USR;
    for (const auto &Offset : Group) {
      USRFindingAction Action(Offset);
      auto Factory = tooling::newFrontendActionFactory(&Action);
      EXPECT_TRUE(tooling::runToolOnCode(Factory->create(), Code));
      const auto &USRs = Action.getUSRs();
      EXPECT_EQ(1u, USRs.size());
      USR = USRs[0];
      CurrUSR.insert(USR);
    }
    EXPECT_EQ(1u, CurrUSR.size());
    CurrUSR.clear();
    AllUSRs.insert(USR);
  }

  EXPECT_EQ(Groups.size(), AllUSRs.size());
}

#if !(defined(_MSC_VER) && _MSC_VER < 1800)
TEST(USRLocFinding, FindsVarUSR) {
  const char VarTest[] = "\n\
namespace A {\n\
int foo;\n\
}\n\
int foo;\n\
int bar = foo;\n\
int baz = A::foo;\n\
void fun1() {\n\
  struct {\n\
    int foo;\n\
  } b = { 100 };\n\
  int foo = 100;\n\
  baz = foo;\n\
  {\n\
    extern int foo;\n\
    baz = foo;\n\
    foo = A::foo + baz;\n\
    A::foo = b.foo;\n\
  }\n\
 foo = b.foo;\n\
}\n";
  std::vector<std::vector<unsigned>> VarTestOffsets(3);
  VarTestOffsets[0].push_back(19);
  VarTestOffsets[0].push_back(63);
  VarTestOffsets[0].push_back(205);
  VarTestOffsets[0].push_back(223);
  VarTestOffsets[1].push_back(30);
  VarTestOffsets[1].push_back(45);
  VarTestOffsets[1].push_back(172);
  VarTestOffsets[1].push_back(187);
  VarTestOffsets[2].push_back(129);
  VarTestOffsets[2].push_back(148);
  VarTestOffsets[2].push_back(242);

  testOffsetGroups(VarTest, VarTestOffsets);
}
#endif

}
}
}
<commit_msg>Revert r215854 corresponding to r215857, "Suppress ClangRenameTests/USRLocFinding.FindsVarUSR on msc17 for now. Will fix later."<commit_after>#include "USRFindingAction.h"
#include "gtest/gtest.h"
#include "clang/Tooling/Tooling.h"
#include <stdio.h>
#include <set>
#include <map>
#include <vector>

namespace clang {
namespace rename {
namespace test {

// Determines if the symbol group invariants hold. To recap, those invariants
// are:
//  (1) All symbols in the same symbol group share the same USR.
//  (2) Two symbols from two different groups do not share the same USR.
static void testOffsetGroups(const char *Code,
                             const std::vector<std::vector<unsigned>> Groups) {
  std::set<std::string> AllUSRs, CurrUSR;

  for (const auto &Group : Groups) {
    // Groups the invariants do not hold then the value of USR is also invalid,
    // but at that point the test has already failed and USR ceases to be
    // useful.
    std::string USR;
    for (const auto &Offset : Group) {
      USRFindingAction Action(Offset);
      auto Factory = tooling::newFrontendActionFactory(&Action);
      EXPECT_TRUE(tooling::runToolOnCode(Factory->create(), Code));
      const auto &USRs = Action.getUSRs();
      EXPECT_EQ(1u, USRs.size());
      USR = USRs[0];
      CurrUSR.insert(USR);
    }
    EXPECT_EQ(1u, CurrUSR.size());
    CurrUSR.clear();
    AllUSRs.insert(USR);
  }

  EXPECT_EQ(Groups.size(), AllUSRs.size());
}

TEST(USRLocFinding, FindsVarUSR) {
  const char VarTest[] = "\n\
namespace A {\n\
int foo;\n\
}\n\
int foo;\n\
int bar = foo;\n\
int baz = A::foo;\n\
void fun1() {\n\
  struct {\n\
    int foo;\n\
  } b = { 100 };\n\
  int foo = 100;\n\
  baz = foo;\n\
  {\n\
    extern int foo;\n\
    baz = foo;\n\
    foo = A::foo + baz;\n\
    A::foo = b.foo;\n\
  }\n\
 foo = b.foo;\n\
}\n";
  std::vector<std::vector<unsigned>> VarTestOffsets(3);
  VarTestOffsets[0].push_back(19);
  VarTestOffsets[0].push_back(63);
  VarTestOffsets[0].push_back(205);
  VarTestOffsets[0].push_back(223);
  VarTestOffsets[1].push_back(30);
  VarTestOffsets[1].push_back(45);
  VarTestOffsets[1].push_back(172);
  VarTestOffsets[1].push_back(187);
  VarTestOffsets[2].push_back(129);
  VarTestOffsets[2].push_back(148);
  VarTestOffsets[2].push_back(242);

  testOffsetGroups(VarTest, VarTestOffsets);
}

}
}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: propertysetinfo.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: os $ $Date: 2001-03-13 14:32:17 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#include "unotools/propertysetinfo.hxx"

using namespace ::utl;
using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;

namespace utl
{
class PropertyMapImpl
{
public:
    PropertyMapImpl() throw();
    virtual ~PropertyMapImpl() throw();

    void add( PropertyMapEntry* pMap ) throw();
    void remove( const OUString& aName ) throw();

    Sequence< Property > getProperties() throw();

    const PropertyMap* getPropertyMap() const throw();

    Property getPropertyByName( const OUString& aName ) throw( UnknownPropertyException );
    sal_Bool hasPropertyByName( const OUString& aName ) throw();

private:
    PropertyMap maPropertyMap;
    Sequence< Property > maProperties;
};
}

PropertyMapImpl::PropertyMapImpl() throw()
{
}

PropertyMapImpl::~PropertyMapImpl() throw()
{
}

void PropertyMapImpl::add( PropertyMapEntry* pMap ) throw()
{
    while( pMap->mpName )
    {
        OUString aName( pMap->mpName, pMap->mnNameLen, RTL_TEXTENCODING_ASCII_US );

#ifndef PRODUCT
        PropertyMap::iterator aIter = maPropertyMap.find( aName );
        if( aIter != maPropertyMap.end() )
        {
            DBG_ERROR( "Warning: PropertyMapEntry added twice, possible error!" );
        }
#endif
        if( NULL == pMap->mpType )
        {
            DBG_ERROR( "No type in PropertyMapEntry!" );
            pMap->mpType = &::getCppuType((const sal_Int32*)0);
        }

        maPropertyMap[aName] = pMap;

        if( maProperties.getLength() )
            maProperties.realloc( 0 );

        pMap = &pMap[1];
    }
}

void PropertyMapImpl::remove( const OUString& aName ) throw()
{
    maPropertyMap.erase( aName );

    if( maProperties.getLength() )
        maProperties.realloc( 0 );
}

Sequence< Property > PropertyMapImpl::getProperties() throw()
{
    // maybe we have to generate the properties after
    // a change in the property map or at first call
    // to getProperties
    if( maProperties.getLength() != (sal_Int32)maPropertyMap.size() )
    {
        maProperties = Sequence< Property >( maPropertyMap.size() );
        Property* pProperties = maProperties.getArray();

        PropertyMap::iterator aIter = maPropertyMap.begin();
        const PropertyMap::iterator aEnd = maPropertyMap.end();
        while( aIter != aEnd )
        {
            PropertyMapEntry* pEntry = (*aIter).second;

            pProperties->Name = OUString( pEntry->mpName, pEntry->mnNameLen, RTL_TEXTENCODING_ASCII_US );
            pProperties->Handle = pEntry->mnWhich;
            pProperties->Type = *pEntry->mpType;
            pProperties->Attributes = pEntry->mnFlags;
            pProperties++;
            aIter++;
        }
    }

    return maProperties;
}

const PropertyMap* PropertyMapImpl::getPropertyMap() const throw()
{
    return &maPropertyMap;
}

Property PropertyMapImpl::getPropertyByName( const OUString& aName ) throw( UnknownPropertyException )
{
    PropertyMap::iterator aIter = maPropertyMap.find( aName );

    if( maPropertyMap.end() == aIter )
        throw UnknownPropertyException();

    PropertyMapEntry* pEntry = (*aIter).second;

    return Property( aName, pEntry->mnWhich, *pEntry->mpType, pEntry->mnFlags );
}

sal_Bool PropertyMapImpl::hasPropertyByName( const OUString& aName ) throw()
{
    return maPropertyMap.find( aName ) != maPropertyMap.end();
}

///////////////////////////////////////////////////////////////////////

PropertySetInfo::PropertySetInfo() throw()
{
    mpMap = new PropertyMapImpl();
}

PropertySetInfo::~PropertySetInfo() throw()
{
    delete mpMap;
}

void PropertySetInfo::add( PropertyMapEntry* pMap ) throw()
{
    mpMap->add( pMap );
}

void PropertySetInfo::remove( const rtl::OUString& aName ) throw()
{
    mpMap->remove( aName );
}

Sequence< ::com::sun::star::beans::Property > SAL_CALL PropertySetInfo::getProperties() throw(::com::sun::star::uno::RuntimeException)
{
    return mpMap->getProperties();
}

Property SAL_CALL PropertySetInfo::getPropertyByName( const ::rtl::OUString& aName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
{
    return mpMap->getPropertyByName( aName );
}

sal_Bool SAL_CALL PropertySetInfo::hasPropertyByName( const ::rtl::OUString& Name ) throw(::com::sun::star::uno::RuntimeException)
{
    return mpMap->hasPropertyByName( Name );
}

const PropertyMap* PropertySetInfo::getPropertyMap() const throw()
{
    return mpMap->getPropertyMap();
}
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.264); FILE MERGED 2005/09/05 14:01:09 rt 1.2.264.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: propertysetinfo.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 09:49:12 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#include "unotools/propertysetinfo.hxx"

using namespace ::utl;
using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;

namespace utl
{
class PropertyMapImpl
{
public:
    PropertyMapImpl() throw();
    virtual ~PropertyMapImpl() throw();

    void add( PropertyMapEntry* pMap ) throw();
    void remove( const OUString& aName ) throw();

    Sequence< Property > getProperties() throw();

    const PropertyMap* getPropertyMap() const throw();

    Property getPropertyByName( const OUString& aName ) throw( UnknownPropertyException );
    sal_Bool hasPropertyByName( const OUString& aName ) throw();

private:
    PropertyMap maPropertyMap;
    Sequence< Property > maProperties;
};
}

PropertyMapImpl::PropertyMapImpl() throw()
{
}

PropertyMapImpl::~PropertyMapImpl() throw()
{
}

void PropertyMapImpl::add( PropertyMapEntry* pMap ) throw()
{
    while( pMap->mpName )
    {
        OUString aName( pMap->mpName, pMap->mnNameLen, RTL_TEXTENCODING_ASCII_US );

#ifndef PRODUCT
        PropertyMap::iterator aIter = maPropertyMap.find( aName );
        if( aIter != maPropertyMap.end() )
        {
            DBG_ERROR( "Warning: PropertyMapEntry added twice, possible error!" );
        }
#endif
        if( NULL == pMap->mpType )
        {
            DBG_ERROR( "No type in PropertyMapEntry!" );
            pMap->mpType = &::getCppuType((const sal_Int32*)0);
        }

        maPropertyMap[aName] = pMap;

        if( maProperties.getLength() )
            maProperties.realloc( 0 );

        pMap = &pMap[1];
    }
}

void PropertyMapImpl::remove( const OUString& aName ) throw()
{
    maPropertyMap.erase( aName );

    if( maProperties.getLength() )
        maProperties.realloc( 0 );
}

Sequence< Property > PropertyMapImpl::getProperties() throw()
{
    // maybe we have to generate the properties after
    // a change in the property map or at first call
    // to getProperties
    if( maProperties.getLength() != (sal_Int32)maPropertyMap.size() )
    {
        maProperties = Sequence< Property >( maPropertyMap.size() );
        Property* pProperties = maProperties.getArray();

        PropertyMap::iterator aIter = maPropertyMap.begin();
        const PropertyMap::iterator aEnd = maPropertyMap.end();
        while( aIter != aEnd )
        {
            PropertyMapEntry* pEntry = (*aIter).second;

            pProperties->Name = OUString( pEntry->mpName, pEntry->mnNameLen, RTL_TEXTENCODING_ASCII_US );
            pProperties->Handle = pEntry->mnWhich;
            pProperties->Type = *pEntry->mpType;
            pProperties->Attributes = pEntry->mnFlags;
            pProperties++;
            aIter++;
        }
    }

    return maProperties;
}

const PropertyMap* PropertyMapImpl::getPropertyMap() const throw()
{
    return &maPropertyMap;
}

Property PropertyMapImpl::getPropertyByName( const OUString& aName ) throw( UnknownPropertyException )
{
    PropertyMap::iterator aIter = maPropertyMap.find( aName );

    if( maPropertyMap.end() == aIter )
        throw UnknownPropertyException();

    PropertyMapEntry* pEntry = (*aIter).second;

    return Property( aName, pEntry->mnWhich, *pEntry->mpType, pEntry->mnFlags );
}

sal_Bool PropertyMapImpl::hasPropertyByName( const OUString& aName ) throw()
{
    return maPropertyMap.find( aName ) != maPropertyMap.end();
}

///////////////////////////////////////////////////////////////////////

PropertySetInfo::PropertySetInfo() throw()
{
    mpMap = new PropertyMapImpl();
}

PropertySetInfo::~PropertySetInfo() throw()
{
    delete mpMap;
}

void PropertySetInfo::add( PropertyMapEntry* pMap ) throw()
{
    mpMap->add( pMap );
}

void PropertySetInfo::remove( const rtl::OUString& aName ) throw()
{
    mpMap->remove( aName );
}

Sequence< ::com::sun::star::beans::Property > SAL_CALL PropertySetInfo::getProperties() throw(::com::sun::star::uno::RuntimeException)
{
    return mpMap->getProperties();
}

Property SAL_CALL PropertySetInfo::getPropertyByName( const ::rtl::OUString& aName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
{
    return mpMap->getPropertyByName( aName );
}

sal_Bool SAL_CALL PropertySetInfo::hasPropertyByName( const ::rtl::OUString& Name ) throw(::com::sun::star::uno::RuntimeException)
{
    return mpMap->hasPropertyByName( Name );
}

const PropertyMap* PropertySetInfo::getPropertyMap() const throw()
{
    return mpMap->getPropertyMap();
}
<|endoftext|>


<commit_before>/*
 * Copyright 2019 The Open GEE Contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "StorageManager.h"

#include <algorithm>
#include <gtest/gtest.h>
#include <sstream>

using namespace std;

const size_t CACHE_SIZE = 5;

class TestItem : public khRefCounter, public StorageManaged {
 public:
  TestItem() : val(nextValue++), saveSucceeds(true) {}
  const int val;
  string savename;
  bool saveSucceeds;
  const string XMLFilename() {
    stringstream filename;
    filename << val;
    return filename.str();
  }
  virtual bool Save(const string &filename) {
    savename = filename;
    return saveSucceeds;
  }
 private:
  static int nextValue;
};
int TestItem::nextValue = 1;
template<> const bool StorageManager<TestItem>::check_timestamps = false;

using HandleType = typename StorageManager<TestItem>::HandleType;
using AssetKey = typename StorageManager<TestItem>::AssetKey;

class TestHandle : public AssetHandleInterface<TestItem> {
  public:
    virtual const AssetKey Key() const { return name; }
    virtual string Filename() const { return "/dev/null"; }
    virtual HandleType Load(const string &) const {
      return khRefGuardFromNew<TestItem>(new TestItem());
    }
    virtual bool Valid(const HandleType &) const { return true; }
    TestHandle(const AssetKey & name) : name(name) {}
    TestHandle() = default;
    AssetKey name;
    HandleType handle;
};

template<class HandleClass>
HandleClass Get(StorageManager<TestItem> & storageManager,
                const AssetKey & name,
                bool checkFileExistenceFirst,
                bool addToCache,
                bool makeMutable) {
  HandleClass handle(name);
  handle.handle = storageManager.Get(&handle, checkFileExistenceFirst, addToCache, makeMutable);
  return handle;
}

class StorageManagerTest : public testing::Test {
 protected:
  StorageManager<TestItem> storageManager;
 public:
  StorageManagerTest() : storageManager(CACHE_SIZE, "test") {}
};

TEST_F(StorageManagerTest, AddAndRetrieve) {
  ASSERT_EQ(storageManager.CacheSize(), 0) << "Storage manager has unexpected item in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";

  // Create some items
  TestHandle first = Get<TestHandle>(storageManager, "first", false, true, false);
  TestHandle second = Get<TestHandle>(storageManager, "second", false, true, false);
  TestHandle third = Get<TestHandle>(storageManager, "third", false, true, false);

  ASSERT_EQ(storageManager.CacheSize(), 3) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
  ASSERT_EQ(first.handle->val, 1) << "First item has unexpected value";
  ASSERT_EQ(second.handle->val, 2) << "Second item has unexpected value";
  ASSERT_EQ(third.handle->val, 3) << "Third item has unexpected value";

  // Retrieve one of the items
  TestHandle second2 = Get<TestHandle>(storageManager, "second", false, true, false);
  ASSERT_EQ(storageManager.CacheSize(), 3) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
  ASSERT_EQ(second.handle->val, second2.handle->val) << "Could not retrieve existing item from storage manager";
}

TEST_F(StorageManagerTest, LoadWithoutCache) {
  TestHandle newItem = Get<TestHandle>(storageManager, "new", false, false, false);
  ASSERT_EQ(storageManager.CacheSize(), 0) << "Storage manager has unexpected item in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";

  storageManager.AddExisting(newItem.name, newItem.handle);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";

  TestHandle new2 = Get<TestHandle>(storageManager, "new", false, true, false);
  ASSERT_EQ(newItem.handle->val, new2.handle->val) << "Could not retrieve existing item from storage manager.";
}

TEST_F(StorageManagerTest, AddNew) {
  HandleType newItem(khRefGuardFromNew(new TestItem()));
  ASSERT_EQ(storageManager.CacheSize(), 0) << "Storage manager has unexpected item in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";

  storageManager.AddNew("newItem", newItem);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 1) << "Storage manager has wrong number of items in dirty map";

  TestHandle another = Get<TestHandle>(storageManager, "another", false, true, false);
  ASSERT_EQ(storageManager.CacheSize(), 2) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 1) << "Storage manager has wrong number of items in dirty map";

  TestHandle retrieved = Get<TestHandle>(storageManager, "newItem", false, true, false);
  ASSERT_EQ(newItem->val, retrieved.handle->val) << "Could not retrieve new item from storage manager.";
}

class TestHandleBadFile : public TestHandle {
  public:
    virtual string Filename() const { return "notafile"; }
    TestHandleBadFile(const AssetKey & name) : TestHandle(name) {}
};

TEST_F(StorageManagerTest, CheckFileExistence) {
  TestHandle goodFile = Get<TestHandle>(storageManager, "good", true, true, false);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";

  TestHandleBadFile badFile = Get<TestHandleBadFile>(storageManager, "bad", true, true, false);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
  ASSERT_FALSE(badFile.handle) << "Should get empty handle from non-existant file";
}

TEST_F(StorageManagerTest, Mutable) {
  TestHandle mut = Get<TestHandle>(storageManager, "mutable", false, true, true);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 1) << "Storage manager has wrong number of items in dirty map";

  TestHandle another = Get<TestHandle>(storageManager, "another", false, true, false);
  ASSERT_EQ(storageManager.CacheSize(), 2) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 1) << "Storage manager has wrong number of items in dirty map";
}

TEST_F(StorageManagerTest, PurgeCache) {
  // Put items in the cache but don't hold handles so they will be purged
  for(size_t i = 0; i < CACHE_SIZE + 2; ++i) {
    stringstream s;
    s << "asset" << i;
    Get<TestHandle>(storageManager, s.str(), false, true, false);
    ASSERT_EQ(storageManager.CacheSize(), min(i+1, CACHE_SIZE)) << "Unexpected number of items in cache";
    ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
  }
}

TEST_F(StorageManagerTest, PurgeCacheWithHandles) {
  {
    // Put items in the cache and hold handles so they won't be purged
    TestHandle handles[CACHE_SIZE+3];
    for(size_t i = 0; i < CACHE_SIZE + 3; ++i) {
      stringstream s;
      s << "asset" << i;
      handles[i] = Get<TestHandle>(storageManager, s.str(), false, true, false);
      ASSERT_EQ(storageManager.CacheSize(), i+1) << "Unexpected number of items in cache";
      ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
    }
  }

  // Now that we no longer have handles items can be removed from the cache.
  // Remove an item but don't purge the cache
  storageManager.NoLongerNeeded("asset0", false);
  ASSERT_EQ(storageManager.CacheSize(), CACHE_SIZE+2) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";

  // Remove an item and do purge the cache
  storageManager.NoLongerNeeded("asset1");
  ASSERT_EQ(storageManager.CacheSize(), CACHE_SIZE) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
  storageManager.NoLongerNeeded("asset1");
  ASSERT_EQ(storageManager.CacheSize(), CACHE_SIZE) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
}

class TestHandleInvalid : public TestHandle {
  public:
    virtual bool Valid(const HandleType &) const { return false; }
    TestHandleInvalid(const AssetKey & name) : TestHandle(name) {}
};

TEST_F(StorageManagerTest, InvalidItemInCache) {
  TestHandle invalid = Get<TestHandle>(storageManager, "invalid", false, true, false);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";

  // Ensure that if we get it again it is reloaded since it's invalid
  TestHandle invalid2 = Get<TestHandleInvalid>(storageManager, "invalid", false, true, false);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
  ASSERT_NE(invalid.handle->val, invalid2.handle->val) << "Did not reload invalid item";
}

TEST_F(StorageManagerTest, Abort) {
  TestHandle handles[5];
  handles[0] = Get<TestHandle>(storageManager, "asset0", false, true, false);
  handles[1] = Get<TestHandle>(storageManager, "asset1", false, true, false);
  handles[2] = Get<TestHandle>(storageManager, "mutable2", false, true, true);
  handles[3] = Get<TestHandle>(storageManager, "asset3", false, true, false);
  handles[4] = Get<TestHandle>(storageManager, "mutable4", false, true, true);
  ASSERT_EQ(storageManager.CacheSize(), 5) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 2) << "Storage manager has wrong number of items in dirty map";

  // Abort should remove the mutable items but nothing else
  storageManager.Abort();
  ASSERT_EQ(storageManager.CacheSize(), 3) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has wrong number of items in dirty map";

  // Try to reload one of the non-dirty items
  TestHandle notdirty = Get<TestHandle>(storageManager, "asset3", false, true, false);
  ASSERT_EQ(handles[3].handle->val, notdirty.handle->val) << "Non-dirty item was removed from cache on abort";

  // Try to reload one of the dirty items
  TestHandle dirty = Get<TestHandle>(storageManager, "mutable2", false, true, true);
  ASSERT_NE(handles[2].handle->val, dirty.handle->val) << "Dirty item was not removed from cache on abort";
  ASSERT_EQ(storageManager.CacheSize(), 4) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 1) << "Storage manager has wrong number of items in dirty map";
}

void getAssetsForDirtyTest(StorageManager<TestItem> & storageManager, TestHandle handles[5]) {
  handles[0] = Get<TestHandle>(storageManager, "asset0", false, true, false);
  handles[1] = Get<TestHandle>(storageManager, "asset1", false, true, false);
  handles[2] = Get<TestHandle>(storageManager, "mutable2", false, true, true);
  handles[3] = Get<TestHandle>(storageManager, "asset3", false, true, false);
  handles[4] = Get<TestHandle>(storageManager, "mutable4", false, true, true);
  ASSERT_EQ(storageManager.CacheSize(), 5) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 2) << "Storage manager has wrong number of items in dirty map";
}

TEST_F(StorageManagerTest, SaveDirty) {
  TestHandle handles[5];
  getAssetsForDirtyTest(storageManager, handles);

  khFilesTransaction trans;
  storageManager.SaveDirtyToDotNew(trans, nullptr);
  ASSERT_EQ(storageManager.CacheSize(), 5) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has wrong number of items in dirty map";
  ASSERT_EQ(trans.NumNew(), 2) << "Wrong number of new items in file transaction";
  ASSERT_EQ(trans.NumDeleted(), 0) << "Wrong number of deleted items in file transaction";
  ASSERT_EQ(handles[0].handle->savename, string()) << "Non-dirty files should not be saved";
  ASSERT_NE(handles[4].handle->savename, string()) << "Dirty files should be saved";
  string savename = handles[4].handle->savename;
  string ext = ".new";
  ASSERT_TRUE(equal(ext.rbegin(), ext.rend(), savename.rbegin())) << "Saved file name must end in .new";
}

TEST_F(StorageManagerTest, SaveDirtyToVector) {
  TestHandle handles[5];
  getAssetsForDirtyTest(storageManager, handles);

  khFilesTransaction trans;
  vector<SharedString> saved;
  storageManager.SaveDirtyToDotNew(trans, &saved);
  ASSERT_EQ(saved.size(), 2) << "Wrong number of items in saved vector";
  ASSERT_TRUE(find(saved.begin(), saved.end(), "mutable2") != saved.end()) << "Dirty item missing from saved vector";
  ASSERT_TRUE(find(saved.begin(), saved.end(), "mutable4") != saved.end()) << "Dirty item missing from saved vector";
}

TEST_F(StorageManagerTest, FailedSave) {
  TestHandle item = Get<TestHandle>(storageManager, "item", false, true, true);
  item.handle->saveSucceeds = false;
  khFilesTransaction trans;
  storageManager.SaveDirtyToDotNew(trans, nullptr);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 1) << "Storage manager has wrong number of items in dirty map";
  ASSERT_EQ(trans.NumNew(), 0) << "Transaction should be empty after failed save";
  ASSERT_EQ(trans.NumDeleted(), 0) << "Wrong number of deleted items in file transaction";
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc,argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Issue #1342: Enhance unit tests<commit_after>/*
 * Copyright 2019 The Open GEE Contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "StorageManager.h"

#include <algorithm>
#include <gtest/gtest.h>
#include <sstream>

using namespace std;

const size_t CACHE_SIZE = 5;

class TestItem : public khRefCounter, public StorageManaged {
 public:
  TestItem() : val(nextValue++), saveSucceeds(true) {}
  const int val;
  string savename;
  bool saveSucceeds;
  const string XMLFilename() {
    stringstream filename;
    filename << val;
    return filename.str();
  }
  virtual bool Save(const string &filename) {
    savename = filename;
    return saveSucceeds;
  }
 private:
  static int nextValue;
};
int TestItem::nextValue = 1;
template<> const bool StorageManager<TestItem>::check_timestamps = false;

using HandleType = typename StorageManager<TestItem>::HandleType;
using AssetKey = typename StorageManager<TestItem>::AssetKey;

class TestHandle : public AssetHandleInterface<TestItem> {
  public:
    virtual const AssetKey Key() const { return name; }
    virtual string Filename() const { return "/dev/null"; }
    virtual HandleType Load(const string &) const {
      return khRefGuardFromNew<TestItem>(new TestItem());
    }
    virtual bool Valid(const HandleType &) const { return true; }
    TestHandle(const AssetKey & name) : name(name) {}
    TestHandle() = default;
    AssetKey name;
    HandleType handle;
};

template<class HandleClass>
HandleClass Get(StorageManager<TestItem> & storageManager,
                const AssetKey & name,
                bool checkFileExistenceFirst,
                bool addToCache,
                bool makeMutable) {
  HandleClass handle(name);
  handle.handle = storageManager.Get(&handle, checkFileExistenceFirst, addToCache, makeMutable);
  return handle;
}

class StorageManagerTest : public testing::Test {
 protected:
  StorageManager<TestItem> storageManager;
 public:
  StorageManagerTest() : storageManager(CACHE_SIZE, "test") {}
};

TEST_F(StorageManagerTest, AddAndRetrieve) {
  ASSERT_EQ(storageManager.CacheSize(), 0) << "Storage manager has unexpected item in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";

  // Create some items
  TestHandle first = Get<TestHandle>(storageManager, "first", false, true, false);
  TestHandle second = Get<TestHandle>(storageManager, "second", false, true, false);
  TestHandle third = Get<TestHandle>(storageManager, "third", false, true, false);

  ASSERT_EQ(storageManager.CacheSize(), 3) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
  ASSERT_EQ(first.handle->val, 1) << "First item has unexpected value";
  ASSERT_EQ(second.handle->val, 2) << "Second item has unexpected value";
  ASSERT_EQ(third.handle->val, 3) << "Third item has unexpected value";

  // Retrieve one of the items
  TestHandle second2 = Get<TestHandle>(storageManager, "second", false, true, false);
  ASSERT_EQ(storageManager.CacheSize(), 3) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
  ASSERT_EQ(second.handle->val, second2.handle->val) << "Could not retrieve existing item from storage manager";
}

TEST_F(StorageManagerTest, LoadWithoutCache) {
  TestHandle newItem = Get<TestHandle>(storageManager, "new", false, false, false);
  ASSERT_EQ(storageManager.CacheSize(), 0) << "Storage manager has unexpected item in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";

  storageManager.AddExisting(newItem.name, newItem.handle);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";

  TestHandle new2 = Get<TestHandle>(storageManager, "new", false, true, false);
  ASSERT_EQ(newItem.handle->val, new2.handle->val) << "Could not retrieve existing item from storage manager.";
}

TEST_F(StorageManagerTest, AddNew) {
  HandleType newItem(khRefGuardFromNew(new TestItem()));
  ASSERT_EQ(storageManager.CacheSize(), 0) << "Storage manager has unexpected item in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";

  storageManager.AddNew("newItem", newItem);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 1) << "Storage manager has wrong number of items in dirty map";

  TestHandle another = Get<TestHandle>(storageManager, "another", false, true, false);
  ASSERT_EQ(storageManager.CacheSize(), 2) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 1) << "Storage manager has wrong number of items in dirty map";

  TestHandle retrieved = Get<TestHandle>(storageManager, "newItem", false, true, false);
  ASSERT_EQ(newItem->val, retrieved.handle->val) << "Could not retrieve new item from storage manager.";
}

class TestHandleBadFile : public TestHandle {
  public:
    virtual string Filename() const { return "notafile"; }
    TestHandleBadFile(const AssetKey & name) : TestHandle(name) {}
};

TEST_F(StorageManagerTest, CheckFileExistence) {
  TestHandle goodFile = Get<TestHandle>(storageManager, "good", true, true, false);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";

  TestHandleBadFile badFile = Get<TestHandleBadFile>(storageManager, "bad", true, true, false);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
  ASSERT_FALSE(badFile.handle) << "Should get empty handle from non-existant file";
}

TEST_F(StorageManagerTest, Mutable) {
  TestHandle mut = Get<TestHandle>(storageManager, "mutable", false, true, true);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 1) << "Storage manager has wrong number of items in dirty map";

  TestHandle another = Get<TestHandle>(storageManager, "another", false, true, false);
  ASSERT_EQ(storageManager.CacheSize(), 2) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 1) << "Storage manager has wrong number of items in dirty map";
}

TEST_F(StorageManagerTest, PurgeCache) {
  // Put items in the cache but don't hold handles so they will be purged
  for(size_t i = 0; i < CACHE_SIZE + 2; ++i) {
    stringstream s;
    s << "asset" << i;
    Get<TestHandle>(storageManager, s.str(), false, true, false);
    ASSERT_EQ(storageManager.CacheSize(), min(i+1, CACHE_SIZE)) << "Unexpected number of items in cache";
    ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
  }
}

TEST_F(StorageManagerTest, PurgeCacheWithHandles) {
  {
    // Put items in the cache and hold handles so they won't be purged
    TestHandle handles[CACHE_SIZE+3];
    for(size_t i = 0; i < CACHE_SIZE + 3; ++i) {
      stringstream s;
      s << "asset" << i;
      handles[i] = Get<TestHandle>(storageManager, s.str(), false, true, false);
      ASSERT_EQ(storageManager.CacheSize(), i+1) << "Unexpected number of items in cache";
      ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
    }
  }

  // Now that we no longer have handles items can be removed from the cache.
  // Remove an item but don't purge the cache
  storageManager.NoLongerNeeded("asset0", false);
  ASSERT_EQ(storageManager.CacheSize(), CACHE_SIZE+2) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";

  // Remove an item and do purge the cache
  storageManager.NoLongerNeeded("asset1");
  ASSERT_EQ(storageManager.CacheSize(), CACHE_SIZE) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
  storageManager.NoLongerNeeded("asset1");
  ASSERT_EQ(storageManager.CacheSize(), CACHE_SIZE) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
}

class TestHandleInvalid : public TestHandle {
  public:
    virtual bool Valid(const HandleType &) const { return false; }
    TestHandleInvalid(const AssetKey & name) : TestHandle(name) {}
};

TEST_F(StorageManagerTest, InvalidItemInCache) {
  TestHandle invalid = Get<TestHandle>(storageManager, "invalid", false, true, false);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";

  // Ensure that if we get it again it is reloaded since it's invalid
  TestHandle invalid2 = Get<TestHandleInvalid>(storageManager, "invalid", false, true, false);
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Storage manager has wrong number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has unexpected item in dirty map";
  ASSERT_NE(invalid.handle->val, invalid2.handle->val) << "Did not reload invalid item";
}

TEST_F(StorageManagerTest, Abort) {
  TestHandle handles[5];
  handles[0] = Get<TestHandle>(storageManager, "asset0", false, true, false);
  handles[1] = Get<TestHandle>(storageManager, "asset1", false, true, false);
  handles[2] = Get<TestHandle>(storageManager, "mutable2", false, true, true);
  handles[3] = Get<TestHandle>(storageManager, "asset3", false, true, false);
  handles[4] = Get<TestHandle>(storageManager, "mutable4", false, true, true);
  ASSERT_EQ(storageManager.CacheSize(), 5) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 2) << "Storage manager has wrong number of items in dirty map";

  // Abort should remove the mutable items but nothing else
  storageManager.Abort();
  ASSERT_EQ(storageManager.CacheSize(), 3) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has wrong number of items in dirty map";

  // Try to reload one of the non-dirty items
  TestHandle notdirty = Get<TestHandle>(storageManager, "asset3", false, true, false);
  ASSERT_EQ(handles[3].handle->val, notdirty.handle->val) << "Non-dirty item was removed from cache on abort";

  // Try to reload one of the dirty items
  TestHandle dirty = Get<TestHandle>(storageManager, "mutable2", false, true, true);
  ASSERT_NE(handles[2].handle->val, dirty.handle->val) << "Dirty item was not removed from cache on abort";
  ASSERT_EQ(storageManager.CacheSize(), 4) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 1) << "Storage manager has wrong number of items in dirty map";
}

void getAssetsForDirtyTest(StorageManager<TestItem> & storageManager, TestHandle handles[5]) {
  handles[0] = Get<TestHandle>(storageManager, "asset0", false, true, false);
  handles[1] = Get<TestHandle>(storageManager, "asset1", false, true, false);
  handles[2] = Get<TestHandle>(storageManager, "mutable2", false, true, true);
  handles[3] = Get<TestHandle>(storageManager, "asset3", false, true, false);
  handles[4] = Get<TestHandle>(storageManager, "mutable4", false, true, true);
  ASSERT_EQ(storageManager.CacheSize(), 5) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 2) << "Storage manager has wrong number of items in dirty map";
}

TEST_F(StorageManagerTest, SaveDirty) {
  TestHandle handles[5];
  getAssetsForDirtyTest(storageManager, handles);

  khFilesTransaction trans;
  bool result = storageManager.SaveDirtyToDotNew(trans, nullptr);
  ASSERT_TRUE(result) << "SaveDirtyToDotNew should return true when there are no issues";
  ASSERT_EQ(storageManager.CacheSize(), 5) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 0) << "Storage manager has wrong number of items in dirty map";
  ASSERT_EQ(trans.NumNew(), 2) << "Wrong number of new items in file transaction";
  ASSERT_EQ(trans.NumDeleted(), 0) << "Wrong number of deleted items in file transaction";
  ASSERT_EQ(handles[0].handle->savename, string()) << "Non-dirty files should not be saved";
  ASSERT_NE(handles[4].handle->savename, string()) << "Dirty files should be saved";
  string savename = handles[4].handle->savename;
  string ext = ".new";
  ASSERT_TRUE(equal(ext.rbegin(), ext.rend(), savename.rbegin())) << "Saved file name must end in .new";
}

TEST_F(StorageManagerTest, SaveDirtyToVector) {
  TestHandle handles[5];
  getAssetsForDirtyTest(storageManager, handles);

  khFilesTransaction trans;
  vector<SharedString> saved;
  storageManager.SaveDirtyToDotNew(trans, &saved);
  ASSERT_EQ(saved.size(), 2) << "Wrong number of items in saved vector";
  ASSERT_TRUE(find(saved.begin(), saved.end(), "mutable2") != saved.end()) << "Dirty item missing from saved vector";
  ASSERT_TRUE(find(saved.begin(), saved.end(), "mutable4") != saved.end()) << "Dirty item missing from saved vector";
}

TEST_F(StorageManagerTest, FailedSave) {
  TestHandle item = Get<TestHandle>(storageManager, "item", false, true, true);
  item.handle->saveSucceeds = false;
  khFilesTransaction trans;
  bool result = storageManager.SaveDirtyToDotNew(trans, nullptr);
  ASSERT_FALSE(result) << "SaveDirtyToDotNew should return false when a save fails";
  ASSERT_EQ(storageManager.CacheSize(), 1) << "Unexpected number of items in cache";
  ASSERT_EQ(storageManager.DirtySize(), 1) << "Storage manager has wrong number of items in dirty map";
  ASSERT_EQ(trans.NumNew(), 0) << "Transaction should be empty after failed save";
  ASSERT_EQ(trans.NumDeleted(), 0) << "Wrong number of deleted items in file transaction";
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc,argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLIndexMarkExport.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 15:06:23 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLINDEXMARKEXPORT_HXX_
#include "XMLIndexMarkExport.hxx"
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSETINFO_HPP_
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

#ifndef _XMLOFF_XMLEXP_HXX
#include "xmlexp.hxx"
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif

using namespace ::xmloff::token;

using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::beans::XPropertySetInfo;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Any;

XMLIndexMarkExport::XMLIndexMarkExport(
    SvXMLExport& rExp,
    XMLTextParagraphExport& rParaExp) :
        rExport(rExp),
        rParaExport(rParaExp),
        sLevel(RTL_CONSTASCII_USTRINGPARAM("Level")),
        sUserIndexName(RTL_CONSTASCII_USTRINGPARAM("UserIndexName")),
        sPrimaryKey(RTL_CONSTASCII_USTRINGPARAM("PrimaryKey")),
        sSecondaryKey(RTL_CONSTASCII_USTRINGPARAM("SecondaryKey")),
        sDocumentIndexMark(RTL_CONSTASCII_USTRINGPARAM("DocumentIndexMark")),
        sIsStart(RTL_CONSTASCII_USTRINGPARAM("IsStart")),
        sIsCollapsed(RTL_CONSTASCII_USTRINGPARAM("IsCollapsed")),
        sAlternativeText(RTL_CONSTASCII_USTRINGPARAM("AlternativeText")),
        sTextReading(RTL_CONSTASCII_USTRINGPARAM("TextReading")),
        sPrimaryKeyReading(RTL_CONSTASCII_USTRINGPARAM("PrimaryKeyReading")),
        sSecondaryKeyReading(RTL_CONSTASCII_USTRINGPARAM
                             ("SecondaryKeyReading")),
        sMainEntry(RTL_CONSTASCII_USTRINGPARAM("IsMainEntry"))
{
}

const enum XMLTokenEnum lcl_pTocMarkNames[] =
    { XML_TOC_MARK, XML_TOC_MARK_START, XML_TOC_MARK_END };
const enum XMLTokenEnum lcl_pUserIndexMarkName[] =
    { XML_USER_INDEX_MARK,
          XML_USER_INDEX_MARK_START, XML_USER_INDEX_MARK_END };
const enum XMLTokenEnum lcl_pAlphaIndexMarkName[] =
    { XML_ALPHABETICAL_INDEX_MARK,
          XML_ALPHABETICAL_INDEX_MARK_START,
          XML_ALPHABETICAL_INDEX_MARK_END };

XMLIndexMarkExport::~XMLIndexMarkExport()
{
}

void XMLIndexMarkExport::ExportIndexMark(
    const Reference<XPropertySet> & rPropSet,
    sal_Bool bAutoStyles)
{
    /// index marks have no styles!
    if (!bAutoStyles)
    {
        const enum XMLTokenEnum * pElements = NULL;
        sal_Int8 nElementNo = -1;

        // get index mark
        Any aAny;
        aAny = rPropSet->getPropertyValue(sDocumentIndexMark);
        Reference<XPropertySet> xIndexMarkPropSet;
        aAny >>= xIndexMarkPropSet;

        // common: handling of start, end, collapsed entries and
        // alternative text

        // collapsed/alternative text entry?
        aAny = rPropSet->getPropertyValue(sIsCollapsed);
        if (*(sal_Bool *)aAny.getValue())
        {
            // collapsed entry: needs alternative text
            nElementNo = 0;

            aAny = xIndexMarkPropSet->getPropertyValue(sAlternativeText);
            OUString sTmp;
            aAny >>= sTmp;
            DBG_ASSERT(sTmp.getLength() > 0,
                       "collapsed index mark without alternative text");
            rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_STRING_VALUE, sTmp);
        }
        else
        {
            // start and end entries: has ID
            aAny = rPropSet->getPropertyValue(sIsStart);
            nElementNo = *(sal_Bool *)aAny.getValue() ? 1 : 2;

            // generate ID
            OUStringBuffer sBuf;
            GetID(sBuf, xIndexMarkPropSet);
            rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_ID,
                                 sBuf.makeStringAndClear());
        }

        // distinguish between TOC, user, alphab. index marks by
        // asking for specific properties
        // Export attributes for -mark-start and -mark elements,
        // but not for -mark-end
        Reference<XPropertySetInfo> xPropertySetInfo =
            xIndexMarkPropSet->getPropertySetInfo();
        if (xPropertySetInfo->hasPropertyByName(sUserIndexName))
        {
            // user index mark
            pElements = lcl_pUserIndexMarkName;
            if (nElementNo != 2)
            {
                ExportUserIndexMarkAttributes(xIndexMarkPropSet);
            }
        }
        else if (xPropertySetInfo->hasPropertyByName(sPrimaryKey))
        {
            // alphabetical index mark
            pElements = lcl_pAlphaIndexMarkName;
            if (nElementNo != 2)
            {
                ExportAlphabeticalIndexMarkAttributes(xIndexMarkPropSet);
            }
        }
        else
        {
            // table of content:
            pElements = lcl_pTocMarkNames;
            if (nElementNo != 2)
            {
                ExportTOCMarkAttributes(xIndexMarkPropSet);
            }
        }

        // export element
        DBG_ASSERT(pElements != NULL, "illegal element array");
        DBG_ASSERT(nElementNo >= 0, "illegal name array index");
        DBG_ASSERT(nElementNo <= 2, "illegal name array index");

        if ((pElements != NULL) && (nElementNo != -1))
        {
            SvXMLElementExport aElem(rExport,
                                     XML_NAMESPACE_TEXT,
                                     pElements[nElementNo],
                                     sal_False, sal_False);
        }
    }
}

void XMLIndexMarkExport::ExportTOCMarkAttributes(
    const Reference<XPropertySet> & rPropSet)
{
    // outline level
    sal_Int16 nLevel;
    Any aAny = rPropSet->getPropertyValue(sLevel);
    aAny >>= nLevel;
    OUStringBuffer sBuf;
    SvXMLUnitConverter::convertNumber(sBuf, (sal_Int32)nLevel + 1);
    rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_OUTLINE_LEVEL,
                             sBuf.makeStringAndClear());
}

void lcl_ExportPropertyString( SvXMLExport& rExport,
                               const Reference<XPropertySet> & rPropSet,
                               const OUString sProperty,
                               XMLTokenEnum eToken,
                               Any& rAny )
{
    rAny = rPropSet->getPropertyValue( sProperty );

    OUString sValue;
    if( rAny >>= sValue )
    {
        if( sValue.getLength() > 0 )
        {
            rExport.AddAttribute( XML_NAMESPACE_TEXT, eToken, sValue );
        }
    }
}

void lcl_ExportPropertyBool( SvXMLExport& rExport,
                             const Reference<XPropertySet> & rPropSet,
                             const OUString sProperty,
                             XMLTokenEnum eToken,
                             Any& rAny )
{
    rAny = rPropSet->getPropertyValue( sProperty );

    sal_Bool bValue;
    if( rAny >>= bValue )
    {
        if( bValue )
        {
            rExport.AddAttribute( XML_NAMESPACE_TEXT, eToken, XML_TRUE );
        }
    }
}

void XMLIndexMarkExport::ExportUserIndexMarkAttributes(
    const Reference<XPropertySet> & rPropSet)
{
    // name of user index
    // (unless it's the default index; then it has no name)
    Any aAny;
    lcl_ExportPropertyString( rExport, rPropSet, sUserIndexName, XML_INDEX_NAME, aAny );

    // additionally export outline level; just reuse ExportTOCMarkAttributes
    ExportTOCMarkAttributes( rPropSet );
}

void XMLIndexMarkExport::ExportAlphabeticalIndexMarkAttributes(
    const Reference<XPropertySet> & rPropSet)
{
    // primary and secondary keys (if available)
    Any aAny;
    lcl_ExportPropertyString( rExport, rPropSet, sTextReading, XML_STRING_VALUE_PHONETIC, aAny );
    lcl_ExportPropertyString( rExport, rPropSet, sPrimaryKey, XML_KEY1, aAny );
    lcl_ExportPropertyString( rExport, rPropSet, sPrimaryKeyReading, XML_KEY1_PHONETIC, aAny );
    lcl_ExportPropertyString( rExport, rPropSet, sSecondaryKey, XML_KEY2, aAny );
    lcl_ExportPropertyString( rExport, rPropSet, sSecondaryKeyReading, XML_KEY2_PHONETIC, aAny );
    lcl_ExportPropertyBool( rExport, rPropSet, sMainEntry, XML_MAIN_ENTRY, aAny );
}

void XMLIndexMarkExport::GetID(
    OUStringBuffer& sBuf,
    const Reference<XPropertySet> & rPropSet)
{
    static const sal_Char sPrefix[] = "IMark";

    // HACK: use address of object to form identifier
    sal_Int64 nId = (sal_Int64)rPropSet.get();
    sBuf.appendAscii(sPrefix, sizeof(sPrefix)-1);
    sBuf.append(nId);
}
<commit_msg>INTEGRATION: CWS warnings01 (1.8.34); FILE MERGED 2005/11/03 17:47:08 cl 1.8.34.1: warning free code changes for unxlngi6<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLIndexMarkExport.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 18:40:20 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLINDEXMARKEXPORT_HXX_
#include "XMLIndexMarkExport.hxx"
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSETINFO_HPP_
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

#ifndef _XMLOFF_XMLEXP_HXX
#include "xmlexp.hxx"
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif

using namespace ::xmloff::token;

using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::beans::XPropertySetInfo;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Any;

XMLIndexMarkExport::XMLIndexMarkExport(
    SvXMLExport& rExp,
    XMLTextParagraphExport& rParaExp)
:   sLevel(RTL_CONSTASCII_USTRINGPARAM("Level"))
,   sUserIndexName(RTL_CONSTASCII_USTRINGPARAM("UserIndexName"))
,   sPrimaryKey(RTL_CONSTASCII_USTRINGPARAM("PrimaryKey"))
,   sSecondaryKey(RTL_CONSTASCII_USTRINGPARAM("SecondaryKey"))
,   sDocumentIndexMark(RTL_CONSTASCII_USTRINGPARAM("DocumentIndexMark"))
,   sIsStart(RTL_CONSTASCII_USTRINGPARAM("IsStart"))
,   sIsCollapsed(RTL_CONSTASCII_USTRINGPARAM("IsCollapsed"))
,   sAlternativeText(RTL_CONSTASCII_USTRINGPARAM("AlternativeText"))
,   sTextReading(RTL_CONSTASCII_USTRINGPARAM("TextReading"))
,   sPrimaryKeyReading(RTL_CONSTASCII_USTRINGPARAM("PrimaryKeyReading"))
,   sSecondaryKeyReading(RTL_CONSTASCII_USTRINGPARAM("SecondaryKeyReading"))
,   sMainEntry(RTL_CONSTASCII_USTRINGPARAM("IsMainEntry"))
,   rExport(rExp)
,   rParaExport(rParaExp)
{
}

const enum XMLTokenEnum lcl_pTocMarkNames[] =
    { XML_TOC_MARK, XML_TOC_MARK_START, XML_TOC_MARK_END };
const enum XMLTokenEnum lcl_pUserIndexMarkName[] =
    { XML_USER_INDEX_MARK,
          XML_USER_INDEX_MARK_START, XML_USER_INDEX_MARK_END };
const enum XMLTokenEnum lcl_pAlphaIndexMarkName[] =
    { XML_ALPHABETICAL_INDEX_MARK,
          XML_ALPHABETICAL_INDEX_MARK_START,
          XML_ALPHABETICAL_INDEX_MARK_END };

XMLIndexMarkExport::~XMLIndexMarkExport()
{
}

void XMLIndexMarkExport::ExportIndexMark(
    const Reference<XPropertySet> & rPropSet,
    sal_Bool bAutoStyles)
{
    /// index marks have no styles!
    if (!bAutoStyles)
    {
        const enum XMLTokenEnum * pElements = NULL;
        sal_Int8 nElementNo = -1;

        // get index mark
        Any aAny;
        aAny = rPropSet->getPropertyValue(sDocumentIndexMark);
        Reference<XPropertySet> xIndexMarkPropSet;
        aAny >>= xIndexMarkPropSet;

        // common: handling of start, end, collapsed entries and
        // alternative text

        // collapsed/alternative text entry?
        aAny = rPropSet->getPropertyValue(sIsCollapsed);
        if (*(sal_Bool *)aAny.getValue())
        {
            // collapsed entry: needs alternative text
            nElementNo = 0;

            aAny = xIndexMarkPropSet->getPropertyValue(sAlternativeText);
            OUString sTmp;
            aAny >>= sTmp;
            DBG_ASSERT(sTmp.getLength() > 0,
                       "collapsed index mark without alternative text");
            rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_STRING_VALUE, sTmp);
        }
        else
        {
            // start and end entries: has ID
            aAny = rPropSet->getPropertyValue(sIsStart);
            nElementNo = *(sal_Bool *)aAny.getValue() ? 1 : 2;

            // generate ID
            OUStringBuffer sBuf;
            GetID(sBuf, xIndexMarkPropSet);
            rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_ID,
                                 sBuf.makeStringAndClear());
        }

        // distinguish between TOC, user, alphab. index marks by
        // asking for specific properties
        // Export attributes for -mark-start and -mark elements,
        // but not for -mark-end
        Reference<XPropertySetInfo> xPropertySetInfo =
            xIndexMarkPropSet->getPropertySetInfo();
        if (xPropertySetInfo->hasPropertyByName(sUserIndexName))
        {
            // user index mark
            pElements = lcl_pUserIndexMarkName;
            if (nElementNo != 2)
            {
                ExportUserIndexMarkAttributes(xIndexMarkPropSet);
            }
        }
        else if (xPropertySetInfo->hasPropertyByName(sPrimaryKey))
        {
            // alphabetical index mark
            pElements = lcl_pAlphaIndexMarkName;
            if (nElementNo != 2)
            {
                ExportAlphabeticalIndexMarkAttributes(xIndexMarkPropSet);
            }
        }
        else
        {
            // table of content:
            pElements = lcl_pTocMarkNames;
            if (nElementNo != 2)
            {
                ExportTOCMarkAttributes(xIndexMarkPropSet);
            }
        }

        // export element
        DBG_ASSERT(pElements != NULL, "illegal element array");
        DBG_ASSERT(nElementNo >= 0, "illegal name array index");
        DBG_ASSERT(nElementNo <= 2, "illegal name array index");

        if ((pElements != NULL) && (nElementNo != -1))
        {
            SvXMLElementExport aElem(rExport,
                                     XML_NAMESPACE_TEXT,
                                     pElements[nElementNo],
                                     sal_False, sal_False);
        }
    }
}

void XMLIndexMarkExport::ExportTOCMarkAttributes(
    const Reference<XPropertySet> & rPropSet)
{
    // outline level
    sal_Int16 nLevel;
    Any aAny = rPropSet->getPropertyValue(sLevel);
    aAny >>= nLevel;
    OUStringBuffer sBuf;
    SvXMLUnitConverter::convertNumber(sBuf, (sal_Int32)nLevel + 1);
    rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_OUTLINE_LEVEL,
                             sBuf.makeStringAndClear());
}

void lcl_ExportPropertyString( SvXMLExport& rExport,
                               const Reference<XPropertySet> & rPropSet,
                               const OUString sProperty,
                               XMLTokenEnum eToken,
                               Any& rAny )
{
    rAny = rPropSet->getPropertyValue( sProperty );

    OUString sValue;
    if( rAny >>= sValue )
    {
        if( sValue.getLength() > 0 )
        {
            rExport.AddAttribute( XML_NAMESPACE_TEXT, eToken, sValue );
        }
    }
}

void lcl_ExportPropertyBool( SvXMLExport& rExport,
                             const Reference<XPropertySet> & rPropSet,
                             const OUString sProperty,
                             XMLTokenEnum eToken,
                             Any& rAny )
{
    rAny = rPropSet->getPropertyValue( sProperty );

    sal_Bool bValue;
    if( rAny >>= bValue )
    {
        if( bValue )
        {
            rExport.AddAttribute( XML_NAMESPACE_TEXT, eToken, XML_TRUE );
        }
    }
}

void XMLIndexMarkExport::ExportUserIndexMarkAttributes(
    const Reference<XPropertySet> & rPropSet)
{
    // name of user index
    // (unless it's the default index; then it has no name)
    Any aAny;
    lcl_ExportPropertyString( rExport, rPropSet, sUserIndexName, XML_INDEX_NAME, aAny );

    // additionally export outline level; just reuse ExportTOCMarkAttributes
    ExportTOCMarkAttributes( rPropSet );
}

void XMLIndexMarkExport::ExportAlphabeticalIndexMarkAttributes(
    const Reference<XPropertySet> & rPropSet)
{
    // primary and secondary keys (if available)
    Any aAny;
    lcl_ExportPropertyString( rExport, rPropSet, sTextReading, XML_STRING_VALUE_PHONETIC, aAny );
    lcl_ExportPropertyString( rExport, rPropSet, sPrimaryKey, XML_KEY1, aAny );
    lcl_ExportPropertyString( rExport, rPropSet, sPrimaryKeyReading, XML_KEY1_PHONETIC, aAny );
    lcl_ExportPropertyString( rExport, rPropSet, sSecondaryKey, XML_KEY2, aAny );
    lcl_ExportPropertyString( rExport, rPropSet, sSecondaryKeyReading, XML_KEY2_PHONETIC, aAny );
    lcl_ExportPropertyBool( rExport, rPropSet, sMainEntry, XML_MAIN_ENTRY, aAny );
}

void XMLIndexMarkExport::GetID(
    OUStringBuffer& sBuf,
    const Reference<XPropertySet> & rPropSet)
{
    static const sal_Char sPrefix[] = "IMark";

    // HACK: use address of object to form identifier
    sal_Int64 nId = sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_uIntPtr>(rPropSet.get()));
    sBuf.appendAscii(sPrefix, sizeof(sPrefix)-1);
    sBuf.append(nId);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLTextNumRuleInfo.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: rt $ $Date: 2008-03-12 11:05:35 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XINDEXREPLACE_HPP_
#include <com/sun/star/container/XIndexReplace.hpp>
#endif
#ifndef _COM_SUN_STAR_STYLE_NUMBERINGTYPE_HPP_
#include <com/sun/star/style/NumberingType.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMED_HPP_
#include <com/sun/star/container/XNamed.hpp>
#endif

#ifndef _XMLOFF_XMLTEXTNUMRULEINFO_HXX
#include "XMLTextNumRuleInfo.hxx"
#endif

using ::rtl::OUString;

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::style;

XMLTextNumRuleInfo::XMLTextNumRuleInfo() :
    sNumberingRules(RTL_CONSTASCII_USTRINGPARAM("NumberingRules")),
    sNumberingLevel(RTL_CONSTASCII_USTRINGPARAM("NumberingLevel")),
    sNumberingStartValue(RTL_CONSTASCII_USTRINGPARAM("NumberingStartValue")),
    sParaIsNumberingRestart(RTL_CONSTASCII_USTRINGPARAM("ParaIsNumberingRestart")),
    sNumberingType(RTL_CONSTASCII_USTRINGPARAM("NumberingType")),
    sIsNumbering(RTL_CONSTASCII_USTRINGPARAM("IsNumbering")),
    sNumberingIsNumber(RTL_CONSTASCII_USTRINGPARAM("NumberingIsNumber")),
    sNumberingIsOutline(RTL_CONSTASCII_USTRINGPARAM("NumberingIsOutline"))
{
    Reset();
}

// --> OD 2006-09-27 #i69627#
void XMLTextNumRuleInfo::Set(
        const ::com::sun::star::uno::Reference <
                        ::com::sun::star::text::XTextContent > & xTextContent,
        const sal_Bool bOutlineStyleAsNormalListStyle )
{
    Reset();
    // --> OD 2006-09-27 #i69627#
    mbOutlineStyleAsNormalListStyle = bOutlineStyleAsNormalListStyle;
    // <--

    Reference< XPropertySet > xPropSet( xTextContent, UNO_QUERY );
    Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();

    Any aAny;

    // check if this paragraph supports a numbering
    if( !xPropSetInfo->hasPropertyByName( sNumberingLevel ) )
        return;

    if( xPropSetInfo->hasPropertyByName( sNumberingRules ) )
    {
        aAny = xPropSet->getPropertyValue( sNumberingRules );
        aAny >>= xNumRules;
    }

    // --> OD 2006-09-27 #i69627#
    bool bSuppressListStyle( false );
    {
        if ( !mbOutlineStyleAsNormalListStyle )
        {
            BOOL bIsOutline = FALSE;
            Reference<XPropertySet> xNumRulesProps(xNumRules, UNO_QUERY);
            if (xNumRulesProps.is() &&
                xNumRulesProps->getPropertySetInfo()->
                hasPropertyByName( sNumberingIsOutline ) )
            {
                aAny = xNumRulesProps->getPropertyValue( sNumberingIsOutline );
                bIsOutline = *(sal_Bool*)aAny.getValue();
                bSuppressListStyle = bIsOutline ? true : false;
            }
        }
    }

    if( xNumRules.is() && !bSuppressListStyle )
    // <--
    {
        Reference < XNamed > xNamed( xNumRules, UNO_QUERY );
        if( xNamed.is() )
        {
            bIsNamed = sal_True;
            sName = xNamed->getName();
        }

        aAny = xPropSet->getPropertyValue( sNumberingLevel );
        aAny >>= nLevel;

        bIsNumbered = sal_True;
        if( xPropSetInfo->hasPropertyByName( sNumberingIsNumber ) )
        {
            aAny = xPropSet->getPropertyValue( sNumberingIsNumber );
            OSL_ENSURE( aAny.hasValue(),
                        "numbered paragraph without number info" );
            if( !aAny.hasValue() )
                bIsNumbered = sal_False;
            else
                bIsNumbered = *(sal_Bool *)aAny.getValue();
        }

        if( bIsNumbered )
        {
            if( xPropSetInfo->hasPropertyByName( sParaIsNumberingRestart ) )
            {
                aAny = xPropSet->getPropertyValue( sParaIsNumberingRestart );
                bIsRestart = *(sal_Bool *)aAny.getValue();
            }
            if( xPropSetInfo->hasPropertyByName( sNumberingStartValue ) )
            {
                aAny = xPropSet->getPropertyValue( sNumberingStartValue );
                aAny >>= nStartValue;
            }
        }

        OSL_ENSURE( nLevel < xNumRules->getCount(), "wrong num rule level" );
        if( nLevel >= xNumRules->getCount() )
        {
            Reset();
            return;
        }

        aAny = xNumRules->getByIndex( nLevel );
        Sequence<PropertyValue> aProps;
        aAny >>= aProps;
        const PropertyValue* pPropArray = aProps.getConstArray();
        sal_Int32 nCount = aProps.getLength();
        for( sal_Int32 i=0; i<nCount; i++ )
        {
            const beans::PropertyValue& rProp = pPropArray[i];

            if( rProp.Name == sNumberingType )
            {
                sal_Int16 nType = 0;
                rProp.Value >>= nType;
                if( NumberingType::CHAR_SPECIAL != nType &&
                    NumberingType::BITMAP != nType )
                {
                    bIsOrdered = sal_True;
                }
                break;
            }
        }
        nLevel++;
    }
}

<commit_msg>INTEGRATION: CWS changefileheader (1.12.18); FILE MERGED 2008/04/01 16:10:11 thb 1.12.18.3: #i85898# Stripping all external header guards 2008/04/01 13:05:32 thb 1.12.18.2: #i85898# Stripping all external header guards 2008/03/31 16:28:37 rt 1.12.18.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: XMLTextNumRuleInfo.cxx,v $
 * $Revision: 1.13 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"
#include <tools/debug.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/container/XIndexReplace.hpp>
#include <com/sun/star/style/NumberingType.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include "XMLTextNumRuleInfo.hxx"

using ::rtl::OUString;

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::style;

XMLTextNumRuleInfo::XMLTextNumRuleInfo() :
    sNumberingRules(RTL_CONSTASCII_USTRINGPARAM("NumberingRules")),
    sNumberingLevel(RTL_CONSTASCII_USTRINGPARAM("NumberingLevel")),
    sNumberingStartValue(RTL_CONSTASCII_USTRINGPARAM("NumberingStartValue")),
    sParaIsNumberingRestart(RTL_CONSTASCII_USTRINGPARAM("ParaIsNumberingRestart")),
    sNumberingType(RTL_CONSTASCII_USTRINGPARAM("NumberingType")),
    sIsNumbering(RTL_CONSTASCII_USTRINGPARAM("IsNumbering")),
    sNumberingIsNumber(RTL_CONSTASCII_USTRINGPARAM("NumberingIsNumber")),
    sNumberingIsOutline(RTL_CONSTASCII_USTRINGPARAM("NumberingIsOutline"))
{
    Reset();
}

// --> OD 2006-09-27 #i69627#
void XMLTextNumRuleInfo::Set(
        const ::com::sun::star::uno::Reference <
                        ::com::sun::star::text::XTextContent > & xTextContent,
        const sal_Bool bOutlineStyleAsNormalListStyle )
{
    Reset();
    // --> OD 2006-09-27 #i69627#
    mbOutlineStyleAsNormalListStyle = bOutlineStyleAsNormalListStyle;
    // <--

    Reference< XPropertySet > xPropSet( xTextContent, UNO_QUERY );
    Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();

    Any aAny;

    // check if this paragraph supports a numbering
    if( !xPropSetInfo->hasPropertyByName( sNumberingLevel ) )
        return;

    if( xPropSetInfo->hasPropertyByName( sNumberingRules ) )
    {
        aAny = xPropSet->getPropertyValue( sNumberingRules );
        aAny >>= xNumRules;
    }

    // --> OD 2006-09-27 #i69627#
    bool bSuppressListStyle( false );
    {
        if ( !mbOutlineStyleAsNormalListStyle )
        {
            BOOL bIsOutline = FALSE;
            Reference<XPropertySet> xNumRulesProps(xNumRules, UNO_QUERY);
            if (xNumRulesProps.is() &&
                xNumRulesProps->getPropertySetInfo()->
                hasPropertyByName( sNumberingIsOutline ) )
            {
                aAny = xNumRulesProps->getPropertyValue( sNumberingIsOutline );
                bIsOutline = *(sal_Bool*)aAny.getValue();
                bSuppressListStyle = bIsOutline ? true : false;
            }
        }
    }

    if( xNumRules.is() && !bSuppressListStyle )
    // <--
    {
        Reference < XNamed > xNamed( xNumRules, UNO_QUERY );
        if( xNamed.is() )
        {
            bIsNamed = sal_True;
            sName = xNamed->getName();
        }

        aAny = xPropSet->getPropertyValue( sNumberingLevel );
        aAny >>= nLevel;

        bIsNumbered = sal_True;
        if( xPropSetInfo->hasPropertyByName( sNumberingIsNumber ) )
        {
            aAny = xPropSet->getPropertyValue( sNumberingIsNumber );
            OSL_ENSURE( aAny.hasValue(),
                        "numbered paragraph without number info" );
            if( !aAny.hasValue() )
                bIsNumbered = sal_False;
            else
                bIsNumbered = *(sal_Bool *)aAny.getValue();
        }

        if( bIsNumbered )
        {
            if( xPropSetInfo->hasPropertyByName( sParaIsNumberingRestart ) )
            {
                aAny = xPropSet->getPropertyValue( sParaIsNumberingRestart );
                bIsRestart = *(sal_Bool *)aAny.getValue();
            }
            if( xPropSetInfo->hasPropertyByName( sNumberingStartValue ) )
            {
                aAny = xPropSet->getPropertyValue( sNumberingStartValue );
                aAny >>= nStartValue;
            }
        }

        OSL_ENSURE( nLevel < xNumRules->getCount(), "wrong num rule level" );
        if( nLevel >= xNumRules->getCount() )
        {
            Reset();
            return;
        }

        aAny = xNumRules->getByIndex( nLevel );
        Sequence<PropertyValue> aProps;
        aAny >>= aProps;
        const PropertyValue* pPropArray = aProps.getConstArray();
        sal_Int32 nCount = aProps.getLength();
        for( sal_Int32 i=0; i<nCount; i++ )
        {
            const beans::PropertyValue& rProp = pPropArray[i];

            if( rProp.Name == sNumberingType )
            {
                sal_Int16 nType = 0;
                rProp.Value >>= nType;
                if( NumberingType::CHAR_SPECIAL != nType &&
                    NumberingType::BITMAP != nType )
                {
                    bIsOrdered = sal_True;
                }
                break;
            }
        }
        nLevel++;
    }
}

<|endoftext|>