office-gobmx/configmgr/source/backend/updatedispatch.cxx
Rüdiger Timm e44f447c40 INTEGRATION: CWS changefileheader (1.11.16); FILE MERGED
2008/04/01 12:27:19 thb 1.11.16.2: #i85898# Stripping all external header guards
2008/03/31 12:22:41 rt 1.11.16.1: #i87441# Change license header to LPGL v3.
2008-04-11 11:34:10 +00:00

503 lines
17 KiB
C++

/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2008 by Sun Microsystems, Inc.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: updatedispatch.cxx,v $
* $Revision: 1.12 $
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org 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 version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_configmgr.hxx"
#include "updatedispatch.hxx"
#include "configpath.hxx"
#include "node.hxx"
#include "treeaccessor.hxx"
#include "valuenodeaccess.hxx"
#include "groupnodeaccess.hxx"
#include "setnodeaccess.hxx"
#include "matchlocale.hxx"
#include <com/sun/star/configuration/backend/XUpdateHandler.hpp>
#include <com/sun/star/configuration/backend/NodeAttribute.hpp>
namespace configmgr
{
// -----------------------------------------------------------------------------
namespace backend
{
// -----------------------------------------------------------------------------
UpdateDispatcher::UpdateDispatcher(UpdateHandler const & _xUpdateHandler, OUString const & _aLocale)
: m_pContextPath(NULL)
, m_xUpdateHandler(_xUpdateHandler)
, m_aLocale(_aLocale)
, m_aElementName()
, m_bInValueSet(false)
, m_bInLocalizedValues(false)
{
}
// -----------------------------------------------------------------------------
UpdateDispatcher::~UpdateDispatcher()
{
}
// -----------------------------------------------------------------------------
void UpdateDispatcher::dispatchUpdate(configuration::AbsolutePath const & _aRootPath, SubtreeChange const& _anUpdate)
{
if (!m_xUpdateHandler.is())
{
OUString sMsg( RTL_CONSTASCII_USTRINGPARAM("ERROR: Cannot dispatch update - no handler found") );
throw uno::RuntimeException(sMsg,NULL);
}
OSL_PRECOND( !_aRootPath.isRoot(), "Cannot apply update, where root is outside a component" );
OSL_PRECOND( m_pContextPath == NULL, "Update Dispatcher already has a context path" );
if (!_aRootPath.getParentPath().isRoot())
{
OSL_ENSURE(false,"Obsolete functionality used: starting update with non-empty context");
m_pContextPath = &_aRootPath;
}
this->startUpdate();
this->applyToChange(_anUpdate);
this->endUpdate();
m_pContextPath = NULL;
}
// -----------------------------------------------------------------------------
void UpdateDispatcher::startUpdate()
{
m_xUpdateHandler->startUpdate();
m_bInValueSet = false;
m_bInLocalizedValues = false;
m_aElementName = OUString();
if (m_pContextPath)
{
configuration::AbsolutePath::Iterator it = m_pContextPath->begin();
configuration::AbsolutePath::Iterator stop = m_pContextPath->end();
OSL_ASSERT(it != stop);
--stop;
for ( ; it != stop; ++it)
{
m_xUpdateHandler->modifyNode(it->getName().toString(),0,0,false);
}
}
}
// -----------------------------------------------------------------------------
void UpdateDispatcher::endUpdate()
{
if (m_pContextPath)
{
configuration::AbsolutePath::Iterator it = m_pContextPath->begin();
configuration::AbsolutePath::Iterator stop = m_pContextPath->end();
OSL_ASSERT(it != stop);
--stop;
for ( ; it != stop; ++it)
{
m_xUpdateHandler->endNode();
}
}
m_xUpdateHandler->endUpdate();
}
// -----------------------------------------------------------------------------
void UpdateDispatcher::handle(ValueChange const& aValueNode)
{
// special case: doing members of a localized property (as set)
if (m_bInLocalizedValues)
{
OUString aLocale = aValueNode.getNodeName();
if (aLocale.getLength())
{
if ( aValueNode.isToDefault() )
m_xUpdateHandler->resetPropertyValueForLocale( aLocale );
else
m_xUpdateHandler->setPropertyValueForLocale( aValueNode.getNewValue(), aLocale );
}
else
{
if ( aValueNode.isToDefault() )
m_xUpdateHandler->resetPropertyValue( );
else
m_xUpdateHandler->setPropertyValue( aValueNode.getNewValue() );
}
return;
}
// normal case: updating a single property
switch (aValueNode.getMode())
{
case ValueChange::wasDefault:
if (aValueNode.isReplacedValue())
{
OSL_ENSURE(m_bInValueSet, "UpdateDispatcher: Cannot add/replace a value in a nonextensible node");
OSL_ENSURE(!aValueNode.isLocalizedValue(), "UpdateDispatcher: Cannot add a localized value in a layer");
sal_Int16 nAttr = getUpdateAttributes(aValueNode.getAttributes(),true);
if (aValueNode.getNewValue().hasValue())
{
m_xUpdateHandler->addOrReplacePropertyWithValue( aValueNode.getNodeName(),
nAttr,
aValueNode.getNewValue());
}
else
{
m_xUpdateHandler->addOrReplaceProperty( aValueNode.getNodeName(),
nAttr,
aValueNode.getValueType());
}
break;
}
// else fall thru to changeValue case
case ValueChange::changeValue:
{
sal_Int16 nAttr = getUpdateAttributes(aValueNode.getAttributes(),false);
sal_Int16 nAttrMask = getUpdateAttributeMask(aValueNode.getAttributes());
m_xUpdateHandler->modifyProperty( aValueNode.getNodeName(),
nAttr, nAttrMask,
aValueNode.getValueType() );
if (aValueNode.isLocalizedValue() && m_aLocale.getLength())
{
m_xUpdateHandler->setPropertyValueForLocale( aValueNode.getNewValue(), m_aLocale );
}
else
{
m_xUpdateHandler->setPropertyValue( aValueNode.getNewValue() );
}
m_xUpdateHandler->endProperty();
}
break;
case ValueChange::setToDefault:
m_xUpdateHandler->resetProperty( aValueNode.getNodeName() );
break;
case ValueChange::changeDefault:
OSL_ENSURE(false, "Illegal mode in ValueChange");
break;
default:
OSL_ENSURE(false, "Illegal mode in ValueChange");
break;
};
}
// -----------------------------------------------------------------------------
void UpdateDispatcher::handle(AddNode const& aAddNode)
{
data::TreeSegment aAddedTree = aAddNode.getNewTree();
OSL_ENSURE(aAddedTree.is(), "AddNode has no new data -> cannot add anything");
OSL_ENSURE( !aAddedTree.is() ||
((m_bInValueSet||m_bInLocalizedValues) == aAddedTree.getSegmentRootNode()->isValue()),
"Found added subtree in value set (extensible group)\n" );
this->visitTree( aAddedTree.getTreeAccess() );
}
// -----------------------------------------------------------------------------
void UpdateDispatcher::handle(RemoveNode const& aRemoveNode)
{
OSL_ENSURE( !m_bInLocalizedValues, "UpdateDispatcher: Removing values for a specific locale is currently not supported");
data::TreeSegment aRemovedTree = aRemoveNode.getRemovedTree();
OSL_ENSURE( !aRemovedTree.is() ||
((m_bInValueSet||m_bInLocalizedValues) == aRemovedTree.getSegmentRootNode()->isValue()),
"Found removed subtree in value set (extensible group)\n" );
if (m_bInLocalizedValues)
OSL_TRACE("configmgr: UpdateDispatcher - Removing value for locale ignored");
else if (m_bInValueSet)
m_xUpdateHandler->removeProperty( aRemoveNode.getNodeName() );
else
m_xUpdateHandler->removeNode( aRemoveNode.getNodeName() );
}
// -----------------------------------------------------------------------------
void UpdateDispatcher::handle(SubtreeChange const& aSubtree)
{
OSL_ENSURE( !m_bInLocalizedValues, "UpdateDispatcher: A localized value cannot be a complete subtree");
OSL_ENSURE( !m_bInValueSet, "UpdateDispatcher: A dynamic property cannot be a complete subtree");
sal_Int16 nAttr = getUpdateAttributes(aSubtree.getAttributes(),false);
sal_Int16 nAttrMask = getUpdateAttributeMask(aSubtree.getAttributes());
if (isLocalizedValueSet(aSubtree))
{
m_xUpdateHandler->modifyProperty( aSubtree.getNodeName(),
nAttr, nAttrMask,
uno::Type() );
m_bInLocalizedValues = true;
this->applyToChildren(aSubtree);
m_bInLocalizedValues = false;
m_xUpdateHandler->endProperty();
}
else
{
m_xUpdateHandler->modifyNode( aSubtree.getNodeName(),
nAttr, nAttrMask,
aSubtree.isToDefault() );
m_bInValueSet = isValueSet(aSubtree);
this->applyToChildren(aSubtree);
m_bInValueSet = false;
m_xUpdateHandler->endNode();
}
}
// -----------------------------------------------------------------------------
data::SetVisitor::Result UpdateDispatcher::handle(data::ValueNodeAccess const& _aNode)
{
OUString aName;
// special case: doing members of a localized property (as set)
if (m_bInLocalizedValues)
{
// the node name is the locale
OUString aLocale;
OSL_VERIFY(testReplacedAndGetName(_aNode,aLocale)); // "Adding a localized subvalue but not as root of element tree"
if (aLocale.getLength() && ! localehelper::isDefaultLanguage(aLocale))
{
m_xUpdateHandler->setPropertyValueForLocale( _aNode.getValue(), aLocale );
}
else
{
m_xUpdateHandler->setPropertyValue( _aNode.getValue() );
}
}
else if (testReplacedAndGetName(_aNode,aName)&& (_aNode.getAttributes().isRemovable()) ) // we must be inside a set of values
{
OSL_ENSURE(!_aNode.isLocalized(), "UpdateDispatcher: Cannot add a localized value in a layer .");
sal_Int16 nAttr = getUpdateAttributes(_aNode.getAttributes(),true);
if (!_aNode.isNull())
{
m_xUpdateHandler->addOrReplacePropertyWithValue( aName,
nAttr,
_aNode.getValue());
}
else
{
m_xUpdateHandler->addOrReplaceProperty( aName,
nAttr,
_aNode.getValueType());
}
}
else // normal case: updating a single property //Inserting set
{
sal_Int16 nAttr = getUpdateAttributes(_aNode.getAttributes(),false);
sal_Int16 nAttrMask = getUpdateAttributeMask(_aNode.getAttributes());
m_xUpdateHandler->modifyProperty( aName, nAttr, nAttrMask, _aNode.getValueType() );
if (_aNode.isLocalized() && m_aLocale.getLength())
{
m_xUpdateHandler->setPropertyValueForLocale( _aNode.getValue(), m_aLocale );
}
else
{
m_xUpdateHandler->setPropertyValue( _aNode.getValue() );
}
m_xUpdateHandler->endProperty();
}
return CONTINUE;
}
// -----------------------------------------------------------------------------
data::SetVisitor::Result UpdateDispatcher::handle(data::GroupNodeAccess const& _aNode)
{
OSL_ENSURE( !m_bInLocalizedValues, "UpdateDispatcher: A localized value cannot be a complete group");
OUString aName;
if ( testReplacedAndGetName(_aNode,aName) )
{
sal_Int16 nAttr = getUpdateAttributes(_aNode.getAttributes(),true);
m_xUpdateHandler->addOrReplaceNode( aName, nAttr );
this->visitChildren(_aNode);
m_xUpdateHandler->endNode();
}
else
{
sal_Int16 nAttr = getUpdateAttributes(_aNode.getAttributes(),false);
sal_Int16 nAttrMask = getUpdateAttributeMask(_aNode.getAttributes());
m_xUpdateHandler->modifyNode( aName, nAttr, nAttrMask, false );
this->visitChildren(_aNode);
m_xUpdateHandler->endNode();
}
return CONTINUE;
}
// -----------------------------------------------------------------------------
data::SetVisitor::Result UpdateDispatcher::handle(data::SetNodeAccess const& _aNode)
{
OSL_ENSURE( !m_bInLocalizedValues, "UpdateDispatcher: A localized value cannot be a complete set");
OUString aName;
if ( testReplacedAndGetName(_aNode,aName) )
{
OSL_ENSURE( !_aNode.isLocalizedValueSetNode(), "UpdateDispatcher: Cannot add a localized value in a layer." );
sal_Int16 nAttr = getUpdateAttributes(_aNode.getAttributes(),true);
m_xUpdateHandler->addOrReplaceNode( aName, nAttr );
this->visitElements(_aNode);
m_xUpdateHandler->endNode();
}
else
{
sal_Int16 nAttr = getUpdateAttributes(_aNode.getAttributes(),false);
sal_Int16 nAttrMask = getUpdateAttributeMask(_aNode.getAttributes());
if (_aNode.isLocalizedValueSetNode())
{
m_xUpdateHandler->modifyProperty( aName, nAttr, nAttrMask, uno::Type() );
m_bInLocalizedValues = true;
this->visitElements(_aNode);
m_bInLocalizedValues = false;
m_xUpdateHandler->endProperty();
}
else
{
m_xUpdateHandler->modifyNode( aName, nAttr, nAttrMask, false );
this->visitElements(_aNode);
m_xUpdateHandler->endNode();
}
}
return CONTINUE;
}
// -----------------------------------------------------------------------------
bool UpdateDispatcher::testReplacedAndGetName(data::NodeAccess const & _aNode, OUString & _aName)
{
if (m_aElementName.getLength())
{
OSL_ENSURE( _aNode->isFragmentRoot(), "ERROR - UpdateDispatcher: Found orphaned 'element' name for inner node");
_aName = m_aElementName;
m_aElementName = OUString();
return true;
}
else
{
OSL_ENSURE(!_aNode->isFragmentRoot(), "ERROR - UpdateDispatcher: Found no 'element' name for fragment root node");
_aName = _aNode.getName().toString();
return false;
}
}
// -----------------------------------------------------------------------------
data::SetVisitor::Result UpdateDispatcher::handle(data::TreeAccessor const& _aElement)
{
m_aElementName = _aElement.getName().toString();
Result aRes = SetVisitor::handle(_aElement); // dispatch to root node
m_aElementName = OUString(); // clear - just to be safe
return aRes;
}
// -----------------------------------------------------------------------------
sal_Int16 UpdateDispatcher::getUpdateAttributes(node::Attributes const & _aAttributes, bool bAdded)
{
namespace NodeAttribute = backenduno::NodeAttribute;
// no support for post-creation attribute changes yet
if (!bAdded)
{
OSL_ENSURE( getUpdateAttributeMask(_aAttributes) == 0,
"Incomplete support for attribute changes" );
return 0;
}
sal_Int16 nResult = 0;
if (_aAttributes.isReadonly())
nResult = NodeAttribute::READONLY;
if (_aAttributes.isFinalized())
nResult |= NodeAttribute::FINALIZED;
if (!_aAttributes.isNullable())
nResult |= NodeAttribute::MANDATORY;
return nResult;
}
// -----------------------------------------------------------------------------
sal_Int16 UpdateDispatcher::getUpdateAttributeMask(node::Attributes const & /*_aAttributes*/)
{
// no support for post-creation attribute changes yet
return 0;
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
} // namespace backend
// -------------------------------------------------------------------------
} // namespace configmgr