lok: register view callback also for nested sm view
[LibreOffice.git] / comphelper / source / misc / sequenceashashmap.cxx
blob34a6a0c8a5809559a209f86364bed9bde6207799
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <boost/property_tree/json_parser.hpp>
24 #include <com/sun/star/beans/NamedValue.hpp>
25 #include <com/sun/star/beans/PropertyValue.hpp>
26 #include <com/sun/star/lang/IllegalArgumentException.hpp>
27 #include <com/sun/star/reflection/XIdlField.hpp>
28 #include <com/sun/star/reflection/theCoreReflection.hpp>
29 #include <comphelper/sequenceashashmap.hxx>
30 #include <comphelper/processfactory.hxx>
31 #include <comphelper/propertysequence.hxx>
32 #include <sal/log.hxx>
33 #include <o3tl/string_view.hxx>
35 using namespace com::sun::star;
37 namespace
39 uno::Any jsonToUnoAny(const boost::property_tree::ptree& aTree)
41 uno::Any aAny;
42 uno::Any aValue;
43 sal_Int32 nFields;
44 uno::Reference<reflection::XIdlField> aField;
45 boost::property_tree::ptree aNodeNull, aNodeValue, aNodeField;
46 const std::string& rType = aTree.get<std::string>("type", "");
47 const std::string& rValue = aTree.get<std::string>("value", "");
48 uno::Sequence<uno::Reference<reflection::XIdlField>> aFields;
49 uno::Reference<reflection::XIdlClass> xIdlClass
50 = css::reflection::theCoreReflection::get(comphelper::getProcessComponentContext())
51 ->forName(OUString::fromUtf8(rType.c_str()));
52 if (xIdlClass.is())
54 uno::TypeClass aTypeClass = xIdlClass->getTypeClass();
55 xIdlClass->createObject(aAny);
56 aFields = xIdlClass->getFields();
57 nFields = aFields.getLength();
58 aNodeValue = aTree.get_child("value", aNodeNull);
59 if (nFields > 0 && aNodeValue != aNodeNull)
61 for (sal_Int32 itField = 0; itField < nFields; ++itField)
63 aField = aFields[itField];
64 aNodeField = aNodeValue.get_child(aField->getName().toUtf8().getStr(), aNodeNull);
65 if (aNodeField != aNodeNull)
67 aValue = jsonToUnoAny(aNodeField);
68 aField->set(aAny, aValue);
72 else if (!rValue.empty())
74 if (aTypeClass == uno::TypeClass_VOID)
75 aAny.clear();
76 else if (aTypeClass == uno::TypeClass_BYTE)
77 aAny <<= static_cast<sal_Int8>(o3tl::toInt32(rValue));
78 else if (aTypeClass == uno::TypeClass_BOOLEAN)
79 aAny <<= OString(rValue.c_str()).toBoolean();
80 else if (aTypeClass == uno::TypeClass_SHORT)
81 aAny <<= static_cast<sal_Int16>(o3tl::toInt32(rValue));
82 else if (aTypeClass == uno::TypeClass_UNSIGNED_SHORT)
83 aAny <<= static_cast<sal_uInt16>(o3tl::toUInt32(rValue));
84 else if (aTypeClass == uno::TypeClass_LONG)
85 aAny <<= o3tl::toInt32(rValue);
86 else if (aTypeClass == uno::TypeClass_UNSIGNED_LONG)
87 aAny <<= static_cast<sal_uInt32>(o3tl::toInt32(rValue));
88 else if (aTypeClass == uno::TypeClass_FLOAT)
89 aAny <<= OString(rValue.c_str()).toFloat();
90 else if (aTypeClass == uno::TypeClass_DOUBLE)
91 aAny <<= o3tl::toDouble(rValue);
92 else if (aTypeClass == uno::TypeClass_STRING)
93 aAny <<= OUString::fromUtf8(rValue.c_str());
96 return aAny;
100 namespace comphelper{
102 SequenceAsHashMap::SequenceAsHashMap()
106 SequenceAsHashMap::SequenceAsHashMap(const css::uno::Any& aSource)
108 (*this) << aSource;
112 SequenceAsHashMap::SequenceAsHashMap(const css::uno::Sequence< css::uno::Any >& lSource)
114 (*this) << lSource;
117 SequenceAsHashMap::SequenceAsHashMap(const css::uno::Sequence< css::beans::PropertyValue >& lSource)
119 (*this) << lSource;
122 SequenceAsHashMap::SequenceAsHashMap(const css::uno::Sequence< css::beans::NamedValue >& lSource)
124 (*this) << lSource;
127 void SequenceAsHashMap::operator<<(const css::uno::Any& aSource)
129 // An empty Any reset this instance!
130 if (!aSource.hasValue())
132 clear();
133 return;
136 css::uno::Sequence< css::beans::NamedValue > lN;
137 if (aSource >>= lN)
139 (*this) << lN;
140 return;
143 css::uno::Sequence< css::beans::PropertyValue > lP;
144 if (aSource >>= lP)
146 (*this) << lP;
147 return;
150 throw css::lang::IllegalArgumentException(
151 "Any contains wrong type.", css::uno::Reference<css::uno::XInterface>(),
152 -1);
156 void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::uno::Any >& lSource)
158 sal_Int32 c = lSource.getLength();
159 sal_Int32 i = 0;
161 m_aMap.reserve(c);
162 for (i=0; i<c; ++i)
164 css::beans::PropertyValue lP;
165 if (lSource[i] >>= lP)
167 if (
168 (lP.Name.isEmpty()) ||
169 (!lP.Value.hasValue())
171 throw css::lang::IllegalArgumentException(
172 "PropertyValue struct contains no useful information.",
173 css::uno::Reference<css::uno::XInterface>(), -1);
174 (*this)[lP.Name] = lP.Value;
175 continue;
178 css::beans::NamedValue lN;
179 if (lSource[i] >>= lN)
181 if (
182 (lN.Name.isEmpty()) ||
183 (!lN.Value.hasValue())
185 throw css::lang::IllegalArgumentException(
186 "NamedValue struct contains no useful information.",
187 css::uno::Reference<css::uno::XInterface>(), -1);
188 (*this)[lN.Name] = lN.Value;
189 continue;
192 // ignore VOID Any ... but reject wrong filled ones!
193 if (lSource[i].hasValue())
194 throw css::lang::IllegalArgumentException(
195 "Any contains wrong type.",
196 css::uno::Reference<css::uno::XInterface>(), -1);
200 void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::beans::PropertyValue >& lSource)
202 clear();
204 sal_Int32 c = lSource.getLength();
205 const css::beans::PropertyValue* pSource = lSource.getConstArray();
207 m_aMap.reserve(c);
208 for (sal_Int32 i=0; i<c; ++i)
209 (*this)[pSource[i].Name] = pSource[i].Value;
212 void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::beans::NamedValue >& lSource)
214 clear();
216 sal_Int32 c = lSource.getLength();
217 const css::beans::NamedValue* pSource = lSource.getConstArray();
219 m_aMap.reserve(c);
220 for (sal_Int32 i=0; i<c; ++i)
221 (*this)[pSource[i].Name] = pSource[i].Value;
224 void SequenceAsHashMap::operator>>(css::uno::Sequence< css::beans::PropertyValue >& lDestination) const
226 sal_Int32 c = static_cast<sal_Int32>(size());
227 lDestination.realloc(c);
228 css::beans::PropertyValue* pDestination = lDestination.getArray();
230 sal_Int32 i = 0;
231 for (const_iterator pThis = begin();
232 pThis != end() ;
233 ++pThis )
235 pDestination[i].Name = pThis->first.maString;
236 pDestination[i].Value = pThis->second;
237 ++i;
241 void SequenceAsHashMap::operator>>(css::uno::Sequence< css::beans::NamedValue >& lDestination) const
243 sal_Int32 c = static_cast<sal_Int32>(size());
244 lDestination.realloc(c);
245 css::beans::NamedValue* pDestination = lDestination.getArray();
247 sal_Int32 i = 0;
248 for (const_iterator pThis = begin();
249 pThis != end() ;
250 ++pThis )
252 pDestination[i].Name = pThis->first.maString;
253 pDestination[i].Value = pThis->second;
254 ++i;
258 css::uno::Any SequenceAsHashMap::getAsConstAny(bool bAsPropertyValueList) const
260 css::uno::Any aDestination;
261 if (bAsPropertyValueList)
262 aDestination <<= getAsConstPropertyValueList();
263 else
264 aDestination <<= getAsConstNamedValueList();
265 return aDestination;
268 css::uno::Sequence< css::beans::NamedValue > SequenceAsHashMap::getAsConstNamedValueList() const
270 css::uno::Sequence< css::beans::NamedValue > lReturn;
271 (*this) >> lReturn;
272 return lReturn;
275 css::uno::Sequence< css::beans::PropertyValue > SequenceAsHashMap::getAsConstPropertyValueList() const
277 css::uno::Sequence< css::beans::PropertyValue > lReturn;
278 (*this) >> lReturn;
279 return lReturn;
282 bool SequenceAsHashMap::match(const SequenceAsHashMap& rCheck) const
284 for (auto const& elem : rCheck)
286 const OUString& sCheckName = elem.first.maString;
287 const css::uno::Any& aCheckValue = elem.second;
288 const_iterator pFound = find(sCheckName);
290 if (pFound == end())
291 return false;
293 const css::uno::Any& aFoundValue = pFound->second;
294 if (aFoundValue != aCheckValue)
295 return false;
298 return true;
301 void SequenceAsHashMap::update(const SequenceAsHashMap& rUpdate)
303 m_aMap.reserve(std::max(size(), rUpdate.size()));
304 for (auto const& elem : rUpdate.m_aMap)
306 m_aMap[elem.first] = elem.second;
310 std::vector<css::beans::PropertyValue> JsonToPropertyValues(const OString& rJson)
312 std::vector<beans::PropertyValue> aArguments;
313 boost::property_tree::ptree aTree, aNodeNull, aNodeValue;
314 std::stringstream aStream(rJson.getStr());
315 boost::property_tree::read_json(aStream, aTree);
317 for (const auto& rPair : aTree)
319 const std::string& rType = rPair.second.get<std::string>("type", "");
320 const std::string& rValue = rPair.second.get<std::string>("value", "");
322 beans::PropertyValue aValue;
323 aValue.Name = OUString::fromUtf8(rPair.first.c_str());
324 if (rType == "string")
325 aValue.Value <<= OUString::fromUtf8(rValue.c_str());
326 else if (rType == "boolean")
327 aValue.Value <<= OString(rValue.c_str()).toBoolean();
328 else if (rType == "float")
329 aValue.Value <<= OString(rValue.c_str()).toFloat();
330 else if (rType == "long")
331 aValue.Value <<= o3tl::toInt32(rValue);
332 else if (rType == "short")
333 aValue.Value <<= sal_Int16(o3tl::toInt32(rValue));
334 else if (rType == "unsigned short")
335 aValue.Value <<= sal_uInt16(o3tl::toUInt32(rValue));
336 else if (rType == "int64")
337 aValue.Value <<= o3tl::toInt64(rValue);
338 else if (rType == "int32")
339 aValue.Value <<= o3tl::toInt32(rValue);
340 else if (rType == "int16")
341 aValue.Value <<= sal_Int16(o3tl::toInt32(rValue));
342 else if (rType == "uint64")
343 aValue.Value <<= OString(rValue.c_str()).toUInt64();
344 else if (rType == "uint32")
345 aValue.Value <<= o3tl::toUInt32(rValue);
346 else if (rType == "uint16")
347 aValue.Value <<= sal_uInt16(o3tl::toUInt32(rValue));
348 else if (rType == "[]byte")
350 aNodeValue = rPair.second.get_child("value", aNodeNull);
351 if (aNodeValue != aNodeNull && aNodeValue.size() == 0)
353 uno::Sequence<sal_Int8> aSeqByte(reinterpret_cast<const sal_Int8*>(rValue.c_str()),
354 rValue.size());
355 aValue.Value <<= aSeqByte;
358 else if (rType == "[]any")
360 aNodeValue = rPair.second.get_child("value", aNodeNull);
361 if (aNodeValue != aNodeNull && !aNodeValue.empty())
363 uno::Sequence<uno::Any> aSeq(aNodeValue.size());
364 std::transform(aNodeValue.begin(), aNodeValue.end(), aSeq.getArray(),
365 [](const auto& rSeqPair) { return jsonToUnoAny(rSeqPair.second); });
366 aValue.Value <<= aSeq;
369 else
370 SAL_WARN("comphelper", "JsonToPropertyValues: unhandled type '" << rType << "'");
371 aArguments.push_back(aValue);
373 return aArguments;
376 } // namespace comphelper
378 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */