office-gobmx/configmgr/source/treemgr/templateimpl.cxx
Rüdiger Timm 4ecc7651b2 INTEGRATION: CWS changefileheader (1.22.16); FILE MERGED
2008/04/01 12:27:38 thb 1.22.16.2: #i85898# Stripping all external header guards
2008/03/31 12:22:56 rt 1.22.16.1: #i87441# Change license header to LPGL v3.
2008-04-11 12:54:33 +00:00

418 lines
15 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: templateimpl.cxx,v $
* $Revision: 1.23 $
*
* 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 <stdio.h>
#include "templateimpl.hxx"
#include "treeprovider.hxx"
#include "nodevisitor.hxx"
#include "treeaccessor.hxx"
#include "nodeaccess.hxx"
#include "valuenodeaccess.hxx"
#include "setnodeaccess.hxx"
#include "strdecl.hxx"
#include "typeconverter.hxx"
#include "localizedtreeactions.hxx"
#include "treeactions.hxx"
#include "apitypes.hxx"
#ifndef INCLUDED_MAP
#include <map>
#define INCLUDED_MAP
#endif
namespace configmgr
{
namespace configuration
{
//-----------------------------------------------------------------------------
Name TemplateName::makeSimpleTypeName(UnoType const& aType)
{
OUString sTypeName = toTemplateName(aType);
return makeName(sTypeName, Name::NoValidate());
}
//-----------------------------------------------------------------------------
UnoType TemplateName::resolveSimpleTypeName(Name const& aName)
{
OUString sTypeName = aName.toString();
return parseTemplateName(sTypeName);
}
//-----------------------------------------------------------------------------
Name TemplateName::makeNativeTypeModuleName()
{
OUString aModuleName( TEMPLATE_MODULE_NATIVE_VALUE );
return makeName(aModuleName, Name::NoValidate());
}
//-----------------------------------------------------------------------------
Name TemplateName::makeLocalizedTypeModuleName()
{
OUString aModuleName( TEMPLATE_MODULE_LOCALIZED_VALUE );
return makeName(aModuleName, Name::NoValidate());
}
//-----------------------------------------------------------------------------
bool TemplateName::isSimpleTypeName() const
{
bool bIsSimple = (aModule.toString().compareToAscii(TEMPLATE_MODULE_NATIVE_PREFIX,
TEMPLATE_MODULE_NATIVE_PREFIX.getLength()) == 0);
OSL_ENSURE(!bIsSimple ||
aModule == makeNativeTypeModuleName() ||
aModule == makeLocalizedTypeModuleName(),
"ERROR: Invalid template module with native prefix found");
return bIsSimple;
}
//-----------------------------------------------------------------------------
UnoType TemplateName::resolveToSimpleType() const
{
UnoType aType;
if ( isSimpleTypeName() )
{
aType = resolveSimpleTypeName( aName );
}
else
OSL_ENSURE(false, "TemplateName::resolveToSimpleType must be called only for simple type name pairs");
return aType;
}
//-----------------------------------------------------------------------------
// class TemplateImplHelper
//-----------------------------------------------------------------------------
TemplateHolder TemplateImplHelper::createNew (TemplateName const& aNames,UnoType const& aType)
{
return new Template(aNames.aName, aNames.aModule, aType);
}
//-----------------------------------------------------------------------------
TemplateHolder TemplateImplHelper::makeSpecialTemplate (TemplateName const& aNames, SpecialTemplateProvider const& aProvider, UnoType const& aType)
{
OSL_ENSURE(aProvider.m_aImpl.is(), "Cannot find a template without a provider");
if (aProvider.m_aImpl.is())
return aProvider.m_aImpl->makeTemplate(aNames,aType);
else
return TemplateHolder(0);
}
//-----------------------------------------------------------------------------
TemplateHolder TemplateImplHelper::makeElementTemplateWithType(TemplateName const& _aNames, TemplateProvider const& _aProvider, data::SetNodeAccess const& _aSet)
{
OSL_ENSURE(_aProvider.m_aImpl.is(), "ERROR: Cannot find a template without a provider");
if (_aProvider.m_aImpl.is())
return _aProvider.m_aImpl->makeElementTemplateWithType(_aNames,_aSet);
else
return TemplateHolder(0);
}
//-----------------------------------------------------------------------------
void TemplateImplHelper::assignActualType (Template& aTemplate,UnoType const& aType)
{
OSL_PRECOND( aType != getNoTypeAvailable(), "ERROR: Assigning NO type to a template" );
if (!aTemplate.isInstanceTypeKnown())
aTemplate.m_aInstanceType = aType;
OSL_ENSURE(aTemplate.isInstanceTypeKnown(), "ERROR: Could not assign given type to a template");
OSL_ENSURE(aTemplate.getInstanceType() == aType, "ERROR: Trying to change instance type of a template");
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// class SpecialTemplateProvider_Impl
//-----------------------------------------------------------------------------
SpecialTemplateProvider_Impl::SpecialTemplateProvider_Impl()
: m_aRepository()
{
}
//-----------------------------------------------------------------------------
TemplateHolder SpecialTemplateProvider_Impl::makeTemplate (TemplateName const& aNames, UnoType const& aType)
{
typedef TemplateRepository::value_type Entry;
TemplateRepository::iterator it = m_aRepository.find(aNames);
if (it == m_aRepository.end())
it = m_aRepository.insert( Entry( aNames, TemplateImplHelper::createNew(aNames,aType) ) ).first;
else if (!it->second->isInstanceTypeKnown())
TemplateImplHelper::assignActualType(*it->second, aType);
OSL_ENSURE(it->second->isInstanceTypeKnown(), "No type assigned to Template");
OSL_ENSURE(it->second->getInstanceType() == aType, "Inconsistent type found for Template");
return it->second;
}
//-----------------------------------------------------------------------------
// class TemplateProvider_Impl
//-----------------------------------------------------------------------------
TemplateProvider_Impl::TemplateProvider_Impl(TemplateManagerRef const & xProvider, RequestOptions const& aOptions)
: m_xProvider(xProvider)
, m_aOptions(aOptions)
, m_aRepository()
{
}
//-----------------------------------------------------------------------------
data::TreeSegment TemplateProvider_Impl::instantiate(TemplateHolder const& aTemplate)
{
data::TreeSegment pRet;
if (aTemplate.is())
{
data::TreeAccessor aTemplateData = m_xProvider->requestTemplate(aTemplate->getName(), aTemplate->getModule());
pRet = cloneExpandedForLocale(aTemplateData, m_aOptions.getLocale());
}
return pRet;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
namespace
{
using namespace data;
//-----------------------------------------------------------------------------
struct TypeDetector : SetVisitor
{
enum State
{
Contradicting = -1,
NotFound = 0,
SomeValue,
VariousValue,
SomeTree
};
State result;
UnoType type;
TypeDetector() : result(NotFound), type() {}
protected:
using SetVisitor::handle;
private: // NodeAction implementation
Result handle(ValueNodeAccess const& _aValueNode);
Result handle(NodeAccess const& _aNonValueNode);
};
//-----------------------------------------------------------------------------
static UnoType detectNodeType(TreeAccessor const& _aElement)
{
if (_aElement == NULL)
throw configuration::Exception("Could not load required template to detect set elements");
TypeDetector aDetector;
aDetector.visitTree( _aElement );
switch(aDetector.result)
{
case TypeDetector::SomeTree: // found tree
case TypeDetector::VariousValue: // found an Any
case TypeDetector::SomeValue: // found a particular value type
break;
#ifdef DBG_UTIL
case TypeDetector::NotFound: OSL_ENSURE(false,"Impossible Result: Node not handled"); if (false) // dirty abuse of case
case TypeDetector::Contradicting: OSL_ENSURE(false,"Impossible Result: Node contradicts itself"); if (false) // dirty abuse of case
#endif // DBG_UTIL
default: OSL_ENSURE(false,"Impossible Result: Unknown result code");
throw configuration::Exception("INTERNAL ERROR: Could not detect set element type from loaded instance");
}
return aDetector.type;
}
//-------------------------------------------------------------------------
static bool detectElementType(UnoType& aType, data::SetNodeAccess const& _aSet)
{
TypeDetector aDetector;
aDetector.visitElements( _aSet );
bool bResult = false;
switch(aDetector.result)
{
case TypeDetector::SomeTree: // found tree
case TypeDetector::VariousValue: // found an Any
aType = aDetector.type;
bResult = true;
break;
case TypeDetector::SomeValue: // found a value or an any
case TypeDetector::NotFound: // found no element
break;
case TypeDetector::Contradicting:
OSL_ENSURE(false,"Invalid Set: contains values and subtrees");
break;
default: OSL_ENSURE(false,"Unreachable code"); break;
}
return bResult;
}
//-----------------------------------------------------------------------------
}
//-----------------------------------------------------------------------------
TemplateHolder TemplateProvider_Impl::makeElementTemplateWithType(TemplateName const& _aNames, data::SetNodeAccess const& _aSet)
{
typedef TemplateRepository::value_type Entry;
TemplateRepository::iterator it = m_aRepository.find(_aNames);
if (it == m_aRepository.end() || !it->second->isInstanceTypeKnown())
{
UnoType aType;
if (_aNames.isSimpleTypeName()) // native type found
{
aType = _aNames.resolveToSimpleType();
if (aType == TemplateImplHelper::getNoTypeAvailable())
throw configuration::Exception("INTERNAL ERROR: Could not resolve native type");
}
else if (!detectElementType(aType,_aSet))
{
OSL_ASSERT(_aNames.aName == _aSet.getElementTemplateName());
OSL_ASSERT(_aNames.aModule == _aSet.getElementTemplateModule());
data::TreeAccessor aTemplateData = m_xProvider->requestTemplate(_aNames.aName, _aNames.aModule);
aType = detectNodeType(aTemplateData); // throws if necessary
}
OSL_ASSERT( aType != TemplateImplHelper::getNoTypeAvailable() );
if (it == m_aRepository.end())
it = m_aRepository.insert( Entry( _aNames, TemplateImplHelper::createNew(_aNames,aType) ) ).first;
else
TemplateImplHelper::assignActualType(*it->second, aType);
OSL_ENSURE(it->second->isInstanceTypeKnown(), "No type assigned to Template");
OSL_ENSURE(it->second->getInstanceType() == aType, "Inconsistent type found for Template");
}
#ifdef DBG_UTIL
else
{
OSL_ENSURE(it->second->isInstanceTypeKnown(), "No type assigned to Template");
UnoType aTestType;
if (detectElementType(aTestType,_aSet))
OSL_ENSURE(it->second->getInstanceType() == aTestType, "Inconsistent type found for Template");
}
#endif // DBG_UTIL
return it->second;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
namespace
{
//-----------------------------------------------------------------------------
TypeDetector::Result TypeDetector::handle(ValueNodeAccess const& _aValueNode)
{
UnoType aFoundType = _aValueNode.getValueType();
bool isNullType = (aFoundType.getTypeClass() == uno::TypeClass_VOID);
bool isAnyType = (aFoundType.getTypeClass() == uno::TypeClass_ANY);
switch (this->result) // transition depends on previous state
{
case NotFound:
this->type = aFoundType;
if (isAnyType)
this->result = VariousValue;
else if (!isNullType)
this->result = SomeValue;
break;
case SomeValue:
if (!isNullType && this->type != aFoundType)
{
this->result = VariousValue;
this->type = configapi::getAnyType();
OSL_ASSERT(type.getTypeClass() == uno::TypeClass_ANY);
}
break;
case VariousValue: // remain unchanged - type already is 'Any'
break;
case SomeTree: OSL_ENSURE(false, "Found value node does not match previous (tree) sibling");
default:
this->result = Contradicting;
break;
}
return CONTINUE; // always continue to detect errors in data
}
//-----------------------------------------------------------------------------
TypeDetector::Result TypeDetector::handle(NodeAccess const& _aNonValueNode)
{
{ (void)_aNonValueNode; }
OSL_ENSURE(!ValueNodeAccess::isInstance(_aNonValueNode),"Value node dipatched to wrong handler");
switch (this->result) // transition depends on previous state
{
case NotFound:
this->type = configapi::getUnoInterfaceType();
this->result = SomeTree;
break;
case SomeTree: // remain unchanged - type already is Tree
break;
case SomeValue:
case VariousValue: OSL_ENSURE(false, "Found Subtree node does not match previous (value) sibling");
default:
this->result = Contradicting;
break;
}
return CONTINUE; // always continue to detect errors in data
}
//-----------------------------------------------------------------------------
} // anonymous
//-----------------------------------------------------------------------------
} // configuration
} // configmgr