zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #00275
[Merge] lp:~fcavalieri/zorba/identifiers into lp:zorba
Federico Cavalieri has proposed merging lp:~fcavalieri/zorba/identifiers into lp:zorba.
Requested reviews:
Markos Zaharioudakis (markos-za)
For more details, see:
https://code.launchpad.net/~fcavalieri/zorba/identifiers/+merge/77297
Introduced a core module which allows to compute a unique identifier which can be used to retrieve a node (even temporary) during all its lifetime.
Added three functions to the store api for computing identifier, assessing if a node already has an identifier and retrieving a node given its identifier.
The simplestore extension comprises additional methods for working with identifiers in a PUL manipulation context.
--
https://code.launchpad.net/~fcavalieri/zorba/identifiers/+merge/77297
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'include/zorba/pregenerated/diagnostic_list.h'
--- include/zorba/pregenerated/diagnostic_list.h 2011-08-17 23:04:48 +0000
+++ include/zorba/pregenerated/diagnostic_list.h 2011-09-28 09:26:25 +0000
@@ -500,6 +500,12 @@
extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZAPI0080_CANNOT_RETRIEVE_NODE_REFERENCE;
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZAPI0090_NO_CURRENT_IDENTIFIER;
+
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZAPI0091_INVALID_NODE_IDENTIFIER;
+
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZAPI0092_IDENTIFIER_ALREADY_PRESENT;
+
extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZCSE0001_NONEXISTENT_INPUT_FIELD;
extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZCSE0002_INCOMPATIBLE_INPUT_FIELD;
=== modified file 'modules/com/zorba-xquery/www/modules/CMakeLists.txt'
--- modules/com/zorba-xquery/www/modules/CMakeLists.txt 2011-08-10 09:40:29 +0000
+++ modules/com/zorba-xquery/www/modules/CMakeLists.txt 2011-09-28 09:26:25 +0000
@@ -46,6 +46,8 @@
URI "http://www.zorba-xquery.com/modules/math";)
DECLARE_ZORBA_MODULE(FILE node-reference.xq VERSION 2.0
URI "http://www.zorba-xquery.com/modules/node-reference";)
+DECLARE_ZORBA_MODULE(FILE node-identifier.xq VERSION 2.0
+ URI "http://www.zorba-xquery.com/modules/node-identifier";)
DECLARE_ZORBA_MODULE(FILE node.xq VERSION 2.0
URI "http://www.zorba-xquery.com/modules/node";)
DECLARE_ZORBA_MODULE(FILE project_xqdoc.xq VERSION 2.0
=== added file 'modules/com/zorba-xquery/www/modules/node-identifier.xq'
--- modules/com/zorba-xquery/www/modules/node-identifier.xq 1970-01-01 00:00:00 +0000
+++ modules/com/zorba-xquery/www/modules/node-identifier.xq 2011-09-28 09:26:25 +0000
@@ -0,0 +1,106 @@
+xquery version "3.0";
+
+(:
+ : Copyright 2006-2011 The FLWOR Foundation.
+ :
+ : Licensed under the Apache License, Version 2.0 (the "License");
+ : you may not use this file except in compliance with the License.
+ : You may obtain a copy of the License at
+ :
+ : http://www.apache.org/licenses/LICENSE-2.0
+ :
+ : Unless required by applicable law or agreed to in writing, software
+ : distributed under the License is distributed on an "AS IS" BASIS,
+ : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ : See the License for the specific language governing permissions and
+ : limitations under the License.
+:)
+
+(:~
+ : This module provides functions to compute a string identifier for
+ : any node, either temporary or stored in a collection and for retrieving
+ : nodes given their identifier. The identifiers are immutable, i.e. a node
+ : identifier do not change during the node lifetime. Identifiers are also
+ : unique in that an already generated identifier cannot be generated again.
+ : Morever a node, at any time during its lifetime can be retrieved by its
+ : identifier.
+ :
+ : @author Federico Cavalieri
+ :)
+module namespace id = "http://www.zorba-xquery.com/modules/node-identifier";;
+declare namespace ann = "http://www.zorba-xquery.com/annotations";;
+declare namespace ver = "http://www.zorba-xquery.com/options/versioning";;
+declare option ver:module-version "2.0";
+
+(:~
+ : Computes a UUID string identifier (with type xs:string) for the given node.
+ : If an identifier has been already generated for the the given node it is
+ : returned. Otherwise a new identifier is generated and returned.
+ :
+ : <p>The returned identifier is immutable, i.e., a node identifier
+ : do not change during the node lifetime.</p>
+ :
+ : <p>The returned identifier is unique, i.e. the same identifier cannot be
+ : generated again.</p>
+ :
+ : @param $arg the node for which the identifier should be computed
+ :
+ : @return the identifier of the node
+ :
+ :)
+declare function id:node-identifier(
+ $node as node()
+) as xs:string external;
+
+(:~
+ : Computes a UUID string identifier (with type xs:string) for the given node.
+ : If an identifier has been already generated for the the given node it is
+ : returned.
+ :
+ : <p>The returned identifier is stable, i.e. the corresoponding node
+ : can be retrieved at any time during its lifetime.</p>
+ :
+ : <p>The returned identifier is unique, i.e. the same identifier cannot be
+ : generated again.</p>
+ :
+ : @param $arg the node for which the identifier should be computed
+ :
+ : @return the identifier of the node
+ :
+ : @error zerr::ZAPI0091 if no identifier has been generated for the given node
+ : computed by the <pre>id:node-identifier</pre> function
+ :
+ :)
+declare function id:current-node-identifier(
+ $node as node()
+) as xs:string external;
+
+(:~
+ : Returns whether an identifier has already been generated the given node or not.
+ :
+ : @param $node a node
+ :
+ : @return whether an identifier has already been generated the given node or not
+ :)
+declare function id:has-identifier(
+ $node as node()
+) as xs:boolean external;
+
+(:~
+ : Returns the node which is identified by the given identifier.
+ :
+ : <p>The function return the empty sequence if the corresponding
+ : node has been deleted or if the given identifier has never been
+ : generated.</p>
+ :
+ : @param $node-identifier the identifier of the node to retrieve
+ :
+ : @return the node identified by the given identifier or empty-sequence
+ : if it cannot be retrieved
+ :
+ : @error zerr::ZAPI0091 if the given identifier is not a valid identifier
+ : computed by the <pre>id:node-identifier</pre> function
+ :)
+declare function id:node-by-identifier(
+ $arg as xs:string
+) as node()? external;
=== modified file 'modules/com/zorba-xquery/www/modules/pregenerated/errors.xq'
--- modules/com/zorba-xquery/www/modules/pregenerated/errors.xq 2011-08-17 23:04:48 +0000
+++ modules/com/zorba-xquery/www/modules/pregenerated/errors.xq 2011-09-28 09:26:25 +0000
@@ -301,6 +301,18 @@
(:~
:)
+declare variable $zerr:ZAPI0090 as xs:QName := fn:QName($zerr:NS, "zerr:ZAPI0090");
+
+(:~
+:)
+declare variable $zerr:ZAPI0091 as xs:QName := fn:QName($zerr:NS, "zerr:ZAPI0091");
+
+(:~
+:)
+declare variable $zerr:ZAPI0092 as xs:QName := fn:QName($zerr:NS, "zerr:ZAPI0092");
+
+(:~
+:)
declare variable $zerr:ZCSE0001 as xs:QName := fn:QName($zerr:NS, "zerr:ZCSE0001");
(:~
=== modified file 'src/context/static_context.cpp'
--- src/context/static_context.cpp 2011-09-06 14:05:29 +0000
+++ src/context/static_context.cpp 2011-09-28 09:26:25 +0000
@@ -280,6 +280,9 @@
static_context::ZORBA_NODEREF_FN_NS = NS_PRE + "modules/node-reference";
const zstring
+static_context::ZORBA_NODEID_FN_NS= NS_PRE + "modules/node-identifier";
+
+const zstring
static_context::ZORBA_STORE_DYNAMIC_COLLECTIONS_DDL_FN_NS
= NS_PRE + "modules/store/dynamic/collections/ddl";
@@ -373,6 +376,7 @@
return (ns == ZORBA_MATH_FN_NS ||
ns == ZORBA_BASE64_FN_NS ||
ns == ZORBA_NODEREF_FN_NS ||
+ ns == ZORBA_NODEID_FN_NS ||
ns == ZORBA_STORE_DYNAMIC_DOCUMENTS_FN_NS ||
ns == ZORBA_STORE_DYNAMIC_UNORDERED_MAP_FN_NS ||
ns == ZORBA_STORE_DYNAMIC_COLLECTIONS_DDL_FN_NS ||
=== modified file 'src/context/static_context.h'
--- src/context/static_context.h 2011-08-31 13:17:59 +0000
+++ src/context/static_context.h 2011-09-28 09:26:25 +0000
@@ -459,6 +459,7 @@
static const zstring ZORBA_MATH_FN_NS;
static const zstring ZORBA_BASE64_FN_NS;
static const zstring ZORBA_NODEREF_FN_NS;
+ static const zstring ZORBA_NODEID_FN_NS;
static const zstring ZORBA_STORE_DYNAMIC_COLLECTIONS_DDL_FN_NS;
static const zstring ZORBA_STORE_DYNAMIC_COLLECTIONS_DML_FN_NS;
static const zstring ZORBA_STORE_STATIC_COLLECTIONS_DDL_FN_NS;
=== modified file 'src/diagnostics/diagnostic_en.xml'
--- src/diagnostics/diagnostic_en.xml 2011-09-16 21:58:20 +0000
+++ src/diagnostics/diagnostic_en.xml 2011-09-28 09:26:25 +0000
@@ -1792,6 +1792,18 @@
<value>can not retrieve node-reference for a node that is not in a collection.</value>
</diagnostic>
+ <diagnostic code="ZAPI0090" name="NO_CURRENT_IDENTIFIER">
+ <value>node has no current identifier.</value>
+ </diagnostic>
+
+ <diagnostic code="ZAPI0091" name="INVALID_NODE_IDENTIFIER">
+ <value>"$1": invalid node identifier.</value>
+ </diagnostic>
+
+ <diagnostic code="ZAPI0092" name="IDENTIFIER_ALREADY_PRESENT">
+ <value>"$1": identifier already present in the store.</value>
+ </diagnostic>
+
<!--////////// Zorba Class Serialization Errors ////////////////////////-->
<diagnostic code="ZCSE0001" name="NONEXISTENT_INPUT_FIELD">
=== modified file 'src/diagnostics/pregenerated/diagnostic_list.cpp'
--- src/diagnostics/pregenerated/diagnostic_list.cpp 2011-08-17 23:04:48 +0000
+++ src/diagnostics/pregenerated/diagnostic_list.cpp 2011-09-28 09:26:25 +0000
@@ -729,6 +729,15 @@
ZorbaErrorCode ZAPI0080_CANNOT_RETRIEVE_NODE_REFERENCE( "ZAPI0080" );
+ZorbaErrorCode ZAPI0090_NO_CURRENT_IDENTIFIER( "ZAPI0090" );
+
+
+ZorbaErrorCode ZAPI0091_INVALID_NODE_IDENTIFIER( "ZAPI0091" );
+
+
+ZorbaErrorCode ZAPI0092_IDENTIFIER_ALREADY_PRESENT( "ZAPI0092" );
+
+
ZorbaErrorCode ZCSE0001_NONEXISTENT_INPUT_FIELD( "ZCSE0001" );
=== modified file 'src/diagnostics/pregenerated/dict_en.cpp'
--- src/diagnostics/pregenerated/dict_en.cpp 2011-09-16 21:58:20 +0000
+++ src/diagnostics/pregenerated/dict_en.cpp 2011-09-28 09:26:25 +0000
@@ -244,6 +244,9 @@
{ "ZAPI0042", "iterator is closed" },
{ "ZAPI0070", "\"$1\": invalid serialization method for SAX" },
{ "ZAPI0080", "can not retrieve node-reference for a node that is not in a collection." },
+ { "ZAPI0090", "node has no current identifier." },
+ { "ZAPI0091", "\"$1\": invalid node identifier." },
+ { "ZAPI0092", "\"$1\": identifier already present in the store." },
{ "ZCSE0001", "\"$1\": nonexistent input field" },
{ "ZCSE0002", "\"$1\": incompatible input field${: type=2}${, class=3}" },
{ "ZCSE0003", "\"$1\": unrecognized class field" },
=== modified file 'src/functions/pregenerated/func_nodes.cpp'
--- src/functions/pregenerated/func_nodes.cpp 2011-08-04 02:39:56 +0000
+++ src/functions/pregenerated/func_nodes.cpp 2011-09-28 09:26:25 +0000
@@ -31,6 +31,46 @@
+PlanIter_t zorba_node_identifier_node_identifier::codegen(
+ CompilerCB*,
+ static_context* sctx,
+ const QueryLoc& loc,
+ std::vector<PlanIter_t>& argv,
+ AnnotationHolder& ann) const
+{
+ return new NodeIdentifierIterator(sctx, loc, argv);
+}
+
+PlanIter_t zorba_node_identifier_current_node_identifier::codegen(
+ CompilerCB*,
+ static_context* sctx,
+ const QueryLoc& loc,
+ std::vector<PlanIter_t>& argv,
+ AnnotationHolder& ann) const
+{
+ return new CurrentNodeIdentifierIterator(sctx, loc, argv);
+}
+
+PlanIter_t zorba_node_identifier_has_identifier::codegen(
+ CompilerCB*,
+ static_context* sctx,
+ const QueryLoc& loc,
+ std::vector<PlanIter_t>& argv,
+ AnnotationHolder& ann) const
+{
+ return new HasIdentifierIterator(sctx, loc, argv);
+}
+
+PlanIter_t zorba_node_identifier_node_by_identifier::codegen(
+ CompilerCB*,
+ static_context* sctx,
+ const QueryLoc& loc,
+ std::vector<PlanIter_t>& argv,
+ AnnotationHolder& ann) const
+{
+ return new NodeByIdentifierIterator(sctx, loc, argv);
+}
+
PlanIter_t fn_zorba_ref_node_reference::codegen(
CompilerCB*,
static_context* sctx,
@@ -236,6 +276,54 @@
{
+ DECL_WITH_KIND(sctx, zorba_node_identifier_node_identifier,
+ (createQName("http://www.zorba-xquery.com/modules/node-identifier","","node-identifier";),
+ GENV_TYPESYSTEM.ANY_NODE_TYPE_ONE,
+ GENV_TYPESYSTEM.STRING_TYPE_ONE),
+ FunctionConsts::ZORBA_NODE_IDENTIFIER_NODE_IDENTIFIER_1);
+
+ }
+
+
+ {
+
+
+ DECL_WITH_KIND(sctx, zorba_node_identifier_current_node_identifier,
+ (createQName("http://www.zorba-xquery.com/modules/node-identifier","","current-node-identifier";),
+ GENV_TYPESYSTEM.ANY_NODE_TYPE_ONE,
+ GENV_TYPESYSTEM.STRING_TYPE_ONE),
+ FunctionConsts::ZORBA_NODE_IDENTIFIER_CURRENT_NODE_IDENTIFIER_1);
+
+ }
+
+
+ {
+
+
+ DECL_WITH_KIND(sctx, zorba_node_identifier_has_identifier,
+ (createQName("http://www.zorba-xquery.com/modules/node-identifier","","has-identifier";),
+ GENV_TYPESYSTEM.ANY_NODE_TYPE_ONE,
+ GENV_TYPESYSTEM.BOOLEAN_TYPE_ONE),
+ FunctionConsts::ZORBA_NODE_IDENTIFIER_HAS_IDENTIFIER_1);
+
+ }
+
+
+ {
+
+
+ DECL_WITH_KIND(sctx, zorba_node_identifier_node_by_identifier,
+ (createQName("http://www.zorba-xquery.com/modules/node-identifier","","node-by-identifier";),
+ GENV_TYPESYSTEM.STRING_TYPE_ONE,
+ GENV_TYPESYSTEM.ANY_NODE_TYPE_QUESTION),
+ FunctionConsts::ZORBA_NODE_IDENTIFIER_NODE_BY_IDENTIFIER_1);
+
+ }
+
+
+ {
+
+
DECL_WITH_KIND(sctx, fn_zorba_ref_node_reference,
(createQName("http://www.zorba-xquery.com/modules/node-reference","","node-reference";),
GENV_TYPESYSTEM.ANY_NODE_TYPE_ONE,
=== modified file 'src/functions/pregenerated/func_nodes.h'
--- src/functions/pregenerated/func_nodes.h 2011-06-16 19:47:58 +0000
+++ src/functions/pregenerated/func_nodes.h 2011-09-28 09:26:25 +0000
@@ -38,6 +38,58 @@
+//zorba-node-identifier:node-identifier
+class zorba_node_identifier_node_identifier : public function
+{
+public:
+ zorba_node_identifier_node_identifier(const signature& sig, FunctionConsts::FunctionKind kind)
+ : function(sig, kind) {
+
+}
+
+ CODEGEN_DECL();
+};
+
+
+//zorba-node-identifier:current-node-identifier
+class zorba_node_identifier_current_node_identifier : public function
+{
+public:
+ zorba_node_identifier_current_node_identifier(const signature& sig, FunctionConsts::FunctionKind kind)
+ : function(sig, kind) {
+
+}
+
+ CODEGEN_DECL();
+};
+
+
+//zorba-node-identifier:has-identifier
+class zorba_node_identifier_has_identifier : public function
+{
+public:
+ zorba_node_identifier_has_identifier(const signature& sig, FunctionConsts::FunctionKind kind)
+ : function(sig, kind) {
+
+}
+
+ CODEGEN_DECL();
+};
+
+
+//zorba-node-identifier:node-by-identifier
+class zorba_node_identifier_node_by_identifier : public function
+{
+public:
+ zorba_node_identifier_node_by_identifier(const signature& sig, FunctionConsts::FunctionKind kind)
+ : function(sig, kind) {
+
+}
+
+ CODEGEN_DECL();
+};
+
+
//fn-zorba-ref:node-reference
class fn_zorba_ref_node_reference : public function
{
=== modified file 'src/functions/pregenerated/function_enum.h'
--- src/functions/pregenerated/function_enum.h 2011-08-17 20:22:07 +0000
+++ src/functions/pregenerated/function_enum.h 2011-09-28 09:26:25 +0000
@@ -193,6 +193,10 @@
FN_ZORBA_MATH_IS_NAN_1,
FN_ZORBA_MATH_MODF_1,
FN_ZORBA_MATH_FREXP_1,
+ ZORBA_NODE_IDENTIFIER_NODE_IDENTIFIER_1,
+ ZORBA_NODE_IDENTIFIER_CURRENT_NODE_IDENTIFIER_1,
+ ZORBA_NODE_IDENTIFIER_HAS_IDENTIFIER_1,
+ ZORBA_NODE_IDENTIFIER_NODE_BY_IDENTIFIER_1,
FN_ZORBA_REF_NODE_REFERENCE_1,
FN_ZORBA_REF_NODE_BY_REFERENCE_1,
FN_LOCAL_NAME_0,
=== modified file 'src/runtime/nodes/nodes_impl.cpp'
--- src/runtime/nodes/nodes_impl.cpp 2011-08-04 02:39:56 +0000
+++ src/runtime/nodes/nodes_impl.cpp 2011-09-28 09:26:25 +0000
@@ -33,6 +33,97 @@
namespace zorba {
+/*******************************************************************************
+********************************************************************************/
+bool
+NodeIdentifierIterator::nextImpl(store::Item_t& aResult, PlanState& aPlanState) const
+{
+ store::Item_t lNode;
+ store::Item_t lGenerateIdentifier;
+ zstring lNodeId;
+
+ PlanIteratorState *state;
+ DEFAULT_STACK_INIT(PlanIteratorState, state, aPlanState);
+
+ consumeNext(lNode, theChildren[0].getp(), aPlanState);
+
+ STACK_PUSH(GENV_STORE.getIdentifier(aResult, lNode), state);
+
+ STACK_END (state);
+}
+
+/*******************************************************************************
+********************************************************************************/
+bool
+CurrentNodeIdentifierIterator::nextImpl(store::Item_t& aResult, PlanState& aPlanState) const
+{
+ store::Item_t lNode;
+ store::Item_t lGenerateIdentifier;
+ zstring lNodeId;
+
+ PlanIteratorState *state;
+ DEFAULT_STACK_INIT(PlanIteratorState, state, aPlanState);
+
+ consumeNext(lNode, theChildren[0].getp(), aPlanState);
+
+ if (!GENV_STORE.hasIdentifier(lNode))
+ {
+ throw XQUERY_EXCEPTION(
+ zerr::ZAPI0090_NO_CURRENT_IDENTIFIER,
+ ERROR_LOC( loc )
+ );
+ }
+ STACK_PUSH(GENV_STORE.getIdentifier(aResult, lNode), state);
+
+ STACK_END (state);
+}
+
+/*******************************************************************************
+********************************************************************************/
+bool
+HasIdentifierIterator::nextImpl(store::Item_t& aResult, PlanState& aPlanState) const
+{
+ store::Item_t lNode;
+
+ PlanIteratorState *state;
+ DEFAULT_STACK_INIT(PlanIteratorState, state, aPlanState);
+
+ consumeNext(lNode, theChildren[0].getp(), aPlanState);
+
+ STACK_PUSH(GENV_ITEMFACTORY->createBoolean(aResult, GENV_STORE.hasIdentifier(lNode)), state);
+
+ STACK_END (state);
+}
+
+/*******************************************************************************
+********************************************************************************/
+bool
+NodeByIdentifierIterator::nextImpl(store::Item_t& result, PlanState& planState) const
+{
+ store::Item_t lUUID;
+
+ PlanIteratorState *state;
+ DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
+
+ consumeNext(lUUID, theChildren[0].getp(), planState);
+
+ if (!utf8::match_whole(lUUID->getStringValue(), "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"))
+ {
+ throw XQUERY_EXCEPTION(
+ zerr::ZAPI0091_INVALID_NODE_IDENTIFIER,
+ ERROR_PARAMS(lUUID->getStringValue()),
+ ERROR_LOC( loc )
+ );
+ }
+
+
+ STACK_PUSH(GENV_STORE.getNodeByIdentifier(result, lUUID->getStringValue()), state);
+
+ STACK_END (state);
+}
+
+
+
bool NodeReferenceIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
PlanIteratorState *state;
=== modified file 'src/runtime/nodes/pregenerated/nodes.cpp'
--- src/runtime/nodes/pregenerated/nodes.cpp 2011-06-16 19:47:58 +0000
+++ src/runtime/nodes/pregenerated/nodes.cpp 2011-09-28 09:26:25 +0000
@@ -32,6 +32,118 @@
namespace zorba {
+// <NodeIdentifierIterator>
+const char* NodeIdentifierIterator::class_name_str = "NodeIdentifierIterator";
+NodeIdentifierIterator::class_factory<NodeIdentifierIterator>
+NodeIdentifierIterator::g_class_factory;
+
+const serialization::ClassVersion
+NodeIdentifierIterator::class_versions[] ={{ 1, 0x000905, false}};
+
+const int NodeIdentifierIterator::class_versions_count =
+sizeof(NodeIdentifierIterator::class_versions)/sizeof(struct serialization::ClassVersion);
+
+void NodeIdentifierIterator::accept(PlanIterVisitor& v) const {
+ v.beginVisit(*this);
+
+ std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+ std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+ for ( ; lIter != lEnd; ++lIter ){
+ (*lIter)->accept(v);
+ }
+
+ v.endVisit(*this);
+}
+
+NodeIdentifierIterator::~NodeIdentifierIterator() {}
+
+// </NodeIdentifierIterator>
+
+
+// <CurrentNodeIdentifierIterator>
+const char* CurrentNodeIdentifierIterator::class_name_str = "CurrentNodeIdentifierIterator";
+CurrentNodeIdentifierIterator::class_factory<CurrentNodeIdentifierIterator>
+CurrentNodeIdentifierIterator::g_class_factory;
+
+const serialization::ClassVersion
+CurrentNodeIdentifierIterator::class_versions[] ={{ 1, 0x000905, false}};
+
+const int CurrentNodeIdentifierIterator::class_versions_count =
+sizeof(CurrentNodeIdentifierIterator::class_versions)/sizeof(struct serialization::ClassVersion);
+
+void CurrentNodeIdentifierIterator::accept(PlanIterVisitor& v) const {
+ v.beginVisit(*this);
+
+ std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+ std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+ for ( ; lIter != lEnd; ++lIter ){
+ (*lIter)->accept(v);
+ }
+
+ v.endVisit(*this);
+}
+
+CurrentNodeIdentifierIterator::~CurrentNodeIdentifierIterator() {}
+
+// </CurrentNodeIdentifierIterator>
+
+
+// <HasIdentifierIterator>
+const char* HasIdentifierIterator::class_name_str = "HasIdentifierIterator";
+HasIdentifierIterator::class_factory<HasIdentifierIterator>
+HasIdentifierIterator::g_class_factory;
+
+const serialization::ClassVersion
+HasIdentifierIterator::class_versions[] ={{ 1, 0x000905, false}};
+
+const int HasIdentifierIterator::class_versions_count =
+sizeof(HasIdentifierIterator::class_versions)/sizeof(struct serialization::ClassVersion);
+
+void HasIdentifierIterator::accept(PlanIterVisitor& v) const {
+ v.beginVisit(*this);
+
+ std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+ std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+ for ( ; lIter != lEnd; ++lIter ){
+ (*lIter)->accept(v);
+ }
+
+ v.endVisit(*this);
+}
+
+HasIdentifierIterator::~HasIdentifierIterator() {}
+
+// </HasIdentifierIterator>
+
+
+// <NodeByIdentifierIterator>
+const char* NodeByIdentifierIterator::class_name_str = "NodeByIdentifierIterator";
+NodeByIdentifierIterator::class_factory<NodeByIdentifierIterator>
+NodeByIdentifierIterator::g_class_factory;
+
+const serialization::ClassVersion
+NodeByIdentifierIterator::class_versions[] ={{ 1, 0x000905, false}};
+
+const int NodeByIdentifierIterator::class_versions_count =
+sizeof(NodeByIdentifierIterator::class_versions)/sizeof(struct serialization::ClassVersion);
+
+void NodeByIdentifierIterator::accept(PlanIterVisitor& v) const {
+ v.beginVisit(*this);
+
+ std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+ std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+ for ( ; lIter != lEnd; ++lIter ){
+ (*lIter)->accept(v);
+ }
+
+ v.endVisit(*this);
+}
+
+NodeByIdentifierIterator::~NodeByIdentifierIterator() {}
+
+// </NodeByIdentifierIterator>
+
+
// <NodeReferenceIterator>
const char* NodeReferenceIterator::class_name_str = "NodeReferenceIterator";
NodeReferenceIterator::class_factory<NodeReferenceIterator>
=== modified file 'src/runtime/nodes/pregenerated/nodes.h'
--- src/runtime/nodes/pregenerated/nodes.h 2011-06-16 19:47:58 +0000
+++ src/runtime/nodes/pregenerated/nodes.h 2011-09-28 09:26:25 +0000
@@ -34,6 +34,150 @@
namespace zorba {
/**
+ *
+ * declare function id:node-identifier($node as node) as xs:string
+ *
+ * Author: Federico Cavalieri
+ */
+class NodeIdentifierIterator : public NaryBaseIterator<NodeIdentifierIterator, PlanIteratorState>
+{
+public:
+ SERIALIZABLE_CLASS(NodeIdentifierIterator);
+
+ SERIALIZABLE_CLASS_CONSTRUCTOR2T(NodeIdentifierIterator,
+ NaryBaseIterator<NodeIdentifierIterator, PlanIteratorState>);
+
+ void serialize( ::zorba::serialization::Archiver& ar)
+ {
+ serialize_baseclass(ar,
+ (NaryBaseIterator<NodeIdentifierIterator, PlanIteratorState>*)this);
+ }
+
+ NodeIdentifierIterator(
+ static_context* sctx,
+ const QueryLoc& loc,
+ std::vector<PlanIter_t>& children)
+ :
+ NaryBaseIterator<NodeIdentifierIterator, PlanIteratorState>(sctx, loc, children)
+ {}
+
+ virtual ~NodeIdentifierIterator();
+
+ void accept(PlanIterVisitor& v) const;
+
+ bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
+ *
+ * declare function id:current-node-identifier($node as node) as xs:string
+ *
+ * Author: Federico Cavalieri
+ */
+class CurrentNodeIdentifierIterator : public NaryBaseIterator<CurrentNodeIdentifierIterator, PlanIteratorState>
+{
+public:
+ SERIALIZABLE_CLASS(CurrentNodeIdentifierIterator);
+
+ SERIALIZABLE_CLASS_CONSTRUCTOR2T(CurrentNodeIdentifierIterator,
+ NaryBaseIterator<CurrentNodeIdentifierIterator, PlanIteratorState>);
+
+ void serialize( ::zorba::serialization::Archiver& ar)
+ {
+ serialize_baseclass(ar,
+ (NaryBaseIterator<CurrentNodeIdentifierIterator, PlanIteratorState>*)this);
+ }
+
+ CurrentNodeIdentifierIterator(
+ static_context* sctx,
+ const QueryLoc& loc,
+ std::vector<PlanIter_t>& children)
+ :
+ NaryBaseIterator<CurrentNodeIdentifierIterator, PlanIteratorState>(sctx, loc, children)
+ {}
+
+ virtual ~CurrentNodeIdentifierIterator();
+
+ void accept(PlanIterVisitor& v) const;
+
+ bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
+ *
+ * declare function ref:has-identifier($node as node) as xs:boolean
+ *
+ * Author: Federico Cavalieri
+ */
+class HasIdentifierIterator : public NaryBaseIterator<HasIdentifierIterator, PlanIteratorState>
+{
+public:
+ SERIALIZABLE_CLASS(HasIdentifierIterator);
+
+ SERIALIZABLE_CLASS_CONSTRUCTOR2T(HasIdentifierIterator,
+ NaryBaseIterator<HasIdentifierIterator, PlanIteratorState>);
+
+ void serialize( ::zorba::serialization::Archiver& ar)
+ {
+ serialize_baseclass(ar,
+ (NaryBaseIterator<HasIdentifierIterator, PlanIteratorState>*)this);
+ }
+
+ HasIdentifierIterator(
+ static_context* sctx,
+ const QueryLoc& loc,
+ std::vector<PlanIter_t>& children)
+ :
+ NaryBaseIterator<HasIdentifierIterator, PlanIteratorState>(sctx, loc, children)
+ {}
+
+ virtual ~HasIdentifierIterator();
+
+ void accept(PlanIterVisitor& v) const;
+
+ bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
+ *
+ * declare function ref:node-by-identifier($identifier as xs:string) as node()?
+ *
+ * Author: Federico Cavalieri
+ */
+class NodeByIdentifierIterator : public NaryBaseIterator<NodeByIdentifierIterator, PlanIteratorState>
+{
+public:
+ SERIALIZABLE_CLASS(NodeByIdentifierIterator);
+
+ SERIALIZABLE_CLASS_CONSTRUCTOR2T(NodeByIdentifierIterator,
+ NaryBaseIterator<NodeByIdentifierIterator, PlanIteratorState>);
+
+ void serialize( ::zorba::serialization::Archiver& ar)
+ {
+ serialize_baseclass(ar,
+ (NaryBaseIterator<NodeByIdentifierIterator, PlanIteratorState>*)this);
+ }
+
+ NodeByIdentifierIterator(
+ static_context* sctx,
+ const QueryLoc& loc,
+ std::vector<PlanIter_t>& children)
+ :
+ NaryBaseIterator<NodeByIdentifierIterator, PlanIteratorState>(sctx, loc, children)
+ {}
+
+ virtual ~NodeByIdentifierIterator();
+
+ void accept(PlanIterVisitor& v) const;
+
+ bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
*
* Iterator to implement the zorba:node-reference function.
*
=== modified file 'src/runtime/spec/mappings.xml'
--- src/runtime/spec/mappings.xml 2011-07-26 21:03:39 +0000
+++ src/runtime/spec/mappings.xml 2011-09-28 09:26:25 +0000
@@ -24,6 +24,10 @@
define="ZORBA_NODEREF_FN_NS"
prefix="fn-zorba-ref"/>
+ <zorba:namespace uri="http://www.zorba-xquery.com/modules/node-identifier";
+ define="ZORBA_NODEID_FN_NS"
+ prefix="zorba-node-identifier"/>
+
<zorba:namespace uri="http://www.zorba-xquery.com/modules/schema";
define="ZORBA_SCHEMA_FN_NS"
prefix="fn-zorba-schema"/>
=== modified file 'src/runtime/spec/nodes/nodes.xml'
--- src/runtime/spec/nodes/nodes.xml 2011-08-04 02:39:56 +0000
+++ src/runtime/spec/nodes/nodes.xml 2011-09-28 09:26:25 +0000
@@ -11,6 +11,90 @@
xmlns:zorba="http://www.zorba-xquery.com";
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
xsi:schemaLocation="http://www.zorba-xquery.com ../runtime.xsd">
+
+<!--
+/*******************************************************************************
+********************************************************************************/
+-->
+ <zorba:iterator name="NodeIdentifierIterator">
+
+ <zorba:description author="Federico Cavalieri">
+ declare function id:node-identifier($node as node) as xs:string
+ </zorba:description>
+
+ <zorba:function>
+
+ <zorba:signature localname="node-identifier" prefix="zorba-node-identifier">
+ <zorba:param>node()</zorba:param>
+ <zorba:output>xs:string</zorba:output>
+ </zorba:signature>
+
+ </zorba:function>
+
+ </zorba:iterator>
+
+<!--
+/*******************************************************************************
+********************************************************************************/
+-->
+ <zorba:iterator name="CurrentNodeIdentifierIterator">
+
+ <zorba:description author="Federico Cavalieri">
+ declare function id:current-node-identifier($node as node) as xs:string
+ </zorba:description>
+
+ <zorba:function>
+
+ <zorba:signature localname="current-node-identifier" prefix="zorba-node-identifier">
+ <zorba:param>node()</zorba:param>
+ <zorba:output>xs:string</zorba:output>
+ </zorba:signature>
+
+ </zorba:function>
+
+ </zorba:iterator>
+
+<!--
+/*******************************************************************************
+********************************************************************************/
+-->
+ <zorba:iterator name="HasIdentifierIterator">
+
+ <zorba:description author="Federico Cavalieri">
+ declare function ref:has-identifier($node as node) as xs:boolean
+ </zorba:description>
+
+ <zorba:function>
+
+ <zorba:signature localname="has-identifier" prefix="zorba-node-identifier">
+ <zorba:param>node()</zorba:param>
+ <zorba:output>xs:boolean</zorba:output>
+ </zorba:signature>
+
+ </zorba:function>
+
+ </zorba:iterator>
+
+<!--
+/*******************************************************************************
+********************************************************************************/
+-->
+ <zorba:iterator name="NodeByIdentifierIterator">
+
+ <zorba:description author="Federico Cavalieri">
+ declare function ref:node-by-identifier($identifier as xs:string) as node()?
+ </zorba:description>
+
+ <zorba:function>
+
+ <zorba:signature localname="node-by-identifier" prefix="zorba-node-identifier">
+ <zorba:param>xs:string</zorba:param>
+ <zorba:output>node()?</zorba:output>
+ </zorba:signature>
+
+ </zorba:function>
+
+ </zorba:iterator>
<!--
/*******************************************************************************
=== modified file 'src/runtime/visitors/pregenerated/planiter_visitor.h'
--- src/runtime/visitors/pregenerated/planiter_visitor.h 2011-08-17 20:22:07 +0000
+++ src/runtime/visitors/pregenerated/planiter_visitor.h 2011-09-28 09:26:25 +0000
@@ -303,6 +303,14 @@
class FrexpIterator;
+ class NodeIdentifierIterator;
+
+ class CurrentNodeIdentifierIterator;
+
+ class HasIdentifierIterator;
+
+ class NodeByIdentifierIterator;
+
class NodeReferenceIterator;
class NodeByReferenceIterator;
@@ -955,6 +963,18 @@
virtual void beginVisit ( const FrexpIterator& ) = 0;
virtual void endVisit ( const FrexpIterator& ) = 0;
+ virtual void beginVisit ( const NodeIdentifierIterator& ) = 0;
+ virtual void endVisit ( const NodeIdentifierIterator& ) = 0;
+
+ virtual void beginVisit ( const CurrentNodeIdentifierIterator& ) = 0;
+ virtual void endVisit ( const CurrentNodeIdentifierIterator& ) = 0;
+
+ virtual void beginVisit ( const HasIdentifierIterator& ) = 0;
+ virtual void endVisit ( const HasIdentifierIterator& ) = 0;
+
+ virtual void beginVisit ( const NodeByIdentifierIterator& ) = 0;
+ virtual void endVisit ( const NodeByIdentifierIterator& ) = 0;
+
virtual void beginVisit ( const NodeReferenceIterator& ) = 0;
virtual void endVisit ( const NodeReferenceIterator& ) = 0;
=== modified file 'src/runtime/visitors/pregenerated/printer_visitor.cpp'
--- src/runtime/visitors/pregenerated/printer_visitor.cpp 2011-08-17 20:22:07 +0000
+++ src/runtime/visitors/pregenerated/printer_visitor.cpp 2011-09-28 09:26:25 +0000
@@ -2013,6 +2013,62 @@
// </FrexpIterator>
+// <NodeIdentifierIterator>
+void PrinterVisitor::beginVisit ( const NodeIdentifierIterator& a) {
+ thePrinter.startBeginVisit("NodeIdentifierIterator", ++theId);
+ printCommons( &a, theId );
+ thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const NodeIdentifierIterator& ) {
+ thePrinter.startEndVisit();
+ thePrinter.endEndVisit();
+}
+// </NodeIdentifierIterator>
+
+
+// <CurrentNodeIdentifierIterator>
+void PrinterVisitor::beginVisit ( const CurrentNodeIdentifierIterator& a) {
+ thePrinter.startBeginVisit("CurrentNodeIdentifierIterator", ++theId);
+ printCommons( &a, theId );
+ thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const CurrentNodeIdentifierIterator& ) {
+ thePrinter.startEndVisit();
+ thePrinter.endEndVisit();
+}
+// </CurrentNodeIdentifierIterator>
+
+
+// <HasIdentifierIterator>
+void PrinterVisitor::beginVisit ( const HasIdentifierIterator& a) {
+ thePrinter.startBeginVisit("HasIdentifierIterator", ++theId);
+ printCommons( &a, theId );
+ thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const HasIdentifierIterator& ) {
+ thePrinter.startEndVisit();
+ thePrinter.endEndVisit();
+}
+// </HasIdentifierIterator>
+
+
+// <NodeByIdentifierIterator>
+void PrinterVisitor::beginVisit ( const NodeByIdentifierIterator& a) {
+ thePrinter.startBeginVisit("NodeByIdentifierIterator", ++theId);
+ printCommons( &a, theId );
+ thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const NodeByIdentifierIterator& ) {
+ thePrinter.startEndVisit();
+ thePrinter.endEndVisit();
+}
+// </NodeByIdentifierIterator>
+
+
// <NodeReferenceIterator>
void PrinterVisitor::beginVisit ( const NodeReferenceIterator& a) {
thePrinter.startBeginVisit("NodeReferenceIterator", ++theId);
=== modified file 'src/runtime/visitors/pregenerated/printer_visitor.h'
--- src/runtime/visitors/pregenerated/printer_visitor.h 2011-08-17 20:22:07 +0000
+++ src/runtime/visitors/pregenerated/printer_visitor.h 2011-09-28 09:26:25 +0000
@@ -457,6 +457,18 @@
void beginVisit( const FrexpIterator& );
void endVisit ( const FrexpIterator& );
+ void beginVisit( const NodeIdentifierIterator& );
+ void endVisit ( const NodeIdentifierIterator& );
+
+ void beginVisit( const CurrentNodeIdentifierIterator& );
+ void endVisit ( const CurrentNodeIdentifierIterator& );
+
+ void beginVisit( const HasIdentifierIterator& );
+ void endVisit ( const HasIdentifierIterator& );
+
+ void beginVisit( const NodeByIdentifierIterator& );
+ void endVisit ( const NodeByIdentifierIterator& );
+
void beginVisit( const NodeReferenceIterator& );
void endVisit ( const NodeReferenceIterator& );
=== modified file 'src/store/api/copymode.h'
--- src/store/api/copymode.h 2011-06-14 17:26:33 +0000
+++ src/store/api/copymode.h 2011-09-28 09:26:25 +0000
@@ -34,13 +34,15 @@
bool theTypePreserve;
bool theNsPreserve;
bool theNsInherit;
+ bool theFreezeIdentifier;
CopyMode()
:
theDoCopy(true),
theTypePreserve(true),
theNsPreserve(true),
- theNsInherit(true)
+ theNsInherit(true),
+ theFreezeIdentifier(false)
{
}
@@ -49,7 +51,8 @@
theDoCopy(aCopyMode.theDoCopy),
theTypePreserve(aCopyMode.theTypePreserve),
theNsPreserve(aCopyMode.theNsPreserve),
- theNsInherit(aCopyMode.theNsInherit)
+ theNsInherit(aCopyMode.theNsInherit),
+ theFreezeIdentifier(aCopyMode.theFreezeIdentifier)
{
}
@@ -57,12 +60,14 @@
bool copy,
bool typePreserve,
bool nsPreserve,
- bool nsInherit)
+ bool nsInherit,
+ bool freezeIdentifier=false)
{
theDoCopy = copy;
theTypePreserve = typePreserve;
theNsPreserve = nsPreserve;
theNsInherit = nsInherit;
+ theFreezeIdentifier=freezeIdentifier;
}
std::string toString() const
@@ -76,6 +81,8 @@
s += (theNsPreserve ? "T" : "F");
s += " ";
s += (theNsInherit ? "T" : "F");
+ s += " ";
+ s += (theFreezeIdentifier ? "T" : "F");
s += "]";
return s;
}
=== modified file 'src/store/api/store.h'
--- src/store/api/store.h 2011-09-27 10:43:46 +0000
+++ src/store/api/store.h 2011-09-28 09:26:25 +0000
@@ -105,9 +105,38 @@
* @returns referenced item if it exists, otherwise NULL
*/
virtual bool getNodeByReference(Item_t& result, const Item* uri) = 0;
-
-
- /* --------------------------- Node Id Management ---------------------------*/
+
+
+ /* ------------------------ Node Identifiers Management ---------------------------*/
+
+ /**
+ * Computes the identifier of the given node.
+ *
+ * @param result the identifier as an item of type xs:string
+ * @param node XDM node
+ * @return whether the identifier has been created successfully
+ */
+ virtual bool getIdentifier(Item_t& result, Item* node) = 0;
+
+ /**
+ * Returns whether an identifier has been generated for the given node.
+ *
+ * @param item XDM node
+ * @return whether an identifier has been generated for the given node.
+ */
+ virtual bool hasIdentifier(const Item* node) = 0;
+
+ /**
+ * Returns the node which is associated to the given identifier.
+ *
+ * @param result the node or NULL if not found
+ * @param identifier the identifier to dereference
+ * @returns whether the referenced item exists, NULL otherwise
+ */
+ virtual bool getNodeByIdentifier(store::Item_t& result, const zstring& identifier) = 0;
+
+
+ /* ------------------------ Node Identity Management ---------------------------*/
/**
* Compares two nodes, based on their node id.
=== modified file 'src/store/naive/node_items.cpp'
--- src/store/naive/node_items.cpp 2011-09-23 14:26:00 +0000
+++ src/store/naive/node_items.cpp 2011-09-28 09:26:25 +0000
@@ -693,6 +693,7 @@
}
#endif
+ GET_STORE().unregisterNode(this);
delete this;
}
@@ -1387,6 +1388,10 @@
throw;
}
+ if (haveFrozenIdentifier() || copymode.theFreezeIdentifier)
+ GET_STORE().copyIdentifier(this,copyNode);
+
+
NODE_TRACE1("}");
NODE_TRACE1("Copied doc node " << this << " to node " << copyNode);
@@ -2011,6 +2016,9 @@
throw;
}
+ if (haveFrozenIdentifier() || copymode.theFreezeIdentifier)
+ GET_STORE().copyIdentifier(this,copyNode);
+
NODE_TRACE1("Copied elem node " << this << " to node " << copyNode
<< " name = " << theName->getStringValue() << " parent = "
<< (parent ? parent : 0x0)
@@ -3125,6 +3133,9 @@
throw;
}
+ if (haveFrozenIdentifier() || copymode.theFreezeIdentifier)
+ GET_STORE().copyIdentifier(this,copyNode);
+
NODE_TRACE1("Copied attribute node " << this << " to node " << copyNode
<< " name = " << theName->show() << " parent = "
<< std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
@@ -3593,6 +3604,9 @@
throw;
}
+ if (haveFrozenIdentifier() || copymode.theFreezeIdentifier)
+ GET_STORE().copyIdentifier(this,copyNode);
+
NODE_TRACE1("Copied text node " << this << " to node " << copyNode
<< " parent = " << std::hex << (parent ? (ulong)parent : 0)
<< " pos = " << pos);
@@ -4079,6 +4093,9 @@
throw;
}
+ if (haveFrozenIdentifier() || copymode.theFreezeIdentifier)
+ GET_STORE().copyIdentifier(this,copyNode);
+
NODE_TRACE1("Copied pi node " << this << " to node " << copyNode
<< " parent = " << std::hex << (parent ? (ulong)parent : 0)
<< " pos = " << pos);
@@ -4202,6 +4219,9 @@
throw;
}
+ if (haveFrozenIdentifier() || copymode.theFreezeIdentifier)
+ GET_STORE().copyIdentifier(this,copyNode);
+
NODE_TRACE1("Copied coment node " << this << " to node " << copyNode
<< " parent = " << std::hex << (parent ? (ulong)parent : 0)
<< " pos = " << pos);
=== modified file 'src/store/naive/node_items.h'
--- src/store/naive/node_items.h 2011-09-23 14:26:00 +0000
+++ src/store/naive/node_items.h 2011-09-28 09:26:25 +0000
@@ -325,14 +325,16 @@
// For element nodes only. The flag is set for a node N if there is another
// node M in its subtree such that N and M have the same name.
- IsRecursive = 0x4000
+ IsRecursive = 0x4000,
#ifndef EMBEDED_TYPE
- ,
// For element and attribute nodes only. The flag is set if the node has
// a type other than untyped (for elements) or untypedAtomic (for attributes)
- HaveType = 0x8000
+ HaveType = 0x8000,
#endif
+
+ HaveIdentifier = 0x10000,
+ HaveFrozenIdentifier = 0x20000
};
protected:
@@ -495,6 +497,15 @@
void setFlags(uint32_t flags) { theFlags = flags; }
+ bool haveIdentifier() const { return (theFlags & HaveIdentifier) != 0; }
+ void setHaveIdentifier() { theFlags |= HaveIdentifier; }
+ void resetHaveIdentifier() { theFlags &= ~HaveIdentifier; }
+
+ bool haveFrozenIdentifier() const { return (theFlags & HaveFrozenIdentifier) != 0; }
+ void setHaveFrozenIdentifier() { theFlags |= HaveFrozenIdentifier; }
+ void resetHaveFrozenIdentifier() { theFlags &= ~HaveFrozenIdentifier; }
+
+
#ifndef ZORBA_NO_FULL_TEXT
FTTokenIterator_t getTokens( TokenizerProvider const&, Tokenizer::Numbers&,
locale::iso639_1::type, bool = false ) const;
=== modified file 'src/store/naive/simple_store.cpp'
--- src/store/naive/simple_store.cpp 2011-09-26 22:49:54 +0000
+++ src/store/naive/simple_store.cpp 2011-09-28 09:26:25 +0000
@@ -57,6 +57,7 @@
#include "store/naive/pul_primitive_factory.h"
#include "util/cxx_util.h"
+#include "util/uuid/uuid.h"
#ifndef ZORBA_NO_FULL_TEXT
#include "runtime/full_text/default_tokenizer.h"
@@ -334,6 +335,24 @@
theNodeFactory = NULL;
}
+ if(theNodeToIdentifiersMap.size()>0)
+ {
+ std::map<const store::Item *,zstring>::iterator iter= theNodeToIdentifiersMap.begin();
+ std::map<const store::Item *,zstring>::iterator end= theNodeToIdentifiersMap.end();
+ for (; iter != end; ++iter)
+ std::cerr << "Identifier: " << iter->first << "is still in the nodes to identifiers map" << std::endl;
+ ZORBA_FATAL(0, theNodeToIdentifiersMap.size()+" node identifiers still in the nodes to identifiers map");
+ }
+
+ if(theIdentifiersToNodeMap.size()>0)
+ {
+ std::map<const zstring,const store::Item *>::iterator iter= theIdentifiersToNodeMap.begin();
+ std::map<const zstring,const store::Item *>::iterator end= theIdentifiersToNodeMap.end();
+ for (; iter != end; ++iter)
+ std::cerr << "Identifier: " << iter->first << "is still in the identifiers to nodes map" << std::endl;
+ ZORBA_FATAL(0, theIdentifiersToNodeMap.size()+" node identifiers still in the identifiers to nodes map");
+ }
+
// do cleanup of the libxml2 library
// however, after that, a user will have to call
// LIBXML_TEST_VERSION if he wants to use libxml2
@@ -1663,6 +1682,179 @@
}
}
+/* ------------------------ Node Identifiers Management ---------------------------*/
+
+/**
+ * Computes the identifier of the given node.
+ *
+ * @param result identifier as an item of type xs:string
+ * @param node XDM node
+ * @return whether the identifier has been created successfully
+ */
+bool SimpleStore::getIdentifier(store::Item_t& result, store::Item* node)
+{
+ std::map<const store::Item *,zstring>::iterator resIt;
+ if ((resIt=theNodeToIdentifiersMap.find(node))!=theNodeToIdentifiersMap.end())
+ {
+ //The node has already an associated identifier
+ zstring id=resIt->second;
+ return theItemFactory->createString(result, id);
+ }
+
+ uuid_t uuid;
+ uuid_create(&uuid);
+ zstring uuidStr=uuidToString(uuid);
+ zstring uuidStr2=uuidStr;
+ zstring uuidStr3=uuidStr;
+ static_cast<const XmlNode*>(node)->setHaveIdentifier();
+ theNodeToIdentifiersMap[node]=uuidStr;
+ theIdentifiersToNodeMap[uuidStr2]=node;
+ return theItemFactory->createString(result, uuidStr3);
+}
+
+/**
+ * Returns the already computed identifier of the given node.
+ * If no identifier has already been computed for the given node
+ * error ZAPI0090 is raised.
+ *
+ * @param result identifier as an item of type xs:string
+ * @param node XDM node
+ * @return whether the identifier has been created successfully
+ */
+bool SimpleStore::getCurrentIdentifier(store::Item_t& result, const store::Item* node)
+{
+ std::map<const store::Item *,zstring>::iterator resIt;
+ if ((resIt=theNodeToIdentifiersMap.find(node))!=theNodeToIdentifiersMap.end())
+ {
+ //The node has already an associated identifier
+ zstring id=resIt->second;
+ return theItemFactory->createString(result, id);
+ }
+ //The node has no identifier
+ throw ZORBA_EXCEPTION(zerr::ZAPI0090_NO_CURRENT_IDENTIFIER);
+}
+
+/**
+ * Returns the node which is associated to the given identifier.
+ *
+ * @param result the node or NULL if not found
+ * @param identifier the identifier to dereference
+ * @returns whether the referenced item exists, NULL otherwise
+ */
+bool SimpleStore::getNodeByIdentifier(store::Item_t& result, const zstring& identifier)
+{
+ std::map<const zstring, const store::Item *>::iterator resIt;
+ if ((resIt=theIdentifiersToNodeMap.find(identifier))!=theIdentifiersToNodeMap.end())
+ {
+ result=resIt->second;
+ return true;
+ }
+ result=NULL;
+ return false;
+}
+
+/**
+ * Returns whether an identifier has been generated for the given node.
+ *
+ * @param item XDM node
+ * @return whether an identifier has been generated for the given node.
+ */
+bool SimpleStore::hasIdentifier(const store::Item* node)
+{
+ return theNodeToIdentifiersMap.find(node)!=theNodeToIdentifiersMap.end();
+}
+
+/**
+ * Copies the identifier of a source node to a target node. The source
+ * node must already have an identifier. The target nodes acquires the
+ * source identifier but it is not registered in the identifier-to-node
+ * map. The target node also get its "haveFrozenIdentifier" flag set.
+ * Used in PUL manipulation.
+ *
+ * @param source source XDM node
+ * @param target target XDM node
+ */
+void SimpleStore::copyIdentifier(const XmlNode* source, XmlNode* target)
+{
+ store::Item_t identifier;
+ getCurrentIdentifier(identifier,source);
+ unregisterNode(target);
+ target->setHaveIdentifier();
+ target->setHaveFrozenIdentifier();
+ theNodeToIdentifiersMap[target]=identifier->getStringValue();
+}
+
+/**
+ * Sets the identifier of a node to a given value. The "haveFrozenIdentifer"
+ * flag is also set.
+ * Used in PUL manipulation.
+ *
+ * @param node XDM node
+ * @param identifier the identifier to set
+ */
+void SimpleStore::restoreIdentifier(XmlNode* node, const zstring& identifier)
+{
+ unregisterNode(node);
+ theNodeToIdentifiersMap[node]=identifier;
+ node->setHaveIdentifier();
+ node->setHaveFrozenIdentifier();
+}
+
+/**
+ * Unfreezes the identifier of a given node:
+ * - Registers the node in the identifiers to node map
+ * - Resets the node "haveFrozenIdentifier" flag
+ * The node must already have an identifier, otherwise
+ * error ZAPI0090 is raised.
+ * The node identifier must not be used for any other
+ * node in the identifier-to-node map, otherwise
+ * error ZAPI0092 is raised.
+ * Used in PUL manipulation.
+ *
+ * @param node XDM node
+ */
+void SimpleStore::unfreezeIdentifier(XmlNode* node)
+{
+ store::Item_t identifier;
+ getCurrentIdentifier(identifier,node);
+ store::Item_t result;
+ if (getNodeByIdentifier(result, identifier->getStringValue()))
+ {
+ throw XQUERY_EXCEPTION(
+ zerr::ZAPI0092_IDENTIFIER_ALREADY_PRESENT,
+ ERROR_PARAMS(identifier->getStringValue())
+ );
+ }
+ theIdentifiersToNodeMap[identifier->getStringValue()]=node;
+ node->resetHaveFrozenIdentifier();
+}
+
+/**
+ * Removes a node from the identifier-to-nodes and nodes-to-identifiers maps.
+ *
+ * @param node XDM node
+ * @return whether the node was registered or not.
+ */
+bool SimpleStore::unregisterNode(XmlNode* node)
+{
+ if (!node->haveIdentifier())
+ return false;
+ std::map<const store::Item *,zstring>::iterator resIt;
+ if ((resIt=theNodeToIdentifiersMap.find(node))!=theNodeToIdentifiersMap.end())
+ {
+ zstring value=resIt->second;
+ theNodeToIdentifiersMap.erase(resIt);
+ node->resetHaveIdentifier();
+ if (!node->haveFrozenIdentifier())
+ theIdentifiersToNodeMap.erase(value);
+ else
+ node->resetHaveFrozenIdentifier();
+ //if a node has a frozen identifier it is not registered in the identifiers to node map
+ return true;
+ }
+ else
+ return false;
+}
/*******************************************************************************
=== modified file 'src/store/naive/simple_store.h'
--- src/store/naive/simple_store.h 2011-09-26 22:49:54 +0000
+++ src/store/naive/simple_store.h 2011-09-28 09:26:25 +0000
@@ -142,6 +142,13 @@
long theTraceLevel;
+ /* ------------------------ Node Identifiers Management ---------------------------*/
+
+ std::map<const zstring, const store::Item *> theIdentifiersToNodeMap;
+ std::map<const store::Item *, zstring> theNodeToIdentifiersMap;
+
+ /* ------------------------ Node Identifiers Management ---------------------------*/
+
#ifndef ZORBA_NO_FULL_TEXT
internal::StemmerProvider const * theStemmerProvider;
TokenizerProvider const * theTokenizerProvider;
@@ -332,6 +339,27 @@
bool getNodeByReference(store::Item_t& result, const store::Item* uri);
+ /* ------------------------ Node Identifiers Management ---------------------------*/
+
+ bool getIdentifier(store::Item_t& result, store::Item* node);
+
+ bool getCurrentIdentifier(store::Item_t& result, const store::Item* node);
+
+ bool hasIdentifier(const store::Item* node);
+
+ bool getNodeByIdentifier(store::Item_t& result, const zstring& identifier);
+
+ bool unregisterNode(XmlNode* node);
+
+ void copyIdentifier(const XmlNode* source, XmlNode* target);
+
+ void restoreIdentifier(XmlNode* node, const zstring& identifier);
+
+ void unfreezeIdentifier(XmlNode* node);
+
+
+ /* ------------------------ Node Identifiers Management ---------------------------*/
+
store::TempSeq_t createTempSeq(bool lazy);
store::TempSeq_t createTempSeq(
=== added directory 'test/rbkt/ExpQueryResults/zorba/identifiers'
=== added file 'test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_1.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_1.xml.res 2011-09-28 09:26:25 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result><before hasid="false">36</before><after hasid="true">36</after><stable>true</stable></result>
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_2.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_2.xml.res 2011-09-28 09:26:25 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result><out-of-module><root><child>text</child></root></out-of-module><temporary-variable/><in-scope><root><child>text</child></root></in-scope></result>
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_3.xml.res'
--- test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_3.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_3.xml.res 2011-09-28 09:26:25 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result><before>No current id</before><get>36</get><after equal="true">36</after></result>
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_1.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_1.xml.res 2011-09-28 09:26:25 +0000
@@ -0,0 +1,1 @@
+<doc>true true true true true true</doc><collection>true true true true true true</collection><in-memory>true true true true true true</in-memory>
=== added file 'test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_2.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_2.xml.res 2011-09-28 09:26:25 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<locked>true true true true true</locked><unlocked>false true false false true</unlocked>
=== added file 'test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_3.xml.res'
--- test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_3.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_3.xml.res 2011-09-28 09:26:25 +0000
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result><test1><?processinginstruction someprocessinginstruction?><!-- This is a comment --><test2>
+ <?processinginstruction someprocessinginstruction1?>
+ <?processinginstruction someprocessinginstruction2?>
+ <?processinginstruction someprocessinginstruction3?>
+ <?processinginstruction someprocessinginstruction4?>
+ <!-- This is a comment1 -->
+ <!-- This is a comment2 -->
+ <!-- This is a comment3 -->
+ <nonEmptyElement1 emptyAttribute2="" emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement1>
+
+ <nonEmptyElement2 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement2>
+
+ <nonEmptyElement3 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement3>
+
+ <nonEmptyElement4 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement4>
+
+ <nonEmptyElement5 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement5>
+</test2></test1><test2><?processinginstruction someprocessinginstruction?><!-- This is a comment --><test2>
+ <?processinginstruction someprocessinginstruction1?>
+ <?processinginstruction someprocessinginstruction2?>
+ <?processinginstruction someprocessinginstruction3?>
+ <?processinginstruction someprocessinginstruction4?>
+ <!-- This is a comment1 -->
+ <!-- This is a comment2 -->
+ <!-- This is a comment3 -->
+ <nonEmptyElement1 emptyAttribute2="" emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement1>
+
+ <nonEmptyElement2 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement2>
+
+ <nonEmptyElement3 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement3>
+
+ <nonEmptyElement4 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement4>
+
+ <nonEmptyElement5 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement5>
+</test2></test2><test3><?processinginstruction someprocessinginstruction?><!-- This is a comment --><test2>
+ <?processinginstruction someprocessinginstruction1?>
+ <?processinginstruction someprocessinginstruction2?>
+ <?processinginstruction someprocessinginstruction3?>
+ <?processinginstruction someprocessinginstruction4?>
+ <!-- This is a comment1 -->
+ <!-- This is a comment2 -->
+ <!-- This is a comment3 -->
+ <nonEmptyElement1 emptyAttribute2="" emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement1>
+
+ <nonEmptyElement2 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement2>
+
+ <nonEmptyElement3 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement3>
+
+ <nonEmptyElement4 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement4>
+
+ <nonEmptyElement5 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement5>
+</test2></test3><testCXDM><?processinginstruction someprocessinginstruction?><!-- This is a comment --><test2>
+ <?processinginstruction someprocessinginstruction1?>
+ <?processinginstruction someprocessinginstruction2?>
+ <?processinginstruction someprocessinginstruction3?>
+ <?processinginstruction someprocessinginstruction4?>
+ <!-- This is a comment1 -->
+ <!-- This is a comment2 -->
+ <!-- This is a comment3 -->
+ <nonEmptyElement1 emptyAttribute2="" emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement1>
+
+ <nonEmptyElement2 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement2>
+
+ <nonEmptyElement3 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement3>
+
+ <nonEmptyElement4 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement4>
+
+ <nonEmptyElement5 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+ <emptyElement/>
+ <textElement>sometext</textElement>
+ </nonEmptyElement5>
+</test2></testCXDM></result>
\ No newline at end of file
=== added directory 'test/rbkt/Queries/zorba/identifiers'
=== added file 'test/rbkt/Queries/zorba/identifiers/identifiers.xqlib'
--- test/rbkt/Queries/zorba/identifiers/identifiers.xqlib 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/identifiers/identifiers.xqlib 2011-09-28 09:26:25 +0000
@@ -0,0 +1,3 @@
+module namespace idd= "http://www.zorba-xquery.com/identifiers";;
+
+declare variable $idd:node:=<root><child>text</child></root>;
=== added file 'test/rbkt/Queries/zorba/identifiers/identifiers_1.xq'
--- test/rbkt/Queries/zorba/identifiers/identifiers_1.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/identifiers/identifiers_1.xq 2011-09-28 09:26:25 +0000
@@ -0,0 +1,15 @@
+import module namespace id = "http://www.zorba-xquery.com/modules/node-identifier";;
+
+variable $node:=<root><child>text</child></root>;
+
+variable $before-hasid:=id:has-identifier($node);
+variable $before-currentid:=id:node-identifier($node);
+variable $got:=id:node-identifier($node);
+variable $after-hasid:=id:has-identifier($node);
+variable $after:=id:node-identifier($node);
+
+<result>
+<before hasid="{$before-hasid}">{fn:string-length($before-currentid)}</before>
+<after hasid="{$after-hasid}">{fn:string-length($got)}</after>
+<stable>{$got eq $after}</stable>
+</result>
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/identifiers/identifiers_2.xq'
--- test/rbkt/Queries/zorba/identifiers/identifiers_2.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/identifiers/identifiers_2.xq 2011-09-28 09:26:25 +0000
@@ -0,0 +1,21 @@
+import module namespace idd = "http://www.zorba-xquery.com/identifiers"; at "identifiers.xqlib";
+import module namespace id = "http://www.zorba-xquery.com/modules/node-identifier";;
+
+
+declare function local:test()
+{
+ let $node:=<root><child>text</child></root>
+ return id:node-identifier($node)
+};
+
+variable $node:=<root><child>text</child></root>;
+variable $id1:=id:node-identifier($idd:node);
+variable $id2:=local:test();
+variable $id3:=id:node-identifier($node);
+
+
+<result>
+<out-of-module>{id:node-by-identifier($id1)}</out-of-module>
+<temporary-variable>{id:node-by-identifier($id2)}</temporary-variable>
+<in-scope>{id:node-by-identifier($id3)}</in-scope>
+</result>
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/identifiers/identifiers_3.xq'
--- test/rbkt/Queries/zorba/identifiers/identifiers_3.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/identifiers/identifiers_3.xq 2011-09-28 09:26:25 +0000
@@ -0,0 +1,23 @@
+import module namespace idd = "http://www.zorba-xquery.com/identifiers"; at "identifiers.xqlib";
+import module namespace id = "http://www.zorba-xquery.com/modules/node-identifier";;
+
+
+variable $node:=<root><child>text</child></root>;
+variable $id1:=
+try
+{
+ id:current-node-identifier($node)
+}
+catch ZAPI0090
+{
+ "No current id"
+};
+variable $id2:=id:node-identifier($node);
+variable $id3:=id:current-node-identifier($node);
+
+
+<result>
+<before>{$id1}</before>
+<get>{fn:string-length($id2)}</get>
+<after equal="{$id2 =$id3}">{fn:string-length($id3)}</after>
+</result>
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/identifiers/identifiers_4.spec'
--- test/rbkt/Queries/zorba/identifiers/identifiers_4.spec 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/identifiers/identifiers_4.spec 2011-09-28 09:26:25 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/errors:ZAPI0091
=== added file 'test/rbkt/Queries/zorba/identifiers/identifiers_4.xq'
--- test/rbkt/Queries/zorba/identifiers/identifiers_4.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/identifiers/identifiers_4.xq 2011-09-28 09:26:25 +0000
@@ -0,0 +1,3 @@
+import module namespace id = "http://www.zorba-xquery.com/modules/node-identifier";;
+
+id:node-by-identifier("this is not an id")
\ No newline at end of file