Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / configmgr / source / childaccess.cxx
blob68bc0b01351c7def605e25b569f856655e8c30dc
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 <sal/config.h>
22 #include <cassert>
23 #include <vector>
25 #include <com/sun/star/container/XChild.hpp>
26 #include <com/sun/star/lang/NoSupportException.hpp>
27 #include <com/sun/star/lang/XUnoTunnel.hpp>
28 #include <com/sun/star/uno/Any.hxx>
29 #include <com/sun/star/uno/Reference.hxx>
30 #include <com/sun/star/uno/Sequence.hxx>
31 #include <com/sun/star/uno/Type.hxx>
32 #include <com/sun/star/uno/XInterface.hpp>
33 #include <cppu/unotype.hxx>
34 #include <cppuhelper/queryinterface.hxx>
35 #include <cppuhelper/weak.hxx>
36 #include <comphelper/servicehelper.hxx>
37 #include <osl/mutex.hxx>
38 #include <rtl/ref.hxx>
39 #include <rtl/ustrbuf.hxx>
40 #include <rtl/ustring.hxx>
41 #include <sal/types.h>
43 #include "access.hxx"
44 #include "childaccess.hxx"
45 #include "components.hxx"
46 #include "data.hxx"
47 #include "localizedpropertynode.hxx"
48 #include "localizedvaluenode.hxx"
49 #include "lock.hxx"
50 #include "modifications.hxx"
51 #include "node.hxx"
52 #include "propertynode.hxx"
53 #include "rootaccess.hxx"
54 #include "type.hxx"
56 namespace configmgr {
58 namespace
60 class theChildAccessUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theChildAccessUnoTunnelId > {};
63 css::uno::Sequence< sal_Int8 > const & ChildAccess::getTunnelId()
65 return theChildAccessUnoTunnelId::get().getSeq();
68 ChildAccess::ChildAccess(
69 Components & components, rtl::Reference< RootAccess > const & root,
70 rtl::Reference< Access > const & parent, OUString const & name,
71 rtl::Reference< Node > const & node):
72 Access(components), root_(root), parent_(parent), name_(name), node_(node),
73 inTransaction_(false),
74 lock_( lock() )
76 assert(root.is() && parent.is() && node.is());
79 ChildAccess::ChildAccess(
80 Components & components, rtl::Reference< RootAccess > const & root,
81 rtl::Reference< Node > const & node):
82 Access(components), root_(root), node_(node), inTransaction_(false),
83 lock_( lock() )
85 assert(root.is() && node.is());
88 std::vector<OUString> ChildAccess::getAbsolutePath() {
89 rtl::Reference< Access > parent(getParentAccess());
90 assert(parent.is());
91 std::vector<OUString> path(parent->getAbsolutePath());
92 path.push_back(name_);
93 return path;
96 std::vector<OUString> ChildAccess::getRelativePath() {
97 std::vector<OUString> path;
98 rtl::Reference< Access > parent(getParentAccess());
99 if (parent.is()) {
100 path = parent->getRelativePath();
102 path.push_back(name_);
103 return path;
106 OUString ChildAccess::getRelativePathRepresentation() {
107 OUStringBuffer path(128);
108 rtl::Reference< Access > parent(getParentAccess());
109 if (parent.is()) {
110 path.append(parent->getRelativePathRepresentation());
111 if (!path.isEmpty()) {
112 path.append('/');
115 path.append(Data::createSegment(node_->getTemplateName(), name_));
116 return path.makeStringAndClear();
119 rtl::Reference< Node > ChildAccess::getNode() {
120 return node_;
123 bool ChildAccess::isFinalized() {
124 return node_->getFinalized() != Data::NO_LAYER ||
125 (parent_.is() && parent_->isFinalized());
128 OUString ChildAccess::getNameInternal() {
129 return name_;
132 rtl::Reference< RootAccess > ChildAccess::getRootAccess() {
133 return root_;
136 rtl::Reference< Access > ChildAccess::getParentAccess() {
137 return parent_;
140 void ChildAccess::acquire() throw () {
141 Access::acquire();
144 void ChildAccess::release() throw () {
145 Access::release();
148 css::uno::Reference< css::uno::XInterface > ChildAccess::getParent()
150 assert(thisIs(IS_ANY));
151 osl::MutexGuard g(*lock_);
152 checkLocalizedPropertyAccess();
153 return static_cast< cppu::OWeakObject * >(parent_.get());
156 void ChildAccess::setParent(css::uno::Reference< css::uno::XInterface > const &)
158 assert(thisIs(IS_ANY));
159 osl::MutexGuard g(*lock_);
160 checkLocalizedPropertyAccess();
161 throw css::lang::NoSupportException(
162 "setParent", static_cast< cppu::OWeakObject * >(this));
165 sal_Int64 ChildAccess::getSomething(
166 css::uno::Sequence< sal_Int8 > const & aIdentifier)
168 assert(thisIs(IS_ANY));
169 osl::MutexGuard g(*lock_);
170 checkLocalizedPropertyAccess();
171 return aIdentifier == getTunnelId()
172 ? reinterpret_cast< sal_Int64 >(this) : 0;
175 void ChildAccess::bind(
176 rtl::Reference< RootAccess > const & root,
177 rtl::Reference< Access > const & parent, OUString const & name)
178 throw ()
180 assert(!parent_.is() && root.is() && parent.is() && !name.isEmpty());
181 root_ = root;
182 parent_ = parent;
183 name_ = name;
186 void ChildAccess::unbind() throw () {
187 assert(parent_.is());
188 parent_->releaseChild(name_);
189 parent_.clear();
190 inTransaction_ = true;
193 void ChildAccess::committed() {
194 inTransaction_ = false;
197 void ChildAccess::setNode(rtl::Reference< Node > const & node) {
198 node_ = node;
201 void ChildAccess::setProperty(
202 css::uno::Any const & value, Modifications * localModifications)
204 assert(localModifications != nullptr);
205 Type type = TYPE_ERROR;
206 bool isNillable = false;
207 switch (node_->kind()) {
208 case Node::KIND_PROPERTY:
210 PropertyNode * prop = static_cast< PropertyNode * >(node_.get());
211 type = prop->getStaticType();
212 isNillable = prop->isNillable();
214 break;
215 case Node::KIND_LOCALIZED_PROPERTY:
217 OUString locale(getRootAccess()->getLocale());
218 if (!Components::allLocales(locale)) {
219 rtl::Reference< ChildAccess > child(getChild(locale));
220 if (child.is()) {
221 child->setProperty(value, localModifications);
222 } else {
223 insertLocalizedValueChild(
224 locale, value, localModifications);
226 return;
229 break;
230 case Node::KIND_LOCALIZED_VALUE:
232 LocalizedPropertyNode * locprop =
233 static_cast< LocalizedPropertyNode * >(getParentNode().get());
234 type = locprop->getStaticType();
235 isNillable = locprop->isNillable();
237 break;
238 default:
239 break;
241 checkValue(value, type, isNillable);
242 getParentAccess()->markChildAsModified(this);
243 changedValue_.reset(new css::uno::Any(value));
244 localModifications->add(getRelativePath());
248 css::uno::Any ChildAccess::asValue()
250 if (changedValue_ != nullptr)
252 return *changedValue_;
254 css::uno::Any value;
255 if (!asSimpleValue(node_, value, getComponents()))
257 if (node_->kind() == Node::KIND_LOCALIZED_PROPERTY)
259 OUString locale(getRootAccess()->getLocale());
260 if (!Components::allLocales(locale)) {
261 rtl::Reference< ChildAccess > child(getChild("*" + locale));
262 // As a last resort, return a nil value even though it may be
263 // illegal for the given property:
264 return child.is() ? child->asValue() : css::uno::Any();
267 value <<= css::uno::Reference< css::uno::XInterface >(
268 static_cast< cppu::OWeakObject * >(this));
270 return value;
273 /// Can we quickly extract a simple value into value ? if so returns true
274 bool ChildAccess::asSimpleValue(const rtl::Reference< Node > &rNode,
275 css::uno::Any &value,
276 Components &components)
278 switch (rNode->kind()) {
279 case Node::KIND_PROPERTY:
280 value = static_cast< PropertyNode * >(rNode.get())->getValue(components);
281 return true;
282 case Node::KIND_LOCALIZED_VALUE:
283 value = static_cast< LocalizedValueNode * >(rNode.get())->getValue();
284 return true;
285 default:
286 return false;
290 void ChildAccess::commitChanges(bool valid, Modifications * globalModifications)
292 assert(globalModifications != nullptr);
293 commitChildChanges(valid, globalModifications);
294 if (valid && changedValue_ != nullptr)
296 std::vector<OUString> path(getAbsolutePath());
297 getComponents().addModification(path);
298 globalModifications->add(path);
299 switch (node_->kind()) {
300 case Node::KIND_PROPERTY:
301 static_cast< PropertyNode * >(node_.get())->setValue(
302 Data::NO_LAYER, *changedValue_);
303 break;
304 case Node::KIND_LOCALIZED_VALUE:
305 static_cast< LocalizedValueNode * >(node_.get())->setValue(
306 Data::NO_LAYER, *changedValue_);
307 break;
308 default:
309 assert(false); // this cannot happen
310 break;
313 changedValue_.reset();
316 ChildAccess::~ChildAccess() {
317 osl::MutexGuard g(*lock_);
318 if (parent_.is()) {
319 parent_->releaseChild(name_);
323 void ChildAccess::addTypes(std::vector< css::uno::Type > * types) const {
324 assert(types != nullptr);
325 types->push_back(cppu::UnoType< css::container::XChild >::get());
326 types->push_back(cppu::UnoType< css::lang::XUnoTunnel >::get());
329 void ChildAccess::addSupportedServiceNames(
330 std::vector<OUString> * services)
332 assert(services != nullptr);
333 services->push_back(
334 getParentNode()->kind() == Node::KIND_GROUP
335 ? OUString("com.sun.star.configuration.GroupElement")
336 : OUString("com.sun.star.configuration.SetElement"));
339 css::uno::Any ChildAccess::queryInterface(css::uno::Type const & aType)
341 assert(thisIs(IS_ANY));
342 osl::MutexGuard g(*lock_);
343 checkLocalizedPropertyAccess();
344 css::uno::Any res(Access::queryInterface(aType));
345 return res.hasValue()
346 ? res
347 : cppu::queryInterface(
348 aType, static_cast< css::container::XChild * >(this),
349 static_cast< css::lang::XUnoTunnel * >(this));
354 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */