diff options
Diffstat (limited to '')
-rw-r--r-- | configmgr/source/childaccess.cxx | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/configmgr/source/childaccess.cxx b/configmgr/source/childaccess.cxx new file mode 100644 index 000000000..60a11006b --- /dev/null +++ b/configmgr/source/childaccess.cxx @@ -0,0 +1,350 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <cassert> +#include <utility> +#include <vector> + +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/lang/NoSupportException.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Type.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <cppu/unotype.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/weak.hxx> +#include <comphelper/servicehelper.hxx> +#include <osl/mutex.hxx> +#include <rtl/ref.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/ustring.hxx> +#include <sal/types.h> + +#include "access.hxx" +#include "childaccess.hxx" +#include "components.hxx" +#include "data.hxx" +#include "localizedpropertynode.hxx" +#include "localizedvaluenode.hxx" +#include "lock.hxx" +#include "modifications.hxx" +#include "node.hxx" +#include "propertynode.hxx" +#include "rootaccess.hxx" +#include "type.hxx" + +namespace configmgr { + +css::uno::Sequence< sal_Int8 > const & ChildAccess::getUnoTunnelId() +{ + static const comphelper::UnoIdInit theChildAccessUnoTunnelId; + return theChildAccessUnoTunnelId.getSeq(); +} + +ChildAccess::ChildAccess( + Components & components, rtl::Reference< RootAccess > const & root, + rtl::Reference< Access > const & parent, OUString name, + rtl::Reference< Node > const & node): + Access(components), root_(root), parent_(parent), name_(std::move(name)), node_(node), + inTransaction_(false), + lock_( lock() ) +{ + assert(root.is() && parent.is() && node.is()); +} + +ChildAccess::ChildAccess( + Components & components, rtl::Reference< RootAccess > const & root, + rtl::Reference< Node > const & node): + Access(components), root_(root), node_(node), inTransaction_(false), + lock_( lock() ) +{ + assert(root.is() && node.is()); +} + +std::vector<OUString> ChildAccess::getAbsolutePath() { + rtl::Reference< Access > parent(getParentAccess()); + assert(parent.is()); + std::vector<OUString> path(parent->getAbsolutePath()); + path.push_back(name_); + return path; +} + +std::vector<OUString> ChildAccess::getRelativePath() { + std::vector<OUString> path; + rtl::Reference< Access > parent(getParentAccess()); + if (parent.is()) { + path = parent->getRelativePath(); + } + path.push_back(name_); + return path; +} + +OUString ChildAccess::getRelativePathRepresentation() { + OUStringBuffer path(128); + rtl::Reference< Access > parent(getParentAccess()); + if (parent.is()) { + path.append(parent->getRelativePathRepresentation()); + if (!path.isEmpty()) { + path.append('/'); + } + } + path.append(Data::createSegment(node_->getTemplateName(), name_)); + return path.makeStringAndClear(); +} + +rtl::Reference< Node > ChildAccess::getNode() { + return node_; +} + +bool ChildAccess::isFinalized() { + return node_->getFinalized() != Data::NO_LAYER || + (parent_.is() && parent_->isFinalized()); +} + +const OUString & ChildAccess::getNameInternal() { + return name_; +} + +rtl::Reference< RootAccess > ChildAccess::getRootAccess() { + return root_; +} + +rtl::Reference< Access > ChildAccess::getParentAccess() { + return parent_; +} + +void ChildAccess::acquire() noexcept { + Access::acquire(); +} + +void ChildAccess::release() noexcept { + Access::release(); +} + +css::uno::Reference< css::uno::XInterface > ChildAccess::getParent() +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return static_cast< cppu::OWeakObject * >(parent_.get()); +} + +void ChildAccess::setParent(css::uno::Reference< css::uno::XInterface > const &) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + throw css::lang::NoSupportException( + "setParent", static_cast< cppu::OWeakObject * >(this)); +} + +sal_Int64 ChildAccess::getSomething( + css::uno::Sequence< sal_Int8 > const & aIdentifier) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return comphelper::getSomethingImpl(aIdentifier, this); +} + +void ChildAccess::bind( + rtl::Reference< RootAccess > const & root, + rtl::Reference< Access > const & parent, OUString const & name) + noexcept +{ + assert(!parent_.is() && root.is() && parent.is() && !name.isEmpty()); + root_ = root; + parent_ = parent; + name_ = name; +} + +void ChildAccess::unbind() noexcept { + assert(parent_.is()); + parent_->releaseChild(name_); + parent_.clear(); + inTransaction_ = true; +} + +void ChildAccess::committed() { + inTransaction_ = false; +} + +void ChildAccess::setNode(rtl::Reference< Node > const & node) { + node_ = node; +} + +void ChildAccess::setProperty( + css::uno::Any const & value, Modifications * localModifications) +{ + assert(localModifications != nullptr); + Type type = TYPE_ERROR; + bool isNillable = false; + switch (node_->kind()) { + case Node::KIND_PROPERTY: + { + PropertyNode * prop = static_cast< PropertyNode * >(node_.get()); + type = prop->getStaticType(); + isNillable = prop->isNillable(); + } + break; + case Node::KIND_LOCALIZED_PROPERTY: + { + OUString locale(getRootAccess()->getLocale()); + if (!Components::allLocales(locale)) { + rtl::Reference< ChildAccess > child(getChild(locale)); + if (child.is()) { + child->setProperty(value, localModifications); + } else { + insertLocalizedValueChild( + locale, value, localModifications); + } + return; + } + } + break; + case Node::KIND_LOCALIZED_VALUE: + { + LocalizedPropertyNode * locprop = + static_cast< LocalizedPropertyNode * >(getParentNode().get()); + type = locprop->getStaticType(); + isNillable = locprop->isNillable(); + } + break; + default: + break; + } + checkValue(value, type, isNillable); + getParentAccess()->markChildAsModified(this); + changedValue_.emplace(value); + localModifications->add(getRelativePath()); +} + + +css::uno::Any ChildAccess::asValue() +{ + if (changedValue_) + { + return *changedValue_; + } + css::uno::Any value; + if (!asSimpleValue(node_, value, getComponents())) + { + if (node_->kind() == Node::KIND_LOCALIZED_PROPERTY) + { + OUString locale(getRootAccess()->getLocale()); + if (!Components::allLocales(locale)) { + rtl::Reference< ChildAccess > child(getChild("*" + locale)); + // As a last resort, return a nil value even though it may be + // illegal for the given property: + return child.is() ? child->asValue() : css::uno::Any(); + } + } + value <<= css::uno::Reference< css::uno::XInterface >( + static_cast< cppu::OWeakObject * >(this)); + } + return value; +} + +/// Can we quickly extract a simple value into value ? if so returns true +bool ChildAccess::asSimpleValue(const rtl::Reference< Node > &rNode, + css::uno::Any &value, + Components &components) +{ + switch (rNode->kind()) { + case Node::KIND_PROPERTY: + value = static_cast< PropertyNode * >(rNode.get())->getValue(components); + return true; + case Node::KIND_LOCALIZED_VALUE: + value = static_cast< LocalizedValueNode * >(rNode.get())->getValue(); + return true; + default: + return false; + } +} + +void ChildAccess::commitChanges(bool valid, Modifications * globalModifications) +{ + assert(globalModifications != nullptr); + commitChildChanges(valid, globalModifications); + if (valid && changedValue_) + { + std::vector<OUString> path(getAbsolutePath()); + getComponents().addModification(path); + globalModifications->add(path); + switch (node_->kind()) { + case Node::KIND_PROPERTY: + static_cast< PropertyNode * >(node_.get())->setValue( + Data::NO_LAYER, *changedValue_); + break; + case Node::KIND_LOCALIZED_VALUE: + static_cast< LocalizedValueNode * >(node_.get())->setValue( + Data::NO_LAYER, *changedValue_); + break; + default: + assert(false); // this cannot happen + break; + } + } + changedValue_.reset(); +} + +ChildAccess::~ChildAccess() { + osl::MutexGuard g(*lock_); + if (parent_.is()) { + parent_->releaseChild(name_); + } +} + +void ChildAccess::addTypes(std::vector< css::uno::Type > * types) const { + assert(types != nullptr); + types->push_back(cppu::UnoType< css::container::XChild >::get()); + types->push_back(cppu::UnoType< css::lang::XUnoTunnel >::get()); +} + +void ChildAccess::addSupportedServiceNames( + std::vector<OUString> * services) +{ + assert(services != nullptr); + services->push_back( + getParentNode()->kind() == Node::KIND_GROUP + ? OUString("com.sun.star.configuration.GroupElement") + : OUString("com.sun.star.configuration.SetElement")); +} + +css::uno::Any ChildAccess::queryInterface(css::uno::Type const & aType) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + css::uno::Any res(Access::queryInterface(aType)); + return res.hasValue() + ? res + : cppu::queryInterface( + aType, static_cast< css::container::XChild * >(this), + static_cast< css::lang::XUnoTunnel * >(this)); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |