tdf#129905 tdf#160365 sw: don't always draw text boundary on frames
[LibreOffice.git] / unotools / source / config / confignode.cxx
blob93b89532072d58a96ef838845e8936731ca0cce3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <unotools/confignode.hxx>
21 #include <unotools/configpaths.hxx>
22 #include <comphelper/diagnose_ex.hxx>
23 #include <osl/diagnose.h>
24 #include <sal/log.hxx>
25 #include <com/sun/star/configuration/theDefaultProvider.hpp>
26 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
27 #include <com/sun/star/lang/XComponent.hpp>
28 #include <com/sun/star/util/XChangesBatch.hpp>
29 #include <com/sun/star/util/XStringEscape.hpp>
30 #include <com/sun/star/lang/XServiceInfo.hpp>
31 #include <com/sun/star/container/XNamed.hpp>
32 #include <com/sun/star/container/XNameContainer.hpp>
33 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
34 #include <comphelper/namedvaluecollection.hxx>
36 namespace utl
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::lang;
41 using namespace ::com::sun::star::util;
42 using namespace ::com::sun::star::beans;
43 using namespace ::com::sun::star::container;
44 using namespace ::com::sun::star::configuration;
46 //= OConfigurationNode
48 OConfigurationNode::OConfigurationNode(const Reference< XInterface >& _rxNode )
49 :m_bEscapeNames(false)
51 OSL_ENSURE(_rxNode.is(), "OConfigurationNode::OConfigurationNode: invalid node interface!");
52 if (_rxNode.is())
54 // collect all interfaces necessary
55 m_xHierarchyAccess.set(_rxNode, UNO_QUERY);
56 m_xDirectAccess.set(_rxNode, UNO_QUERY);
58 // reset _all_ interfaces if _one_ of them is not supported
59 if (!m_xHierarchyAccess.is() || !m_xDirectAccess.is())
61 m_xHierarchyAccess = nullptr;
62 m_xDirectAccess = nullptr;
65 // now for the non-critical interfaces
66 m_xReplaceAccess.set(_rxNode, UNO_QUERY);
67 m_xContainerAccess.set(_rxNode, UNO_QUERY);
70 Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY);
71 if (xConfigNodeComp.is())
72 startComponentListening(xConfigNodeComp);
74 if (isValid())
75 m_bEscapeNames = isSetNode() && Reference< XStringEscape >::query(m_xDirectAccess).is();
78 OConfigurationNode::OConfigurationNode(const OConfigurationNode& _rSource)
79 : OEventListenerAdapter()
80 , m_xHierarchyAccess(_rSource.m_xHierarchyAccess)
81 , m_xDirectAccess(_rSource.m_xDirectAccess)
82 , m_xReplaceAccess(_rSource.m_xReplaceAccess)
83 , m_xContainerAccess(_rSource.m_xContainerAccess)
84 , m_bEscapeNames(_rSource.m_bEscapeNames)
86 Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY);
87 if (xConfigNodeComp.is())
88 startComponentListening(xConfigNodeComp);
91 OConfigurationNode::OConfigurationNode(OConfigurationNode&& _rSource)
92 : OEventListenerAdapter()
93 , m_xHierarchyAccess(std::move(_rSource.m_xHierarchyAccess))
94 , m_xDirectAccess(std::move(_rSource.m_xDirectAccess))
95 , m_xReplaceAccess(std::move(_rSource.m_xReplaceAccess))
96 , m_xContainerAccess(std::move(_rSource.m_xContainerAccess))
97 , m_bEscapeNames(std::move(_rSource.m_bEscapeNames))
99 Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY);
100 if (xConfigNodeComp.is())
101 startComponentListening(xConfigNodeComp);
104 OConfigurationNode& OConfigurationNode::operator=(const OConfigurationNode& _rSource)
106 stopAllComponentListening();
108 m_xHierarchyAccess = _rSource.m_xHierarchyAccess;
109 m_xDirectAccess = _rSource.m_xDirectAccess;
110 m_xContainerAccess = _rSource.m_xContainerAccess;
111 m_xReplaceAccess = _rSource.m_xReplaceAccess;
112 m_bEscapeNames = _rSource.m_bEscapeNames;
114 Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY);
115 if (xConfigNodeComp.is())
116 startComponentListening(xConfigNodeComp);
118 return *this;
121 OConfigurationNode& OConfigurationNode::operator=(OConfigurationNode&& _rSource)
123 stopAllComponentListening();
125 m_xHierarchyAccess = std::move(_rSource.m_xHierarchyAccess);
126 m_xDirectAccess = std::move(_rSource.m_xDirectAccess);
127 m_xContainerAccess = std::move(_rSource.m_xContainerAccess);
128 m_xReplaceAccess = std::move(_rSource.m_xReplaceAccess);
129 m_bEscapeNames = std::move(_rSource.m_bEscapeNames);
131 Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY);
132 if (xConfigNodeComp.is())
133 startComponentListening(xConfigNodeComp);
135 return *this;
138 void OConfigurationNode::_disposing( const EventObject& _rSource )
140 Reference< XComponent > xDisposingSource(_rSource.Source, UNO_QUERY);
141 Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY);
142 if (xDisposingSource.get() == xConfigNodeComp.get())
143 clear();
146 OUString OConfigurationNode::getLocalName() const
148 OUString sLocalName;
151 Reference< XNamed > xNamed( m_xDirectAccess, UNO_QUERY_THROW );
152 sLocalName = xNamed->getName();
154 catch( const Exception& )
156 DBG_UNHANDLED_EXCEPTION("unotools");
158 return sLocalName;
161 OUString OConfigurationNode::normalizeName(const OUString& _rName, NAMEORIGIN _eOrigin) const
163 OUString sName(_rName);
164 if (m_bEscapeNames)
166 Reference< XStringEscape > xEscaper(m_xDirectAccess, UNO_QUERY);
167 if (xEscaper.is() && !sName.isEmpty())
171 if (NO_CALLER == _eOrigin)
172 sName = xEscaper->escapeString(sName);
173 else
174 sName = xEscaper->unescapeString(sName);
176 catch(Exception&)
178 DBG_UNHANDLED_EXCEPTION("unotools");
182 return sName;
185 Sequence< OUString > OConfigurationNode::getNodeNames() const noexcept
187 OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::getNodeNames: object is invalid!");
188 Sequence< OUString > aReturn;
189 if (m_xDirectAccess.is())
193 aReturn = m_xDirectAccess->getElementNames();
194 // normalize the names
195 std::transform(std::cbegin(aReturn), std::cend(aReturn), aReturn.getArray(),
196 [this](const OUString& rName) -> OUString { return normalizeName(rName, NO_CONFIGURATION); });
198 catch(Exception&)
200 TOOLS_WARN_EXCEPTION( "unotools", "OConfigurationNode::getNodeNames");
204 return aReturn;
207 bool OConfigurationNode::removeNode(const OUString& _rName) const noexcept
209 OSL_ENSURE(m_xContainerAccess.is(), "OConfigurationNode::removeNode: object is invalid!");
210 if (m_xContainerAccess.is())
214 OUString sName = normalizeName(_rName, NO_CALLER);
215 m_xContainerAccess->removeByName(sName);
216 return true;
218 catch (NoSuchElementException&)
220 SAL_WARN( "unotools", "OConfigurationNode::removeNode: there is no element named: " << _rName );
222 catch(Exception&)
224 TOOLS_WARN_EXCEPTION( "unotools", "OConfigurationNode::removeNode");
227 return false;
230 OConfigurationNode OConfigurationNode::insertNode(const OUString& _rName,const Reference< XInterface >& _xNode) const noexcept
232 if(_xNode.is())
236 OUString sName = normalizeName(_rName, NO_CALLER);
237 m_xContainerAccess->insertByName(sName, Any(_xNode));
238 // if we're here, all was ok ...
239 return OConfigurationNode( _xNode );
241 catch(const Exception&)
243 DBG_UNHANDLED_EXCEPTION("unotools");
246 // dispose the child if it has already been created, but could not be inserted
247 Reference< XComponent > xChildComp(_xNode, UNO_QUERY);
248 if (xChildComp.is())
249 try { xChildComp->dispose(); } catch(Exception&) { }
252 return OConfigurationNode();
255 OConfigurationNode OConfigurationNode::createNode(const OUString& _rName) const noexcept
257 Reference< XSingleServiceFactory > xChildFactory(m_xContainerAccess, UNO_QUERY);
258 OSL_ENSURE(xChildFactory.is(), "OConfigurationNode::createNode: object is invalid or read-only!");
260 if (xChildFactory.is()) // implies m_xContainerAccess.is()
262 Reference< XInterface > xNewChild;
265 xNewChild = xChildFactory->createInstance();
267 catch(const Exception&)
269 DBG_UNHANDLED_EXCEPTION("unotools");
271 return insertNode(_rName,xNewChild);
274 return OConfigurationNode();
277 OConfigurationNode OConfigurationNode::openNode(const OUString& _rPath) const noexcept
279 OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::openNode: object is invalid!");
280 OSL_ENSURE(m_xHierarchyAccess.is(), "OConfigurationNode::openNode: object is invalid!");
283 OUString sNormalized = normalizeName(_rPath, NO_CALLER);
285 Reference< XInterface > xNode;
286 if (m_xDirectAccess.is() && m_xDirectAccess->hasByName(sNormalized))
288 xNode.set(
289 m_xDirectAccess->getByName(sNormalized), css::uno::UNO_QUERY);
290 if (!xNode.is())
291 OSL_FAIL("OConfigurationNode::openNode: could not open the node!");
293 else if (m_xHierarchyAccess.is())
295 xNode.set(
296 m_xHierarchyAccess->getByHierarchicalName(_rPath),
297 css::uno::UNO_QUERY);
298 if (!xNode.is())
299 OSL_FAIL("OConfigurationNode::openNode: could not open the node!");
301 if (xNode.is())
302 return OConfigurationNode( xNode );
304 catch(const NoSuchElementException&)
306 SAL_WARN( "unotools", "OConfigurationNode::openNode: there is no element named " << _rPath );
308 catch(Exception&)
310 TOOLS_WARN_EXCEPTION( "unotools", "OConfigurationNode::openNode: caught an exception while retrieving the node!");
312 return OConfigurationNode();
315 bool OConfigurationNode::isSetNode() const
317 bool bIsSet = false;
318 Reference< XServiceInfo > xSI(m_xHierarchyAccess, UNO_QUERY);
319 if (xSI.is())
321 try { bIsSet = xSI->supportsService("com.sun.star.configuration.SetAccess"); }
322 catch(Exception&) { }
324 return bIsSet;
327 bool OConfigurationNode::hasByHierarchicalName( const OUString& _rName ) const noexcept
329 OSL_ENSURE( m_xHierarchyAccess.is(), "OConfigurationNode::hasByHierarchicalName: no hierarchy access!" );
332 if ( m_xHierarchyAccess.is() )
334 OUString sName = normalizeName( _rName, NO_CALLER );
335 return m_xHierarchyAccess->hasByHierarchicalName( sName );
338 catch(Exception&)
341 return false;
344 bool OConfigurationNode::hasByName(const OUString& _rName) const noexcept
346 OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::hasByName: object is invalid!");
349 OUString sName = normalizeName(_rName, NO_CALLER);
350 if (m_xDirectAccess.is())
351 return m_xDirectAccess->hasByName(sName);
353 catch(Exception&)
356 return false;
359 bool OConfigurationNode::setNodeValue(const OUString& _rPath, const Any& _rValue) const noexcept
361 bool bResult = false;
363 OSL_ENSURE(m_xReplaceAccess.is(), "OConfigurationNode::setNodeValue: object is invalid!");
364 if (m_xReplaceAccess.is())
368 // check if _rPath is a level-1 path
369 OUString sNormalizedName = normalizeName(_rPath, NO_CALLER);
370 if (m_xReplaceAccess->hasByName(sNormalizedName))
372 m_xReplaceAccess->replaceByName(sNormalizedName, _rValue);
373 bResult = true;
376 // check if the name refers to an indirect descendant
377 else if (m_xHierarchyAccess.is() && m_xHierarchyAccess->hasByHierarchicalName(_rPath))
379 OSL_ASSERT(!_rPath.isEmpty());
381 OUString sParentPath, sLocalName;
383 if ( splitLastFromConfigurationPath(_rPath, sParentPath, sLocalName) )
385 OConfigurationNode aParentAccess = openNode(sParentPath);
386 if (aParentAccess.isValid())
387 bResult = aParentAccess.setNodeValue(sLocalName, _rValue);
389 else
391 m_xReplaceAccess->replaceByName(sLocalName, _rValue);
392 bResult = true;
397 catch(Exception&)
399 TOOLS_WARN_EXCEPTION( "unotools", "OConfigurationNode::setNodeValue: could not replace the value");
403 return bResult;
406 Any OConfigurationNode::getNodeValue(const OUString& _rPath) const noexcept
408 OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::hasByName: object is invalid!");
409 OSL_ENSURE(m_xHierarchyAccess.is(), "OConfigurationNode::hasByName: object is invalid!");
410 Any aReturn;
413 OUString sNormalizedPath = normalizeName(_rPath, NO_CALLER);
414 if (m_xDirectAccess.is() && m_xDirectAccess->hasByName(sNormalizedPath) )
416 aReturn = m_xDirectAccess->getByName(sNormalizedPath);
418 else if (m_xHierarchyAccess.is())
420 aReturn = m_xHierarchyAccess->getByHierarchicalName(_rPath);
423 catch(const NoSuchElementException&)
425 DBG_UNHANDLED_EXCEPTION("unotools");
427 return aReturn;
430 void OConfigurationNode::clear() noexcept
432 m_xHierarchyAccess.clear();
433 m_xDirectAccess.clear();
434 m_xReplaceAccess.clear();
435 m_xContainerAccess.clear();
438 //= helper
440 namespace
443 Reference< XMultiServiceFactory > lcl_getConfigProvider( const Reference<XComponentContext> & i_rContext )
447 Reference< XMultiServiceFactory > xProvider = theDefaultProvider::get( i_rContext );
448 return xProvider;
450 catch ( const Exception& )
452 DBG_UNHANDLED_EXCEPTION("unotools");
454 return nullptr;
457 Reference< XInterface > lcl_createConfigurationRoot( const Reference< XMultiServiceFactory >& i_rxConfigProvider,
458 const OUString& i_rNodePath, const bool i_bUpdatable, const sal_Int32 i_nDepth )
460 ENSURE_OR_RETURN( i_rxConfigProvider.is(), "invalid provider", nullptr );
463 ::comphelper::NamedValueCollection aArgs;
464 aArgs.put( "nodepath", i_rNodePath );
465 aArgs.put( "depth", i_nDepth );
467 OUString sAccessService( i_bUpdatable ?
468 OUString( "com.sun.star.configuration.ConfigurationUpdateAccess" ) :
469 OUString( "com.sun.star.configuration.ConfigurationAccess" ));
471 Reference< XInterface > xRoot(
472 i_rxConfigProvider->createInstanceWithArguments( sAccessService, aArgs.getWrappedPropertyValues() ),
473 UNO_SET_THROW
475 return xRoot;
477 catch ( const Exception& )
479 DBG_UNHANDLED_EXCEPTION("unotools");
481 return nullptr;
485 OConfigurationTreeRoot::OConfigurationTreeRoot( const Reference< XInterface >& _rxRootNode )
486 :OConfigurationNode( _rxRootNode )
487 ,m_xCommitter( _rxRootNode, UNO_QUERY )
491 OConfigurationTreeRoot::OConfigurationTreeRoot( const Reference<XComponentContext> & i_rContext, const OUString& i_rNodePath, const bool i_bUpdatable )
492 :OConfigurationNode( lcl_createConfigurationRoot( lcl_getConfigProvider( i_rContext ),
493 i_rNodePath, i_bUpdatable, -1 ) )
494 ,m_xCommitter()
496 if ( i_bUpdatable )
498 m_xCommitter.set( getUNONode(), UNO_QUERY );
499 OSL_ENSURE( m_xCommitter.is(), "OConfigurationTreeRoot::OConfigurationTreeRoot: could not create an updatable node!" );
503 void OConfigurationTreeRoot::clear() noexcept
505 OConfigurationNode::clear();
506 m_xCommitter.clear();
509 bool OConfigurationTreeRoot::commit() const noexcept
511 OSL_ENSURE(isValid(), "OConfigurationTreeRoot::commit: object is invalid!");
512 if (!isValid())
513 return false;
514 OSL_ENSURE(m_xCommitter.is(), "OConfigurationTreeRoot::commit: I'm a readonly node!");
515 if (!m_xCommitter.is())
516 return false;
520 m_xCommitter->commitChanges();
521 return true;
523 catch(const Exception&)
525 DBG_UNHANDLED_EXCEPTION("unotools");
527 return false;
530 OConfigurationTreeRoot OConfigurationTreeRoot::createWithProvider(const Reference< XMultiServiceFactory >& _rxConfProvider, const OUString& _rPath, sal_Int32 _nDepth, CREATION_MODE _eMode)
532 Reference< XInterface > xRoot( lcl_createConfigurationRoot(
533 _rxConfProvider, _rPath, _eMode != CM_READONLY, _nDepth ) );
534 if ( xRoot.is() )
535 return OConfigurationTreeRoot( xRoot );
536 return OConfigurationTreeRoot();
539 OConfigurationTreeRoot OConfigurationTreeRoot::createWithComponentContext( const Reference< XComponentContext >& _rxContext, const OUString& _rPath, sal_Int32 _nDepth, CREATION_MODE _eMode )
541 return createWithProvider( lcl_getConfigProvider( _rxContext ), _rPath, _nDepth, _eMode );
544 OConfigurationTreeRoot OConfigurationTreeRoot::tryCreateWithComponentContext( const Reference< XComponentContext >& rxContext,
545 const OUString& _rPath, sal_Int32 _nDepth , CREATION_MODE _eMode )
547 OSL_ENSURE( rxContext.is(), "OConfigurationTreeRoot::tryCreateWithComponentContext: invalid XComponentContext!" );
550 Reference< XMultiServiceFactory > xConfigFactory = theDefaultProvider::get( rxContext );
551 return createWithProvider( xConfigFactory, _rPath, _nDepth, _eMode );
553 catch(const Exception&)
555 // silence this, 'cause the contract of this method states "no assertions"
557 return OConfigurationTreeRoot();
560 } // namespace utl
562 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */