merge the formfield patch from ooo-build
[ooovba.git] / configmgr / source / tree / localizedtreeactions.cxx
blob24c7fb88b9ec6e914836116380b54a6cdd84cc67
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: localizedtreeactions.cxx,v $
10 * $Revision: 1.19 $
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>
36 #include "localizedtreeactions.hxx"
37 #include "treeactions.hxx"
38 #include "builddata.hxx"
39 #include "subtree.hxx"
40 #include "matchlocale.hxx"
41 #include "typeconverter.hxx"
42 #include "change.hxx"
43 #include "treechangefactory.hxx"
44 #include "treenodefactory.hxx"
45 #include "strdecl.hxx"
46 #include <osl/diagnose.h>
49 //..........................................................................
50 namespace configmgr
53 //--------------------------------------------------------------------------
54 namespace
56 //--------------------------------------------------------------------------
57 //==========================================================================
58 //= OCloneForLocale
59 //==========================================================================
60 //= clones a subtree , in the process selecting only the best match locale
61 //= from the set representation of localized values
62 //==========================================================================
63 class OCloneForLocale : public NodeAction
65 rtl::OUString m_sTargetLocale;
66 std::auto_ptr<INode> m_pClone;
67 public:
68 OCloneForLocale(rtl::OUString const& aLocale) : m_sTargetLocale(aLocale) {}
69 std::auto_ptr<INode> getResult() { return m_pClone; }
71 private:
72 void handle(ValueNode const& _aValue);
73 void handle(ISubtree const& _aSubtree);
75 //--------------------------------------------------------------------------
76 struct OCloneChildrenForLocale : NodeAction
78 ISubtree& m_rParent;
79 localehelper::FindBestLocale& m_rLocaleMatcher;
80 public:
81 OCloneChildrenForLocale(ISubtree& _rParent, localehelper::FindBestLocale& _rLocaleMatcher)
82 : m_rParent(_rParent)
83 , m_rLocaleMatcher(_rLocaleMatcher)
86 virtual void handle(ValueNode const& _aValue);
87 virtual void handle(ISubtree const& _aSubtree);
90 //--------------------------------------------------------------------------
91 struct OSelectForLocale : NodeAction
93 ValueNode const* m_pFound;
94 localehelper::FindBestLocale& m_rLocaleMatcher;
95 public:
96 OSelectForLocale(localehelper::FindBestLocale& _rLocaleMatcher)
97 : m_pFound(NULL)
98 , m_rLocaleMatcher(_rLocaleMatcher)
102 bool hasResult() const
103 { return m_pFound != NULL; }
105 ValueNode const* getResult() const
106 { return m_pFound; }
108 private:
109 virtual void handle(ValueNode const& _aValue);
110 virtual void handle(ISubtree const& _aSubtree);
112 void maybeSelect(ValueNode const& _aNode);
115 //--------------------------------------------------------------------------
116 //--------------------------------------------------------------------------
117 void OSelectForLocale::handle(ValueNode const& _aValue)
119 maybeSelect(_aValue);
121 //--------------------------------------------------------------------------
122 void OSelectForLocale::handle(ISubtree const& /*_aSubtree*/)
124 OSL_ENSURE(false, "INTERNAL ERROR: Inconsistent data: Found a Subtree in a set of localized values");
126 //--------------------------------------------------------------------------
127 void OSelectForLocale::maybeSelect(ValueNode const& _aNode)
129 if (m_rLocaleMatcher.accept( localehelper::makeLocale(_aNode.getName()) ) )
130 m_pFound = &_aNode;
132 else
133 OSL_ENSURE(m_pFound, "WARNING: Node Locale wasn't accepted, but no node had been found before");
136 //--------------------------------------------------------------------------
137 //--------------------------------------------------------------------------
138 std::auto_ptr< INode > implReduceLocalizedSet(ISubtree const& _aSubtree, localehelper::FindBestLocale& _rLocaleMatcher)
140 // -- find the best-match locale -----------------------------
141 _rLocaleMatcher.reset();
143 OSelectForLocale aSelector(_rLocaleMatcher);
145 aSelector.applyToChildren(_aSubtree);
147 std::auto_ptr< INode > pResult;
149 // -- look for a non-NULL value -----------------------------
150 uno::Type aValueType;
151 if (aSelector.hasResult())
153 ValueNode const& rSelected = *aSelector.getResult();
155 aValueType = rSelected.getValueType();
157 if (!rSelected.isNull()) // values are present - clone it from the values
159 pResult.reset ( new ValueNode( _aSubtree.getName(),
160 rSelected.getValue(), rSelected.getDefault(),
161 _aSubtree.getAttributes()
162 ) );
166 else // no entry - exract the type to be used from the template name
167 aValueType = parseTemplateName(_aSubtree.getElementTemplateName());
169 // -- create NULL value, if none was found -----------------------------
170 // create a NULL of the found type
171 if (pResult.get() == NULL)
173 pResult.reset( new ValueNode( _aSubtree.getName(),
174 aValueType,
175 _aSubtree.getAttributes()
176 ) );
179 // -- -----------------------------
180 OSL_ENSURE( aValueType != uno::Type(), "VOID result type found");
181 #if OSL_DEBUG_LEVEL > 0
182 uno::Type aTemplateType = parseTemplateName( _aSubtree.getElementTemplateName() );
183 OSL_ENSURE( ( aValueType == aTemplateType ) || ( aTemplateType.getTypeClass() == uno::TypeClass_ANY ),
184 "ERROR: Found Value Type doesn't match encoded value type in pseudo template name");
185 #endif
186 OSL_POSTCOND( static_cast<ValueNode&>(*pResult).getValueType() == aValueType,
187 "ERROR: Resulting Value Type doesn't match original value type" );
189 return pResult;
191 //--------------------------------------------------------------------------
192 std::auto_ptr< INode > implCloneForLocale(ISubtree const& _aSubtree, localehelper::FindBestLocale& _rLocaleMatcher)
194 std::auto_ptr< INode > pClone;
196 if (isLocalizedValueSet(_aSubtree))
198 pClone = implReduceLocalizedSet(_aSubtree, _rLocaleMatcher);
200 else
202 // ISubtree should get a clone(NoChildCopy) member ...
203 std::auto_ptr< Subtree > pCloneTree( new Subtree(_aSubtree, treeop::NoChildCopy()) );
205 OCloneChildrenForLocale aSubCloner(*pCloneTree,_rLocaleMatcher);
207 aSubCloner.applyToChildren(_aSubtree);
209 pClone.reset( pCloneTree.release() );
212 return pClone;
214 //--------------------------------------------------------------------------
215 //--- OCloneChildrenForLocale:-----------------------------------------------------------------------
217 void OCloneChildrenForLocale::handle(ValueNode const& _aValue)
219 // just a single value - nothing to do
220 std::auto_ptr< INode > pClone( _aValue.clone() );
222 m_rParent.addChild(pClone);
225 //--------------------------------------------------------------------------
226 void OCloneChildrenForLocale::handle(ISubtree const& _aSubtree)
228 std::auto_ptr< INode > pClone = implCloneForLocale(_aSubtree,m_rLocaleMatcher);
230 m_rParent.addChild(pClone);
233 //--------------------------------------------------------------------------
234 //= OCloneForLocale
236 // rtl::OUString m_sTargetLocale;
237 // std::auto_ptr<INode> m_pClone;
239 void OCloneForLocale::handle(ValueNode const& _aValue)
241 // just a single value - nothing to do
242 std::auto_ptr< INode > pClone( _aValue.clone() );
244 m_pClone = pClone;
246 //--------------------------------------------------------------------------
247 void OCloneForLocale::handle(ISubtree const& _aSubtree)
249 localehelper::FindBestLocale aLocaleMatcher( localehelper::makeLocale(m_sTargetLocale) );
251 m_pClone = implCloneForLocale(_aSubtree,aLocaleMatcher);
253 //--------------------------------------------------------------------------
255 //--------------------------------------------------------------------------
256 } // anonymous namespace
258 //==========================================================================
259 // Helper function to invoke the previous ones properly
261 // convert to the given locale format, assuming the original representation was expanded
262 static std::auto_ptr<INode> impl_cloneExpandedForLocale(INode const* _pNode, rtl::OUString const& _sLocale)
264 OSL_ASSERT(_pNode != NULL);
266 if ( localehelper::designatesAllLocales(localehelper::makeLocale(_sLocale)) ) // from expanded to expanded
268 return _pNode->clone();
271 else // needs reduction
273 OCloneForLocale aCloner(_sLocale);
274 aCloner.applyToNode(*_pNode);
275 return aCloner.getResult();
278 //--------------------------------------------------------------------------
280 // convert to the given locale format, assuming the original representation was expanded
281 static rtl::Reference< data::TreeSegment > old_cloneExpandedForLocale(rtl::OUString const& _sName, INode const* _pNode, rtl::OUString const& _sLocale)
283 if (_pNode == NULL)
284 return rtl::Reference< data::TreeSegment >();
286 std::auto_ptr<INode> aResult;
287 if (dynamic_cast< ISubtree const * >(_pNode) == 0) // simple value - nothing to reduce
288 aResult = _pNode->clone();
290 else
291 aResult = impl_cloneExpandedForLocale(_pNode,_sLocale);
293 return data::TreeSegment::create(_sName,aResult);
295 //--------------------------------------------------------------------------
297 // -----------------------------------------------------------------------------
298 //--------------------------------------------------------------------------
299 rtl::Reference< data::TreeSegment > cloneExpandedForLocale(sharable::TreeFragment * tree, rtl::OUString const& _sLocale)
301 std::auto_ptr<INode> aOldTree = data::convertTree(tree, true);
303 return old_cloneExpandedForLocale(tree->getName(), aOldTree.get(), _sLocale);
305 //--------------------------------------------------------------------------
306 // convert to the given locale format, assuming the original representation was expanded
307 std::auto_ptr<INode> reduceExpandedForLocale(std::auto_ptr<ISubtree> _pNode, rtl::OUString const& _sLocale)
309 std::auto_ptr<INode> aResult;
311 if ( _pNode.get() == NULL || // nothing to reduce
312 localehelper::designatesAllLocales(localehelper::makeLocale(_sLocale)) ) // from expanded to expanded
314 aResult.reset( _pNode.release() );
317 else // needs reduction
319 OCloneForLocale aCloner(_sLocale);
320 aCloner.applyToNode(*_pNode);
321 aResult = aCloner.getResult();
323 OSL_ENSURE(aResult.get(),"Cloning a tree for a locale unexpectedly produced NOTHING");
325 return aResult;
327 //--------------------------------------------------------------------------
328 namespace
330 //--------------------------------------------------------------------------
331 class ExpandTreeForLocale : NodeModification
333 ISubtree & m_rParent;
334 rtl::OUString const & m_aSourceLocale;
336 ExpandTreeForLocale(ISubtree & _rParent,rtl::OUString const & _aSourceLocale)
337 : m_rParent(_rParent)
338 , m_aSourceLocale(_aSourceLocale)
341 void handle(ISubtree& _rNode);
342 void handle(ValueNode& _rNode);
344 void substitute(std::auto_ptr<INode> _aExpanded);
345 public:
346 static void expand(ISubtree& _rTree, rtl::OUString const & _aSourceLocale)
348 ExpandTreeForLocale(_rTree,_aSourceLocale).applyToChildren(_rTree);
351 // returns NULL, if not a localized value
352 static std::auto_ptr<ISubtree> expanded(ValueNode const& _aNode, rtl::OUString const & _aSourceLocale);
355 //--------------------------------------------------------------------------
356 class ExpandChangesForLocale : ChangeTreeModification
358 SubtreeChange & m_rParent;
359 rtl::OUString const & m_aSourceLocale;
361 ExpandChangesForLocale(SubtreeChange & _rParent,rtl::OUString const & _aSourceLocale)
362 : m_rParent(_rParent)
363 , m_aSourceLocale(_aSourceLocale)
366 void handle(SubtreeChange& _rNode);
367 void handle(ValueChange& _rNode);
369 void handle(AddNode& _rNode);
370 void handle(RemoveNode& _rNode);
372 void substitute(std::auto_ptr<Change> _aExpanded);
373 public:
374 static void expand(SubtreeChange& _rTree, rtl::OUString const & _aSourceLocale)
376 ExpandChangesForLocale(_rTree,_aSourceLocale).applyToChildren(_rTree);
379 // returns NULL, if not a localized value
380 static std::auto_ptr<SubtreeChange> expanded(ValueChange const& _aNode, rtl::OUString const & _aSourceLocale);
382 //--------------------------------------------------------------------------
383 inline
384 void ExpandTreeForLocale::substitute(std::auto_ptr<INode> _aExpanded)
386 m_rParent.removeChild(_aExpanded->getName());
387 m_rParent.addChild(_aExpanded);
390 //--------------------------------------------------------------------------
391 void ExpandTreeForLocale::handle(ISubtree& _rNode)
393 expand(_rNode,m_aSourceLocale);
396 //--------------------------------------------------------------------------
397 void ExpandTreeForLocale::handle(ValueNode& _rNode)
399 std::auto_ptr<ISubtree> aExpanded = expanded(_rNode,m_aSourceLocale);
401 if (aExpanded.get())
402 substitute( base_ptr(aExpanded) );
405 //--------------------------------------------------------------------------
407 std::auto_ptr<ISubtree> ExpandTreeForLocale::expanded(ValueNode const& _aNode, rtl::OUString const & _aSourceLocale)
409 if (!_aNode.isLocalized()) return std::auto_ptr<ISubtree>();
411 OTreeNodeFactory & rFactory = getDefaultTreeNodeFactory();
413 node::Attributes aValueAttributes = _aNode.getAttributes();
415 aValueAttributes.setLocalized(false);
416 if (aValueAttributes.state() == node::isMerged)
417 aValueAttributes.setState( node::isReplaced );
420 std::auto_ptr<ValueNode> aValue = _aNode.isNull()
421 ? rFactory.createNullValueNode(_aSourceLocale,_aNode.getValueType(),aValueAttributes)
422 : rFactory.createValueNode(_aSourceLocale,_aNode.getValue(),aValueAttributes);
424 std::auto_ptr<ISubtree> aRet = rFactory.createSetNode( _aNode.getName(),
425 toTemplateName(_aNode.getValueType()),
426 TEMPLATE_MODULE_LOCALIZED_VALUE,
427 _aNode.getAttributes() );
429 aRet->addChild(base_ptr(aValue));
431 return aRet;
434 //--------------------------------------------------------------------------
435 //--------------------------------------------------------------------------
436 inline
437 void ExpandChangesForLocale::substitute(std::auto_ptr<Change> _aExpanded)
439 m_rParent.removeChange(_aExpanded->getNodeName());
440 m_rParent.addChange(_aExpanded);
443 //--------------------------------------------------------------------------
445 void ExpandChangesForLocale::handle(SubtreeChange& _rNode)
447 expand(_rNode,m_aSourceLocale);
450 //--------------------------------------------------------------------------
451 void ExpandChangesForLocale::handle(ValueChange& _rNode)
453 std::auto_ptr<SubtreeChange> aExpanded = expanded(_rNode,m_aSourceLocale);
455 if (aExpanded.get())
456 substitute( base_ptr( aExpanded ) );
459 //--------------------------------------------------------------------------
460 void ExpandChangesForLocale::handle(AddNode& _rNode)
462 rtl::Reference< data::TreeSegment > seg(_rNode.getNewTree());
463 std::auto_ptr<INode> pAdded(data::convertTree(seg.is() ? seg->fragment : 0, false));
464 if (pAdded.get() != NULL)
466 std::auto_ptr<INode> pExpanded;
467 if (ISubtree * pAddedTree = pAdded->asISubtree())
469 ExpandTreeForLocale::expand(*pAddedTree,m_aSourceLocale);
470 pExpanded = pAdded;
472 else if(ValueNode * pAddedValue = pAdded->asValueNode())
474 pExpanded = base_ptr(ExpandTreeForLocale::expanded(*pAddedValue,m_aSourceLocale));
476 else
477 OSL_ENSURE(false, "Cannot expand unknown Node type (found in AddNode)");
480 if (pExpanded.get())
482 rtl::Reference< data::TreeSegment > aExpanded = data::TreeSegment::create( _rNode.getNodeName(),pExpanded);
483 std::auto_ptr<AddNode> aExpandedAdd( new AddNode( aExpanded, _rNode.getNodeName(), _rNode.isToDefault() ) );
485 if (_rNode.isReplacing()) aExpandedAdd->setReplacing();
487 substitute( base_ptr( aExpandedAdd ) );
490 else
491 OSL_ENSURE(false, "Cannot expand AddNode without content");
494 //--------------------------------------------------------------------------
495 void ExpandChangesForLocale::handle(RemoveNode& )
497 // nothing to do
500 //--------------------------------------------------------------------------
501 std::auto_ptr<SubtreeChange> ExpandChangesForLocale::expanded(ValueChange const& _aNode, rtl::OUString const & _aSourceLocale)
503 std::auto_ptr<SubtreeChange> aRet;
504 if (_aNode.isLocalizedValue())
506 OTreeNodeFactory & rNodeFactory = getDefaultTreeNodeFactory();
507 OTreeChangeFactory & rFactory = getDefaultTreeChangeFactory();
509 node::Attributes aValueAttributes = _aNode.getAttributes();
511 aValueAttributes.setLocalized(false);
512 if (aValueAttributes.state() == node::isMerged)
513 aValueAttributes.setState( node::isReplaced );
516 rtl::OUString const sTemplateName = toTemplateName(_aNode.getValueType());
518 std::auto_ptr<ValueNode> aValue = _aNode.getNewValue().hasValue()
519 ? rNodeFactory.createValueNode(sTemplateName,_aNode.getNewValue(),aValueAttributes)
520 : rNodeFactory.createNullValueNode(sTemplateName,_aNode.getValueType(),aValueAttributes);
522 rtl::Reference< data::TreeSegment > aValueSegment = data::TreeSegment::create(_aSourceLocale, base_ptr(aValue));
524 std::auto_ptr<AddNode> aAddValue = rFactory.createAddNodeChange(aValueSegment,_aSourceLocale,_aNode.isToDefault());
525 aAddValue->setReplacing();
527 aRet = rFactory.createSetNodeChange( _aNode.getNodeName(),
528 sTemplateName,
529 TEMPLATE_MODULE_LOCALIZED_VALUE,
530 _aNode.getAttributes() );
532 aRet->addChange(base_ptr(aAddValue));
534 return aRet;
537 //--------------------------------------------------------------------------
538 } // anonymous namespace
539 //--------------------------------------------------------------------------
541 //--------------------------------------------------------------------------
542 //..........................................................................
543 } // namespace configmgr
544 //..........................................................................