Update ooo320-m1
[ooovba.git] / configmgr / source / treemgr / templateimpl.cxx
blob87bccef5d2dc5bcca2db9fd36d1d424bab945b93
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: templateimpl.cxx,v $
10 * $Revision: 1.24 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
34 #include <stdio.h>
35 #include "templateimpl.hxx"
36 #include "treemanager.hxx"
37 #include "node.hxx"
38 #include "nodevisitor.hxx"
39 #include "strdecl.hxx"
40 #include "typeconverter.hxx"
41 #include "localizedtreeactions.hxx"
42 #include "treeactions.hxx"
43 #include "apitypes.hxx"
45 #ifndef INCLUDED_MAP
46 #include <map>
47 #define INCLUDED_MAP
48 #endif
50 namespace configmgr
52 namespace configuration
54 //-----------------------------------------------------------------------------
56 com::sun::star::uno::Type TemplateName::resolveSimpleTypeName(rtl::OUString const& aName)
58 rtl::OUString sTypeName = aName;
59 return parseTemplateName(sTypeName);
61 //-----------------------------------------------------------------------------
62 #if OSL_DEBUG_LEVEL > 0
63 rtl::OUString TemplateName::makeNativeTypeModuleName()
65 return rtl::OUString( TEMPLATE_MODULE_NATIVE_VALUE );
68 //-----------------------------------------------------------------------------
69 rtl::OUString TemplateName::makeLocalizedTypeModuleName()
71 return rtl::OUString( TEMPLATE_MODULE_LOCALIZED_VALUE );
73 #endif
74 //-----------------------------------------------------------------------------
75 bool TemplateName::isSimpleTypeName() const
77 bool bIsSimple = (aModule.compareToAscii(TEMPLATE_MODULE_NATIVE_PREFIX,
78 TEMPLATE_MODULE_NATIVE_PREFIX.getLength()) == 0);
80 OSL_ENSURE(!bIsSimple ||
81 aModule == makeNativeTypeModuleName() ||
82 aModule == makeLocalizedTypeModuleName(),
83 "ERROR: Invalid template module with native prefix found");
85 return bIsSimple;
87 //-----------------------------------------------------------------------------
89 com::sun::star::uno::Type TemplateName::resolveToSimpleType() const
91 com::sun::star::uno::Type aType;
92 if ( isSimpleTypeName() )
94 aType = resolveSimpleTypeName( aName );
96 else
97 OSL_ENSURE(false, "TemplateName::resolveToSimpleType must be called only for simple type name pairs");
98 return aType;
100 //-----------------------------------------------------------------------------
101 // class TemplateImplHelper
102 //-----------------------------------------------------------------------------
104 rtl::Reference<Template> TemplateImplHelper::createNew (TemplateName const& aNames,com::sun::star::uno::Type const& aType)
106 return new Template(aNames.aName, aNames.aModule, aType);
108 //-----------------------------------------------------------------------------
110 rtl::Reference<Template> TemplateImplHelper::makeElementTemplateWithType(TemplateName const& _aNames, TemplateProvider const& _aProvider, sharable::SetNode * set)
112 OSL_ENSURE(_aProvider.m_aImpl.is(), "ERROR: Cannot find a template without a provider");
114 if (_aProvider.m_aImpl.is())
115 return _aProvider.m_aImpl->makeElementTemplateWithType(_aNames, set);
117 else
118 return rtl::Reference<Template>(0);
120 //-----------------------------------------------------------------------------
122 void TemplateImplHelper::assignActualType (Template& aTemplate,com::sun::star::uno::Type const& aType)
124 OSL_PRECOND( aType != getNoTypeAvailable(), "ERROR: Assigning NO type to a template" );
126 if (!aTemplate.isInstanceTypeKnown())
127 aTemplate.m_aInstanceType = aType;
129 OSL_ENSURE(aTemplate.isInstanceTypeKnown(), "ERROR: Could not assign given type to a template");
130 OSL_ENSURE(aTemplate.getInstanceType() == aType, "ERROR: Trying to change instance type of a template");
132 //-----------------------------------------------------------------------------
134 //-----------------------------------------------------------------------------
135 // class TemplateProvider_Impl
136 //-----------------------------------------------------------------------------
138 TemplateProvider_Impl::TemplateProvider_Impl(rtl::Reference< TreeManager > const & xProvider, RequestOptions const& aOptions)
139 : m_xProvider(xProvider)
140 , m_aOptions(aOptions)
141 , m_aRepository()
144 //-----------------------------------------------------------------------------
146 rtl::Reference< data::TreeSegment > TemplateProvider_Impl::instantiate(rtl::Reference<Template> const& aTemplate)
148 if (aTemplate.is())
150 sharable::TreeFragment * aTemplateData = m_xProvider->requestTemplate(aTemplate->getName(), aTemplate->getModule());
152 return cloneExpandedForLocale(aTemplateData, m_aOptions.getLocale());
153 } else {
154 return rtl::Reference< data::TreeSegment >();
157 //-----------------------------------------------------------------------------
159 //-----------------------------------------------------------------------------
160 namespace
162 //-----------------------------------------------------------------------------
163 struct TypeDetector : data::SetVisitor
165 enum State
167 Contradicting = -1,
168 NotFound = 0,
169 SomeValue,
170 VariousValue,
171 SomeTree
174 State result;
175 com::sun::star::uno::Type type;
177 TypeDetector() : result(NotFound), type() {}
179 private:
180 using SetVisitor::handle;
181 virtual bool handle(sharable::Node * node);
182 virtual bool handle(sharable::ValueNode * node);
184 //-----------------------------------------------------------------------------
185 static com::sun::star::uno::Type detectNodeType(sharable::TreeFragment * element)
187 if (element == 0)
188 throw configuration::Exception("Could not load required template to detect set elements");
190 TypeDetector aDetector;
191 aDetector.visitTree(element);
193 switch(aDetector.result)
195 case TypeDetector::SomeTree: // found tree
196 case TypeDetector::VariousValue: // found an Any
197 case TypeDetector::SomeValue: // found a particular value type
198 break;
200 #ifdef DBG_UTIL
201 case TypeDetector::NotFound: OSL_ENSURE(false,"Impossible Result: Node not handled"); if (false) // dirty abuse of case
202 case TypeDetector::Contradicting: OSL_ENSURE(false,"Impossible Result: Node contradicts itself"); if (false) // dirty abuse of case
203 #endif // DBG_UTIL
204 default: OSL_ENSURE(false,"Impossible Result: Unknown result code");
206 throw configuration::Exception("INTERNAL ERROR: Could not detect set element type from loaded instance");
208 return aDetector.type;
211 //-------------------------------------------------------------------------
212 static bool detectElementType(com::sun::star::uno::Type& aType, sharable::SetNode * set)
214 TypeDetector aDetector;
215 aDetector.visitElements(set);
217 bool bResult = false;
218 switch(aDetector.result)
220 case TypeDetector::SomeTree: // found tree
221 case TypeDetector::VariousValue: // found an Any
222 aType = aDetector.type;
223 bResult = true;
224 break;
226 case TypeDetector::SomeValue: // found a value or an any
227 case TypeDetector::NotFound: // found no element
228 break;
230 case TypeDetector::Contradicting:
231 OSL_ENSURE(false,"Invalid Set: contains values and subtrees");
232 break;
234 default: OSL_ENSURE(false,"Unreachable code"); break;
236 return bResult;
238 //-----------------------------------------------------------------------------
241 //-----------------------------------------------------------------------------
242 rtl::Reference<Template> TemplateProvider_Impl::makeElementTemplateWithType(TemplateName const& _aNames, sharable::SetNode * set)
244 TemplateRepository::iterator it = m_aRepository.find(_aNames);
246 if (it == m_aRepository.end() || !it->second->isInstanceTypeKnown())
248 com::sun::star::uno::Type aType;
249 if (_aNames.isSimpleTypeName()) // native type found
251 aType = _aNames.resolveToSimpleType();
253 if (aType == TemplateImplHelper::getNoTypeAvailable())
254 throw configuration::Exception("INTERNAL ERROR: Could not resolve native type");
257 else if (!detectElementType(aType, set))
259 OSL_ASSERT(_aNames.aName == set->getElementTemplateName());
260 OSL_ASSERT(_aNames.aModule == set->getElementTemplateModule());
262 sharable::TreeFragment * aTemplateData = m_xProvider->requestTemplate(_aNames.aName, _aNames.aModule);
264 aType = detectNodeType(aTemplateData); // throws if necessary
266 OSL_ASSERT( aType != TemplateImplHelper::getNoTypeAvailable() );
268 if (it == m_aRepository.end())
269 it = m_aRepository.insert( TemplateRepository::value_type( _aNames, TemplateImplHelper::createNew(_aNames,aType) ) ).first;
271 else
272 TemplateImplHelper::assignActualType(*it->second, aType);
274 OSL_ENSURE(it->second->isInstanceTypeKnown(), "No type assigned to Template");
275 OSL_ENSURE(it->second->getInstanceType() == aType, "Inconsistent type found for Template");
278 #ifdef DBG_UTIL
279 else
281 OSL_ENSURE(it->second->isInstanceTypeKnown(), "No type assigned to Template");
282 com::sun::star::uno::Type aTestType;
283 if (detectElementType(aTestType, set))
284 OSL_ENSURE(it->second->getInstanceType() == aTestType, "Inconsistent type found for Template");
286 #endif // DBG_UTIL
288 return it->second;
291 //-----------------------------------------------------------------------------
292 //-----------------------------------------------------------------------------
293 namespace
295 //-----------------------------------------------------------------------------
296 bool TypeDetector::handle(sharable::ValueNode * node)
298 com::sun::star::uno::Type aFoundType = node->getValueType();
300 bool isNullType = (aFoundType.getTypeClass() == uno::TypeClass_VOID);
301 bool isAnyType = (aFoundType.getTypeClass() == uno::TypeClass_ANY);
303 switch (this->result) // transition depends on previous state
305 case NotFound:
306 this->type = aFoundType;
308 if (isAnyType)
309 this->result = VariousValue;
311 else if (!isNullType)
312 this->result = SomeValue;
314 break;
316 case SomeValue:
317 if (!isNullType && this->type != aFoundType)
319 this->result = VariousValue;
320 this->type = configapi::getAnyType();
321 OSL_ASSERT(type.getTypeClass() == uno::TypeClass_ANY);
323 break;
325 case VariousValue: // remain unchanged - type already is 'Any'
326 break;
328 case SomeTree: OSL_ENSURE(false, "Found value node does not match previous (tree) sibling");
329 default:
330 this->result = Contradicting;
331 break;
333 return false; // always continue to detect errors in data
335 //-----------------------------------------------------------------------------
336 bool TypeDetector::handle(sharable::Node * node)
338 (void) node; // avoid warnings
339 OSL_ENSURE(!node->isValue(), "Value node dipatched to wrong handler");
340 switch (this->result) // transition depends on previous state
342 case NotFound:
343 this->type = configapi::getUnoInterfaceType();
344 this->result = SomeTree;
345 break;
347 case SomeTree: // remain unchanged - type already is Tree
348 break;
350 case SomeValue:
351 case VariousValue: OSL_ENSURE(false, "Found Subtree node does not match previous (value) sibling");
352 default:
353 this->result = Contradicting;
354 break;
356 return false; // always continue to detect errors in data
359 //-----------------------------------------------------------------------------
360 } // anonymous
361 //-----------------------------------------------------------------------------
362 } // configuration
363 } // configmgr