Merge lp:~zorba-coders/zorba/xml-in-json-indices into lp:zorba

Proposed by Ghislain Fourny on 2012-09-03
Status: Merged
Approved by: Paul J. Lucas on 2013-02-21
Approved revision: 11065
Merged at revision: 11247
Proposed branch: lp:~zorba-coders/zorba/xml-in-json-indices
Merge into: lp:zorba
Diff against target: 4187 lines (+1673/-1025)
37 files modified
src/runtime/collections/collections_impl.cpp (+2/-2)
src/runtime/json/json_constructors.cpp (+1/-1)
src/runtime/json/jsoniq_functions_impl.cpp (+5/-5)
src/store/api/item.h (+44/-29)
src/store/naive/CMakeLists.txt (+25/-23)
src/store/naive/collection.cpp (+25/-16)
src/store/naive/collection.h (+23/-37)
src/store/naive/collection_tree_info.h (+194/-0)
src/store/naive/item.cpp (+1/-1)
src/store/naive/json_items.cpp (+163/-170)
src/store/naive/json_items.h (+46/-92)
src/store/naive/loader_dtd.cpp (+2/-3)
src/store/naive/loader_fast.cpp (+2/-1)
src/store/naive/node_items.cpp (+121/-50)
src/store/naive/node_items.h (+121/-76)
src/store/naive/pul_primitives.cpp (+6/-16)
src/store/naive/simple_collection.cpp (+322/-326)
src/store/naive/simple_collection.h (+60/-25)
src/store/naive/simple_collection_set.h (+9/-14)
src/store/naive/simple_item_factory.cpp (+1/-1)
src/store/naive/simple_pul.cpp (+44/-91)
src/store/naive/simple_store.cpp (+14/-10)
src/store/naive/store.cpp (+22/-19)
src/store/naive/store_defs.h (+18/-16)
src/store/naive/structured_item.cpp (+144/-0)
src/store/naive/structured_item.h (+93/-0)
src/types/typeops.cpp (+1/-1)
test/rbkt/ExpQueryResults/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point-maintenance.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/jsoniq/collection-and-index/foaf-json-xml-update-index-point.xml.res (+1/-0)
test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point-maintenance.spec (+1/-0)
test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point-maintenance.xq (+36/-0)
test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point.spec (+1/-0)
test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point.xq (+15/-0)
test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-update-index-point.spec (+1/-0)
test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-update-index-point.xq (+25/-0)
test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf_module-with-index-and-xml.xqlib (+82/-0)
To merge this branch: bzr merge lp:~zorba-coders/zorba/xml-in-json-indices
Reviewer Review Type Date Requested Status
Paul J. Lucas Approve on 2013-02-21
Till Westmann 2012-09-03 Approve on 2013-02-15
Matthias Brantner 2012-09-04 Approve on 2013-02-14
Markos Zaharioudakis 2012-11-10 Approve on 2013-02-07
Review via email: mp+122548@code.launchpad.net

Commit message

1. Introducing StructuredItem interface and CollectionTreeInfo class to manage interactions between trees (of JSON and/or XML nodes) and collections.
2. Extending the use of colleciotn-relative tree positions to JSON trees.
3. Fixing index maintenance for XML embedded in JSON.

Description of the change

1. Introducing StructuredItem interface and CollectionTreeInfo class to manage interactions between trees (of JSON and/or XML nodes) and collections.
2. Extending the use of colleciotn-relative tree positions to JSON trees.
3. Fixing index maintenance for XML embedded in JSON.

To post a comment you must log in.
Zorba Build Bot (zorba-buildbot) wrote :

The attempt to merge lp:~zorba-coders/zorba/xml-in-json-indices into lp:zorba failed. Below is the output from the failed tests.

CMake Error at /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake:274 (message):
  Validation queue job xml-in-json-indices-2012-09-03T16-19-54.674Z is
  finished. The final status was:

  1 tests did not succeed - changes not commited.

Error in read script: /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake

Zorba Build Bot (zorba-buildbot) wrote :

The attempt to merge lp:~zorba-coders/zorba/xml-in-json-indices into lp:zorba failed. Below is the output from the failed tests.

CMake Error at /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake:274 (message):
  Validation queue job xml-in-json-indices-2012-09-04T14-36-58.242Z is
  finished. The final status was:

  No tests were run - build or configure step must have failed.

  Not commiting changes.

Error in read script: /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake

Zorba Build Bot (zorba-buildbot) wrote :

The attempt to merge lp:~zorba-coders/zorba/xml-in-json-indices into lp:zorba failed. Below is the output from the failed tests.

CMake Error at /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake:274 (message):
  Validation queue job xml-in-json-indices-2012-09-04T16-08-03.962Z is
  finished. The final status was:

  No tests were run - build or configure step must have failed.

  Not commiting changes.

Error in read script: /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake

Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job xml-in-json-indices-2012-09-04T16-15-05.617Z is finished. The final status was:

All tests succeeded!

Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 2 Pending.

Till Westmann (tillw) wrote :

Seems to work fine :)

There are some minor things that I've fixed myself. Among them is a new test. However, I actually intended this test to do something else that it does now. The intention was to replace the string value of the "name" pair with and XDM value and to verify that the index will indeed be updated. However having a string as the value leads to a type error, as the key expression of the index cannot be evaluated anymore … so I replaced 2 "wrong" pairs with one "right" pair instead, which is close but not quite there …

I also found some other stuff that I would like to keep open for discussion:

The build fails if ZORBA_WITH_JSON is turned off . More generally it seems that we are giving up on using ZORBA_WITH_JSON to turn JSONiq off. Is that intended (agreed on)?

Some comments in the StructuredItem class would help (e.g. the semantics of getStructuredItemRefCount is not immediately obvious).
Should we have zorba::store::Item::isStructured()?

There should be a template function for SimpleJSONObject::setTree and SimpleJSONArray::setTree and for SimpleJSONObject::isInSubTree and SimpleJSONArray::isInSubTree (and possibly others).

It would be nice if there was no additional member needed for XmlTree::theStructuredItemRoot (not sure how to do that though ..).

review: Needs Fixing
Ghislain Fourny (gislenius) wrote :

Hi Till,

Thanks for your comments. I significantly refactored and simplified the code, added comments, added an isStructuredItem method. I hope it makes sense.

Zorba Build Bot (zorba-buildbot) wrote :

The attempt to merge lp:~zorba-coders/zorba/xml-in-json-indices into lp:zorba failed. Below is the output from the failed tests.

No current working directory
No current working directory

I really like the introduction of the new StructuredItem. It makes a lot of sense and makes the code much cleaner. Regarding the implementation, I have some questions:

- Why is theTreeInfo in XmlTree allocated using new? Is this really required?
- Does every JSONItem have it's own CollectionTreeInfo class? If so, this seems quite some overhead. For example, each JSONItem will have it's own copy of the TreeId and Position.
- The XmlTree seems to contain two pointers to the root node; one from CollectionTreeInfo and one from XmlTree directly. Am I missing something here?

review: Needs Information
Ghislain Fourny (gislenius) wrote :

Hi Matthias,

Actually, absolutely all items in a tree that is in a collection share a unique CollectionTreeInfo instance, so that the TreeId, position, etc, exist only once physically. JSON items point to it (as before), and node items have their XML tree point to it.

JSON items only have a non-NULL pointer to CollectionTreeInfo if they are in a collection. The CollectionTreeInfo instance is created upon an attachToCollection call and delete upon detachFromCollection.

XML nodes also have a pointer if they are not in a collection, because the tree ID (among others) is also needed at some places (like structural URIs) even if they are not in a collection. In such a case, i.e., the XML tree is not in a collection, the XML tree needs to instantiate its own CollectionTreeInfo (with a NULL collection pointer). It will be deleted upon insertion in a collection and replaced with the collection-tree-wide instance. It will be recreated upon quitting the collection.

Finally, note that the root of an XML tree (mostly used for garbage collection if I am correct) might be different from the overall root of the tree in the collection (which might be a JSON item). An XML tree can "become" in a collection either directly (through attachToCollection), in which case these roots are the same, or indirectly (through setCollectionTreeInfo) if it was inserted in a JSON item that is in a collection.

I hope this helps. Does it make sense?

Zorba Build Bot (zorba-buildbot) wrote :

Attempt to merge into lp:zorba failed due to conflicts:

text conflict in src/store/naive/node_items.h

Ghislain Fourny (gislenius) wrote :

Hi Matthias,

Just a tiny correction: If the XML node is the (overall) root of the collection tree, then the existing CollectionTreeInfo instance is used. A new instance thereof is only created if the XML node gets inserted in a tree the root of which is a JSON item -- in which case the root JSON item is the owner of the instance.

Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job xml-in-json-indices-2012-09-12T14-39-42.74Z is finished. The final status was:

All tests succeeded!

Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 1 Needs Fixing, 1 Needs Information.

Till Westmann (tillw) wrote :
Download full text (6.8 KiB)

When running foaf-json-xml-index-point-maintenance.xq I run into a memory problem:

==13041== Invalid read of size 8
==13041== at 0x5ED4C32: zorba::simplestore::CollectionTreeInfo::getCollection() const (collection_tree_info.h:54)
==13041== by 0x5EC3C45: zorba::simplestore::XmlTree::setCollectionTreeInfo(zorba::simplestore::CollectionTreeInfo*) (node_items.cpp:272)
==13041== by 0x5EC5AA2: zorba::simplestore::XmlNode::setCollectionTreeInfo(zorba::simplestore::CollectionTreeInfo*) (node_items.cpp:939)
==13041== by 0x5F81BFB: zorba::simplestore::json::SimpleJSONObject::setCollectionTreeInfo(zorba::simplestore::CollectionTreeInfo*) (json_items.cpp:505)
==13041== by 0x5F802D5: zorba::simplestore::json::JSONItem::detachFromCollection() (json_items.cpp:165)
==13041== by 0x5F18251: zorba::simplestore::SimpleCollection::removeNode(zorba::store::Item*, zorba::IntegerImpl<long long>&) (simple_collection.cpp:271)
==13041== by 0x5F08680: zorba::simplestore::UpdDeleteNodesFromCollection::apply() (pul_primitives.cpp:1280)
==13041== by 0x5F4A797: zorba::simplestore::applyList(std::vector<zorba::simplestore::UpdatePrimitive*, std::allocator<zorba::simplestore::UpdatePrimitive*> >&) (simple_pul.cpp:73)
==13041== by 0x5F59674: zorba::simplestore::CollectionPul::applyUpdates() (simple_pul.cpp:3528)
==13041== by 0x5F54319: zorba::simplestore::PULImpl::applyUpdates(bool) (simple_pul.cpp:2471)
==13041== by 0x5BAE9C7: zorba::apply_updates(zorba::CompilerCB*, zorba::dynamic_context*, zorba::static_context*, zorba::store::PUL*, zorba::QueryLoc const&) (apply_updates.cpp:203)
==13041== by 0x5BAE34F: zorba::ApplyIterator::nextImpl(zorba::store::ItemHandle<zorba::store::Item>&, zorba::PlanState&) const (apply_updates.cpp:124)
==13041== Address 0xaec5090 is 0 bytes inside a block of size 32 free'd
==13041== at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13041== by 0x5F802B7: zorba::simplestore::json::JSONItem::detachFromCollection() (json_items.cpp:164)
==13041== by 0x5F18251: zorba::simplestore::SimpleCollection::removeNode(zorba::store::Item*, zorba::IntegerImpl<long long>&) (simple_collection.cpp:271)
==13041== by 0x5F08680: zorba::simplestore::UpdDeleteNodesFromCollection::apply() (pul_primitives.cpp:1280)
==13041== by 0x5F4A797: zorba::simplestore::applyList(std::vector<zorba::simplestore::UpdatePrimitive*, std::allocator<zorba::simplestore::UpdatePrimitive*> >&) (simple_pul.cpp:73)
==13041== by 0x5F59674: zorba::simplestore::CollectionPul::applyUpdates() (simple_pul.cpp:3528)
==13041== by 0x5F54319: zorba::simplestore::PULImpl::applyUpdates(bool) (simple_pul.cpp:2471)
==13041== by 0x5BAE9C7: zorba::apply_updates(zorba::CompilerCB*, zorba::dynamic_context*, zorba::static_context*, zorba::store::PUL*, zorba::QueryLoc const&) (apply_updates.cpp:203)
==13041== by 0x5BAE34F: zorba::ApplyIterator::nextImpl(zorba::store::ItemHandle<zorba::store::Item>&, zorba::PlanState&) const (apply_updates.cpp:124)
==13041== by 0x5BB16D0: zorba::Batcher<zorba::ApplyIterator>::produceNext(zorba::store::ItemHandle<zorba::store::Item>&, zorba::PlanState&) const (plan_iterator...

Read more...

review: Needs Fixing
Ghislain Fourny (gislenius) wrote :

Hi Till,

Good catch, it was a double free. Only Linux complained about it. Thanks! It should be fixed now, rerunning the tests.

Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job xml-in-json-indices-2012-11-09T13-57-20.423Z is finished. The final status was:

All tests succeeded!

Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 1 Needs Fixing, 1 Needs Information.

Paul J. Lucas (paul-lucas) wrote :

Why are .h files listed in the CMakefiles? You don't need to do that. The CMake system figures out the .h dependences from the specified .cpp files. Remove the .h dependencies.

Paul J. Lucas (paul-lucas) wrote :

In detachFromCollection(), you declare a local TreeId. A TreeId is currently defined as a typedef for a ulong. Defining a local variable of a C++ built-in type does no initialization, so the value of lTreeId is garbage.

Paul J. Lucas (paul-lucas) :
review: Needs Fixing
Markos Zaharioudakis (markos-za) wrote :

Why is the isStructuredItem() method a virtual one? I don't think it needs to be.

Markos Zaharioudakis (markos-za) wrote :

In XmlTree, there are now 2 pointers to the root node of the tree: theRootNode and theTreeInfo->theRoot.
Also, theTreeInfo should be an embeded instance of CollectionTreeInfo, instead of being allocated every time an XmlTree is constructed.

There is already an Item::isInSubtreeOf() method at the store API. Currently, this method applies to AnyURI items only. I think it should be extended to apply to structured items as well, and then the StructuredItem::isInSubtree() should be removed. This will make things consistent with the isAncestor, isChild, etc. methods, which apply to both AnyURI items and nodes.

review: Needs Fixing
Markos Zaharioudakis (markos-za) wrote :

Sorry, Ghislain, I did not see Mathias questions and your answers. Now I understand why there 2 root pointers. But I still don't see why a CollectionTreeInfo must be heap-allocated every time an XmlTree is constructed. And I have one more question: an XML tree can have a tree ID even if it is not in a collection. The tree id is used in the construction of structural references, and maybe in other places that I don't remember right now. In your merge proposal I see that the tree id is changed when a tree is inserted in a collection, its tree id changes. Are you sure this is OK? And does it really need to change?

Ghislain Fourny (gislenius) wrote :

> Why are .h files listed in the CMakefiles? You don't need to do that. The
> CMake system figures out the .h dependences from the specified .cpp files.
> Remove the .h dependencies.

Hi Paul,

It's because it adds them to the XCode project. Not having them makes full-text search very cumbersome (i.e., headers are not considered).

Ghislain Fourny (gislenius) wrote :

> In detachFromCollection(), you declare a local TreeId. A TreeId is currently
> defined as a typedef for a ulong. Defining a local variable of a C++ built-in
> type does no initialization, so the value of lTreeId is garbage.

This is now fixed. Actually, the variable would not have been used, but I agree it's cleaner that way. Thanks for noticing.

Ghislain Fourny (gislenius) wrote :

Hi Markos,

Thanks for your thorough analysis.

> Also, theTreeInfo should be an embeded instance of CollectionTreeInfo,
> instead of being allocated every time an XmlTree is constructed.

> But I still don't see why a CollectionTreeInfo must be heap-allocated
> every time an XmlTree is constructed.

The reason is that the CollectionTreeInfo object is not necessarily owned by the XMLTree, but it can also be shared with JSON items higher in the collection tree and possibly other XML trees that are also in the collection tree.

There are basically three cases:
(i) The XMLTree is not in a collection.
(ii) The XMLTree is in a collection and its root is also the overall collection tree root.
(iii) The XMLTree is in a collection, but the overall root is a JSON item.

If it were not for case (iii), it would have worked to embed the CollectionTreeInfo object in the class. But case (iii) is incompatible with this... The code should however only allocate/deallocate this object from the heap when switching between case (iii) and case (i).

Does it make sense?

Ghislain Fourny (gislenius) wrote :

I will also investigate the other two remarks, which make sense to me (isSubtreeOf, tree ID when not in a collection).

Zorba Build Bot (zorba-buildbot) wrote :

Attempt to merge into lp:zorba failed due to conflicts:

text conflict in src/store/naive/CMakeLists.txt

Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job xml-in-json-indices-2012-12-12T11-47-09.52Z is finished. The final status was:

All tests succeeded!

Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 4 Needs Fixing, 1 Needs Information.

Paul J. Lucas (paul-lucas) wrote :

> It's because it adds them to the XCode project. Not having them makes full-
> text search very cumbersome (i.e., headers are not considered).

Isn't that what our own HEADER_GROUP_SUBFOLDER custom macro is for?

Ghislain Fourny (gislenius) wrote :

> And I have one more question: an XML tree can have a tree ID even
> if it is not in a collection. The tree id is used in the construction of
> structural references, and maybe in other places that I don't remember right
> now. In your merge proposal I see that the tree id is changed when a tree is
> inserted in a collection, its tree id changes. Are you sure this is OK? And
> does it really need to change?

My understanding of the status quo is that the tree ID is already set using the new collection's tree ID generator (when calling setCollection() with a non-NULL collection):

- if (collection != NULL)
- theId = collection->createTreeId();

And the tree ID is left unchanged when leaving the collection.

setCollection has now been replaced with the more explicit attachToCollection and detachFromCollection of the StructuredItem API, but I think that the behaviour described above should be left intact by this merge proposal in both cases.

Does it make sense?

Ghislain Fourny (gislenius) wrote :

> In XmlTree, there are now 2 pointers to the root node of the tree: theRootNode
> and theTreeInfo->theRoot.
> Also, theTreeInfo should be an embeded instance of CollectionTreeInfo, instead
> of being allocated every time an XmlTree is constructed.
>
> There is already an Item::isInSubtreeOf() method at the store API. Currently,
> this method applies to AnyURI items only. I think it should be extended to
> apply to structured items as well, and then the StructuredItem::isInSubtree()
> should be removed. This will make things consistent with the isAncestor,
> isChild, etc. methods, which apply to both AnyURI items and nodes.

I added an implementation of Item::isInSubtreeOf() for structured items as you requested. However, the function StructuredItem::isInSubtree() is still needed because (i) it is the other way round and in particular (ii) it is based on a structural recursion on "this" taking advantage of dynamic binding, so that the code depends on the kind of structured item.
Item::isInSubtreeOf() cannot use a structural recursion in the same way, so that it calls StructuredItem::isInSubTree() instead to avoid both (i) code replication and (ii) making structural_item.h aware of its subclasses.

Does it make sense?

Ghislain Fourny (gislenius) wrote :

> Why is the isStructuredItem() method a virtual one? I don't think it needs to
> be.

Nice catch, I made it non-virtual.

Ghislain Fourny (gislenius) wrote :

> > It's because it adds them to the XCode project. Not having them makes full-
> > text search very cumbersome (i.e., headers are not considered).
>
> Isn't that what our own HEADER_GROUP_SUBFOLDER custom macro is for?

Thanks for the pointer. I removed the .h files for now and will address this in another merge proposal.

Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job xml-in-json-indices-2012-12-14T12-50-24.017Z is finished. The final status was:

All tests succeeded!

Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 4 Needs Fixing, 1 Needs Information.

Zorba Build Bot (zorba-buildbot) wrote :

The attempt to merge lp:~zorba-coders/zorba/xml-in-json-indices into lp:zorba failed. Below is the output from the failed tests.

CMake Error at /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake:275 (message):
  Validation queue job xml-in-json-indices-2013-01-29T10-15-10.37Z is
  finished. The final status was:

  7 tests did not succeed - changes not commited.

Error in read script: /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake

Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job xml-in-json-indices-2013-01-29T13-59-36.602Z is finished. The final status was:

All tests succeeded!

Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 4 Needs Fixing, 1 Needs Information.

Zorba Build Bot (zorba-buildbot) wrote :

Attempt to merge into lp:zorba failed due to conflicts:

text conflict in src/store/naive/simple_collection.cpp

Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job xml-in-json-indices-2013-01-30T14-46-35.086Z is finished. The final status was:

All tests succeeded!

Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 4 Needs Fixing, 1 Needs Information.

Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job xml-in-json-indices-2013-02-04T15-47-42.372Z is finished. The final status was:

All tests succeeded!

Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 4 Needs Fixing, 1 Needs Information.

review: Approve
review: Approve
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job xml-in-json-indices-2013-02-07T14-13-01.44Z is finished. The final status was:

All tests succeeded!

Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 2 Approve, 2 Needs Fixing, 1 Needs Information.

review: Approve
review: Approve
Paul J. Lucas (paul-lucas) wrote :

In several places, I see calls to to_xs_unsignedInt() and to to_xs_unsignedLong() without catching the possible std::range_error.

Till Westmann (tillw) :
review: Approve
Ghislain Fourny (gislenius) wrote :

Good catch Paul. Do the changes fulfil your expectations provided all tests pass? I am not pushing yet to the patch queue because it might get through without your approval.

Ghislain Fourny (gislenius) wrote :

I just noticed you are in a Need Fixing state, so I am pushing to the patch queue.

Paul J. Lucas (paul-lucas) wrote :

> Do the changes fulfil your expectations provided all tests pass?

No because you should catch by const& not by value. And is "assert(false)" really the only/best thing you can do? Is there any legitimate way the position can exceed the size of a long? If the answer is "yes," then you need to do something better.

Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job xml-in-json-indices-2013-02-18T15-20-10.215Z is finished. The final status was:

All tests succeeded!

Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 4 Approve, 1 Needs Fixing.

Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job xml-in-json-indices-2013-02-18T16-14-00.593Z is finished. The final status was:

All tests succeeded!

Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 4 Approve, 1 Needs Fixing.

Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job xml-in-json-indices-2013-02-21T14-37-15.369Z is finished. The final status was:

All tests succeeded!

Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 4 Approve, 1 Needs Fixing.

11065. By Ghislain Fourny on 2013-02-21

Changing exception to const&.

Ghislain Fourny (gislenius) wrote :

Hi Paul,

I formerly assessed the risk of reaching the limits of the int/long range for a position as highly unlikely, but I do have doubts about whether a negative number might go through. So I changed assert(false) to a proper processor exception. I also changed to const&.

Paul J. Lucas (paul-lucas) :
review: Approve
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job xml-in-json-indices-2013-02-21T15-43-09.091Z is finished. The final status was:

All tests succeeded!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/runtime/collections/collections_impl.cpp'
2--- src/runtime/collections/collections_impl.cpp 2013-01-31 11:32:47 +0000
3+++ src/runtime/collections/collections_impl.cpp 2013-02-21 15:32:25 +0000
4@@ -1816,12 +1816,12 @@
5 consumeNext(content, theChildren[1].getp(), planState);
6
7 // Target check.
8- if (! target->getCollection())
9+ if (!target->getCollection() || !target->isStructuredItem())
10 {
11 throw XQUERY_EXCEPTION(zerr::ZDDY0017_NODE_IS_ORPHAN, ERROR_LOC(loc));
12 }
13
14- if ((target->isNode() || target->isJSONItem()) && !target->isRoot())
15+ if (!target->isCollectionRoot())
16 {
17 throw XQUERY_EXCEPTION(
18 zerr::ZDDY0039_NON_ROOT_NODE_EDIT,
19
20=== modified file 'src/runtime/json/json_constructors.cpp'
21--- src/runtime/json/json_constructors.cpp 2012-10-08 12:09:36 +0000
22+++ src/runtime/json/json_constructors.cpp 2013-02-21 15:32:25 +0000
23@@ -304,7 +304,7 @@
24 consumeNext(name, theChildren[i], planState);
25 consumeNext(value, theChildren[numPairs + i], planState);
26
27- if (theCopyInputs[i] && (value->isNode() || value->isJSONItem()))
28+ if (theCopyInputs[i] && (value->isStructuredItem()))
29 value = value->copy(NULL, copymode);
30
31 names[i].transfer(name);
32
33=== modified file 'src/runtime/json/jsoniq_functions_impl.cpp'
34--- src/runtime/json/jsoniq_functions_impl.cpp 2013-02-16 17:16:13 +0000
35+++ src/runtime/json/jsoniq_functions_impl.cpp 2013-02-21 15:32:25 +0000
36@@ -975,7 +975,7 @@
37 {
38 value = obj->getObjectValue(key);
39
40- if (value->isNode() || value->isJSONItem())
41+ if (value->isStructuredItem())
42 value = value->copy(NULL, copymode);
43
44 newValues.push_back(value);
45@@ -1261,7 +1261,7 @@
46 theSctx->preserve_ns(),
47 theSctx->inherit_ns());
48
49- if (content->isNode() || content->isJSONItem())
50+ if (content->isStructuredItem())
51 {
52 content = content->copy(NULL, copymode);
53 }
54@@ -1308,7 +1308,7 @@
55
56 while (consumeNext(member, theChildren[2].getp(), planState))
57 {
58- if (member->isNode() || member->isJSONItem())
59+ if (member->isStructuredItem())
60 {
61 member = member->copy(NULL, copymode);
62 }
63@@ -1356,7 +1356,7 @@
64
65 while (consumeNext(member, theChildren[1].getp(), planState))
66 {
67- if (member->isNode() || member->isJSONItem())
68+ if (member->isStructuredItem())
69 {
70 member = member->copy(NULL, copymode);
71 }
72@@ -1481,7 +1481,7 @@
73 consumeNext(selector, theChildren[1].getp(), planState);
74 consumeNext(newValue, theChildren[2].getp(), planState);
75
76- if (theCopyInput && (newValue->isNode() || newValue->isJSONItem()))
77+ if (theCopyInput && (newValue->isStructuredItem()))
78 {
79 copymode.set(true,
80 theSctx->construction_mode() == StaticContextConsts::cons_preserve,
81
82=== modified file 'src/store/api/item.h'
83--- src/store/api/item.h 2013-02-05 04:08:51 +0000
84+++ src/store/api/item.h 2013-02-21 15:32:25 +0000
85@@ -45,10 +45,16 @@
86
87 typedef StoreConsts::NodeKind NodeKind;
88
89-/**
90- * Class Item represents an "item" as defined by the XQuery Data Model (XDM)
91- * [http://www.w3.org/TR/xquery-semantics/doc-fs-Item]
92- */
93+/*******************************************************************************
94+ Class Item represents an "item" as defined by the XQuery Data Model (XDM)
95+ [http://www.w3.org/TR/xquery-semantics/doc-fs-Item]
96+
97+ theUnion:
98+ ---------
99+ It stores either a pointer to an XmlTree or an ItemKind enum value. The
100+ low-order bit is used to distinguish between these 2 cases: a 0 bit indicates
101+ an XmlTree pointer, and a 1 bit indicated an ItemKind.
102+********************************************************************************/
103 class ZORBA_DLL_PUBLIC Item
104 {
105 public:
106@@ -181,6 +187,15 @@
107
108
109 /**
110+ * @return "true" if the item is a JSON item or a node
111+ */
112+ bool
113+ isStructuredItem() const
114+ {
115+ return isNode() || isJSONItem();
116+ }
117+
118+ /**
119 * @return a string representation of the item's kind
120 */
121 zstring printKind() const;
122@@ -454,25 +469,21 @@
123 virtual const xs_duration&
124 getDurationValue() const;
125
126-
127 /** Accessor for xs:dayTimeDuration
128 */
129 virtual const xs_dayTimeDuration&
130 getDayTimeDurationValue() const;
131
132-
133 /** Accessor for xs:yearMonthDuration
134 */
135 virtual const xs_yearMonthDuration&
136 getYearMonthDurationValue() const;
137
138-
139 /** Accessor for xs:hexBinary
140 */
141 virtual xs_hexBinary
142 getHexBinaryValue() const;
143
144-
145 /**
146 * Helper method for numeric atomic items
147 * @return true, if containing number is not-a-number (possible for
148@@ -481,7 +492,6 @@
149 virtual bool
150 isNaN() const;
151
152-
153 /**
154 * Helper method for numeric atomic items
155 * @return true, if containing numbers represents -INF or +INF
156@@ -525,8 +535,25 @@
157 virtual bool
158 isTextRef() const;
159
160-
161- /* ------------------- Methods for Nodes ------------------------------------- */
162+ /* ------------------- Methods for XML and JSON Nodes --------------------- */
163+
164+ /**
165+ * @return true if this node is the root node of a tree that belongs to a
166+ * a collection directly.
167+ */
168+ virtual bool
169+ isCollectionRoot() const;
170+
171+ /**
172+ * @return true if this node is in the subtree starting at the given item.
173+ * NOTE: for the purposes of this method, XML trees that are pointed-to
174+ * by a JSON tree are considered part of that JSON tree. As a result,
175+ * an XML node may be in the subtree of a JSON node.
176+ */
177+ virtual bool
178+ isInSubtreeOf(const store::Item_t&) const;
179+
180+ /* ------------------- Methods for XML Nodes ------------------------------ */
181
182 /**
183 * getNodeProperty functions - Accessor of XDM (see XDM specification, Section 5)
184@@ -558,10 +585,10 @@
185 * @return True if this is an element node with name N and it has at least one
186 * descendant whose name is also N.
187 *
188- * Note: This function is used purely for enabling certain optimizations in the
189- * query processor. As a result, it is not necessary that a store actually
190- * provides info about the recursivity of a node; such a store should
191- * provide a dummy implementation of this method that simply returns true.
192+ * Note: This function is used purely for enabling certain optimizations in
193+ * the query processor. As a result, it is not necessary that a store actually
194+ * provides info about the recursivity of a node; such a store should provide
195+ * a dummy implementation of this method that simply returns true.
196 */
197 virtual bool
198 isRecursive() const;
199@@ -614,8 +641,8 @@
200 */
201 virtual void
202 getNamespaceBindings(
203- NsBindings& bindings,
204- StoreConsts::NsScoping ns_scoping = StoreConsts::ALL_NAMESPACES) const;
205+ NsBindings& bindings,
206+ StoreConsts::NsScoping ns_scoping = StoreConsts::ALL_NAMESPACES) const;
207
208 /** Accessor for element node
209 * @return boolean?
210@@ -747,12 +774,6 @@
211 *
212 */
213 virtual bool
214- isInSubtreeOf(const store::Item_t&) const;
215-
216- /**
217- *
218- */
219- virtual bool
220 isDescendant(const store::Item_t&) const;
221
222 /**
223@@ -844,12 +865,6 @@
224 getJSONItemKind() const;
225
226 /**
227- * @return true if the JSON item is a root in a collection.
228- */
229- virtual bool
230- isRoot() const;
231-
232- /**
233 * defined on JSONArray
234 * (jdm:size accessor on an array)
235 * @return the number of values in the array.
236
237=== modified file 'src/store/naive/CMakeLists.txt'
238--- src/store/naive/CMakeLists.txt 2012-11-29 00:47:32 +0000
239+++ src/store/naive/CMakeLists.txt 2013-02-21 15:32:25 +0000
240@@ -16,45 +16,47 @@
241 # Source Files
242 #
243 SET(ZORBA_STORE_IMPL_SRCS
244+ atomic_items.cpp
245+ collection.cpp
246+ dataguide.cpp
247+ inmemorystore.cpp
248+ inmemorystorec.cpp
249 item.cpp
250+ item_iterator.cpp
251 item_vector.cpp
252+ loader_fast.cpp
253+ loader_dtd.cpp
254+ node_factory.cpp
255 node_items.cpp
256- node_factory.cpp
257+ node_iterators.cpp
258 node_updates.cpp
259- simple_pul.cpp
260+ nsbindings.cpp
261+ ordpath.cpp
262+ properties.cpp
263+ pul_primitive_factory.cpp
264 pul_primitives.cpp
265- pul_primitive_factory.cpp
266- atomic_items.cpp
267- item_iterator.cpp
268- node_iterators.cpp
269- simple_item_factory.cpp
270- simple_store.cpp
271- simple_iterator_factory.cpp
272+ qname_pool.cpp
273 simple_collection.cpp
274 simple_collection_set.cpp
275 simple_index.cpp
276+ simple_index_general.cpp
277 simple_index_value.cpp
278- simple_index_general.cpp
279+ simple_item_factory.cpp
280+ simple_iterator_factory.cpp
281+ simple_lazy_temp_seq.cpp
282+ simple_pul.cpp
283+ simple_store.cpp
284 simple_temp_seq.cpp
285- simple_lazy_temp_seq.cpp
286- loader_fast.cpp
287- loader_dtd.cpp
288- qname_pool.cpp
289+ store.cpp
290 string_pool.cpp
291- ordpath.cpp
292- nsbindings.cpp
293- properties.cpp
294- inmemorystore.cpp
295- inmemorystorec.cpp
296- dataguide.cpp
297+ structured_item.cpp
298 tree_id_generator.cpp
299- collection.cpp
300- store.cpp
301 )
302
303 IF (NOT ZORBA_NO_FULL_TEXT)
304 LIST(APPEND ZORBA_STORE_IMPL_SRCS
305- ft_token_store.cpp naive_ft_token_iterator.cpp)
306+ ft_token_store.cpp
307+ naive_ft_token_iterator.cpp)
308 ENDIF (NOT ZORBA_NO_FULL_TEXT)
309
310 IF (ZORBA_WITH_JSON)
311
312=== modified file 'src/store/naive/collection.cpp'
313--- src/store/naive/collection.cpp 2012-09-19 21:16:15 +0000
314+++ src/store/naive/collection.cpp 2013-02-21 15:32:25 +0000
315@@ -26,11 +26,19 @@
316 namespace zorba {
317 namespace simplestore {
318
319-void Collection::claimOwnership(zorba::simplestore::XmlTree* aTree)
320+
321+/*******************************************************************************
322+
323+*******************************************************************************/
324+void Collection::getIndexes(std::vector<store::Index*>& indexes)
325 {
326- aTree->claimedByCollection(this);
327+ getIndexes(getName(), indexes);
328 }
329
330+
331+/*******************************************************************************
332+ Static method
333+*******************************************************************************/
334 void Collection::getIndexes(
335 const store::Item* name,
336 std::vector<store::Index*>& indexes)
337@@ -46,9 +54,9 @@
338 const store::IndexSpecification& indexSpec = index->getSpecification();
339
340 const std::vector<store::Item_t>& indexSources = indexSpec.theSources;
341- uint64_t numIndexSources = (uint64_t)indexSources.size();
342+ csize numIndexSources = indexSources.size();
343
344- for (ulong i = 0; i < numIndexSources; ++i)
345+ for (csize i = 0; i < numIndexSources; ++i)
346 {
347 if (indexSources[i]->equals(name))
348 {
349@@ -59,6 +67,19 @@
350 }
351 }
352
353+
354+/*******************************************************************************
355+
356+*******************************************************************************/
357+void Collection::getActiveICs(std::vector<store::IC*>& ics)
358+{
359+ getActiveICs(getName(), ics);
360+}
361+
362+
363+/*******************************************************************************
364+ Static method
365+*******************************************************************************/
366 void Collection::getActiveICs(
367 const store::Item* name,
368 std::vector<store::IC*>& ics)
369@@ -96,18 +117,6 @@
370 activeICNames->close();
371 }
372
373-/*******************************************************************************
374-
375-*******************************************************************************/
376-void Collection::getActiveICs(std::vector<store::IC*>& ics)
377-{
378- getActiveICs(getName(), ics);
379-}
380-
381-void Collection::getIndexes(std::vector<store::Index*>& indexes)
382-{
383- getIndexes(getName(), indexes);
384-}
385
386 } /* namespace simplestore */
387 } /* namespace zorba */
388
389=== modified file 'src/store/naive/collection.h'
390--- src/store/naive/collection.h 2012-12-17 10:30:41 +0000
391+++ src/store/naive/collection.h 2013-02-21 15:32:25 +0000
392@@ -26,25 +26,21 @@
393 /*******************************************************************************
394 Interface for Collection used in the SimpleStore
395
396- theName : The user-provided qname of the collection.
397+ theName:
398+ --------
399+ The user-provided qname of the collection.
400 ********************************************************************************/
401 class Collection : public store::Collection
402 {
403 protected:
404- store::Item_t theName;
405+ store::Item_t theName;
406
407 public:
408 /***************************** Constructors *********************************/
409
410- Collection(const store::Item_t& aName)
411- :
412- theName(aName)
413- {
414- }
415+ Collection(const store::Item_t& name) : theName(name) { }
416
417- Collection()
418- {
419- }
420+ Collection() { }
421
422 virtual ~Collection() {}
423
424@@ -54,20 +50,21 @@
425
426 zorba::xs_integer size() const = 0;
427
428- zorba::store::Iterator_t getIterator(
429- const xs_integer& aSkip,
430- const zstring& aStart) = 0;
431+ virtual bool isDynamic() const = 0;
432+
433+ virtual void getAnnotations(std::vector<store::Annotation_t>&) const = 0;
434+
435+ store::Iterator_t getIterator(const xs_integer& skip, const zstring& start) = 0;
436+
437+ virtual bool findNode(const store::Item* node, xs_integer& position) const = 0;
438
439 virtual zorba::store::Item_t nodeAt(xs_integer position) = 0;
440
441- virtual bool findNode(
442- const store::Item* node,
443- xs_integer& position) const = 0;
444-
445- virtual bool isDynamic() const = 0;
446-
447- virtual void getAnnotations(
448- std::vector<zorba::store::Annotation_t>&) const = 0;
449+ /***************************** ID Management ********************************/
450+
451+ virtual ulong getId() const = 0;
452+
453+ virtual TreeId createTreeId() = 0;
454
455 /************************* Updates on collection ****************************/
456
457@@ -84,39 +81,28 @@
458
459 virtual bool removeNode(xs_integer position) = 0;
460
461- virtual zorba::xs_integer removeNodes(
462- xs_integer position,
463- xs_integer num) = 0;
464+ virtual zorba::xs_integer removeNodes(xs_integer position, xs_integer num) = 0;
465
466 virtual void removeAll() = 0;
467
468 virtual void adjustTreePositions() = 0;
469
470- /***************************** ID Management ********************************/
471-
472- virtual ulong getId() const = 0;
473-
474- virtual TreeId createTreeId() = 0;
475-
476 /*********************** Indices ********************************************/
477+
478 static void getIndexes(
479 const store::Item* name,
480 std::vector<store::Index*>& indexes);
481
482 void getIndexes(std::vector<store::Index*>& indexes);
483
484- /**** Returns active integrity constraints referencing this collection ******/
485+ /*********************** Integrity Constraints ******************************/
486+
487 static void getActiveICs(
488 const store::Item* name,
489 std::vector<store::IC*>& ics);
490
491 void getActiveICs(std::vector<store::IC*>& ics);
492-
493- /**************************** Claim of ownership ****************************/
494-protected:
495- virtual void claimOwnership(simplestore::XmlTree* aTree);
496-
497-}; /* class Collection */
498+};
499
500
501 } /* namespace simplestore */ } /* namespace zorba */
502
503=== added file 'src/store/naive/collection_tree_info.h'
504--- src/store/naive/collection_tree_info.h 1970-01-01 00:00:00 +0000
505+++ src/store/naive/collection_tree_info.h 2013-02-21 15:32:25 +0000
506@@ -0,0 +1,194 @@
507+/*
508+ * Copyright 2006-2008 The FLWOR Foundation.
509+ *
510+ * Licensed under the Apache License, Version 2.0 (the "License");
511+ * you may not use this file except in compliance with the License.
512+ * You may obtain a copy of the License at
513+ *
514+ * http://www.apache.org/licenses/LICENSE-2.0
515+ *
516+ * Unless required by applicable law or agreed to in writing, software
517+ * distributed under the License is distributed on an "AS IS" BASIS,
518+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
519+ * See the License for the specific language governing permissions and
520+ * limitations under the License.
521+ */
522+
523+#ifndef ZORBA_STORE_COLLECTION_TREE_INFO_H
524+#define ZORBA_STORE_COLLECTION_TREE_INFO_H
525+
526+#include <zorba/config.h>
527+
528+namespace zorba
529+{
530+
531+namespace simplestore
532+{
533+
534+class Collection;
535+class StructuredItem;
536+
537+/******************************************************************************
538+ Contains info about an XML or JSON tree that belongs to a collection, either
539+ directly or indirectly. A tree belongs to a collection "directly" if the
540+ collection stores a "pointer" to the root of the tree. A tree belongs to a
541+ collection "indirectly" if it is pointed-to by a tree that belongs to the
542+ collection directly. Such indirect membership happens only when an XML tree
543+ is pointed-to by a JSON tree that belongs to a collection directly. Indirect
544+ membership cannot happen for JSON trees.
545+
546+ A tree may belong to at most one collection at a time.
547+
548+ A CollectionTreeInfo instance is created when a tree is attached to a collection
549+ (directly or indirectly) and is destroyed when the tree is detached from the
550+ collection. For XML trees, a pointer to this CollectionTreeInfo is stored in
551+ the XmlTree obj representing the tree. For JSON trees, a pointer to the
552+ CollectionTreeInfo is stored in each node of the tree.
553+
554+ Each tree within a collection must have an id that uniquely identifies the
555+ tree within the collection.
556+
557+ XML trees need a tree id even if they don't belong to a collection. As a
558+ result, XML trees store their id inside their associated XmlTree object.
559+ When an XML tree does not belong to a collection, its id uniquely identifies
560+ the tree among all the trees that do not belong to any collection. When an
561+ XML tree enters a collection, its tree id is updated so that is becomes
562+ unique within the target collection. When an XML tree exits a collection,
563+ its id is again updated appropriately.
564+
565+ JSON trees need a tree id only while inside a collection. For this purpose,
566+ the CollectionTreeInfoWithTreeId subclass is use to provide the storage for
567+ the tree id.
568+
569+ theCollection:
570+ --------------
571+ The collection where this tree belongs to.
572+
573+ theRoot:
574+ --------
575+ The xml or json node that is directly stored in the collection. For JSON trees
576+ this is the root node of the tree. For XML trees, it is the root node of the
577+ tree, if the tree belongs to the collection directly, or it is the root of a
578+ JSON tree that belongs to the collection directly and also points to the XML
579+ tree.
580+
581+ thePosition:
582+ ------------
583+ The position of this tree within its containing collection. It is used as a
584+ hint to quickly retrieve the tree of a node within a collection.
585+
586+ Very simple API (just getters and setters for each of the data members).
587+*******************************************************************************/
588+
589+class CollectionTreeInfo
590+{
591+protected:
592+ Collection* theCollection;
593+ xs_integer thePosition;
594+ StructuredItem* theRoot;
595+
596+public:
597+ CollectionTreeInfo()
598+ :
599+ theCollection(NULL),
600+ thePosition(0),
601+ theRoot(NULL)
602+ {
603+ }
604+
605+ simplestore::Collection* getCollection() const
606+ {
607+ return theCollection;
608+ }
609+
610+ void setCollection(simplestore::Collection* aCollection)
611+ {
612+ theCollection = aCollection;
613+ }
614+
615+ StructuredItem* getRoot() const
616+ {
617+ return theRoot;
618+ }
619+
620+ void setRoot(StructuredItem* aRoot)
621+ {
622+ theRoot = aRoot;
623+ }
624+
625+ const xs_integer& getPosition() const
626+ {
627+ return thePosition;
628+ }
629+
630+ void setPosition(const xs_integer& aPosition)
631+ {
632+ thePosition = aPosition;
633+ }
634+};
635+
636+
637+/******************************************************************************
638+
639+*******************************************************************************/
640+class CollectionTreeInfoWithTreeId : public CollectionTreeInfo
641+{
642+private:
643+ TreeId theTreeId;
644+
645+public:
646+ CollectionTreeInfoWithTreeId() : theTreeId() {}
647+
648+ simplestore::Collection* getCollection() const
649+ {
650+ return theCollection;
651+ }
652+
653+ void setCollection(simplestore::Collection* aCollection)
654+ {
655+ theCollection = aCollection;
656+ }
657+
658+ const TreeId& getTreeId() const
659+ {
660+ return theTreeId;
661+ }
662+
663+ void setTreeId(const TreeId& aId)
664+ {
665+ theTreeId = aId;
666+ }
667+
668+ StructuredItem* getRoot() const
669+ {
670+ return theRoot;
671+ }
672+
673+ void setRoot(StructuredItem* aRoot)
674+ {
675+ theRoot = aRoot;
676+ }
677+
678+ const xs_integer& getPosition() const
679+ {
680+ return thePosition;
681+ }
682+
683+ void setPosition(const xs_integer& aPosition)
684+ {
685+ thePosition = aPosition;
686+ }
687+};
688+
689+
690+} // namespace simplestore
691+} // namespace zorba
692+#endif /* ZORBA_STORE_COLLECTION_TREE_INFO_H */
693+
694+/*
695+ * Local variables:
696+ * mode: c++
697+ * End:
698+ */
699+/* vim:set et sw=2 ts=2: */
700+
701
702=== modified file 'src/store/naive/item.cpp'
703--- src/store/naive/item.cpp 2013-02-05 04:08:51 +0000
704+++ src/store/naive/item.cpp 2013-02-21 15:32:25 +0000
705@@ -1348,7 +1348,7 @@
706 );
707 }
708
709-bool Item::isRoot() const
710+bool Item::isCollectionRoot() const
711 {
712 throw ZORBA_EXCEPTION(
713 zerr::ZSTR0050_FUNCTION_NOT_IMPLEMENTED_FOR_ITEMTYPE,
714
715=== modified file 'src/store/naive/json_items.cpp'
716--- src/store/naive/json_items.cpp 2013-02-17 00:59:54 +0000
717+++ src/store/naive/json_items.cpp 2013-02-21 15:32:25 +0000
718@@ -37,14 +37,6 @@
719 /******************************************************************************
720
721 *******************************************************************************/
722-JSONTree::~JSONTree()
723-{
724- GET_STORE().unregisterReferenceToDeletedNode(theRoot);
725-}
726-
727-/******************************************************************************
728-
729-*******************************************************************************/
730 store::Item* JSONNull::getType() const
731 {
732 return GET_STORE().JS_NULL_QNAME;
733@@ -94,7 +86,7 @@
734 *******************************************************************************/
735 JSONItem::~JSONItem()
736 {
737- delete theTree;
738+ delete theCollectionInfo;
739 }
740
741
742@@ -112,58 +104,39 @@
743 *******************************************************************************/
744 void JSONItem::destroy()
745 {
746+ GET_STORE().unregisterReferenceToUnusedNode(this);
747 delete this;
748 }
749
750
751-/******************************************************************************
752-
753-*******************************************************************************/
754-const simplestore::Collection* JSONItem::getCollection() const
755-{
756- if (theTree == NULL)
757- {
758- return NULL;
759- }
760- return theTree->getCollection();
761-}
762-
763-
764-/******************************************************************************
765- Should only to be called if item is in a collection.
766-*******************************************************************************/
767-const TreeId& JSONItem::getTreeId() const
768-{
769- ZORBA_ASSERT(theTree);
770- return theTree->getTreeId();
771-}
772-
773-
774-/******************************************************************************
775- Should only to be called if item is in a collection.
776-*******************************************************************************/
777-JSONItem* JSONItem::getRoot() const
778-{
779- ZORBA_ASSERT(theTree);
780- return theTree->getRoot();
781-}
782-
783-
784-/*******************************************************************************
785-
786-********************************************************************************/
787-void JSONItem::attachToCollection(Collection* aCollection, const TreeId& aTreeId)
788+/*******************************************************************************
789+
790+********************************************************************************/
791+long JSONItem::getCollectionTreeRefCount() const
792+{
793+ return getRefCount();
794+}
795+
796+/*******************************************************************************
797+
798+********************************************************************************/
799+void JSONItem::attachToCollection(
800+ Collection* aCollection,
801+ const TreeId& aTreeId,
802+ const xs_integer& aPosition)
803 {
804 ASSERT_INVARIANT();
805-
806+
807 assert(aCollection);
808
809 // Attach
810- assert(getTree() == NULL);
811- setTree(new JSONTree());
812- getTree()->setRoot(this);
813- getTree()->setCollection(aCollection);
814- getTree()->setTreeId(aTreeId);
815+ assert(theCollectionInfo == NULL);
816+ CollectionTreeInfoWithTreeId* collectionInfo = new CollectionTreeInfoWithTreeId();
817+ collectionInfo->setCollection(aCollection);
818+ collectionInfo->setTreeId(aTreeId);
819+ collectionInfo->setPosition(aPosition);
820+ collectionInfo->setRoot(this);
821+ setCollectionTreeInfo(collectionInfo);
822
823 ASSERT_INVARIANT();
824 }
825@@ -175,11 +148,12 @@
826 {
827 ASSERT_INVARIANT();
828
829- JSONTree* lTree = getTree();
830+
831+ CollectionTreeInfo* collectionInfo = theCollectionInfo;
832 // Detach
833- assert(lTree);
834- delete lTree;
835- setTree(NULL);
836+ assert(collectionInfo);
837+ setCollectionTreeInfo(NULL);
838+ delete collectionInfo;
839
840 ASSERT_INVARIANT();
841 }
842@@ -190,12 +164,12 @@
843 *******************************************************************************/
844 void JSONItem::assertInvariant() const
845 {
846- if (theTree != NULL)
847+ if (theCollectionInfo != NULL)
848 {
849- assert(theTree->getCollection() != NULL);
850- assert(theTree->getRoot() != NULL);
851- assert(isThisTreeOfAllDescendants(theTree));
852- assert(theTree->getRoot()->isThisJSONItemInDescendance(this));
853+ assert(theCollectionInfo->getCollection() != NULL);
854+ assert(theCollectionInfo->getRoot() != NULL);
855+ assert(isThisTreeOfAllDescendants(theCollectionInfo));
856+ assert(theCollectionInfo->getRoot()->isInSubtree(this));
857 }
858 }
859 #endif
860@@ -229,11 +203,11 @@
861 {
862 store::Item* lName = lIter->first;
863 store::Item* lChild = lIter->second;
864- if (getCollection() != NULL && lChild->isJSONItem())
865+ if (getCollection() != NULL && lChild->isStructuredItem())
866 {
867- assert(dynamic_cast<JSONItem*>(lChild));
868- JSONItem* lJSONItem = static_cast<JSONItem*>(lChild);
869- lJSONItem->setTree(NULL);
870+ assert(dynamic_cast<StructuredItem*>(lChild));
871+ StructuredItem* lStructuredItem = static_cast<StructuredItem*>(lChild);
872+ lStructuredItem->setCollectionTreeInfo(NULL);
873 }
874 lName->removeReference();
875 lChild->removeReference();
876@@ -324,11 +298,11 @@
877 {
878 store::Item* lValue = aValue.getp();
879
880- if (getCollection() != NULL && aValue->isJSONItem())
881+ if (getCollection() != NULL && (aValue->isStructuredItem()))
882 {
883- assert(dynamic_cast<JSONItem*>(aValue.getp()));
884- JSONItem* lJSONItem = static_cast<JSONItem*>(aValue.getp());
885- lJSONItem->setTree(getTree());
886+ assert(dynamic_cast<StructuredItem*>(aValue.getp()));
887+ StructuredItem* lStructuredItem = static_cast<StructuredItem*>(aValue.getp());
888+ lStructuredItem->setCollectionTreeInfo(theCollectionInfo);
889 }
890
891 csize lPosition = thePairs.size();
892@@ -360,7 +334,7 @@
893
894 if (getCollection() != NULL)
895 {
896- array->setTree(getTree());
897+ array->setCollectionTreeInfo(theCollectionInfo);
898 }
899
900 lValue->removeReference();
901@@ -399,11 +373,11 @@
902 lKey = thePairs[lPosition].first;
903 lValue = thePairs[lPosition].second;
904
905- if (getCollection() != NULL && lValue->isJSONItem())
906+ if (getCollection() != NULL && (lValue->isStructuredItem()))
907 {
908- assert(dynamic_cast<JSONItem*>(lValue.getp()));
909- JSONItem* lJSONItem = static_cast<JSONItem*>(lValue.getp());
910- lJSONItem->setTree(NULL);
911+ assert(dynamic_cast<StructuredItem*>(lValue.getp()));
912+ StructuredItem* lStructuredItem = static_cast<StructuredItem*>(lValue.getp());
913+ lStructuredItem->setCollectionTreeInfo(NULL);
914 }
915
916 lKey->removeReference();
917@@ -455,18 +429,20 @@
918
919 if (getCollection() != NULL)
920 {
921- if (lOldValue->isJSONItem())
922+ if (lOldValue->isStructuredItem())
923 {
924- assert(dynamic_cast<JSONItem*>(lOldValue.getp()));
925- JSONItem* lJSONItem = static_cast<JSONItem*>(lOldValue.getp());
926- lJSONItem->setTree(NULL);
927+ assert(dynamic_cast<StructuredItem*>(lOldValue.getp()));
928+ StructuredItem* lStructuredItem =
929+ static_cast<StructuredItem*>(lOldValue.getp());
930+ lStructuredItem->setCollectionTreeInfo(NULL);
931 }
932
933- if (aValue->isJSONItem())
934+ if (aValue->isStructuredItem())
935 {
936- assert(dynamic_cast<JSONItem*>(aValue.getp()));
937- JSONItem* lJSONItem = static_cast<JSONItem*>(aValue.getp());
938- lJSONItem->setTree(getTree());
939+ assert(dynamic_cast<StructuredItem*>(aValue.getp()));
940+ StructuredItem* lStructuredItem =
941+ static_cast<StructuredItem*>(aValue.getp());
942+ lStructuredItem->setCollectionTreeInfo(theCollectionInfo);
943 }
944 }
945
946@@ -518,6 +494,7 @@
947 return true;
948 }
949
950+
951 /******************************************************************************
952
953 *******************************************************************************/
954@@ -527,27 +504,28 @@
955 assert(lOther);
956 std::swap(theKeys, lOther->theKeys);
957 std::swap(thePairs, lOther->thePairs);
958- setTree(getTree());
959- lOther->setTree(lOther->getTree());
960+ setCollectionTreeInfo(theCollectionInfo);
961+ lOther->setCollectionTreeInfo(lOther->theCollectionInfo);
962 }
963
964+
965 /******************************************************************************
966
967 *******************************************************************************/
968-void SimpleJSONObject::setTree(JSONTree* aTree)
969+void SimpleJSONObject::setCollectionTreeInfo(CollectionTreeInfo* collectionInfo)
970 {
971- theTree = aTree;
972+ theCollectionInfo = static_cast<CollectionTreeInfoWithTreeId*>(collectionInfo);
973
974- for (Pairs::iterator lIter = thePairs.begin();
975- lIter != thePairs.end();
976- ++lIter)
977+ for (Pairs::iterator ite = thePairs.begin();
978+ ite != thePairs.end();
979+ ++ite)
980 {
981- store::Item* lValue = lIter->second;
982- if (lValue->isJSONItem())
983+ store::Item* value = ite->second;
984+
985+ if (value->isStructuredItem())
986 {
987- assert(dynamic_cast<JSONItem*>(lValue));
988- JSONItem* lJSONItem = static_cast<JSONItem*>(lValue);
989- lJSONItem->setTree(aTree);
990+ StructuredItem* structuredItem = static_cast<StructuredItem*>(value);
991+ structuredItem->setCollectionTreeInfo(collectionInfo);
992 }
993 }
994 }
995@@ -651,9 +629,10 @@
996 /******************************************************************************
997
998 *******************************************************************************/
999-bool SimpleJSONObject::isThisTreeOfAllDescendants(const JSONTree* aTree) const
1000+bool SimpleJSONObject::isThisTreeOfAllDescendants(
1001+ const CollectionTreeInfo* collectionInfo) const
1002 {
1003- if (theTree != aTree)
1004+ if (theCollectionInfo != collectionInfo)
1005 {
1006 return false;
1007 }
1008@@ -664,19 +643,21 @@
1009 {
1010 store::Item* lValue = lIter->second;
1011 const JSONItem* lJSONItem = dynamic_cast<const JSONItem*>(lValue);
1012- if (lJSONItem != NULL && (!lJSONItem->isThisTreeOfAllDescendants(aTree)))
1013+ if (lJSONItem != NULL &&
1014+ !lJSONItem->isThisTreeOfAllDescendants(collectionInfo))
1015 {
1016 return false;
1017 }
1018 }
1019 return true;
1020 }
1021+#endif // NDEBUG
1022
1023
1024 /******************************************************************************
1025
1026 *******************************************************************************/
1027-bool SimpleJSONObject::isThisJSONItemInDescendance(const store::Item* anItem) const
1028+bool SimpleJSONObject::isInSubtree(const StructuredItem* anItem) const
1029 {
1030 if (this == anItem)
1031 {
1032@@ -688,23 +669,18 @@
1033 ++lIter)
1034 {
1035 store::Item* lValue = lIter->second;
1036- const SimpleJSONObject* lObject =
1037- dynamic_cast<const SimpleJSONObject*>(lValue);
1038- const SimpleJSONArray* lArray =
1039- dynamic_cast<const SimpleJSONArray*>(lValue);
1040-
1041- if (lObject != NULL && lObject->isThisJSONItemInDescendance(anItem))
1042- {
1043- return true;
1044- }
1045- else if (lArray != NULL && lArray->isThisJSONItemInDescendance(anItem))
1046- {
1047- return true;
1048+ if (lValue->isStructuredItem())
1049+ {
1050+ const StructuredItem* lStructuredItem =
1051+ static_cast<const StructuredItem*>(lValue);
1052+ if (lStructuredItem->isInSubtree(anItem))
1053+ {
1054+ return true;
1055+ }
1056 }
1057 }
1058 return false;
1059 }
1060-#endif // NDEBUG
1061
1062
1063 /******************************************************************************
1064@@ -799,11 +775,13 @@
1065 lIter != theContent.end();
1066 ++lIter)
1067 {
1068- if (getCollection() != NULL && (*lIter)->isJSONItem())
1069+ if (getCollection() != NULL &&
1070+ ((*lIter)->isStructuredItem()))
1071 {
1072- assert(dynamic_cast<JSONItem*>(*lIter));
1073- JSONItem* lJSONItem = static_cast<JSONItem*>(*lIter);
1074- lJSONItem->setTree(NULL);
1075+ assert(dynamic_cast<StructuredItem*>(*lIter));
1076+ StructuredItem* lStructuredItem =
1077+ static_cast<StructuredItem*>(*lIter);
1078+ lStructuredItem->setCollectionTreeInfo(NULL);
1079 }
1080 (*lIter)->removeReference();
1081 }
1082@@ -831,11 +809,12 @@
1083 {
1084 ASSERT_INVARIANT();
1085
1086- if (getCollection() != NULL && aValue->isJSONItem())
1087+ if (getCollection() != NULL && (aValue->isStructuredItem()))
1088 {
1089- assert(dynamic_cast<JSONItem*>(aValue.getp()));
1090- JSONItem* lJSONItem = static_cast<JSONItem*>(aValue.getp());
1091- lJSONItem->setTree(getTree());
1092+ assert(dynamic_cast<StructuredItem*>(aValue.getp()));
1093+ StructuredItem* lStructuredItem =
1094+ static_cast<StructuredItem*>(aValue.getp());
1095+ lStructuredItem->setCollectionTreeInfo(theCollectionInfo);
1096 }
1097
1098 aValue->addReference();
1099@@ -878,11 +857,13 @@
1100 {
1101 ASSERT_INVARIANT();
1102
1103- if (getCollection() != NULL && member->isJSONItem())
1104+ if (getCollection() != NULL &&
1105+ (member->isStructuredItem()))
1106 {
1107- assert(dynamic_cast<JSONItem*>(member.getp()));
1108- JSONItem* lJSONItem = static_cast<JSONItem*>(member.getp());
1109- lJSONItem->setTree(getTree());
1110+ assert(dynamic_cast<StructuredItem*>(member.getp()));
1111+ StructuredItem* lStructuredItem =
1112+ static_cast<StructuredItem*>(member.getp());
1113+ lStructuredItem->setCollectionTreeInfo(theCollectionInfo);
1114 }
1115
1116 member->addReference();
1117@@ -939,11 +920,13 @@
1118 {
1119 store::Item* lItem = aNewMembers[i].getp();
1120
1121- if (getCollection() != NULL && lItem->isJSONItem())
1122+ if (getCollection() != NULL &&
1123+ (lItem->isStructuredItem()))
1124 {
1125- assert(dynamic_cast<JSONItem*>(lItem));
1126- JSONItem* lJSONItem = static_cast<JSONItem*>(lItem);
1127- lJSONItem->setTree(getTree());
1128+ assert(dynamic_cast<StructuredItem*>(lItem));
1129+ StructuredItem* lStructuredItem =
1130+ static_cast<StructuredItem*>(lItem);
1131+ lStructuredItem->setCollectionTreeInfo(theCollectionInfo);
1132 }
1133
1134 lItem->addReference();
1135@@ -962,11 +945,13 @@
1136 ASSERT_INVARIANT();
1137 store::Item_t lItem = getArrayValue(aPos);
1138
1139- if (getCollection() != NULL && lItem->isJSONItem())
1140+ if (getCollection() != NULL &&
1141+ (lItem->isStructuredItem()))
1142 {
1143- assert(dynamic_cast<JSONItem*>(lItem.getp()));
1144- JSONItem* lJSONItem = static_cast<JSONItem*>(lItem.getp());
1145- lJSONItem->setTree(NULL);
1146+ assert(dynamic_cast<StructuredItem*>(lItem.getp()));
1147+ StructuredItem* lStructuredItem =
1148+ static_cast<StructuredItem*>(lItem.getp());
1149+ lStructuredItem->setCollectionTreeInfo(NULL);
1150 }
1151
1152 lItem->removeReference();
1153@@ -986,8 +971,8 @@
1154 SimpleJSONArray* lOther = dynamic_cast<SimpleJSONArray*>(anotherItem);
1155 assert(lOther);
1156 std::swap(theContent, lOther->theContent);
1157- setTree(getTree());
1158- lOther->setTree(lOther->getTree());
1159+ setCollectionTreeInfo(theCollectionInfo);
1160+ lOther->setCollectionTreeInfo(lOther->theCollectionInfo);
1161 }
1162
1163 /******************************************************************************
1164@@ -1000,26 +985,30 @@
1165 ASSERT_INVARIANT();
1166 store::Item_t lItem = getArrayValue(aPos);
1167
1168- if (getCollection() != NULL && lItem->isJSONItem())
1169+ if (getCollection() != NULL &&
1170+ (lItem->isStructuredItem()))
1171 {
1172- assert(dynamic_cast<JSONItem*>(lItem.getp()));
1173- JSONItem* lJSONItem = static_cast<JSONItem*>(lItem.getp());
1174- lJSONItem->setTree(NULL);
1175+ assert(dynamic_cast<StructuredItem*>(lItem.getp()));
1176+ StructuredItem* lStructuredItem =
1177+ static_cast<StructuredItem*>(lItem.getp());
1178+ lStructuredItem->setCollectionTreeInfo(NULL);
1179 }
1180
1181 uint64_t pos = cast(aPos) - 1;
1182
1183- if (getCollection() != NULL && value->isJSONItem())
1184+ if (getCollection() != NULL &&
1185+ (value->isStructuredItem()))
1186 {
1187- assert(dynamic_cast<JSONItem*>(value.getp()));
1188- JSONItem* lJSONItem = static_cast<JSONItem*>(value.getp());
1189- lJSONItem->setTree(getTree());
1190+ assert(dynamic_cast<StructuredItem*>(value.getp()));
1191+ StructuredItem* lStructuredItem =
1192+ static_cast<StructuredItem*>(value.getp());
1193+ lStructuredItem->setCollectionTreeInfo(theCollectionInfo);
1194 }
1195
1196 theContent[pos]->removeReference();
1197 value->addReference();
1198 theContent[pos] = value.getp();
1199-
1200+
1201 ASSERT_INVARIANT();
1202 return lItem;
1203 }
1204@@ -1028,20 +1017,20 @@
1205 /******************************************************************************
1206
1207 *******************************************************************************/
1208-void SimpleJSONArray::setTree(JSONTree* aTree)
1209+void SimpleJSONArray::setCollectionTreeInfo(CollectionTreeInfo* collectionInfo)
1210 {
1211- theTree = aTree;
1212+ theCollectionInfo = static_cast<CollectionTreeInfoWithTreeId*>(collectionInfo);
1213
1214- for (Members::const_iterator lIter = theContent.begin();
1215- lIter != theContent.end();
1216- ++lIter)
1217+ for (Members::const_iterator ite = theContent.begin();
1218+ ite != theContent.end();
1219+ ++ite)
1220 {
1221- store::Item* lValue = *lIter;
1222- if (lValue->isJSONItem())
1223+ store::Item* value = *ite;
1224+
1225+ if (value->isStructuredItem())
1226 {
1227- assert(dynamic_cast<JSONItem*>(lValue));
1228- JSONItem* lJSONItem = static_cast<JSONItem*>(lValue);
1229- lJSONItem->setTree(aTree);
1230+ StructuredItem* structuredItem = static_cast<StructuredItem*>(value);
1231+ structuredItem->setCollectionTreeInfo(collectionInfo);
1232 }
1233 }
1234 }
1235@@ -1195,9 +1184,10 @@
1236 /******************************************************************************
1237
1238 *******************************************************************************/
1239-bool SimpleJSONArray::isThisTreeOfAllDescendants(const JSONTree* aTree) const
1240+bool SimpleJSONArray::isThisTreeOfAllDescendants(
1241+ const CollectionTreeInfo* collectionInfo) const
1242 {
1243- if (getTree() != aTree)
1244+ if (theCollectionInfo != collectionInfo)
1245 {
1246 return false;
1247 }
1248@@ -1208,7 +1198,8 @@
1249 {
1250 store::Item* lValue = (*lIter);
1251 const JSONItem* lJSONItem = dynamic_cast<const JSONItem*>(lValue);
1252- if (lJSONItem != NULL && (!lJSONItem->isThisTreeOfAllDescendants(aTree)))
1253+ if (lJSONItem != NULL &&
1254+ !lJSONItem->isThisTreeOfAllDescendants(collectionInfo))
1255 {
1256 return false;
1257 }
1258@@ -1217,37 +1208,39 @@
1259 }
1260
1261
1262+#endif // NDEBUG
1263+
1264 /******************************************************************************
1265
1266 *******************************************************************************/
1267-bool SimpleJSONArray::isThisJSONItemInDescendance(const store::Item* anItem) const
1268+bool SimpleJSONArray::isInSubtree(const StructuredItem* anItem) const
1269 {
1270- if(this == anItem)
1271+ if (this == anItem)
1272 {
1273 return true;
1274 }
1275+
1276 for (Members::const_iterator lIter = theContent.begin();
1277 lIter != theContent.end();
1278 ++lIter)
1279 {
1280- const SimpleJSONObject* lObject =
1281- dynamic_cast<const SimpleJSONObject*>(*lIter);
1282- const SimpleJSONArray* lArray =
1283- dynamic_cast<const SimpleJSONArray*>(*lIter);
1284- if (lObject != NULL && lObject->isThisJSONItemInDescendance(anItem))
1285- {
1286- return true;
1287- }
1288- else if (lArray != NULL && lArray->isThisJSONItemInDescendance(anItem))
1289- {
1290- return true;
1291+ store::Item* lValue = *lIter;
1292+
1293+ if (lValue->isStructuredItem())
1294+ {
1295+ const StructuredItem* structuredItem =
1296+ static_cast<const StructuredItem*>(lValue);
1297+
1298+ if (structuredItem->isInSubtree(anItem))
1299+ {
1300+ return true;
1301+ }
1302 }
1303 }
1304+
1305 return false;
1306 }
1307
1308-#endif // NDEBUG
1309-
1310
1311 /******************************************************************************
1312
1313
1314=== modified file 'src/store/naive/json_items.h'
1315--- src/store/naive/json_items.h 2013-02-17 00:59:54 +0000
1316+++ src/store/naive/json_items.h 2013-02-21 15:32:25 +0000
1317@@ -22,11 +22,15 @@
1318 #include <zorba/config.h>
1319 #include "util/unordered_map.h"
1320
1321+#include "diagnostics/assert.h"
1322+
1323 #include "store/api/item_handle.h"
1324 #include "store/api/iterator.h"
1325
1326 #include "atomic_items.h"
1327+#include "collection_tree_info.h"
1328 #include "simple_collection.h"
1329+#include "structured_item.h"
1330
1331
1332 namespace zorba
1333@@ -40,6 +44,8 @@
1334 namespace simplestore
1335 {
1336
1337+class CollectionTreeInfoGetters;
1338+
1339 namespace json
1340 {
1341
1342@@ -84,66 +90,20 @@
1343
1344 *******************************************************************************/
1345
1346-class JSONTree
1347-{
1348-private:
1349- simplestore::Collection * theCollection;
1350- TreeId theId;
1351- JSONItem * theRoot;
1352-
1353-public:
1354- JSONTree() : theCollection(NULL), theId(), theRoot(NULL)
1355- {}
1356-
1357- ~JSONTree();
1358-
1359- simplestore::Collection* getCollection() const
1360- {
1361- return theCollection;
1362- }
1363-
1364- void setCollection(simplestore::Collection* aCollection)
1365- {
1366- theCollection = aCollection;
1367- }
1368-
1369- const TreeId& getTreeId() const
1370- {
1371- return theId;
1372- }
1373-
1374- void setTreeId(const TreeId& aId)
1375- {
1376- theId = aId;
1377- }
1378-
1379- JSONItem* getRoot() const
1380- {
1381- return theRoot;
1382- }
1383-
1384- void setRoot(JSONItem* aRoot)
1385- {
1386- theRoot = aRoot;
1387- }
1388-};
1389-
1390-
1391-/******************************************************************************
1392-
1393-*******************************************************************************/
1394-
1395-class JSONItem : public store::Item
1396-{
1397+class JSONItem : public StructuredItem
1398+{
1399+ // Used to access collection tree information.
1400+ friend class zorba::simplestore::CollectionTreeInfoGetters;
1401+
1402 protected:
1403 SYNC_CODE(mutable RCLock theRCLock;)
1404
1405- JSONTree * theTree;
1406+ CollectionTreeInfoWithTreeId * theCollectionInfo;
1407
1408 public:
1409 SYNC_CODE(RCLock* getRCLock() const { return &theRCLock; })
1410
1411- JSONItem() : store::Item(JSONIQ), theTree(NULL) {}
1412+ JSONItem() : StructuredItem(store::Item::JSONIQ), theCollectionInfo(NULL) {}
1413
1414 virtual ~JSONItem();
1415
1416@@ -151,31 +111,28 @@
1417
1418 virtual void destroy();
1419
1420- const simplestore::Collection* getCollection() const;
1421-
1422- virtual void setTree(JSONTree* aTree) = 0;
1423-
1424- JSONTree* getTree() const
1425- {
1426- return theTree;
1427- }
1428-
1429- bool isRoot() const
1430- {
1431- return theTree != NULL && (this == theTree->getRoot());
1432- }
1433-
1434- // These two functions are only to be called if in a collection.
1435- const TreeId& getTreeId() const;
1436-
1437- JSONItem* getRoot() const;
1438-
1439- void attachToCollection(Collection* aCollection, const TreeId& aTreeId);
1440+ // StructuredItem API
1441+
1442+ void attachToCollection(
1443+ Collection* aCollection,
1444+ const TreeId& aTreeId,
1445+ const xs_integer& aPosition);
1446
1447 void detachFromCollection();
1448
1449+ CollectionTreeInfo* getCollectionTreeInfo() const { return theCollectionInfo; }
1450+
1451+ void setCollectionTreeInfo(CollectionTreeInfo* collectionInfo) = 0;
1452+
1453+ long getCollectionTreeRefCount() const;
1454+
1455 // store API
1456
1457+ const store::Collection* getCollection() const
1458+ {
1459+ return (theCollectionInfo ? theCollectionInfo->getCollection() : NULL);
1460+ }
1461+
1462 virtual bool equals(
1463 const store::Item* other,
1464 long timezone = 0,
1465@@ -188,9 +145,8 @@
1466 #ifndef NDEBUG
1467 virtual void assertInvariant() const;
1468
1469- virtual bool isThisTreeOfAllDescendants(const JSONTree* aTree) const = 0;
1470-
1471- virtual bool isThisJSONItemInDescendance(const store::Item* aJSONItem) const = 0;
1472+ virtual bool isThisTreeOfAllDescendants(
1473+ const CollectionTreeInfo* collectionInfo) const = 0;
1474 #endif
1475 };
1476
1477@@ -345,21 +301,19 @@
1478 const store::Item_t& aName,
1479 const store::Item_t& aNewName);
1480
1481+ // StructuredItem API
1482+
1483+ void setCollectionTreeInfo(CollectionTreeInfo* collectionInfo);
1484+
1485+ bool isInSubtree(const StructuredItem* aJSONItem) const;
1486+
1487 virtual void swap(store::Item* anotherItem);
1488
1489- // root management
1490-
1491-protected:
1492- void setTree(JSONTree* aTree);
1493-
1494 // Invariant handling
1495-public:
1496 #ifndef NDEBUG
1497 void assertInvariant() const;
1498
1499- bool isThisTreeOfAllDescendants(const JSONTree* aTree) const;
1500-
1501- bool isThisJSONItemInDescendance(const store::Item* aJSONItem) const;
1502+ bool isThisTreeOfAllDescendants(const CollectionTreeInfo* collectionInfo) const;
1503 #endif
1504 };
1505
1506@@ -454,7 +408,7 @@
1507 {}
1508
1509 virtual ~SimpleJSONArray();
1510-
1511+
1512 // store API
1513
1514 size_t alloc_size() const;
1515@@ -506,11 +460,13 @@
1516 virtual store::Item_t
1517 replace(const xs_integer& aPos, const store::Item_t& value);
1518
1519+ // StructuredItem API
1520+
1521+ void setCollectionTreeInfo(CollectionTreeInfo* collectionInfo);
1522+
1523 virtual void swap(Item* anotherItem);
1524
1525- // root management
1526-public:
1527- void setTree(JSONTree* aTree);
1528+ bool isInSubtree(const StructuredItem* aJSONItem) const;
1529
1530 protected:
1531 void add(uint64_t pos, const std::vector<store::Item_t>& aNewMembers);
1532@@ -520,9 +476,7 @@
1533 // Invariant handling
1534 public:
1535 #ifndef NDEBUG
1536- bool isThisTreeOfAllDescendants(const JSONTree* aTree) const;
1537-
1538- bool isThisJSONItemInDescendance(const store::Item* aJSONItem) const;
1539+ bool isThisTreeOfAllDescendants(const CollectionTreeInfo* colectionInfo) const;
1540 #endif
1541 };
1542
1543
1544=== modified file 'src/store/naive/loader_dtd.cpp'
1545--- src/store/naive/loader_dtd.cpp 2013-02-13 02:18:07 +0000
1546+++ src/store/naive/loader_dtd.cpp 2013-02-21 15:32:25 +0000
1547@@ -37,7 +37,6 @@
1548 #include "loader.h"
1549 #include "simple_item_factory.h"
1550 #include "node_factory.h"
1551-
1552 #include "zorbatypes/datetime.h"
1553 #include "zorbatypes/URI.h"
1554
1555@@ -198,7 +197,7 @@
1556 if (docUri.empty())
1557 {
1558 std::ostringstream uristream;
1559- uristream << "zorba://internalDocumentURI-" << theTree->getId();
1560+ uristream << "zorba://internalDocumentURI-" << theTree->getTreeId();
1561 theDocUri = uristream.str();
1562 }
1563 else
1564@@ -796,7 +795,7 @@
1565 if (docUri.empty())
1566 {
1567 std::ostringstream uristream;
1568- uristream << "zorba://internalDocumentURI-" << theTree->getId();
1569+ uristream << "zorba://internalDocumentURI-" << theTree->getTreeId();
1570 theDocUri = uristream.str();
1571 }
1572 else
1573
1574=== modified file 'src/store/naive/loader_fast.cpp'
1575--- src/store/naive/loader_fast.cpp 2013-02-13 02:10:51 +0000
1576+++ src/store/naive/loader_fast.cpp 2013-02-21 15:32:25 +0000
1577@@ -372,7 +372,8 @@
1578 if (docUri.empty())
1579 {
1580 std::ostringstream uristream;
1581- uristream << "zorba://internalDocumentURI-" << theTree->getId();
1582+ uristream << "zorba://internalDocumentURI-" << theTree->getTreeId();
1583+
1584 theDocUri = uristream.str();
1585 }
1586 else
1587
1588=== modified file 'src/store/naive/node_items.cpp'
1589--- src/store/naive/node_items.cpp 2013-02-07 02:43:13 +0000
1590+++ src/store/naive/node_items.cpp 2013-02-21 15:32:25 +0000
1591@@ -71,9 +71,7 @@
1592 XmlTree::XmlTree()
1593 :
1594 theRefCount(0),
1595- theId(0),
1596- thePos(0),
1597- theCollection(NULL),
1598+ theCollectionInfo(NULL),
1599 theRootNode(NULL),
1600 #ifdef DATAGUIDE
1601 theDataGuideRootNode(NULL),
1602@@ -91,9 +89,8 @@
1603 XmlTree::XmlTree(XmlNode* root, const TreeId& id)
1604 :
1605 theRefCount(0),
1606- theId(id),
1607- thePos(0),
1608- theCollection(NULL),
1609+ theCollectionInfo(NULL),
1610+ theTreeId(id),
1611 theRootNode(root),
1612 #ifdef DATAGUIDE
1613 theDataGuideRootNode(NULL),
1614@@ -111,47 +108,17 @@
1615 /*******************************************************************************
1616
1617 ********************************************************************************/
1618-void XmlTree::claimedByCollection(Collection* collection)
1619-{
1620- ZORBA_ASSERT(collection != NULL);
1621- theCollection = collection;
1622-}
1623-
1624-
1625-/*******************************************************************************
1626-
1627-********************************************************************************/
1628-void XmlTree::setCollection(Collection* collection, xs_integer pos)
1629-{
1630- ZORBA_ASSERT(collection == NULL || theCollection == NULL);
1631-
1632- theCollection = collection;
1633- thePos = pos;
1634-
1635- if (collection != NULL)
1636- theId = collection->createTreeId();
1637-}
1638-
1639-
1640-/*******************************************************************************
1641-
1642-********************************************************************************/
1643-ulong XmlTree::getCollectionId() const
1644-{
1645- if (theCollection != NULL)
1646- return theCollection->getId();
1647- else
1648- return 0;
1649-}
1650-
1651-
1652-/*******************************************************************************
1653-
1654-********************************************************************************/
1655 void XmlTree::destroy() throw()
1656 {
1657 // std::cout << "Deleting Xml Tree: " << this << std::endl;
1658
1659+ // Only delete if not in a collection, or if it is the overall root.
1660+ if (theCollectionInfo != NULL &&
1661+ theCollectionInfo->getRoot() == static_cast<StructuredItem*>(getRoot()))
1662+ {
1663+ delete theCollectionInfo;
1664+ }
1665+
1666 if (theRootNode != 0)
1667 {
1668 theRootNode->destroy(false);
1669@@ -285,9 +252,56 @@
1670 }
1671 }
1672
1673-
1674 #endif // #ifndef EMBEDED_TYPE
1675
1676+/*******************************************************************************
1677+
1678+********************************************************************************/
1679+void XmlTree::setCollectionTreeInfo(CollectionTreeInfo* collectionInfo)
1680+{
1681+ // If the supplied tree information is not NULL, the existing tree info must
1682+ // be NULL.
1683+ assert(!collectionInfo || !theCollectionInfo);
1684+ // If the supplied tree information is NULL, the existing tree info must
1685+ // exist, and this node may not be the root.
1686+ assert(collectionInfo || theCollectionInfo);
1687+ assert(collectionInfo ||
1688+ theCollectionInfo->getRoot() != static_cast<StructuredItem*>(getRoot()));
1689+
1690+ theCollectionInfo = collectionInfo;
1691+}
1692+
1693+/*******************************************************************************
1694+
1695+********************************************************************************/
1696+void XmlTree::attachToCollection(
1697+ simplestore::Collection* aCollection,
1698+ const TreeId& aTreeId,
1699+ const xs_integer& aPosition)
1700+{
1701+ assert(!theCollectionInfo);
1702+
1703+ theCollectionInfo = new CollectionTreeInfo();
1704+ theCollectionInfo->setCollection(aCollection);
1705+ theCollectionInfo->setPosition(aPosition);
1706+ theCollectionInfo->setRoot(getRoot());
1707+ theTreeId = aTreeId;
1708+}
1709+
1710+/*******************************************************************************
1711+
1712+********************************************************************************/
1713+void XmlTree::detachFromCollection()
1714+{
1715+ // The tree info must exist and this XML must be the overall root.
1716+ assert(theCollectionInfo);
1717+ assert(theCollectionInfo->getRoot() == static_cast<StructuredItem*>(getRoot()));
1718+
1719+ delete theCollectionInfo;
1720+ theCollectionInfo = NULL;
1721+}
1722+
1723+
1724
1725 /////////////////////////////////////////////////////////////////////////////////
1726 // //
1727@@ -909,6 +923,55 @@
1728 GET_STORE().unregisterReferenceToDeletedNode(this);
1729 }
1730
1731+/*******************************************************************************
1732+
1733+********************************************************************************/
1734+void XmlNode::attachToCollection(
1735+ simplestore::Collection* aCollection,
1736+ const TreeId& aTreeId,
1737+ const xs_integer& aPosition)
1738+{
1739+ getTree()->attachToCollection(aCollection, aTreeId, aPosition);
1740+}
1741+
1742+/*******************************************************************************
1743+
1744+********************************************************************************/
1745+void XmlNode::detachFromCollection()
1746+{
1747+ getTree()->detachFromCollection();
1748+}
1749+
1750+/*******************************************************************************
1751+
1752+********************************************************************************/
1753+void XmlNode::setCollectionTreeInfo(CollectionTreeInfo* lTreeInfo)
1754+{
1755+ getTree()->setCollectionTreeInfo(lTreeInfo);
1756+}
1757+
1758+/*******************************************************************************
1759+
1760+********************************************************************************/
1761+long XmlNode::getCollectionTreeRefCount() const
1762+{
1763+ return getTree()->getRefCount();
1764+}
1765+
1766+/*******************************************************************************
1767+
1768+********************************************************************************/
1769+bool XmlNode::isInSubtree(const StructuredItem* anotherItem) const
1770+{
1771+ if (!anotherItem->isNode())
1772+ {
1773+ return false;
1774+ }
1775+ assert(this == getTree()->getRoot());
1776+ assert(dynamic_cast<const XmlNode*>(anotherItem));
1777+ const XmlNode* aNode = static_cast<const XmlNode*>(anotherItem);
1778+ return getTree() == aNode->getTree();
1779+}
1780
1781
1782 /////////////////////////////////////////////////////////////////////////////////
1783@@ -1327,6 +1390,7 @@
1784 ********************************************************************************/
1785 bool OrdPathNode::isAncestor(const store::Item_t& aOther) const
1786 {
1787+ assert(dynamic_cast<XmlNode*>(aOther.getp()));
1788 assert(!static_cast<XmlNode*>(aOther.getp())->isConnectorNode());
1789
1790 const OrdPathNode* lThisNode = static_cast<const OrdPathNode*>(this);
1791@@ -1353,6 +1417,7 @@
1792 ********************************************************************************/
1793 bool OrdPathNode::isFollowing(const store::Item_t& aOther) const
1794 {
1795+ assert(dynamic_cast<XmlNode*>(aOther.getp()));
1796 assert(!static_cast<XmlNode*>(aOther.getp())->isConnectorNode());
1797
1798 const OrdPathNode* lThisNode = static_cast<const OrdPathNode*>(this);
1799@@ -1370,6 +1435,7 @@
1800 ********************************************************************************/
1801 bool OrdPathNode::isDescendant(const store::Item_t& aOther) const
1802 {
1803+ assert(dynamic_cast<XmlNode*>(aOther.getp()));
1804 assert(!static_cast<XmlNode*>(aOther.getp())->isConnectorNode());
1805
1806 const OrdPathNode* lThisNode = static_cast<const OrdPathNode*>(this);
1807@@ -1387,6 +1453,7 @@
1808 ********************************************************************************/
1809 bool OrdPathNode::isPrecedingSibling(const store::Item_t& aOther) const
1810 {
1811+ assert(dynamic_cast<XmlNode*>(aOther.getp()));
1812 assert(!static_cast<XmlNode*>(aOther.getp())->isConnectorNode());
1813
1814 return isPreceding(aOther) && getParent() == aOther->getParent();
1815@@ -1398,6 +1465,7 @@
1816 ********************************************************************************/
1817 bool OrdPathNode::isPreceding(const store::Item_t& aOther) const
1818 {
1819+ assert(dynamic_cast<XmlNode*>(aOther.getp()));
1820 assert(!static_cast<XmlNode*>(aOther.getp())->isConnectorNode());
1821
1822 const OrdPathNode* lThisNode = static_cast<const OrdPathNode*>(this);
1823@@ -1415,6 +1483,7 @@
1824 ********************************************************************************/
1825 bool OrdPathNode::isChild(const store::Item_t& aOther) const
1826 {
1827+ assert(dynamic_cast<XmlNode*>(aOther.getp()));
1828 assert(!static_cast<XmlNode*>(aOther.getp())->isConnectorNode());
1829
1830 return aOther->getParent() == this;
1831@@ -1426,6 +1495,7 @@
1832 ********************************************************************************/
1833 bool OrdPathNode::isParent(const store::Item_t& aOther) const
1834 {
1835+ assert(dynamic_cast<XmlNode*>(aOther.getp()));
1836 assert(!static_cast<XmlNode*>(aOther.getp())->isConnectorNode());
1837
1838 return this->getParent() == aOther;
1839@@ -1455,6 +1525,7 @@
1840 ********************************************************************************/
1841 store::Item_t OrdPathNode::leastCommonAncestor(const store::Item_t& aOther) const
1842 {
1843+ assert(dynamic_cast<XmlNode*>(aOther.getp()));
1844 assert(!static_cast<XmlNode*>(aOther.getp())->isConnectorNode());
1845
1846 const OrdPathNode* lThisNode = static_cast<const OrdPathNode*>(this);
1847@@ -1889,7 +1960,7 @@
1848 theDocUri(docUri)
1849 {
1850 STORE_TRACE1("{\nConstructing doc node " << this << " tree = "
1851- << getTree()->getId() << ":" << getTree()
1852+ << getTreeId() << ":" << getTree()
1853 << " doc uri = " << docUri);
1854 }
1855
1856@@ -2250,7 +2321,7 @@
1857
1858 STORE_TRACE1("Constructed element node " << this << " parent = "
1859 << std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
1860- << " tree = " << getTree()->getId() << ":" << getTree()
1861+ << " tree = " << getTreeId() << ":" << getTree()
1862 << " ordpath = " << theOrdPath.show()
1863 << " name = " << theName->getStringValue()
1864 << " type = " << getType()->getStringValue());
1865@@ -3757,7 +3828,7 @@
1866
1867 STORE_TRACE1("Constructed attribute node " << this << " parent = "
1868 << std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
1869- << " tree = " << getTree()->getId() << ":" << getTree()
1870+ << " tree = " << getTreeId() << ":" << getTree()
1871 << " ordpath = " << theOrdPath.show()
1872 << " name = " << theName->getStringValue()
1873 << " value = " << getStringValue());
1874@@ -4223,7 +4294,7 @@
1875 #else
1876 STORE_TRACE1("Constructed text node " << this << " parent = "
1877 << std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
1878- << " tree = " << getTree()->getId() << ":" << getTree()
1879+ << " tree = " << getTreeId() << ":" << getTree()
1880 << " content = " << getText());
1881 #endif
1882 }
1883@@ -4940,7 +5011,7 @@
1884
1885 STORE_TRACE1("Constructed pi node " << this << " parent = "
1886 << std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
1887- << " tree = " << getTree()->getId() << ":" << getTree()
1888+ << " tree = " << getTreeId() << ":" << getTree()
1889 << " ordpath = " << theOrdPath.show() << " target = " << theTarget);
1890 }
1891
1892@@ -5100,7 +5171,7 @@
1893
1894 STORE_TRACE1("Constructed comment node " << this << " parent = "
1895 << std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
1896- << " tree = " << getTree()->getId() << ":" << getTree()
1897+ << " tree = " << getTreeId() << ":" << getTree()
1898 << " ordpath = " << theOrdPath.show() << " content = "
1899 << theContent);
1900 }
1901
1902=== modified file 'src/store/naive/node_items.h'
1903--- src/store/naive/node_items.h 2013-02-07 02:43:13 +0000
1904+++ src/store/naive/node_items.h 2013-02-21 15:32:25 +0000
1905@@ -44,6 +44,10 @@
1906 #include "store_defs.h"
1907 #include "text_node_content.h"
1908 #include "tree_id.h"
1909+#include "simple_store.h"
1910+#include "structured_item.h"
1911+#include "collection_tree_info.h"
1912+#include "collection.h"
1913
1914 // Note: whether the EMBEDED_TYPE is defined or not is done in store_defs.h
1915 #ifndef EMBEDED_TYPE
1916@@ -66,6 +70,10 @@
1917 namespace simplestore
1918 {
1919
1920+namespace json {
1921+ class JSONItem;
1922+}
1923+
1924 class AttributeNode;
1925 class CommentNode;
1926 class DocumentNode;
1927@@ -95,6 +103,8 @@
1928
1929 class Collection;
1930
1931+class CollectionTreeInfoGetters;
1932+
1933 typedef std::vector<NodeTypeInfo> TypeUndoList;
1934
1935 typedef rchandle<NsBindingsContext> NsBindingsContext_t;
1936@@ -111,38 +121,51 @@
1937
1938 /*******************************************************************************
1939
1940- theRefCount : It is the sum of theRefCounts of all the nodes belonging to
1941- this tree. Individual nodes are not destroyed when their
1942- refCount goes to 0. Instead, nodes belonging to a tree are all
1943- destroyed together when theRefCount of the tree goes to 0
1944- (i.e. when there are no refs to any of the nodes in the tree).
1945- theRCLock : Protects theRefCount
1946-
1947- theId : An internally generated id for the tree. The id uniquely
1948- identifies the tree within its containing collection (see
1949- Collection::createTreeId() method). Trees that do not
1950- belong to any collection, are considered to belong to a
1951- "virtual" collection (with collection id equal to 0), and
1952- their id is created by the SimpleStore::createId() method.
1953- theId it is guaranteed to be stable during the lifetime of
1954- the tree, but may be reused after the tree is destroyed.
1955- theId is used in building node URIs that are returned to
1956- the application. It is not meant to be used (at least not
1957- directly) to sort nodes in doc order.
1958- thePos : The position of this tree within its containing collection.
1959- After inserting/deleting one or more nodes in/from the middle
1960-
1961- theBaseUri : The base uri property of the tree's root node.
1962- theDocUri : A user provided uri for the tree (may be NULL).
1963-
1964- theCollection : The collection where this xml tree belongs to, if any. An xml
1965- tree may belong to at most one collection at a time.
1966- theRootNode : The root node of the tree.
1967-
1968- theIsValidated : True if the tree has ever undergone schema validation.
1969- theIsRecursive : True if the tree contains at least one pair of element nodes
1970- that have the same tag name and are in an ancestor-descendant
1971- relationship with each other.
1972+ Class XmlTree contains top-level information about an xml tree. Every node of
1973+ such a tree has a pointer to the associated XmlTree object.
1974+
1975+ theRefCount:
1976+ ------------
1977+ It is the sum of theRefCounts of all the nodes belonging to this tree.
1978+ Individual nodes are not destroyed when their refCount goes to 0. Instead,
1979+ nodes belonging to a tree are all destroyed together when theRefCount of
1980+ the tree goes to 0 (i.e. when there are no refs to any of the nodes in the
1981+ tree).
1982+
1983+ theRCLock:
1984+ ----------
1985+ Protects theRefCount
1986+
1987+ theTreeId:
1988+ ----------
1989+ A collection-relative id for this tree. Uniquely identifies the tree within a
1990+ collection, or if the tree does not belong to any collection, its id is unique
1991+ among all the other trees that do not belong to any collection either. NOTE:
1992+ when a tree becomes member of a colection, it gets a new id.
1993+
1994+ theCollectionInfo:
1995+ ------------------
1996+ Contains info that is relevant only if the tree belongs to a collection (see
1997+ class CollectionTreeInfo for more details).
1998+
1999+ theRootNode:
2000+ ------------
2001+ The root node of this XML tree.
2002+
2003+ theIsValidated :
2004+ ----------------
2005+ True if the tree has ever undergone schema validation.
2006+
2007+ theIsRecursive :
2008+ ----------------
2009+ True if the tree contains at least one pair of element nodes that have the
2010+ same tag name and are in an ancestor-descendant relationship with each other.
2011+
2012+ theTypesMap:
2013+ ------------
2014+
2015+ theTokens:
2016+ ----------
2017 ********************************************************************************/
2018 class XmlTree
2019 {
2020@@ -150,6 +173,9 @@
2021
2022 // make sure that only created by the factory
2023 friend class NodeFactory;
2024+
2025+ // For setting positions directly.
2026+ friend class SimpleCollection;
2027
2028 #ifndef EMBEDED_TYPE
2029 typedef NodePointerHashMap<store::Item_t> NodeTypeMap;
2030@@ -159,10 +185,9 @@
2031 mutable long theRefCount;
2032 SYNC_CODE(mutable RCLock theRCLock;)
2033
2034- TreeId theId;
2035- xs_integer thePos;
2036+ CollectionTreeInfo * theCollectionInfo;
2037
2038- Collection * theCollection;
2039+ TreeId theTreeId;
2040
2041 XmlNode * theRootNode;
2042
2043@@ -198,27 +223,41 @@
2044 long& getRefCount() { return theRefCount; }
2045
2046 SYNC_CODE(RCLock* getRCLock() const { return &theRCLock; })
2047-
2048- void setId(const TreeId& id) { theId = id; }
2049-
2050- const TreeId& getId() const { return theId; }
2051-
2052- ulong getCollectionId() const;
2053-
2054- const Collection* getCollection() const { return theCollection; }
2055-
2056-private:
2057-friend class zorba::simplestore::Collection;
2058- // Allows a collection to claim ownership of a node it already owns, but
2059- // which does not have the backpointer yet.
2060- void claimedByCollection(Collection* coll);
2061
2062-public:
2063- void setCollection(Collection* coll, xs_integer pos);
2064-
2065- void setPosition(xs_integer pos) { thePos = pos; }
2066-
2067- xs_integer getPosition() const { return thePos; }
2068+ const TreeId& getTreeId() const { return theTreeId; }
2069+
2070+ CollectionTreeInfo* getCollectionTreeInfo() const { return theCollectionInfo; }
2071+
2072+ void setCollectionTreeInfo(CollectionTreeInfo* collectionInfo);
2073+
2074+ void attachToCollection(
2075+ simplestore::Collection* aCollection,
2076+ const TreeId& aTreeId,
2077+ const xs_integer& aPosition);
2078+
2079+ void detachFromCollection();
2080+
2081+ ulong getCollectionId() const
2082+ {
2083+ return (theCollectionInfo ? theCollectionInfo->getCollection()->getId() : 0);
2084+ }
2085+
2086+ const store::Collection* getCollection() const
2087+ {
2088+ return (theCollectionInfo ? theCollectionInfo->getCollection() : NULL);
2089+ }
2090+
2091+ const xs_integer& getPosition() const
2092+ {
2093+ ZORBA_ASSERT(theCollectionInfo);
2094+ return theCollectionInfo->getPosition();
2095+ }
2096+
2097+ void setPosition(const xs_integer& pos) const
2098+ {
2099+ ZORBA_ASSERT(theCollectionInfo);
2100+ return theCollectionInfo->setPosition(pos);
2101+ }
2102
2103 XmlNode* getRoot() const { return theRootNode; }
2104
2105@@ -264,7 +303,7 @@
2106
2107 ******************************************************************************/
2108
2109-class XmlNode : public store::Item
2110+class XmlNode : public StructuredItem
2111 {
2112 friend class XmlTree;
2113 friend class NodeFactory;
2114@@ -363,7 +402,9 @@
2115 {
2116 }
2117
2118- XmlNode(store::StoreConsts::NodeKind k) : Item(), theParent(NULL)
2119+ XmlNode(store::StoreConsts::NodeKind k) :
2120+ StructuredItem(),
2121+ theParent(NULL)
2122 {
2123 theFlags = (uint32_t)k;
2124 }
2125@@ -428,7 +469,7 @@
2126 const store::Collection* getCollection() const
2127 {
2128 assert(!isConnectorNode());
2129- return reinterpret_cast<const store::Collection*>(getTree()->getCollection());
2130+ return getTree()->getCollection();
2131 }
2132
2133 virtual void getDocumentURI(zstring& uri) const
2134@@ -441,11 +482,6 @@
2135 return reinterpret_cast<store::Item*>(theParent);
2136 }
2137
2138- bool isRoot() const
2139- {
2140- return getCollection() != NULL && getParent() == NULL;
2141- }
2142-
2143 bool equals(
2144 const store::Item* other,
2145 long timezone = 0,
2146@@ -503,17 +539,9 @@
2147
2148 XmlTree* getTree() const { return (XmlTree*)theUnion.treeRCPtr; }
2149
2150- const TreeId& getTreeId() const { return getTree()->getId(); }
2151-
2152 XmlNode* getRoot() const { return getTree()->getRoot(); }
2153
2154- void setCollection(Collection* coll, xs_integer pos)
2155- {
2156- assert(!isConnectorNode());
2157- getTree()->setCollection(coll, pos);
2158- }
2159-
2160- ulong getCollectionId() const
2161+ ulong getCollectionId() const
2162 {
2163 assert(!isConnectorNode());
2164 return getTree()->getCollectionId();
2165@@ -567,6 +595,23 @@
2166 locale::iso639_1::type,
2167 bool = false ) const;
2168 #endif /* ZORBA_NO_FULL_TEXT */
2169+
2170+ //
2171+ // StructuredItem Methods
2172+ //
2173+
2174+ virtual void attachToCollection(
2175+ simplestore::Collection* aCollection,
2176+ const TreeId& aTreeId,
2177+ const xs_integer& aPosition);
2178+
2179+ virtual void detachFromCollection();
2180+
2181+ virtual void setCollectionTreeInfo(CollectionTreeInfo* collectionInfo);
2182+
2183+ virtual long getCollectionTreeRefCount() const;
2184+
2185+ virtual bool isInSubtree(const StructuredItem* anotherItem) const;
2186 };
2187
2188
2189@@ -1614,8 +1659,8 @@
2190 {
2191 if (col1 == 0)
2192 {
2193- TreeId tree1 = this->getTreeId();
2194- TreeId tree2 = other->getTreeId();
2195+ TreeId tree1 = this->getTree()->getTreeId();
2196+ TreeId tree2 = other->getTree()->getTreeId();
2197
2198 if (tree1 < tree2)
2199 return -1;
2200@@ -1664,8 +1709,8 @@
2201 {
2202 if (col1 == 0)
2203 {
2204- const TreeId& tree1 = this->getTreeId();
2205- const TreeId& tree2 = other->getTreeId();
2206+ const TreeId& tree1 = this->getTree()->getTreeId();
2207+ const TreeId& tree2 = other->getTree()->getTreeId();
2208
2209 if (tree1 < tree2)
2210 return -1;
2211
2212=== modified file 'src/store/naive/pul_primitives.cpp'
2213--- src/store/naive/pul_primitives.cpp 2013-02-03 19:01:15 +0000
2214+++ src/store/naive/pul_primitives.cpp 2013-02-21 15:32:25 +0000
2215@@ -166,7 +166,8 @@
2216
2217 if (theTarget->isNode())
2218 {
2219- static_cast<zorba::simplestore::XmlNode*>(theTarget.getp())
2220+ assert(dynamic_cast<XmlNode*>(theTarget.getp()));
2221+ static_cast<XmlNode*>(theTarget.getp())
2222 ->unregisterReferencesToDeletedSubtree();
2223 }
2224 }
2225@@ -1037,22 +1038,11 @@
2226
2227 for (uint64_t i = 0; i < size; ++i)
2228 {
2229- long lRefCount = 0;
2230 store::Item* lItem = collection->nodeAt(xs_integer(i)).getp();
2231- if (lItem->isNode())
2232- {
2233- assert(dynamic_cast<XmlNode*>(lItem));
2234- XmlNode* lNode = static_cast<XmlNode*>(lItem);
2235- lRefCount = lNode->getTree()->getRefCount();
2236-#ifdef ZORBA_WITH_JSON
2237- }
2238- else if (lItem->isJSONItem())
2239- {
2240- assert(dynamic_cast<json::JSONItem*>(lItem));
2241- json::JSONItem* lJSONItem = static_cast<json::JSONItem*>(lItem);
2242- lRefCount = lJSONItem->getRefCount();
2243-#endif
2244- }
2245+ assert(lItem->isStructuredItem());
2246+ assert(dynamic_cast<StructuredItem*>(lItem));
2247+ StructuredItem* lNode = static_cast<StructuredItem*>(lItem);
2248+ long lRefCount = lNode->getCollectionTreeRefCount();
2249
2250 if (lRefCount > 1)
2251 {
2252
2253=== modified file 'src/store/naive/simple_collection.cpp'
2254--- src/store/naive/simple_collection.cpp 2013-01-30 01:13:09 +0000
2255+++ src/store/naive/simple_collection.cpp 2013-02-21 15:32:25 +0000
2256@@ -38,13 +38,13 @@
2257
2258 ********************************************************************************/
2259 SimpleCollection::SimpleCollection(
2260- const store::Item_t& aName,
2261- const std::vector<store::Annotation_t>& aAnnotations,
2262+ const store::Item_t& name,
2263+ const std::vector<store::Annotation_t>& annotations,
2264 bool isDynamic)
2265 :
2266- theName(aName),
2267+ Collection(name),
2268 theIsDynamic(isDynamic),
2269- theAnnotations(aAnnotations)
2270+ theAnnotations(annotations)
2271 {
2272 theId = GET_STORE().createCollectionId();
2273 theTreeIdGenerator = GET_STORE().getTreeIdGeneratorFactory().createTreeGenerator(0);
2274@@ -73,69 +73,169 @@
2275
2276
2277 /*******************************************************************************
2278+
2279+********************************************************************************/
2280+void SimpleCollection::getAnnotations(
2281+ std::vector<store::Annotation_t>& annotations) const
2282+{
2283+ annotations = theAnnotations;
2284+}
2285+
2286+
2287+/*******************************************************************************
2288 Return an iterator over the nodes of this collection.
2289
2290 Note: it is allowed to have several concurrent iterators on the same collection
2291 but each iterator should be used by a single thread only.
2292 ********************************************************************************/
2293-store::Iterator_t SimpleCollection::getIterator(const xs_integer& aSkip,
2294- const zstring& aStart)
2295+store::Iterator_t SimpleCollection::getIterator(
2296+ const xs_integer& skip,
2297+ const zstring& startRef)
2298 {
2299- store::Item_t lReferencedNode;
2300- xs_integer lReferencedPosition = xs_integer::zero();
2301- if (aStart.size() != 0
2302- && (!GET_STORE().getNodeByReference(lReferencedNode, aStart)
2303- || !findNode(lReferencedNode.getp(), lReferencedPosition)))
2304+ store::Item_t startNode;
2305+ xs_integer startPos = xs_integer::zero();
2306+
2307+ if (startRef.size() != 0 &&
2308+ (!GET_STORE().getNodeByReference(startNode, startRef) ||
2309+ !findNode(startNode.getp(), startPos)))
2310 {
2311 throw ZORBA_EXCEPTION(zerr::ZSTR0066_REFERENCED_NODE_NOT_IN_COLLECTION,
2312- ERROR_PARAMS(aStart, theName->getStringValue()));
2313- }
2314-
2315- return new CollectionIter(
2316- this,
2317- aSkip + lReferencedPosition);
2318+ ERROR_PARAMS(startRef, theName->getStringValue()));
2319+ }
2320+
2321+ try
2322+ {
2323+ return new CollectionIter(this, skip + startPos);
2324+ }
2325+ catch (const std::range_error&)
2326+ {
2327+ throw ZORBA_EXCEPTION(
2328+ zerr::ZXQD0004_INVALID_PARAMETER,
2329+ ERROR_PARAMS(ZED(ZXQD0004_NOT_WITHIN_RANGE), skip)
2330+ );
2331+ }
2332+}
2333+
2334+
2335+/*******************************************************************************
2336+ Check if the tree rooted at the given node belongs to this collection. If yes,
2337+ return true and the position of the tree within the collection. Otherwise,
2338+ return false.
2339+********************************************************************************/
2340+bool SimpleCollection::findNode(const store::Item* item, xs_integer& position) const
2341+{
2342+ if (!(item->isStructuredItem()))
2343+ {
2344+ throw ZORBA_EXCEPTION(zerr::ZSTR0013_COLLECTION_ITEM_MUST_BE_STRUCTURED,
2345+ ERROR_PARAMS(getName()->getStringValue()));
2346+ }
2347+
2348+ const StructuredItem* structuredItem = static_cast<const StructuredItem*>(item);
2349+
2350+ if (structuredItem->isNode())
2351+ {
2352+ const XmlNode* node = static_cast<const XmlNode*>(item);
2353+ if (node->getTree()->getRoot() != node)
2354+ {
2355+ throw ZORBA_EXCEPTION(zerr::ZSTR0011_COLLECTION_NON_ROOT_NODE,
2356+ ERROR_PARAMS(getName()->getStringValue()));
2357+ }
2358+ }
2359+
2360+ if (theTrees.empty())
2361+ return false;
2362+
2363+ if (item->getCollection() != this)
2364+ return false;
2365+
2366+ position = structuredItem->getPosition();
2367+
2368+ csize pos = 0;
2369+ try
2370+ {
2371+ pos = to_xs_unsignedInt(position);
2372+ } catch (const std::range_error&)
2373+ {
2374+ throw ZORBA_EXCEPTION(
2375+ zerr::ZXQD0004_INVALID_PARAMETER,
2376+ ERROR_PARAMS(ZED(ZXQD0004_NOT_WITHIN_RANGE), position)
2377+ );
2378+ }
2379+
2380+ StructuredItem* collectionItem =
2381+ static_cast<StructuredItem*>(theTrees[pos].getp());
2382+
2383+ if (pos < theTrees.size() &&
2384+ collectionItem->getTreeId() == structuredItem->getTreeId())
2385+ {
2386+ return true;
2387+ }
2388+
2389+ csize numTrees = theTrees.size();
2390+
2391+ for (csize i = 0; i < numTrees; ++i)
2392+ {
2393+ // check if the nodes are the same
2394+ if (item->equals(theTrees[i]))
2395+ {
2396+ ZORBA_ASSERT(theTrees[i]->getCollection() == this);
2397+ position = i;
2398+ return true;
2399+ }
2400+ }
2401+
2402+ return false;
2403+}
2404+
2405+
2406+/*******************************************************************************
2407+ Return the node at the given position within the collection, or NULL if the
2408+ given position is >= than the number of nodes in the collection.
2409+********************************************************************************/
2410+store::Item_t SimpleCollection::nodeAt(xs_integer position)
2411+{
2412+ try
2413+ {
2414+ csize pos = to_xs_unsignedInt(position);
2415+ if (pos >= theTrees.size())
2416+ {
2417+ return NULL;
2418+ }
2419+
2420+ return theTrees[pos];
2421+ }
2422+ catch (const std::range_error&)
2423+ {
2424+ throw ZORBA_EXCEPTION(
2425+ zerr::ZXQD0004_INVALID_PARAMETER,
2426+ ERROR_PARAMS(ZED(ZXQD0004_NOT_WITHIN_RANGE), position)
2427+ );
2428+ }
2429+}
2430+
2431+
2432+/*******************************************************************************
2433+
2434+********************************************************************************/
2435+TreeId SimpleCollection::createTreeId()
2436+{
2437+ return theTreeIdGenerator->create();
2438 }
2439
2440
2441 /*******************************************************************************
2442 Insert the given node to the collection. If the node is in any collection
2443- already or if the node has a parent, this method raises an error. Otherwise,
2444- the node is inserted into the given position.
2445+ already or if the node is an xml node with a parent, this method raises an
2446+ error. Otherwise, the node is inserted into the given position.
2447 ********************************************************************************/
2448 void SimpleCollection::addNode(store::Item* item, xs_integer position)
2449 {
2450- XmlNode* node = NULL;
2451-#ifdef ZORBA_WITH_JSON
2452- json::JSONItem* lJSONItem = NULL;
2453-#endif
2454+ if (!(item->isStructuredItem()))
2455+ {
2456+ throw ZORBA_EXCEPTION(zerr::ZSTR0013_COLLECTION_ITEM_MUST_BE_STRUCTURED,
2457+ ERROR_PARAMS(getName()->getStringValue()));
2458+ }
2459
2460- if (item->isNode())
2461- {
2462- node = static_cast<XmlNode*>(item);
2463-
2464- if (node->getParent() != NULL)
2465- {
2466- throw ZORBA_EXCEPTION(zerr::ZSTR0011_COLLECTION_NON_ROOT_NODE,
2467- ERROR_PARAMS(getName()->getStringValue()));
2468- }
2469- }
2470-#ifdef ZORBA_WITH_JSON
2471- else if (item->isJSONItem())
2472- {
2473- lJSONItem = static_cast<json::JSONItem*>(item);
2474- }
2475- else
2476- {
2477- throw ZORBA_EXCEPTION(zerr::ZSTR0013_COLLECTION_ITEM_MUST_BE_STRUCTURED,
2478- ERROR_PARAMS(getName()->getStringValue()));
2479- }
2480-#else
2481- else
2482- {
2483- throw ZORBA_EXCEPTION(zerr::ZSTR0012_COLLECTION_ITEM_MUST_BE_A_NODE,
2484- ERROR_PARAMS(getName()->getStringValue()));
2485- }
2486-#endif
2487 if (item->getCollection() != NULL)
2488 {
2489 throw ZORBA_EXCEPTION(zerr::ZSTR0010_COLLECTION_NODE_ALREADY_IN_COLLECTION,
2490@@ -143,35 +243,54 @@
2491 item->getCollection()->getName()->getStringValue()));
2492 }
2493
2494- xs_long lPosition = to_xs_long(position);
2495- xs_integer pos = xs_integer(0);
2496-
2497- SYNC_CODE(AutoLatch lock(theLatch, Latch::WRITE););
2498-
2499- if (lPosition < 0 || to_xs_unsignedLong(position) >= theXmlTrees.size())
2500- {
2501- pos = theXmlTrees.size();
2502- theXmlTrees.push_back(item);
2503- }
2504- else
2505- {
2506- theXmlTrees.insert(theXmlTrees.begin() + lPosition, item);
2507- }
2508-
2509-#ifdef ZORBA_WITH_JSON
2510- if (lJSONItem)
2511- lJSONItem->attachToCollection(this, createTreeId());
2512- else
2513-#endif
2514- node->setCollection(this, pos);
2515+ StructuredItem* structuredItem = static_cast<StructuredItem*>(item);
2516+
2517+ if (structuredItem->isNode())
2518+ {
2519+ XmlNode* node = static_cast<XmlNode*>(item);
2520+ if (node->getRoot() != node)
2521+ {
2522+ throw ZORBA_EXCEPTION(zerr::ZSTR0011_COLLECTION_NON_ROOT_NODE,
2523+ ERROR_PARAMS(getName()->getStringValue()));
2524+ }
2525+ }
2526+
2527+ try
2528+ {
2529+ xs_long pos = to_xs_long(position);
2530+ SYNC_CODE(AutoLatch lock(theLatch, Latch::WRITE););
2531+
2532+ if (pos < 0 || to_xs_unsignedLong(position) >= theTrees.size())
2533+ {
2534+ theTrees.push_back(item);
2535+
2536+ structuredItem->attachToCollection(this,
2537+ createTreeId(),
2538+ xs_integer(theTrees.size()));
2539+ }
2540+ else
2541+ {
2542+ theTrees.insert(theTrees.begin() + pos, item);
2543+
2544+ structuredItem->attachToCollection(this, createTreeId(), position);
2545+ }
2546+ }
2547+ catch (const std::range_error&)
2548+ {
2549+ throw ZORBA_EXCEPTION(
2550+ zerr::ZXQD0004_INVALID_PARAMETER,
2551+ ERROR_PARAMS(ZED(ZXQD0004_NOT_WITHIN_RANGE), position)
2552+ );
2553+ }
2554+
2555 }
2556
2557
2558 /*******************************************************************************
2559 Insert the given nodes to the collection before or after the given target node.
2560- If any of the nodes is not a root node or is in any collection already, this
2561- method raises an error. The moethod returns the position occupied by the first
2562- new node after the insertion is done.
2563+ If any of the nodes is a non root xml node or is in any collection already,
2564+ this method raises an error. The moethod returns the position occupied by the
2565+ first new node after the insertion is done.
2566 ********************************************************************************/
2567 xs_integer SimpleCollection::addNodes(
2568 std::vector<store::Item_t>& items,
2569@@ -189,87 +308,78 @@
2570 ERROR_PARAMS(theName->getStringValue()));
2571 }
2572
2573- csize targetPos = to_xs_unsignedInt(pos);
2574+ csize targetPos = 0;
2575+ try {
2576+ targetPos = to_xs_unsignedInt(pos);
2577+ }
2578+ catch (const std::range_error&)
2579+ {
2580+ throw ZORBA_EXCEPTION(
2581+ zerr::ZXQD0004_INVALID_PARAMETER,
2582+ ERROR_PARAMS(ZED(ZXQD0004_NOT_WITHIN_RANGE), pos)
2583+ );
2584+ }
2585
2586 if (!before)
2587 {
2588 ++targetPos;
2589 }
2590
2591- csize numNodes = theXmlTrees.size();
2592+ csize numNodes = theTrees.size();
2593 csize numNewNodes = items.size();
2594
2595 for (csize i = 0; i < numNewNodes; ++i)
2596 {
2597 store::Item* item = items[i].getp();
2598
2599- XmlNode* node = NULL;
2600-#ifdef ZORBA_WITH_JSON
2601- json::JSONItem* lJSONItem = NULL;
2602-#endif
2603-
2604- if (item->isNode())
2605- {
2606- node = static_cast<XmlNode*>(item);
2607-
2608- if (node->getParent() != NULL)
2609- {
2610- throw ZORBA_EXCEPTION(zerr::ZSTR0011_COLLECTION_NON_ROOT_NODE,
2611- ERROR_PARAMS(getName()->getStringValue()));
2612- }
2613- }
2614-#ifdef ZORBA_WITH_JSON
2615- else if (item->isJSONItem())
2616- {
2617- lJSONItem = static_cast<json::JSONItem*>(item);
2618- }
2619- else
2620+ if (!(item->isStructuredItem()))
2621 {
2622 throw ZORBA_EXCEPTION(zerr::ZSTR0013_COLLECTION_ITEM_MUST_BE_STRUCTURED,
2623 ERROR_PARAMS(getName()->getStringValue()));
2624 }
2625-#else
2626- else
2627- {
2628- throw ZORBA_EXCEPTION(zerr::ZSTR0012_COLLECTION_ITEM_MUST_BE_A_NODE,
2629- ERROR_PARAMS(getName()->getStringValue()));
2630- }
2631-#endif
2632
2633 if (item->getCollection() != NULL)
2634 {
2635 throw ZORBA_EXCEPTION(zerr::ZSTR0010_COLLECTION_NODE_ALREADY_IN_COLLECTION,
2636 ERROR_PARAMS(getName()->getStringValue(),
2637- node->getCollection()->getName()->getStringValue()));
2638+ item->getCollection()->getName()->getStringValue()));
2639+ }
2640+
2641+ StructuredItem* structuredItem = static_cast<StructuredItem*>(item);
2642+
2643+ if (structuredItem->isNode())
2644+ {
2645+ XmlNode* node = static_cast<XmlNode*>(item);
2646+
2647+ if (node->getRoot() != node)
2648+ {
2649+ throw ZORBA_EXCEPTION(zerr::ZSTR0011_COLLECTION_NON_ROOT_NODE,
2650+ ERROR_PARAMS(getName()->getStringValue()));
2651+ }
2652 }
2653
2654 pos = targetPos + i;
2655
2656-#ifdef ZORBA_WITH_JSON
2657- if (lJSONItem)
2658- lJSONItem->attachToCollection(this, createTreeId());
2659- else
2660-#endif
2661- node->setCollection(this, pos);
2662+ structuredItem->attachToCollection(this, createTreeId(), pos);
2663 } // for each new node
2664
2665- theXmlTrees.resize(numNodes + numNewNodes);
2666+ theTrees.resize(numNodes + numNewNodes);
2667
2668 if (targetPos < numNodes)
2669 {
2670- memmove(&theXmlTrees[targetPos + numNewNodes],
2671- &theXmlTrees[targetPos],
2672+ memmove(&theTrees[targetPos + numNewNodes],
2673+ &theTrees[targetPos],
2674 (numNodes-targetPos) * sizeof(store::Item_t));
2675 }
2676
2677 for (csize i = targetPos; i < targetPos + numNewNodes; ++i)
2678 {
2679- theXmlTrees[i].setNull();
2680+ theTrees[i].setNull();
2681 }
2682
2683 for (csize i = 0; i < numNewNodes; ++i)
2684 {
2685- theXmlTrees[targetPos + i].transfer(items[i]);
2686+ theTrees[targetPos + i].transfer(items[i]);
2687 }
2688
2689 return xs_integer(targetPos);
2690@@ -283,32 +393,11 @@
2691 ********************************************************************************/
2692 bool SimpleCollection::removeNode(store::Item* item, xs_integer& position)
2693 {
2694- XmlNode* node = NULL;
2695-#ifdef ZORBA_WITH_JSON
2696- json::JSONItem* lJSONItem = NULL;
2697-#endif
2698-
2699- if (item->isNode())
2700- {
2701- node = static_cast<XmlNode*>(item);
2702- }
2703-#ifdef ZORBA_WITH_JSON
2704- else if (item->isJSONItem())
2705- {
2706- lJSONItem = static_cast<json::JSONItem*>(item);
2707- }
2708- else
2709+ if (!(item->isStructuredItem()))
2710 {
2711 throw ZORBA_EXCEPTION(zerr::ZSTR0013_COLLECTION_ITEM_MUST_BE_STRUCTURED,
2712 ERROR_PARAMS(getName()->getStringValue()));
2713 }
2714-#else
2715- else
2716- {
2717- throw ZORBA_EXCEPTION(zerr::ZSTR0012_COLLECTION_ITEM_MUST_BE_A_NODE,
2718- ERROR_PARAMS(getName()->getStringValue()));
2719- }
2720-#endif
2721
2722 SYNC_CODE(AutoLatch lock(theLatch, Latch::WRITE);)
2723
2724@@ -318,18 +407,23 @@
2725 {
2726 ZORBA_ASSERT(item->getCollection() == this);
2727
2728- xs_integer const &zero = xs_integer::zero();
2729-
2730-#ifdef ZORBA_WITH_JSON
2731- if (lJSONItem)
2732- lJSONItem->detachFromCollection();
2733- else
2734-#endif
2735- node->setCollection(NULL, zero);
2736-
2737- csize pos = to_xs_unsignedInt(position);
2738- theXmlTrees.erase(theXmlTrees.begin() + pos);
2739- return true;
2740+ StructuredItem* structuredItem = static_cast<StructuredItem*>(item);
2741+
2742+ structuredItem->detachFromCollection();
2743+
2744+ try
2745+ {
2746+ csize pos = to_xs_unsignedInt(position);
2747+ theTrees.erase(theTrees.begin() + pos);
2748+ return true;
2749+ }
2750+ catch (const std::range_error&)
2751+ {
2752+ throw ZORBA_EXCEPTION(
2753+ zerr::ZXQD0004_INVALID_PARAMETER,
2754+ ERROR_PARAMS(ZED(ZXQD0004_NOT_WITHIN_RANGE), position)
2755+ );
2756+ }
2757 }
2758 else
2759 {
2760@@ -347,38 +441,33 @@
2761 {
2762 SYNC_CODE(AutoLatch lock(theLatch, Latch::WRITE);)
2763
2764- std::size_t pos = to_xs_unsignedInt(position);
2765+ std::size_t pos = 0;
2766+ try {
2767+ pos = to_xs_unsignedInt(position);
2768+ }
2769+ catch (const std::range_error&)
2770+ {
2771+ throw ZORBA_EXCEPTION(
2772+ zerr::ZXQD0004_INVALID_PARAMETER,
2773+ ERROR_PARAMS(ZED(ZXQD0004_NOT_WITHIN_RANGE), position)
2774+ );
2775+ }
2776
2777- if (pos >= theXmlTrees.size())
2778+ if (pos >= theTrees.size())
2779 {
2780 return false;
2781 }
2782 else
2783 {
2784- store::Item* item = theXmlTrees[pos].getp();
2785+ store::Item* item = theTrees[pos].getp();
2786
2787 ZORBA_ASSERT(item->getCollection() == this);
2788-
2789- xs_integer const &zero = xs_integer::zero();
2790-
2791- if (item->isNode())
2792- {
2793- XmlNode* node = static_cast<XmlNode*>(item);
2794- node->setCollection(NULL, zero);
2795- }
2796-#ifdef ZORBA_WITH_JSON
2797- else if (item->isJSONItem())
2798- {
2799- json::JSONItem* lJSONItem = static_cast<json::JSONItem*>(item);
2800- lJSONItem->detachFromCollection();
2801- }
2802-#endif
2803- else
2804- {
2805- ZORBA_ASSERT(false);
2806- }
2807-
2808- theXmlTrees.erase(theXmlTrees.begin() + pos);
2809+ ZORBA_ASSERT(item->isStructuredItem());
2810+
2811+ StructuredItem* structuredItem = static_cast<StructuredItem*>(item);
2812+ structuredItem->detachFromCollection();
2813+
2814+ theTrees.erase(theTrees.begin() + pos);
2815 return true;
2816 }
2817 }
2818@@ -387,54 +476,61 @@
2819 /*******************************************************************************
2820 Remove a given number of trees starting with the tree at the given position.
2821 If the given number is 0 or the given position is >= than the number of trees
2822- in the collection, this mothod is a noop. The method returns the number of
2823+ in the collection, this method is a noop. The method returns the number of
2824 trees that are actually deleted.
2825 ********************************************************************************/
2826 xs_integer SimpleCollection::removeNodes(xs_integer position, xs_integer numNodes)
2827 {
2828 SYNC_CODE(AutoLatch lock(theLatch, Latch::WRITE);)
2829
2830- csize pos = to_xs_unsignedInt(position);
2831- csize num = to_xs_unsignedInt(numNodes);
2832+ csize pos, num;
2833+ try
2834+ {
2835+ pos = to_xs_unsignedInt(position);
2836+ }
2837+ catch (const std::range_error&)
2838+ {
2839+ throw ZORBA_EXCEPTION(
2840+ zerr::ZXQD0004_INVALID_PARAMETER,
2841+ ERROR_PARAMS(ZED(ZXQD0004_NOT_WITHIN_RANGE), position)
2842+ );
2843+ }
2844+ try
2845+ {
2846+ num = to_xs_unsignedInt(numNodes);
2847+ }
2848+ catch (const std::range_error&)
2849+ {
2850+ throw ZORBA_EXCEPTION(
2851+ zerr::ZXQD0004_INVALID_PARAMETER,
2852+ ERROR_PARAMS(ZED(ZXQD0004_NOT_WITHIN_RANGE), numNodes)
2853+ );
2854+ }
2855
2856- if (num == 0 || pos >= theXmlTrees.size())
2857+ if (num == 0 || pos >= theTrees.size())
2858 {
2859 return xs_integer::zero();
2860 }
2861 else
2862 {
2863- uint64_t last = pos + num;
2864- if (last > theXmlTrees.size())
2865+ csize last = pos + num;
2866+
2867+ if (last > theTrees.size())
2868 {
2869- last = theXmlTrees.size();
2870+ last = theTrees.size();
2871 }
2872
2873- xs_integer const &zero = xs_integer::zero();
2874-
2875 for (csize i = pos; i < last; ++i)
2876- {
2877- store::Item* item = theXmlTrees[pos].getp();
2878+ {
2879+ store::Item* item = theTrees[pos].getp();
2880
2881 ZORBA_ASSERT(item->getCollection() == this);
2882-
2883- if (item->isNode())
2884- {
2885- XmlNode* node = static_cast<XmlNode*>(item);
2886- node->setCollection(NULL, zero);
2887- }
2888-#ifdef ZORBA_WITH_JSON
2889- else if (item->isJSONItem())
2890- {
2891- json::JSONItem* lJSONItem = static_cast<json::JSONItem*>(item);
2892- lJSONItem->detachFromCollection();
2893- }
2894-#endif
2895- else
2896- {
2897- ZORBA_ASSERT(false);
2898- }
2899-
2900- theXmlTrees.erase(theXmlTrees.begin() + pos);
2901+ ZORBA_ASSERT(item->isStructuredItem());
2902+
2903+ StructuredItem* structuredItem = static_cast<StructuredItem*>(item);
2904+ structuredItem->detachFromCollection();
2905+
2906+ theTrees.erase(theTrees.begin() + pos);
2907 }
2908
2909 return xs_integer(last - pos);
2910@@ -443,115 +539,26 @@
2911
2912
2913 /*******************************************************************************
2914- * Remove all the nodes from the collection
2915+ Remove all the nodes from the collection
2916 ********************************************************************************/
2917 void SimpleCollection::removeAll()
2918 {
2919 SYNC_CODE(AutoLatch lock(theLatch, Latch::WRITE);)
2920
2921- theXmlTrees.clear();
2922-}
2923-
2924-
2925-/*******************************************************************************
2926- Return the node at the given position within the collection, or NULL if the
2927- given position is >= than the number of nodes in the collection.
2928-********************************************************************************/
2929-store::Item_t SimpleCollection::nodeAt(xs_integer position)
2930-{
2931- csize pos = to_xs_unsignedInt(position);
2932- if (pos >= theXmlTrees.size())
2933- {
2934- return NULL;
2935- }
2936-
2937- return theXmlTrees[pos];
2938-}
2939-
2940-
2941-/*******************************************************************************
2942- Check if the tree rooted at the given node belongs to this collection. If yes,
2943- return true and the position of the tree within the collection. Otherwise,
2944- return false.
2945-********************************************************************************/
2946-bool SimpleCollection::findNode(const store::Item* item, xs_integer& position) const
2947-{
2948- const XmlNode* node = NULL;
2949-
2950- if (item->isNode())
2951- {
2952- node = static_cast<const XmlNode*>(item);
2953-
2954- if (node->getParent() != NULL)
2955- {
2956- throw ZORBA_EXCEPTION(zerr::ZSTR0011_COLLECTION_NON_ROOT_NODE,
2957- ERROR_PARAMS(getName()->getStringValue()));
2958- }
2959- }
2960-#ifdef ZORBA_WITH_JSON
2961- else if (item->isJSONObject())
2962- {
2963- }
2964- else if (item->isJSONArray())
2965- {
2966- }
2967- else
2968- {
2969- throw ZORBA_EXCEPTION(zerr::ZSTR0013_COLLECTION_ITEM_MUST_BE_STRUCTURED,
2970- ERROR_PARAMS(getName()->getStringValue()));
2971- }
2972-#else
2973- else
2974- {
2975- throw ZORBA_EXCEPTION(zerr::ZSTR0012_COLLECTION_ITEM_MUST_BE_A_NODE,
2976- ERROR_PARAMS(getName()->getStringValue()));
2977- }
2978-#endif
2979-
2980- if (theXmlTrees.empty())
2981- return false;
2982-
2983- if (item->getCollection() != this)
2984- return false;
2985-
2986- if (node)
2987- {
2988- position = node->getTree()->getPosition();
2989-
2990- csize pos = to_xs_unsignedInt(position);
2991-
2992- if (pos < theXmlTrees.size() &&
2993- theXmlTrees[pos]->isNode() &&
2994- BASE_NODE(theXmlTrees[pos])->getTreeId() == node->getTreeId())
2995- {
2996- return true;
2997- }
2998- }
2999-
3000- csize numTrees = theXmlTrees.size();
3001+ csize numTrees = theTrees.size();
3002
3003 for (csize i = 0; i < numTrees; ++i)
3004 {
3005- // check if the nodes are the same
3006- if (item->equals(theXmlTrees[i]))
3007- {
3008- ZORBA_ASSERT(theXmlTrees[i]->getCollection() == this);
3009- position = i;
3010- return true;
3011- }
3012+ store::Item* item = theTrees[i].getp();
3013+
3014+ ZORBA_ASSERT(item->getCollection() == this);
3015+ ZORBA_ASSERT(item->isStructuredItem());
3016+
3017+ StructuredItem* structuredItem = static_cast<StructuredItem*>(item);
3018+ structuredItem->detachFromCollection();
3019 }
3020
3021- return false;
3022-}
3023-
3024-
3025-/*******************************************************************************
3026-
3027-********************************************************************************/
3028-void SimpleCollection::getAnnotations(
3029- std::vector<store::Annotation_t>& annotations) const
3030-{
3031- annotations = theAnnotations;
3032+ theTrees.clear();
3033 }
3034
3035
3036@@ -560,16 +567,11 @@
3037 ********************************************************************************/
3038 void SimpleCollection::adjustTreePositions()
3039 {
3040- csize numTrees = theXmlTrees.size();
3041+ csize numTrees = theTrees.size();
3042
3043 for (csize i = 0; i < numTrees; ++i)
3044 {
3045-#ifdef ZORBA_WITH_JSON
3046- if (theXmlTrees[i]->isNode())
3047- BASE_NODE(theXmlTrees[i])->getTree()->setPosition(xs_integer(i));
3048-#else
3049- BASE_NODE(theXmlTrees[i])->getTree()->setPosition(xs_integer(i));
3050-#endif
3051+ static_cast<StructuredItem*>(theTrees[i].getp())->setPosition(xs_integer(i));
3052 }
3053 }
3054
3055@@ -577,22 +579,13 @@
3056 /*******************************************************************************
3057
3058 ********************************************************************************/
3059-TreeId SimpleCollection::createTreeId()
3060-{
3061- return theTreeIdGenerator->create();
3062-}
3063-
3064-
3065-/*******************************************************************************
3066-
3067-********************************************************************************/
3068 SimpleCollection::CollectionIter::CollectionIter(
3069 SimpleCollection* collection,
3070- const xs_integer& aSkip)
3071+ const xs_integer& skip)
3072 :
3073 theCollection(collection),
3074 theHaveLock(false),
3075- theSkip(aSkip)
3076+ theSkip(to_xs_unsignedLong(skip))
3077 {
3078 }
3079
3080@@ -607,6 +600,9 @@
3081 }
3082
3083
3084+/*******************************************************************************
3085+
3086+********************************************************************************/
3087 void SimpleCollection::CollectionIter::skip()
3088 {
3089 // skip by position
3090@@ -617,7 +613,7 @@
3091 }
3092 else
3093 {
3094- theIterator += to_xs_long(theSkip);
3095+ theIterator += theSkip;
3096 }
3097 }
3098
3099@@ -630,8 +626,8 @@
3100 SYNC_CODE(theCollection->theLatch.rlock();)
3101 theHaveLock = true;
3102
3103- theIterator = theCollection->theXmlTrees.begin();
3104- theEnd = theCollection->theXmlTrees.end();
3105+ theIterator = theCollection->theTrees.begin();
3106+ theEnd = theCollection->theTrees.end();
3107 skip();
3108 }
3109
3110@@ -665,8 +661,8 @@
3111 ********************************************************************************/
3112 void SimpleCollection::CollectionIter::reset()
3113 {
3114- theIterator = theCollection->theXmlTrees.begin();
3115- theEnd = theCollection->theXmlTrees.end();
3116+ theIterator = theCollection->theTrees.begin();
3117+ theEnd = theCollection->theTrees.end();
3118 skip();
3119 }
3120
3121
3122=== modified file 'src/store/naive/simple_collection.h'
3123--- src/store/naive/simple_collection.h 2013-01-30 01:13:09 +0000
3124+++ src/store/naive/simple_collection.h 2013-02-21 15:32:25 +0000
3125@@ -33,13 +33,42 @@
3126
3127
3128 /*******************************************************************************
3129- theId : An internally generated unique id.
3130- theName : The user provided qname of the collection.
3131- theXmlTrees : The set of root nodes comprising this collection. Implemented
3132- as vector of rchandles to nodes.
3133- theTreeCounter : Incremented every time a new tree is added to the collection.
3134- The current value of the counter is then assigned as the id
3135- the new tree.
3136+ theId:
3137+ ------
3138+ An internally generated unique id for the collection.
3139+
3140+ theName:
3141+ --------
3142+ The user provided qname of the collection (inherited from simplestore::Collection).
3143+
3144+ theIsDynamic:
3145+ -------------
3146+ Whether the collection is dynamic or not. Static (ie, non-dynamic) collections
3147+ must be declared in the static context to be usable, whereas dynamic ones do
3148+ not have any declarations. As far as the store is concerned, this property
3149+ is used only for naming purposes: a static and a dynamic collection may have
3150+ the same name, so the isDynamic property is used to resolve such name conflicts.
3151+
3152+ theTrees:
3153+ ------------
3154+ The root nodes of the XML and/or JSON trees that comprise this collection.
3155+
3156+ theTreeIdGenerator:
3157+ -------------------
3158+ A generator of tree ids for the trees that belong to this collection. The
3159+ generated tree ids are unique within the collection. Every time a tree is
3160+ added to the collection it is assigned a new tree id that is generated by
3161+ this generator.
3162+
3163+ theAnnotations:
3164+ ---------------
3165+ The properties of the collection. For static collections, the values of these
3166+ properties are specified by the user in the collection declaration. Dynamic
3167+ collections use pre-determined default values.
3168+
3169+ theLatch:
3170+ ---------
3171+ Synchronizes concurrent accesses to the collection.
3172 ********************************************************************************/
3173 class SimpleCollection : public Collection
3174 {
3175@@ -54,7 +83,7 @@
3176 checked_vector<store::Item_t>::iterator theIterator;
3177 checked_vector<store::Item_t>::iterator theEnd;
3178 bool theHaveLock;
3179- xs_integer theSkip;
3180+ csize theSkip;
3181
3182 public:
3183 CollectionIter(SimpleCollection* collection, const xs_integer& skip);
3184@@ -65,6 +94,7 @@
3185 bool next(store::Item_t& result);
3186 void reset();
3187 void close();
3188+
3189 private:
3190 void skip();
3191 };
3192@@ -72,8 +102,9 @@
3193
3194 protected:
3195 ulong theId;
3196- store::Item_t theName;
3197- checked_vector<store::Item_t> theXmlTrees;
3198+
3199+ checked_vector<store::Item_t> theTrees;
3200+
3201 bool theIsDynamic;
3202
3203 TreeIdGenerator * theTreeIdGenerator;
3204@@ -82,36 +113,44 @@
3205
3206 SYNC_CODE(Latch theLatch;)
3207
3208+protected:
3209 // default constructor added in order to allow subclasses to instantiate
3210 // a collection without name
3211 SimpleCollection();
3212
3213 public:
3214 SimpleCollection(
3215- const store::Item_t& aName,
3216+ const store::Item_t& name,
3217 const std::vector<store::Annotation_t>& annotations,
3218 bool isDynamic = false);
3219
3220 virtual ~SimpleCollection();
3221
3222- /********************** All these methods implement the **********************
3223- ***************** zorba::simplestore::Collection interface ******************/
3224-
3225- ulong getId() const { return theId; }
3226+ //
3227+ // Store API methods
3228+ //
3229
3230 const store::Item* getName() const { return theName.getp(); }
3231
3232- xs_integer size() const { return xs_integer( theXmlTrees.size() ); }
3233+ xs_integer size() const { return xs_integer( theTrees.size() ); }
3234
3235 bool isDynamic() const { return theIsDynamic; }
3236
3237 void getAnnotations(std::vector<store::Annotation_t>& annotations) const;
3238
3239+ store::Iterator_t getIterator(const xs_integer& skip, const zstring& start);
3240+
3241+ bool findNode(const store::Item* node, xs_integer& position) const;
3242+
3243+ store::Item_t nodeAt(xs_integer position);
3244+
3245+ //
3246+ // simplestore methods
3247+ //
3248+ ulong getId() const { return theId; }
3249+
3250 TreeId createTreeId();
3251
3252- store::Iterator_t getIterator(const xs_integer& aSkip,
3253- const zstring& aStart);
3254-
3255 void addNode(store::Item* node, xs_integer position = xs_integer(-1));
3256
3257 xs_integer addNodes(
3258@@ -123,14 +162,10 @@
3259
3260 bool removeNode(xs_integer position);
3261
3262+ xs_integer removeNodes(xs_integer position, xs_integer num);
3263+
3264 void removeAll();
3265
3266- xs_integer removeNodes(xs_integer position, xs_integer num);
3267-
3268- bool findNode(const store::Item* node, xs_integer& position) const;
3269-
3270- store::Item_t nodeAt(xs_integer position);
3271-
3272 void adjustTreePositions();
3273 };
3274
3275
3276=== modified file 'src/store/naive/simple_collection_set.h'
3277--- src/store/naive/simple_collection_set.h 2013-01-22 18:43:03 +0000
3278+++ src/store/naive/simple_collection_set.h 2013-02-21 15:32:25 +0000
3279@@ -45,23 +45,18 @@
3280 virtual
3281 ~SimpleCollectionSet();
3282
3283- virtual void
3284- clear();
3285-
3286- virtual bool
3287- insert(const store::Item* aName, store::Collection_t& aCollection);
3288-
3289- virtual bool
3290- get(
3291- const zorba::store::Item* aName,
3292- store::Collection_t& aCollection,
3293+ virtual void clear();
3294+
3295+ virtual bool insert(const store::Item* name, store::Collection_t& collection);
3296+
3297+ virtual bool get(
3298+ const zorba::store::Item* name,
3299+ store::Collection_t& collection,
3300 bool isDynamic);
3301
3302- virtual bool
3303- remove(const store::Item* name, bool isDynamic);
3304+ virtual bool remove(const store::Item* name, bool isDynamic);
3305
3306- virtual zorba::store::Iterator_t
3307- names(bool isDynamic);
3308+ virtual zorba::store::Iterator_t names(bool isDynamic);
3309 };
3310
3311
3312
3313=== modified file 'src/store/naive/simple_item_factory.cpp'
3314--- src/store/naive/simple_item_factory.cpp 2013-02-12 04:20:23 +0000
3315+++ src/store/naive/simple_item_factory.cpp 2013-02-21 15:32:25 +0000
3316@@ -2159,7 +2159,7 @@
3317
3318 while (source->next(item))
3319 {
3320- if (copymode.theDoCopy && (item->isNode() || item->isJSONItem()))
3321+ if (copymode.theDoCopy && (item->isStructuredItem()))
3322 item = item->copy(NULL, copymode);
3323
3324 array->push_back(item);
3325
3326=== modified file 'src/store/naive/simple_pul.cpp'
3327--- src/store/naive/simple_pul.cpp 2013-01-17 04:43:05 +0000
3328+++ src/store/naive/simple_pul.cpp 2013-02-21 15:32:25 +0000
3329@@ -170,32 +170,20 @@
3330
3331 #ifdef ZORBA_WITH_JSON
3332 assert(target->isNode()
3333- || target->isJSONObject()
3334- || target->isJSONArray());
3335+ || target->isJSONItem());
3336 #else
3337 assert(target->isNode());
3338 #endif
3339
3340- const store::Collection* lCollection;
3341-
3342- if (target->isNode())
3343- {
3344- assert(dynamic_cast<const XmlNode*>(target));
3345- const XmlNode* lNode = static_cast<const XmlNode*>(target);
3346- lCollection = lNode->getCollection();
3347-#ifdef ZORBA_WITH_JSON
3348- }
3349- else if (target->isJSONItem())
3350- {
3351- assert(dynamic_cast<const json::JSONItem*>(target));
3352- const json::JSONItem* lJSONItem = static_cast<const json::JSONItem*>(target);
3353- lCollection = lJSONItem->getCollection();
3354-#endif
3355- }
3356+ assert(dynamic_cast<const StructuredItem*>(target));
3357+ const StructuredItem* lStructuredItem =
3358+ static_cast<const StructuredItem*>(target);
3359+ const store::Collection* lCollection = lStructuredItem->getCollection();
3360
3361 if (lCollection != NULL)
3362 {
3363- collName = static_cast<const QNameItem*>(lCollection->getName())->getNormalized();
3364+ collName = static_cast<const QNameItem*>(
3365+ lCollection->getName())->getNormalized();
3366
3367 if (collName == theLastCollection)
3368 return theLastPul;
3369@@ -2298,45 +2286,21 @@
3370 for (; it != end; ++it)
3371 {
3372 zorba::store::Item* lItem = (*it).first;
3373- if (lItem->isNode())
3374- {
3375- assert(dynamic_cast<const XmlNode*>(lItem));
3376- const XmlNode* lNode = static_cast<const XmlNode*>(lItem);
3377- for (csize i = 0; i < numRoots; i++)
3378- {
3379- if (rootNodes[i]->isNode())
3380- {
3381- assert(dynamic_cast<const XmlNode*>(rootNodes[i]));
3382- XmlNode* lRootNode = static_cast<XmlNode*>(rootNodes[i]);
3383-
3384- if (lNode->getTree() == lRootNode->getTree())
3385- {
3386- found = true;
3387- break;
3388- }
3389- }
3390- }
3391-#ifdef ZORBA_WITH_JSON
3392- }
3393- else if (lItem->isJSONItem())
3394- {
3395- assert(dynamic_cast<const json::JSONItem*>(lItem));
3396- const json::JSONItem* lJSONItem = static_cast<const json::JSONItem*>(lItem);
3397- for (csize i = 0; i < numRoots; i++)
3398- {
3399- if (rootNodes[i]->isJSONItem())
3400- {
3401- assert(dynamic_cast<const json::JSONItem*>(rootNodes[i]));
3402- json::JSONItem* lRootJSONItem = static_cast<json::JSONItem*>(rootNodes[i]);
3403-
3404- if (lJSONItem->getTree() == lRootJSONItem->getTree())
3405- {
3406- found = true;
3407- break;
3408- }
3409- }
3410- }
3411-#endif
3412+ assert(dynamic_cast<const StructuredItem*>(lItem));
3413+ const StructuredItem* lStructuredItem =
3414+ static_cast<const StructuredItem*>(lItem);
3415+
3416+ for (csize i = 0; i < numRoots; i++)
3417+ {
3418+ assert(dynamic_cast<const StructuredItem*>(rootNodes[i]));
3419+ StructuredItem* lRootStructuredItem =
3420+ static_cast<StructuredItem*>(rootNodes[i]);
3421+
3422+ if (lRootStructuredItem->isInSubtree(lStructuredItem))
3423+ {
3424+ found = true;
3425+ break;
3426+ }
3427 }
3428
3429 if (!found)
3430@@ -2398,31 +2362,30 @@
3431 NodeToUpdatesMap::iterator end = pul->theNodeToUpdatesMap.end();
3432 for (; ite != end; ++ite)
3433 {
3434- store::Item* lItem = (*ite).first;
3435-#ifdef ZORBA_WITH_JSON
3436- ZORBA_ASSERT(lItem->isNode() || lItem->isJSONItem());
3437+ store::Item* item = (*ite).first;
3438+ ZORBA_ASSERT(item->isStructuredItem());
3439
3440- if (lItem->isJSONItem())
3441- {
3442- json::JSONItem* lJSONItem = dynamic_cast<json::JSONItem*>(lItem);
3443- ZORBA_ASSERT(lJSONItem != NULL);
3444- pul->theModifiedDocs.insert(const_cast<json::JSONItem*>(lJSONItem->getRoot()));
3445- continue;
3446- }
3447-#endif
3448- ZORBA_ASSERT(lItem->isNode());
3449- XmlNode* node = dynamic_cast<XmlNode*>((*ite).first);
3450- ZORBA_ASSERT(node != NULL);
3451- pul->theModifiedDocs.insert(node->getRoot());
3452+ StructuredItem* structuredItem = static_cast<StructuredItem*>(item);
3453+ pul->theModifiedDocs.insert(structuredItem->getCollectionRoot());
3454 continue;
3455 }
3456
3457- csize numCollUpdates = pul->theInsertIntoCollectionList.size();
3458-
3459- for (csize i = 0; i < numCollUpdates; ++i)
3460- {
3461- UpdCollection* upd = static_cast<UpdCollection*>
3462- (pul->theInsertIntoCollectionList[i]);
3463+ csize numCollUpdates = pul->theEditInCollectionList.size();
3464+
3465+ for (csize i = 0; i < numCollUpdates; ++i)
3466+ {
3467+ UpdEditInCollection* upd =
3468+ static_cast<UpdEditInCollection*>(pul->theEditInCollectionList[i]);
3469+
3470+ pul->theModifiedDocs.insert(upd->getTarget());
3471+ }
3472+
3473+ numCollUpdates = pul->theInsertIntoCollectionList.size();
3474+
3475+ for (csize i = 0; i < numCollUpdates; ++i)
3476+ {
3477+ UpdCollection* upd =
3478+ static_cast<UpdCollection*>(pul->theInsertIntoCollectionList[i]);
3479
3480 csize numDocs = upd->numNodes();
3481
3482@@ -2430,22 +2393,12 @@
3483 pul->theInsertedDocs.push_back(upd->getNode(j));
3484 }
3485
3486- numCollUpdates = pul->theEditInCollectionList.size();
3487-
3488- for (csize i = 0; i < numCollUpdates; ++i)
3489- {
3490- UpdEditInCollection* upd = static_cast<UpdEditInCollection*>
3491- (pul->theEditInCollectionList[i]);
3492-
3493- pul->theModifiedDocs.insert(upd->getTarget());
3494- }
3495-
3496 numCollUpdates = pul->theDeleteFromCollectionList.size();
3497
3498 for (csize i = 0; i < numCollUpdates; ++i)
3499 {
3500- UpdCollection* upd = static_cast<UpdCollection*>
3501- (pul->theDeleteFromCollectionList[i]);
3502+ UpdCollection* upd =
3503+ static_cast<UpdCollection*>(pul->theDeleteFromCollectionList[i]);
3504
3505 csize numDocs = upd->numNodes();
3506
3507
3508=== modified file 'src/store/naive/simple_store.cpp'
3509--- src/store/naive/simple_store.cpp 2013-01-17 04:43:05 +0000
3510+++ src/store/naive/simple_store.cpp 2013-02-21 15:32:25 +0000
3511@@ -266,10 +266,10 @@
3512
3513
3514 /*******************************************************************************
3515- Computes the reference of the given node.
3516+ Computes the reference of the given node.
3517
3518- @param node XDM node
3519- @return the identifier as an item of type xs:anyURI
3520+ @param node XDM node
3521+ @return the identifier as an item of type xs:anyURI
3522 ********************************************************************************/
3523 bool SimpleStore::getNodeReference(store::Item_t& result, const store::Item* node)
3524 {
3525@@ -308,11 +308,11 @@
3526 {
3527 using namespace zorba::simplestore::json;
3528
3529- bool lHasReference = false;
3530+ bool hasReference = false;
3531 if (node->isNode())
3532 {
3533 const XmlNode* x = static_cast<const XmlNode*>(node);
3534- lHasReference = x->haveReference();
3535+ hasReference = x->haveReference();
3536 }
3537 else
3538 {
3539@@ -320,17 +320,21 @@
3540 JSONItem* j = const_cast<JSONItem*>(static_cast<const JSONItem*>(node));
3541
3542 // only root nodes in a collection can have a reference
3543- if (j->getTree() && j->getTree()->getRoot() == j)
3544+ if (j->isCollectionRoot())
3545 {
3546- ItemRefMap::iterator lIter = theNodeToReferencesMap.find(node);
3547+ ItemRefMap::iterator iter = theNodeToReferencesMap.find(node);
3548
3549- lHasReference = (lIter != theNodeToReferencesMap.end());
3550+ hasReference = (iter != theNodeToReferencesMap.end());
3551 }
3552 }
3553- return lHasReference;
3554+
3555+ return hasReference;
3556 }
3557
3558
3559+/*******************************************************************************
3560+
3561+********************************************************************************/
3562 bool SimpleStore::assignReference(const store::Item* node, const zstring& reference)
3563 {
3564 using namespace zorba::simplestore::json;
3565@@ -352,7 +356,7 @@
3566 assert(node->isJSONItem());
3567 const JSONItem* j = static_cast<const JSONItem*>(node);
3568
3569- if (!j->getTree() || j != j->getTree()->getRoot())
3570+ if (! j->isCollectionRoot())
3571 throw ZORBA_EXCEPTION(zerr::ZAPI0080_CANNOT_RETRIEVE_REFERENCE);
3572 }
3573
3574
3575=== modified file 'src/store/naive/store.cpp'
3576--- src/store/naive/store.cpp 2012-11-21 03:17:34 +0000
3577+++ src/store/naive/store.cpp 2013-02-21 15:32:25 +0000
3578@@ -608,7 +608,7 @@
3579 bool more = true;
3580
3581 #ifdef ZORBA_WITH_JSON
3582- assert(domainNode->isNode() || domainNode->isJSONItem());
3583+ assert(domainNode->isStructuredItem());
3584 #else
3585 assert(domainNode->isNode());
3586 #endif
3587@@ -631,7 +631,7 @@
3588 // If current node has no keys, put it in the "null" entry and continue
3589 // with the next domain node, if nay.
3590 #ifdef ZORBA_WITH_JSON
3591- if (!more || firstKeyItem->isNode() || firstKeyItem->isJSONItem())
3592+ if (!more || firstKeyItem->isStructuredItem())
3593 #else
3594 if (!more || firstKeyItem->isNode())
3595 #endif
3596@@ -648,7 +648,7 @@
3597 // If current domain node has exactly 1 key, insert it in the index
3598 // and continue with next domain node, if any.
3599 #ifdef ZORBA_WITH_JSON
3600- if (!more || keyItem->isNode() || keyItem->isJSONItem())
3601+ if (!more || keyItem->isStructuredItem())
3602 #else
3603 if (!more || keyItem->isNode())
3604 #endif
3605@@ -673,7 +673,7 @@
3606 while ((more = sourceIter->next(keyItem)))
3607 {
3608 #ifdef ZORBA_WITH_JSON
3609- if (keyItem->isNode() || keyItem->isJSONItem())
3610+ if (keyItem->isStructuredItem())
3611 #else
3612 if (keyItem->isNode())
3613 #endif
3614@@ -1211,11 +1211,12 @@
3615 #ifdef TEXT_ORDPATH
3616 const OrdPathNode* n = static_cast<const OrdPathNode*>(node);
3617
3618- return theItemFactory->createStructuralAnyURI(result,
3619- n->getCollectionId(),
3620- n->getTreeId(),
3621- n->getNodeKind(),
3622- n->getOrdPath());
3623+ return theItemFactory->createStructuralAnyURI(
3624+ result,
3625+ n->getCollectionId(),
3626+ n->getTree()->getTreeId(),
3627+ n->getNodeKind(),
3628+ n->getOrdPath());
3629 #else
3630 if (node->getNodeKind() == store::StoreConsts::textNode)
3631 {
3632@@ -1223,21 +1224,23 @@
3633 const TextNode* n = static_cast<const TextNode*>(node);
3634 n->getOrdPath(ordPath);
3635
3636- return GET_FACTORY().createStructuralAnyURI(result,
3637- n->getCollectionId(),
3638- n->getTreeId(),
3639- store::StoreConsts::textNode,
3640- ordPath);
3641+ return GET_FACTORY().createStructuralAnyURI(
3642+ result,
3643+ n->getCollectionId(),
3644+ n->getTree()->getTreeId(),
3645+ store::StoreConsts::textNode,
3646+ ordPath);
3647 }
3648 else
3649 {
3650 const OrdPathNode* n = static_cast<const OrdPathNode*>(node);
3651
3652- return GET_FACTORY().createStructuralAnyURI(result,
3653- n->getCollectionId(),
3654- n->getTreeId(),
3655- n->getNodeKind(),
3656- n->getOrdPath());
3657+ return GET_FACTORY().createStructuralAnyURI(
3658+ result,
3659+ n->getCollectionId(),
3660+ n->getTree()->getTreeId(),
3661+ n->getNodeKind(),
3662+ n->getOrdPath());
3663 }
3664 #endif
3665 }
3666
3667=== modified file 'src/store/naive/store_defs.h'
3668--- src/store/naive/store_defs.h 2012-09-19 21:16:15 +0000
3669+++ src/store/naive/store_defs.h 2013-02-21 15:32:25 +0000
3670@@ -38,22 +38,24 @@
3671
3672 #define GET_PUL_FACTORY() \
3673 (GET_STORE().getPULFactory())
3674-
3675-#define BASE_NODE(item) (reinterpret_cast<XmlNode*>((item).getp()))
3676-
3677-#define INTERNAL_NODE(item) (reinterpret_cast<InternalNode*>((item).getp()))
3678-
3679-#define DOC_NODE(item) (reinterpret_cast<DocumentNode*>((item).getp()))
3680-
3681-#define ATTR_NODE(item) (reinterpret_cast<AttributeNode*>((item).getp()))
3682-
3683-#define ELEM_NODE(item) (reinterpret_cast<ElementNode*>((item).getp()))
3684-
3685-#define TEXT_NODE(item) (reinterpret_cast<TextNode*>((item).getp()))
3686-
3687-#define PI_NODE(item) (reinterpret_cast<PiNode*>((item).getp()))
3688-
3689-#define COMMENT_NODE(item) (reinterpret_cast<CommentNode*>((item).getp()))
3690+
3691+#define STRUCT_NODE(item) (static_cast<StructuredItem*>((item).getp()))
3692+
3693+#define BASE_NODE(item) (static_cast<XmlNode*>((item).getp()))
3694+
3695+#define INTERNAL_NODE(item) (static_cast<InternalNode*>((item).getp()))
3696+
3697+#define DOC_NODE(item) (static_cast<DocumentNode*>((item).getp()))
3698+
3699+#define ATTR_NODE(item) (static_cast<AttributeNode*>((item).getp()))
3700+
3701+#define ELEM_NODE(item) (static_cast<ElementNode*>((item).getp()))
3702+
3703+#define TEXT_NODE(item) (static_cast<TextNode*>((item).getp()))
3704+
3705+#define PI_NODE(item) (static_cast<PiNode*>((item).getp()))
3706+
3707+#define COMMENT_NODE(item) (static_cast<CommentNode*>((item).getp()))
3708
3709
3710 #ifndef NDEBUG
3711
3712=== added file 'src/store/naive/structured_item.cpp'
3713--- src/store/naive/structured_item.cpp 1970-01-01 00:00:00 +0000
3714+++ src/store/naive/structured_item.cpp 2013-02-21 15:32:25 +0000
3715@@ -0,0 +1,144 @@
3716+/*
3717+ * Copyright 2006-2013 The FLWOR Foundation.
3718+ *
3719+ * Licensed under the Apache License, Version 2.0 (the "License");
3720+ * you may not use this file except in compliance with the License.
3721+ * You may obtain a copy of the License at
3722+ *
3723+ * http://www.apache.org/licenses/LICENSE-2.0
3724+ *
3725+ * Unless required by applicable law or agreed to in writing, software
3726+ * distributed under the License is distributed on an "AS IS" BASIS,
3727+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3728+ * See the License for the specific language governing permissions and
3729+ * limitations under the License.
3730+ */
3731+
3732+#include "structured_item.h"
3733+#include "collection_tree_info.h"
3734+#include "collection.h"
3735+#include "node_items.h"
3736+#include "json_items.h"
3737+
3738+
3739+namespace zorba
3740+{
3741+namespace simplestore
3742+{
3743+
3744+
3745+/*******************************************************************************
3746+ Get the id of the tree this node belongs to
3747+********************************************************************************/
3748+const TreeId& StructuredItem::getTreeId() const
3749+{
3750+ if (isNode())
3751+ {
3752+ const XmlNode* node = static_cast<const XmlNode*>(this);
3753+ return node->getTree()->getTreeId();
3754+ }
3755+ else
3756+ {
3757+ assert(isJSONItem());
3758+
3759+ const json::JSONItem* node = static_cast<const json::JSONItem*>(this);
3760+
3761+ CollectionTreeInfoWithTreeId* info =
3762+ static_cast<CollectionTreeInfoWithTreeId*>(node->getCollectionTreeInfo());
3763+
3764+ ZORBA_ASSERT(info);
3765+
3766+ return info->getTreeId();
3767+ }
3768+}
3769+
3770+
3771+/*******************************************************************************
3772+
3773+********************************************************************************/
3774+CollectionTreeInfo* StructuredItem::getCollectionTreeInfo() const
3775+{
3776+ if (isNode())
3777+ {
3778+ const XmlNode* node = static_cast<const XmlNode*>(this);
3779+ return node->getTree()->getCollectionTreeInfo();
3780+ }
3781+ else
3782+ {
3783+ assert(isJSONItem());
3784+ const json::JSONItem* node = static_cast<const json::JSONItem*>(this);
3785+ return node->getCollectionTreeInfo();
3786+ }
3787+}
3788+
3789+
3790+/*******************************************************************************
3791+ Let T be the tree containing this node. If T belongs to a collection directly,
3792+ return the root node of T. If T belongs to a collection indirectly, return the
3793+ root node of the (JSON) tree that points to T and belongs to the collection
3794+ directly. If T does not belong to any collection, return NULL.
3795+********************************************************************************/
3796+StructuredItem* StructuredItem::getCollectionRoot() const
3797+{
3798+ CollectionTreeInfo* info = getCollectionTreeInfo();
3799+ return info ? info->getRoot() : NULL;
3800+}
3801+
3802+
3803+/*******************************************************************************
3804+ Assuming the tree T this node belongs to is in a collection, return the
3805+ position of T within its containing collection.
3806+********************************************************************************/
3807+const xs_integer& StructuredItem::getPosition() const
3808+{
3809+ CollectionTreeInfo* info = getCollectionTreeInfo();
3810+ ZORBA_ASSERT(info);
3811+ return info->getPosition();
3812+}
3813+
3814+
3815+/*******************************************************************************
3816+ Assuming the tree T this node belongs to is in a collection, store the
3817+ position of T within its containing collection. The position is stored
3818+ inside the CollectionTreeInfo object associated with the node.
3819+********************************************************************************/
3820+void StructuredItem::setPosition(const xs_integer& pos)
3821+{
3822+ CollectionTreeInfo* info = getCollectionTreeInfo();
3823+ ZORBA_ASSERT(info);
3824+ info->setPosition(pos);
3825+}
3826+
3827+
3828+/*******************************************************************************
3829+ Return true if this node is the root node of a tree that belongs to a
3830+ a collection directly.
3831+********************************************************************************/
3832+bool StructuredItem::isCollectionRoot() const
3833+{
3834+ return getCollectionRoot() == this;
3835+}
3836+
3837+
3838+/*******************************************************************************
3839+ Return true if this node is in the subtree starting at the given item.
3840+
3841+ NOTE: for the purposes of this method, XML trees that are pointed-to by a
3842+ JSON tree are considered part of that JSON tree. As a result, an XML node
3843+ may be in the subtree of a JSON node.
3844+********************************************************************************/
3845+bool StructuredItem::isInSubtreeOf(const store::Item_t& anItem) const
3846+{
3847+ if (!anItem->isStructuredItem())
3848+ {
3849+ return false;
3850+ }
3851+
3852+ StructuredItem* structuredItem = static_cast<StructuredItem*>(anItem.getp());
3853+
3854+ return structuredItem->isInSubtree(this);
3855+};
3856+
3857+
3858+} // simplestore
3859+} // zorba
3860
3861=== added file 'src/store/naive/structured_item.h'
3862--- src/store/naive/structured_item.h 1970-01-01 00:00:00 +0000
3863+++ src/store/naive/structured_item.h 2013-02-21 15:32:25 +0000
3864@@ -0,0 +1,93 @@
3865+/*
3866+ * Copyright 2006-2012 The FLWOR Foundation.
3867+ *
3868+ * Licensed under the Apache License, Version 2.0 (the "License");
3869+ * you may not use this file except in compliance with the License.
3870+ * You may obtain a copy of the License at
3871+ *
3872+ * http://www.apache.org/licenses/LICENSE-2.0
3873+ *
3874+ * Unless required by applicable law or agreed to in writing, software
3875+ * distributed under the License is distributed on an "AS IS" BASIS,
3876+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3877+ * See the License for the specific language governing permissions and
3878+ * limitations under the License.
3879+ */
3880+
3881+#ifndef ZORBA_SIMPLE_STORE_STRUCTURED_ITEMS
3882+#define ZORBA_SIMPLE_STORE_STRUCTURED_ITEMS
3883+
3884+#include "store/api/item.h"
3885+#include "tree_id.h"
3886+
3887+namespace zorba
3888+{
3889+namespace simplestore
3890+{
3891+
3892+class Collection;
3893+class CollectionTreeInfo;
3894+
3895+
3896+/*******************************************************************************
3897+ StructuredItem represents either an XML node or a JSON node.
3898+
3899+ An important goal of the StructureItem class is to provide methods that
3900+ manage the interactions between trees of nodes and collections. These methods
3901+ operate on instances of the CollectionTreeInfo class. See comments in
3902+ collection_tree_info.h for more details.
3903+********************************************************************************/
3904+class StructuredItem : public store::Item
3905+{
3906+public:
3907+ StructuredItem(ItemKind k) : Item(k) {}
3908+
3909+ StructuredItem() : Item() {}
3910+
3911+ //--------------------- Item API ---------------------------------------------
3912+
3913+ bool isInSubtreeOf(const store::Item_t& anItem) const;
3914+
3915+ bool isCollectionRoot() const;
3916+
3917+ //--------------------- Structured Item API ----------------------------------
3918+
3919+ const TreeId& getTreeId() const;
3920+
3921+ StructuredItem* getCollectionRoot() const;
3922+
3923+ const xs_integer& getPosition() const;
3924+
3925+ void setPosition(const xs_integer& pos);
3926+
3927+ // Attaches a root node to a collection (populates collection info).
3928+ virtual void attachToCollection(
3929+ Collection* collection,
3930+ const TreeId& treeId,
3931+ const xs_integer& position) = 0;
3932+
3933+ // Detaches a root node from a collection (populates collection info).
3934+ virtual void detachFromCollection() = 0;
3935+
3936+ // Propagates collection tree info to descendants
3937+ // (not to be called on a root - use functions above if root).
3938+ virtual void setCollectionTreeInfo(CollectionTreeInfo* collectionInfo) = 0;
3939+
3940+ // Returns total number of outstanding pointers to the tree (for garbage
3941+ // collection purposes).
3942+ virtual long getCollectionTreeRefCount() const = 0;
3943+
3944+ // Tells if the given item is in the subtree starting at this item.
3945+ // NOTE: for the purposes of this method, XML trees that are pointed-to
3946+ // by a JSON tree are considered part of that JSON tree. As a result,
3947+ // an XML node may be in the subtree of a JSON node.
3948+ virtual bool isInSubtree(const StructuredItem* anotherItem) const = 0;
3949+
3950+protected:
3951+ CollectionTreeInfo* getCollectionTreeInfo() const;
3952+};
3953+
3954+} // namespace simplestore
3955+} // namespace zorba
3956+#endif /* ZORBA_SIMPLE_STORE_NODE_ITEMS */
3957+
3958
3959=== modified file 'src/types/typeops.cpp'
3960--- src/types/typeops.cpp 2013-01-29 06:01:31 +0000
3961+++ src/types/typeops.cpp 2013-02-21 15:32:25 +0000
3962@@ -811,7 +811,7 @@
3963 case XQType::STRUCTURED_ITEM_KIND:
3964 {
3965 #ifdef ZORBA_WITH_JSON
3966- if (subitem->isJSONItem() || subitem->isNode())
3967+ if (subitem->isStructuredItem())
3968 #else
3969 if (subitem->isNode())
3970 #endif
3971
3972=== added file 'test/rbkt/ExpQueryResults/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point-maintenance.xml.res'
3973--- test/rbkt/ExpQueryResults/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point-maintenance.xml.res 1970-01-01 00:00:00 +0000
3974+++ test/rbkt/ExpQueryResults/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point-maintenance.xml.res 2013-02-21 15:32:25 +0000
3975@@ -0,0 +1,1 @@
3976+{ "name" : "<name><first>Bev</first><last>Picard</last></name>", "age" : 38, "gender" : "female", "friends" : [ "Jean-Luc Picard", "Ensign Crusher" ] }
3977\ No newline at end of file
3978
3979=== added file 'test/rbkt/ExpQueryResults/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point.xml.res'
3980--- test/rbkt/ExpQueryResults/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point.xml.res 1970-01-01 00:00:00 +0000
3981+++ test/rbkt/ExpQueryResults/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point.xml.res 2013-02-21 15:32:25 +0000
3982@@ -0,0 +1,1 @@
3983+{ "name" : "<name><grade>Lieutenant Commander</grade><first>Data</first></name>", "age" : 100, "gender" : "positronic matrix", "friends" : [ "Geordi La Forge" ] }
3984\ No newline at end of file
3985
3986=== added file 'test/rbkt/ExpQueryResults/zorba/jsoniq/collection-and-index/foaf-json-xml-update-index-point.xml.res'
3987--- test/rbkt/ExpQueryResults/zorba/jsoniq/collection-and-index/foaf-json-xml-update-index-point.xml.res 1970-01-01 00:00:00 +0000
3988+++ test/rbkt/ExpQueryResults/zorba/jsoniq/collection-and-index/foaf-json-xml-update-index-point.xml.res 2013-02-21 15:32:25 +0000
3989@@ -0,0 +1,1 @@
3990+{ "age" : 30, "gender" : "male", "name" : "<name><first>William</first><last>Riker</last></name>" }
3991\ No newline at end of file
3992
3993=== added file 'test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point-maintenance.spec'
3994--- test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point-maintenance.spec 1970-01-01 00:00:00 +0000
3995+++ test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point-maintenance.spec 2013-02-21 15:32:25 +0000
3996@@ -0,0 +1,1 @@
3997+Serialization: method=json-xml-hybrid jsoniq-multiple-items=appended jsoniq-extensions=yes
3998
3999=== added file 'test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point-maintenance.xq'
4000--- test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point-maintenance.xq 1970-01-01 00:00:00 +0000
4001+++ test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point-maintenance.xq 2013-02-21 15:32:25 +0000
4002@@ -0,0 +1,36 @@
4003+
4004+import module namespace foaf = "http://www.w3.org/TestModules/foaf" at
4005+ "foaf_module-with-index-and-xml.xqlib";
4006+
4007+import module namespace ddl = "http://www.zorba-xquery.com/modules/store/static/collections/ddl";
4008+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";
4009+import module namespace index_ddl = "http://www.zorba-xquery.com/modules/store/static/indexes/ddl";
4010+import module namespace index_dml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";
4011+
4012+declare namespace err = "http://www.w3.org/2005/xqt-errors";
4013+
4014+foaf:create-db();
4015+
4016+dml:delete(dml:collection($foaf:network)[. ("name")/first eq "James"]);
4017+
4018+dml:insert($foaf:network,
4019+ {
4020+ "name" : <name><first>Wesley</first><last>Crusher</last></name>,
4021+ "age" : 20,
4022+ "gender" : "male",
4023+ "friends" : [ "Beverly Crusher" ]
4024+ }
4025+);
4026+
4027+(replace value of node dml:collection($foaf:network)[.("name")/first eq "Beverly"]("name")/first with "Bev",
4028+replace value of node dml:collection($foaf:network)[.("name")/first eq "Beverly"]("name")/last with "Picard",
4029+
4030+for $person in dml:collection($foaf:network)
4031+let $friends := $person("friends")
4032+for $i in 1 to jn:size($friends)
4033+where $friends($i) eq "Beverly Crusher"
4034+return
4035+replace json value of $friends($i) with "Bev Picard")
4036+;
4037+
4038+foaf:probe-point-id($foaf:person, "Bev")
4039
4040=== added file 'test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point.spec'
4041--- test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point.spec 1970-01-01 00:00:00 +0000
4042+++ test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point.spec 2013-02-21 15:32:25 +0000
4043@@ -0,0 +1,1 @@
4044+Serialization: method=json-xml-hybrid jsoniq-multiple-items=appended jsoniq-extensions=yes
4045
4046=== added file 'test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point.xq'
4047--- test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point.xq 1970-01-01 00:00:00 +0000
4048+++ test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-index-point.xq 2013-02-21 15:32:25 +0000
4049@@ -0,0 +1,15 @@
4050+
4051+import module namespace foaf = "http://www.w3.org/TestModules/foaf" at
4052+ "foaf_module-with-index-and-xml.xqlib";
4053+
4054+import module namespace ddl = "http://www.zorba-xquery.com/modules/store/static/collections/ddl";
4055+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";
4056+import module namespace index_ddl = "http://www.zorba-xquery.com/modules/store/static/indexes/ddl";
4057+import module namespace index_dml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";
4058+
4059+declare namespace err = "http://www.w3.org/2005/xqt-errors";
4060+
4061+foaf:create-db();
4062+
4063+for $x in foaf:probe-point-id($foaf:person, "Data")
4064+return $x
4065
4066=== added file 'test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-update-index-point.spec'
4067--- test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-update-index-point.spec 1970-01-01 00:00:00 +0000
4068+++ test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-update-index-point.spec 2013-02-21 15:32:25 +0000
4069@@ -0,0 +1,1 @@
4070+Serialization: method=json-xml-hybrid jsoniq-multiple-items=appended jsoniq-extensions=yes
4071
4072=== added file 'test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-update-index-point.xq'
4073--- test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-update-index-point.xq 1970-01-01 00:00:00 +0000
4074+++ test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf-json-xml-update-index-point.xq 2013-02-21 15:32:25 +0000
4075@@ -0,0 +1,25 @@
4076+import module namespace foaf = "http://www.w3.org/TestModules/foaf" at
4077+ "foaf_module-with-index-and-xml.xqlib";
4078+
4079+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";
4080+
4081+declare namespace err = "http://www.w3.org/2005/xqt-errors";
4082+
4083+foaf:create-db();
4084+
4085+dml:insert($foaf:network, {
4086+ "first-name" : "William",
4087+ "last-name" : "Riker",
4088+ "age" : 30,
4089+ "gender" : "male"
4090+ });
4091+
4092+let $riker := dml:collection($foaf:network)[ .("last-name") eq "Riker" ]
4093+return {
4094+ insert json { "name" : <name><first>William</first><last>Riker</last></name> } into $riker;
4095+ delete json $riker("first-name");
4096+ delete json $riker("last-name");
4097+}
4098+
4099+for $x in foaf:probe-point-id($foaf:person, "William")
4100+return $x
4101
4102=== added file 'test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf_module-with-index-and-xml.xqlib'
4103--- test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf_module-with-index-and-xml.xqlib 1970-01-01 00:00:00 +0000
4104+++ test/rbkt/Queries/zorba/jsoniq/collection-and-index/foaf_module-with-index-and-xml.xqlib 2013-02-21 15:32:25 +0000
4105@@ -0,0 +1,82 @@
4106+
4107+module namespace foaf = "http://www.w3.org/TestModules/foaf";
4108+
4109+import module namespace ddl = "http://www.zorba-xquery.com/modules/store/static/collections/ddl";
4110+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";
4111+import module namespace index_ddl = "http://www.zorba-xquery.com/modules/store/static/indexes/ddl";
4112+import module namespace index_dml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";
4113+
4114+declare namespace ann = "http://www.zorba-xquery.com/annotations";
4115+
4116+declare variable $foaf:network:= xs:QName("foaf:network");
4117+declare variable $foaf:person:= xs:QName("foaf:person");
4118+declare variable $foaf:age:= xs:QName("foaf:age");
4119+declare variable $foaf:friends:= xs:QName("foaf:friends");
4120+
4121+declare collection foaf:network as object()*;
4122+
4123+
4124+(:
4125+ The person index maps each person name with its information.
4126+:)
4127+
4128+declare %ann:automatic index foaf:person
4129+on nodes dml:collection(xs:QName("foaf:network"))
4130+by .("name")/string(first) as xs:string?;
4131+
4132+(:
4133+ Create and populate the collection, and then create the indexes
4134+:)
4135+
4136+declare %ann:sequential function foaf:create-db()
4137+{
4138+ ddl:create($foaf:network);
4139+
4140+ dml:insert($foaf:network, (
4141+ {
4142+ "name" : <name><first>James</first><middle>T.</middle><last>Kirk</last></name>,
4143+ "age" : 30,
4144+ "gender" : "male",
4145+ "friends" : [ "Mister Spock", "Scotty", "Jean-Luc Picard"]
4146+ },
4147+
4148+ {
4149+ "name" : <name><first>Jean-Luc</first><last>Picard</last></name>,
4150+ "age" : 40,
4151+ "gender" : "male",
4152+ "friends" : [ "James T. Kirk", "Lieutenant Commander Data", "Beverly Crusher" ]
4153+ },
4154+
4155+ {
4156+ "name" : <name><first>Beverly</first><last>Crusher</last></name>,
4157+ "age" : 38,
4158+ "gender" : "female",
4159+ "friends" : [ "Jean-Luc Picard", "Ensign Crusher" ]
4160+ },
4161+
4162+ {
4163+ "name" : <name><grade>Lieutenant Commander</grade><first>Data</first></name>,
4164+ "age" : 100,
4165+ "gender" : "positronic matrix",
4166+ "friends" : [ "Geordi La Forge" ]
4167+ }
4168+ ));
4169+
4170+ index_ddl:create($foaf:person);
4171+};
4172+
4173+
4174+declare function foaf:probe-point-id($indexName as xs:QName, $id as xs:string)
4175+{
4176+ index_dml:probe-index-point-value($indexName, $id)
4177+};
4178+
4179+declare function foaf:probe-range-id($indexName as xs:QName, $lower as xs:integer, $upper as xs:integer)
4180+{
4181+ index_dml:probe-index-range-value($indexName, $lower, $upper, true(), true(), true(), true())
4182+};
4183+
4184+declare function foaf:probe-point-general-id($indexName as xs:QName, $names as xs:string*)
4185+{
4186+ index_dml:probe-index-point-general($indexName, $names)
4187+};

Subscribers

People subscribed via source and target branches