/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include using namespace com::sun::star; namespace { uno::Any jsonToUnoAny(const boost::property_tree::ptree& aTree) { uno::Any aAny; uno::Any aValue; sal_Int32 nFields; uno::Reference aField; boost::property_tree::ptree aNodeNull, aNodeValue, aNodeField; const std::string& rType = aTree.get("type", ""); const std::string& rValue = aTree.get("value", ""); uno::Sequence> aFields; uno::Reference xIdlClass = css::reflection::theCoreReflection::get(comphelper::getProcessComponentContext()) ->forName(OUString::fromUtf8(rType.c_str())); if (xIdlClass.is()) { uno::TypeClass aTypeClass = xIdlClass->getTypeClass(); xIdlClass->createObject(aAny); aFields = xIdlClass->getFields(); nFields = aFields.getLength(); aNodeValue = aTree.get_child("value", aNodeNull); if (nFields > 0 && aNodeValue != aNodeNull) { for (sal_Int32 itField = 0; itField < nFields; ++itField) { aField = aFields[itField]; aNodeField = aNodeValue.get_child(aField->getName().toUtf8().getStr(), aNodeNull); if (aNodeField != aNodeNull) { aValue = jsonToUnoAny(aNodeField); aField->set(aAny, aValue); } } } else if (!rValue.empty()) { if (aTypeClass == uno::TypeClass_VOID) aAny.clear(); else if (aTypeClass == uno::TypeClass_BYTE) aAny <<= static_cast(o3tl::toInt32(rValue)); else if (aTypeClass == uno::TypeClass_BOOLEAN) aAny <<= OString(rValue.c_str()).toBoolean(); else if (aTypeClass == uno::TypeClass_SHORT) aAny <<= static_cast(o3tl::toInt32(rValue)); else if (aTypeClass == uno::TypeClass_UNSIGNED_SHORT) aAny <<= static_cast(o3tl::toUInt32(rValue)); else if (aTypeClass == uno::TypeClass_LONG) aAny <<= o3tl::toInt32(rValue); else if (aTypeClass == uno::TypeClass_UNSIGNED_LONG) aAny <<= static_cast(o3tl::toInt32(rValue)); else if (aTypeClass == uno::TypeClass_FLOAT) aAny <<= OString(rValue.c_str()).toFloat(); else if (aTypeClass == uno::TypeClass_DOUBLE) aAny <<= o3tl::toDouble(rValue); else if (aTypeClass == uno::TypeClass_STRING) aAny <<= OUString::fromUtf8(rValue.c_str()); } } return aAny; } } namespace comphelper{ SequenceAsHashMap::SequenceAsHashMap() { } SequenceAsHashMap::SequenceAsHashMap(const css::uno::Any& aSource) { (*this) << aSource; } SequenceAsHashMap::SequenceAsHashMap(const css::uno::Sequence< css::uno::Any >& lSource) { (*this) << lSource; } SequenceAsHashMap::SequenceAsHashMap(const css::uno::Sequence< css::beans::PropertyValue >& lSource) { (*this) << lSource; } SequenceAsHashMap::SequenceAsHashMap(const css::uno::Sequence< css::beans::NamedValue >& lSource) { (*this) << lSource; } void SequenceAsHashMap::operator<<(const css::uno::Any& aSource) { // An empty Any reset this instance! if (!aSource.hasValue()) { clear(); return; } css::uno::Sequence< css::beans::NamedValue > lN; if (aSource >>= lN) { (*this) << lN; return; } css::uno::Sequence< css::beans::PropertyValue > lP; if (aSource >>= lP) { (*this) << lP; return; } throw css::lang::IllegalArgumentException( "Any contains wrong type.", css::uno::Reference(), -1); } void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::uno::Any >& lSource) { sal_Int32 c = lSource.getLength(); sal_Int32 i = 0; m_aMap.reserve(c); for (i=0; i>= lP) { if ( (lP.Name.isEmpty()) || (!lP.Value.hasValue()) ) throw css::lang::IllegalArgumentException( "PropertyValue struct contains no useful information.", css::uno::Reference(), -1); (*this)[lP.Name] = lP.Value; continue; } css::beans::NamedValue lN; if (lSource[i] >>= lN) { if ( (lN.Name.isEmpty()) || (!lN.Value.hasValue()) ) throw css::lang::IllegalArgumentException( "NamedValue struct contains no useful information.", css::uno::Reference(), -1); (*this)[lN.Name] = lN.Value; continue; } // ignore VOID Any ... but reject wrong filled ones! if (lSource[i].hasValue()) throw css::lang::IllegalArgumentException( "Any contains wrong type.", css::uno::Reference(), -1); } } void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::beans::PropertyValue >& lSource) { clear(); sal_Int32 c = lSource.getLength(); const css::beans::PropertyValue* pSource = lSource.getConstArray(); m_aMap.reserve(c); for (sal_Int32 i=0; i& lSource) { clear(); sal_Int32 c = lSource.getLength(); const css::beans::NamedValue* pSource = lSource.getConstArray(); m_aMap.reserve(c); for (sal_Int32 i=0; i>(css::uno::Sequence< css::beans::PropertyValue >& lDestination) const { sal_Int32 c = static_cast(size()); lDestination.realloc(c); css::beans::PropertyValue* pDestination = lDestination.getArray(); sal_Int32 i = 0; for (const_iterator pThis = begin(); pThis != end() ; ++pThis ) { pDestination[i].Name = pThis->first.maString; pDestination[i].Value = pThis->second; ++i; } } void SequenceAsHashMap::operator>>(css::uno::Sequence< css::beans::NamedValue >& lDestination) const { sal_Int32 c = static_cast(size()); lDestination.realloc(c); css::beans::NamedValue* pDestination = lDestination.getArray(); sal_Int32 i = 0; for (const_iterator pThis = begin(); pThis != end() ; ++pThis ) { pDestination[i].Name = pThis->first.maString; pDestination[i].Value = pThis->second; ++i; } } css::uno::Any SequenceAsHashMap::getAsConstAny(bool bAsPropertyValueList) const { css::uno::Any aDestination; if (bAsPropertyValueList) aDestination <<= getAsConstPropertyValueList(); else aDestination <<= getAsConstNamedValueList(); return aDestination; } css::uno::Sequence< css::beans::NamedValue > SequenceAsHashMap::getAsConstNamedValueList() const { css::uno::Sequence< css::beans::NamedValue > lReturn; (*this) >> lReturn; return lReturn; } css::uno::Sequence< css::beans::PropertyValue > SequenceAsHashMap::getAsConstPropertyValueList() const { css::uno::Sequence< css::beans::PropertyValue > lReturn; (*this) >> lReturn; return lReturn; } bool SequenceAsHashMap::match(const SequenceAsHashMap& rCheck) const { for (auto const& elem : rCheck) { const OUString& sCheckName = elem.first.maString; const css::uno::Any& aCheckValue = elem.second; const_iterator pFound = find(sCheckName); if (pFound == end()) return false; const css::uno::Any& aFoundValue = pFound->second; if (aFoundValue != aCheckValue) return false; } return true; } void SequenceAsHashMap::update(const SequenceAsHashMap& rUpdate) { m_aMap.reserve(std::max(size(), rUpdate.size())); for (auto const& elem : rUpdate.m_aMap) { m_aMap[elem.first] = elem.second; } } std::vector JsonToPropertyValues(const OString& rJson) { std::vector aArguments; boost::property_tree::ptree aTree, aNodeNull, aNodeValue; std::stringstream aStream(rJson.getStr()); boost::property_tree::read_json(aStream, aTree); for (const auto& rPair : aTree) { const std::string& rType = rPair.second.get("type", ""); const std::string& rValue = rPair.second.get("value", ""); beans::PropertyValue aValue; aValue.Name = OUString::fromUtf8(rPair.first.c_str()); if (rType == "string") aValue.Value <<= OUString::fromUtf8(rValue.c_str()); else if (rType == "boolean") aValue.Value <<= OString(rValue.c_str()).toBoolean(); else if (rType == "float") aValue.Value <<= OString(rValue.c_str()).toFloat(); else if (rType == "long") aValue.Value <<= o3tl::toInt32(rValue); else if (rType == "short") aValue.Value <<= sal_Int16(o3tl::toInt32(rValue)); else if (rType == "unsigned short") aValue.Value <<= sal_uInt16(o3tl::toUInt32(rValue)); else if (rType == "int64") aValue.Value <<= o3tl::toInt64(rValue); else if (rType == "int32") aValue.Value <<= o3tl::toInt32(rValue); else if (rType == "int16") aValue.Value <<= sal_Int16(o3tl::toInt32(rValue)); else if (rType == "uint64") aValue.Value <<= OString(rValue.c_str()).toUInt64(); else if (rType == "uint32") aValue.Value <<= o3tl::toUInt32(rValue); else if (rType == "uint16") aValue.Value <<= sal_uInt16(o3tl::toUInt32(rValue)); else if (rType == "[]byte") { aNodeValue = rPair.second.get_child("value", aNodeNull); if (aNodeValue != aNodeNull && aNodeValue.size() == 0) { uno::Sequence aSeqByte(reinterpret_cast(rValue.c_str()), rValue.size()); aValue.Value <<= aSeqByte; } } else if (rType == "[]any") { aNodeValue = rPair.second.get_child("value", aNodeNull); if (aNodeValue != aNodeNull && !aNodeValue.empty()) { uno::Sequence aSeq(aNodeValue.size()); std::transform(aNodeValue.begin(), aNodeValue.end(), aSeq.getArray(), [](const auto& rSeqPair) { return jsonToUnoAny(rSeqPair.second); }); aValue.Value <<= aSeq; } } else SAL_WARN("comphelper", "JsonToPropertyValues: unhandled type '" << rType << "'"); aArguments.push_back(aValue); } return aArguments; } } // namespace comphelper /* vim:set shiftwidth=4 softtabstop=4 expandtab: */