Skip to content
This repository was archived by the owner on Sep 16, 2024. It is now read-only.

Commit fbbead3

Browse files
authored
Merge pull request #143 from hansenmc/importExport
Adjust export/import to preserve query elements
2 parents 7f4177d + 585e453 commit fbbead3

File tree

4 files changed

+206
-163
lines changed

4 files changed

+206
-163
lines changed
Lines changed: 20 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -1,169 +1,26 @@
11
package com.marklogic.client.ext.qconsole.impl;
22

3-
/**
4-
* This scripts are defined as strings so that it's easy to reuse this in an environment like Gradle without
5-
* having to read files from the classpath.
6-
*/
7-
public class QconsoleScripts {
3+
import java.io.BufferedReader;
4+
import java.io.InputStream;
5+
import java.io.InputStreamReader;
6+
import java.nio.charset.StandardCharsets;
7+
import java.util.stream.Collectors;
88

9-
/**
10-
* This relies on internal APIs in the qconsole-model function that have changed between MarkLogic 8 and 9.
11-
* Specifically, qconsole-model:default-content-source() in ML8 was removed and qconsole-model:default-database()
12-
* can be used instead.
13-
*/
14-
public static final String IMPORT = "xquery version \"1.0-ml\";\n" +
15-
"\n" +
16-
"declare namespace qconsole=\"http://marklogic.com/appservices/qconsole\";\n" +
17-
"\n" +
18-
"import module namespace amped-qconsole = \"http://marklogic.com/appservices/qconsole/util-amped\" at \"/MarkLogic/appservices/qconsole/qconsole-amped.xqy\";\n" +
19-
"import module namespace idecl = \"http://marklogic.com/appservices/qconsole/decl\" at \"/MarkLogic/appservices/qconsole/qconsole-decl.xqy\";\n" +
20-
"import module namespace qconsole-model = \"http://marklogic.com/appservices/qconsole/model\" at \"/MarkLogic/appservices/qconsole/qconsole-model.xqy\";\n" +
21-
"\n" +
22-
"declare namespace eval = \"xdmp:eval\";\n" +
23-
"\n" +
24-
"declare variable $exported-workspace as node() external;\n" +
25-
"declare variable $user as xs:string external;\n" +
26-
"\n" +
27-
"declare function local:qconsole-eval(\n" +
28-
" $xquery as xs:string,\n" +
29-
" $vars as item()*,\n" +
30-
" $options as element(eval:options)?\n" +
31-
") as item()*\n" +
32-
"{ xdmp:log(text{(\"local:qconsole-eval\", xdmp:quote($vars))}),\n" +
33-
" xdmp:security-assert(\"http://marklogic.com/xdmp/privileges/qconsole\", \"execute\"),\n" +
34-
" xdmp:eval($xquery, $vars, <options xmlns=\"xdmp:eval\">\n" +
35-
" <database>{xdmp:database(\"App-Services\")}</database>\n" +
36-
" </options>)\n" +
37-
"};\n" +
38-
"\n" +
39-
"declare function local:import-workspace(\n" +
40-
" $workspace as element(),\n" +
41-
" $user as xs:string \n" +
42-
") as xs:string*\n" +
43-
"{\n" +
44-
" let $eval-query :=\n" +
45-
" 'declare namespace qconsole = \"http://marklogic.com/appservices/qconsole\";\n" +
46-
" import module namespace qconsole-model=\"http://marklogic.com/appservices/qconsole/model\"\n" +
47-
" at \"/MarkLogic/appservices/qconsole/qconsole-model.xqy\";\n" +
48-
" import module namespace amped-qconsole = \"http://marklogic.com/appservices/qconsole/util-amped\"\n" +
49-
" at \"/MarkLogic/appservices/qconsole/qconsole-amped.xqy\";\n" +
50-
" declare variable $xquery-query-template as xs:string external;\n" +
51-
" declare variable $workspace as element(export) external;\n" +
52-
" declare variable $user as xs:string external;\n" +
53-
" let $_ := xdmp:log(text{(\"user\", $user)})\n" +
54-
" let $wsid := xdmp:random()\n" +
55-
" let $imported-wsname := string($workspace/workspace/@name)\n" +
56-
" let $existing-wsnames := amped-qconsole:qconsole-get-user-workspaces(())/qconsole:name/string()\n" +
57-
" let $wsname :=\n" +
58-
" if( $imported-wsname = $existing-wsnames )\n" +
59-
" then qconsole-model:generate-workspace-name(())\n" +
60-
" else $imported-wsname\n" +
61-
" let $queries := $workspace/workspace/query\n" +
62-
" let $userid := xdmp:user($user)\n" +
63-
" let $_ := xdmp:log(text{(\"userid\", $userid)})\n" +
64-
" let $ws := <qconsole:workspace>\n" +
65-
" <qconsole:id>{$wsid}</qconsole:id>\n" +
66-
" <qconsole:name>{$wsname}</qconsole:name>\n" +
67-
" <qconsole:security>\n" +
68-
" <qconsole:userid>{$userid}</qconsole:userid>\n" +
69-
" </qconsole:security>\n" +
70-
" <qconsole:active>true</qconsole:active>\n" +
71-
" <qconsole:queries>\n" +
72-
" {\n" +
73-
" for $q at $i in $queries\n" +
74-
" let $qid := xdmp:random()\n" +
75-
" let $qname := string($q/@name)\n" +
76-
" let $focus := string($q/@focus)\n" +
77-
" let $active := string($q/@active)\n" +
78-
" let $content-source :=\n" +
79-
" if ( exists($q/@content-source) )\n" +
80-
" then string($q/@content-source)\n" +
81-
" else qconsole-model:default-database()\n" +
82-
" let $mode := string($q/@mode)\n" +
83-
" let $query-text := text { $q }\n" +
84-
" let $q-uri := concat(\"/queries/\", $qid, \".txt\")\n" +
85-
" let $save-q := amped-qconsole:qconsole-document-insert($q-uri, $query-text)\n" +
86-
" return\n" +
87-
" <qconsole:query>\n" +
88-
" <qconsole:id>{$qid}</qconsole:id>\n" +
89-
" <qconsole:name>{$qname}</qconsole:name>\n" +
90-
" <qconsole:content-source>{$content-source}</qconsole:content-source>\n" +
91-
" <qconsole:active>{$active}</qconsole:active>\n" +
92-
" <qconsole:focus>{$focus}</qconsole:focus>\n" +
93-
" <qconsole:mode>{$mode}</qconsole:mode>\n" +
94-
" </qconsole:query>\n" +
95-
" }\n" +
96-
" </qconsole:queries>\n" +
97-
" </qconsole:workspace>\n" +
98-
" let $ws-uri := concat(\"/workspaces/\", $wsid, \".xml\")\n" +
99-
" let $save-ws := amped-qconsole:qconsole-document-insert($ws-uri, $ws)\n" +
100-
" let $set-active := qconsole-model:set-only-one-workspace-active($wsid)\n" +
101-
" return $wsid'\n" +
102-
" \n" +
103-
" let $new-wsid := \n" +
104-
" local:qconsole-eval($eval-query, \n" +
105-
" (xs:QName(\"workspace\"), $workspace, \n" +
106-
" xs:QName(\"xquery-query-template\"), $idecl:default-query-text,\n" +
107-
" xs:QName(\"user\"), $user), ())\n" +
108-
" let $ws-uri := concat(\"/workspaces/\", $new-wsid, \".xml\")\n" +
109-
" return $ws-uri\n" +
110-
"};\n" +
111-
"\n" +
112-
"local:import-workspace($exported-workspace/element(), $user)";
9+
public class QconsoleScripts {
11310

114-
public final static String EXPORT = "xquery version \"1.0-ml\";\n" +
115-
"\n" +
116-
"declare namespace qconsole=\"http://marklogic.com/appservices/qconsole\";\n" +
117-
"\n" +
118-
"declare variable $user as xs:string external;\n" +
119-
"declare variable $workspace as xs:string external;\n" +
120-
"\n" +
121-
"declare function local:do-eval($query as xs:string, $vars) {\n" +
122-
" xdmp:eval($query, $vars, \n" +
123-
" <options xmlns=\"xdmp:eval\">\n" +
124-
" <database>{xdmp:database(\"App-Services\")}</database>\n" +
125-
" </options>)\n" +
126-
"};\n" +
127-
"\n" +
128-
"declare function local:get-ws-uri($user as xs:string, $workspace as xs:string) {\n" +
129-
" let $ws-query := 'xquery version \"1.0-ml\";\n" +
130-
" declare namespace qconsole = \"http://marklogic.com/appservices/qconsole\";\n" +
131-
" declare variable $user as xs:string external;\n" +
132-
" declare variable $workspace as xs:string external;\n" +
133-
" cts:uris((), (), cts:and-query((\n" +
134-
" cts:directory-query(\"/workspaces/\"),\n" +
135-
" cts:element-value-query(xs:QName(\"qconsole:userid\"), xs:string(xdmp:user($user))),\n" +
136-
" cts:element-value-query(xs:QName(\"qconsole:name\"), $workspace)\n" +
137-
" ))\n" +
138-
" )'\n" +
139-
" return local:do-eval($ws-query, (xs:QName(\"user\"), $user, xs:QName(\"workspace\"), $workspace))\n" +
140-
"};\n" +
141-
"\n" +
142-
"declare function local:get-workspace($ws-uri as xs:string) {\n" +
143-
" let $query := \"declare variable $ws-uri as xs:string external; fn:doc($ws-uri)\"\n" +
144-
" return local:do-eval($query, (xs:QName(\"ws-uri\"), $ws-uri))\n" +
145-
"};\n" +
146-
"\n" +
147-
"let $user := ($user, xdmp:get-current-user())[1]\n" +
148-
"\n" +
149-
"let $ws-uri := local:get-ws-uri($user, $workspace)\n" +
150-
"let $ws := local:get-workspace($ws-uri)\n" +
151-
"let $queries := \n" +
152-
" for $q in $ws/qconsole:workspace/qconsole:queries/qconsole:query\n" +
153-
" return \n" +
154-
" <query name=\"{string($q/qconsole:name)}\" focus=\"{string($q/qconsole:focus)}\" active=\"{string($q/qconsole:active)}\" mode=\"{string($q/qconsole:mode)}\">\n" +
155-
" {local:do-eval(concat(\"fn:doc('/queries/\", xs:unsignedLong($q/qconsole:id), \".txt')\"), ())}\n" +
156-
" </query>\n" +
157-
"\n" +
158-
"let $export := \n" +
159-
" if ($queries) then (\n" +
160-
" <export>\n" +
161-
" <workspace name=\"{string($ws/qconsole:workspace/qconsole:name)}\">\n" +
162-
" {$queries}\n" +
163-
" </workspace>\n" +
164-
" </export> )\n" +
165-
" else (text{\"No workspace found with the name of \", $workspace, \".\"})\n" +
166-
"\n" +
167-
"return $export";
11+
private final static String MODULE_PATH = "com/marklogic/client/ext/qconsole/impl/";
12+
public static final String IMPORT;
13+
public final static String EXPORT;
14+
static {
15+
IMPORT = readFile( MODULE_PATH + "import-workspaces.xqy");
16+
EXPORT = readFile(MODULE_PATH + "export-workspaces.xqy");
17+
}
16818

19+
private static String readFile(String fileName){
20+
InputStream inputStream = QconsoleScripts.class.getClassLoader().getResourceAsStream(fileName);
21+
return new BufferedReader(
22+
new InputStreamReader(inputStream, StandardCharsets.UTF_8))
23+
.lines()
24+
.collect(Collectors.joining("\n"));
25+
}
16926
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
xquery version "1.0-ml";
2+
3+
declare namespace qconsole="http://marklogic.com/appservices/qconsole";
4+
5+
declare variable $user as xs:string external;
6+
declare variable $workspace as xs:string external;
7+
8+
declare function local:do-invoke($function as xdmp:function) {
9+
xdmp:invoke-function($function,
10+
<options xmlns="xdmp:eval">
11+
<database>{xdmp:database("App-Services")}</database>
12+
</options>)
13+
};
14+
15+
declare function local:get-workspace-uri($user as xs:string, $workspace as xs:string) {
16+
let $workspace-query := function() {
17+
cts:uris((), (), cts:and-query((
18+
cts:directory-query("/workspaces/"),
19+
cts:element-value-query(xs:QName("qconsole:userid"), xs:string(xdmp:user($user))),
20+
cts:element-value-query(xs:QName("qconsole:name"), $workspace)
21+
)))
22+
}
23+
return local:do-invoke($workspace-query)
24+
};
25+
26+
declare function local:get-workspace($ws-uri as xs:string) {
27+
let $query := function() { fn:doc($ws-uri) }
28+
return local:do-invoke($query)
29+
};
30+
31+
declare function local:to-attribute($element as element()) {
32+
attribute { $element/local-name() } { string($element) }
33+
};
34+
35+
let $user := ($user, xdmp:get-current-user())[1]
36+
let $workspace-uri := local:get-workspace-uri($user, $workspace)
37+
let $workspace := local:get-workspace($workspace-uri)
38+
let $queries :=
39+
for $query in $workspace/qconsole:workspace/qconsole:queries/qconsole:query
40+
return
41+
<query>{
42+
$query/qconsole:* ! local:to-attribute(.),
43+
local:do-invoke(function() {fn:doc("/queries/" || xs:string($query/qconsole:id) || ".txt")})
44+
}</query>
45+
return
46+
if ($queries)
47+
then
48+
<export>
49+
<workspace name="{string($workspace/qconsole:workspace/qconsole:name)}">
50+
{$queries}
51+
</workspace>
52+
</export>
53+
else
54+
text{ "No workspace found with the name of ", $workspace, "." }
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
xquery version "1.0-ml";
2+
(:
3+
This relies on internal APIs in the qconsole-model function that have changed between MarkLogic 8 and 9.
4+
Specifically, qconsole-model:default-content-source() in ML8 was removed and qconsole-model:default-database()
5+
can be used instead.
6+
:)
7+
declare namespace qconsole = "http://marklogic.com/appservices/qconsole";
8+
9+
import module namespace amped-qconsole = "http://marklogic.com/appservices/qconsole/util-amped" at "/MarkLogic/appservices/qconsole/qconsole-amped.xqy";
10+
import module namespace qconsole-model = "http://marklogic.com/appservices/qconsole/model" at "/MarkLogic/appservices/qconsole/qconsole-model.xqy";
11+
12+
declare variable $exported-workspace as node() external;
13+
declare variable $user as xs:string external;
14+
15+
declare function local:qconsole-invoke(
16+
$xquery as xdmp:function
17+
) as item()*
18+
{
19+
xdmp:security-assert("http://marklogic.com/xdmp/privileges/qconsole", "execute"),
20+
xdmp:invoke-function($xquery,
21+
<options xmlns="xdmp:eval">
22+
<database>{xdmp:database("App-Services")}</database>
23+
</options>)
24+
};
25+
26+
declare function local:workspace-uri($workspace-id) {
27+
"/workspaces/" || xs:string($workspace-id) || ".xml"
28+
};
29+
30+
declare function local:import-workspace(
31+
$workspace as element(),
32+
$user as xs:string
33+
) as xs:string*
34+
{
35+
let $query := function() {
36+
let $_ := xdmp:log(text{("user", $user)})
37+
let $workspace-id := xdmp:random()
38+
let $imported-workspace-name := string($workspace/workspace/@name)
39+
let $existing-workspace-names := amped-qconsole:qconsole-get-user-workspaces(())/qconsole:name/string()
40+
let $workspace-name :=
41+
if ($imported-workspace-name = $existing-workspace-names)
42+
then qconsole-model:generate-workspace-name(())
43+
else $imported-workspace-name
44+
let $queries := $workspace/workspace/query
45+
let $user-id := xdmp:user($user)
46+
let $_ := xdmp:log(text{("userid", $user-id)})
47+
let $workspace :=
48+
<qconsole:workspace>
49+
<qconsole:id>{$workspace-id}</qconsole:id>
50+
<qconsole:name>{$workspace-name}</qconsole:name>
51+
<qconsole:security>
52+
<qconsole:userid>{$user-id}</qconsole:userid>
53+
</qconsole:security>
54+
<qconsole:active>true</qconsole:active>
55+
<qconsole:queries>{
56+
for $query in $queries
57+
let $source :=
58+
if (exists($query/@content-source))
59+
then qconsole-model:convert-content-source($query/@content-source)
60+
else
61+
let $s := map:map()
62+
let $database-name :=
63+
if (exists($query/@database-name) and string-length($query/@database-name) gt 0)
64+
then $query/@database-name ! (., map:put($s, ./local-name(), .))
65+
else ""
66+
let $database :=
67+
let $db-id :=
68+
if ( (exists($query/@database) and string-length($query/@database) gt 0) or string-length($database-name) gt 0 )
69+
then qconsole-model:identify-resource("database", $query/@database, $database-name)
70+
else qconsole-model:default-database()
71+
let $_ := map:put($s, "database", $db-id)
72+
return $db-id
73+
let $server-name :=
74+
if (exists($query/@server-name) and string-length($query/@server-name) gt 0)
75+
then $query/@server-name ! (., map:put($s, ./local-name(), .))
76+
else ""
77+
let $server :=
78+
let $server-id :=
79+
if ( (exists($query/@server) and string-length($query/@server) gt 0) or string-length($server-name) gt 0 )
80+
then qconsole-model:identify-resource("server", $query/@server, $server-name)
81+
else qconsole-model:default-app-server($database)
82+
let $_ := map:put($s, "server", $server-id)
83+
return $server-id
84+
return $s
85+
let $_ :=
86+
for $item in ($query/@*[not(local-name() = ("id", "database", "database-name", "server", "server-name"))])
87+
return map:put($source, $item/local-name(), $item)
88+
let $query-text := text {$query}
89+
let $query-id := xdmp:random()
90+
let $query-uri := concat("/queries/", $query-id, ".txt")
91+
let $save-query := amped-qconsole:qconsole-document-insert($query-uri, $query-text)
92+
return
93+
<qconsole:query>
94+
<qconsole:id>{$query-id}</qconsole:id>
95+
{ map:keys($source) ! element {"qconsole:" || .} { string(map:get($source, .)) } }
96+
</qconsole:query>
97+
}</qconsole:queries>
98+
</qconsole:workspace>
99+
let $workspace-uri := local:workspace-uri($workspace-id)
100+
let $save-workspace := amped-qconsole:qconsole-document-insert($workspace-uri, $workspace)
101+
let $set-active := qconsole-model:set-only-one-workspace-active($workspace-id)
102+
return $workspace-id
103+
}
104+
let $new-wsid := local:qconsole-invoke($query)
105+
let $workspace-uri := local:workspace-uri($new-wsid)
106+
return $workspace-uri
107+
};
108+
109+
local:import-workspace($exported-workspace/element(), $user)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.marklogic.client.ext.qconsole.impl;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.junit.jupiter.api.Assertions.assertNotNull;
6+
import static org.junit.jupiter.api.Assertions.assertTrue;
7+
8+
public class QconsoleScriptsTest {
9+
10+
@Test
11+
public void testImport() {
12+
String importModule = QconsoleScripts.IMPORT;
13+
assertNotNull(importModule);
14+
assertTrue(importModule.startsWith("xquery version"));
15+
}
16+
17+
@Test
18+
public void testExport() {
19+
String exportModule = QconsoleScripts.EXPORT;
20+
assertNotNull(exportModule);
21+
assertTrue(exportModule.startsWith("xquery version"));
22+
}
23+
}

0 commit comments

Comments
 (0)