diff --git a/.gitignore b/.gitignore
index 9c9c8ab..421a8fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
-build
-/nbproject/private/
-/JavaApplication1/nbproject/private/
+target/
+.idea/
+xquery-versioning-module.iml
diff --git a/GPL1-template.txt b/GPL1-template.txt
new file mode 100644
index 0000000..b946a8e
--- /dev/null
+++ b/GPL1-template.txt
@@ -0,0 +1,17 @@
+${project.description}
+Copyright (C) ${project.inceptionYear} ${organisation} <${email}>
+${url}
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..0f48181
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,190 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License. The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Program or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public License (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the program under these
+ conditions, and telling the user how to view a copy of this General
+ Public License.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/License.md b/License.md
deleted file mode 100644
index 0671f06..0000000
--- a/License.md
+++ /dev/null
@@ -1,264 +0,0 @@
-The GNU General Public License, Version 2, June 1991 (GPLv2)
-============================================================
-
-> Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-> 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-
-Everyone is permitted to copy and distribute verbatim copies of this license
-document, but changing it is not allowed.
-
-
-Preamble
---------
-
-The licenses for most software are designed to take away your freedom to share
-and change it. By contrast, the GNU General Public License is intended to
-guarantee your freedom to share and change free software--to make sure the
-software is free for all its users. This General Public License applies to most
-of the Free Software Foundation's software and to any other program whose
-authors commit to using it. (Some other Free Software Foundation software is
-covered by the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
-When we speak of free software, we are referring to freedom, not price. Our
-General Public Licenses are designed to make sure that you have the freedom to
-distribute copies of free software (and charge for this service if you wish),
-that you receive source code or can get it if you want it, that you can change
-the software or use pieces of it in new free programs; and that you know you can
-do these things.
-
-To protect your rights, we need to make restrictions that forbid anyone to deny
-you these rights or to ask you to surrender the rights. These restrictions
-translate to certain responsibilities for you if you distribute copies of the
-software, or if you modify it.
-
-For example, if you distribute copies of such a program, whether gratis or for a
-fee, you must give the recipients all the rights that you have. You must make
-sure that they, too, receive or can get the source code. And you must show them
-these terms so they know their rights.
-
-We protect your rights with two steps: (1) copyright the software, and (2) offer
-you this license which gives you legal permission to copy, distribute and/or
-modify the software.
-
-Also, for each author's protection and ours, we want to make certain that
-everyone understands that there is no warranty for this free software. If the
-software is modified by someone else and passed on, we want its recipients to
-know that what they have is not the original, so that any problems introduced by
-others will not reflect on the original authors' reputations.
-
-Finally, any free program is threatened constantly by software patents. We wish
-to avoid the danger that redistributors of a free program will individually
-obtain patent licenses, in effect making the program proprietary. To prevent
-this, we have made it clear that any patent must be licensed for everyone's free
-use or not licensed at all.
-
-The precise terms and conditions for copying, distribution and modification
-follow.
-
-
-Terms And Conditions For Copying, Distribution And Modification
----------------------------------------------------------------
-
-**0.** This License applies to any program or other work which contains a notice
-placed by the copyright holder saying it may be distributed under the terms of
-this General Public License. The "Program", below, refers to any such program or
-work, and a "work based on the Program" means either the Program or any
-derivative work under copyright law: that is to say, a work containing the
-Program or a portion of it, either verbatim or with modifications and/or
-translated into another language. (Hereinafter, translation is included without
-limitation in the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not covered by
-this License; they are outside its scope. The act of running the Program is not
-restricted, and the output from the Program is covered only if its contents
-constitute a work based on the Program (independent of having been made by
-running the Program). Whether that is true depends on what the Program does.
-
-**1.** You may copy and distribute verbatim copies of the Program's source code
-as you receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice and
-disclaimer of warranty; keep intact all the notices that refer to this License
-and to the absence of any warranty; and give any other recipients of the Program
-a copy of this License along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and you may at
-your option offer warranty protection in exchange for a fee.
-
-**2.** You may modify your copy or copies of the Program or any portion of it,
-thus forming a work based on the Program, and copy and distribute such
-modifications or work under the terms of Section 1 above, provided that you also
-meet all of these conditions:
-
-* **a)** You must cause the modified files to carry prominent notices stating
- that you changed the files and the date of any change.
-
-* **b)** You must cause any work that you distribute or publish, that in whole
- or in part contains or is derived from the Program or any part thereof, to
- be licensed as a whole at no charge to all third parties under the terms of
- this License.
-
-* **c)** If the modified program normally reads commands interactively when
- run, you must cause it, when started running for such interactive use in the
- most ordinary way, to print or display an announcement including an
- appropriate copyright notice and a notice that there is no warranty (or
- else, saying that you provide a warranty) and that users may redistribute
- the program under these conditions, and telling the user how to view a copy
- of this License. (Exception: if the Program itself is interactive but does
- not normally print such an announcement, your work based on the Program is
- not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If identifiable
-sections of that work are not derived from the Program, and can be reasonably
-considered independent and separate works in themselves, then this License, and
-its terms, do not apply to those sections when you distribute them as separate
-works. But when you distribute the same sections as part of a whole which is a
-work based on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the entire whole,
-and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest your
-rights to work written entirely by you; rather, the intent is to exercise the
-right to control the distribution of derivative or collective works based on the
-Program.
-
-In addition, mere aggregation of another work not based on the Program with the
-Program (or with a work based on the Program) on a volume of a storage or
-distribution medium does not bring the other work under the scope of this
-License.
-
-**3.** You may copy and distribute the Program (or a work based on it, under
-Section 2) in object code or executable form under the terms of Sections 1 and 2
-above provided that you also do one of the following:
-
-* **a)** Accompany it with the complete corresponding machine-readable source
- code, which must be distributed under the terms of Sections 1 and 2 above on
- a medium customarily used for software interchange; or,
-
-* **b)** Accompany it with a written offer, valid for at least three years, to
- give any third party, for a charge no more than your cost of physically
- performing source distribution, a complete machine-readable copy of the
- corresponding source code, to be distributed under the terms of Sections 1
- and 2 above on a medium customarily used for software interchange; or,
-
-* **c)** Accompany it with the information you received as to the offer to
- distribute corresponding source code. (This alternative is allowed only for
- noncommercial distribution and only if you received the program in object
- code or executable form with such an offer, in accord with Subsection b
- above.)
-
-The source code for a work means the preferred form of the work for making
-modifications to it. For an executable work, complete source code means all the
-source code for all modules it contains, plus any associated interface
-definition files, plus the scripts used to control compilation and installation
-of the executable. However, as a special exception, the source code distributed
-need not include anything that is normally distributed (in either source or
-binary form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component itself
-accompanies the executable.
-
-If distribution of executable or object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the source code
-from the same place counts as distribution of the source code, even though third
-parties are not compelled to copy the source along with the object code.
-
-**4.** You may not copy, modify, sublicense, or distribute the Program except as
-expressly provided under this License. Any attempt otherwise to copy, modify,
-sublicense or distribute the Program is void, and will automatically terminate
-your rights under this License. However, parties who have received copies, or
-rights, from you under this License will not have their licenses terminated so
-long as such parties remain in full compliance.
-
-**5.** You are not required to accept this License, since you have not signed
-it. However, nothing else grants you permission to modify or distribute the
-Program or its derivative works. These actions are prohibited by law if you do
-not accept this License. Therefore, by modifying or distributing the Program (or
-any work based on the Program), you indicate your acceptance of this License to
-do so, and all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-**6.** Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the original
-licensor to copy, distribute or modify the Program subject to these terms and
-conditions. You may not impose any further restrictions on the recipients'
-exercise of the rights granted herein. You are not responsible for enforcing
-compliance by third parties to this License.
-
-**7.** If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues), conditions
-are imposed on you (whether by court order, agreement or otherwise) that
-contradict the conditions of this License, they do not excuse you from the
-conditions of this License. If you cannot distribute so as to satisfy
-simultaneously your obligations under this License and any other pertinent
-obligations, then as a consequence you may not distribute the Program at all.
-For example, if a patent license would not permit royalty-free redistribution of
-the Program by all those who receive copies directly or indirectly through you,
-then the only way you could satisfy both it and this License would be to refrain
-entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply and the
-section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any patents or
-other property right claims or to contest validity of any such claims; this
-section has the sole purpose of protecting the integrity of the free software
-distribution system, which is implemented by public license practices. Many
-people have made generous contributions to the wide range of software
-distributed through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing to
-distribute software through any other system and a licensee cannot impose that
-choice.
-
-This section is intended to make thoroughly clear what is believed to be a
-consequence of the rest of this License.
-
-**8.** If the distribution and/or use of the Program is restricted in certain
-countries either by patents or by copyrighted interfaces, the original copyright
-holder who places the Program under this License may add an explicit
-geographical distribution limitation excluding those countries, so that
-distribution is permitted only in or among countries not thus excluded. In such
-case, this License incorporates the limitation as if written in the body of this
-License.
-
-**9.** The Free Software Foundation may publish revised and/or new versions of
-the General Public License from time to time. Such new versions will be similar
-in spirit to the present version, but may differ in detail to address new
-problems or concerns.
-
-Each version is given a distinguishing version number. If the Program specifies
-a version number of this License which applies to it and "any later version",
-you have the option of following the terms and conditions either of that version
-or of any later version published by the Free Software Foundation. If the
-Program does not specify a version number of this License, you may choose any
-version ever published by the Free Software Foundation.
-
-**10.** If you wish to incorporate parts of the Program into other free programs
-whose distribution conditions are different, write to the author to ask for
-permission. For software which is copyrighted by the Free Software Foundation,
-write to the Free Software Foundation; we sometimes make exceptions for this.
-Our decision will be guided by the two goals of preserving the free status of
-all derivatives of our free software and of promoting the sharing and reuse of
-software generally.
-
-
-No Warranty
------------
-
-**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
-THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
-STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
-"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
-BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
-INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
-BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
-OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
diff --git a/README.md b/README.md
index 1600c1d..4c62ff6 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,101 @@
-# eXistdb Versioning extension expath package #
+# Versioning Module for eXist-db XQuery #
+[![Java 8](https://img.shields.io/badge/java-8-blue.svg)](http://java.oracle.com) [![License](https://img.shields.io/badge/license-GPL%201.0-blue.svg)](https://www.gnu.org/licenses/gpl-1.0.html)
-This repository holds the old code from the eXistdb Versioning extension.
+This repository holds the for the eXist-db XQuery Versioning extension module.
-### ROADMAP ###
+### Building a EXPath Package for eXist-db ###
-Turn it into an installable and working xar package.
+Building requires that you have Java JDK version 8 and Maven 3 installed.
-### LICENSE ###
+```bash
+$ https://www.github.com/exist-db/xquery-versioning-module.git
+$ mvn package
+```
-GPL
\ No newline at end of file
+You will then find a file named similar to `target/xquery-versioning-module-1.0.xar`.
+
+### Example `collection.xconf` Trigger Configuration
+```xml
+
+
+
+
+
+
+
+```
+
+
+### API Overview
+
+Namespace URI: `http://exist-db.org/xquery/versioning`
+
+Namespace Prefix: `versioning`
+
+Class: `org.exist.versioning.xquery.VersioningModule`
+
+
+1. To find the differences between two nodes:
+ ```xquery
+ versioning:diff($a as node(), $b as node()) as node()
+ ```
+
+2. To apply a patch to a node:
+ ```xquery
+ versioning:patch($node as node(), $patch as node()) as item()
+ ```
+
+3. To annotate a node:
+ ```xquery
+ versioning:annotate($node as node(), $patch as node()) as item()
+ ```
+
+
+### Utility API Overview
+
+Namespace URI: `http://exist-db.org/versioning`
+
+Namespace Prefix: `v`
+
+file: `versioning.xqm`
+
+1. Return all revisions of the specified document as a sequence of xs:integer revision numbers in ascending order:
+ ```xquery
+ v:revisions($doc as node()) as xs:integer*
+ ```
+
+2. Return all version docs, including the full diff, for the specified document:
+ ```xquery
+ v:versions($doc as node()) as element(v:version)*
+ ```
+
+3. Restore a certain revision of a document by applying a sequence of diffs and return it as an in-memory node:
+ ```xquery
+ v:doc($doc as node(), $rev as xs:integer?) as node()*
+ ```
+
+4. Apply a given patch on a document:
+ ```xquery
+ v:apply-patch($doc as node(), $diffs as element(v:version)*)
+ ```
+
+5. For the document passed as first argument, retrieve the revision specified in the second argument. Generate a diff between both version, i.e. **HEAD** and the given revision:
+ ```xquery
+ v:diff($doc as node(), $rev as xs:integer) as element(v:version)?
+ ```
+
+6. Return an XML document in which all changes between ``$rev` and ``$rev - 1` are annotated.
+ ```xquery
+ v:annotate($doc as node(), $rev as xs:integer)
+ ```
+
+7. Check if there are any revisions in the database which are newer than the version identified by the specified base revision and key:
+ ```xquery
+ v:find-newer-revision($doc as node(), $base as xs:integer, $key as xs:string) as element(v:version)?
+ ```
+
+8. Returns an XML fragment showing the version history of the document to which the specified node belongs. All revisions are listed with date and user, but without the detailed diff:
+ ```xquery
+ v:history($doc as node()) as element(v:history)
+ ```
diff --git a/build.properties.xml b/build.properties.xml
deleted file mode 100644
index d786449..0000000
--- a/build.properties.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
- versioning
- 1.0.0
- versioning
-
-
diff --git a/build.xml b/build.xml
deleted file mode 100644
index 11003ea..0000000
--- a/build.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/extension.xml b/extension.xml
deleted file mode 100644
index 6842dcd..0000000
--- a/extension.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ivy.xml b/ivy.xml
deleted file mode 100644
index 955d008..0000000
--- a/ivy.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ivysettings.xml b/ivysettings.xml
deleted file mode 100644
index 32534fd..0000000
--- a/ivysettings.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/nbproject/project.xml b/nbproject/project.xml
deleted file mode 100644
index 24c3178..0000000
--- a/nbproject/project.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
- org.netbeans.modules.ant.freeform
-
-
- versionig-xar
-
-
-
- versionig-xar
-
-
-
-
- .
- UTF-8
-
-
-
- java
- test
- UTF-8
-
-
-
- java
- src/main/java
- UTF-8
-
-
-
-
- xar
-
-
- clean
-
-
- clean
- xar
-
-
-
-
-
-
- test
-
-
-
- src/main/java
-
-
- build.xml
-
-
-
-
-
-
-
-
-
-
-
-
- test
-
- build/lib/Saxon-HE.jar:build/lib/antlr.jar:build/lib/avalon-framework.jar:build/lib/c3p0.jar:build/lib/commons-codec.jar:build/lib/commons-io.jar:build/lib/commons-logging.jar:build/lib/commons-pool.jar:build/lib/excalibur-cli.jar:build/lib/existdb-core.jar:build/lib/gnu-crypto.jar:build/lib/isorelax.jar:build/lib/jing.jar:build/lib/junit.jar:build/lib/log4j-api.jar:build/lib/log4j-core.jar:build/lib/log4j.jar:build/lib/logkit.jar:build/lib/pkg-repo.jar:build/lib/quartz.jar:build/lib/servlet-api.jar:build/lib/slf4j-api.jar:build/lib/ws-commons-util.jar:build/lib/xercesImpl.jar:build/lib/xml-apis.jar:build/lib/xml-resolver.jar:build/lib/xmldb-api.jar:build/lib/xmlrpc-client.jar:build/lib/xmlrpc-common.jar:build/lib/xmlrpc-server.jar
- 1.8
-
-
- src/main/java
- 1.8
-
-
-
-
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..36d75d1
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,258 @@
+
+
+
+ 4.0.0
+
+
+ org.sonatype.oss
+ oss-parent
+ 7
+
+
+
+ org.exist-db.xquery.extensions
+ xquery-versioning-module
+ 1.0
+
+ Versioning Module
+ Versioning Module for eXist-db XQuery
+ https://www.github.com/exist-db/xquery-versioning-module
+ 2008
+
+
+ eXist-db
+ http://exist-db.org
+
+
+
+
+ >GNU General Public License, version 1
+ https://opensource.org/licenses/GPL-1.0
+ repo
+
+
+
+
+ scm:git:https://www.github.com/exist-db/xquery-versioning-module.git
+ scm:git:https://www.github.com/exist-db/xquery-versioning-module.git
+ scm:git:https://www.github.com/exist-db/xquery-versioning-module.git
+
+
+
+ http://exist-db.org/xquery/versioning
+ 3.0.RC1
+ 1.7
+
+ 1.7
+ UTF-8
+
+ org.exist.versioning.xquery
+ VersioningModule
+ ${project.version}
+ ${java-package-name}
+ ${project.name}
+ ${versioning.module.namespace}
+ ${project.artifactId}
+ ${project.artifactId}-${project.version}
+
+
+
+
+ org.exist-db
+ exist-core
+ ${exist.version}
+ provided
+
+
+ com.bmsi
+ gnudiff
+ ${gnudiff.version}
+
+
+
+
+
+
+ com.mycila
+ license-maven-plugin
+ 3.0
+
+ ${basedir}/GPL1-template.txt
+ true
+ true
+ true
+
+ ${project.organization.name}
+ exit-open@lists.sourceforge.net
+ ${project.organization.url}
+
+
+ xquery-license-style.xml
+
+
+ xquery_style
+ xquery_style
+
+
+ pom.xml
+ README.md
+ LICENSE
+ GPL1-template.txt
+ xquery-license-style.xml
+ xar-assembly.xml
+ src/test/resources/**
+ docs/**
+ collection.sample.xconf
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.6.1
+
+
+ ${java.version}
+ ${project.build.sourceEncoding}
+
+
+
+ compile
+
+ compile
+
+
+
+
+
+ com.code54.mojo
+ buildversion-plugin
+ 1.0.3
+
+
+ validate
+
+ set-properties
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.0.2
+
+
+
+
+ ${java-package-name}.${java-package-main-class-name}
+ ${java-package-name}
+
+
+
+ ${versioning.module.namespace}
+
+ ${build-tag}
+ ${build-commit}
+ ${build-commit-abbrev}
+ ${build-version}
+ ${build-tstamp}
+ ${project.scm.connection}
+ ${project.description}
+ ${project.url}
+
+
+
+
+
+ ro.kuberam.maven.plugins
+ kuberam-expath-plugin
+ 0.4.8
+
+
+ create-xar
+ package
+
+ make-xar
+
+
+ xar-assembly.xml
+ ${package-final-name}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.0.1
+
+
+
+ true
+ true
+
+
+ ${build-tag}
+ ${build-commit}
+ ${build-commit-abbrev}
+ ${build-version}
+ ${build-tstamp}
+ ${project.scm.connection}
+ ${project.description}
+ ${project.url}
+
+
+
+
+
+ attach-sources
+ verify
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.6
+
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 2.5.3
+
+ forked-path
+ true
+ @{project.version}
+
+
+
+
+
+
+
+
+ exist
+ https://raw.github.com/eXist-db/mvn-repo/master/
+
+
+
+
+
+ clojars.org
+ http://clojars.org/repo
+
+
+
diff --git a/src/main/java/bmsi/util/Diff.java b/src/main/java/bmsi/util/Diff.java
deleted file mode 100644
index c3602ab..0000000
--- a/src/main/java/bmsi/util/Diff.java
+++ /dev/null
@@ -1,890 +0,0 @@
-/*
- * $Log: Diff.java,v $
- * Revision 1.6 2003/03/06 22:51:32 stuart
- * Convert to CVS
- *
- * Revision 1.5 2002/07/19 19:14:40 stuart
- * fix reverseScript, make change ctor public, update docs
- *
- * Revision 1.4 2002/04/09 17:53:39 stuart
- * More flexible interface for diff() function.
- *
- * Revision 1.3 2000/03/03 21:58:03 stuart
- * move discard_confusing_lines and shift_boundaries to class file_data
- *
- * Revision 1.2 2000/03/02 16:37:38 stuart
- * Add GPL and copyright
- *
- */
-package bmsi.util;
-
-import java.util.Hashtable;
-
-/** A class to compare vectors of objects. The result of comparison
- is a list of change objects which form an
- edit script. The objects compared are traditionally lines
- of text from two files. Comparison options such as "ignore
- whitespace" are implemented by modifying the equals
- and hashcode methods for the objects compared.
-
- The basic algorithm is described in:
- "An O(ND) Difference Algorithm and its Variations", Eugene Myers,
- Algorithmica Vol. 1 No. 2, 1986, p 251.
-
- This class outputs different results from GNU diff 1.15 on some
- inputs. Our results are actually better (smaller change list, smaller
- total size of changes), but it would be nice to know why. Perhaps
- there is a memory overwrite bug in GNU diff 1.15.
-
- @author Stuart D. Gathman, translated from GNU diff 1.15
- Copyright (C) 2000 Business Management Systems, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the
- GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
-public class Diff {
-
- /** Prepare to find differences between two arrays. Each element of
- the arrays is translated to an "equivalence number" based on
- the result of equals. The original Object arrays
- are no longer needed for computing the differences. They will
- be needed again later to print the results of the comparison as
- an edit script, if desired.
- */
- public Diff(Object[] a,Object[] b) {
- Hashtable h = new Hashtable(a.length + b.length);
- filevec[0] = new file_data(a,h);
- filevec[1] = new file_data(b,h);
- }
-
- /** 1 more than the maximum equivalence value used for this or its
- sibling file. */
- private int equiv_max = 1;
-
- /** When set to true, the comparison uses a heuristic to speed it up.
- With this heuristic, for files with a constant small density
- of changes, the algorithm is linear in the file size. */
- public boolean heuristic = false;
-
- /** When set to true, the algorithm returns a guarranteed minimal
- set of changes. This makes things slower, sometimes much slower. */
- public boolean no_discards = false;
-
- private int[] xvec, yvec; /* Vectors being compared. */
- private int[] fdiag; /* Vector, indexed by diagonal, containing
- the X coordinate of the point furthest
- along the given diagonal in the forward
- search of the edit matrix. */
- private int[] bdiag; /* Vector, indexed by diagonal, containing
- the X coordinate of the point furthest
- along the given diagonal in the backward
- search of the edit matrix. */
- private int fdiagoff, bdiagoff;
- private final file_data[] filevec = new file_data[2];
- private int cost;
-
- /** Find the midpoint of the shortest edit script for a specified
- portion of the two files.
-
- We scan from the beginnings of the files, and simultaneously from the ends,
- doing a breadth-first search through the space of edit-sequence.
- When the two searches meet, we have found the midpoint of the shortest
- edit sequence.
-
- The value returned is the number of the diagonal on which the midpoint lies.
- The diagonal number equals the number of inserted lines minus the number
- of deleted lines (counting only lines before the midpoint).
- The edit cost is stored into COST; this is the total number of
- lines inserted or deleted (counting only lines before the midpoint).
-
- This function assumes that the first lines of the specified portions
- of the two files do not match, and likewise that the last lines do not
- match. The caller must trim matching lines from the beginning and end
- of the portions it is going to specify.
-
- Note that if we return the "wrong" diagonal value, or if
- the value of bdiag at that diagonal is "wrong",
- the worst this can do is cause suboptimal diff output.
- It cannot cause incorrect diff output. */
-
- private int diag (int xoff, int xlim, int yoff, int ylim) {
- final int[] fd = fdiag; // Give the compiler a chance.
- final int[] bd = bdiag; // Additional help for the compiler.
- final int[] xv = xvec; // Still more help for the compiler.
- final int[] yv = yvec; // And more and more . . .
- final int dmin = xoff - ylim; // Minimum valid diagonal.
- final int dmax = xlim - yoff; // Maximum valid diagonal.
- final int fmid = xoff - yoff; // Center diagonal of top-down search.
- final int bmid = xlim - ylim; // Center diagonal of bottom-up search.
- int fmin = fmid, fmax = fmid; // Limits of top-down search.
- int bmin = bmid, bmax = bmid; // Limits of bottom-up search.
- /* True if southeast corner is on an odd
- diagonal with respect to the northwest. */
- final boolean odd = (fmid - bmid & 1) != 0;
-
- fd[fdiagoff + fmid] = xoff;
- bd[bdiagoff + bmid] = xlim;
-
- for (int c = 1;; ++c)
- {
- int d; /* Active diagonal. */
- boolean big_snake = false;
-
- /* Extend the top-down search by an edit step in each diagonal. */
- if (fmin > dmin)
- fd[fdiagoff + --fmin - 1] = -1;
- else
- ++fmin;
- if (fmax < dmax)
- fd[fdiagoff + ++fmax + 1] = -1;
- else
- --fmax;
- for (d = fmax; d >= fmin; d -= 2)
- {
- int x, y, oldx, tlo = fd[fdiagoff + d - 1], thi = fd[fdiagoff + d + 1];
-
- if (tlo >= thi)
- x = tlo + 1;
- else
- x = thi;
- oldx = x;
- y = x - d;
- while (x < xlim && y < ylim && xv[x] == yv[y]) {
- ++x; ++y;
- }
- if (x - oldx > 20)
- big_snake = true;
- fd[fdiagoff + d] = x;
- if (odd && bmin <= d && d <= bmax && bd[bdiagoff + d] <= fd[fdiagoff + d])
- {
- cost = 2 * c - 1;
- return d;
- }
- }
-
- /* Similar extend the bottom-up search. */
- if (bmin > dmin)
- bd[bdiagoff + --bmin - 1] = Integer.MAX_VALUE;
- else
- ++bmin;
- if (bmax < dmax)
- bd[bdiagoff + ++bmax + 1] = Integer.MAX_VALUE;
- else
- --bmax;
- for (d = bmax; d >= bmin; d -= 2)
- {
- int x, y, oldx, tlo = bd[bdiagoff + d - 1], thi = bd[bdiagoff + d + 1];
-
- if (tlo < thi)
- x = tlo;
- else
- x = thi - 1;
- oldx = x;
- y = x - d;
- while (x > xoff && y > yoff && xv[x - 1] == yv[y - 1]) {
- --x; --y;
- }
- if (oldx - x > 20)
- big_snake = true;
- bd[bdiagoff + d] = x;
- if (!odd && fmin <= d && d <= fmax && bd[bdiagoff + d] <= fd[fdiagoff + d])
- {
- cost = 2 * c;
- return d;
- }
- }
-
- /* Heuristic: check occasionally for a diagonal that has made
- lots of progress compared with the edit distance.
- If we have any such, find the one that has made the most
- progress and return it as if it had succeeded.
-
- With this heuristic, for files with a constant small density
- of changes, the algorithm is linear in the file size. */
-
- if (c > 200 && big_snake && heuristic)
- {
- int best = 0;
- int bestpos = -1;
-
- for (d = fmax; d >= fmin; d -= 2)
- {
- int dd = d - fmid;
- if ((fd[fdiagoff + d] - xoff)*2 - dd > 12 * (c + (dd > 0 ? dd : -dd)))
- {
- if (fd[fdiagoff + d] * 2 - dd > best
- && fd[fdiagoff + d] - xoff > 20
- && fd[fdiagoff + d] - d - yoff > 20)
- {
- int k;
- int x = fd[fdiagoff + d];
-
- /* We have a good enough best diagonal;
- now insist that it end with a significant snake. */
- for (k = 1; k <= 20; k++)
- if (xvec[x - k] != yvec[x - d - k])
- break;
-
- if (k == 21)
- {
- best = fd[fdiagoff + d] * 2 - dd;
- bestpos = d;
- }
- }
- }
- }
- if (best > 0)
- {
- cost = 2 * c - 1;
- return bestpos;
- }
-
- best = 0;
- for (d = bmax; d >= bmin; d -= 2)
- {
- int dd = d - bmid;
- if ((xlim - bd[bdiagoff + d])*2 + dd > 12 * (c + (dd > 0 ? dd : -dd)))
- {
- if ((xlim - bd[bdiagoff + d]) * 2 + dd > best
- && xlim - bd[bdiagoff + d] > 20
- && ylim - (bd[bdiagoff + d] - d) > 20)
- {
- /* We have a good enough best diagonal;
- now insist that it end with a significant snake. */
- int k;
- int x = bd[bdiagoff + d];
-
- for (k = 0; k < 20; k++)
- if (xvec[x + k] != yvec[x - d + k])
- break;
- if (k == 20)
- {
- best = (xlim - bd[bdiagoff + d]) * 2 + dd;
- bestpos = d;
- }
- }
- }
- }
- if (best > 0)
- {
- cost = 2 * c - 1;
- return bestpos;
- }
- }
- }
- }
-
- /** Compare in detail contiguous subsequences of the two files
- which are known, as a whole, to match each other.
-
- The results are recorded in the vectors filevec[N].changed_flag, by
- storing a 1 in the element for each line that is an insertion or deletion.
-
- The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1.
-
- Note that XLIM, YLIM are exclusive bounds.
- All line numbers are origin-0 and discarded lines are not counted. */
-
- private void compareseq (int xoff, int xlim, int yoff, int ylim) {
- /* Slide down the bottom initial diagonal. */
- while (xoff < xlim && yoff < ylim && xvec[xoff] == yvec[yoff]) {
- ++xoff; ++yoff;
- }
- /* Slide up the top initial diagonal. */
- while (xlim > xoff && ylim > yoff && xvec[xlim - 1] == yvec[ylim - 1]) {
- --xlim; --ylim;
- }
-
- /* Handle simple cases. */
- if (xoff == xlim)
- while (yoff < ylim)
- filevec[1].changed_flag[1+filevec[1].realindexes[yoff++]] = true;
- else if (yoff == ylim)
- while (xoff < xlim)
- filevec[0].changed_flag[1+filevec[0].realindexes[xoff++]] = true;
- else
- {
- /* Find a point of correspondence in the middle of the files. */
-
- int d = diag (xoff, xlim, yoff, ylim);
- int c = cost;
- int f = fdiag[fdiagoff + d];
- int b = bdiag[bdiagoff + d];
-
- if (c == 1)
- {
- /* This should be impossible, because it implies that
- one of the two subsequences is empty,
- and that case was handled above without calling `diag'.
- Let's verify that this is true. */
- throw new IllegalArgumentException("Empty subsequence");
- }
- else
- {
- /* Use that point to split this problem into two subproblems. */
- compareseq (xoff, b, yoff, b - d);
- /* This used to use f instead of b,
- but that is incorrect!
- It is not necessarily the case that diagonal d
- has a snake from b to f. */
- compareseq (b, xlim, b - d, ylim);
- }
- }
- }
-
- /** Discard lines from one file that have no matches in the other file.
- */
-
- private void discard_confusing_lines() {
- filevec[0].discard_confusing_lines(filevec[1]);
- filevec[1].discard_confusing_lines(filevec[0]);
- }
-
- private boolean inhibit = false;
-
- /** Adjust inserts/deletes of blank lines to join changes
- as much as possible.
- */
-
- private void shift_boundaries() {
- if (inhibit)
- return;
- filevec[0].shift_boundaries(filevec[1]);
- filevec[1].shift_boundaries(filevec[0]);
- }
-
- public interface ScriptBuilder {
- /** Scan the tables of which lines are inserted and deleted,
- producing an edit script.
- @param changed0 true for lines in first file which do not match 2nd
- @param len0 number of lines in first file
- @param changed1 true for lines in 2nd file which do not match 1st
- @param len1 number of lines in 2nd file
- @return a linked list of changes - or null
- */
- public change build_script(
- boolean[] changed0,int len0,
- boolean[] changed1,int len1
- );
- }
-
- /** Scan the tables of which lines are inserted and deleted,
- producing an edit script in reverse order. */
-
- static class ReverseScript implements ScriptBuilder {
- public change build_script(
- final boolean[] changed0,int len0,
- final boolean[] changed1,int len1)
- {
- change script = null;
- int i0 = 0, i1 = 0;
- while (i0 < len0 || i1 < len1) {
- if (changed0[1+i0] || changed1[1+i1]) {
- int line0 = i0, line1 = i1;
-
- /* Find # lines changed here in each file. */
- while (changed0[1+i0]) ++i0;
- while (changed1[1+i1]) ++i1;
-
- /* Record this change. */
- script = new change(line0, line1, i0 - line0, i1 - line1, script);
- }
-
- /* We have reached lines in the two files that match each other. */
- i0++; i1++;
- }
-
- return script;
- }
- }
-
- static class ForwardScript implements ScriptBuilder {
- /** Scan the tables of which lines are inserted and deleted,
- producing an edit script in forward order. */
- public change build_script(
- final boolean[] changed0,int len0,
- final boolean[] changed1,int len1)
- {
- change script = null;
- int i0 = len0, i1 = len1;
-
- while (i0 >= 0 || i1 >= 0)
- {
- if (changed0[i0] || changed1[i1])
- {
- int line0 = i0, line1 = i1;
-
- /* Find # lines changed here in each file. */
- while (changed0[i0]) --i0;
- while (changed1[i1]) --i1;
-
- /* Record this change. */
- script = new change(i0, i1, line0 - i0, line1 - i1, script);
- }
-
- /* We have reached lines in the two files that match each other. */
- i0--; i1--;
- }
-
- return script;
- }
- }
-
- /** Standard ScriptBuilders. */
- public final static ScriptBuilder
- forwardScript = new ForwardScript(),
- reverseScript = new ReverseScript();
-
- /* Report the differences of two files. DEPTH is the current directory
- depth. */
- public final change diff_2(final boolean reverse) {
- return diff(reverse ? reverseScript : forwardScript);
- }
-
- /** Get the results of comparison as an edit script. The script
- is described by a list of changes. The standard ScriptBuilder
- implementations provide for forward and reverse edit scripts.
- Alternate implementations could, for instance, list common elements
- instead of differences.
- @param bld an object to build the script from change flags
- @return the head of a list of changes
- */
- public change diff(final ScriptBuilder bld) {
-
- /* Some lines are obviously insertions or deletions
- because they don't match anything. Detect them now,
- and avoid even thinking about them in the main comparison algorithm. */
-
- discard_confusing_lines ();
-
- /* Now do the main comparison algorithm, considering just the
- undiscarded lines. */
-
- xvec = filevec[0].undiscarded;
- yvec = filevec[1].undiscarded;
-
- int diags =
- filevec[0].nondiscarded_lines + filevec[1].nondiscarded_lines + 3;
- fdiag = new int[diags];
- fdiagoff = filevec[1].nondiscarded_lines + 1;
- bdiag = new int[diags];
- bdiagoff = filevec[1].nondiscarded_lines + 1;
-
- compareseq (0, filevec[0].nondiscarded_lines,
- 0, filevec[1].nondiscarded_lines);
- fdiag = null;
- bdiag = null;
-
- /* Modify the results slightly to make them prettier
- in cases where that can validly be done. */
-
- shift_boundaries ();
-
- /* Get the results of comparison in the form of a chain
- of `struct change's -- an edit script. */
- return bld.build_script(
- filevec[0].changed_flag,
- filevec[0].buffered_lines,
- filevec[1].changed_flag,
- filevec[1].buffered_lines
- );
-
- }
-
- /** The result of comparison is an "edit script": a chain of change objects.
- Each change represents one place where some lines are deleted
- and some are inserted.
-
- LINE0 and LINE1 are the first affected lines in the two files (origin 0).
- DELETED is the number of lines deleted here from file 0.
- INSERTED is the number of lines inserted here in file 1.
-
- If DELETED is 0 then LINE0 is the number of the line before
- which the insertion was done; vice versa for INSERTED and LINE1. */
-
- public static class change {
- /** Previous or next edit command. */
- public change link;
- /** # lines of file 1 changed here. */
- public final int inserted;
- /** # lines of file 0 changed here. */
- public final int deleted;
- /** Line number of 1st deleted line. */
- public final int line0;
- /** Line number of 1st inserted line. */
- public final int line1;
-
- /** Cons an additional entry onto the front of an edit script OLD.
- LINE0 and LINE1 are the first affected lines in the two files (origin 0).
- DELETED is the number of lines deleted here from file 0.
- INSERTED is the number of lines inserted here in file 1.
-
- If DELETED is 0 then LINE0 is the number of the line before
- which the insertion was done; vice versa for INSERTED and LINE1. */
- public change(int line0, int line1, int deleted, int inserted, change old) {
- this.line0 = line0;
- this.line1 = line1;
- this.inserted = inserted;
- this.deleted = deleted;
- this.link = old;
- //System.err.println(line0+","+line1+","+inserted+","+deleted);
- }
- }
-
- /** Data on one input file being compared.
- */
-
- class file_data {
-
- /** Allocate changed array for the results of comparison. */
- void clear() {
- /* Allocate a flag for each line of each file, saying whether that line
- is an insertion or deletion.
- Allocate an extra element, always zero, at each end of each vector.
- */
- changed_flag = new boolean[buffered_lines + 2];
- }
-
- /** Return equiv_count[I] as the number of lines in this file
- that fall in equivalence class I.
- @return the array of equivalence class counts.
- */
- int[] equivCount() {
- int[] equiv_count = new int[equiv_max];
- for (int i = 0; i < buffered_lines; ++i)
- ++equiv_count[equivs[i]];
- return equiv_count;
- }
-
- /** Discard lines that have no matches in another file.
-
- A line which is discarded will not be considered by the actual
- comparison algorithm; it will be as if that line were not in the file.
- The file's `realindexes' table maps virtual line numbers
- (which don't count the discarded lines) into real line numbers;
- this is how the actual comparison algorithm produces results
- that are comprehensible when the discarded lines are counted.
-
- When we discard a line, we also mark it as a deletion or insertion
- so that it will be printed in the output.
- @param f the other file
- */
- void discard_confusing_lines(file_data f) {
- clear();
- /* Set up table of which lines are going to be discarded. */
- final byte[] discarded = discardable(f.equivCount());
-
- /* Don't really discard the provisional lines except when they occur
- in a run of discardables, with nonprovisionals at the beginning
- and end. */
- filterDiscards(discarded);
-
- /* Actually discard the lines. */
- discard(discarded);
- }
-
- /** Mark to be discarded each line that matches no line of another file.
- If a line matches many lines, mark it as provisionally discardable.
- @see equivCount()
- @param counts The count of each equivalence number for the other file.
- @return 0=nondiscardable, 1=discardable or 2=provisionally discardable
- for each line
- */
-
- private byte[] discardable(final int[] counts) {
- final int end = buffered_lines;
- final byte[] discards = new byte[end];
- final int[] equivs = this.equivs;
- int many = 5;
- int tem = end / 64;
-
- /* Multiply MANY by approximate square root of number of lines.
- That is the threshold for provisionally discardable lines. */
- while ((tem = tem >> 2) > 0)
- many *= 2;
-
- for (int i = 0; i < end; i++)
- {
- int nmatch;
- if (equivs[i] == 0)
- continue;
- nmatch = counts[equivs[i]];
- if (nmatch == 0)
- discards[i] = 1;
- else if (nmatch > many)
- discards[i] = 2;
- }
- return discards;
- }
-
- /** Don't really discard the provisional lines except when they occur
- in a run of discardables, with nonprovisionals at the beginning
- and end. */
-
- private void filterDiscards(final byte[] discards) {
- final int end = buffered_lines;
-
- for (int i = 0; i < end; i++)
- {
- /* Cancel provisional discards not in middle of run of discards. */
- if (discards[i] == 2)
- discards[i] = 0;
- else if (discards[i] != 0)
- {
- /* We have found a nonprovisional discard. */
- int j;
- int length;
- int provisional = 0;
-
- /* Find end of this run of discardable lines.
- Count how many are provisionally discardable. */
- for (j = i; j < end; j++)
- {
- if (discards[j] == 0)
- break;
- if (discards[j] == 2)
- ++provisional;
- }
-
- /* Cancel provisional discards at end, and shrink the run. */
- while (j > i && discards[j - 1] == 2) {
- discards[--j] = 0; --provisional;
- }
-
- /* Now we have the length of a run of discardable lines
- whose first and last are not provisional. */
- length = j - i;
-
- /* If 1/4 of the lines in the run are provisional,
- cancel discarding of all provisional lines in the run. */
- if (provisional * 4 > length)
- {
- while (j > i)
- if (discards[--j] == 2)
- discards[j] = 0;
- }
- else
- {
- int consec;
- int minimum = 1;
- int tem = length / 4;
-
- /* MINIMUM is approximate square root of LENGTH/4.
- A subrun of two or more provisionals can stand
- when LENGTH is at least 16.
- A subrun of 4 or more can stand when LENGTH >= 64. */
- while ((tem = tem >> 2) > 0)
- minimum *= 2;
- minimum++;
-
- /* Cancel any subrun of MINIMUM or more provisionals
- within the larger run. */
- for (j = 0, consec = 0; j < length; j++)
- if (discards[i + j] != 2)
- consec = 0;
- else if (minimum == ++consec)
- /* Back up to start of subrun, to cancel it all. */
- j -= consec;
- else if (minimum < consec)
- discards[i + j] = 0;
-
- /* Scan from beginning of run
- until we find 3 or more nonprovisionals in a row
- or until the first nonprovisional at least 8 lines in.
- Until that point, cancel any provisionals. */
- for (j = 0, consec = 0; j < length; j++)
- {
- if (j >= 8 && discards[i + j] == 1)
- break;
- if (discards[i + j] == 2) {
- consec = 0; discards[i + j] = 0;
- }
- else if (discards[i + j] == 0)
- consec = 0;
- else
- consec++;
- if (consec == 3)
- break;
- }
-
- /* I advances to the last line of the run. */
- i += length - 1;
-
- /* Same thing, from end. */
- for (j = 0, consec = 0; j < length; j++)
- {
- if (j >= 8 && discards[i - j] == 1)
- break;
- if (discards[i - j] == 2) {
- consec = 0; discards[i - j] = 0;
- }
- else if (discards[i - j] == 0)
- consec = 0;
- else
- consec++;
- if (consec == 3)
- break;
- }
- }
- }
- }
- }
-
- /** Actually discard the lines.
- @param discards flags lines to be discarded
- */
- private void discard(final byte[] discards) {
- final int end = buffered_lines;
- int j = 0;
- for (int i = 0; i < end; ++i)
- if (no_discards || discards[i] == 0)
- {
- undiscarded[j] = equivs[i];
- realindexes[j++] = i;
- }
- else
- changed_flag[1+i] = true;
- nondiscarded_lines = j;
- }
-
- file_data(Object[] data,Hashtable h) {
- buffered_lines = data.length;
-
- equivs = new int[buffered_lines];
- undiscarded = new int[buffered_lines];
- realindexes = new int[buffered_lines];
-
- for (int i = 0; i < data.length; ++i) {
- Integer ir = (Integer)h.get(data[i]);
- if (ir == null)
- h.put(data[i],new Integer(equivs[i] = equiv_max++));
- else
- equivs[i] = ir.intValue();
- }
- }
-
- /** Adjust inserts/deletes of blank lines to join changes
- as much as possible.
-
- We do something when a run of changed lines include a blank
- line at one end and have an excluded blank line at the other.
- We are free to choose which blank line is included.
- `compareseq' always chooses the one at the beginning,
- but usually it is cleaner to consider the following blank line
- to be the "change". The only exception is if the preceding blank line
- would join this change to other changes.
- @param f the file being compared against
- */
-
- void shift_boundaries(file_data f) {
- final boolean[] changed = changed_flag;
- final boolean[] other_changed = f.changed_flag;
- int i = 0;
- int j = 0;
- int i_end = buffered_lines;
- int preceding = -1;
- int other_preceding = -1;
-
- for (;;)
- {
- int start, end, other_start;
-
- /* Scan forwards to find beginning of another run of changes.
- Also keep track of the corresponding point in the other file. */
-
- while (i < i_end && !changed[1+i])
- {
- while (other_changed[1+j++])
- /* Non-corresponding lines in the other file
- will count as the preceding batch of changes. */
- other_preceding = j;
- i++;
- }
-
- if (i == i_end)
- break;
-
- start = i;
- other_start = j;
-
- for (;;)
- {
- /* Now find the end of this run of changes. */
-
- while (i < i_end && changed[1+i]) i++;
- end = i;
-
- /* If the first changed line matches the following unchanged one,
- and this run does not follow right after a previous run,
- and there are no lines deleted from the other file here,
- then classify the first changed line as unchanged
- and the following line as changed in its place. */
-
- /* You might ask, how could this run follow right after another?
- Only because the previous run was shifted here. */
-
- if (end != i_end
- && equivs[start] == equivs[end]
- && !other_changed[1+j]
- && end != i_end
- && !((preceding >= 0 && start == preceding)
- || (other_preceding >= 0
- && other_start == other_preceding)))
- {
- changed[1+end++] = true;
- changed[1+start++] = false;
- ++i;
- /* Since one line-that-matches is now before this run
- instead of after, we must advance in the other file
- to keep in synch. */
- ++j;
- }
- else
- break;
- }
-
- preceding = i;
- other_preceding = j;
- }
- }
-
- /** Number of elements (lines) in this file. */
- final int buffered_lines;
-
- /** Vector, indexed by line number, containing an equivalence code for
- each line. It is this vector that is actually compared with that
- of another file to generate differences. */
- private final int[] equivs;
-
- /** Vector, like the previous one except that
- the elements for discarded lines have been squeezed out. */
- final int[] undiscarded;
-
- /** Vector mapping virtual line numbers (not counting discarded lines)
- to real ones (counting those lines). Both are origin-0. */
- final int[] realindexes;
-
- /** Total number of nondiscarded lines. */
- int nondiscarded_lines;
-
- /** Array, indexed by real origin-1 line number,
- containing true for a line that is an insertion or a deletion.
- The results of comparison are stored here. */
- boolean[] changed_flag;
-
- }
-}
diff --git a/src/main/java/org/exist/versioning/Diff.java b/src/main/java/org/exist/versioning/Diff.java
index 4981a08..dc16e3b 100644
--- a/src/main/java/org/exist/versioning/Diff.java
+++ b/src/main/java/org/exist/versioning/Diff.java
@@ -1,27 +1,26 @@
-package org.exist.versioning;
-
-import org.exist.dom.persistent.DocumentImpl;
-import org.exist.util.serializer.Receiver;/*
- * eXist Open Source Native XML Database
- * Copyright (C) 2001-07 The eXist Project
- * http://exist-db.org
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+/**
+ * Versioning Module for eXist-db XQuery
+ * Copyright (C) 2008 eXist-db
+ * http://exist-db.org
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
*
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * \$Id\$
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+package org.exist.versioning;
+
+import org.exist.dom.persistent.DocumentImpl;
+import org.exist.util.serializer.Receiver;
public interface Diff {
void diff(DocumentImpl docA, DocumentImpl docB)
diff --git a/src/main/java/org/exist/versioning/DiffException.java b/src/main/java/org/exist/versioning/DiffException.java
index 27813e7..a0b2863 100644
--- a/src/main/java/org/exist/versioning/DiffException.java
+++ b/src/main/java/org/exist/versioning/DiffException.java
@@ -1,23 +1,21 @@
-/*
- * eXist Open Source Native XML Database
- * Copyright (C) 2001-07 The eXist Project
- * http://exist-db.org
+/**
+ * Versioning Module for eXist-db XQuery
+ * Copyright (C) 2008 eXist-db
+ * http://exist-db.org
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * $Id$
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.exist.versioning;
@@ -25,11 +23,11 @@ public class DiffException extends Exception {
private static final long serialVersionUID = 2294067063976070362L;
- public DiffException(String message) {
+ public DiffException(final String message) {
super(message);
}
- public DiffException(String message, Throwable cause) {
+ public DiffException(final String message, final Throwable cause) {
super(message, cause);
}
}
diff --git a/src/main/java/org/exist/versioning/DiffNode.java b/src/main/java/org/exist/versioning/DiffNode.java
index 396d42c..d7b8fcb 100644
--- a/src/main/java/org/exist/versioning/DiffNode.java
+++ b/src/main/java/org/exist/versioning/DiffNode.java
@@ -1,3 +1,22 @@
+/**
+ * Versioning Module for eXist-db XQuery
+ * Copyright (C) 2008 eXist-db
+ * http://exist-db.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
package org.exist.versioning;
import org.exist.numbering.NodeId;
@@ -12,48 +31,55 @@ public class DiffNode {
protected int status = UNCHANGED;
- protected NodeId nodeId;
- protected int nodeType;
+ protected final NodeId nodeId;
+ protected final int nodeType;
protected String value = null;
protected QName qname = null;
- public DiffNode(NodeId nodeId, int nodeType, String value) {
+ public DiffNode(final NodeId nodeId, final int nodeType, final String value) {
this.nodeId = nodeId;
this.nodeType = nodeType;
this.value = value;
}
- public DiffNode(NodeId nodeId, int nodeType, QName qname) {
+ public DiffNode(final NodeId nodeId, final int nodeType, final QName qname) {
this.nodeId = nodeId;
this.nodeType = nodeType;
this.qname = qname;
}
- public void setStatus(int status) {
+ public void setStatus(final int status) {
this.status = status;
}
- public boolean equals(Object obj) {
- DiffNode other = (DiffNode) obj;
- if (nodeType != other.nodeType)
+ @Override
+ public boolean equals(final Object obj) {
+ final DiffNode other = (DiffNode) obj;
+ if (nodeType != other.nodeType) {
return false;
- if (qname != null)
+ }
+ if (qname != null) {
return qname.equals(other.qname);
- else
+ } else {
return value.equals(other.value);
+ }
}
+ @Override
public int hashCode() {
- if (qname == null)
+ if (qname == null) {
return (value.hashCode() << 1) + nodeType;
- else
+ } else {
return (qname.hashCode() << 1) + nodeType;
+ }
}
+ @Override
public String toString() {
- if (qname == null)
+ if (qname == null) {
return nodeType + " " + nodeId.toString() + " " + value;
- else
+ } else {
return nodeType + " " + nodeId.toString() + " " + qname;
+ }
}
}
\ No newline at end of file
diff --git a/src/main/java/org/exist/versioning/Difference.java b/src/main/java/org/exist/versioning/Difference.java
index 7cae9e8..962f6bc 100644
--- a/src/main/java/org/exist/versioning/Difference.java
+++ b/src/main/java/org/exist/versioning/Difference.java
@@ -1,3 +1,22 @@
+/**
+ * Versioning Module for eXist-db XQuery
+ * Copyright (C) 2008 eXist-db
+ * http://exist-db.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
package org.exist.versioning;
import org.exist.dom.persistent.NodeProxy;
@@ -32,70 +51,73 @@ public abstract class Difference implements Comparable {
public final static QName ELEMENT_APPEND = new QName("append", StandardDiff.NAMESPACE, StandardDiff.PREFIX);
public final static QName ELEMENT_DELETE = new QName("delete", StandardDiff.NAMESPACE, StandardDiff.PREFIX);
- protected int type;
- protected NodeProxy refChild;
+ protected final int type;
+ protected final NodeProxy refChild;
- public Difference(int type, NodeProxy reference) {
+ public Difference(final int type, final NodeProxy refChild) {
this.type = type;
- this.refChild = reference;
+ this.refChild = refChild;
}
- public abstract void serialize(DBBroker broker, Receiver handler);
+ public abstract void serialize(final DBBroker broker, final Receiver handler);
- public boolean equals(Object obj) {
- Difference other = (Difference) obj;
+ @Override
+ public boolean equals(final Object obj) {
+ final Difference other = (Difference) obj;
return refChild.getNodeId().equals(other.refChild.getNodeId());
}
- public int compareTo(Difference other) {
+ @Override
+ public int compareTo(final Difference other) {
return refChild.getNodeId().compareTo(other.refChild.getNodeId());
}
public static class Insert extends Difference {
- protected DocumentImpl otherDoc;
+ protected final DocumentImpl otherDoc;
protected DiffNode[] nodes;
- public Insert(NodeProxy reference, DocumentImpl otherDoc) {
+ public Insert(final NodeProxy reference, final DocumentImpl otherDoc) {
super(INSERT, reference);
this.otherDoc = otherDoc;
}
- public Insert(int type, NodeProxy reference, DocumentImpl otherDoc) {
+ public Insert(final int type, final NodeProxy reference, final DocumentImpl otherDoc) {
super(type, reference);
this.otherDoc = otherDoc;
}
- protected void addNodes(DiffNode[] nodesToAdd) {
- if (nodes == null)
+ protected void addNodes(final DiffNode[] nodesToAdd) {
+ if (nodes == null) {
nodes = nodesToAdd;
- else {
- DiffNode n[] = new DiffNode[nodes.length + nodesToAdd.length];
+ } else {
+ final DiffNode n[] = new DiffNode[nodes.length + nodesToAdd.length];
System.arraycopy(nodes, 0, n, 0, nodes.length);
System.arraycopy(nodesToAdd, 0, n, nodes.length, nodesToAdd.length);
nodes = n;
}
}
- public void serialize(DBBroker broker, Receiver handler) {
+ @Override
+ public void serialize(final DBBroker broker, final Receiver handler) {
try {
- AttrList attribs = new AttrList();
+ final AttrList attribs = new AttrList();
attribs.addAttribute(ATTR_REF, refChild.getNodeId().toString());
handler.startElement(ELEMENT_INSERT, attribs);
serializeChildren(broker, handler);
handler.endElement(ELEMENT_INSERT);
- } catch (SAXException e) {
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ } catch (final SAXException e) {
+ e.printStackTrace();
}
}
- protected void serializeChildren(DBBroker broker, Receiver handler) throws SAXException {
+ protected void serializeChildren(final DBBroker broker, final Receiver handler) throws SAXException {
AttrList attribs;
for (int i = 0; i < nodes.length; i++) {
switch (nodes[i].nodeType) {
case XMLStreamReader.ATTRIBUTE:
attribs = new AttrList();
- AttrImpl attr = (AttrImpl) broker.objectWith(otherDoc, nodes[i].nodeId);
+ final AttrImpl attr = (AttrImpl) broker.objectWith(otherDoc, nodes[i].nodeId);
attribs.addAttribute(new QName(attr.getLocalName(), attr.getNamespaceURI(), attr.getPrefix()),
attr.getValue(), attr.getType());
handler.startElement(ELEMENT_ATTRIBUTE, attribs);
@@ -105,13 +127,13 @@ protected void serializeChildren(DBBroker broker, Receiver handler) throws SAXEx
// check if there's a complete element to write, not just a start or end tag
// if yes, just copy the element, if no, write a start-tag node
boolean isClosed = false;
- NodeId nodeId = nodes[i].nodeId;
+ final NodeId nodeId = nodes[i].nodeId;
for (int j = i; j < nodes.length; j++) {
if (nodes[j].nodeType == XMLStreamReader.END_ELEMENT &&
nodes[j].nodeId.equals(nodeId)) {
isClosed = true;
- NodeProxy proxy = new NodeProxy(otherDoc, nodes[i].nodeId);
- Serializer serializer = broker.getSerializer();
+ final NodeProxy proxy = new NodeProxy(otherDoc, nodes[i].nodeId);
+ final Serializer serializer = broker.getSerializer();
serializer.reset();
serializer.setProperty(Serializer.GENERATE_DOC_EVENTS, "false");
serializer.setReceiver(handler);
@@ -144,8 +166,8 @@ protected void serializeChildren(DBBroker broker, Receiver handler) throws SAXEx
handler.endElement(ELEMENT_COMMENT);
break;
default:
- NodeProxy proxy = new NodeProxy(otherDoc, nodes[i].nodeId);
- Serializer serializer = broker.getSerializer();
+ final NodeProxy proxy = new NodeProxy(otherDoc, nodes[i].nodeId);
+ final Serializer serializer = broker.getSerializer();
serializer.reset();
serializer.setProperty(Serializer.GENERATE_DOC_EVENTS, "false");
serializer.setReceiver(handler);
@@ -158,39 +180,41 @@ protected void serializeChildren(DBBroker broker, Receiver handler) throws SAXEx
public final static class Append extends Insert {
- public Append(NodeProxy reference, DocumentImpl otherDoc) {
+ public Append(final NodeProxy reference, final DocumentImpl otherDoc) {
super(APPEND, reference, otherDoc);
}
- public void serialize(DBBroker broker, Receiver handler) {
+ @Override
+ public void serialize(final DBBroker broker, final Receiver handler) {
try {
- AttrList attribs = new AttrList();
+ final AttrList attribs = new AttrList();
attribs.addAttribute(ATTR_REF, refChild.getNodeId().toString());
handler.startElement(ELEMENT_APPEND, attribs);
serializeChildren(broker, handler);
handler.endElement(ELEMENT_APPEND);
- } catch (SAXException e) {
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ } catch (final SAXException e) {
+ e.printStackTrace();
}
}
}
public final static class Delete extends Difference {
- protected int event = -1;
+ protected final int event;
- public Delete(NodeProxy reference) {
+ public Delete(final NodeProxy reference) {
this(-1, reference);
}
- public Delete(int event, NodeProxy reference) {
+ public Delete(final int event, final NodeProxy reference) {
super(DELETE, reference);
this.event = event;
}
- public void serialize(DBBroker broker, Receiver handler) {
+ @Override
+ public void serialize(final DBBroker broker, final Receiver handler) {
try {
- AttrList attribs = new AttrList();
+ final AttrList attribs = new AttrList();
if (event == XMLStreamReader.START_ELEMENT || event == XMLStreamReader.END_ELEMENT) {
String ev = event == XMLStreamReader.START_ELEMENT ? "start" : "end";
attribs.addAttribute(ATTR_EVENT, ev);
@@ -198,9 +222,9 @@ public void serialize(DBBroker broker, Receiver handler) {
attribs.addAttribute(ATTR_REF, refChild.getNodeId().toString());
handler.startElement(ELEMENT_DELETE, attribs);
handler.endElement(ELEMENT_DELETE);
- } catch (SAXException e) {
+ } catch (final SAXException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/exist/versioning/Patch.java b/src/main/java/org/exist/versioning/Patch.java
index 8904041..82d84c3 100644
--- a/src/main/java/org/exist/versioning/Patch.java
+++ b/src/main/java/org/exist/versioning/Patch.java
@@ -1,23 +1,21 @@
-/*
- * eXist Open Source Native XML Database
- * Copyright (C) 2001-07 The eXist Project
- * http://exist-db.org
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+/**
+ * Versioning Module for eXist-db XQuery
+ * Copyright (C) 2008 eXist-db
+ * http://exist-db.org
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
*
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * $Id$
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.exist.versioning;
@@ -49,9 +47,7 @@
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.Stack;
+import java.util.*;
/**
* Patch a given source document by applying a diff in eXist's diff format.
@@ -77,7 +73,7 @@ public class Patch {
private Map appendedNodes = null;
private boolean annotate = false;
- private Stack elementStack = null;
+ private Deque elementStack = null;
private NewArrayNodeSet changeSet = null;
private DocumentImpl diffDoc;
@@ -148,7 +144,7 @@ public void patch(ExtendedXMLStreamReader reader, Receiver receiver) throws Diff
public void annotate(ExtendedXMLStreamReader reader, Receiver receiver) throws DiffException {
annotate = true;
- elementStack = new Stack();
+ elementStack = new ArrayDeque<>();
buildChangeSet();
try {
NodeId skipSubtree = null;
@@ -212,7 +208,7 @@ private void insertNode(StoredNode insertedNode, Receiver receiver, String chang
receiver.attribute(qname, reader.getAttributeValue(i));
}
} else if ("comment".equals(reader.getLocalName())) {
- StringBuffer buf = new StringBuffer();
+ StringBuilder buf = new StringBuilder();
while (reader.hasNext()) {
status = reader.next();
if (status == XMLStreamReader.END_ELEMENT &&
@@ -338,14 +334,14 @@ private void copyNode(ExtendedXMLStreamReader reader, Receiver receiver, int sta
}
}
- private void parseDiff(DBBroker broker, DocumentImpl doc) throws XPathException {
- deletedNodes = new TreeMap();
- insertedNodes = new TreeMap();
- appendedNodes = new TreeMap();
- XQuery service = broker.getXQueryService();
+ private void parseDiff(final DBBroker broker, final DocumentImpl doc) throws XPathException {
+ deletedNodes = new TreeMap<>();
+ insertedNodes = new TreeMap<>();
+ appendedNodes = new TreeMap<>();
+ XQuery service = broker.getBrokerPool().getXQueryService();
Sequence changes;
try {
- changes = service.execute("declare namespace v=\"http://exist-db.org/versioning\";" +
+ changes = service.execute(broker, "declare namespace v=\"http://exist-db.org/versioning\";" +
"doc('" + doc.getURI().toString() + "')/v:version/v:diff/*",
Sequence.EMPTY_SEQUENCE, AccessContext.TEST);
} catch (PermissionDeniedException e) {
diff --git a/src/main/java/org/exist/versioning/StandardDiff.java b/src/main/java/org/exist/versioning/StandardDiff.java
index 41de200..a1012f0 100644
--- a/src/main/java/org/exist/versioning/StandardDiff.java
+++ b/src/main/java/org/exist/versioning/StandardDiff.java
@@ -1,3 +1,22 @@
+/**
+ * Versioning Module for eXist-db XQuery
+ * Copyright (C) 2008 eXist-db
+ * http://exist-db.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
package org.exist.versioning;
import bmsi.util.Diff;
@@ -34,19 +53,19 @@ public class StandardDiff implements org.exist.versioning.Diff {
private final static QName DIFF_ELEMENT = new QName("diff", NAMESPACE, PREFIX);
- private DBBroker broker;
+ private final DBBroker broker;
private List changes = null;
- public StandardDiff(DBBroker broker) {
+ public StandardDiff(final DBBroker broker) {
this.broker = broker;
}
- public void diff(DocumentImpl docA, DocumentImpl docB)
- throws DiffException {
+ @Override
+ public void diff(final DocumentImpl docA, final DocumentImpl docB) throws DiffException {
try {
- DiffNode[] nodesA = getNodes(broker, docA);
- DiffNode[] nodesB = getNodes(broker, docB);
+ final DiffNode[] nodesA = getNodes(broker, docA);
+ final DiffNode[] nodesB = getNodes(broker, docB);
if (LOG.isTraceEnabled()) {
LOG.trace("Source:");
@@ -55,32 +74,30 @@ public void diff(DocumentImpl docA, DocumentImpl docB)
debugNodes(nodesB);
}
- Diff diff = new Diff(nodesA, nodesB);
- Diff.change script = diff.diff_2(false);
- changes = getChanges(script, docA, docB, nodesA, nodesB);
- } catch (XMLStreamException e) {
- throw new DiffException(e.getMessage(), e);
- } catch (IOException e) {
+ final Diff diff = new Diff(nodesA, nodesB);
+ final Diff.change script = diff.diff_2(false);
+ this.changes = getChanges(script, docA, docB, nodesA, nodesB);
+ } catch (final XMLStreamException | IOException e) {
throw new DiffException(e.getMessage(), e);
}
}
- private void debugNodes(DiffNode[] nodes) {
- StringBuffer buf = new StringBuffer();
+ private void debugNodes(final DiffNode[] nodes) {
+ final StringBuilder buf = new StringBuilder();
buf.append('\n');
for (int i = 0; i < nodes.length; i++) {
- DiffNode node = nodes[i];
+ final DiffNode node = nodes[i];
buf.append(Integer.toString(i)).append(' ').append(node.toString()).append('\n');
}
LOG.trace(buf.toString());
}
+ @Override
public String diff2XML() throws DiffException {
- try {
- StringWriter writer = new StringWriter();
- SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject(
+ try(final StringWriter writer = new StringWriter()) {
+ final SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject(
SAXSerializer.class);
- Properties outputProperties = new Properties();
+ final Properties outputProperties = new Properties();
outputProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
outputProperties.setProperty(OutputKeys.INDENT, "no");
sax.setOutput(writer, outputProperties);
@@ -88,7 +105,7 @@ public String diff2XML() throws DiffException {
diff2XML(sax);
sax.endDocument();
return writer.toString();
- } catch (SAXException e) {
+ } catch (final IOException | SAXException e) {
throw new DiffException("error while serializing diff: " + e.getMessage(), e);
}
}
diff --git a/src/main/java/org/exist/versioning/VersioningFilter.java b/src/main/java/org/exist/versioning/VersioningFilter.java
index 323cad8..63d500a 100644
--- a/src/main/java/org/exist/versioning/VersioningFilter.java
+++ b/src/main/java/org/exist/versioning/VersioningFilter.java
@@ -1,3 +1,22 @@
+/**
+ * Versioning Module for eXist-db XQuery
+ * Copyright (C) 2008 eXist-db
+ * http://exist-db.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
package org.exist.versioning;
import org.exist.dom.persistent.DocumentImpl;
@@ -24,33 +43,26 @@ public class VersioningFilter extends CustomMatchListener {
private int elementStack = 0;
- public VersioningFilter() {
- }
-
@Override
- public void startElement(QName qname, AttrList attribs) throws SAXException {
+ public void startElement(final QName qname, final AttrList attribs) throws SAXException {
if (elementStack == 0) {
final NodeHandle node = getCurrentNode();
if (node != null) {
final DocumentImpl doc = node.getOwnerDocument();
- XmldbURI uri = doc.getURI();
+ final XmldbURI uri = doc.getURI();
if (!uri.startsWith(XmldbURI.SYSTEM_COLLECTION_URI)) {
if (doc.getCollection().getConfiguration(getBroker()).triggerRegistered(VersioningTrigger.class)) {
try {
- long rev = VersioningHelper.getCurrentRevision(getBroker(), doc.getURI());
- long time = System.currentTimeMillis();
- String key = Long.toHexString(time) + Long.toHexString(rev);
+ final long rev = VersioningHelper.getCurrentRevision(getBroker(), doc.getURI());
+ final long time = System.currentTimeMillis();
+ final String key = Long.toHexString(time) + Long.toHexString(rev);
attribs.addAttribute(ATTR_REVISION, rev == 0 ? "0" : Long.toString(rev));
attribs.addAttribute(ATTR_KEY, key);
attribs.addAttribute(ATTR_PATH, doc.getURI().toString());
- } catch (XPathException e) {
- LOG.error("Exception while retrieving versioning info: " + e.getMessage(), e);
- } catch (IOException e) {
+ } catch (XPathException | IOException | PermissionDeniedException e) {
LOG.error("Exception while retrieving versioning info: " + e.getMessage(), e);
- } catch (PermissionDeniedException e) {
- LOG.error("Exception while retrieving versioning info: " + e.getMessage(), e);
- }
+ }
}
}
}
@@ -59,7 +71,8 @@ public void startElement(QName qname, AttrList attribs) throws SAXException {
nextListener.startElement(qname, attribs);
}
- public void endElement(QName qname) throws SAXException {
+ @Override
+ public void endElement(final QName qname) throws SAXException {
--elementStack;
nextListener.endElement(qname);
}
diff --git a/src/main/java/org/exist/versioning/VersioningHelper.java b/src/main/java/org/exist/versioning/VersioningHelper.java
index be9c2f3..398c024 100644
--- a/src/main/java/org/exist/versioning/VersioningHelper.java
+++ b/src/main/java/org/exist/versioning/VersioningHelper.java
@@ -1,29 +1,28 @@
-/*
- * eXist Open Source Native XML Database
- * Copyright (C) 2001-07 The eXist Project
- * http://exist-db.org
+/**
+ * Versioning Module for eXist-db XQuery
+ * Copyright (C) 2008 eXist-db
+ * http://exist-db.org
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * $Id$
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.exist.versioning;
import org.exist.security.PermissionDeniedException;
import org.exist.security.xacml.AccessContext;
import org.exist.source.StringSource;
+import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
import org.exist.storage.XQueryPool;
import org.exist.xmldb.XmldbURI;
@@ -77,87 +76,116 @@ public class VersioningHelper {
private final static StringSource GET_BASE_REV_FOR_KEY_SOURCE = new StringSource(GET_BASE_REV_FOR_KEY);
- public static long getCurrentRevision(DBBroker broker, XmldbURI docPath) throws XPathException, IOException, PermissionDeniedException {
- String docName = docPath.lastSegment().toString();
- XmldbURI collectionPath = docPath.removeLastSegment();
- XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath);
- XQuery xquery = broker.getXQueryService();
- XQueryPool pool = xquery.getXQueryPool();
- XQueryContext context;
- CompiledXQuery compiled = pool.borrowCompiledXQuery(broker, GET_CURRENT_REV_SOURCE);
- if(compiled == null)
- context = xquery.newContext(AccessContext.VALIDATION_INTERNAL);
- else
- context = compiled.getContext();
+ public static long getCurrentRevision(final DBBroker broker, final XmldbURI docPath)
+ throws XPathException, IOException, PermissionDeniedException {
+ final String docName = docPath.lastSegment().toString();
+ final XmldbURI collectionPath = docPath.removeLastSegment();
+ final XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath);
+
+ final BrokerPool brokerPool = broker.getBrokerPool();
+ final XQuery xquery = brokerPool.getXQueryService();
+ final XQueryPool xqueryPool = brokerPool.getXQueryPool();
+ CompiledXQuery compiled = xqueryPool.borrowCompiledXQuery(broker, GET_CURRENT_REV_SOURCE);
+ final XQueryContext context;
+ if(compiled == null) {
+ context = new XQueryContext(brokerPool, AccessContext.VALIDATION_INTERNAL);
+ } else {
+ context = compiled.getContext();
+ }
context.declareVariable("collection", path.toString());
context.declareVariable("document", docName);
- if(compiled == null)
- compiled = xquery.compile(context, GET_CURRENT_REV_SOURCE);
+ if(compiled == null) {
+ compiled = xquery.compile(broker, context, GET_CURRENT_REV_SOURCE);
+ } else {
+ compiled.getContext().updateContext(context);
+ context.getWatchDog().reset();
+ }
+
try {
- Sequence s = xquery.execute(compiled, Sequence.EMPTY_SEQUENCE);
- if (s.isEmpty())
+ final Sequence s = xquery.execute(broker, compiled, Sequence.EMPTY_SEQUENCE);
+ if (s.isEmpty()) {
return 0;
- IntegerValue iv = (IntegerValue) s.itemAt(0);
+ }
+ final IntegerValue iv = (IntegerValue) s.itemAt(0);
return iv.getLong();
} finally {
- pool.returnCompiledXQuery(GET_CURRENT_REV_SOURCE, compiled);
+ xqueryPool.returnCompiledXQuery(GET_CURRENT_REV_SOURCE, compiled);
}
}
- public static boolean newerRevisionExists(DBBroker broker, XmldbURI docPath, long baseRev, String key) throws XPathException, IOException, PermissionDeniedException {
- String docName = docPath.lastSegment().toString();
- XmldbURI collectionPath = docPath.removeLastSegment();
- XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath);
- XQuery xquery = broker.getXQueryService();
- XQueryPool pool = xquery.getXQueryPool();
- XQueryContext context;
- CompiledXQuery compiled = pool.borrowCompiledXQuery(broker, GET_CONFLICTING_REV_SOURCE);
- if(compiled == null)
- context = xquery.newContext(AccessContext.VALIDATION_INTERNAL);
- else
+ public static boolean newerRevisionExists(final DBBroker broker, final XmldbURI docPath, final long baseRev,
+ final String key) throws XPathException, IOException, PermissionDeniedException {
+ final String docName = docPath.lastSegment().toString();
+ final XmldbURI collectionPath = docPath.removeLastSegment();
+ final XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath);
+
+ final BrokerPool brokerPool = broker.getBrokerPool();
+ final XQuery xquery = brokerPool.getXQueryService();
+ final XQueryPool xqueryPool = brokerPool.getXQueryPool();
+ final XQueryContext context;
+ CompiledXQuery compiled = xqueryPool.borrowCompiledXQuery(broker, GET_CONFLICTING_REV_SOURCE);
+ if(compiled == null) {
+ context = new XQueryContext(brokerPool, AccessContext.VALIDATION_INTERNAL);
+ } else {
context = compiled.getContext();
+ }
context.declareVariable("collection", path.toString());
context.declareVariable("document", docName);
context.declareVariable("base", new IntegerValue(baseRev));
context.declareVariable("key", key);
- if(compiled == null)
- compiled = xquery.compile(context, GET_CONFLICTING_REV_SOURCE);
+ if(compiled == null) {
+ compiled = xquery.compile(broker, context, GET_CONFLICTING_REV_SOURCE);
+ } else {
+ compiled.getContext().updateContext(context);
+ context.getWatchDog().reset();
+ }
+
try {
- Sequence s = xquery.execute(compiled, Sequence.EMPTY_SEQUENCE);
+ final Sequence s = xquery.execute(broker, compiled, Sequence.EMPTY_SEQUENCE);
return !s.isEmpty();
} finally {
- pool.returnCompiledXQuery(GET_CONFLICTING_REV_SOURCE, compiled);
+ xqueryPool.returnCompiledXQuery(GET_CONFLICTING_REV_SOURCE, compiled);
}
}
- public static long getBaseRevision(DBBroker broker, XmldbURI docPath, long baseRev, String sessionKey) throws XPathException, IOException, PermissionDeniedException {
- String docName = docPath.lastSegment().toString();
- XmldbURI collectionPath = docPath.removeLastSegment();
- XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath);
- XQuery xquery = broker.getXQueryService();
- XQueryPool pool = xquery.getXQueryPool();
- XQueryContext context;
- CompiledXQuery compiled = pool.borrowCompiledXQuery(broker, GET_BASE_REV_FOR_KEY_SOURCE);
- if(compiled == null)
- context = xquery.newContext(AccessContext.VALIDATION_INTERNAL);
- else
+ public static long getBaseRevision(final DBBroker broker, final XmldbURI docPath, final long baseRev,
+ final String sessionKey) throws XPathException, IOException, PermissionDeniedException {
+ final String docName = docPath.lastSegment().toString();
+ final XmldbURI collectionPath = docPath.removeLastSegment();
+ final XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath);
+
+ final BrokerPool brokerPool = broker.getBrokerPool();
+ final XQuery xquery = brokerPool.getXQueryService();
+ final XQueryPool xqueryPool = brokerPool.getXQueryPool();
+ final XQueryContext context;
+ CompiledXQuery compiled = xqueryPool.borrowCompiledXQuery(broker, GET_BASE_REV_FOR_KEY_SOURCE);
+ if (compiled == null) {
+ context = new XQueryContext(brokerPool, AccessContext.VALIDATION_INTERNAL);
+ } else {
context = compiled.getContext();
+ }
context.declareVariable("collection", path.toString());
context.declareVariable("document", docName);
context.declareVariable("base", new IntegerValue(baseRev));
context.declareVariable("key", sessionKey);
- if(compiled == null)
- compiled = xquery.compile(context, GET_BASE_REV_FOR_KEY_SOURCE);
+ if (compiled == null) {
+ compiled = xquery.compile(broker, context, GET_BASE_REV_FOR_KEY_SOURCE);
+ } else {
+ compiled.getContext().updateContext(context);
+ context.getWatchDog().reset();
+ }
+
try {
- Sequence s = xquery.execute(compiled, Sequence.EMPTY_SEQUENCE);
- if (s.isEmpty())
+ final Sequence s = xquery.execute(broker, compiled, Sequence.EMPTY_SEQUENCE);
+ if (s.isEmpty()) {
return 0;
-
- IntegerValue iv = (IntegerValue) s.itemAt(0);
- return iv.getLong();
+ } else {
+ final IntegerValue iv = (IntegerValue) s.itemAt(0);
+ return iv.getLong();
+ }
} finally {
- pool.returnCompiledXQuery(GET_BASE_REV_FOR_KEY_SOURCE, compiled);
+ xqueryPool.returnCompiledXQuery(GET_BASE_REV_FOR_KEY_SOURCE, compiled);
}
}
}
diff --git a/src/main/java/org/exist/versioning/VersioningTrigger.java b/src/main/java/org/exist/versioning/VersioningTrigger.java
index b9e34cd..10e2a9b 100644
--- a/src/main/java/org/exist/versioning/VersioningTrigger.java
+++ b/src/main/java/org/exist/versioning/VersioningTrigger.java
@@ -1,34 +1,31 @@
-/*
- * eXist Open Source Native XML Database
- * Copyright (C) 2001-2010 The eXist Project
- * http://exist-db.org
+/**
+ * Versioning Module for eXist-db XQuery
+ * Copyright (C) 2008 eXist-db
+ * http://exist-db.org
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * $Id$
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.exist.versioning;
import java.io.DataInputStream;
import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -101,28 +98,32 @@ public class VersioningTrigger extends FilteringTrigger {
private boolean checkForConflicts = false;
@Override
- public void configure(DBBroker broker, Collection parent, Map> parameters)
+ public void configure(final DBBroker broker, final Collection parent, final Map> parameters)
throws TriggerException {
super.configure(broker, parent, parameters);
if (parameters != null) {
- String allowOverwrite = (String) parameters.get(PARAM_OVERWRITE).get(0);
- if (allowOverwrite != null)
- checkForConflicts = allowOverwrite.equals("false") || allowOverwrite.equals("no");
+ final String allowOverwrite = (String) parameters.get(PARAM_OVERWRITE).get(0);
+ if (allowOverwrite != null) {
+ checkForConflicts = allowOverwrite.equals("false") || allowOverwrite.equals("no");
+ }
}
-
- LOG.debug("checkForConflicts: " + checkForConflicts);
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("checkForConflicts: " + checkForConflicts);
+ }
}
//XXX: is it safe to delete?
@Deprecated
- public void finish(int event, DBBroker broker, Txn transaction, XmldbURI documentPath, DocumentImpl document) {
-
- if (documentPath == null || documentPath.startsWith(VERSIONS_COLLECTION))
- return;
+ public void finish(final int event, final DBBroker broker, final Txn transaction, XmldbURI documentPath,
+ final DocumentImpl document) {
- Subject activeSubject = broker.getSubject();
+ if (documentPath == null || documentPath.startsWith(VERSIONS_COLLECTION)) {
+ return;
+ }
+ final Subject activeSubject = broker.getSubject();
try {
broker.setSubject(broker.getBrokerPool().getSecurityManager().getSystemSubject());
@@ -132,13 +133,10 @@ public void finish(int event, DBBroker broker, Txn transaction, XmldbURI documen
vDoc.getUpdateLock().acquire(Lock.WRITE_LOCK);
vCollection.addDocument(transaction, broker, vDoc);
broker.storeXMLResource(transaction, vDoc);
- } catch (LockException e) {
+ } catch (LockException | PermissionDeniedException e) {
LOG.warn("Versioning trigger could not store base document: " + vDoc.getFileURI() +
e.getMessage(), e);
- } catch (PermissionDeniedException e) {
- LOG.warn("Versioning trigger could not store base document: " + vDoc.getFileURI() +
- e.getMessage(), e);
- } finally {
+ } finally {
vDoc.getUpdateLock().release(Lock.WRITE_LOCK);
}
}
@@ -148,92 +146,93 @@ public void finish(int event, DBBroker broker, Txn transaction, XmldbURI documen
try {
vCollection = getVersionsCollection(broker, transaction, documentPath.removeLastSegment());
- String existingURI = document.getFileURI().toString();
- XmldbURI deletedURI = XmldbURI.create(existingURI + DELETED_SUFFIX);
+ final String existingURI = document.getFileURI().toString();
+ final XmldbURI deletedURI = XmldbURI.create(existingURI + DELETED_SUFFIX);
lastRev = vCollection.getDocument(broker, deletedURI);
if (lastRev == null) {
lastRev = vCollection.getDocument(broker, XmldbURI.create(existingURI + BASE_SUFFIX));
removeLast = false;
- } else
- removeLast = true;
- } catch (IOException e) {
+ } else {
+ removeLast = true;
+ }
+ } catch (IOException | TriggerException e) {
LOG.warn("Caught exception in VersioningTrigger: " + e.getMessage(), e);
} catch (PermissionDeniedException e) {
LOG.warn("Permission denied in VersioningTrigger: " + e.getMessage(), e);
- } catch (TriggerException e) {
- LOG.warn("Caught exception in VersioningTrigger: " + e.getMessage(), e);
}
- }
+ }
if (lastRev != null || event == REMOVE_DOCUMENT_EVENT) {
try {
- long revision = newRevision(broker.getBrokerPool());
- if (documentPath.isCollectionPathAbsolute())
- documentPath = documentPath.lastSegment();
- XmldbURI diffUri = XmldbURI.createInternal(documentPath.toString() + '.' + revision);
+ final long revision = newRevision(broker.getBrokerPool());
+ if (documentPath.isCollectionPathAbsolute()) {
+ documentPath = documentPath.lastSegment();
+ }
+ final XmldbURI diffUri = XmldbURI.createInternal(documentPath.toString() + '.' + revision);
vCollection.setTriggersEnabled(false);
- StringWriter writer = new StringWriter();
- SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject(
- SAXSerializer.class);
- Properties outputProperties = new Properties();
- outputProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
- outputProperties.setProperty(OutputKeys.INDENT, "no");
- sax.setOutput(writer, outputProperties);
-
- sax.startDocument();
- sax.startElement(ELEMENT_VERSION, null);
- writeProperties(sax, getVersionProperties(revision, documentPath, activeSubject));
-
- if(event == REMOVE_DOCUMENT_EVENT) {
- sax.startElement(ELEMENT_REMOVED, null);
- sax.endElement(ELEMENT_REMOVED);
- } else {
-
- //Diff
- if(document instanceof BinaryDocument) {
- //create a copy of the last Binary revision
- XmldbURI binUri = XmldbURI.create(diffUri.toString() + BINARY_SUFFIX);
- broker.copyResource(transaction, document, vCollection, binUri);
-
- //Create metadata about the last Binary Version
- sax.startElement(ELEMENT_REPLACED_BINARY, null);
- sax.attribute(ATTRIBUTE_REF, binUri.toString());
- sax.endElement(ELEMENT_REPLACED_BINARY);
- } else if(lastRev instanceof BinaryDocument) {
- //create a copy of the last XML revision
- XmldbURI xmlUri = XmldbURI.create(diffUri.toString() + XML_SUFFIX);
- broker.copyResource(transaction, document, vCollection, xmlUri);
-
- //Create metadata about the last Binary Version
- sax.startElement(ELEMENT_REPLACED_XML, null);
- sax.attribute(ATTRIBUTE_REF, xmlUri.toString());
- sax.endElement(ELEMENT_REPLACED_BINARY);
- } else {
- //Diff the XML versions
- Diff diff = new StandardDiff(broker);
- diff.diff(lastRev, document);
- diff.diff2XML(sax);
- }
-
- sax.endElement(ELEMENT_VERSION);
-
- sax.endDocument();
- String editscript = writer.toString();
-
- if (removeLast) {
- if(lastRev instanceof BinaryDocument) {
- vCollection.removeBinaryResource(transaction, broker, lastRev.getFileURI());
- } else {
- vCollection.removeXMLResource(transaction, broker, lastRev.getFileURI());
- }
- }
-
- IndexInfo info = vCollection.validateXMLResource(transaction, broker, diffUri, editscript);
- vCollection.store(transaction, broker, info, editscript, false);
- }
- } catch (Exception e) {
+ try(StringWriter writer = new StringWriter()) {
+ final SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject(
+ SAXSerializer.class);
+ final Properties outputProperties = new Properties();
+ outputProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+ outputProperties.setProperty(OutputKeys.INDENT, "no");
+ sax.setOutput(writer, outputProperties);
+
+ sax.startDocument();
+ sax.startElement(ELEMENT_VERSION, null);
+ writeProperties(sax, getVersionProperties(revision, documentPath, activeSubject));
+
+ if (event == REMOVE_DOCUMENT_EVENT) {
+ sax.startElement(ELEMENT_REMOVED, null);
+ sax.endElement(ELEMENT_REMOVED);
+ } else {
+
+ //Diff
+ if (document instanceof BinaryDocument) {
+ //create a copy of the last Binary revision
+ final XmldbURI binUri = XmldbURI.create(diffUri.toString() + BINARY_SUFFIX);
+ broker.copyResource(transaction, document, vCollection, binUri);
+
+ //Create metadata about the last Binary Version
+ sax.startElement(ELEMENT_REPLACED_BINARY, null);
+ sax.attribute(ATTRIBUTE_REF, binUri.toString());
+ sax.endElement(ELEMENT_REPLACED_BINARY);
+ } else if (lastRev instanceof BinaryDocument) {
+ //create a copy of the last XML revision
+ final XmldbURI xmlUri = XmldbURI.create(diffUri.toString() + XML_SUFFIX);
+ broker.copyResource(transaction, document, vCollection, xmlUri);
+
+ //Create metadata about the last Binary Version
+ sax.startElement(ELEMENT_REPLACED_XML, null);
+ sax.attribute(ATTRIBUTE_REF, xmlUri.toString());
+ sax.endElement(ELEMENT_REPLACED_BINARY);
+ } else {
+ //Diff the XML versions
+ final Diff diff = new StandardDiff(broker);
+ diff.diff(lastRev, document);
+ diff.diff2XML(sax);
+ }
+
+ sax.endElement(ELEMENT_VERSION);
+
+ sax.endDocument();
+ final String editscript = writer.toString();
+
+ if (removeLast) {
+ if (lastRev instanceof BinaryDocument) {
+ vCollection.removeBinaryResource(transaction, broker, lastRev.getFileURI());
+ } else {
+ vCollection.removeXMLResource(transaction, broker, lastRev.getFileURI());
+ }
+ }
+
+ final IndexInfo info = vCollection.validateXMLResource(transaction, broker, diffUri, editscript);
+ vCollection.store(transaction, broker, info, editscript, false);
+ }
+ }
+ } catch (final Exception e) {
LOG.warn("Caught exception in VersioningTrigger: " + e.getMessage(), e);
} finally {
vCollection.setTriggersEnabled(true);
@@ -244,30 +243,31 @@ public void finish(int event, DBBroker broker, Txn transaction, XmldbURI documen
}
}
- private void before(DBBroker broker, Txn transaction, DocumentImpl document, boolean remove)
- throws TriggerException {
+ private void before(final DBBroker broker, final Txn transaction, final DocumentImpl document, final boolean remove)
+ throws TriggerException {
this.documentPath = document.getURI();
- if (documentPath.startsWith(VERSIONS_COLLECTION))
- return;
+ if (documentPath.startsWith(VERSIONS_COLLECTION)) {
+ return;
+ }
this.broker = broker;
- Subject activeSubject = broker.getSubject();
+ final Subject activeSubject = broker.getSubject();
try {
broker.setSubject(broker.getBrokerPool().getSecurityManager().getSystemSubject());
- Collection collection = document.getCollection();
- if (collection.getURI().startsWith(VERSIONS_COLLECTION))
- return;
+ final Collection collection = document.getCollection();
+ if (collection.getURI().startsWith(VERSIONS_COLLECTION)) {
+ return;
+ }
vCollection = getVersionsCollection(broker, transaction, documentPath.removeLastSegment());
- String existingURI = document.getFileURI().toString();
- XmldbURI baseURI = XmldbURI.create(existingURI + BASE_SUFFIX);
- DocumentImpl baseRev = vCollection.getDocument(broker, baseURI);
-
- String vFileName;
+ final String existingURI = document.getFileURI().toString();
+ final XmldbURI baseURI = XmldbURI.create(existingURI + BASE_SUFFIX);
+ final DocumentImpl baseRev = vCollection.getDocument(broker, baseURI);
+ final String vFileName;
if (baseRev == null) {
vFileName = baseURI.toString();
removeLast = false;
@@ -283,12 +283,12 @@ private void before(DBBroker broker, Txn transaction, DocumentImpl document, boo
// setReferenced(true) will tell the broker that the document
// data is referenced from another document and should not be
- // deleted when the orignal document is removed.
+ // deleted when the original document is removed.
document.getMetadata().setReferenced(true);
if(document instanceof BinaryDocument) {
- XmldbURI binUri = XmldbURI.createInternal(vFileName);
+ final XmldbURI binUri = XmldbURI.createInternal(vFileName);
broker.copyResource(transaction, document, vCollection, binUri);
vDoc = vCollection.getDocument(broker, binUri);
} else {
@@ -301,21 +301,22 @@ private void before(DBBroker broker, Txn transaction, DocumentImpl document, boo
lastRev = vDoc;
}
- } catch (PermissionDeniedException e) {
+ } catch (final PermissionDeniedException e) {
throw new TriggerException("Permission denied in VersioningTrigger: " + e.getMessage(), e);
- } catch (Exception e) {
+ } catch (final Exception e) {
LOG.warn("Caught exception in VersioningTrigger: " + e.getMessage(), e);
} finally {
broker.setSubject(activeSubject);
}
}
- private void after(DBBroker broker, Txn transaction, DocumentImpl document, boolean remove) {
- if (documentPath == null || documentPath.startsWith(VERSIONS_COLLECTION))
- return;
-
- Subject activeSubject = broker.getSubject();
+ private void after(final DBBroker broker, final Txn transaction, final DocumentImpl document,
+ final boolean remove) {
+ if (documentPath == null || documentPath.startsWith(VERSIONS_COLLECTION)) {
+ return;
+ }
+ final Subject activeSubject = broker.getSubject();
try {
broker.setSubject(broker.getBrokerPool().getSecurityManager().getSystemSubject());
@@ -323,94 +324,94 @@ private void after(DBBroker broker, Txn transaction, DocumentImpl document, bool
try {
vCollection = getVersionsCollection(broker, transaction, documentPath.removeLastSegment());
- String existingURI = document.getFileURI().toString();
- XmldbURI deletedURI = XmldbURI.create(existingURI + DELETED_SUFFIX);
+ final String existingURI = document.getFileURI().toString();
+ final XmldbURI deletedURI = XmldbURI.create(existingURI + DELETED_SUFFIX);
lastRev = vCollection.getDocument(broker, deletedURI);
if (lastRev == null) {
lastRev = vCollection.getDocument(broker, XmldbURI.create(existingURI + BASE_SUFFIX));
removeLast = false;
- } else
- removeLast = true;
- } catch (IOException e) {
+ } else {
+ removeLast = true;
+ }
+ } catch (final IOException | TriggerException e) {
LOG.warn("Caught exception in VersioningTrigger: " + e.getMessage(), e);
- } catch (PermissionDeniedException e) {
+ } catch (final PermissionDeniedException e) {
LOG.warn("Permission denied in VersioningTrigger: " + e.getMessage(), e);
- } catch (TriggerException e) {
- LOG.warn("Caught exception in VersioningTrigger: " + e.getMessage(), e);
}
- }
+ }
if (lastRev != null || remove) {
try {
- long revision = newRevision(broker.getBrokerPool());
+ final long revision = newRevision(broker.getBrokerPool());
if (documentPath.isCollectionPathAbsolute()) {
documentPath = documentPath.lastSegment();
}
- XmldbURI diffUri = XmldbURI.createInternal(documentPath.toString() + '.' + revision);
+ final XmldbURI diffUri = XmldbURI.createInternal(documentPath.toString() + '.' + revision);
vCollection.setTriggersEnabled(false);
- StringWriter writer = new StringWriter();
- SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject(
- SAXSerializer.class);
- Properties outputProperties = new Properties();
- outputProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
- outputProperties.setProperty(OutputKeys.INDENT, "no");
- sax.setOutput(writer, outputProperties);
-
- sax.startDocument();
- sax.startElement(ELEMENT_VERSION, null);
- writeProperties(sax, getVersionProperties(revision, documentPath, activeSubject));
-
- if (remove) {
- sax.startElement(ELEMENT_REMOVED, null);
- sax.endElement(ELEMENT_REMOVED);
- } else {
-
- //Diff
- if(document instanceof BinaryDocument) {
- //create a copy of the last Binary revision
- XmldbURI binUri = XmldbURI.create(diffUri.toString() + BINARY_SUFFIX);
- broker.copyResource(transaction, document, vCollection, binUri);
-
- //Create metadata about the last Binary Version
- sax.startElement(ELEMENT_REPLACED_BINARY, null);
- sax.attribute(ATTRIBUTE_REF, binUri.toString());
- sax.endElement(ELEMENT_REPLACED_BINARY);
- } else if(lastRev instanceof BinaryDocument) {
- //create a copy of the last XML revision
- XmldbURI xmlUri = XmldbURI.create(diffUri.toString() + XML_SUFFIX);
- broker.copyResource(transaction, document, vCollection, xmlUri);
-
- //Create metadata about the last Binary Version
- sax.startElement(ELEMENT_REPLACED_XML, null);
- sax.attribute(ATTRIBUTE_REF, xmlUri.toString());
- sax.endElement(ELEMENT_REPLACED_XML);
- } else {
- //Diff the XML versions
- Diff diff = new StandardDiff(broker);
- diff.diff(lastRev, document);
- diff.diff2XML(sax);
- }
-
- sax.endElement(ELEMENT_VERSION);
-
- sax.endDocument();
- String editscript = writer.toString();
-
- if (removeLast) {
- if(lastRev instanceof BinaryDocument) {
- vCollection.removeBinaryResource(transaction, broker, lastRev.getFileURI());
- } else {
- vCollection.removeXMLResource(transaction, broker, lastRev.getFileURI());
- }
- }
-
- IndexInfo info = vCollection.validateXMLResource(transaction, broker, diffUri, editscript);
- vCollection.store(transaction, broker, info, editscript, false);
- }
- } catch (Exception e) {
+ try(final StringWriter writer = new StringWriter()) {
+ final SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject(
+ SAXSerializer.class);
+ final Properties outputProperties = new Properties();
+ outputProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+ outputProperties.setProperty(OutputKeys.INDENT, "no");
+ sax.setOutput(writer, outputProperties);
+
+ sax.startDocument();
+ sax.startElement(ELEMENT_VERSION, null);
+ writeProperties(sax, getVersionProperties(revision, documentPath, activeSubject));
+
+ if (remove) {
+ sax.startElement(ELEMENT_REMOVED, null);
+ sax.endElement(ELEMENT_REMOVED);
+ } else {
+
+ //Diff
+ if (document instanceof BinaryDocument) {
+ //create a copy of the last Binary revision
+ final XmldbURI binUri = XmldbURI.create(diffUri.toString() + BINARY_SUFFIX);
+ broker.copyResource(transaction, document, vCollection, binUri);
+
+ //Create metadata about the last Binary Version
+ sax.startElement(ELEMENT_REPLACED_BINARY, null);
+ sax.attribute(ATTRIBUTE_REF, binUri.toString());
+ sax.endElement(ELEMENT_REPLACED_BINARY);
+ } else if (lastRev instanceof BinaryDocument) {
+ //create a copy of the last XML revision
+ final XmldbURI xmlUri = XmldbURI.create(diffUri.toString() + XML_SUFFIX);
+ broker.copyResource(transaction, document, vCollection, xmlUri);
+
+ //Create metadata about the last Binary Version
+ sax.startElement(ELEMENT_REPLACED_XML, null);
+ sax.attribute(ATTRIBUTE_REF, xmlUri.toString());
+ sax.endElement(ELEMENT_REPLACED_XML);
+ } else {
+ //Diff the XML versions
+ final Diff diff = new StandardDiff(broker);
+ diff.diff(lastRev, document);
+ diff.diff2XML(sax);
+ }
+
+ sax.endElement(ELEMENT_VERSION);
+
+ sax.endDocument();
+ final String editscript = writer.toString();
+
+ if (removeLast) {
+ if (lastRev instanceof BinaryDocument) {
+ vCollection.removeBinaryResource(transaction, broker, lastRev.getFileURI());
+ } else {
+ vCollection.removeXMLResource(transaction, broker, lastRev.getFileURI());
+ }
+ }
+
+ final IndexInfo info = vCollection.validateXMLResource(transaction, broker, diffUri, editscript);
+ vCollection.store(transaction, broker, info, editscript, false);
+ }
+ }
+ } catch (final Exception e) {
LOG.warn("Caught exception in VersioningTrigger: " + e.getMessage(), e);
} finally {
vCollection.setTriggersEnabled(true);
@@ -421,10 +422,9 @@ private void after(DBBroker broker, Txn transaction, DocumentImpl document, bool
}
}
- private Properties getVersionProperties(long revision, XmldbURI documentPath, Account commitAccount)
- throws XPathException {
- Properties properties = new Properties();
-
+ private Properties getVersionProperties(final long revision, final XmldbURI documentPath,
+ final Account commitAccount) throws XPathException {
+ final Properties properties = new Properties();
properties.setProperty("document", documentPath.toString());
properties.setProperty("revision", Long.toString(revision));
properties.setProperty("date", new DateTimeValue(new Date()).getStringValue());
@@ -432,32 +432,29 @@ private Properties getVersionProperties(long revision, XmldbURI documentPath, Ac
if (documentKey != null) {
properties.setProperty("key", documentKey);
}
-
return properties;
}
- public static void writeProperties(Receiver receiver, Properties properties)
- throws SAXException {
+ public static void writeProperties(final Receiver receiver, final Properties properties) throws SAXException {
receiver.startElement(PROPERTIES_ELEMENT, null);
-
- for (Entry