/* -*- 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 {
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();
}
const 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 cppu::getXWeak(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(
u"setParent"_ustr, getXWeak());
}
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 >(getXWeak());
}
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_, true);
break;
case Node::KIND_LOCALIZED_VALUE:
static_cast< LocalizedValueNode * >(node_.get())->setValue(
Data::NO_LAYER, *changedValue_, true);
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
? u"com.sun.star.configuration.GroupElement"_ustr
: u"com.sun.star.configuration.SetElement"_ustr);
}
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));
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V530 The return value of function 'append' is required to be utilized.