1 /*
2  * Copyright 2006-2008 The FLWOR Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "stdafx.h"
17 #include <zorba/config.h>
18 
19 #ifdef ZORBA_WITH_JSON
20 
21 
22 #include <sstream>
23 
24 #include "system/globalenv.h"
25 
26 #include "api/serialization/serializer.h"
27 
28 #include "compiler/api/compilercb.h"
29 
30 #include "runtime/json/jsoniq_functions.h"
31 #include "runtime/parsing_and_serializing/parsing_and_serializing.h"
32 #include "runtime/visitors/planiter_visitor.h"
33 #include "runtime/api/plan_iterator_wrapper.h"
34 #include "runtime/util/item_iterator.h"
35 
36 #include "diagnostics/diagnostic.h"
37 #include "diagnostics/xquery_diagnostics.h"
38 #include "diagnostics/util_macros.h"
39 
40 #include "zorba/internal/diagnostic.h"
41 
42 #include "context/static_context.h"
43 
44 #include "types/casting.h"
45 #include "types/typeimpl.h"
46 #include "types/typeops.h"
47 #include "types/root_typemanager.h"
48 
49 #include "store/api/pul.h"
50 #include "store/api/item.h"
51 #include "store/api/item_factory.h"
52 #include "store/api/store.h"
53 #include "store/api/copymode.h"
54 
55 #include <zorba/store_consts.h>
56 
57 namespace zorba {
58 
59 const zstring XS_URI("http://www.w3.org/2001/XMLSchema");
60 
61 const zstring ENCODE_DECODE_DEFAULT_PREFIX("Q{http://jsoniq.org/roundtrip}");
62 
63 const zstring NS_PREFIX_KEY("prefix");
64 const zstring TYPE_KEY("type");
65 const zstring VALUE_KEY("value");
66 
67 const char * OPTIONS_KEY_PREFIX = "prefix";
68 const char * OPTIONS_KEY_SER_PARAMS = "serialization-parameters";
69 
70 const char * SEQTYPE_ANYNODE  = "node()";
71 const char * SEQTYPE_COMMENT  = "comment()";
72 const char * SEQTYPE_DOCUMENT = "document-node()";
73 const char * SEQTYPE_ELEMENT  = "element()";
74 const char * SEQTYPE_PROCINST = "processing-instruction()";
75 const char * SEQTYPE_TEXT     = "text()";
76 
kind2str(const store::NodeKind & aKind)77 const char * kind2str(const store::NodeKind& aKind)
78 {
79   // we do not support attibutes and namespaces as they cannot be serialized
80   switch (aKind)
81   {
82   case store::StoreConsts::anyNode:      return SEQTYPE_ANYNODE;
83   case store::StoreConsts::commentNode:  return SEQTYPE_COMMENT;
84   case store::StoreConsts::documentNode: return SEQTYPE_DOCUMENT;
85   case store::StoreConsts::elementNode:  return SEQTYPE_ELEMENT;
86   case store::StoreConsts::piNode:       return SEQTYPE_PROCINST;
87   case store::StoreConsts::textNode:     return SEQTYPE_TEXT;
88   default: return "";
89   }
90 }
91 
str2kind(const zstring & aString,store::NodeKind & aKind)92 bool str2kind(const zstring& aString, store::NodeKind& aKind)
93 {
94   switch(aString.at(0))
95   {
96   case 'c':
97     if (aString == SEQTYPE_COMMENT)
98     {
99       aKind = store::StoreConsts::commentNode;
100       return true;
101     }
102     break;
103   case 'd':
104     if (aString == SEQTYPE_DOCUMENT)
105     {
106       aKind = store::StoreConsts::documentNode;
107       return true;
108     }
109     break;
110   case 'e':
111   case 'n': // "node()" maps to element for backwards compatibility
112     if (aString == SEQTYPE_ELEMENT || aString == SEQTYPE_ANYNODE)
113     {
114       aKind = store::StoreConsts::elementNode;
115       return true;
116     }
117     break;
118   case 'p':
119     if (aString == SEQTYPE_PROCINST)
120     {
121       aKind = store::StoreConsts::piNode;
122       return true;
123     }
124     break;
125   case 't':
126     if (aString == SEQTYPE_TEXT)
127     {
128       aKind = store::StoreConsts::textNode;
129       return true;
130     }
131     break;
132   }
133   return false;
134 }
135 
136 /*******************************************************************************
137   json:decode-from-roundtrip($items as json-item()*,
138                              $options as object()) as structured-item()*
139 ********************************************************************************/
140 
141 void
parseQName(store::Item_t & aResult,const zstring & aQNameString,const zstring & aPrefix,store::ItemFactory * aFactory)142 parseQName(store::Item_t& aResult,
143            const zstring& aQNameString,
144            const zstring& aPrefix,
145            store::ItemFactory* aFactory)
146 {
147   // TODO there probably is a better solution somewhere
148   if (aQNameString.substr(0, 3) == "xs:")
149   {
150     aFactory->createQName(aResult, XS_URI, "xs", aQNameString.substr(3));
151   }
152   else if (aQNameString.substr(0, 2) == "Q{")
153   {
154     zstring::size_type lPos = aQNameString.find('}');
155     aFactory->createQName(aResult,
156                           aQNameString.substr(2, lPos - 2),
157                           aPrefix,
158                           aQNameString.substr(lPos + 1));
159   }
160   else
161   {
162     aFactory->createQName(aResult, "", "", aQNameString);
163   }
164 }
165 
166 void
extractChildOfKind(const store::Item_t & aParent,const store::NodeKind & aKind,store::Item_t & aChild)167 JSONDecodeFromRoundtripIterator::extractChildOfKind(
168   const store::Item_t& aParent,
169   const store::NodeKind& aKind,
170   store::Item_t& aChild)
171 {
172   store::Iterator_t lIt = aParent->getChildren();
173   bool lFound = false;
174   lIt->open();
175   while (! lFound && lIt->next(aChild))
176   {
177     lFound = aChild->getNodeKind() == aKind;
178   }
179   lIt->close();
180   ZORBA_ASSERT(lFound);
181 }
182 
183 bool
decodeNode(const store::Item_t & aSerializedNode,const store::NodeKind & aKind,store::Item_t & aResult) const184 JSONDecodeFromRoundtripIterator::decodeNode(
185   const store::Item_t& aSerializedNode,
186   const store::NodeKind& aKind,
187   store::Item_t& aResult) const
188 {
189   store::LoadProperties lProperties;
190   lProperties.setStoreDocument(false);
191   store::Item_t lDoc;
192   zstring lXmlString;
193   switch (aKind)
194   {
195   case store::StoreConsts::commentNode:
196   case store::StoreConsts::piNode:
197   case store::StoreConsts::textNode:
198     {
199       // we have to wrap these 3 node kinds, so we cannot care about streams
200       aSerializedNode->getStringValue2(lXmlString);
201       lXmlString = "<a>" + lXmlString + "</a>";
202       std::istringstream lStream(lXmlString.c_str());
203       lDoc = GENV.getStore().loadDocument("", "", lStream, lProperties);
204     }
205     break;
206   default:
207     if (aSerializedNode->isStreamable())
208     {
209       lDoc = GENV.getStore().loadDocument(
210             "", "", aSerializedNode->getStream(), lProperties);
211     }
212     else
213     {
214       aSerializedNode->getStringValue2(lXmlString);
215       std::istringstream lStream(lXmlString.c_str());
216       lDoc = GENV.getStore().loadDocument("", "", lStream, lProperties);
217     }
218     break;
219   }
220   if (aKind == store::StoreConsts::documentNode)
221   {
222     aResult = lDoc;
223   }
224   else
225   {
226     store::Item_t lRootElem;
227     extractChildOfKind(lDoc, store::StoreConsts::elementNode, lRootElem);
228     if (aKind == store::StoreConsts::elementNode)
229     {
230       // if we needed an element we're done
231       aResult = lRootElem;
232     }
233     else
234     {
235       // otherwise we have to pass through the wrapper that we've created
236       extractChildOfKind(lRootElem, aKind, aResult);
237     }
238   }
239   return true;
240 }
241 
242 bool
decodeXDM(const store::Item_t & anObj,store::Item_t & aResult,JSONDecodeFromRoundtripIteratorState * aState) const243 JSONDecodeFromRoundtripIterator::decodeXDM(
244   const store::Item_t& anObj,
245   store::Item_t& aResult,
246   JSONDecodeFromRoundtripIteratorState* aState) const
247 {
248   store::Item_t lItem;
249 
250   zstring lTypeKey = aState->thePrefix + TYPE_KEY;
251   GENV_ITEMFACTORY->createString(lItem, lTypeKey);
252   store::Item_t lTypeValueItem = anObj->getObjectValue(lItem);
253   if (lTypeValueItem.isNull())
254   {
255     // nothing to change, aResult is not set, the caller needs to use anObj
256     return false;
257   }
258 
259   zstring lValueKey = aState->thePrefix + VALUE_KEY;
260   GENV_ITEMFACTORY->createString(lItem, lValueKey);
261   store::Item_t lValueValueItem = anObj->getObjectValue(lItem);
262   if (lValueValueItem.isNull())
263   {
264     // nothing to change, aResult is not set, the caller needs to use anObj
265     return false;
266   }
267 
268   zstring lTypeNameString;
269   lTypeValueItem->getStringValue2(lTypeNameString);
270   store::NodeKind lNodeKind;
271   if (str2kind(lTypeNameString, lNodeKind))
272   {
273     return decodeNode(lValueValueItem, lNodeKind, aResult);
274   }
275   else
276   {
277     store::Item_t lTypeQName;
278     parseQName(lTypeQName, lTypeNameString, "", GENV_ITEMFACTORY);
279     if (lTypeQName->getLocalName() == "QName"
280         && lTypeQName->getNamespace() == XS_URI)
281     {
282       zstring lPrefixKey = aState->thePrefix + NS_PREFIX_KEY;
283       GENV_ITEMFACTORY->createString(lItem, lPrefixKey);
284       store::Item_t lPrefixValue = anObj->getObjectValue(lItem);
285       zstring lPrefixString;
286       if (! lPrefixValue.isNull())
287       {
288         lPrefixValue->getStringValue2(lPrefixString);
289       }
290       zstring lValueValue;
291       lValueValueItem->getStringValue2(lValueValue);
292       parseQName(aResult, lValueValue, lPrefixString, GENV_ITEMFACTORY);
293     }
294     else
295     {
296       TypeManager* lTypeMgr = theSctx->get_typemanager();
297       xqtref_t lTargetType = lTypeMgr->create_named_type(
298             lTypeQName.getp(), TypeConstants::QUANT_ONE, loc);
299       namespace_context lTmpNsCtx(theSctx);
300       GenericCast::castToAtomic(aResult,
301                                 lValueValueItem,
302                                 lTargetType.getp(),
303                                 lTypeMgr,
304                                 &lTmpNsCtx,
305                                 loc);
306     }
307     return true;
308   }
309 }
310 
311 bool
decodeObject(const store::Item_t & anObj,store::Item_t & aResult,JSONDecodeFromRoundtripIteratorState * aState) const312 JSONDecodeFromRoundtripIterator::decodeObject(
313   const store::Item_t& anObj,
314   store::Item_t& aResult,
315   JSONDecodeFromRoundtripIteratorState* aState) const
316 {
317   if (decodeXDM(anObj, aResult, aState))
318   {
319     return true;
320   }
321 
322   std::vector<store::Item_t> newNames;
323   std::vector<store::Item_t> newValues;
324   bool modified = false;
325 
326   store::Item_t key;
327   store::Item_t value;
328   store::Item_t newValue;
329   store::Iterator_t it = anObj->getObjectKeys();
330   it->open();
331   while (it->next(key))
332   {
333     newNames.push_back(key);
334     value = anObj->getObjectValue(key);
335     const bool gotNew = decodeItem(value, newValue, aState);
336     newValues.push_back(gotNew ? newValue : value);
337     modified = modified || gotNew;
338   }
339   it->close();
340   if (modified)
341   {
342     GENV_ITEMFACTORY->createJSONObject(aResult, newNames, newValues);
343     return true;
344   }
345   // nothing to change, aResult is not set, the caller needs to use anObj
346   return false;
347 }
348 
349 bool
decodeArray(const store::Item_t & anArray,store::Item_t & aResult,JSONDecodeFromRoundtripIteratorState * aState) const350 JSONDecodeFromRoundtripIterator::decodeArray(
351   const store::Item_t& anArray,
352   store::Item_t& aResult,
353   JSONDecodeFromRoundtripIteratorState* aState) const
354 {
355   std::vector<store::Item_t> newItems;
356   bool modified = false;
357 
358   store::Item_t item, newItem;
359   store::Iterator_t it = anArray->getArrayValues();
360   it->open();
361   while (it->next(item))
362   {
363     const bool gotNew = decodeItem(item, newItem, aState);
364     newItems.push_back(gotNew ? newItem : item);
365     modified = modified || gotNew;
366   }
367   it->close();
368   if (modified)
369   {
370     GENV_ITEMFACTORY->createJSONArray(aResult, newItems);
371     return true;
372   }
373   // nothing to change, aResult is not set, the caller needs to use anArray
374   return false;
375 }
376 
377 bool
decodeItem(const store::Item_t & anItem,store::Item_t & aResult,JSONDecodeFromRoundtripIteratorState * aState) const378 JSONDecodeFromRoundtripIterator::decodeItem(
379   const store::Item_t& anItem,
380   store::Item_t& aResult,
381   JSONDecodeFromRoundtripIteratorState* aState) const
382 {
383   if (anItem->isJSONObject())
384   {
385     return decodeObject(anItem, aResult, aState);
386   }
387   else if (anItem->isJSONArray())
388   {
389     return decodeArray(anItem, aResult, aState);
390   }
391   else
392   {
393     // nothing to change, aResult is not set, the caller needs to use anItem
394     return false;
395   }
396 }
397 
398 bool
nextImpl(store::Item_t & aResult,PlanState & aPlanState) const399 JSONDecodeFromRoundtripIterator::nextImpl(
400   store::Item_t& aResult,
401   PlanState& aPlanState) const
402 {
403   store::Item_t lInput;
404   store::Item_t lDecParams;
405 
406   JSONDecodeFromRoundtripIteratorState* lState;
407   DEFAULT_STACK_INIT(JSONDecodeFromRoundtripIteratorState, lState, aPlanState);
408 
409   // get decoding parameters
410   if (theChildren.size() == 2)
411   {
412     // the signature says that the second parameter has to be exactly one object
413     consumeNext(lDecParams, theChildren.at(1), aPlanState);
414     store::Item_t lPrefixKey;
415     zstring lPrefixNameStr = OPTIONS_KEY_PREFIX;
416     GENV_ITEMFACTORY->createString(lPrefixKey, lPrefixNameStr);
417     store::Item_t lPrefixValue = lDecParams->getObjectValue(lPrefixKey);
418     if (! lPrefixValue.isNull())
419     {
420       if (lPrefixValue->getTypeCode() != store::XS_STRING)
421       {
422         RAISE_ERROR(jerr::JNTY0023, loc,
423                     ERROR_PARAMS(lPrefixValue->getStringValue(),
424                                  OPTIONS_KEY_PREFIX,
425                                  "string"));
426       }
427       lPrefixValue->getStringValue2(lState->thePrefix);
428     }
429   }
430   else
431   {
432     lState->thePrefix = ENCODE_DECODE_DEFAULT_PREFIX;
433   }
434 
435   while (consumeNext(lInput, theChildren.at(0), aPlanState))
436   {
437     if (! decodeItem(lInput, aResult, lState))
438     {
439       aResult = lInput;
440     }
441     STACK_PUSH (true, lState);
442   }
443 
444   STACK_END(lState);
445 }
446 
447 
448 /*******************************************************************************
449   jn:encode-for-roundtrip($items as structured-item()*,
450                           $options as object()) as json-item()*
451 ********************************************************************************/
452 bool
encodeObject(const store::Item_t & anObj,store::Item_t & aResult,JSONEncodeForRoundtripIteratorState * aState) const453 JSONEncodeForRoundtripIterator::encodeObject(
454   const store::Item_t& anObj,
455   store::Item_t& aResult,
456   JSONEncodeForRoundtripIteratorState* aState) const
457 {
458   std::vector<store::Item_t> newNames;
459   std::vector<store::Item_t> newValues;
460   bool modified = false;
461 
462   store::Item_t key;
463   store::Item_t value;
464   store::Item_t newValue;
465   store::Iterator_t it = anObj->getObjectKeys();
466   it->open();
467   while (it->next(key))
468   {
469     newNames.push_back(key);
470     value = anObj->getObjectValue(key);
471     const bool gotNew = encodeItem(value, newValue, aState);
472     newValues.push_back(gotNew ? newValue : value);
473     modified = modified || gotNew;
474   }
475   it->close();
476   if (modified)
477   {
478     GENV_ITEMFACTORY->createJSONObject(aResult, newNames, newValues);
479     return true;
480   }
481   // nothing to change, aResult is not set, the caller needs to use anObj
482   return false;
483 }
484 
485 bool
encodeArray(const store::Item_t & anArray,store::Item_t & aResult,JSONEncodeForRoundtripIteratorState * aState) const486 JSONEncodeForRoundtripIterator::encodeArray(
487   const store::Item_t& anArray,
488   store::Item_t& aResult,
489   JSONEncodeForRoundtripIteratorState* aState) const
490 {
491   std::vector<store::Item_t> newItems;
492   bool modified = false;
493 
494   store::Item_t item, newItem;
495   store::Iterator_t it = anArray->getArrayValues();
496   it->open();
497   while (it->next(item))
498   {
499     const bool gotNew = encodeItem(item, newItem, aState);
500     newItems.push_back(gotNew ? newItem : item);
501     modified = modified || gotNew;
502   }
503   it->close();
504   if (modified)
505   {
506     GENV_ITEMFACTORY->createJSONArray(aResult, newItems);
507     return true;
508   }
509   // nothing to change, aResult is not set, the caller needs to use anArray
510   return false;
511 }
512 
513 bool
encodeAtomic(const store::Item_t & aValue,store::Item_t & aResult,JSONEncodeForRoundtripIteratorState * aState) const514 JSONEncodeForRoundtripIterator::encodeAtomic(
515   const store::Item_t& aValue,
516   store::Item_t& aResult,
517   JSONEncodeForRoundtripIteratorState* aState) const
518 {
519   store::SchemaTypeCode typeCode = aValue->getTypeCode();
520   switch (typeCode) {
521   case store::XS_DOUBLE:
522   case store::XS_FLOAT:
523     if (aValue->getBaseItem() == NULL
524         && ! aValue->isNaN() && ! aValue->isPosOrNegInf())
525     {
526       // nothing to change, aResult is not set, the caller needs to use aValue
527       return false;
528     }
529     break;
530   case store::XS_STRING:
531   case store::XS_INTEGER:
532   case store::XS_DECIMAL:
533   case store::XS_BOOLEAN:
534   case store::JS_NULL:
535     if (aValue->getBaseItem() == NULL)
536     {
537       // nothing to change, aResult is not set, the caller needs to use aValue
538       return false;
539     }
540     break;
541   default:
542     break;
543   }
544 
545   std::vector<store::Item_t> names(2);
546   std::vector<store::Item_t> values(2);
547 
548   {
549     const store::Item_t& typeName = aValue->getType();
550 
551     zstring typeKey = aState->thePrefix + TYPE_KEY;
552     const zstring ns = typeName->getNamespace();
553     const zstring local = typeName->getLocalName();
554     zstring typeValue = ns.compare(XS_URI)
555         ? "Q{" + ns + "}" + local : "xs:" + local;
556 
557     GENV_ITEMFACTORY->createString(names.at(0), typeKey);
558     GENV_ITEMFACTORY->createString(values.at(0), typeValue);
559   }
560 
561   {
562     zstring valueKey = aState->thePrefix + VALUE_KEY;
563     zstring valueValue;
564     if (typeCode == store::XS_QNAME)
565     {
566       // QNames are a special case, as the prefix should be maintained as well
567       // but it's not part of the EQName serialization
568       zstring prefixValue = aValue->getPrefix();
569       if (prefixValue.length() > 0)
570       {
571         zstring prefixKey = aState->thePrefix + NS_PREFIX_KEY;
572         store::Item_t lItem;
573         GENV_ITEMFACTORY->createString(lItem, prefixKey);
574         names.push_back(lItem);
575         GENV_ITEMFACTORY->createString(lItem, prefixValue);
576         values.push_back(lItem);
577       }
578 
579       const zstring ns = aValue->getNamespace();
580       const zstring local = aValue->getLocalName();
581       valueValue = ns.empty() ? local : "Q{" + ns + "}" + local;
582     }
583     else
584     {
585       aValue->getStringValue2(valueValue);
586     }
587     GENV_ITEMFACTORY->createString(names.at(1), valueKey);
588     GENV_ITEMFACTORY->createString(values.at(1), valueValue);
589   }
590 
591   GENV_ITEMFACTORY->createJSONObject(aResult, names, values);
592   return true;
593 }
594 
595 bool
encodeNode(const store::Item_t & aNode,store::Item_t & aResult,JSONEncodeForRoundtripIteratorState * aState) const596 JSONEncodeForRoundtripIterator::encodeNode(
597     const store::Item_t& aNode,
598     store::Item_t& aResult,
599     JSONEncodeForRoundtripIteratorState* aState) const
600 {
601   std::vector<store::Item_t> names(2);
602   std::vector<store::Item_t> values(2);
603 
604   {
605     zstring typeKey = aState->thePrefix + TYPE_KEY;
606     zstring typeValue = kind2str(aNode->getNodeKind());
607     GENV_ITEMFACTORY->createString(names.at(0), typeKey);
608     GENV_ITEMFACTORY->createString(values.at(0), typeValue);
609   }
610 
611   {
612     zstring valueKey = aState->thePrefix + VALUE_KEY;
613 
614     store::Iterator_t lItemIt = new ItemIterator(aNode);
615     zorba::serializer lSerializer(aState->theDiag);
616     // TODO what do we set, if nothing is passed?
617     lSerializer.setParameter("omit-xml-declaration", "yes");
618 
619     if (! aState->theSerParams.isNull())
620     {
621       FnSerializeIterator::setSerializationParams(
622           lSerializer,
623           aState->theSerParams,
624           theSctx,
625           loc);
626     }
627 
628     // and now serialize
629     std::auto_ptr<std::stringstream> lResultStream(new std::stringstream());
630     lItemIt->open();
631     lSerializer.serialize(lItemIt, *lResultStream.get());
632     lItemIt->close();
633 
634     GENV_ITEMFACTORY->createString(names.at(1), valueKey);
635     GENV_ITEMFACTORY->createStreamableString(
636         values.at(1), *lResultStream.release(),
637         FnSerializeIterator::streamReleaser, true);
638   }
639 
640   GENV_ITEMFACTORY->createJSONObject(aResult, names, values);
641   return true;
642 }
643 
644 bool
encodeItem(const store::Item_t & anItem,store::Item_t & aResult,JSONEncodeForRoundtripIteratorState * aState) const645 JSONEncodeForRoundtripIterator::encodeItem(
646   const store::Item_t& anItem,
647   store::Item_t& aResult,
648   JSONEncodeForRoundtripIteratorState* aState) const
649 {
650   if (anItem->isJSONObject())
651   {
652     return encodeObject(anItem, aResult, aState);
653   }
654   else if (anItem->isJSONArray())
655   {
656     return encodeArray(anItem, aResult, aState);
657   }
658   else if (anItem->isAtomic())
659   {
660     return encodeAtomic(anItem, aResult, aState);
661   }
662   else
663   {
664     return encodeNode(anItem, aResult, aState);
665   }
666 }
667 
668 bool
nextImpl(store::Item_t & aResult,PlanState & aPlanState) const669 JSONEncodeForRoundtripIterator::nextImpl(
670   store::Item_t& aResult,
671   PlanState& aPlanState) const
672 {
673   store::Item_t lInput;
674 
675   JSONEncodeForRoundtripIteratorState* lState;
676   DEFAULT_STACK_INIT(JSONEncodeForRoundtripIteratorState, lState, aPlanState);
677 
678   lState->thePrefix = ENCODE_DECODE_DEFAULT_PREFIX;
679   lState->theDiag = aPlanState.theCompilerCB->theXQueryDiagnostics;
680 
681   // get encoding parameters
682   if (theChildren.size() == 2)
683   {
684     // the signature says that the second parameter has to be exactly one object
685     store::Item_t lEncParams;
686     consumeNext(lEncParams, theChildren.at(1), aPlanState);
687     store::Item_t lPrefixKey;
688     zstring lPrefixNameStr = OPTIONS_KEY_PREFIX;
689     GENV_ITEMFACTORY->createString(lPrefixKey, lPrefixNameStr);
690     store::Item_t lPrefixValue = lEncParams->getObjectValue(lPrefixKey);
691     if (! lPrefixValue.isNull())
692     {
693       if (lPrefixValue->getTypeCode() != store::XS_STRING)
694       {
695         RAISE_ERROR(jerr::JNTY0023, loc,
696                     ERROR_PARAMS(lPrefixValue->getStringValue(),
697                                  OPTIONS_KEY_PREFIX,
698                                  "string"));
699       }
700       lPrefixValue->getStringValue2(lState->thePrefix);
701     }
702 
703     store::Item_t lSerParamKey;
704     zstring lSerParamNameStr = OPTIONS_KEY_SER_PARAMS;
705     GENV_ITEMFACTORY->createString(lSerParamKey, lSerParamNameStr);
706     store::Item_t lSerParamValue = lEncParams->getObjectValue(lSerParamKey);
707     if (! lSerParamValue.isNull())
708     {
709       if (! lSerParamValue->isNode()
710           || lSerParamValue->getNodeKind() != store::StoreConsts::elementNode)
711       {
712         RAISE_ERROR(jerr::JNTY0023, loc,
713                     ERROR_PARAMS(lSerParamValue->getStringValue(),
714                                  OPTIONS_KEY_SER_PARAMS,
715                                  ZED(ElementNode)));
716       }
717       lState->theSerParams = lSerParamValue;
718     }
719   }
720 
721   while(consumeNext(lInput, theChildren.at(0), aPlanState))
722   {
723     if (! encodeItem(lInput, aResult, lState))
724     {
725       aResult = lInput;
726     }
727     STACK_PUSH (true, lState);
728   }
729   STACK_END(lState);
730 }
731 
732 
733 /*******************************************************************************
734 
735 ********************************************************************************/
736 void
init(PlanState & aState)737 JSONParseIteratorState::init(PlanState& aState)
738 {
739   PlanIteratorState::init(aState);
740   theAllowMultiple = true; // default
741   theInputStream = 0;
742   theGotOne = false;
743 }
744 
745 void
reset(PlanState & aState)746 JSONParseIteratorState::reset(PlanState& aState)
747 {
748   PlanIteratorState::reset(aState);
749   if (theInput == NULL && theInputStream)
750   {
751     delete theInputStream;
752   }
753 }
754 
~JSONParseIteratorState()755 JSONParseIteratorState::~JSONParseIteratorState()
756 {
757   if (theInput == NULL && theInputStream)
758   {
759     delete theInputStream;
760   }
761 }
762 
763 void
processOptions(const store::Item_t & aOptions,bool & aAllowMultiple) const764 JSONParseIterator::processOptions(
765     const store::Item_t& aOptions,
766     bool& aAllowMultiple) const
767 {
768   store::Item_t lOptionName, lOptionValue;
769 
770   zstring s("jsoniq-multiple-top-level-items");
771   GENV_ITEMFACTORY->createString(lOptionName, s);
772   lOptionValue = aOptions->getObjectValue(lOptionName);
773 
774   if (lOptionValue != NULL)
775   {
776     store::SchemaTypeCode lType = lOptionValue->getTypeCode();
777     if (!TypeOps::is_subtype(lType, store::XS_BOOLEAN))
778     {
779       const TypeManager* tm = theSctx->get_typemanager();
780       xqtref_t lType = tm->create_value_type(lOptionValue, loc);
781       RAISE_ERROR(jerr::JNTY0020, loc,
782       ERROR_PARAMS(lType->toSchemaString(), s, "xs:boolean"));
783     }
784     aAllowMultiple = lOptionValue->getBooleanValue();
785   }
786 }
787 
788 bool
nextImpl(store::Item_t & result,PlanState & planState) const789 JSONParseIterator::nextImpl(
790   store::Item_t& result,
791   PlanState& planState) const
792 {
793   store::Item_t lInput;
794 
795   JSONParseIteratorState* state;
796   DEFAULT_STACK_INIT(JSONParseIteratorState, state, planState);
797 
798   if (consumeNext(lInput, theChildren[0].getp(), planState))
799   {
800     if (theChildren.size() == 2)
801     {
802       store::Item_t lOptions;
803       consumeNext(lOptions, theChildren[1].getp(), planState);
804       processOptions(lOptions, state->theAllowMultiple);
805     }
806 
807     if (lInput->isStreamable())
808     {
809       state->theInput = lInput;
810       state->theInputStream = &lInput->getStream();
811     }
812     else
813     {
814       // will be deleted in the state
815       state->theInputStream = new std::stringstream(
816           lInput->getStringValue().c_str());
817     }
818 
819     while (true)
820     {
821       try
822       {
823         // streamable string or non-literal string
824         if (state->theInput != NULL || theRelativeLocation == QueryLoc::null)
825         {
826           result = GENV_STORE.parseJSON(*state->theInputStream, 0);
827         }
828         else
829         {
830           // pass the query location of the StringLiteral to the JSON
831           // parser such that it can give better error locations.
832           zorba::internal::diagnostic::location lLoc;
833           lLoc = ERROR_LOC(theRelativeLocation);
834           result = GENV_STORE.parseJSON(*state->theInputStream, &lLoc);
835         }
836       }
837       catch (zorba::XQueryException& e)
838       {
839         // rethrow with JNDY0021
840         XQueryException xq = XQUERY_EXCEPTION(
841             jerr::JNDY0021,
842             ERROR_PARAMS(e.what()),
843             ERROR_LOC(loc));
844 
845         // use location of e in case of literal string
846         if (!(theRelativeLocation == QueryLoc::null)) set_source(xq, e);
847         throw xq;
848       }
849 
850       if (result != NULL)
851       {
852         if (!state->theAllowMultiple && state->theGotOne)
853         {
854           RAISE_ERROR(jerr::JNDY0021, loc,
855           ERROR_PARAMS(ZED(JSON_UNEXPECTED_EXTRA_CONTENT)));
856         }
857         state->theGotOne = true;
858         STACK_PUSH(true, state);
859         continue;
860       }
861       else
862       {
863         break;
864       }
865     }
866   }
867 
868   STACK_END(state);
869 }
870 
871 
872 /*******************************************************************************
873   json:names($o as object()) as xs:string*
874 ********************************************************************************/
875 bool
nextImpl(store::Item_t & result,PlanState & planState) const876 JSONObjectNamesIterator::nextImpl(
877   store::Item_t& result,
878   PlanState& planState) const
879 {
880   store::Item_t input;
881   store::Item_t key;
882 
883   JSONObjectNamesIteratorState* state;
884   DEFAULT_STACK_INIT(JSONObjectNamesIteratorState, state, planState);
885 
886   consumeNext(input, theChild.getp(), planState);
887 
888   state->theNames = input->getObjectKeys();
889   state->theNames->open();
890 
891   while (state->theNames->next(key))
892   {
893     result = key;
894     STACK_PUSH (true, state);
895   }
896   state->theNames = NULL;
897 
898   STACK_END(state);
899 }
900 
901 
902 /*******************************************************************************
903   json:value($o as object(), $name as xs:string) as item()?
904 ********************************************************************************/
905 bool
nextImpl(store::Item_t & result,PlanState & planState) const906 JSONObjectValueIterator::nextImpl(
907   store::Item_t& result,
908   PlanState& planState) const
909 {
910   store::Item_t lInput;
911   store::Item_t lName;
912 
913   PlanIteratorState* state;
914   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
915 
916   consumeNext(lInput, theChild0.getp(), planState);
917   consumeNext(lName, theChild1.getp(), planState);
918 
919   result = lInput->getObjectValue(lName);
920 
921   STACK_PUSH(result != 0, state);
922 
923   STACK_END(state);
924 }
925 
926 
927 /*******************************************************************************
928   json:project($o as object(), $names as xs:string*) as object()
929 ********************************************************************************/
930 bool
nextImpl(store::Item_t & result,PlanState & planState) const931 JSONObjectProjectIterator::nextImpl(
932   store::Item_t& result,
933   PlanState& planState) const
934 {
935   store::Item_t obj;
936   store::Item_t key;
937   store::Iterator_t keysIte;
938   store::Item_t value;
939   store::Item_t name;
940   std::vector<store::Item_t> names;
941   csize numNames = 0;
942   store::CopyMode copymode;
943   std::vector<store::Item_t> newNames;
944   std::vector<store::Item_t> newValues;
945   csize i;
946 
947   PlanIteratorState* state;
948   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
949 
950   consumeNext(obj, theChild0.getp(), planState);
951 
952   while (consumeNext(name, theChild1.getp(), planState))
953   {
954     ++numNames;
955     names.resize(numNames);
956     names[numNames - 1].transfer(name);
957   }
958 
959   keysIte = obj->getObjectKeys();
960   keysIte->open();
961 
962   while (keysIte->next(key))
963   {
964     for (i = 0; i < numNames; ++i)
965     {
966       if (names[i]->getStringValue() == key->getStringValue())
967         break;
968     }
969 
970     if (i < numNames)
971     {
972       value = obj->getObjectValue(key);
973 
974       if (value->isNode() || value->isJSONItem())
975         value = value->copy(NULL, copymode);
976 
977       newValues.push_back(value);
978       newNames.push_back(key);
979     }
980   }
981 
982   keysIte->close();
983 
984   GENV_ITEMFACTORY->createJSONObject(result, newNames, newValues);
985 
986   STACK_PUSH(true, state);
987   STACK_END(state);
988 }
989 
990 
991 /*******************************************************************************
992   j:size($i as array()) as xs:integer*
993 ********************************************************************************/
994 bool
nextImpl(store::Item_t & result,PlanState & planState) const995 JSONArraySizeIterator::nextImpl(
996   store::Item_t& result,
997   PlanState& planState) const
998 {
999   store::Item_t lJSONItem;
1000   xs_integer lSize;
1001 
1002   PlanIteratorState* state;
1003   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1004 
1005   consumeNext(lJSONItem, theChild.getp(), planState);
1006 
1007   lSize = lJSONItem->getArraySize();
1008 
1009   STACK_PUSH(GENV_ITEMFACTORY->createInteger(result, lSize), state);
1010 
1011   STACK_END(state);
1012 }
1013 
1014 
1015 /*******************************************************************************
1016   json:member($a as array(), $pos as xs:integer) as item()?
1017 ********************************************************************************/
1018 bool
nextImpl(store::Item_t & result,PlanState & planState) const1019 JSONArrayMemberIterator::nextImpl(
1020   store::Item_t& result,
1021   PlanState& planState) const
1022 {
1023   store::Item_t lInput;
1024   store::Item_t lPosition;
1025 
1026   PlanIteratorState* state;
1027   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1028 
1029   consumeNext(lInput, theChild0.getp(), planState);
1030   consumeNext(lPosition, theChild1.getp(), planState);
1031 
1032   result = lInput->getArrayValue(lPosition->getIntegerValue());
1033 
1034   STACK_PUSH(result != 0, state);
1035 
1036   STACK_END(state);
1037 }
1038 
1039 
1040 /*******************************************************************************
1041   json:members($a as array()) as item()*
1042 ********************************************************************************/
1043 bool
nextImpl(store::Item_t & result,PlanState & planState) const1044 JSONArrayMembersIterator::nextImpl(
1045   store::Item_t& result,
1046   PlanState& planState) const
1047 {
1048   store::Item_t array;
1049 
1050   JSONArrayMembersIteratorState* state;
1051   DEFAULT_STACK_INIT(JSONArrayMembersIteratorState, state, planState);
1052 
1053   consumeNext(array, theChild.getp(), planState);
1054 
1055   state->theMembers = array->getArrayValues();
1056   state->theMembers->open();
1057   while (state->theMembers->next(result))
1058   {
1059     STACK_PUSH(true, state);
1060   }
1061   state->theMembers->close();
1062 
1063   STACK_END(state);
1064 }
1065 
1066 
1067 /*******************************************************************************
1068   json:flatten($a as array()) as item()*
1069 
1070   op-zorba:flatten-internal($a as item()*) as item()*
1071 ********************************************************************************/
reset(PlanState & planState)1072 void JSONArrayFlattenIteratorState::reset(PlanState& planState)
1073 {
1074   PlanIteratorState::reset(planState);
1075   while (!theStack.empty())
1076   {
1077     theStack.pop();
1078   }
1079 }
1080 
1081 
1082 bool
nextImpl(store::Item_t & result,PlanState & planState) const1083 JSONArrayFlattenIterator::nextImpl(
1084   store::Item_t& result,
1085   PlanState& planState) const
1086 {
1087   store::Item_t item;
1088   bool lFoundArray = false;
1089 
1090   JSONArrayFlattenIteratorState* state;
1091   DEFAULT_STACK_INIT(JSONArrayFlattenIteratorState, state, planState);
1092 
1093   consumeNext(item, theChild.getp(), planState);
1094 
1095   assert(item->isJSONArray());
1096 
1097   state->theStack.push(item->getArrayValues());
1098   state->theStack.top()->open();
1099 
1100   while (!state->theStack.empty())
1101   {
1102     while (state->theStack.top()->next(result))
1103     {
1104       if (result->isJSONArray())
1105       {
1106         state->theStack.push(result->getArrayValues());
1107         state->theStack.top()->open();
1108         lFoundArray = true;
1109         break;
1110       }
1111 
1112       STACK_PUSH(true, state);
1113     }
1114 
1115     if (lFoundArray)
1116     {
1117       lFoundArray = false;
1118       continue;
1119     }
1120 
1121     state->theStack.top()->close();
1122     state->theStack.pop();
1123   }
1124 
1125   STACK_END(state);
1126 }
1127 
1128 
1129 /*******************************************************************************
1130   op_zorba:json-item-accessor($i as json-item(), $s as xs:anyAtomic) as item()?
1131 ********************************************************************************/
1132 bool
nextImpl(store::Item_t & result,PlanState & planState) const1133 JSONItemAccessorIterator::nextImpl(
1134   store::Item_t& result,
1135   PlanState& planState) const
1136 {
1137   store::Item_t input;
1138   store::Item_t selector;
1139 
1140   const TypeManager* tm = theSctx->get_typemanager();
1141 
1142   PlanIteratorState* state;
1143   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1144 
1145   consumeNext(input, theChild0.getp(), planState);
1146   consumeNext(selector, theChild1.getp(), planState);
1147 
1148   if (input->isJSONArray())
1149   {
1150     store::SchemaTypeCode type = selector->getTypeCode();
1151 
1152     if (!TypeOps::is_subtype(type, store::XS_INTEGER))
1153     {
1154       xqtref_t type = tm->create_value_type(selector, loc);
1155 
1156       RAISE_ERROR(err::XPTY0004, loc,
1157       ERROR_PARAMS(ZED(XPTY0004_NoTypePromotion_23),
1158                    type->toSchemaString(),
1159                    GENV_TYPESYSTEM.INTEGER_TYPE_ONE->toSchemaString()));
1160     }
1161 
1162     result = input->getArrayValue(selector->getIntegerValue());
1163   }
1164   else if (input->isJSONObject())
1165   {
1166     store::SchemaTypeCode type = selector->getTypeCode();
1167 
1168     if (!TypeOps::is_subtype(type, store::XS_STRING) &&
1169         !TypeOps::is_subtype(type, store::XS_UNTYPED_ATOMIC) &&
1170         !TypeOps::is_subtype(type, store::XS_ANY_URI))
1171     {
1172       xqtref_t type = tm->create_value_type(selector, loc);
1173 
1174       RAISE_ERROR(err::XPTY0004, loc,
1175       ERROR_PARAMS(ZED(XPTY0004_NoTypePromotion_23),
1176                    type->toSchemaString(),
1177                    GENV_TYPESYSTEM.STRING_TYPE_ONE->toSchemaString()));
1178     }
1179 
1180     result = input->getObjectValue(selector);
1181   }
1182   else
1183   {
1184     ZORBA_ASSERT(false);
1185   }
1186 
1187   STACK_PUSH(result != 0, state);
1188 
1189   STACK_END(state);
1190 }
1191 
1192 
1193 /*******************************************************************************
1194   jn:null() as jn:null
1195 ********************************************************************************/
1196 bool
nextImpl(store::Item_t & result,PlanState & planState) const1197 JSONNullIterator::nextImpl(
1198   store::Item_t& result,
1199   PlanState& planState) const
1200 {
1201   PlanIteratorState* state;
1202   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1203 
1204   STACK_PUSH(GENV_ITEMFACTORY->createJSONNull(result), state);
1205 
1206   STACK_END(state);
1207 }
1208 
1209 
1210 /*******************************************************************************
1211   jn:is-null(xs:anyAtomicType) as xs:boolean
1212 ********************************************************************************/
1213 bool
nextImpl(store::Item_t & result,PlanState & planState) const1214 JSONIsNullIterator::nextImpl(
1215   store::Item_t& result,
1216   PlanState& planState) const
1217 {
1218   PlanIteratorState* state;
1219   store::Item_t lItem;
1220   bool lIsNull;
1221 
1222   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1223 
1224   consumeNext(lItem, theChild.getp(), planState);
1225 
1226   lIsNull = (lItem->getTypeCode() == store::JS_NULL);
1227 
1228   STACK_PUSH(GENV_ITEMFACTORY->createBoolean(result, lIsNull), state);
1229 
1230   STACK_END(state);
1231 }
1232 
1233 
1234 /*******************************************************************************
1235   updating function op-zorba:object-insert(
1236       $o as object(),
1237       $c as object())
1238 ********************************************************************************/
nextImpl(store::Item_t & result,PlanState & planState) const1239 bool JSONObjectInsertIterator::nextImpl(
1240   store::Item_t& result,
1241   PlanState& planState) const
1242 {
1243   store::Item_t target;
1244   store::Item_t content;
1245   store::PUL_t pul;
1246   store::CopyMode copymode;
1247   PlanIteratorState* state;
1248 
1249   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1250 
1251   consumeNext(target, theChildren[0].getp(), planState);
1252 
1253   consumeNext(content, theChildren[1].getp(), planState);
1254 
1255   copymode.set(true,
1256                theSctx->construction_mode() == StaticContextConsts::cons_preserve,
1257                theSctx->preserve_ns(),
1258                theSctx->inherit_ns());
1259 
1260   if (content->isNode() || content->isJSONItem())
1261   {
1262     content = content->copy(NULL, copymode);
1263   }
1264 
1265   pul = GENV_ITEMFACTORY->createPendingUpdateList();
1266 
1267   pul->addJSONObjectInsert(&loc, target, content);
1268 
1269   result.transfer(pul);
1270 
1271   STACK_PUSH(true, state);
1272 
1273   STACK_END(state);
1274 }
1275 
1276 
1277 /*******************************************************************************
1278   updating function op-zorba:array-insert(
1279       $o as array(),
1280       $pos as xs:integer,
1281       $values as item()*,
1282 ********************************************************************************/
nextImpl(store::Item_t & result,PlanState & planState) const1283 bool JSONArrayInsertIterator::nextImpl(
1284   store::Item_t& result,
1285   PlanState& planState) const
1286 {
1287   store::Item_t array;
1288   store::Item_t member;
1289   store::Item_t pos;
1290   std::vector<store::Item_t> members;
1291   store::PUL_t pul;
1292   store::CopyMode copymode;
1293 
1294   PlanIteratorState* state;
1295   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1296 
1297   consumeNext(array, theChildren[0].getp(), planState);
1298   consumeNext(pos, theChildren[1].getp(), planState);
1299 
1300   copymode.set(true,
1301                theSctx->construction_mode() == StaticContextConsts::cons_preserve,
1302                theSctx->preserve_ns(),
1303                theSctx->inherit_ns());
1304 
1305   while (consumeNext(member, theChildren[2].getp(), planState))
1306   {
1307     if (member->isNode() || member->isJSONItem())
1308     {
1309       member = member->copy(NULL, copymode);
1310     }
1311 
1312     members.resize(members.size() + 1);
1313     members.back().transfer(member);
1314   }
1315 
1316   pul = GENV_ITEMFACTORY->createPendingUpdateList();
1317 
1318   pul->addJSONArrayInsert(&loc, array, pos, members);
1319 
1320   result.transfer(pul);
1321 
1322   STACK_PUSH(true, state);
1323 
1324   STACK_END (state);
1325 }
1326 
1327 
1328 /*******************************************************************************
1329   updating function op-zorba:array-append(
1330       $o as array(),
1331       $values as item()*)
1332 ********************************************************************************/
nextImpl(store::Item_t & result,PlanState & planState) const1333 bool JSONArrayAppendIterator::nextImpl(
1334   store::Item_t& result,
1335   PlanState& planState) const
1336 {
1337   store::Item_t array;
1338   store::Item_t member;
1339   std::vector<store::Item_t> members;
1340   store::PUL_t pul;
1341   store::CopyMode copymode;
1342 
1343   PlanIteratorState* state;
1344   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1345 
1346   consumeNext(array, theChildren[0].getp(), planState);
1347 
1348   copymode.set(true,
1349                theSctx->construction_mode() == StaticContextConsts::cons_preserve,
1350                theSctx->preserve_ns(),
1351                theSctx->inherit_ns());
1352 
1353   while (consumeNext(member, theChildren[1].getp(), planState))
1354   {
1355     if (member->isNode() || member->isJSONItem())
1356     {
1357       member = member->copy(NULL, copymode);
1358     }
1359 
1360     members.resize(members.size() + 1);
1361     members.back().transfer(member);
1362   }
1363 
1364   pul = GENV_ITEMFACTORY->createPendingUpdateList();
1365 
1366   pul->addJSONArrayAppend(&loc, array, members);
1367 
1368   result.transfer(pul);
1369 
1370   STACK_PUSH(true, state);
1371 
1372   STACK_END (state);
1373 }
1374 
1375 
1376 /*******************************************************************************
1377   updating function op-zorba:json-delete(
1378       $target as json-item(),
1379       $selector as xs:anyAtomicType)
1380 ********************************************************************************/
nextImpl(store::Item_t & result,PlanState & planState) const1381 bool JSONDeleteIterator::nextImpl(
1382     store::Item_t& result,
1383     PlanState& planState) const
1384 {
1385   store::Item_t target;
1386   store::Item_t selector;
1387   store::PUL_t pul;
1388 
1389   const TypeManager* tm = theSctx->get_typemanager();
1390 
1391   PlanIteratorState* state;
1392   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1393 
1394   consumeNext(target, theChildren[0].getp(), planState);
1395   consumeNext(selector, theChildren[1].getp(), planState);
1396 
1397   pul = GENV_ITEMFACTORY->createPendingUpdateList();
1398 
1399   if (target->isJSONObject())
1400   {
1401     store::SchemaTypeCode type = selector->getTypeCode();
1402 
1403     if (type != store::XS_STRING && type != store::XS_ANY_URI)
1404     {
1405       xqtref_t type = tm->create_value_type(selector, loc);
1406 
1407       RAISE_ERROR(jerr::JNUP0007, loc,
1408       ERROR_PARAMS(ZED(JNUP0007_Object), type->toSchemaString()));
1409     }
1410 
1411     pul->addJSONObjectDelete(&loc, target, selector);
1412   }
1413   else if (target->isJSONArray())
1414   {
1415     store::SchemaTypeCode type = selector->getTypeCode();
1416 
1417     if (type != store::XS_INTEGER)
1418     {
1419       xqtref_t type = tm->create_value_type(selector, loc);
1420 
1421       RAISE_ERROR(jerr::JNUP0007, loc,
1422       ERROR_PARAMS(ZED(JNUP0007_Array), type->toSchemaString()));
1423     }
1424 
1425     pul->addJSONArrayDelete(&loc, target, selector);
1426   }
1427 
1428   result.transfer(pul);
1429 
1430   STACK_PUSH(true, state);
1431 
1432   STACK_END (state);
1433 }
1434 
1435 
1436 /*******************************************************************************
1437   updating function op-zorba:replace-value(
1438       $target as json-item(),
1439       $selector as xs:anyAtomicType,
1440       $newValue as item())
1441 ********************************************************************************/
JSONReplaceValueIterator(static_context * sctx,const QueryLoc & loc,std::vector<PlanIter_t> & args,bool copyInput)1442 JSONReplaceValueIterator::JSONReplaceValueIterator(
1443     static_context* sctx,
1444     const QueryLoc& loc,
1445     std::vector<PlanIter_t>& args,
1446     bool copyInput)
1447   :
1448   NaryBaseIterator<JSONReplaceValueIterator, PlanIteratorState>(sctx, loc, args)
1449 {
1450   if (theChildren[2]->isConstructor())
1451   {
1452     theCopyInput = false;
1453   }
1454   else
1455   {
1456     theCopyInput = copyInput;
1457   }
1458 }
1459 
1460 
nextImpl(store::Item_t & result,PlanState & planState) const1461 bool JSONReplaceValueIterator::nextImpl(
1462   store::Item_t& result,
1463   PlanState& planState) const
1464 {
1465   store::Item_t target;
1466   store::Item_t selector;
1467   store::Item_t newValue;
1468   store::PUL_t pul;
1469   store::CopyMode copymode;
1470 
1471   const TypeManager* tm = theSctx->get_typemanager();
1472 
1473   PlanIteratorState* state;
1474   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1475 
1476   consumeNext(target, theChildren[0].getp(), planState);
1477   consumeNext(selector, theChildren[1].getp(), planState);
1478   consumeNext(newValue, theChildren[2].getp(), planState);
1479 
1480   if (theCopyInput && (newValue->isNode() || newValue->isJSONItem()))
1481   {
1482     copymode.set(true,
1483                  theSctx->construction_mode() == StaticContextConsts::cons_preserve,
1484                  theSctx->preserve_ns(),
1485                  theSctx->inherit_ns());
1486 
1487     newValue = newValue->copy(NULL, copymode);
1488   }
1489 
1490   pul = GENV_ITEMFACTORY->createPendingUpdateList();
1491 
1492   if (target->isJSONObject())
1493   {
1494     store::SchemaTypeCode type = selector->getTypeCode();
1495 
1496     if (type != store::XS_STRING && type != store::XS_ANY_URI)
1497     {
1498       xqtref_t type = tm->create_value_type(selector, loc);
1499 
1500       RAISE_ERROR(jerr::JNUP0007, loc,
1501       ERROR_PARAMS(ZED(JNUP0007_Object), type->toSchemaString()));
1502     }
1503 
1504     pul->addJSONObjectReplaceValue(&loc, target, selector, newValue);
1505   }
1506   else if (target->isJSONArray())
1507   {
1508     store::SchemaTypeCode type = selector->getTypeCode();
1509 
1510     if (type != store::XS_INTEGER)
1511     {
1512       xqtref_t type = tm->create_value_type(selector, loc);
1513 
1514       RAISE_ERROR(jerr::JNUP0007, loc,
1515       ERROR_PARAMS(ZED(JNUP0007_Array), type->toSchemaString()));
1516     }
1517 
1518     pul->addJSONArrayReplaceValue(&loc, target, selector, newValue);
1519   }
1520 
1521   result.transfer(pul);
1522 
1523   STACK_PUSH(true, state);
1524 
1525   STACK_END(state);
1526 }
1527 
1528 
1529 /*******************************************************************************
1530   updating function op-zorba:object-rename(
1531       $o as object(),
1532       $name as xs:string,
1533       $newName as xs:string)
1534 ********************************************************************************/
nextImpl(store::Item_t & result,PlanState & planState) const1535 bool JSONRenameIterator::nextImpl(
1536   store::Item_t& result,
1537   PlanState& planState) const
1538 {
1539   store::Item_t target;
1540   store::Item_t name;
1541   store::Item_t newName;
1542   store::PUL_t pul;
1543 
1544   PlanIteratorState* state;
1545   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1546 
1547   consumeNext(target, theChildren[0].getp(), planState);
1548   consumeNext(name, theChildren[1].getp(), planState);
1549   consumeNext(newName, theChildren[2].getp(), planState);
1550 
1551   pul = GENV_ITEMFACTORY->createPendingUpdateList();
1552 
1553   pul->addJSONObjectRename(&loc, target, name, newName);
1554 
1555   result.transfer(pul);
1556 
1557   STACK_PUSH(true, state);
1558 
1559   STACK_END(state);
1560 }
1561 
1562 
1563 /*******************************************************************************
1564 
1565 ********************************************************************************/
nextImpl(store::Item_t & result,PlanState & planState) const1566 bool JSONBoxIterator::nextImpl(
1567   store::Item_t& result,
1568   PlanState& planState) const
1569 {
1570   store::Item_t value1;
1571   store::Item_t value2;
1572   store::Item_t value;
1573 
1574   PlanIteratorState* state;
1575   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1576 
1577   if (!consumeNext(value1, theChild, planState))
1578   {
1579     GENV_STORE.getItemFactory()->createJSONNull(result);
1580   }
1581   else if (!consumeNext(value2, theChild, planState))
1582   {
1583     result.transfer(value1);
1584   }
1585   else
1586   {
1587     store::CopyMode copymode;
1588     copymode.set(false, true, true, true);
1589 
1590     store::Iterator_t wrapper = new PlanIteratorWrapper(theChild, planState);
1591 
1592     GENV_STORE.getItemFactory()->
1593     createJSONArray(result, value1, value2, wrapper, copymode);
1594   }
1595 
1596   STACK_PUSH(true, state);
1597   STACK_END(state);
1598 }
1599 
1600 
1601 } /* namespace zorba */
1602 /* vim:set et sw=2 ts=2: */
1603 
1604 #endif /* ZORBA_WITH_JSON */
1605