1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: templateimpl.cxx,v $
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"
35 #include "templateimpl.hxx"
36 #include "treemanager.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"
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
);
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");
87 //-----------------------------------------------------------------------------
89 com::sun::star::uno::Type
TemplateName::resolveToSimpleType() const
91 com::sun::star::uno::Type aType
;
92 if ( isSimpleTypeName() )
94 aType
= resolveSimpleTypeName( aName
);
97 OSL_ENSURE(false, "TemplateName::resolveToSimpleType must be called only for simple type name pairs");
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
);
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
)
144 //-----------------------------------------------------------------------------
146 rtl::Reference
< data::TreeSegment
> TemplateProvider_Impl::instantiate(rtl::Reference
<Template
> const& aTemplate
)
150 sharable::TreeFragment
* aTemplateData
= m_xProvider
->requestTemplate(aTemplate
->getName(), aTemplate
->getModule());
152 return cloneExpandedForLocale(aTemplateData
, m_aOptions
.getLocale());
154 return rtl::Reference
< data::TreeSegment
>();
157 //-----------------------------------------------------------------------------
159 //-----------------------------------------------------------------------------
162 //-----------------------------------------------------------------------------
163 struct TypeDetector
: data::SetVisitor
175 com::sun::star::uno::Type type
;
177 TypeDetector() : result(NotFound
), type() {}
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
)
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
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
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
;
226 case TypeDetector::SomeValue
: // found a value or an any
227 case TypeDetector::NotFound
: // found no element
230 case TypeDetector::Contradicting
:
231 OSL_ENSURE(false,"Invalid Set: contains values and subtrees");
234 default: OSL_ENSURE(false,"Unreachable code"); break;
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
;
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");
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");
291 //-----------------------------------------------------------------------------
292 //-----------------------------------------------------------------------------
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
306 this->type
= aFoundType
;
309 this->result
= VariousValue
;
311 else if (!isNullType
)
312 this->result
= SomeValue
;
317 if (!isNullType
&& this->type
!= aFoundType
)
319 this->result
= VariousValue
;
320 this->type
= configapi::getAnyType();
321 OSL_ASSERT(type
.getTypeClass() == uno::TypeClass_ANY
);
325 case VariousValue
: // remain unchanged - type already is 'Any'
328 case SomeTree
: OSL_ENSURE(false, "Found value node does not match previous (tree) sibling");
330 this->result
= Contradicting
;
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
343 this->type
= configapi::getUnoInterfaceType();
344 this->result
= SomeTree
;
347 case SomeTree
: // remain unchanged - type already is Tree
351 case VariousValue
: OSL_ENSURE(false, "Found Subtree node does not match previous (value) sibling");
353 this->result
= Contradicting
;
356 return false; // always continue to detect errors in data
359 //-----------------------------------------------------------------------------
361 //-----------------------------------------------------------------------------