<commit_before>/*************************************************************************
 *
 *  $RCSfile: providerimpl.hxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-19 16:18:36 $
 *
 *  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 CONFIGMGR_API_PROVIDERIMPL_HXX_
#define CONFIGMGR_API_PROVIDERIMPL_HXX_

#ifndef CONFIGMGR_TREEPROVIDER_HXX
#include "treeprovider.hxx"
#endif
#ifndef CONFIGMGR_DEFAULTPROVIDER_HXX
#include "defaultprovider.hxx"
#endif
#ifndef _CONFIGMGR_COMMONTYPES_HXX_
#include "commontypes.hxx" // IInterface
#endif

#ifndef CONFIGMGR_MISC_REQUESTOPTIONS_HXX_
#include "requestoptions.hxx"
#endif

#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif
#ifndef _COM_SUN_STAR_SCRIPT_XTYPECONVERTER_HPP_
#include <com/sun/star/script/XTypeConverter.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XEVENTLISTENER_HPP_
#include <com/sun/star/lang/XEventListener.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

namespace com { namespace sun { namespace star {
    namespace uno
    {
        class Any;
        class XInterface;
        template <class> class Sequence;
        template <class> class Reference;
    }
    namespace beans
    {
        struct PropertyValue;
    }
}   }   }

namespace rtl
{
    class OUString;
    template <class RCType> class Reference;
}

namespace configmgr
{
    namespace css       = ::com::sun::star;
    namespace uno       = css::uno;
    namespace script    = css::script;
    namespace lang      = css::lang;
    namespace beans     = css::beans;
    using ::rtl::OUString;

    class ISubtree;
    class ITemplateManager;
    class IConfigDefaultProvider;
    class TreeManager;
    class ContextReader;

    struct IConfigBroadcaster;

    namespace configapi
    {
        class NodeElement;
        class ApiProviderInstances;
        class Factory;
    }

    // -----------------------------------------------------------------------------
    class OProviderImpl : public ITreeManager, public IDefaultableTreeManager, public IInterface
    {
        friend class OProvider;
        OProvider*                          m_pProvider;        /// used for ref counting, uno representation
    public:
        //==========================================================================
        //= FactoryArguments
        //==========================================================================
        /** Helper class for evaluation of the arguments for creating a service instance.*/
        struct FactoryArguments
        {
            /// possible arguments, given only in small letters.
            enum Argument
            {
                ARG_NODEPATH,           // requested node path
                ARG_DEPTH,              // depth of the tree
                ARG_USER_DEPRECATED,    // name of the entity to be manipulated - deprecated version
                ARG_LOCALE,             // desired locale
                ARG_NOCACHE_OBSOLETE,   // cache disabling - obsolete and nonfunctional
                ARG_ASYNC_DEPRECATED,   // lasy write data - deprecated version
                ARG_ASYNC,              // lazy write data
                ARG_ENTITY,             // name of the entity to be manipulated - only for admin

                _arg_count,
                ARG_NOT_FOUND = _arg_count
            };
            static sal_Char const * const asciiArgumentNames[];

            static OUString getArgumentName(Argument _which)                CFG_NOTHROW();
            static Argument lookupArgument(OUString const& sArgumentName)   CFG_NOTHROW();

            static OUString getUserArgumentNameD()              CFG_NOTHROW() { return getArgumentName(ARG_USER_DEPRECATED);     }
            static OUString getEntityArgumentName()             CFG_NOTHROW() { return getArgumentName(ARG_ENTITY);     }
            static OUString getNodePathArgumentName()           CFG_NOTHROW() { return getArgumentName(ARG_NODEPATH); }
            static OUString getDepthArgumentNameArgumentName()  CFG_NOTHROW() { return getArgumentName(ARG_DEPTH);    }
            static OUString getLocaleArgumentName()             CFG_NOTHROW() { return getArgumentName(ARG_LOCALE);   }
            static OUString getNoCacheArgumentNameD()           CFG_NOTHROW() { return getArgumentName(ARG_NOCACHE_OBSOLETE);  }
            static OUString getAsyncArgumentName()              CFG_NOTHROW() { return getArgumentName(ARG_ASYNC);    }
        public:
            /** extracts arguments from the argument sequence into to the parameter variables

unknown arguments are ignored

                @throws com::sun::star::lang::IllegalArgumentException
                    if an element of _rArgs had the wrong type or
                    if the value of a known argument has the wrong type or
                    if the value of a known argument is out of range (sometimes)
                    or if no non-empty node path argument could be extracted,
            */
            static void extractArgs(    const uno::Sequence<uno::Any>& _rArgs,
                                        OUString&   /* [out] */ _rNodeAccessor,
                                        sal_Int32&  /* [out] */ _nLevels,
                                        RequestOptions& /* [in/out] */ xOptions
                                   ) CFG_THROW1(lang::IllegalArgumentException);

            static bool extractOneArgument( OUString const& aName, uno::Any const& aValue,
                                            OUString&   /* [out] */ _rNodeAccessor,
                                            sal_Int32&  /* [out] */ _nLevels,
                                            RequestOptions& /* [in/out] */ xOptions
                                          ) CFG_NOTHROW();

        };

    public:
        typedef uno::Reference< uno::XComponentContext >        CreationContext;
        typedef uno::Reference< script::XTypeConverter >        TypeConverterRef;
    private:
        TypeConverterRef                    m_xTypeConverter;
        RequestOptions                      m_aDefaultOptions;
        configapi::ApiProviderInstances*    m_pNewProviders;    /// order depedency - this must be after the TreeManager
        mutable osl::Mutex                  m_aTreeManagerMutex;
        TreeManager*                        m_pTreeManager;     /// the tree cache. Will hold a reference to us as long as it life

        rtl::Reference< TreeManager > maybeGetTreeManager() const CFG_NOTHROW();
        rtl::Reference< TreeManager > getTreeManager() const CFG_UNO_THROW_RTE();
        void setTreeManager(TreeManager * pTreeManager) CFG_UNO_THROW_RTE();
        void clearTreeManager() CFG_NOTHROW();
    public:
        OProviderImpl(OProvider* _pProvider, CreationContext const & _xContext);

        virtual ~OProviderImpl();

        /// ITreeManager
        virtual memory::Segment* getDataSegment(AbsolutePath const& _rAccessor, const RequestOptions& _aOptions);
        virtual data::NodeAccess requestSubtree(AbsolutePath const& aSubtreePath, const RequestOptions& _aOptions) CFG_UNO_THROW_ALL(  );
        virtual void updateTree(memory::UpdateAccessor& _aAccessToken, TreeChangeList& aChanges) CFG_UNO_THROW_ALL(  );

        virtual void releaseSubtree( AbsolutePath const& aSubtreePath, const RequestOptions& _aOptions ) CFG_NOTHROW();
        virtual void saveAndNotifyUpdate(memory::Accessor const& _aChangedDataAccessor, TreeChangeList const& aChanges) CFG_UNO_THROW_ALL(  );
        virtual void disposeData(const RequestOptions& _aOptions) CFG_NOTHROW();
        virtual void fetchSubtree(AbsolutePath const& aSubtreePath, const RequestOptions& _aOptions) CFG_NOTHROW();
        /// IDefaultableTreeManager
        virtual sal_Bool fetchDefaultData(  memory::UpdateAccessor& _aAccessToken,
                                            AbsolutePath const& aSubtreePath, const RequestOptions& _aOptions
                                          ) CFG_UNO_THROW_ALL(  );

        // IInterface
        virtual void SAL_CALL acquire(  ) throw ();
        virtual void SAL_CALL release(  ) throw ();

        // DefaultProvider access
        rtl::Reference< IConfigDefaultProvider >  getDefaultProvider() const CFG_UNO_THROW_RTE( );

        // TemplateManager access
        rtl::Reference< IConfigTemplateManager >  getTemplateProvider() const CFG_UNO_THROW_RTE( );

    protected:
        static OUString getErrorMessage(AbsolutePath const& _rAccessor, const RequestOptions& _aOptions);

        virtual void SAL_CALL dispose() throw();
    public:
        RequestOptions const& getDefaultOptions() const {return m_aDefaultOptions;}
        TypeConverterRef getTypeConverter() const {return m_xTypeConverter;}
        configapi::Factory& getWriterFactory();
        IConfigBroadcaster* getNotifier() CFG_NOTHROW();
        uno::XInterface*    getProviderInstance();

        // actual factory methods
        // the returned object (if any) has to be acquired once)
        configapi::NodeElement* buildReadAccess( OUString const& _rAccessor, const RequestOptions& _aOptions, sal_Int32 nMinLevels) CFG_UNO_THROW_ALL(  );
        // the returned object (if any) has to be acquired once)
        configapi::NodeElement* buildUpdateAccess(OUString const& _rAccessor, const RequestOptions& _aOptions, sal_Int32 nMinLevels) CFG_UNO_THROW_ALL(  );

    private:
        bool initSession(const ContextReader& _rSettings);
    private:
        void implInitFromSettings(const ContextReader& _rSettings, bool& rNeedProfile);
        void implInitFromProfile(data::NodeAccess const& aProfile);

        virtual void initFromSettings(const ContextReader& _rSettings, bool& rNeedProfile);
        virtual void initFromProfile(data::NodeAccess const& aProfile);
    };
} // namespace configmgr

#endif // CONFIGMGR_API_PROVIDERIMPL_HXX_

<commit_msg>INTEGRATION: CWS networker2 (1.12.78); FILE MERGED 2003/12/18 11:49:37 jb 1.12.78.1: #i23603# Add XLocalized to configuration provider; change requestoptions and localehelper to use UNO Locale objects internally.<commit_after>/*************************************************************************
 *
 *  $RCSfile: providerimpl.hxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: obo $ $Date: 2004-01-20 16:24:15 $
 *
 *  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 CONFIGMGR_API_PROVIDERIMPL_HXX_
#define CONFIGMGR_API_PROVIDERIMPL_HXX_

#ifndef CONFIGMGR_TREEPROVIDER_HXX
#include "treeprovider.hxx"
#endif
#ifndef CONFIGMGR_DEFAULTPROVIDER_HXX
#include "defaultprovider.hxx"
#endif
#ifndef _CONFIGMGR_COMMONTYPES_HXX_
#include "commontypes.hxx" // IInterface
#endif

#ifndef CONFIGMGR_MISC_REQUESTOPTIONS_HXX_
#include "requestoptions.hxx"
#endif

#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif
#ifndef _COM_SUN_STAR_SCRIPT_XTYPECONVERTER_HPP_
#include <com/sun/star/script/XTypeConverter.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XEVENTLISTENER_HPP_
#include <com/sun/star/lang/XEventListener.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

namespace com { namespace sun { namespace star {
    namespace uno
    {
        class Any;
        class XInterface;
        template <class> class Sequence;
        template <class> class Reference;
    }
    namespace beans
    {
        struct PropertyValue;
    }
}   }   }

namespace rtl
{
    class OUString;
    template <class RCType> class Reference;
}

namespace configmgr
{
    namespace css       = ::com::sun::star;
    namespace uno       = css::uno;
    namespace script    = css::script;
    namespace lang      = css::lang;
    namespace beans     = css::beans;
    using ::rtl::OUString;

    class ISubtree;
    class ITemplateManager;
    class IConfigDefaultProvider;
    class TreeManager;
    class ContextReader;

    struct IConfigBroadcaster;

    namespace configapi
    {
        class NodeElement;
        class ApiProviderInstances;
        class Factory;
    }

    // -----------------------------------------------------------------------------
    class OProviderImpl : public ITreeManager, public IDefaultableTreeManager, public IInterface
    {
        friend class OProvider;
        OProvider*                          m_pProvider;        /// used for ref counting, uno representation
    public:
        //==========================================================================
        //= FactoryArguments
        //==========================================================================
        /** Helper class for evaluation of the arguments for creating a service instance.*/
        struct FactoryArguments
        {
            /// possible arguments, given only in small letters.
            enum Argument
            {
                ARG_NODEPATH,           // requested node path
                ARG_DEPTH,              // depth of the tree
                ARG_USER_DEPRECATED,    // name of the entity to be manipulated - deprecated version
                ARG_LOCALE,             // desired locale
                ARG_NOCACHE_OBSOLETE,   // cache disabling - obsolete and nonfunctional
                ARG_ASYNC_DEPRECATED,   // lasy write data - deprecated version
                ARG_ASYNC,              // lazy write data
                ARG_ENTITY,             // name of the entity to be manipulated - only for admin

                _arg_count,
                ARG_NOT_FOUND = _arg_count
            };
            static sal_Char const * const asciiArgumentNames[];

            static OUString getArgumentName(Argument _which)                CFG_NOTHROW();
            static Argument lookupArgument(OUString const& sArgumentName)   CFG_NOTHROW();

            static OUString getUserArgumentNameD()              CFG_NOTHROW() { return getArgumentName(ARG_USER_DEPRECATED);     }
            static OUString getEntityArgumentName()             CFG_NOTHROW() { return getArgumentName(ARG_ENTITY);     }
            static OUString getNodePathArgumentName()           CFG_NOTHROW() { return getArgumentName(ARG_NODEPATH); }
            static OUString getDepthArgumentNameArgumentName()  CFG_NOTHROW() { return getArgumentName(ARG_DEPTH);    }
            static OUString getLocaleArgumentName()             CFG_NOTHROW() { return getArgumentName(ARG_LOCALE);   }
            static OUString getNoCacheArgumentNameD()           CFG_NOTHROW() { return getArgumentName(ARG_NOCACHE_OBSOLETE);  }
            static OUString getAsyncArgumentName()              CFG_NOTHROW() { return getArgumentName(ARG_ASYNC);    }
        public:
            /** extracts arguments from the argument sequence into to the parameter variables

unknown arguments are ignored

                @throws com::sun::star::lang::IllegalArgumentException
                    if an element of _rArgs had the wrong type or
                    if the value of a known argument has the wrong type or
                    if the value of a known argument is out of range (sometimes)
                    or if no non-empty node path argument could be extracted,
            */
            static void extractArgs(    const uno::Sequence<uno::Any>& _rArgs,
                                        OUString&   /* [out] */ _rNodeAccessor,
                                        sal_Int32&  /* [out] */ _nLevels,
                                        RequestOptions& /* [in/out] */ xOptions
                                   ) CFG_THROW1(lang::IllegalArgumentException);

            static bool extractOneArgument( OUString const& aName, uno::Any const& aValue,
                                            OUString&   /* [out] */ _rNodeAccessor,
                                            sal_Int32&  /* [out] */ _nLevels,
                                            RequestOptions& /* [in/out] */ xOptions
                                          ) CFG_NOTHROW();

        };

    public:
        typedef uno::Reference< uno::XComponentContext >        CreationContext;
        typedef uno::Reference< script::XTypeConverter >        TypeConverterRef;
    private:
        TypeConverterRef                    m_xTypeConverter;
        RequestOptions                      m_aDefaultOptions;
        configapi::ApiProviderInstances*    m_pNewProviders;    /// order depedency - this must be after the TreeManager
        mutable osl::Mutex                  m_aTreeManagerMutex;
        TreeManager*                        m_pTreeManager;     /// the tree cache. Will hold a reference to us as long as it life

        rtl::Reference< TreeManager > maybeGetTreeManager() const CFG_NOTHROW();
        rtl::Reference< TreeManager > getTreeManager() const CFG_UNO_THROW_RTE();
        void setTreeManager(TreeManager * pTreeManager) CFG_UNO_THROW_RTE();
        void clearTreeManager() CFG_NOTHROW();
    public:
        OProviderImpl(OProvider* _pProvider, CreationContext const & _xContext);

        virtual ~OProviderImpl();

        /// ITreeManager
        virtual memory::Segment* getDataSegment(AbsolutePath const& _rAccessor, const RequestOptions& _aOptions);
        virtual data::NodeAccess requestSubtree(AbsolutePath const& aSubtreePath, const RequestOptions& _aOptions) CFG_UNO_THROW_ALL(  );
        virtual void updateTree(memory::UpdateAccessor& _aAccessToken, TreeChangeList& aChanges) CFG_UNO_THROW_ALL(  );

        virtual void releaseSubtree( AbsolutePath const& aSubtreePath, const RequestOptions& _aOptions ) CFG_NOTHROW();
        virtual void saveAndNotifyUpdate(memory::Accessor const& _aChangedDataAccessor, TreeChangeList const& aChanges) CFG_UNO_THROW_ALL(  );
        virtual void disposeData(const RequestOptions& _aOptions) CFG_NOTHROW();
        virtual void fetchSubtree(AbsolutePath const& aSubtreePath, const RequestOptions& _aOptions) CFG_NOTHROW();
        /// IDefaultableTreeManager
        virtual sal_Bool fetchDefaultData(  memory::UpdateAccessor& _aAccessToken,
                                            AbsolutePath const& aSubtreePath, const RequestOptions& _aOptions
                                          ) CFG_UNO_THROW_ALL(  );

        // IInterface
        virtual void SAL_CALL acquire(  ) throw ();
        virtual void SAL_CALL release(  ) throw ();

        // DefaultProvider access
        rtl::Reference< IConfigDefaultProvider >  getDefaultProvider() const CFG_UNO_THROW_RTE( );

        // TemplateManager access
        rtl::Reference< IConfigTemplateManager >  getTemplateProvider() const CFG_UNO_THROW_RTE( );

    protected:
        static OUString getErrorMessage(AbsolutePath const& _rAccessor, const RequestOptions& _aOptions);

        virtual void SAL_CALL dispose() throw();
    public:
        void setDefaultLocale( RequestOptions::Locale const & aLocale );

        RequestOptions const& getDefaultOptions() const {return m_aDefaultOptions;}
        TypeConverterRef getTypeConverter() const {return m_xTypeConverter;}
        configapi::Factory& getWriterFactory();
        IConfigBroadcaster* getNotifier() CFG_NOTHROW();
        uno::XInterface*    getProviderInstance();

        // actual factory methods
        // the returned object (if any) has to be acquired once)
        configapi::NodeElement* buildReadAccess( OUString const& _rAccessor, const RequestOptions& _aOptions, sal_Int32 nMinLevels) CFG_UNO_THROW_ALL(  );
        // the returned object (if any) has to be acquired once)
        configapi::NodeElement* buildUpdateAccess(OUString const& _rAccessor, const RequestOptions& _aOptions, sal_Int32 nMinLevels) CFG_UNO_THROW_ALL(  );

    private:
        bool initSession(const ContextReader& _rSettings);
    private:
        void implInitFromSettings(const ContextReader& _rSettings, bool& rNeedProfile);
        void implInitFromProfile(data::NodeAccess const& aProfile);

        virtual void initFromSettings(const ContextReader& _rSettings, bool& rNeedProfile);
        virtual void initFromProfile(data::NodeAccess const& aProfile);
    };
} // namespace configmgr

#endif // CONFIGMGR_API_PROVIDERIMPL_HXX_

<|endoftext|>


<commit_before>#ifndef ALEPH_GEOMETRY_RIPS_EXPANDER_TOP_DOWN_HH__
#define ALEPH_GEOMETRY_RIPS_EXPANDER_TOP_DOWN_HH__

#include <list>
#include <vector>

#include "topology/MaximalCliques.hh"

namespace aleph
{

namespace geometry
{

template <class SimplicialComplex> class RipsExpanderTopDown
{
public:
  using Simplex           = typename SimplicialComplex::ValueType;
  using DataType          = typename Simplex::DataType;
  using VertexType        = typename Simplex::VertexType;

  SimplicialComplex operator()( const SimplicialComplex& K, unsigned kMax )
  {
    return this->operator()( K, kMax, 0 );
  }

  SimplicialComplex operator()( const SimplicialComplex& K, unsigned kMax, unsigned kMin )
  {
    (void) kMax;
    (void) kMin;

    auto maximalCliques = aleph::topology::maximalCliquesKoch( K );

    std::list<Simplex> simplices;

    for( auto&& clique : maximalCliques )
      simplices.push_back( Simplex( clique.begin(), clique.end() ) );

    return SimplicialComplex( simplices.begin(), simplices.end() );
  }
};

} // namespace geometry

} // namespace aleph

#endif
<commit_msg>Generating all combinations of maximal simplices<commit_after>#ifndef ALEPH_GEOMETRY_RIPS_EXPANDER_TOP_DOWN_HH__
#define ALEPH_GEOMETRY_RIPS_EXPANDER_TOP_DOWN_HH__

#include <algorithm>
#include <list>
#include <vector>

#include "topology/MaximalCliques.hh"

namespace aleph
{

namespace geometry
{

namespace detail
{

/*
  Originally written by Thomas Draper for an article of Mark Nelson in the
  C/C++ users journal. See

    http://marknelson.us/2002/03/01/next-permutation/

  for more information.
*/

template <class Iterator> bool next_combination( const Iterator first, Iterator k, const Iterator last )
{
  if( first == last || first == k || last == k )
    return false;

  auto itr1 = first;
  auto itr2 = last;
  ++itr1;

  if(last == itr1)
    return false;

  itr1 = last;
  --itr1;
  itr1 = k;
  --itr2;

  while( first != itr1 )
  {
    if( *--itr1 < *itr2 )
    {
      auto j = k;
      while( !(*itr1 < *j) )
        ++j;

      std::iter_swap( itr1, j );

      ++itr1;
      ++j;
      itr2 = k;

      std::rotate( itr1, j, last );

      while( last != j )
      {
        ++j;
        ++itr2;
      }

      std::rotate( k, itr2, last );
      return true;
    }
  }

  std::rotate( first, k, last );
  return false;
}

} // namespace detail

template <class SimplicialComplex> class RipsExpanderTopDown
{
public:
  using Simplex           = typename SimplicialComplex::ValueType;
  using DataType          = typename Simplex::DataType;
  using VertexType        = typename Simplex::VertexType;

  SimplicialComplex operator()( const SimplicialComplex& K, unsigned kMax )
  {
    return this->operator()( K, kMax, 1 );
  }

  SimplicialComplex operator()( const SimplicialComplex& K, unsigned kMax, unsigned kMin )
  {
    auto maximalCliques = aleph::topology::maximalCliquesKoch( K );

    std::list<Simplex> simplices;

    for( auto&& clique : maximalCliques )
    {
      auto C = std::vector<VertexType>( clique.begin(), clique.end() );

      for( unsigned k = kMin; k <= std::min( kMax, unsigned( C.size() ) ); k++ )
      {
        do
        {
          simplices.push_back( Simplex( C.begin(), C.begin() + k ) );
        }
        while( detail::next_combination( C.begin(), C.begin() + k, C.end() ) );
      }

    }

    return SimplicialComplex( simplices.begin(), simplices.end() );
  }
};

} // namespace geometry

} // namespace aleph

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: treefragment.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2002-02-19 13:09:06 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#include "treefragment.hxx"

#ifndef CONFIGMGR_CONFIGURATION_ATTRIBUTES_HXX_
#include "attributes.hxx"
#endif

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

namespace configmgr
{
//-----------------------------------------------------------------------------
    namespace sharable
    {
//-----------------------------------------------------------------------------
rtl::OUString TreeFragment::getName(memory::Accessor const & _aAccessor) const
{
    return readString(_aAccessor,this->header.name);
}
//-----------------------------------------------------------------------------

bool TreeFragment::isNamed(rtl::OUString const & _aName, memory::Accessor const & _aAccessor) const
{
    // TODO: optimize comparison
    return !!(this->getName(_aAccessor) == _aName);
}
//-----------------------------------------------------------------------------

bool TreeFragment::hasDefaults() const
{
    switch (this->header.state & State::mask_state)
    {
    default: OSL_ASSERT(false); // not reachable

    case State::merged:
    case State::defaulted:  return true;

    case State::replaced:
    case State::added:      return false;
    }
}
//-----------------------------------------------------------------------------

bool TreeFragment::hasDefaultsAvailable() const
{
    return (this->header.state & State::flag_default_avail) || isDefault();
}
//-----------------------------------------------------------------------------

bool TreeFragment::isDefault() const
{
    return (this->header.state & State::mask_state) == State::defaulted;
}
//-----------------------------------------------------------------------------

bool TreeFragment::isNew() const
{
    return (this->header.state & State::mask_state) == State::added;
}
//-----------------------------------------------------------------------------

configmgr::node::Attributes TreeFragment::getAttributes() const
{
    configmgr::node::Attributes aResult;

    switch (this->header.state & State::mask_state)
    {
    case State::merged:     aResult.setState(configmgr::node::isMerged);   break;
    case State::defaulted:  aResult.setState(configmgr::node::isDefault);  break;
    case State::replaced:   aResult.setState(configmgr::node::isReplaced); break;
    case State::added:      aResult.setState(configmgr::node::isAdded);    break;
    default: OSL_ASSERT(false); break; // not reachable
    }

    aResult.bWritable   = ! (this->header.state & State::flag_readonly);

    OSL_ASSERT( header.count != 0 );
    NodeInfo const & aRootNodeInfo = this->nodes[0].node.info;

    aResult.bFinalized  = !!(aRootNodeInfo.flags & Flags::finalized);
    aResult.bLocalized  = !!(aRootNodeInfo.flags & Flags::localized);

    return aResult;
}

//-----------------------------------------------------------------------------
    } // namespace sharable
//-----------------------------------------------------------------------------
} // namespace configmgr

<commit_msg>INTEGRATION: CWS cfg01 (1.2.24); FILE MERGED 2003/03/13 15:09:13 jb 1.2.24.3: #107404# Further clean up of node::Attributes interface 2003/02/28 16:33:37 ssmith 1.2.24.2: #107403# #107403# adding support for mandatory flag and changing dynamic properties semantics 2003/02/17 15:57:36 ssmith 1.2.24.1: #107404# refactoring code to support encapsulation<commit_after>/*************************************************************************
 *
 *  $RCSfile: treefragment.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2003-04-01 13:38:18 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#include "treefragment.hxx"

#ifndef CONFIGMGR_CONFIGURATION_ATTRIBUTES_HXX_
#include "attributes.hxx"
#endif

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

namespace configmgr
{
//-----------------------------------------------------------------------------
    namespace sharable
    {
//-----------------------------------------------------------------------------
rtl::OUString TreeFragment::getName(memory::Accessor const & _aAccessor) const
{
    return readString(_aAccessor,this->header.name);
}
//-----------------------------------------------------------------------------

bool TreeFragment::isNamed(rtl::OUString const & _aName, memory::Accessor const & _aAccessor) const
{
    // TODO: optimize comparison
    return !!(this->getName(_aAccessor) == _aName);
}
//-----------------------------------------------------------------------------

bool TreeFragment::hasDefaults() const
{
    switch (this->header.state & State::mask_state)
    {
    default: OSL_ASSERT(false); // not reachable

    case State::merged:
    case State::defaulted:  return true;

    case State::replaced:
    case State::added:      return false;
    }
}
//-----------------------------------------------------------------------------

bool TreeFragment::hasDefaultsAvailable() const
{
    return (this->header.state & State::flag_default_avail) || isDefault();
}
//-----------------------------------------------------------------------------

bool TreeFragment::isDefault() const
{
    return (this->header.state & State::mask_state) == State::defaulted;
}
//-----------------------------------------------------------------------------

bool TreeFragment::isNew() const
{
    return (this->header.state & State::mask_state) == State::added;
}
//-----------------------------------------------------------------------------

configmgr::node::Attributes TreeFragment::getAttributes() const
{
    configmgr::node::Attributes aResult;

    switch (this->header.state & State::mask_state)
    {
    case State::merged:     aResult.setState(configmgr::node::isMerged);   break;
    case State::defaulted:  aResult.setState(configmgr::node::isDefault);  break;
    case State::replaced:   aResult.setState(configmgr::node::isReplaced); break;
    case State::added:      aResult.setState(configmgr::node::isAdded);    break;
    default: OSL_ASSERT(false); break; // not reachable
    }

    aResult.setRemovability(!!(this->header.state & State::flag_removable),
                            !!(this->header.state & State::flag_mandatory));

    OSL_ASSERT( header.count != 0 );
    NodeInfo const & aRootNodeInfo = this->nodes[0].node.info;

    aResult.setAccess(  !!(this->header.state & State::flag_readonly),
                        !!(aRootNodeInfo.flags & Flags::finalized)  );

    aResult.setLocalized ( !!(aRootNodeInfo.flags & Flags::localized));

    return aResult;
}

//-----------------------------------------------------------------------------
    } // namespace sharable
//-----------------------------------------------------------------------------
} // namespace configmgr

<|endoftext|>


<commit_before>//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
//  This source code is licensed under the BSD-style license found in the
//  LICENSE file in the root directory of this source tree. An additional grant
//  of patent rights can be found in the PATENTS file in the same directory.

#ifndef ROCKSDB_LITE

#include <string>
#include <utility>
#include <vector>

#include "db/db_impl.h"
#include "db/write_callback.h"
#include "rocksdb/db.h"
#include "rocksdb/write_batch.h"
#include "util/logging.h"
#include "util/sync_point.h"
#include "util/testharness.h"

using std::string;

namespace rocksdb {

class WriteCallbackTest : public testing::Test {
 public:
  string dbname;

  WriteCallbackTest() {
    dbname = test::TmpDir() + "/write_callback_testdb";
  }
};

class WriteCallbackTestWriteCallback1 : public WriteCallback {
 public:
  bool was_called = false;

  Status Callback(DB *db) override {
    was_called = true;

    // Make sure db is a DBImpl
    DBImpl* db_impl = dynamic_cast<DBImpl*> (db);
    if (db_impl == nullptr) {
      return Status::InvalidArgument("");
    }

    return Status::OK();
  }

  bool AllowWriteBatching() override { return true; }
};

class WriteCallbackTestWriteCallback2 : public WriteCallback {
 public:
  Status Callback(DB *db) override {
    return Status::Busy();
  }
  bool AllowWriteBatching() override { return true; }
};

class MockWriteCallback : public WriteCallback {
 public:
  bool should_fail_ = false;
  bool was_called_ = false;
  bool allow_batching_ = false;

  Status Callback(DB* db) override {
    was_called_ = true;
    if (should_fail_) {
      return Status::Busy();
    } else {
      return Status::OK();
    }
  }

  bool AllowWriteBatching() override { return allow_batching_; }
};

TEST_F(WriteCallbackTest, WriteWithCallbackTest) {
  struct WriteOP {
    WriteOP(bool should_fail = false) { callback_.should_fail_ = should_fail; }

    void Put(const string& key, const string& val) {
      kvs_.push_back(std::make_pair(key, val));
      write_batch_.Put(key, val);
    }

    void Clear() {
      kvs_.clear();
      write_batch_.Clear();
      callback_.was_called_ = false;
    }

    MockWriteCallback callback_;
    WriteBatch write_batch_;
    std::vector<std::pair<string, string>> kvs_;
  };

  std::vector<std::vector<WriteOP>> write_scenarios = {
      {true},
      {false},
      {false, false},
      {true, true},
      {true, false},
      {false, true},
      {false, false, false},
      {true, true, true},
      {false, true, false},
      {true, false, true},
      {true, false, false, false, false},
      {false, false, false, false, true},
      {false, false, true, false, true},
  };

  for (auto& allow_parallel : {true, false}) {
    for (auto& allow_batching : {true, false}) {
      for (auto& enable_WAL : {true, false}) {
        for (auto& write_group : write_scenarios) {
          Options options;
          options.create_if_missing = true;
          options.allow_concurrent_memtable_write = allow_parallel;

          ReadOptions read_options;
          DB* db;
          DBImpl* db_impl;

          ASSERT_OK(DB::Open(options, dbname, &db));

          db_impl = dynamic_cast<DBImpl*>(db);
          ASSERT_TRUE(db_impl);

          std::atomic<uint64_t> threads_waiting(0);
          std::atomic<uint64_t> seq(db_impl->GetLatestSequenceNumber());
          ASSERT_EQ(db_impl->GetLatestSequenceNumber(), 0);

          rocksdb::SyncPoint::GetInstance()->SetCallBack(
              "WriteThread::JoinBatchGroup:Wait", [&](void* arg) {
                uint64_t cur_threads_waiting = 0;
                bool is_leader = false;
                bool is_last = false;

                // who am i
                do {
                  cur_threads_waiting = threads_waiting.load();
                  is_leader = (cur_threads_waiting == 0);
                  is_last = (cur_threads_waiting == write_group.size() - 1);
                } while (!threads_waiting.compare_exchange_strong(
                    cur_threads_waiting, cur_threads_waiting + 1));

                // check my state
                auto* writer = reinterpret_cast<WriteThread::Writer*>(arg);

                if (is_leader) {
                  ASSERT_TRUE(writer->state ==
                              WriteThread::State::STATE_GROUP_LEADER);
                } else {
                  ASSERT_TRUE(writer->state == WriteThread::State::STATE_INIT);
                }

                // (meta test) the first WriteOP should indeed be the first
                // and the last should be the last (all others can be out of
                // order)
                if (is_leader) {
                  ASSERT_TRUE(writer->callback->Callback(nullptr).ok() ==
                              !write_group.front().callback_.should_fail_);
                } else if (is_last) {
                  ASSERT_TRUE(writer->callback->Callback(nullptr).ok() ==
                              !write_group.back().callback_.should_fail_);
                }

                // wait for friends
                while (threads_waiting.load() < write_group.size()) {
                }
              });

          rocksdb::SyncPoint::GetInstance()->SetCallBack(
              "WriteThread::JoinBatchGroup:DoneWaiting", [&](void* arg) {
                // check my state
                auto* writer = reinterpret_cast<WriteThread::Writer*>(arg);

                if (!allow_batching) {
                  // no batching so everyone should be a leader
                  ASSERT_TRUE(writer->state ==
                              WriteThread::State::STATE_GROUP_LEADER);
                } else if (!allow_parallel) {
                  ASSERT_TRUE(writer->state ==
                              WriteThread::State::STATE_COMPLETED);
                }
              });

          std::atomic<uint32_t> thread_num(0);
          std::atomic<char> dummy_key(0);
          std::function<void()> write_with_callback_func = [&]() {
            uint32_t i = thread_num.fetch_add(1);
            Random rnd(i);

            // leaders gotta lead
            while (i > 0 && threads_waiting.load() < 1) {
            }

            // loser has to lose
            while (i == write_group.size() - 1 &&
                   threads_waiting.load() < write_group.size() - 1) {
            }

            auto& write_op = write_group.at(i);
            write_op.Clear();
            write_op.callback_.allow_batching_ = allow_batching;

            // insert some keys
            for (uint32_t j = 0; j < rnd.Next() % 50; j++) {
              // grab unique key
              char my_key = 0;
              do {
                my_key = dummy_key.load();
              } while (!dummy_key.compare_exchange_strong(my_key, my_key + 1));

              string skey(5, my_key);
              string sval(10, my_key);
              write_op.Put(skey, sval);

              if (!write_op.callback_.should_fail_) {
                seq.fetch_add(1);
              }
            }

            WriteOptions woptions;
            woptions.disableWAL = !enable_WAL;
            woptions.sync = enable_WAL;
            Status s = db_impl->WriteWithCallback(
                woptions, &write_op.write_batch_, &write_op.callback_);

            if (write_op.callback_.should_fail_) {
              ASSERT_TRUE(s.IsBusy());
            } else {
              ASSERT_OK(s);
            }
          };

          rocksdb::SyncPoint::GetInstance()->EnableProcessing();

          // do all the writes
          std::vector<std::thread> threads;
          for (uint32_t i = 0; i < write_group.size(); i++) {
            threads.emplace_back(write_with_callback_func);
          }
          for (auto& t : threads) {
            t.join();
          }

          rocksdb::SyncPoint::GetInstance()->DisableProcessing();

          // check for keys
          string value;
          for (auto& w : write_group) {
            ASSERT_TRUE(w.callback_.was_called_);
            for (auto& kvp : w.kvs_) {
              if (w.callback_.should_fail_) {
                ASSERT_TRUE(
                    db->Get(read_options, kvp.first, &value).IsNotFound());
              } else {
                ASSERT_OK(db->Get(read_options, kvp.first, &value));
                ASSERT_EQ(value, kvp.second);
              }
            }
          }

          ASSERT_EQ(seq.load(), db_impl->GetLatestSequenceNumber());

          delete db;
          DestroyDB(dbname, options);
        }
      }
    }
  }
}

TEST_F(WriteCallbackTest, WriteCallBackTest) {
  Options options;
  WriteOptions write_options;
  ReadOptions read_options;
  string value;
  DB* db;
  DBImpl* db_impl;

  options.create_if_missing = true;
  Status s = DB::Open(options, dbname, &db);
  ASSERT_OK(s);

  db_impl = dynamic_cast<DBImpl*> (db);
  ASSERT_TRUE(db_impl);

  WriteBatch wb;

  wb.Put("a", "value.a");
  wb.Delete("x");

  // Test a simple Write
  s = db->Write(write_options, &wb);
  ASSERT_OK(s);

  s = db->Get(read_options, "a", &value);
  ASSERT_OK(s);
  ASSERT_EQ("value.a", value);

  // Test WriteWithCallback
  WriteCallbackTestWriteCallback1 callback1;
  WriteBatch wb2;

  wb2.Put("a", "value.a2");

  s = db_impl->WriteWithCallback(write_options, &wb2, &callback1);
  ASSERT_OK(s);
  ASSERT_TRUE(callback1.was_called);

  s = db->Get(read_options, "a", &value);
  ASSERT_OK(s);
  ASSERT_EQ("value.a2", value);

  // Test WriteWithCallback for a callback that fails
  WriteCallbackTestWriteCallback2 callback2;
  WriteBatch wb3;

  wb3.Put("a", "value.a3");

  s = db_impl->WriteWithCallback(write_options, &wb3, &callback2);
  ASSERT_NOK(s);

  s = db->Get(read_options, "a", &value);
  ASSERT_OK(s);
  ASSERT_EQ("value.a2", value);

  delete db;
  DestroyDB(dbname, options);
}

}  // namespace rocksdb

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

#else
#include <stdio.h>

int main(int argc, char** argv) {
  fprintf(stderr,
          "SKIPPED as WriteWithCallback is not supported in ROCKSDB_LITE\n");
  return 0;
}

#endif  // !ROCKSDB_LITE
<commit_msg>write_callback_test: clean test directory before running tests<commit_after>//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
//  This source code is licensed under the BSD-style license found in the
//  LICENSE file in the root directory of this source tree. An additional grant
//  of patent rights can be found in the PATENTS file in the same directory.

#ifndef ROCKSDB_LITE

#include <string>
#include <utility>
#include <vector>

#include "db/db_impl.h"
#include "db/write_callback.h"
#include "rocksdb/db.h"
#include "rocksdb/write_batch.h"
#include "util/logging.h"
#include "util/sync_point.h"
#include "util/testharness.h"

using std::string;

namespace rocksdb {

class WriteCallbackTest : public testing::Test {
 public:
  string dbname;

  WriteCallbackTest() {
    dbname = test::TmpDir() + "/write_callback_testdb";
  }
};

class WriteCallbackTestWriteCallback1 : public WriteCallback {
 public:
  bool was_called = false;

  Status Callback(DB *db) override {
    was_called = true;

    // Make sure db is a DBImpl
    DBImpl* db_impl = dynamic_cast<DBImpl*> (db);
    if (db_impl == nullptr) {
      return Status::InvalidArgument("");
    }

    return Status::OK();
  }

  bool AllowWriteBatching() override { return true; }
};

class WriteCallbackTestWriteCallback2 : public WriteCallback {
 public:
  Status Callback(DB *db) override {
    return Status::Busy();
  }
  bool AllowWriteBatching() override { return true; }
};

class MockWriteCallback : public WriteCallback {
 public:
  bool should_fail_ = false;
  bool was_called_ = false;
  bool allow_batching_ = false;

  Status Callback(DB* db) override {
    was_called_ = true;
    if (should_fail_) {
      return Status::Busy();
    } else {
      return Status::OK();
    }
  }

  bool AllowWriteBatching() override { return allow_batching_; }
};

TEST_F(WriteCallbackTest, WriteWithCallbackTest) {
  struct WriteOP {
    WriteOP(bool should_fail = false) { callback_.should_fail_ = should_fail; }

    void Put(const string& key, const string& val) {
      kvs_.push_back(std::make_pair(key, val));
      write_batch_.Put(key, val);
    }

    void Clear() {
      kvs_.clear();
      write_batch_.Clear();
      callback_.was_called_ = false;
    }

    MockWriteCallback callback_;
    WriteBatch write_batch_;
    std::vector<std::pair<string, string>> kvs_;
  };

  std::vector<std::vector<WriteOP>> write_scenarios = {
      {true},
      {false},
      {false, false},
      {true, true},
      {true, false},
      {false, true},
      {false, false, false},
      {true, true, true},
      {false, true, false},
      {true, false, true},
      {true, false, false, false, false},
      {false, false, false, false, true},
      {false, false, true, false, true},
  };

  for (auto& allow_parallel : {true, false}) {
    for (auto& allow_batching : {true, false}) {
      for (auto& enable_WAL : {true, false}) {
        for (auto& write_group : write_scenarios) {
          Options options;
          options.create_if_missing = true;
          options.allow_concurrent_memtable_write = allow_parallel;

          ReadOptions read_options;
          DB* db;
          DBImpl* db_impl;

          DestroyDB(dbname, options);
          ASSERT_OK(DB::Open(options, dbname, &db));

          db_impl = dynamic_cast<DBImpl*>(db);
          ASSERT_TRUE(db_impl);

          std::atomic<uint64_t> threads_waiting(0);
          std::atomic<uint64_t> seq(db_impl->GetLatestSequenceNumber());
          ASSERT_EQ(db_impl->GetLatestSequenceNumber(), 0);

          rocksdb::SyncPoint::GetInstance()->SetCallBack(
              "WriteThread::JoinBatchGroup:Wait", [&](void* arg) {
                uint64_t cur_threads_waiting = 0;
                bool is_leader = false;
                bool is_last = false;

                // who am i
                do {
                  cur_threads_waiting = threads_waiting.load();
                  is_leader = (cur_threads_waiting == 0);
                  is_last = (cur_threads_waiting == write_group.size() - 1);
                } while (!threads_waiting.compare_exchange_strong(
                    cur_threads_waiting, cur_threads_waiting + 1));

                // check my state
                auto* writer = reinterpret_cast<WriteThread::Writer*>(arg);

                if (is_leader) {
                  ASSERT_TRUE(writer->state ==
                              WriteThread::State::STATE_GROUP_LEADER);
                } else {
                  ASSERT_TRUE(writer->state == WriteThread::State::STATE_INIT);
                }

                // (meta test) the first WriteOP should indeed be the first
                // and the last should be the last (all others can be out of
                // order)
                if (is_leader) {
                  ASSERT_TRUE(writer->callback->Callback(nullptr).ok() ==
                              !write_group.front().callback_.should_fail_);
                } else if (is_last) {
                  ASSERT_TRUE(writer->callback->Callback(nullptr).ok() ==
                              !write_group.back().callback_.should_fail_);
                }

                // wait for friends
                while (threads_waiting.load() < write_group.size()) {
                }
              });

          rocksdb::SyncPoint::GetInstance()->SetCallBack(
              "WriteThread::JoinBatchGroup:DoneWaiting", [&](void* arg) {
                // check my state
                auto* writer = reinterpret_cast<WriteThread::Writer*>(arg);

                if (!allow_batching) {
                  // no batching so everyone should be a leader
                  ASSERT_TRUE(writer->state ==
                              WriteThread::State::STATE_GROUP_LEADER);
                } else if (!allow_parallel) {
                  ASSERT_TRUE(writer->state ==
                              WriteThread::State::STATE_COMPLETED);
                }
              });

          std::atomic<uint32_t> thread_num(0);
          std::atomic<char> dummy_key(0);
          std::function<void()> write_with_callback_func = [&]() {
            uint32_t i = thread_num.fetch_add(1);
            Random rnd(i);

            // leaders gotta lead
            while (i > 0 && threads_waiting.load() < 1) {
            }

            // loser has to lose
            while (i == write_group.size() - 1 &&
                   threads_waiting.load() < write_group.size() - 1) {
            }

            auto& write_op = write_group.at(i);
            write_op.Clear();
            write_op.callback_.allow_batching_ = allow_batching;

            // insert some keys
            for (uint32_t j = 0; j < rnd.Next() % 50; j++) {
              // grab unique key
              char my_key = 0;
              do {
                my_key = dummy_key.load();
              } while (!dummy_key.compare_exchange_strong(my_key, my_key + 1));

              string skey(5, my_key);
              string sval(10, my_key);
              write_op.Put(skey, sval);

              if (!write_op.callback_.should_fail_) {
                seq.fetch_add(1);
              }
            }

            WriteOptions woptions;
            woptions.disableWAL = !enable_WAL;
            woptions.sync = enable_WAL;
            Status s = db_impl->WriteWithCallback(
                woptions, &write_op.write_batch_, &write_op.callback_);

            if (write_op.callback_.should_fail_) {
              ASSERT_TRUE(s.IsBusy());
            } else {
              ASSERT_OK(s);
            }
          };

          rocksdb::SyncPoint::GetInstance()->EnableProcessing();

          // do all the writes
          std::vector<std::thread> threads;
          for (uint32_t i = 0; i < write_group.size(); i++) {
            threads.emplace_back(write_with_callback_func);
          }
          for (auto& t : threads) {
            t.join();
          }

          rocksdb::SyncPoint::GetInstance()->DisableProcessing();

          // check for keys
          string value;
          for (auto& w : write_group) {
            ASSERT_TRUE(w.callback_.was_called_);
            for (auto& kvp : w.kvs_) {
              if (w.callback_.should_fail_) {
                ASSERT_TRUE(
                    db->Get(read_options, kvp.first, &value).IsNotFound());
              } else {
                ASSERT_OK(db->Get(read_options, kvp.first, &value));
                ASSERT_EQ(value, kvp.second);
              }
            }
          }

          ASSERT_EQ(seq.load(), db_impl->GetLatestSequenceNumber());

          delete db;
          DestroyDB(dbname, options);
        }
      }
    }
  }
}

TEST_F(WriteCallbackTest, WriteCallBackTest) {
  Options options;
  WriteOptions write_options;
  ReadOptions read_options;
  string value;
  DB* db;
  DBImpl* db_impl;

  DestroyDB(dbname, options);

  options.create_if_missing = true;
  Status s = DB::Open(options, dbname, &db);
  ASSERT_OK(s);

  db_impl = dynamic_cast<DBImpl*> (db);
  ASSERT_TRUE(db_impl);

  WriteBatch wb;

  wb.Put("a", "value.a");
  wb.Delete("x");

  // Test a simple Write
  s = db->Write(write_options, &wb);
  ASSERT_OK(s);

  s = db->Get(read_options, "a", &value);
  ASSERT_OK(s);
  ASSERT_EQ("value.a", value);

  // Test WriteWithCallback
  WriteCallbackTestWriteCallback1 callback1;
  WriteBatch wb2;

  wb2.Put("a", "value.a2");

  s = db_impl->WriteWithCallback(write_options, &wb2, &callback1);
  ASSERT_OK(s);
  ASSERT_TRUE(callback1.was_called);

  s = db->Get(read_options, "a", &value);
  ASSERT_OK(s);
  ASSERT_EQ("value.a2", value);

  // Test WriteWithCallback for a callback that fails
  WriteCallbackTestWriteCallback2 callback2;
  WriteBatch wb3;

  wb3.Put("a", "value.a3");

  s = db_impl->WriteWithCallback(write_options, &wb3, &callback2);
  ASSERT_NOK(s);

  s = db->Get(read_options, "a", &value);
  ASSERT_OK(s);
  ASSERT_EQ("value.a2", value);

  delete db;
  DestroyDB(dbname, options);
}

}  // namespace rocksdb

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

#else
#include <stdio.h>

int main(int argc, char** argv) {
  fprintf(stderr,
          "SKIPPED as WriteWithCallback is not supported in ROCKSDB_LITE\n");
  return 0;
}

#endif  // !ROCKSDB_LITE
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include "propertyeditorvalue.h"
#include <QRegExp>
#include <abstractview.h>
#include <nodeabstractproperty.h>
#include <nodeproperty.h>
#include <model.h>
#include <nodemetainfo.h>
#include <metainfo.h>
#include <nodeproperty.h>
#include <qmlobjectnode.h>

//using namespace QmlDesigner;

PropertyEditorValue::PropertyEditorValue(QObject *parent)
   : QObject(parent),
   m_isInSubState(false),
   m_isInModel(false),
   m_isBound(false),
   m_isValid(false),
   m_complexNode(new PropertyEditorNodeWrapper(this))
{
}

QVariant PropertyEditorValue::value() const
{
    QVariant returnValue = m_value;
    if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name()))
        if (modelNode().metaInfo().propertyTypeName(name()) == QLatin1String("QUrl")) {
        returnValue = returnValue.toUrl().toString();
    }
    return returnValue;
}

static bool cleverDoubleCompare(QVariant value1, QVariant value2)
{ //we ignore slight changes on doubles
    if ((value1.type() == QVariant::Double) && (value2.type() == QVariant::Double)) {
        int a = value1.toDouble() * 100;
        int b = value2.toDouble() * 100;

        if (qFuzzyCompare((qreal(a) / 100), (qreal(b) / 100))) {
            return true;
        }
    }
    return false;
}

static bool cleverColorCompare(QVariant value1, QVariant value2)
{
    if ((value1.type() == QVariant::Color) && (value2.type() == QVariant::Color)) {
        QColor c1 = value1.value<QColor>();
        QColor c2 = value2.value<QColor>();
        QString a = c1.name();
        QString b = c2.name();
        if (a != b)
            return false;
        return (c1.alpha() == c2.alpha());
    }
    if ((value1.type() == QVariant::String) && (value2.type() == QVariant::Color)) {
        return cleverColorCompare(QVariant(QColor(value1.toString())), value2);
    }
    if ((value1.type() == QVariant::Color) && (value2.type() == QVariant::String)) {
        return cleverColorCompare(value1, QVariant(QColor(value2.toString())));
    }
    return false;
}

void PropertyEditorValue::setValueWithEmit(const QVariant &value)
{
    if (m_value != value || isBound()) {
        QVariant newValue = value;
        if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name()))
            if (modelNode().metaInfo().propertyTypeName(name()) == QLatin1String("QUrl")) {
            newValue = QUrl(newValue.toString());
        }

        if (cleverDoubleCompare(newValue, m_value))
            return;
        if (cleverColorCompare(newValue, m_value))
            return;
        setValue(newValue);
        m_isBound = false;
        emit valueChanged(name(), value);
        emit valueChangedQml();
        emit isBoundChanged();
    }
}

void PropertyEditorValue::setValue(const QVariant &value)
{
    if ((m_value != value) &&
        !cleverDoubleCompare(value, m_value) &&
        !cleverColorCompare(value, m_value))

        m_value = value;

    if (m_value.isValid())
        emit valueChangedQml();
    emit isBoundChanged();

}

QString PropertyEditorValue::expression() const
{

    return m_expression;
}

void PropertyEditorValue::setExpressionWithEmit(const QString &expression)
{
    if ( m_expression != expression) {
        setExpression(expression);
        emit expressionChanged(name());
    }
}

void PropertyEditorValue::setExpression(const QString &expression)
{
    if ( m_expression != expression) {
        m_expression = expression;
        emit expressionChanged(QString());
    }
}

bool PropertyEditorValue::isInSubState() const
{
    const QmlDesigner::QmlObjectNode objectNode(modelNode());
    return objectNode.isValid() && objectNode.currentState().isValid() && objectNode.propertyAffectedByCurrentState(name());
}

bool PropertyEditorValue::isBound() const
{
    const QmlDesigner::QmlObjectNode objectNode(modelNode());
    return objectNode.isValid() && objectNode.hasBindingProperty(name());
}

bool PropertyEditorValue::isInModel() const
{
    return modelNode().isValid() && modelNode().hasProperty(name());
}

QString PropertyEditorValue::name() const
{
    return m_name;
}

void PropertyEditorValue::setName(const QString &name)
{
    m_name = name;
}

bool PropertyEditorValue::isValid() const
{
    return m_isValid;
}

void PropertyEditorValue::setIsValid(bool valid)
{
    m_isValid = valid;
}

bool PropertyEditorValue::isTranslated() const
{
    if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name()))
        if (modelNode().metaInfo().propertyTypeName(name()) == QLatin1String("QString") || modelNode().metaInfo().propertyTypeName(name()) == QLatin1String("string")) {
            const QmlDesigner::QmlObjectNode objectNode(modelNode());
            if (objectNode.isValid() && objectNode.hasBindingProperty(name())) {
                //qsTr()
                QRegExp rx("qsTr(\"*\")");
                rx.setPatternSyntax(QRegExp::Wildcard);
                return rx.exactMatch(expression());
            }
            return false;
        }
    return false;
}

QmlDesigner::ModelNode PropertyEditorValue::modelNode() const
{
    return m_modelNode;
}

void PropertyEditorValue::setModelNode(const QmlDesigner::ModelNode &modelNode)
{
    if (modelNode != m_modelNode) {
        m_modelNode = modelNode;
        m_complexNode->update();
        emit modelNodeChanged();
    }
}

PropertyEditorNodeWrapper* PropertyEditorValue::complexNode()
{
    return m_complexNode;
}

void PropertyEditorValue::resetValue()
{
    if (m_value.isValid() || isBound()) {
        m_value = QVariant();
        m_isBound = false;
        emit valueChanged(name(), QVariant());
    }
}

void PropertyEditorValue::registerDeclarativeTypes()
{
    qmlRegisterType<PropertyEditorValue>("Bauhaus",1,0,"PropertyEditorValue");
    qmlRegisterType<PropertyEditorNodeWrapper>("Bauhaus",1,0,"PropertyEditorNodeWrapper");
    qmlRegisterType<QDeclarativePropertyMap>("Bauhaus",1,0,"QDeclarativePropertyMap");
}

PropertyEditorNodeWrapper::PropertyEditorNodeWrapper(PropertyEditorValue* parent) : QObject(parent), m_valuesPropertyMap(this)
{
    m_editorValue = parent;
    connect(m_editorValue, SIGNAL(modelNodeChanged()), this, SLOT(update()));
}

PropertyEditorNodeWrapper::PropertyEditorNodeWrapper(QObject *parent) : QObject(parent), m_editorValue(NULL)
{
}

bool PropertyEditorNodeWrapper::exists()
{
    if (!(m_editorValue && m_editorValue->modelNode().isValid()))
        return false;

    return m_modelNode.isValid();
}

QString PropertyEditorNodeWrapper::type()
{
    if (!(m_modelNode.isValid()))
        return QString();

    return m_modelNode.simplifiedTypeName();

}

QmlDesigner::ModelNode PropertyEditorNodeWrapper::parentModelNode() const
{
    return  m_editorValue->modelNode();
}

QString PropertyEditorNodeWrapper::propertyName() const
{
    return m_editorValue->name();
}

QDeclarativePropertyMap* PropertyEditorNodeWrapper::properties()
{
    return &m_valuesPropertyMap;
}

void PropertyEditorNodeWrapper::add(const QString &type)
{

    QString propertyType = type;

    if ((m_editorValue && m_editorValue->modelNode().isValid())) {
        if (propertyType.isEmpty())
            propertyType = m_editorValue->modelNode().metaInfo().propertyTypeName(m_editorValue->name());
        while (propertyType.contains('*')) //strip star
            propertyType.chop(1);
        m_modelNode = m_editorValue->modelNode().view()->createModelNode(propertyType, 4, 7);
        m_editorValue->modelNode().nodeAbstractProperty(m_editorValue->name()).reparentHere(m_modelNode);
        if (!m_modelNode.isValid()) {
            qWarning("PropertyEditorNodeWrapper::add failed");
        }
    } else {
        qWarning("PropertyEditorNodeWrapper::add failed - node invalid");
    }
    setup();
}

void PropertyEditorNodeWrapper::remove()
{
    if ((m_editorValue && m_editorValue->modelNode().isValid())) {
        if (QmlDesigner::QmlObjectNode(m_modelNode).isValid())
            QmlDesigner::QmlObjectNode(m_modelNode).destroy();
        m_editorValue->modelNode().removeProperty(m_editorValue->name());
    } else {
        qWarning("PropertyEditorNodeWrapper::remove failed - node invalid");
    }
    m_modelNode = QmlDesigner::ModelNode();

    foreach (const QString &propertyName, m_valuesPropertyMap.keys())
        m_valuesPropertyMap.clear(propertyName);
    foreach (QObject *object, m_valuesPropertyMap.children())
        delete object;
    emit propertiesChanged();
    emit existsChanged();
}

void PropertyEditorNodeWrapper::changeValue(const QString &name)
{
    if (name.isNull())
        return;
    if (m_modelNode.isValid()) {
        QmlDesigner::QmlObjectNode fxObjectNode(m_modelNode);

        PropertyEditorValue *valueObject = qvariant_cast<PropertyEditorValue *>(m_valuesPropertyMap.value(name));

        if (valueObject->value().isValid())
            fxObjectNode.setVariantProperty(name, valueObject->value());
        else
            fxObjectNode.removeVariantProperty(name);
    }
}

void PropertyEditorNodeWrapper::setup()
{
    Q_ASSERT(m_editorValue);
    Q_ASSERT(m_editorValue->modelNode().isValid());
    if ((m_editorValue->modelNode().isValid() && m_modelNode.isValid())) {
        QmlDesigner::QmlObjectNode fxObjectNode(m_modelNode);
        foreach ( const QString &propertyName, m_valuesPropertyMap.keys())
            m_valuesPropertyMap.clear(propertyName);
        foreach (QObject *object, m_valuesPropertyMap.children())
            delete object;

        foreach (const QString &propertyName, m_modelNode.metaInfo().propertyNames()) {
            if (fxObjectNode.isValid()) {
                PropertyEditorValue *valueObject = new PropertyEditorValue(&m_valuesPropertyMap);
                valueObject->setName(propertyName);
                valueObject->setValue(fxObjectNode.instanceValue(propertyName));
                connect(valueObject, SIGNAL(valueChanged(QString, const QVariant&)), &m_valuesPropertyMap, SIGNAL(valueChanged(QString, const QVariant&)));
                m_valuesPropertyMap.insert(propertyName, QVariant::fromValue(valueObject));
            }
        }
    }
    connect(&m_valuesPropertyMap, SIGNAL(valueChanged(const QString &, const QVariant&)), this, SLOT(changeValue(const QString&)));

    emit propertiesChanged();
    emit existsChanged();
}

void PropertyEditorNodeWrapper::update()
{
    if (m_editorValue && m_editorValue->modelNode().isValid()) {
        if (m_editorValue->modelNode().hasProperty(m_editorValue->name()) && m_editorValue->modelNode().property(m_editorValue->name()).isNodeProperty()) {
            m_modelNode = m_editorValue->modelNode().nodeProperty(m_editorValue->name()).modelNode();
        }
        setup();
        emit existsChanged();
        emit typeChanged();
    }
}

<commit_msg>QmlDesigner.propertyEditor: bugfix for assert<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include "propertyeditorvalue.h"
#include <QRegExp>
#include <abstractview.h>
#include <nodeabstractproperty.h>
#include <nodeproperty.h>
#include <model.h>
#include <nodemetainfo.h>
#include <metainfo.h>
#include <nodeproperty.h>
#include <qmlobjectnode.h>

//using namespace QmlDesigner;

PropertyEditorValue::PropertyEditorValue(QObject *parent)
   : QObject(parent),
   m_isInSubState(false),
   m_isInModel(false),
   m_isBound(false),
   m_isValid(false),
   m_complexNode(new PropertyEditorNodeWrapper(this))
{
}

QVariant PropertyEditorValue::value() const
{
    QVariant returnValue = m_value;
    if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name()))
        if (modelNode().metaInfo().propertyTypeName(name()) == QLatin1String("QUrl")) {
        returnValue = returnValue.toUrl().toString();
    }
    return returnValue;
}

static bool cleverDoubleCompare(QVariant value1, QVariant value2)
{ //we ignore slight changes on doubles
    if ((value1.type() == QVariant::Double) && (value2.type() == QVariant::Double)) {
        int a = value1.toDouble() * 100;
        int b = value2.toDouble() * 100;

        if (qFuzzyCompare((qreal(a) / 100), (qreal(b) / 100))) {
            return true;
        }
    }
    return false;
}

static bool cleverColorCompare(QVariant value1, QVariant value2)
{
    if ((value1.type() == QVariant::Color) && (value2.type() == QVariant::Color)) {
        QColor c1 = value1.value<QColor>();
        QColor c2 = value2.value<QColor>();
        QString a = c1.name();
        QString b = c2.name();
        if (a != b)
            return false;
        return (c1.alpha() == c2.alpha());
    }
    if ((value1.type() == QVariant::String) && (value2.type() == QVariant::Color)) {
        return cleverColorCompare(QVariant(QColor(value1.toString())), value2);
    }
    if ((value1.type() == QVariant::Color) && (value2.type() == QVariant::String)) {
        return cleverColorCompare(value1, QVariant(QColor(value2.toString())));
    }
    return false;
}

/* "red" is the same color as "#ff0000"
  To simplify editing we convert all explicit color names in the hash format */
static void fixAmbigousColorNames(const QmlDesigner::ModelNode &modelNode, const QString &name, QVariant *value)
{
    if (modelNode.isValid() && modelNode.metaInfo().isValid()
            && (modelNode.metaInfo().propertyTypeName(name) == "QColor"
                || modelNode.metaInfo().propertyTypeName(name) == "color")) {
        if ((value->type() == QVariant::Color)) {
            *value = QColor(value->value<QColor>().name());
        } else {
            *value = QColor(value->toString()).name();
        }
    }
}

void PropertyEditorValue::setValueWithEmit(const QVariant &value)
{
    if (m_value != value || isBound()) {
        QVariant newValue = value;
        if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name()))
            if (modelNode().metaInfo().propertyTypeName(name()) == QLatin1String("QUrl")) {
            newValue = QUrl(newValue.toString());
        }

        if (cleverDoubleCompare(newValue, m_value))
            return;
        if (cleverColorCompare(newValue, m_value))
            return;
        setValue(newValue);
        m_isBound = false;
        emit valueChanged(name(), value);
        emit valueChangedQml();
        emit isBoundChanged();
    }
}

void PropertyEditorValue::setValue(const QVariant &value)
{
    if ((m_value != value) &&
        !cleverDoubleCompare(value, m_value) &&
        !cleverColorCompare(value, m_value))

        m_value = value;

    fixAmbigousColorNames(modelNode(), name(), &m_value);

    if (m_value.isValid())
        emit valueChangedQml();
    emit isBoundChanged();

}

QString PropertyEditorValue::expression() const
{

    return m_expression;
}

void PropertyEditorValue::setExpressionWithEmit(const QString &expression)
{
    if ( m_expression != expression) {
        setExpression(expression);
        emit expressionChanged(name());
    }
}

void PropertyEditorValue::setExpression(const QString &expression)
{
    if ( m_expression != expression) {
        m_expression = expression;
        emit expressionChanged(QString());
    }
}

bool PropertyEditorValue::isInSubState() const
{
    const QmlDesigner::QmlObjectNode objectNode(modelNode());
    return objectNode.isValid() && objectNode.currentState().isValid() && objectNode.propertyAffectedByCurrentState(name());
}

bool PropertyEditorValue::isBound() const
{
    const QmlDesigner::QmlObjectNode objectNode(modelNode());
    return objectNode.isValid() && objectNode.hasBindingProperty(name());
}

bool PropertyEditorValue::isInModel() const
{
    return modelNode().isValid() && modelNode().hasProperty(name());
}

QString PropertyEditorValue::name() const
{
    return m_name;
}

void PropertyEditorValue::setName(const QString &name)
{
    m_name = name;
}

bool PropertyEditorValue::isValid() const
{
    return m_isValid;
}

void PropertyEditorValue::setIsValid(bool valid)
{
    m_isValid = valid;
}

bool PropertyEditorValue::isTranslated() const
{
    if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name()))
        if (modelNode().metaInfo().propertyTypeName(name()) == QLatin1String("QString") || modelNode().metaInfo().propertyTypeName(name()) == QLatin1String("string")) {
            const QmlDesigner::QmlObjectNode objectNode(modelNode());
            if (objectNode.isValid() && objectNode.hasBindingProperty(name())) {
                //qsTr()
                QRegExp rx("qsTr(\"*\")");
                rx.setPatternSyntax(QRegExp::Wildcard);
                return rx.exactMatch(expression());
            }
            return false;
        }
    return false;
}

QmlDesigner::ModelNode PropertyEditorValue::modelNode() const
{
    return m_modelNode;
}

void PropertyEditorValue::setModelNode(const QmlDesigner::ModelNode &modelNode)
{
    if (modelNode != m_modelNode) {
        m_modelNode = modelNode;
        m_complexNode->update();
        emit modelNodeChanged();
    }
}

PropertyEditorNodeWrapper* PropertyEditorValue::complexNode()
{
    return m_complexNode;
}

void PropertyEditorValue::resetValue()
{
    if (m_value.isValid() || isBound()) {
        m_value = QVariant();
        m_isBound = false;
        emit valueChanged(name(), QVariant());
    }
}

void PropertyEditorValue::registerDeclarativeTypes()
{
    qmlRegisterType<PropertyEditorValue>("Bauhaus",1,0,"PropertyEditorValue");
    qmlRegisterType<PropertyEditorNodeWrapper>("Bauhaus",1,0,"PropertyEditorNodeWrapper");
    qmlRegisterType<QDeclarativePropertyMap>("Bauhaus",1,0,"QDeclarativePropertyMap");
}

PropertyEditorNodeWrapper::PropertyEditorNodeWrapper(PropertyEditorValue* parent) : QObject(parent), m_valuesPropertyMap(this)
{
    m_editorValue = parent;
    connect(m_editorValue, SIGNAL(modelNodeChanged()), this, SLOT(update()));
}

PropertyEditorNodeWrapper::PropertyEditorNodeWrapper(QObject *parent) : QObject(parent), m_editorValue(NULL)
{
}

bool PropertyEditorNodeWrapper::exists()
{
    if (!(m_editorValue && m_editorValue->modelNode().isValid()))
        return false;

    return m_modelNode.isValid();
}

QString PropertyEditorNodeWrapper::type()
{
    if (!(m_modelNode.isValid()))
        return QString();

    return m_modelNode.simplifiedTypeName();

}

QmlDesigner::ModelNode PropertyEditorNodeWrapper::parentModelNode() const
{
    return  m_editorValue->modelNode();
}

QString PropertyEditorNodeWrapper::propertyName() const
{
    return m_editorValue->name();
}

QDeclarativePropertyMap* PropertyEditorNodeWrapper::properties()
{
    return &m_valuesPropertyMap;
}

void PropertyEditorNodeWrapper::add(const QString &type)
{

    QString propertyType = type;

    if ((m_editorValue && m_editorValue->modelNode().isValid())) {
        if (propertyType.isEmpty())
            propertyType = m_editorValue->modelNode().metaInfo().propertyTypeName(m_editorValue->name());
        while (propertyType.contains('*')) //strip star
            propertyType.chop(1);
        m_modelNode = m_editorValue->modelNode().view()->createModelNode(propertyType, 4, 7);
        m_editorValue->modelNode().nodeAbstractProperty(m_editorValue->name()).reparentHere(m_modelNode);
        if (!m_modelNode.isValid()) {
            qWarning("PropertyEditorNodeWrapper::add failed");
        }
    } else {
        qWarning("PropertyEditorNodeWrapper::add failed - node invalid");
    }
    setup();
}

void PropertyEditorNodeWrapper::remove()
{
    if ((m_editorValue && m_editorValue->modelNode().isValid())) {
        if (QmlDesigner::QmlObjectNode(m_modelNode).isValid())
            QmlDesigner::QmlObjectNode(m_modelNode).destroy();
        m_editorValue->modelNode().removeProperty(m_editorValue->name());
    } else {
        qWarning("PropertyEditorNodeWrapper::remove failed - node invalid");
    }
    m_modelNode = QmlDesigner::ModelNode();

    foreach (const QString &propertyName, m_valuesPropertyMap.keys())
        m_valuesPropertyMap.clear(propertyName);
    foreach (QObject *object, m_valuesPropertyMap.children())
        delete object;
    emit propertiesChanged();
    emit existsChanged();
}

void PropertyEditorNodeWrapper::changeValue(const QString &name)
{
    if (name.isNull())
        return;
    if (m_modelNode.isValid()) {
        QmlDesigner::QmlObjectNode fxObjectNode(m_modelNode);

        PropertyEditorValue *valueObject = qvariant_cast<PropertyEditorValue *>(m_valuesPropertyMap.value(name));

        if (valueObject->value().isValid())
            fxObjectNode.setVariantProperty(name, valueObject->value());
        else
            fxObjectNode.removeVariantProperty(name);
    }
}

void PropertyEditorNodeWrapper::setup()
{
    Q_ASSERT(m_editorValue);
    Q_ASSERT(m_editorValue->modelNode().isValid());
    if ((m_editorValue->modelNode().isValid() && m_modelNode.isValid())) {
        QmlDesigner::QmlObjectNode fxObjectNode(m_modelNode);
        foreach ( const QString &propertyName, m_valuesPropertyMap.keys())
            m_valuesPropertyMap.clear(propertyName);
        foreach (QObject *object, m_valuesPropertyMap.children())
            delete object;

        foreach (const QString &propertyName, m_modelNode.metaInfo().propertyNames()) {
            if (fxObjectNode.isValid()) {
                PropertyEditorValue *valueObject = new PropertyEditorValue(&m_valuesPropertyMap);
                valueObject->setName(propertyName);
                valueObject->setValue(fxObjectNode.instanceValue(propertyName));
                connect(valueObject, SIGNAL(valueChanged(QString, const QVariant&)), &m_valuesPropertyMap, SIGNAL(valueChanged(QString, const QVariant&)));
                m_valuesPropertyMap.insert(propertyName, QVariant::fromValue(valueObject));
            }
        }
    }
    connect(&m_valuesPropertyMap, SIGNAL(valueChanged(const QString &, const QVariant&)), this, SLOT(changeValue(const QString&)));

    emit propertiesChanged();
    emit existsChanged();
}

void PropertyEditorNodeWrapper::update()
{
    if (m_editorValue && m_editorValue->modelNode().isValid()) {
        if (m_editorValue->modelNode().hasProperty(m_editorValue->name()) && m_editorValue->modelNode().property(m_editorValue->name()).isNodeProperty()) {
            m_modelNode = m_editorValue->modelNode().nodeProperty(m_editorValue->name()).modelNode();
        }
        setup();
        emit existsChanged();
        emit typeChanged();
    }
}

<|endoftext|>


<commit_before>#include "stdafx.h"
#include "SettingsUI.h"
#include "Display.h"
#include "afxdialogex.h"

#define MIN_MS USER_TIMER_MINIMUM
#define MAX_MS 60000

IMPLEMENT_DYNAMIC(Display, CPropertyPage)

Display::Display() :
CPropertyPage(Display::IDD) {
}

Display::~Display() {

}

void Display::DoDataExchange(CDataExchange* pDX) {
    CPropertyPage::DoDataExchange(pDX);
    DDX_Control(pDX, CHK_ONTOP, _onTop);
    DDX_Control(pDX, SP_DELAY, _spinDelay);
    DDX_Control(pDX, SP_SPEED, _spinSpeed);
    DDX_Control(pDX, CHK_FULLSCREEN, _fullscreen);
    DDX_Control(pDX, CMB_POSITION, _position);
    DDX_Control(pDX, LBL_CUSTOMX, _lbX);
    DDX_Control(pDX, LBL_CUSTOMY, _lbY);
    DDX_Control(pDX, ED_CUSTOMX, _customX);
    DDX_Control(pDX, ED_CUSTOMY, _customY);
    DDX_Control(pDX, ED_DELAY, _delay);
    DDX_Control(pDX, ED_SPEED, _speed);
    DDX_Control(pDX, CMB_ANIMATION, _animation);
    DDX_Control(pDX, CMB_MONITOR, _monitor);
}

BOOL Display::OnApply() {
    return CPropertyPage::OnApply();
}

BOOL Display::OnCommand(WPARAM wParam, LPARAM lParam) {
    SetModified();
    return CPropertyPage::OnCommand(wParam, lParam);
}

BOOL Display::OnInitDialog() {
    CPropertyPage::OnInitDialog();

    _position.AddString(L"Top");
    _position.AddString(L"Left");
    _position.AddString(L"Right");
    _position.AddString(L"Bottom");
    _position.AddString(L"Center");
    _position.AddString(L"Custom");

    _spinDelay.SetRange32(MIN_MS, MAX_MS);
    _spinSpeed.SetRange32(MIN_MS, MAX_MS);
    return TRUE;
}

BEGIN_MESSAGE_MAP(Display, CPropertyPage)
    ON_NOTIFY(UDN_DELTAPOS, SP_DELAY, &Display::OnDeltaposDelay)
    ON_NOTIFY(UDN_DELTAPOS, SP_SPEED, &Display::OnDeltaposSpeed)
    ON_CBN_SELCHANGE(CMB_POSITION, &Display::OnCbnSelchangePosition)
END_MESSAGE_MAP()

void Display::OnDeltaposDelay(NMHDR *pNMHDR, LRESULT *pResult) {
    LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
    pNMUpDown->iDelta *= 100;
    *pResult = 0;
}

void Display::OnDeltaposSpeed(NMHDR *pNMHDR, LRESULT *pResult) {
    LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
    pNMUpDown->iDelta *= 100;
    *pResult = 0;
}

void Display::OnCbnSelchangePosition() {
    int selIdx = _position.GetCurSel();
    CString selected;
    _position.GetLBText(selIdx, selected);
    BOOL isCustom = (selected == L"Custom");
    _lbX.EnableWindow(isCustom);
    _lbY.EnableWindow(isCustom);
    _customX.EnableWindow(isCustom);
    _customY.EnableWindow(isCustom);
}
<commit_msg>Initial Display settings load logic<commit_after>#include "stdafx.h"
#include "SettingsUI.h"
#include "Display.h"
#include "afxdialogex.h"

#include "Monitor.h"
#include "Settings.h"

#define MIN_MS USER_TIMER_MINIMUM
#define MAX_MS 60000

IMPLEMENT_DYNAMIC(Display, CPropertyPage)

Display::Display() :
CPropertyPage(Display::IDD) {
}

Display::~Display() {

}

void Display::DoDataExchange(CDataExchange* pDX) {
    CPropertyPage::DoDataExchange(pDX);
    DDX_Control(pDX, CHK_ONTOP, _onTop);
    DDX_Control(pDX, SP_DELAY, _spinDelay);
    DDX_Control(pDX, SP_SPEED, _spinSpeed);
    DDX_Control(pDX, CHK_FULLSCREEN, _fullscreen);
    DDX_Control(pDX, CMB_POSITION, _position);
    DDX_Control(pDX, LBL_CUSTOMX, _lbX);
    DDX_Control(pDX, LBL_CUSTOMY, _lbY);
    DDX_Control(pDX, ED_CUSTOMX, _customX);
    DDX_Control(pDX, ED_CUSTOMY, _customY);
    DDX_Control(pDX, ED_DELAY, _delay);
    DDX_Control(pDX, ED_SPEED, _speed);
    DDX_Control(pDX, CMB_ANIMATION, _animation);
    DDX_Control(pDX, CMB_MONITOR, _monitor);
}

BOOL Display::OnApply() {
    return CPropertyPage::OnApply();
}

BOOL Display::OnCommand(WPARAM wParam, LPARAM lParam) {
    SetModified();
    return CPropertyPage::OnCommand(wParam, lParam);
}

BOOL Display::OnInitDialog() {
    CPropertyPage::OnInitDialog();

    Settings *settings = Settings::Instance();

    _onTop.SetCheck(settings->AlwaysOnTop());
    _fullscreen.SetCheck(settings->HideFullscreen());

    _position.AddString(L"Top");
    _position.AddString(L"Left");
    _position.AddString(L"Right");
    _position.AddString(L"Bottom");
    _position.AddString(L"Center");
    _position.AddString(L"Custom");
    Settings::OSDPos position = settings->OSDPosition();
    _position.SetCurSel((int) position);

    _customX.SetWindowText(std::to_wstring(settings->OSDX()).c_str());
    _customY.SetWindowText(std::to_wstring(settings->OSDY()).c_str());

    _monitor.AddString(L"Default");
    std::list<DISPLAY_DEVICE> devices = Monitor::ListAll();
    for (DISPLAY_DEVICE dev : devices) {
        MessageBox(dev.DeviceString);
    }

    _animation.AddString(L"None");
    _animation.AddString(L"Fade");

    _spinDelay.SetRange32(MIN_MS, MAX_MS);
    int delay = settings->HideDelay();
    std::wstring delayStr = std::to_wstring(delay);
    _delay.SetWindowTextW(delayStr.c_str());

    _spinSpeed.SetRange32(MIN_MS, MAX_MS);
    int speed = settings->HideSpeed();
    std::wstring speedStr = std::to_wstring(speed);
    _speed.SetWindowTextW(speedStr.c_str());

    return TRUE;
}

BEGIN_MESSAGE_MAP(Display, CPropertyPage)
    ON_NOTIFY(UDN_DELTAPOS, SP_DELAY, &Display::OnDeltaposDelay)
    ON_NOTIFY(UDN_DELTAPOS, SP_SPEED, &Display::OnDeltaposSpeed)
    ON_CBN_SELCHANGE(CMB_POSITION, &Display::OnCbnSelchangePosition)
END_MESSAGE_MAP()

void Display::OnDeltaposDelay(NMHDR *pNMHDR, LRESULT *pResult) {
    LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
    pNMUpDown->iDelta *= 100;
    *pResult = 0;
}

void Display::OnDeltaposSpeed(NMHDR *pNMHDR, LRESULT *pResult) {
    LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
    pNMUpDown->iDelta *= 100;
    *pResult = 0;
}

void Display::OnCbnSelchangePosition() {
    int selIdx = _position.GetCurSel();
    CString selected;
    _position.GetLBText(selIdx, selected);
    BOOL isCustom = (selected == L"Custom");
    _lbX.EnableWindow(isCustom);
    _lbY.EnableWindow(isCustom);
    _customX.EnableWindow(isCustom);
    _customY.EnableWindow(isCustom);
}
<|endoftext|>