VariantJsonCompressor.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2012-2016, High Performance Humanoid Technologies (H2T),
5  * Karlsruhe Institute of Technology (KIT), all rights reserved.
6  *
7  * ArmarX is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  * ArmarX is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  *
19  * @author Simon Ottenhaus (simon dot ottenhaus at kit dot edu)
20  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
21  * GNU General Public License
22  */
23 
24 #include "VariantJsonCompressor.h"
25 #include "VariantJsonException.h"
26 
29 
31 
32 #include <Ice/ObjectFactory.h>
33 
34 namespace armarx
35 {
37  {
38  }
39 
40  ParseResult VariantJsonCompressor::CheckUserInput(const std::string& json, const std::string& variantBaseTypeName, const Ice::CommunicatorPtr& communicator)
41  {
42  StructuralJsonParser parser(json, false, true);
43  parser.parse();
44  if (parser.iserr())
45  {
46  return ParseResult("JSON parse error: " + parser.geterr(), ParseResult::eSytaxError);
47  }
48 
49  ContainerTypePtr containerInfo = ::armarx::VariantContainerType::FromString(variantBaseTypeName);
50  ParseResult result = CheckUserInput(parser.parsedJson, containerInfo, communicator);
51  if (result.iserr())
52  {
53  JPathNavigator nav(parser.parsedJson);
54  nav = nav.selectSingleNode("type");
55  if (nav.isString())
56  {
57  std::string type = nav.asString();
59  {
60  return ParseResult("Input might be in old format. Try importing.\n" + result.geterr(), result.getErrorType());
61  }
62  }
63  }
64  return result;
65  }
66 
67  ParseResult VariantJsonCompressor::FormatUserInput(std::string& json, int indenting)
68  {
69  StructuralJsonParser parser(json, false, true);
70  parser.parse();
71  if (parser.iserr())
72  {
73  return ParseResult("JSON parse error: " + parser.geterr(), ParseResult::eSytaxError);
74  }
75  json = parser.parsedJson->toJsonString(indenting);
76  return ParseResult::Success();
77  }
78 
79  ParseResult VariantJsonCompressor::CheckUserInput(const JsonDataPtr& json, const ContainerTypePtr& containerInfo, const Ice::CommunicatorPtr& communicator)
80  {
81  JPathNavigator nav(json);
82  if (containerInfo->subType)
83  {
84  if (containerInfo->typeId == SingleTypeVariantList::getTypePrefix())
85  {
86  if (!nav.isArray())
87  {
88  return ParseResult::Error("Unexpected JSON data type. Expected array at " + nav.getData()->getLexerStartOffset().toLongString(), ParseResult::eContainerMismatch);
89  }
90  for (JPathNavigator child : nav.select("*"))
91  {
92  ParseResult r = CheckUserInput(child.getData(), containerInfo->subType, communicator);
93  if (r.iserr())
94  {
95  return r;
96  }
97  }
98  return ParseResult::Success();
99  }
100  else if (containerInfo->typeId == StringValueMap::getTypePrefix())
101  {
102  if (!nav.isObject())
103  {
104  return ParseResult::Error("Unexpected JSON data type. Expected object at " + nav.getData()->getLexerStartOffset().toLongString(), ParseResult::eContainerMismatch);
105  }
106  for (JPathNavigator child : nav.select("*"))
107  {
108  ParseResult r = CheckUserInput(child.getData(), containerInfo->subType, communicator);
109  if (r.iserr())
110  {
111  return r;
112  }
113  }
114  return ParseResult::Success();
115  }
116  else
117  {
118  return ParseResult::Error("Unknown container type: " + containerInfo->typeId + ". At " + nav.getData()->getLexerStartOffset().toLongString(), ParseResult::eContainerMismatch);
119  }
120  }
121  else if (VariantType::IsBasicType(Variant::hashTypeName(containerInfo->typeId)))
122  {
123  VariantTypeId type = Variant::hashTypeName(containerInfo->typeId);
124  if (type == VariantType::Bool && !nav.isBool())
125  {
126  return ParseResult::Error("Cannot parse Variant: Expected bool at " + nav.getData()->getLexerStartOffset().toLongString(), ParseResult::eVariantParseError);
127  }
128  else if (type == VariantType::String && !nav.isString())
129  {
130  return ParseResult::Error("Cannot parse Variant: Expected string at " + nav.getData()->getLexerStartOffset().toLongString(), ParseResult::eVariantParseError);
131  }
132  else if (type == VariantType::Float && !nav.isNumber())
133  {
134  return ParseResult::Error("Cannot parse Variant: Expected number at " + nav.getData()->getLexerStartOffset().toLongString(), ParseResult::eVariantParseError);
135  }
136  else if (type == VariantType::Double && !nav.isNumber())
137  {
138  return ParseResult::Error("Cannot parse Variant: Expected number at " + nav.getData()->getLexerStartOffset().toLongString(), ParseResult::eVariantParseError);
139  }
140  else if (type == VariantType::Int && !nav.isInt())
141  {
142  return ParseResult::Error("Cannot parse Variant: Expected int at " + nav.getData()->getLexerStartOffset().toLongString(), ParseResult::eVariantParseError);
143  }
144  else if (type == VariantType::Long && !nav.isInt())
145  {
146  return ParseResult::Error("Cannot parse Variant: Expected int at " + nav.getData()->getLexerStartOffset().toLongString(), ParseResult::eVariantParseError);
147  }
148 
149  return ParseResult::Success();
150  }
151  else
152  {
153  Ice::ValueFactoryPtr factory = communicator->getValueFactoryManager()->find(containerInfo->typeId);
154  SerializablePtr obj = SerializablePtr::dynamicCast(factory->create(containerInfo->typeId));
155  static Ice::Current c;
156 
157  JSONObjectPtr jsonObject = new JSONObject();
158  jsonObject->fromString(json->toJsonString(0));
159  try
160  {
161  obj->deserialize(jsonObject, c);
162  }
163  catch (const UserException& ex)
164  {
165  return ParseResult::Error(std::string("Cannot parse Variant: ") + ex.ice_id() + ": " + ex.reason + ". At " + nav.getData()->getLexerStartOffset().toLongString(), ParseResult::eVariantParseError);
166  }
167  catch (LocalException& ex)
168  {
169  return ParseResult::Error(std::string("Cannot parse Variant: ") + ex.name() + ": " + ex.getReason() + ". At " + nav.getData()->getLexerStartOffset().toLongString(), ParseResult::eVariantParseError);
170  }
171 
172  VariantDataPtr variant = VariantDataPtr::dynamicCast(obj);
173  if (variant == 0)
174  {
175  return ParseResult::Error("Cannot cast Variant. Expected: " + containerInfo->typeId + ". Is: " + obj->ice_id() + ". At " + nav.getData()->getLexerStartOffset().toLongString(), ParseResult::eVariantParseError);
176  }
177  return ParseResult::Success();
178  }
179  }
180 
181  std::string VariantJsonCompressor::Compress(const std::string& json, const std::string& variantBaseTypeName, int indenting)
182  {
183  JsonDataPtr compressed = CompressToJson(json, variantBaseTypeName);
184  return compressed->toJsonString(indenting);
185  }
186 
187  JsonDataPtr VariantJsonCompressor::CompressToJson(const std::string& json, const std::string& variantBaseTypeName)
188  {
189  StructuralJsonParser parser(json, false, true);
190  parser.parse();
191  if (parser.iserr())
192  {
193  throw VariantJsonException("Invalid json: ") << parser.geterr();
194  }
195 
196  ContainerTypePtr containerInfo = ::armarx::VariantContainerType::FromString(variantBaseTypeName);
197  return Compress(parser.parsedJson, containerInfo);
198  }
199 
200  std::string VariantJsonCompressor::Decompress(const std::string& json, const std::string& variantBaseTypeName)
201  {
202  StructuralJsonParser parser(json, false, true);
203  parser.parse();
204  if (parser.iserr())
205  {
206  throw VariantJsonException("Invalid json: ") << parser.geterr();
207  }
208 
209  ContainerTypePtr containerInfo = ::armarx::VariantContainerType::FromString(variantBaseTypeName);
210  JsonDataPtr decompressed = Decompress(parser.parsedJson, containerInfo);
211  return decompressed->toJsonString(0);
212  }
213 
214  std::string VariantJsonCompressor::DecompressBasicVariant(const std::string& value, const std::string& variantBaseTypeName)
215  {
216  int typeId = Variant::hashTypeName(variantBaseTypeName);
217 
218  JsonObjectPtr variant(new JsonObject);
219  variant->add("typeName", variantBaseTypeName);
220 
221  if (typeId == VariantType::Int)
222  {
223  variant->add("value", JsonValue::CreateRaw(JsonValue::eNumber, value));
224  }
225  else if (typeId == VariantType::Long)
226  {
227  variant->add("value", JsonValue::CreateRaw(JsonValue::eNumber, value));
228  }
229  else if (typeId == VariantType::Bool)
230  {
231  variant->add("value", JsonValue::CreateRaw(JsonValue::eBool, value));
232  }
233  else if (typeId == VariantType::Float)
234  {
235  variant->add("value", JsonValue::CreateRaw(JsonValue::eNumber, value));
236  }
237  else if (typeId == VariantType::Double)
238  {
239  variant->add("value", JsonValue::CreateRaw(JsonValue::eNumber, value));
240  }
241  else if (typeId == VariantType::String)
242  {
243  variant->add("value", JsonValue::CreateRaw(JsonValue::eString, value));
244  }
245  else
246  {
247  throw VariantJsonException("Unsupported Basic Type: ") << variantBaseTypeName;
248  }
249 
250  JsonObjectPtr o(new JsonObject);
251  o->add("type", JsonValue(SingleVariant::getTypePrefix()));
252  o->add("variant", variant);
253  return o->toJsonString(0);
254  }
255 
256  JsonDataPtr VariantJsonCompressor::Decompress(const JsonDataPtr& json, const ContainerTypePtr& containerInfo)
257  {
258  if (containerInfo->subType)
259  {
260  JPathNavigator nav(json);
261  if (containerInfo->typeId == SingleTypeVariantList::getTypePrefix())
262  {
263  JsonArrayPtr array(new JsonArray);
264  if (!nav.isArray())
265  {
266  throw VariantJsonException("Wrong JSON data type. Expected array at ") << nav.getData()->getLexerStartOffset().toLongString();
267  }
268  for (JPathNavigator child : nav.select("*"))
269  {
270  array->add(Decompress(child.getData(), containerInfo->subType));
271  }
272  JsonObjectPtr o(new JsonObject);
273  o->add("array", array);
274  o->add("type", JsonValue(containerInfo->typeId));
275  return o;
276  }
277  else if (containerInfo->typeId == StringValueMap::getTypePrefix())
278  {
279  JsonObjectPtr map(new JsonObject);
280  if (!nav.isObject())
281  {
282  throw VariantJsonException("Wrong JSON data type. Expected object at ") << nav.getData()->getLexerStartOffset().toLongString();
283  }
284  for (JPathNavigator child : nav.select("*"))
285  {
286  map->add(child.getKey(), Decompress(child.getData(), containerInfo->subType));
287  }
288  JsonObjectPtr o(new JsonObject);
289  o->add("map", map);
290  o->add("type", JsonValue(containerInfo->typeId));
291  return o;
292  }
293  else
294  {
295  throw VariantJsonException("Unknown container type: ") << containerInfo->typeId;
296  }
297  }
298  else
299  {
300  JsonObjectPtr variant(new JsonObject);
301  variant->add("typeName", containerInfo->typeId);
302  variant->add("value", json->clone());
303  JsonObjectPtr o(new JsonObject);
304  o->add("type", JsonValue(SingleVariant::getTypePrefix()));
305  o->add("variant", variant);
306  return o;
307  }
308  }
309 
310  JsonDataPtr VariantJsonCompressor::Compress(const JPathNavigator& nav, const ContainerTypePtr& containerInfo)
311  {
312  if (containerInfo->subType)
313  {
314  if (containerInfo->typeId == SingleTypeVariantList::getTypePrefix())
315  {
316  JsonArrayPtr a(new JsonArray);
317  for (JPathNavigator child : nav.select("array/*"))
318  {
319  a->add(Compress(child.getData(), containerInfo->subType));
320  }
321  return a;
322  }
323  else if (containerInfo->typeId == StringValueMap::getTypePrefix())
324  {
325  JsonObjectPtr o(new JsonObject);
326  for (JPathNavigator child : nav.select("map/*"))
327  {
328  o->add(child.getKey(), Compress(child.getData(), containerInfo->subType));
329  }
330  return o;
331  }
332  else
333  {
334  throw VariantJsonException("Unknown container type: ") << containerInfo->typeId;
335  }
336  }
337  else
338  {
339  std::string typeName = nav.selectSingleNode("variant/typeName").asString();
340  if (typeName != containerInfo->typeId)
341  {
342  throw VariantJsonException("typeName mismatch. expected: ") << containerInfo->typeId << ". is: " << typeName;
343  }
344 
345  return nav.selectSingleNode("variant/value").getData();
346  }
347  }
348 }
349 
armarx::JsonValue::eNumber
@ eNumber
Definition: JsonValue.h:38
armarx::ParseResult::eSytaxError
@ eSytaxError
Definition: ParseResult.h:36
armarx::VariantType::Float
const VariantTypeId Float
Definition: Variant.h:918
armarx::JPathNavigator::isString
bool isString() const
Definition: JPathNavigator.cpp:58
armarx::ParseResult
Definition: ParseResult.h:33
armarx::ParseResult::iserr
bool iserr()
Definition: ParseResult.cpp:33
JSONObject.h
armarx::JPathNavigator::asString
std::string asString() const
Definition: JPathNavigator.cpp:203
armarx::SingleVariant::getTypePrefix
static std::string getTypePrefix()
Definition: VariantContainer.cpp:144
armarx::JsonArrayPtr
std::shared_ptr< JsonArray > JsonArrayPtr
Definition: JsonArray.h:32
armarx::VariantJsonCompressor::FormatUserInput
static ParseResult FormatUserInput(std::string &json, int indenting=2)
Definition: VariantJsonCompressor.cpp:67
StructuralJsonParser.h
IceStorm::Parser::parse
int parse(FILE *, bool)
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
armarx::VariantType::Bool
const VariantTypeId Bool
Definition: Variant.h:915
armarx::JsonArray
Definition: JsonArray.h:34
armarx::JPathNavigator
Definition: JPathNavigator.h:35
armarx::JsonValue
Definition: JsonValue.h:34
armarx::JsonValue::eString
@ eString
Definition: JsonValue.h:38
IceInternal::Handle< ::Ice::Communicator >
armarx::VariantType::Double
const VariantTypeId Double
Definition: Variant.h:919
armarx::VariantJsonCompressor::VariantJsonCompressor
VariantJsonCompressor()
Definition: VariantJsonCompressor.cpp:36
armarx::VariantJsonException
Definition: VariantJsonException.h:32
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
armarx::VariantJsonCompressor::CheckUserInput
static ParseResult CheckUserInput(const std::string &json, const std::string &variantBaseTypeName, const Ice::CommunicatorPtr &communicator)
Definition: VariantJsonCompressor.cpp:40
JPathNavigator.h
armarx::JSONObjectPtr
IceInternal::Handle< JSONObject > JSONObjectPtr
Definition: JSONObject.h:34
armarx::ParseResult::getErrorType
ErrorType getErrorType()
Definition: ParseResult.cpp:43
armarx::VariantType::Long
const VariantTypeId Long
Definition: Variant.h:917
armarx::ParseResult::eVariantParseError
@ eVariantParseError
Definition: ParseResult.h:36
armarx::VariantJsonCompressor::Decompress
static std::string Decompress(const std::string &json, const std::string &variantBaseTypeName)
Definition: VariantJsonCompressor.cpp:200
armarx::JsonValue::eBool
@ eBool
Definition: JsonValue.h:38
armarx::VariantTypeId
Ice::Int VariantTypeId
Definition: Variant.h:44
armarx::VariantType::IsBasicType
bool IsBasicType(VariantTypeId id)
Definition: Variant.cpp:772
armarx::VariantJsonCompressor::CompressToJson
static JsonDataPtr CompressToJson(const std::string &json, const std::string &variantBaseTypeName)
Definition: VariantJsonCompressor.cpp:187
IceStorm::parser
Parser * parser
Definition: Parser.cpp:33
armarx::JsonObject
Definition: JsonObject.h:36
VariantJsonCompressor.h
armarx::VariantJsonCompressor::DecompressBasicVariant
static std::string DecompressBasicVariant(const std::string &value, const std::string &variantBaseTypeName)
Definition: VariantJsonCompressor.cpp:214
armarx::VariantType::Int
const VariantTypeId Int
Definition: Variant.h:916
armarx::Variant::hashTypeName
static int hashTypeName(const std::string &typeName)
Compute and return a hash value for a given type name.
Definition: Variant.cpp:699
armarx::ParseResult::geterr
std::string geterr()
Definition: ParseResult.cpp:38
armarx::JPathNavigator::selectSingleNode
JPathNavigator selectSingleNode(const std::string &expr) const
Definition: JPathNavigator.cpp:110
armarx::ParseResult::Error
static ParseResult Error(const std::string &error, ErrorType errorType)
Definition: ParseResult.cpp:63
armarx::JsonDataPtr
std::shared_ptr< JsonData > JsonDataPtr
Definition: JsonData.h:31
armarx::VariantType::String
const VariantTypeId String
Definition: Variant.h:920
armarx::ParseResult::eContainerMismatch
@ eContainerMismatch
Definition: ParseResult.h:36
armarx::VariantJsonCompressor::Compress
static std::string Compress(const std::string &json, const std::string &variantBaseTypeName, int indenting=2)
Definition: VariantJsonCompressor.cpp:181
armarx::StructuralJsonParser
Definition: StructuralJsonParser.h:35
armarx::JsonValue::CreateRaw
static JsonValuePtr CreateRaw(Type type, const std::string &value)
Definition: JsonValue.cpp:95
armarx::VariantContainerType::FromString
static ContainerTypePtr FromString(const std::string &typeStr)
Definition: VariantContainer.cpp:262
armarx::ParseResult::Success
static ParseResult Success()
Definition: ParseResult.cpp:58
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
VariantJsonException.h
armarx::JsonObjectPtr
std::shared_ptr< JsonObject > JsonObjectPtr
Definition: JsonObject.h:34
armarx::StringValueMap::getTypePrefix
static std::string getTypePrefix()
Definition: StringValueMap.cpp:179
armarx::SingleTypeVariantList::getTypePrefix
static std::string getTypePrefix()
Definition: SingleTypeVariantList.cpp:201