Permalink
Browse files

mirror module refactor, closes #41

  • Loading branch information...
1 parent 3b1ec3e commit d27c6f11eeb8721fde8cad0419c4261b72095abb @EfraimFeinstein EfraimFeinstein committed Jun 27, 2012
Showing with 228 additions and 118 deletions.
  1. +123 −32 code/modules/mirror.xqm
  2. +1 −1 code/queries/pre-release-testing.xql
  3. +104 −85 code/tests/modules/mirror.t.xml
@@ -5,6 +5,7 @@ xquery version "3.0";
: aspect of another collection, maintaining the same directory
: structure and permissions
:
+ : @author Efraim Feinstein
: Open Siddur Project
: Copyright 2011-2012 Efraim Feinstein <efraim.feinstein@gmail.com>
: Licensed under the GNU Lesser General Public License, version 3 or later
@@ -21,49 +22,134 @@ import module namespace magic="http://jewishliturgy.org/magic"
declare namespace error="http://jewishliturgy.org/errors";
declare namespace tei="http://www.tei-c.org/ns/1.0";
-(:~ given a path, return the mirror path :)
+declare variable $mirror:configuration := "mirror-conf.xml";
+
+(:~ create a mirror collection
+ : @param $mirror-path Full path to the new mirror collection
+ : @param $original-path Full path to the collection that is to be mirrored
+ : @return empty-sequence()
+ :)
+declare function mirror:create(
+ $mirror-path as xs:string,
+ $original-path as xs:string
+ ) as empty-sequence() {
+ let $create :=
+ app:make-collection-path(
+ $mirror-path, "/", sm:get-permissions($original-path)
+ )
+ let $uri := xs:anyURI(
+ xmldb:store($mirror-path, $mirror:configuration,
+ <mirror:configuration>
+ <mirror:of>{replace($original-path, "^/db", "")}</mirror:of>
+ </mirror:configuration>)
+ )
+ return
+ if ($uri)
+ then
+ system:as-user("admin", $magic:password, (
+ sm:chown($uri, "admin"),
+ sm:chgrp($uri, "dba"),
+ sm:chmod($uri, "rw-rw-r--")
+ ))
+ else error(xs:QName("error:STORAGE"), "Cannot store mirror collection configuration.", $mirror-path)
+};
+
+(:~ @return the configuration file for a mirror collection
+ : @error error:NOT_A_MIRROR if the collection is not a mirror collection
+ :)
+declare function local:config(
+ $mirror-path as xs:string
+ ) as document-node() {
+ let $config := doc($mirror-path || "/" || $mirror:configuration)
+ return
+ if ($config)
+ then $config
+ else error(xs:QName("error:NOT_A_MIRROR"), "The collection is not a mirror collection.", $mirror-path)
+};
+
+(:~ @return the original base path :)
+declare function local:base-path(
+ $mirror-path as xs:string
+ ) as xs:string {
+ local:config($mirror-path)/mirror:configuration/mirror:of/string()
+};
+
+(:~ @param $path The relative (not beginning with /) or absolute (beginning with /) path of the desired collection
+ : @return the mirror path
+ : @error error:NOT_A_MIRROR The collection $mirror-path is not a mirror collection
+ : @error error:NOT_MIRRORED The collection $path is not a subcollection of the original path and is not mirrored in this mirror collection
+ :)
declare function mirror:mirror-path(
- $mirror as xs:string,
+ $mirror-path as xs:string,
$path as xs:string
) as xs:string {
- let $mirror-no-db := replace($mirror, "^/db", "")
+ let $mirror-no-db := replace($mirror-path, "^/db", "")
let $path-no-db := replace($path, "^/db", "")
- let $base-paths := tokenize($mirror-no-db,"/")
- let $base-path := string-join(subsequence($base-paths, 1, count($base-paths) - 1), "/")
- return app:concat-path(("/", $mirror-no-db, replace($path-no-db,
- concat("^(", $base-path, ")?"),
- ""))[.])
+ let $base-path := local:base-path($mirror-path)
+ return
+ if (starts-with($path-no-db, $base-path))
+ then replace($path-no-db, "^" || $base-path, $mirror-no-db)
+ else if (starts-with($path, "/"))
+ then
+ error(
+ xs:QName("error:NOT_MIRRORED"),
+ "The absolute path " || $path || "is not mirrored in " || $mirror-path
+ )
+ else
+ (: relative path :)
+ app:concat-path($mirror-no-db, $path)
};
+(:~ turn a path from relative to a mirror to one relative the original path
+ : @error error:NOT_A_MIRROR The collection $mirror-path is not a mirror collection
+ : @error error:NOT_MIRRORED The collection $path is not a subcollection of the original path and is not mirrored in this mirror collection
+ :)
declare function mirror:unmirror-path(
- $mirror as xs:string,
+ $mirror-path as xs:string,
$mirrored-path as xs:string
) as xs:string {
- let $mirror-no-db := replace($mirror, "^/db", "")
- let $tokens := tokenize($mirror-no-db, "/")
+ let $mirror-no-db := replace($mirror-path, "^/db", "")
+ let $base-path := local:base-path($mirror-path)
let $mirrored-path-no-db := replace($mirrored-path, "^/db", "")
- let $unmirror := string-join(subsequence($tokens, 1, count($tokens) - 1), "/")
return
- app:concat-path(("/", $unmirror, substring-after($mirrored-path-no-db, $mirror-no-db))[.])
+ if (starts-with($mirrored-path-no-db, $mirror-no-db))
+ then replace($mirrored-path-no-db, "^" || $mirror-no-db, $base-path)
+ else
+ error(
+ xs:QName("error:NOT_MIRRORED"),
+ "The absolute path " || $mirrored-path || "is not mirrored in " || $mirror-path
+ )
};
(:~ make a mirror collection path that mirrors the same path in
: the normal /db hierarchy
- : @param $mirror the location of the mirror
+ : @param $mirror-path the base location of the mirror
: @param $path the path that should be mirrored (relative to /db)
+ : @error error:NOT_A_MIRROR The collection $mirror-path is not a mirror collection
+ : @error error:NOT_MIRRORED The collection $path is not a subcollection of the original path and is not mirrored in this mirror collection
+ : @error error:CREATE A collection could not be created
:)
+(: TODO: this function is wrong! :)
declare function mirror:make-collection-path(
- $mirror as xs:string,
+ $mirror-path as xs:string,
$path as xs:string
) as empty-sequence() {
- let $unmirror-base := mirror:unmirror-path($mirror, $mirror)
- let $mirrored-path := mirror:mirror-path($mirror, $path)
- let $steps := tokenize(substring-after($mirrored-path, $unmirror-base), '/')[.]
+ let $mirror-path-no-db := replace($mirror-path, "^/db", "")
+ let $path-no-db := replace($path, "^/db", "")
+ let $mirrored-path := mirror:mirror-path($mirror-path, $path)
+ let $base-path := local:base-path($mirror-path)
+ (: extended-* is the path part after the mirror or original base. :)
+ let $extended-path := substring-after($path, $base-path)
+ let $extended-mirror := substring-after($mirrored-path, $mirror-path-no-db)
+ let $steps :=
+ tokenize($extended-mirror, '/')[.]
for $step in 1 to count($steps)
let $this-step :=
- app:concat-path(($unmirror-base, subsequence($steps, 2, $step - 1)))
- let $mirror-this-step := mirror:mirror-path($mirror,$this-step)
- let $mirror-previous-step := app:concat-path(($unmirror-base, subsequence($steps, 1, $step - 1)))
+ app:concat-path(($base-path, subsequence($steps, 1, $step)))
+ let $mirror-this-step :=
+ mirror:mirror-path($mirror-path,$this-step)
+ let $mirror-previous-step :=
+ app:concat-path(($mirror-path, subsequence($steps, 1, $step - 1)))
where not(xmldb:collection-available($mirror-this-step))
return
let $new-collection := $steps[$step]
@@ -85,7 +171,7 @@ declare function mirror:make-collection-path(
if (xmldb:create-collection($mirror-previous-step, $new-collection))
then
mirror:mirror-permissions($this-step, $mirror-this-step)
- else error(xs:QName('error:CREATE'), concat('Cannot create index collection ', $this-step))
+ else error(xs:QName('error:CREATE'), concat('Cannot create mirror collection ', $this-step))
)
};
@@ -103,23 +189,23 @@ declare function mirror:mirror-permissions(
: up to date information and returns an xs:boolean
:)
declare function mirror:is-up-to-date(
- $mirror as xs:string,
+ $mirror-path as xs:string,
$original as item(),
- $up-to-date-function as function(xs:string, item()) as xs:boolean??
+ $up-to-date-function as (function(xs:string, item()) as xs:boolean)?
) as xs:boolean {
let $original-doc :=
typeswitch($original)
case document-node() return $original
default return doc($original)
let $collection := util:collection-name($original-doc)
let $resource := util:document-name($original-doc)
- let $mirror-collection := mirror:mirror-path($mirror, $collection)
+ let $mirror-collection := mirror:mirror-path($mirror-path, $collection)
let $last-modified := xmldb:last-modified($collection, $resource)
let $mirror-last-modified := xmldb:last-modified($mirror-collection, $resource)
return
(
if (exists($up-to-date-function))
- then boolean($up-to-date-function($mirror, $original))
+ then boolean($up-to-date-function($mirror-path, $original))
else true()
) and
not(
@@ -130,23 +216,28 @@ declare function mirror:is-up-to-date(
};
declare function mirror:is-up-to-date(
- $mirror as xs:string,
+ $mirror-path as xs:string,
$original as item()
) as xs:boolean {
- mirror:is-up-to-date($mirror, $original, ())
+ mirror:is-up-to-date($mirror-path, $original, ())
};
-(:~ store data in a mirror collection :)
+(:~ store data in a mirror collection
+ : @param $mirror-path Base of the mirror
+ : @param $collection Original path to the collection
+ : @param $resource Resource name
+ : @param $data The data to store
+ :)
declare function mirror:store(
- $mirror as xs:string,
+ $mirror-path as xs:string,
$collection as xs:string,
$resource as xs:string,
$data as item()+
) as xs:string? {
- let $mirror-collection := mirror:mirror-path($mirror, $collection)
+ let $mirror-collection := mirror:mirror-path($mirror-path, $collection)
let $make :=
system:as-user("admin", $magic:password,
- mirror:make-collection-path($mirror, $collection)
+ mirror:make-collection-path($mirror-path, $collection)
)
let $mirror-path := concat($mirror-collection, "/", $resource)
return
@@ -9,14 +9,14 @@ import module namespace api="http://jewishliturgy.org/modules/api"
let $tests-to-run :=
<tests>
+ <test module="/code/tests/modules/mirror.t.xml"/>
<test module="/code/tests/api/data.t.xml" admin="1"/>
<test module="/code/tests/api/index.t.xml" />
<test module="/code/tests/api/demo.t.xml"/>
<test module="/code/tests/api/access.t.xml" />
<test module="/code/tests/api/login.t.xml"/>
<test module="/code/tests/api/user.t.xml"/>
<test module="/code/tests/api/group.t.xml"/>
- <!--test module="/code/tests/modules/mirror.t.xml" admin="1"/-->
<test module="/code/tests/api/data/dindex.t.xml"/>
<test module="/code/tests/api/data/notes.t.xml"/>
<test module="/code/tests/api/data/original.t.xml"/>
Oops, something went wrong.

0 comments on commit d27c6f1

Please sign in to comment.