From 2ee62d4a36fd178dd35d77911a50963fc3433751 Mon Sep 17 00:00:00 2001
From: gregor herrmann
Date: Sun, 16 May 2010 15:39:36 +0000
Subject: [PATCH 1/1] [svn-upgrade] Integrating new upstream version,
jabref-plugin-oo (0.7.4+ds)
---
CHANGELOG | 131 ++++
OOPlugin.html | 269 +++++++
build.xml | 66 ++
example_style_file.jstyle | 53 ++
net/sf/jabref/oo/OOBibBase.java | 1181 ++++++++++++++++++++++++++++++
net/sf/jabref/oo/OOBibStyle.java | 840 +++++++++++++++++++++
net/sf/jabref/oo/OOUtil.java | 285 +++++++
plugin.xml | 32 +
8 files changed, 2857 insertions(+)
create mode 100755 CHANGELOG
create mode 100755 OOPlugin.html
create mode 100755 build.xml
create mode 100755 example_style_file.jstyle
create mode 100755 net/sf/jabref/oo/OOBibBase.java
create mode 100755 net/sf/jabref/oo/OOBibStyle.java
create mode 100755 net/sf/jabref/oo/OOUtil.java
create mode 100755 plugin.xml
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100755
index 0000000..aac2787
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,131 @@
+
+0.7.4:
+ - Added optional citation property "AuthorLastSeparatorInText" which, if present,
+ overrides "AuthorLastSeparator" for in-text author-year citations.
+ - Added citation property "MultiCiteChronological". For author-year citations, this
+ property can be set to false instead of true to get alphabetical sorting of entries
+ within the same citation.
+ - Fixed bug: for normal characters, CharEscapementHeight was set to 0 instead of 100.
+0.7.3:
+ - Changed order of formatting operations in order to fix the problem that formatting
+ of the first part of a reference list entry gets lost.
+ - Added tag to indicate small caps in reference list.
+ - Modified parsing of style file so boolean properties can be parsed even if extra
+ white space is included, e.g. "true ".
+ - Fixed bug in "MaxAuthorsFirst" handling: if two citations can be grouped, but one of
+ them has appeared earlier, this should prevent grouping if the difference between
+ "MaxAuthorsFirst" and "MaxAuthors" has bearing on the citations in question.
+0.7.2:
+ - Added option "MaxAuthorsFirst" to control how many authors can be shown the first
+ time a citation appears before "et al" is used. "MaxAuthors" controls the following
+ appearances.
+0.7.1:
+ - The preformatter is now preferentially run after instead of before formatters called
+ from the layout specification. This solves the problems of e.g. organization author
+ names wrapped in braces (e.g. {World Bank}), where the braces have no effect as long
+ as the preprocessor is run first. This feature depends on a change introduced in
+ JabRef 2.6, and if older versions are used, the preprocessor will be run first as before.
+ - Fixed problem with repeated citations in numbered citations.
+ - Fixed problem with paragraph format not affecting the entire bibliography entries.
+0.7:
+ - All BibTeX fields are now run through a formatter that translates LaTeX character
+ sequences and \textit{} and \textbf{} commands before insertion into OO.
+0.6:
+ - Improved behaviour when the document references BibTeX keys not found in the
+ BibTeX database. Citation is now marked as undefined, and the remaining
+ bibliography gets created as normal.
+ - Added settings popup menu, and option for whether to automatically sync
+ bibliography when inserting new citations.
+0.5:
+ - Fixed bug in Merge citations feature - citations would be lost when combined
+ citations have same year.
+ - Fixed problem with connection on Mac.
+0.4:
+ - Added optional citation properties BracketBeforeInList and BracketAfterInList that override
+ BracketBefore and BracketAfter for the numbering of the reference list.
+ - Added support for and tags in reference layouts, for superscript and
+ subscript, respectively.
+ - Added "SubscriptCitations" property that gives subscripted citation markers.
+0.3:
+ - Some changes to the interface.
+ - Added property MinimumGroupingCount the determines how many consecutive numbers are
+ required for grouping in a citation marker (e.g. [1-3] or[2;5-8]).
+ - Fixed bug in properties parsing - empty strings are no longer ignored and replaced by
+ default values.
+0.2.1:
+ - Fixed bug in sorting of reference list.
+0.2:
+ - Citation markers are now set to language [None] to prevent spell checker from underlining
+ names.
+ - Fixed sorting of citations in table cells and footnotes.
+ - Added option for superscripted citation markers.
+0.1.9:
+ - Added support for citations in table cells and footnotes. Currently sorting by position
+ fails if there are such citations.
+ - Added properties for setting bold/italic formatting on citation markers.
+0.1.2:
+ - Added button for inserting invisible citations (without text in the citation marker),
+ which can be used to insert an entry into the reference list without citing it.
+ - When citations are merged, they are now sorted chronologically (oldest first).
+0.1.1:
+ - It is now possible to connect again after OpenOffice has been shut down and started
+ again.
+ - Added property ReferenceHeaderParagraphFormat in style file to control the paragraph
+ format of the bibliography header.
+ - Added error message for the case that OpenOffice has been shut down after connection.
+ - Fixed bug in handling of von particles in citation markers.
+0.1:
+ - Added functionality to choose which Writer document to connect to - selector is shown
+ both when connecting, and when using the new "Select Writer document" button.
+ - Improved appearance of the OpenOffice panel.
+ - A space is now inserted after newly inserted citations, in order to alleviate problem
+ with new text becoming part of the citation marker.
+ - Some improvements to cursor placement after inserting citation.
+
+0.0.9 (2008-10-19):
+ - Streamlined connection process by adding button that attempts to find the necessary
+ paths automatically.
+ - Made adaptations to connect to OpenOffice.org 3.x, due to changed library locations.
+ - Fixed bug: plugin tries to connect even if user cancels the connect dialog.
+
+0.0.8 (2008-09-03):
+ - No changes, but packaged with JabRef 2.4.
+
+0.0.7 (2008-02-20):
+ - Added interface for selecting style. You can set up a list of single files and directories
+ that will be scanned to build a list of styles (directories can be scanned recursively).
+ - Fixed problem with layouts starting with a tag such as "" would disable bold/italics
+ formatting for the entire entry.
+ - Added property "ReferenceParagraphFormat" that determines what paragraph format is used
+ for the reference list (default value is "Default").
+
+0.0.6 (2008-02-12):
+ - "Test" button in this version autocombines citations that are separated by spaces only.
+ - Number citation markers now give citations in ascending order (instead of chronologically,
+ as with author-year citations), and group consecutive entries (e.g. [1-3; 6]).
+
+0.0.5 (2008-02-06):
+ - Fixed bug in author-year citations with names like "Van der Waal". Von-particles are
+ now included in the citations.
+
+0.0.4 (2008-01-09):
+ - When synchronizing bibliography, the style file is now automatically reloaded if it has
+ been modified since the last read.
+ - Cleaned out some obsolete code.
+
+0.0.3 (2007-12-22):
+ - Reworked the entire plugin to bypass OpenOffice.org's built-in bibliography functions.
+ This makes it possible to solve the open issues in previous versions, and add support
+ for multiple citations, and uniquefier letters and formatting within fields in the
+ bibliography.
+ - The bibliography is now formatted using standard JabRef layout, including formatters.
+ - A new formatter FormatChars is added, which translates LaTeX commands for bold and italic
+ into the and markup used by this plugin. This lets the formatting carry into
+ the bibliography in OO where appropriate.
+
+0.0.2 (2007-12-04):
+ - Fixed bug that prevented the "editor" field from being exported.
+ - Missing fields are now populated from crossreferenced entry where available.
+
+0.0.1 (2007-12-01):
+ - First version.
diff --git a/OOPlugin.html b/OOPlugin.html
new file mode 100755
index 0000000..dabb3ea
--- /dev/null
+++ b/OOPlugin.html
@@ -0,0 +1,269 @@
+OpenOffice plugin for JabRef
+
+Introduction
+
+ JabRef is an open source BibTeX bibliography
+ manager.
+
This plugin offers an interface for inserting citations and formatting a Bibliography in an
+ OpenOffice writer document from JabRef.
+
+
+ How to use the plugin
+
+ The plugin can be used with JabRef 2.4 or newer. If your JabRef version doesn't
+ have a plugin manager (versions 2.4.x), you need to put the plugin jar file
+ in a directory named plugins
below the directory where the JabRef
+ jar file is installed (typically under C:\Program files\Jabref 2.x
+ if you are running under Windows). The plugin should be loaded next time you
+ start JabRef, and an item named OpenOffice.org panel should appear in
+ JabRef's Plugins menu.
+
The plugin should work with OpenOffice versions 2.4.x and 3.x, provided it
+ is installed with Java support (this is usually the case on Windows, while in
+ some Linux distributions you need to install a separate package named
+ openoffice.org-java-common
or something similar).
+
+ Updates:
+ 2010-05-11: Version 0.7.4: Added option to sort alphabetically for citations with multiple entries.
+ 2010-03-04: Version 0.7.3: Added support for <smallcaps> tag to indicate small caps in reference list. Several bug fixes.
+ 2010-02-02: Version 0.7.2: Added MaxAuthorsFirst property to override MaxAuthors the first time each citation appears.
+ 2009-10-07: Version 0.7.1: Several important bug fixes.
+ 2009-08-26: Version 0.7: BibTeX fields are now preprocessed to handle LaTeX \textit and \textbf commands and
+ character sequences. NOTE: it is no longer necessary to run FormatChars on fields.
+ 2009-08-23: Version 0.6: Improved handling of undefined BibTeX keys. Added option to not sync automatically when adding citation.
+ 2009-08-05: Version 0.5: Fixed connection problem on Mac. Fixed bug in merge function.
+ 2009-06-03: Version 0.4: Added support for superscript/subscript tags in reference list, subscripted citations
+ and different brackets for numbering in the reference list.
+ 2009-05-17: Version 0.3: Added MinimumGroupingCount property. Some GUI changes.
+ 2009-04-02: Version 0.2.1: Fixed bug in sorting of reference list.
+ 2009-03-01: Version 0.2: Better sorting of citations in captions, tables and footnotes.
+ 2009-02-25: Version 0.1.9: Added support for bold/italic citation markers, and for citations in table cells and footnotes.
+ 2008-12-21: Version 0.1.2: Added invisible citations. Merged citations are now sorted.
+ 2008-11-19: Version 0.1.1: Improved handling of OpenOffice shutdown and reconnect.
+ 2008-10-25: Version 0.1: User interface improvements. Can now select which Writer document to work with.
+ 2008-10-19: Version 0.0.9: Enabled connection to OpenOffice.org 3. Streamlined connection process.
+ 2008-09-03: Version 0.0.8: No major changes, but packaged with JabRef 2.4.
+ 2008-02-20: Version 0.0.7: New interface for style selection. Styles can now specify paragraph format.
+ 2008-02-13: Version 0.0.6: Sorting and grouping of number citation markers.
+ 2008-02-06: Version 0.0.5: Modified style file format. Fixed bug in handling names with elements like "van der".
+ 2008-01-09: Version 0.0.4: Style file is now automatically reloaded if modified.
+ 2007-12-17: Version 0.0.3: From this version, we bypass OO's built-in bibliographic system.
+ 2007-12-04: Version 0.0.2
+ 2007-12-01: Version 0.0.1
+
+ Downloads:
+ The plugin.
+ Plugin source code. The source code tree includes four
+ OpenOffice.org jars and JabRef 2.5. The plugin is built using
+ an included Ant build file.
+ Example style file
+
+ The plugin is distributed under the terms of the GNU
+ General Public License,
+ version 2 or later.
+
+ Using the OpenOffice interface
+
+ To communicate with OpenOffice, the OO plugin must first connect to a running OpenOffice
+ instance. You need to start OpenOffice and enter your document before connecting from
+ JabRef. The plugin needs to know the location of your OpenOffice executable (soffice.exe on
+ Windows, and soffice on other platforms), and the directory where several OpenOffice
+ jar files reside. If you connect by clicking the Connect button, the plugin will try to
+ automatically determine these locations. If this does not work, you need to connect using the
+ Manual connect button, which will open a window asking you for the needed locations.
+
+ After the connection has been established, you can insert citations by selecting one or more
+ entries in JabRef and using the Push to OpenOffice button in the dropdown menu of JabRef's
+ toolbar, or by using the appropriate button in the OpenOffice plugin panel in the side pane. This
+ will insert citations for the selected entries at the current cursor position in the OpenOffice
+ document, and update the bibliography to contain the full reference.
+
+ Note: JabRef does not use OpenOffice's built-in bibliography system, because of the
+ limitations of that system. A document containing citations inserted from JabRef will
+ not generally be compatible with other reference managers such as Bibus and Zotero.
+
+ Two different types of citations
+ can be inserted - either a citation in parenthesis, "(Author 2007)", or an in-text citation,
+ "Author (2007)". This distinction is only meaningful if author-year citations are used instead of
+ numbered citations, but the distinction will be preserved if you switch between the two styles.
+
+ If you modify entries in JabRef after inserting their citations into OpenOffice, you will
+ need to synchronize the bibliography. The Sync OO bibliography button will update all
+ entries of the bibliography, provided their BibTeX keys have not been altered (JabRef encodes the
+ BibTeX key into the reference name for each citation to keep track of which BibTeX key
+ the original JabRef entry has).
+
+ The style file
+
+ You need to select a style file before connecting to OpenOffice - an external file which is selected
+ using a standard file dialog. The style file defines the
+ format of citations and the format of the bibliography. You can use standard JabRef export
+ formatters to process entry fields before they are sent to OpenOffice.
+ Through the style file, the intention is to give as much flexibility in citation styles as possible.
+
+ Here is an example style file:
+
+NAME
+Example style file for JabRef-oo plugin.
+
+JOURNALS
+Journal name 1
+Journal name 2
+
+PROPERTIES
+Title=References
+IsSortByPosition=false
+IsNumberEntries=false
+ReferenceParagraphFormat=Default
+ReferenceHeaderParagraphFormat=Heading 1
+
+CITATION
+AuthorField=author/editor
+YearField=year
+MaxAuthors=3
+MaxAuthorsFirst=6
+AuthorSeparator=,
+AuthorLastSeparator= &
+EtAlString= et al.
+YearSeparator=
+InTextYearSeparator=
+BracketBefore=[
+BracketAfter=]
+BracketBeforeInList=[
+BracketAfterInList=]
+CitationSeparator=;
+UniquefierSeparator=,
+GroupedNumbersSeparator=-
+MinimumGroupingCount=3
+FormatCitations=false
+ItalicCitations=false
+BoldCitations=false
+SuperscriptCitations=false
+SubscriptCitations=false
+
+
+LAYOUT
+article=\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (<b>\year\uniq). <i>\title, \journal \volume\begin{pages} : \format[FormatPagesForHTML]{\pages}\end{pages}.
+
+book=\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author}\begin{editor}\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\editor} (Ed.)\end{editor}, <b>\year\uniq. <i>\title. \publisher, \address.
+
+incollection=\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (<b>\year\uniq). <i>\title. In: \format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\editor} (Ed.), <i>\booktitle, \publisher.
+
+inbook=\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (<b>\year\uniq). <i>\chapter. In: \format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\editor} (Ed.), <i>\title, \publisher.
+
+phdthesis=\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (<b>\year\uniq). <i>\title, \school.
+
+default=\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (<b>\year\uniq). <i>\title, \journal \volume\begin{pages} : \format[FormatPagesForHTML]{\pages}\end{pages}.
+
+
+
+(Note that the layout for each entry type must be constrained to a single line in the style file - above, the lines are broken up to improve readability.)
+
+
+ The PROPERTIES section describes global properties for the bibliography:
+
Title
: determines the header text for the bibliography.
+ IsSortByPosition
: determines how the bibliography is sorted. If true, the entries
+ will be sorted according to the order in which they are cited. If false, the entries will be
+ sorted alphabetically by authors.
+ IsNumberEntries
: determines the type of citations to use. If true, number
+ citations will be used. The citation numbers will be included in the bibliography as well.
+ If false, author-year citations will be used.
+
+
+ The CITATION section describes the format of the citation markers inserted into the text.
+ If numbered entries are used, only the BracketBefore
and BracketAfter
properties
+ are relevant - they define which characters the citation number is wrapped in. The citation is composed
+ as follows:
+ [BracketBefore][Number][BracketAfter]
+ where [Number] is the number of the citation, determined according to the ordering of the bibliography and/or
+ the position of the citation in the text. If a citation refers to several entries, these will be separated
+ by the string given in the property CitationSeparator
(for instance, if CitationSeparator
=;,
+ the citation could look like [2;4;6]
). If two or more of the entries have a series of consecutive
+ numbers, the numbers can be grouped (for instance [2-4]
for 2, 3 and 4 or [2;5-7]
for
+ 2, 5, 6 and 7). The property GroupedNumbersSeparator
(default -
) determines which string separates the first and last
+ of the grouped numbers. The integer property MinimumGroupingCount
(default 3) determines what number of
+ consecutive numbers are required before entries are grouped. If MinimumGroupingCount
=3, the numbers
+ 2 and 3 will not be grouped, while 2, 3, 4 will be. If MinimumGroupingCount
=0, no grouping will be
+ done regardless of the number of consecutive numbers.
+
+ If numbered entries are not used, author-year citations will be created based on the citation properties.
+ A parenthesis citation is composed as follows:
+ [BracketBefore][Author][YearSeparator][Year][BracketAfter]
+ where [Author] is the result of looking up the field or fields given in the AuthorField
property,
+ and formatting a list of authors. The list can contain up to MaxAuthors
names - if more are present,
+ the list will be composed as the first author plus the text specified in the property EtAlString
.
+ If several, slash-separated, fields are given in the AuthorField
property, they will be looked up
+ successively if the first field is empty for the given BibTeX entry. In the example above, the "author" field will
+ be used, but if empty, the "editor" field will be used as a backup.
+
The names in the author list will be separated by the text given by the AuthorSeparator
+ property, except for the last two names, which will be separated by the text given by AuthorLastSeparator
.
+ If the property AuthorLastSeparatorInText
is given, it overrides the former for citations of the in-text
+ type. This makes it possible to get citations like (Olsen & Jensen, 2008)
and Olsen and Jensen (2008)
+ for the same style.
+
+ [Year] is the result of looking up the field or fields given in the [YearField] property.
+ An in-text citation is composed as follows:
+ [Author][InTextYearSeparator][BracketBefore][Year][BracketAfter]
+ where [Author] and [Year] are resolved in exactly the same way as for the parenthesis citations.
+
+ If two different cited sources have the same authors and publication year, and author-year citations are used,
+ their markers will need modification in order to be distinguishable. This is done automatically by appending a
+ letter after the year for
+ each of the publications; 'a' for the first cited reference, 'b' for the next, and so on.
+ For instance, if the author "Olsen" has two cited papers from 2005, the citation markers will be modified to
+ (Olsen, 2005a)
and (Olsen, 2005b)
. In the bibliography
+ layout, the placement of the "uniquefier" letter is indicated explicitly by inserting the virtual field
+ uniq
.
+ If several entries that have been "uniquefied" are cited together, they will be grouped in the citation
+ marker. For instance, of the two entries in the example above are cited together, the citation marker will
+ be (Olsen, 2005a, b)
rather than Olsen, 2005a; Olsen, 2005b)
. The grouped uniquefier
+ letters (a and b in our example) will be separated by the string specified by the UniquefierSeparator
+ property.
+
+ The property FormatCitations
determines whether the citation markers should be formatted with
+ regards to italics, boldness, superscript and subscript. If FormatCitations
is false, no such formatting
+ will be done. If true, the citations will be italicized or not depending on the ItalicCitations
property, set to bold
+ or not depending on the BoldCitations
property, and similar for the SuperscriptCitations
and
+ SubscriptCitations
properties.
+ The LAYOUT section describes how the bibliography entry for each entry type in JabRef
+ should appear. Each line should start with either the name of a BibTeX entry type, or the word
+ default
, followed by a '='. The default
layout will be used for all
+ entry types for which an explicit layout hasn't been given.
+ The remainder of each line defines the layout, with normal text and spaces appearing literally
+ in the bibliography entry. Information from the BibTeX entry is inserted by adding \field
markers
+ with the appropriate field name (e.g. \author
for inserting the author names). Formatting
+ information for the field can be included here, following JabRef's standard export layout syntax.
+ Refer to JabRef's documentation on custom export filters
+ for more information about which formatters are available.
+ If author-year citations are used, you have to explicitly specify the position of the "uniquefier" letter
+ that is added to distinguish similar-looking citations. This is done by including a marker for the virtual field
+ uniq
, typically right after the year (as shown in the example style file). The uniq
+ field is automatically set correctly for each entry before its reference text is laid out.
+
+ To indicate formatting in the bibliography, you can use the HTML-like tag pairs <b> </b>,
+ <i> </i>, <sup> </sup> and <sub> </sub> to specify bold text,
+ italic text, superscript and subscript, respectively.
+ If you are using numbered citations, the number for each entry will be automatically inserted at the start
+ of each entry in the reference list. By default, the numbers will be enclosed in the same brackets defined for
+ citations. The optional citation properties BracketBeforeInList
and
+ BracketAfterInList
override BracketBefore
and BracketAfter
if set. These
+ can be used if you want different types of brackets (or no brackets) in the reference list. Note that these need
+ not be brackets as such - they can be any combination of characters.
+
+Known issues
+
+
+ - Make sure to save your Writer document in OpenDocument format
+ (odt). Saving to Word format will lose your reference marks.
+ - There is currently no support for footnote based citations.
+ - The cursor may be poorly positioned after inserting a citation.
+ - Copy-pasting the example style file directly from this page can give an unparseable
+ file. To avoid this, instead download the example file from the link in the download section.
+
+
+Contact
+
+If you have tested this plugin, and want to give your feedback, or if you
+want to contribute to the development of the plugin, please contact me at the
+e-mail address mortenalver at users.sourceforge.net.
+
+
diff --git a/build.xml b/build.xml
new file mode 100755
index 0000000..712e5cb
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example_style_file.jstyle b/example_style_file.jstyle
new file mode 100755
index 0000000..7208ba8
--- /dev/null
+++ b/example_style_file.jstyle
@@ -0,0 +1,53 @@
+NAME
+Example style file for JabRef-oo plugin.
+
+JOURNALS
+Journal name 1
+Journal name 2
+
+PROPERTIES
+Title=References
+IsSortByPosition=false
+IsNumberEntries=false
+ReferenceParagraphFormat=Text body
+ReferenceHeaderParagraphFormat=Heading 2
+
+CITATION
+AuthorField=author/editor
+YearField=year
+MaxAuthors=2
+MaxAuthorsFirst=6
+AuthorSeparator=,
+AuthorLastSeparator= &
+AuthorLastSeparatorInText= &
+EtAlString= et al.
+YearSeparator=
+InTextYearSeparator=
+BracketBefore=[
+BracketAfter=]
+BracketBeforeInList=[
+BracketAfterInList=]
+CitationSeparator=;
+UniquefierSeparator=,
+GroupedNumbersSeparator=-
+MinimumGroupingCount=3
+FormatCitations=false
+ItalicCitations=false
+BoldCitations=false
+SuperscriptCitations=false
+SubscriptCitations=false
+MultiCiteChronological=true
+
+LAYOUT
+article=\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (\year\uniq). \title, \journal \volume\begin{pages} : \format[FormatPagesForHTML]{\pages}\end{pages}.
+
+book=\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author}\begin{editor}\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\editor} (Ed.)\end{editor}, \year\uniq. \title. \publisher, \address.
+
+incollection=\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (\year\uniq). \title. In: \format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\editor} (Ed.), \booktitle, \publisher.
+
+inbook=\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (\year\uniq). \chapter. In: \format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\editor} (Ed.), \title, \publisher.
+
+phdthesis=\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (\year\uniq). \title, \school.
+
+default=\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (\year\uniq). \title, \journal \volume\begin{pages} : \format[FormatPagesForHTML]{\pages}\end{pages}.
+
diff --git a/net/sf/jabref/oo/OOBibBase.java b/net/sf/jabref/oo/OOBibBase.java
new file mode 100755
index 0000000..6fbc11d
--- /dev/null
+++ b/net/sf/jabref/oo/OOBibBase.java
@@ -0,0 +1,1181 @@
+package net.sf.jabref.oo;
+
+import com.sun.star.awt.Point;
+import com.sun.star.awt.XWindow;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.comp.helper.Bootstrap;
+import com.sun.star.container.*;
+import com.sun.star.frame.*;
+import com.sun.star.lang.*;
+import com.sun.star.lang.Locale;
+import com.sun.star.text.*;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import net.sf.jabref.*;
+import net.sf.jabref.export.layout.Layout;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import classes.net.sf.jabref.oo.ComparableMark;
+
+/**
+ * Class for manipulating the Bibliography of the currently start document in OpenOffice.
+ */
+public class OOBibBase {
+
+ final static String BIB_SECTION_NAME = "JR_bib";
+ final static String BIB_SECTION_END_NAME = "JR_bib_end";
+ final static String BIB_CITATION = "JR_cite";
+ final Pattern citePattern = Pattern.compile(BIB_CITATION+"\\d*_(\\d*)_(.*)");
+
+ final static int
+ AUTHORYEAR_PAR = 1,
+ AUTHORYEAR_INTEXT = 2,
+ INVISIBLE_CIT = 3;
+
+ final static String DEFAULT_CONNECTION_STRING = "uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager";
+ final String[] BIB_TYPES = new String[] { "ARTICLE", "BOOK", "BOOKLET", "CONFERENCE",
+ "INBOOK", "INCOLLECTION", "INPROCEEDINGS", "JOURNAL", "MANUAL", "MASTERTHESIS",
+ "MISC", "PHDTHESIS", "PROCEEDINGS", "TECHREPORT", "UNPUBLISHED", "EMAIL", "WWW",
+ "CUSTOM1", "CUSTOM2", "CUSTOM3", "CUSTOM4", "CUSTOM5" };
+
+
+ private XMultiServiceFactory mxDocFactory = null;
+ private XTextDocument mxDoc = null;
+ private XText text = null;
+ private XDesktop xDesktop = null;
+ XTextViewCursorSupplier xViewCursorSupplier = null;
+ XComponent xCurrentComponent = null;
+ XComponentLoader xComponentLoader = null;
+ private boolean atEnd;
+ private AlphanumericComparator entryComparator = new AlphanumericComparator();
+ private YearComparator yearComparator = new YearComparator();
+
+ private HashMap uniquefiers = new HashMap();
+
+ private String[] sortedReferenceMarks = null;
+
+ public OOBibBase(String pathToOO, boolean atEnd) throws Exception {
+ this.atEnd = atEnd;
+ xDesktop = simpleBootstrap(pathToOO);//getDesktop();
+ try {
+ selectDocument();
+ } catch (Exception ex) {
+ // Could not find a writer document?
+ return;
+ }
+
+ }
+
+ public boolean isConnectedToDocument() {
+ return xCurrentComponent != null;
+ }
+
+ public String getCurrentDocumentTitle() {
+ if (mxDoc != null) {
+ try {
+ return String.valueOf(OOUtil.getProperty
+ (mxDoc.getCurrentController().getFrame(), "Title"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ else
+ return null;
+ }
+
+ public void selectDocument() throws Exception {
+ List ls = getTextDocuments();
+ XTextDocument selected = null;
+ if (ls.size() == 0) {
+ // No text documents found.
+ throw new Exception("No Writer documents found");
+ }
+ else if (ls.size() > 1) {
+ selected = OOUtil.selectComponent(null, xDesktop, ls);
+ }
+ else
+ selected = ls.get(0);
+
+ if (selected == null) {
+ return;
+ }
+ xCurrentComponent = (XComponent) UnoRuntime.queryInterface(
+ XComponent.class, selected);
+ mxDoc = selected;
+
+ com.sun.star.text.XDocumentIndexesSupplier indexesSupp = (com.sun.star.text.XDocumentIndexesSupplier) UnoRuntime.queryInterface(
+ com.sun.star.text.XDocumentIndexesSupplier.class, xCurrentComponent);
+
+ XModel xModel = (XModel) UnoRuntime.queryInterface(XModel.class, xCurrentComponent);
+ XController xController = xModel.getCurrentController();
+ xViewCursorSupplier =
+ (com.sun.star.text.XTextViewCursorSupplier) UnoRuntime.queryInterface(
+ com.sun.star.text.XTextViewCursorSupplier.class, xController);
+
+ // get a reference to the body text of the document
+ text = mxDoc.getText();
+
+ // Access the text document's multi service factory:
+ mxDocFactory = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, mxDoc);
+
+ }
+
+ public XDesktop simpleBootstrap(String pathToExecutable) throws Exception {
+
+
+ ClassLoader loader = ClassLoader.getSystemClassLoader();
+ if (loader instanceof URLClassLoader) {
+ URLClassLoader cl = (URLClassLoader) loader;
+ Class sysclass = URLClassLoader.class;
+ try {
+
+ Method method = sysclass.getDeclaredMethod("addURL", new Class[]{URL.class});
+ method.setAccessible(true);
+
+ method.invoke(cl, new Object[]{new File(pathToExecutable).toURI().toURL()});
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw new IOException("Error, could not add URL to system classloader");
+ }
+ } else {
+ System.out.println("Error occured, URLClassLoader expected but " +
+ loader.getClass() + " received. Could not continue.");
+ }
+
+ //Get the office component context:
+ XComponentContext xContext = Bootstrap.bootstrap();
+
+ //Get the office service manager:
+ XMultiComponentFactory xServiceManager = xContext.getServiceManager();
+
+ //Create the desktop, which is the root frame of the
+ //hierarchy of frames that contain viewable components:
+ Object desktop = xServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", xContext);
+
+ XDesktop xD = (XDesktop) UnoRuntime.queryInterface(XDesktop.class, desktop);
+
+ xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface(
+ XComponentLoader.class, desktop);
+
+ return xD;
+
+ }
+
+ public List getTextDocuments() throws Exception {
+ List res = new ArrayList();
+ XEnumerationAccess enumA = xDesktop.getComponents();
+ XEnumeration e = enumA.createEnumeration();
+
+ // TODO: http://api.openoffice.org/docs/DevelopersGuide/OfficeDev/OfficeDev.xhtml#1_1_3_2_1_2_Frame_Hierarchies
+
+ while (e.hasMoreElements()) {
+ Object o = e.nextElement();
+ XComponent comp = (XComponent) UnoRuntime.queryInterface(XComponent.class, o);
+ XTextDocument doc = (XTextDocument) UnoRuntime.queryInterface(
+ XTextDocument.class, comp);
+ if (doc != null) {
+ res.add(doc);
+ }
+ }
+ return res;
+ }
+
+
+ public void updateSortedReferenceMarks() throws Exception {
+ XReferenceMarksSupplier supplier = (XReferenceMarksSupplier) UnoRuntime.queryInterface(
+ XReferenceMarksSupplier.class, xCurrentComponent);
+ XNameAccess nameAccess = supplier.getReferenceMarks();
+ String[] names;
+ sortedReferenceMarks = getSortedReferenceMarks(nameAccess);
+ }
+
+ /**
+ * This method inserts a cite marker in the text for the given BibtexEntry,
+ * and may refresh the bibliography.
+ * @param entries The entries to cite.
+ * @param database The database the entry belongs to.
+ * @param style The bibliography style we are using.
+ * @param inParenthesis Indicates whether it is an in-text citation or a citation in parenthesis.
+ * This is not relevant if numbered citations are used.
+ * @param withText Indicates whether this should be a normal citation (true) or an empty
+ * (invisible) citation (false).
+ * @param sync Indicates whether the reference list should be refreshed.
+ * @throws Exception
+ */
+ public void insertEntry(BibtexEntry[] entries, BibtexDatabase database, OOBibStyle style,
+ boolean inParenthesis, boolean withText, boolean sync) throws Exception {
+
+ try {
+ XTextViewCursor xViewCursor = xViewCursorSupplier.getViewCursor();
+
+ if (entries.length > 1) {
+ if (style.getBooleanCitProperty("MultiCiteChronological"))
+ Arrays.sort(entries, yearComparator);
+ else
+ Arrays.sort(entries, entryComparator);
+ }
+
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < entries.length; i++) {
+ BibtexEntry entry = entries[i];
+ if (i > 0)
+ sb.append(",");
+ sb.append(entry.getCiteKey());
+ }
+ String keyString = sb.toString();
+ // Insert bookmark:
+ String bName = getUniqueReferenceMarkName(keyString,
+ withText ? (inParenthesis ? AUTHORYEAR_PAR : AUTHORYEAR_INTEXT) : INVISIBLE_CIT);
+ //XTextContent content = insertBookMark(bName, xViewCursor);
+
+
+ String citeText = style.isNumberEntries() ? "-" : style.getCitationMarker(entries, database, inParenthesis, null, null);
+
+ //System.out.println(text+" / "+xViewCursor.getText());
+ xViewCursor.getText().insertString(xViewCursor, " ", false);
+ xViewCursor.goLeft((short)1,false);
+ insertReferenceMark(bName, citeText, xViewCursor, withText, style);
+ //xViewCursor.collapseToEnd();
+
+ xViewCursor.collapseToEnd();
+ xViewCursor.goRight((short)1,false);
+
+ XTextRange position = xViewCursor.getEnd();
+
+ if (sync) {
+ // To account for numbering and for uniqiefiers, we must refresh the cite markers:
+ updateSortedReferenceMarks();
+ refreshCiteMarkers(database, style);
+
+ // Insert it at the current position:
+ rebuildBibTextSection(database, style);
+ }
+
+ // Go back to the relevant position:
+ try {
+ xViewCursor.gotoRange(position, false);
+ } catch (Exception ex) {
+ System.out.println("Catch");
+ ex.printStackTrace();
+ }
+ } catch (DisposedException ex) {
+ // We need to catch this one here because the OOTestPanel class is
+ // loaded before connection, and therefore cannot directly reference
+ // or catch a DisposedException (which is in a OO jar file).
+ throw new ConnectionLostException(ex.getMessage());
+ }
+ }
+
+ /**
+ * Refresh all cite markers in the document.
+ * @param database The database to get entries from.
+ * @param style The bibliography style to use.
+ * @return A list of those referenced BibTeX keys that could not be resolved.
+ * @throws UndefinedParagraphFormatException
+ * @throws Exception
+ */
+ public List refreshCiteMarkers(BibtexDatabase database, OOBibStyle style) throws
+ UndefinedParagraphFormatException, Exception {
+ try {
+ return refreshCiteMarkersInternal(database, style);
+ } catch (DisposedException ex) {
+ // We need to catch this one here because the OOTestPanel class is
+ // loaded before connection, and therefore cannot directly reference
+ // or catch a DisposedException (which is in a OO jar file).
+ throw new ConnectionLostException(ex.getMessage());
+ }
+ }
+
+ private List refreshCiteMarkersInternal(BibtexDatabase database, OOBibStyle style) throws
+ UndefinedParagraphFormatException, Exception {
+
+ List cited = findCitedKeys();
+ List entries = findCitedEntries(database, cited);
+
+ XReferenceMarksSupplier supplier = (XReferenceMarksSupplier) UnoRuntime.queryInterface(
+ XReferenceMarksSupplier.class, xCurrentComponent);
+ XNameAccess nameAccess = supplier.getReferenceMarks();
+
+ String[] names;
+ if (style.isSortByPosition()) {
+ // We need to sort the reference marks according to their order of appearance:
+ /*if (sortedReferenceMarks == null)
+ updateSortedReferenceMarks();*/
+ names = sortedReferenceMarks;
+ }
+ else if (style.isNumberEntries()) {
+ // We need to sort the reference marks according to the sorting of the bibliographic
+ // entries:
+ Collections.sort(entries, entryComparator);
+ // Rebuild the list of cited keys according to the sort order:
+ cited.clear();
+ for (Iterator iterator = entries.iterator(); iterator.hasNext();) {
+ BibtexEntry entry = iterator.next();
+ cited.add(entry.getCiteKey());
+ }
+ names = nameAccess.getElementNames();
+ }
+ else {
+ /*if (sortedReferenceMarks == null)
+ updateSortedReferenceMarks();*/
+ names = sortedReferenceMarks;
+ }
+
+ HashMap numbers = new HashMap();
+ //HashMap 1) {
+ if (style.getBooleanCitProperty("MultiCiteChronological"))
+ Arrays.sort(cEntries, yearComparator);
+ else
+ Arrays.sort(cEntries, entryComparator);
+ // Update key list to match the new sorting:
+ for (int j = 0; j < cEntries.length; j++) {
+ bibtexKeys[i][j] = cEntries[j].getCiteKey();
+ }
+ }
+ /*System.out.println(style.getBooleanCitProperty("MultiCiteChronological"));
+ for (int j = 0; j < cEntries.length; j++) {
+ BibtexEntry cEntry = cEntries[j];
+ System.out.println(cEntry.getCiteKey());
+ } */
+
+ citationMarker = style.getCitationMarker(cEntries, database, type == AUTHORYEAR_PAR, null, null);
+ // We need "normalized" (in parenthesis) markers for uniqueness checking purposes:
+ for (int j=0; j> refKeys = new HashMap>();
+ HashMap> refNums = new HashMap>();
+ for (int i = 0; i < citMarkers.length; i++) {
+ String[] markers = normCitMarkers[i]; // compare normalized markers, since the actual markers can be different
+ for (int j=0; j l = new ArrayList(1);
+ l.add(bibtexKeys[i][j]);
+ refKeys.put(marker, l);
+ List l2 = new ArrayList(1);
+ l2.add(i);
+ refNums.put(marker, l2);
+ }
+ else {
+ // Ok, we have seen this exact marker before.
+ if (!refKeys.get(marker).contains(bibtexKeys[i][j])) {
+ // ... but not for this entry.
+ refKeys.get(marker).add(bibtexKeys[i][j]);
+ refNums.get(marker).add(i);
+ }
+ }
+ }
+ }
+ // Go through the collected lists and see where we need to uniquefy:
+ for (String marker : refKeys.keySet()) {
+ List keys = refKeys.get(marker);
+ if (keys.size() > 1) {
+ // This marker appears for more than one unique entry:
+ int uniq = 'a';
+ for (String key : keys) {
+ // Update the map of uniquefiers for the benefit of both the following generation of new
+ // citation markers, and for the method that builds the bibliography:
+ uniquefiers.put(key, String.valueOf((char)uniq));
+ uniq++;
+ }
+ }
+ }
+
+ // Finally, go through all citation markers, and update those referring to entries in our current list:
+ int maxAuthorsFirst = style.getIntCitProperty("MaxAuthorsFirst");
+ HashSet seenBefore = new HashSet();
+ for (int j = 0; j < bibtexKeys.length; j++) {
+ boolean needsChange = false;
+ int[] firstLimAuthors = new int[bibtexKeys[j].length];
+ String[] uniquif = new String[bibtexKeys[j].length];
+ BibtexEntry[] cEntries = new BibtexEntry[bibtexKeys[j].length];
+ for (int k=0; k 0) {
+ if (!seenBefore.contains(bibtexKeys[j][k])) {
+ firstLimAuthors[k] = maxAuthorsFirst;
+ }
+ seenBefore.add(bibtexKeys[j][k]);
+ }
+ String uniq = uniquefiers.get(bibtexKeys[j][k]);
+ if ((uniq != null) && (uniq.length() >= 0)) {
+ needsChange = true;
+ cEntries[k] = OOUtil.createAdaptedEntry(database.getEntryByKey(bibtexKeys[j][k]));
+ uniquif[k] = uniq;
+ }
+ else if (firstLimAuthors[k] > 0) {
+ needsChange = true;
+ cEntries[k] = OOUtil.createAdaptedEntry(database.getEntryByKey(bibtexKeys[j][k]));
+ uniquif[k] = "";
+ }
+ else {
+ cEntries[k] = OOUtil.createAdaptedEntry(database.getEntryByKey(bibtexKeys[j][k]));
+ uniquif[k] = "";
+ }
+ }
+ if (needsChange)
+ citMarkers[j] = style.getCitationMarker(cEntries, database, types[j] == AUTHORYEAR_PAR,
+ uniquif, firstLimAuthors);
+ }
+ }
+
+ // Refresh all reference marks with the citation markers we computed:
+ boolean hadBibSection = getBookmarkRange(BIB_SECTION_NAME) != null;
+ for (int i = 0; i < names.length; i++) {
+ Object o = nameAccess.getByName(names[i]);
+ XTextContent bm = (XTextContent) UnoRuntime.queryInterface
+ (XTextContent.class, o);
+
+ XTextCursor cursor = bm.getAnchor().getText().createTextCursorByRange(bm.getAnchor());
+ text.removeTextContent(bm);
+ insertReferenceMark(names[i], citMarkers[i], cursor, types[i] != INVISIBLE_CIT, style);
+ if (hadBibSection && (getBookmarkRange(BIB_SECTION_NAME) == null)) {
+ // We have overwritten the marker for the start of the reference list.
+ // We need to add it again.
+ cursor.collapseToEnd();
+ OOUtil.insertParagraphBreak(text, cursor);
+ insertBookMark(BIB_SECTION_NAME, cursor);
+ /* The following is for resetting the paragraph format, but should probably
+ not be done.
+
+ XParagraphCursor parCursor =
+ (XParagraphCursor)UnoRuntime.queryInterface(
+ java.lang.Class.forName("com.sun.star.text.XParagraphCursor"), cursor);
+ parCursor.gotoPreviousParagraph(false);
+ parCursor.gotoStartOfParagraph(false);
+ parCursor.gotoEndOfParagraph(true);
+ XPropertySet props = (XPropertySet) UnoRuntime.queryInterface(
+ XPropertySet.class, parCursor);
+
+ try {
+ props.setPropertyValue("ParaStyleName", "Default");
+ } catch (com.sun.star.lang.IllegalArgumentException ex) {
+ throw new UndefinedParagraphFormatException("Default");
+ }
+ */
+
+ }
+ }
+
+ ArrayList unresolvedKeys = new ArrayList();
+ for (BibtexEntry entry : entries) {
+ if (entry instanceof UndefinedBibtexEntry) {
+ String key = ((UndefinedBibtexEntry)entry).getKey();
+ if (!unresolvedKeys.contains(key))
+ unresolvedKeys.add(key);
+ }
+ }
+ return unresolvedKeys;
+ }
+
+ public String[] getSortedReferenceMarks(final XNameAccess nameAccess) throws Exception {
+ /*
+ PropertyValue[] props = new PropertyValue[2];
+
+ props[0] = new PropertyValue();
+ props[0].Name = "Model";
+
+ props[0].Value = mxDoc.getCurrentController().getModel();
+ props[1] = new PropertyValue();
+ props[1].Name = "Hidden";
+ props[1].Value = true;
+
+ // argument xModel wins over URL.
+ System.out.println("her");
+ XComponent comp = xComponentLoader.loadComponentFromURL("private:factory/swriter",
+ "_blank", 0, props);
+ System.out.println("her2");
+
+ XTextDocument newDoc = (XTextDocument)UnoRuntime.queryInterface(
+ XTextDocument.class, comp);
+ System.out.println("newDoc = "+newDoc);
+
+ // Controller of the hidden frame
+ XController xController = newDoc.getCurrentController();
+
+ XFrame xFrame = xController.getFrame();
+ XWindow xContainerWindow = xFrame.getContainerWindow();
+ XWindow xComponentWindow = xFrame.getComponentWindow();
+
+ xContainerWindow.setVisible(true);
+ xComponentWindow.setFocus();
+ xContainerWindow.setVisible(false);
+ */
+ XTextViewCursorSupplier css = (XTextViewCursorSupplier)UnoRuntime.queryInterface(
+ XTextViewCursorSupplier.class, mxDoc.getCurrentController());
+
+ XTextViewCursor tvc = css.getViewCursor();
+ XTextRange initialPos = tvc.getStart();
+ String[] names = nameAccess.getElementNames();
+ Point[] positions = new Point[names.length];
+ for (int i = 0; i < names.length; i++) {
+ String name = names[i];
+ XTextContent tc = (XTextContent) UnoRuntime.queryInterface
+ (XTextContent.class, nameAccess.getByName(name));
+ XTextRange r = tc.getAnchor();
+ // Check if we are inside a footnote:
+ if (UnoRuntime.queryInterface(XFootnote.class, r.getText()) != null) {
+ // Find the linking footnote marker:
+ XFootnote footer = (XFootnote)UnoRuntime.queryInterface(XFootnote.class, r.getText());
+ // The footnote's anchor gives the correct position in the text:
+ r = footer.getAnchor();
+ }
+
+ positions[i] = findPosition(tvc, r);
+ }
+ TreeSet set = new TreeSet();
+ for (int i = 0; i < positions.length; i++) {
+ set.add(new ComparableMark(names[i], positions[i]));
+ }
+ int i=0;
+ for (Iterator iterator = set.iterator(); iterator.hasNext();) {
+ ComparableMark mark = iterator.next();
+ //System.out.println(mark.getPosition().X+" -- "+mark.getPosition().Y+" : "+mark.getName());
+ names[i++] = mark.getName();
+ }
+ tvc.gotoRange(initialPos, false);
+ //xFrame.dispose();
+
+ return names;
+
+ /*final XTextRangeCompare compare = (XTextRangeCompare) UnoRuntime.queryInterface
+ (XTextRangeCompare.class, text);
+ Arrays.sort(names, new Comparator() {
+ public int compare(String o1, String o2) {
+ try {
+ XTextRange r1 = ((XTextContent) UnoRuntime.queryInterface
+ (XTextContent.class, nameAccess.getByName(o1))).getAnchor();
+ XTextRange r2 = ((XTextContent) UnoRuntime.queryInterface
+ (XTextContent.class, nameAccess.getByName(o2))).getAnchor();
+
+ try {
+ return compare.compareRegionStarts(r2, r1);
+ } catch (com.sun.star.lang.IllegalArgumentException ex) {
+ // problem comparing reference marks in different areas (text, table, etc.)
+ return 0;
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ return 0;
+ }
+ }
+ });
+ return names;*/
+ }
+
+ public void rebuildBibTextSection(BibtexDatabase database, OOBibStyle style)
+ throws Exception {
+ List cited = findCitedKeys();
+ List entries = findCitedEntries(database, cited);
+
+ String[] names = sortedReferenceMarks;
+ if (style.isSortByPosition()) {
+ // We need to sort the entries according to their order of appearance:
+ entries = getSortedEntriesFromSortedRefMarks(names, database, entries);
+ }
+ else {
+ Collections.sort(entries, entryComparator);
+ }
+
+ clearBibTextSectionContent();
+ populateBibTextSection(database, entries, style);
+ }
+
+
+
+ public String getUniqueReferenceMarkName(String bibtexKey, int type) {
+ XReferenceMarksSupplier supplier = (XReferenceMarksSupplier) UnoRuntime.queryInterface(
+ XReferenceMarksSupplier.class, xCurrentComponent);
+ XNameAccess xNamedRefMarks = supplier.getReferenceMarks();
+ int i=0;
+ String name = BIB_CITATION+"_"+type+"_"+bibtexKey;
+ while (xNamedRefMarks.hasByName(name)) {
+ name = BIB_CITATION+i+"_"+type+"_"+bibtexKey;
+ i++;
+ }
+ return name;
+ }
+
+ public List findCitedEntries(BibtexDatabase database, List keys) {
+ List entries = new ArrayList();
+ for (String key : keys) {
+ BibtexEntry entry = database.getEntryByKey(key);
+
+ if (entry != null)
+ entries.add(OOUtil.createAdaptedEntry(entry));
+ else {
+ entries.add(new UndefinedBibtexEntry(key));
+ }
+ }
+ return entries;
+ }
+
+ public List findCitedKeys() throws com.sun.star.container.NoSuchElementException, WrappedTargetException {
+
+ XReferenceMarksSupplier supplier = (XReferenceMarksSupplier) UnoRuntime.queryInterface(
+ XReferenceMarksSupplier.class, xCurrentComponent);
+ XNameAccess xNamedMarks = supplier.getReferenceMarks();
+ String[] names = xNamedMarks.getElementNames();
+ ArrayList keys = new ArrayList();
+ for (int i = 0; i < names.length; i++) {
+ Object bookmark = xNamedMarks.getByName(names[i]);
+ XTextContent xTextContent = (XTextContent) UnoRuntime.queryInterface(
+ XTextContent.class, bookmark);
+
+ String name = names[i];
+ List newKeys = parseRefMarkName(name);
+ for (String key : newKeys)
+ if (!keys.contains(key))
+ keys.add(key);
+ }
+
+ return keys;
+ }
+
+ public List getSortedEntriesFromSortedRefMarks(String[] names,
+ BibtexDatabase database, List entries)
+ throws BibtexEntryNotFoundException {
+
+ List newList = new ArrayList();
+ HashMap adaptedEntries = new HashMap();
+ for (int i = 0; i < names.length; i++) {
+ Matcher m = citePattern.matcher(names[i]);
+ if (m.find()) {
+ String[] keys = m.group(2).split(",");
+ for (int j = 0; j < keys.length; j++) {
+ BibtexEntry origEntry = database.getEntryByKey(keys[j]);
+ if (origEntry == null) {
+ System.out.println("Bibtex key not found : '"+keys[j]+"'");
+ System.out.println("Problem with reference mark: '"+names[i]+"'");
+ newList.add(new UndefinedBibtexEntry(keys[j]));
+ //throw new BibtexEntryNotFoundException(keys[j], "");
+ } else {
+ BibtexEntry entry = adaptedEntries.get(origEntry);
+ if (entry == null) {
+ entry = OOUtil.createAdaptedEntry(origEntry);
+ adaptedEntries.put(origEntry, entry);
+ }
+ if (!newList.contains(entry)) {
+ newList.add(entry);
+ }
+ }
+ }
+ }
+ }
+
+ return newList;
+ }
+
+ public Point findPosition(XTextViewCursor cursor, XTextRange range) {
+ cursor.gotoRange(range, false);
+ return cursor.getPosition();
+ }
+
+ /**
+ * Extract the list of bibtex keys from a reference mark name.
+ * @param name The reference mark name.
+ * @return The list of bibtex keys encoded in the name.
+ */
+ public List parseRefMarkName(String name) {
+ ArrayList keys = new ArrayList();
+ Matcher m = citePattern.matcher(name);
+ if (m.find()) {
+ String[] keystring = m.group(2).split(",");
+ for (int j = 0; j < keystring.length; j++) {
+ if (!keys.contains(keystring[j]))
+ keys.add(keystring[j]);
+ }
+ }
+ return keys;
+ }
+
+ /**
+ * Resolve the bibtex key from a citation reference marker name, and look up
+ * the index of the key in a list of keys.
+ * @param citRefName The name of the ReferenceMark representing the citation.
+ * @param keys A List of bibtex keys representing the entries in the bibliography.
+ * @return the indices of the cited keys, -1 if a key is not found. Returns null if the ref name
+ * could not be resolved as a citation.
+ */
+ public int[] findCitedEntryIndex(String citRefName, List keys) {
+ Matcher m = citePattern.matcher(citRefName);
+ if (m.find()) {
+ String[] keyStrings = m.group(2).split(",");
+ int[] res = new int[keyStrings.length];
+ for (int i=0; i entries,
+ OOBibStyle style, String parFormat)
+ throws UndefinedParagraphFormatException, Exception {
+ // If we don't have numbered entries, we need to sort the entries before adding them:
+ if (!style.isSortByPosition())
+ Collections.sort(entries, entryComparator);
+ int number = 1;
+ for (BibtexEntry entry : entries) {
+ if (entry instanceof UndefinedBibtexEntry)
+ continue;
+ OOUtil.insertParagraphBreak(text, cursor);
+ if (style.isNumberEntries()) {
+ int minGroupingCount = style.getIntCitProperty("MinimumGroupingCount");
+ OOUtil.insertTextAtCurrentLocation(text, cursor,
+ style.getNumCitationMarker(new int[] {number++}, minGroupingCount, true)+" ",
+ false, false, false, false, false, false);
+ }
+ Layout layout = style.getReferenceFormat(entry.getType().getName());
+ try {
+ layout.setPostFormatter(OOUtil.postformatter);
+ } catch (NoSuchMethodError ex) {
+
+ }
+ OOUtil.insertFullReferenceAtCurrentLocation(text, cursor, layout, parFormat, entry, database,
+ uniquefiers.get(entry.getCiteKey()));
+ }
+
+ }
+
+ public void insertFullReferenceAtViewCursor(BibtexDatabase database, List entries,
+ OOBibStyle style, String parFormat) throws Exception {
+ XTextViewCursor xViewCursor = xViewCursorSupplier.getViewCursor();
+ insertFullReferenceAtCursor(xViewCursor, database, entries, style, parFormat);
+ }
+
+
+ public void insertMarkedUpTextAtViewCursor(String lText, String parFormat) throws Exception {
+ XTextViewCursor xViewCursor = xViewCursorSupplier.getViewCursor();
+ XTextCursor cursor = text.createTextCursorByRange(xViewCursor.getEnd());
+ OOUtil.insertOOFormattedTextAtCurrentLocation(text,cursor, lText, parFormat);
+
+ }
+
+ /**
+ * This method creates and inserts an XTextSection named as determined by the
+ * string BIB_SECTION_NAME.
+ * @param end true to indicate that the section should be put at the end of the document,
+ * false to indicate that it should be put at the cursor position.
+ * @return true if the bibliography already existed, false otherwise..
+ * @throws Exception
+ */
+ public boolean createBibTextSection(boolean end) throws Exception {
+ // Check if there already is a bookmarked section:
+ XBookmarksSupplier bSupp = (XBookmarksSupplier) UnoRuntime.queryInterface(
+ XBookmarksSupplier.class, mxDoc);
+ if (bSupp.getBookmarks().hasByName(BIB_SECTION_NAME)) {
+ System.out.println("Found existing JabRef bookmark");
+ return true;
+ }
+ XTextCursor mxDocCursor = text.createTextCursor();
+ if (end)
+ mxDocCursor.gotoEnd(false);
+ OOUtil.insertParagraphBreak(text, mxDocCursor);
+ insertBookMark(BIB_SECTION_NAME, mxDocCursor);
+ return false;
+ }
+
+ public void clearBibTextSectionContent() throws Exception {
+ // Get a range comparator:
+ XTextRangeCompare compare = (XTextRangeCompare) UnoRuntime.queryInterface
+ (XTextRangeCompare.class, text);
+ // Find the bookmarks for the bibliography:
+ XTextRange range = getBookmarkRange(BIB_SECTION_NAME);
+ if (range == null)
+ createBibTextSection(atEnd);
+ XTextRange rangeEnd = getBookmarkRange(BIB_SECTION_END_NAME);
+ if (rangeEnd == null) {
+ // No end bookmark. This means that there is no bibliography.
+ return;
+ }
+ // Get a paragraph cursor at the start of the bibliography:
+ //System.out.println("text="+text+" range="+range);
+ XTextCursor mxDocCursor = text.createTextCursorByRange(range.getEnd());
+ mxDocCursor.goRight((short)1, true);
+ boolean couldExpand = true;
+ while (couldExpand && (compare.compareRegionEnds(mxDocCursor, rangeEnd) > 0)) {
+ couldExpand = mxDocCursor.goRight((short)1, true);
+ }
+ // Finally, clear the bibliography:
+ mxDocCursor.setString("");
+ mxDocCursor.collapseToStart();
+ removeBookMark(BIB_SECTION_END_NAME);
+ // If we lost the start bookmark, recreate it:
+ if (getBookmarkRange(BIB_SECTION_NAME) == null)
+ insertBookMark(BIB_SECTION_NAME, mxDocCursor);
+ }
+
+ public void populateBibTextSection(BibtexDatabase database, List entries,
+ OOBibStyle style)
+ throws UndefinedParagraphFormatException, Exception {
+ XTextRange range = getBookmarkRange(BIB_SECTION_NAME);
+ XTextCursor cursor = text.createTextCursorByRange(range.getEnd());
+ OOUtil.insertTextAtCurrentLocation(text, cursor, (String)style.getProperty("Title"),
+ (String)style.getProperty("ReferenceHeaderParagraphFormat"));
+ insertFullReferenceAtCursor(cursor, database, entries, style,
+ (String)style.getProperty("ReferenceParagraphFormat"));
+ insertBookMark(BIB_SECTION_END_NAME, cursor);
+ }
+
+ public XTextContent insertBookMark(String name, XTextCursor position) throws Exception {
+ Object bookmark = mxDocFactory.createInstance("com.sun.star.text.Bookmark");
+ // name the bookmark
+ XNamed xNamed = (XNamed) UnoRuntime.queryInterface(
+ XNamed.class, bookmark);
+ xNamed.setName(name);
+ // get XTextContent interface
+ XTextContent xTextContent = (XTextContent) UnoRuntime.queryInterface(
+ XTextContent.class, bookmark);
+ // insert bookmark at the end of the document
+ // instead of mxDocText.getEnd you could use a text cursor's XTextRange interface or any XTextRange
+ text.insertTextContent(position, xTextContent, true);
+ position.collapseToEnd();
+ return xTextContent;
+ }
+
+ public void insertReferenceMark(String name, String citText, XTextCursor position, boolean withText,
+ OOBibStyle style)
+ throws Exception {
+ Object bookmark = mxDocFactory.createInstance("com.sun.star.text.ReferenceMark");
+ // Name the reference
+ XNamed xNamed = (XNamed) UnoRuntime.queryInterface(
+ XNamed.class, bookmark);
+ xNamed.setName(name);
+ // get XTextContent interface
+ if (true) {
+
+ XTextContent xTextContent = (XTextContent) UnoRuntime.queryInterface(
+ XTextContent.class, bookmark);
+ if (withText) {
+ position.setString(citText);
+ XPropertySet xCursorProps = (XPropertySet) UnoRuntime.queryInterface(
+ XPropertySet.class, position);
+ // Set language to [None]:
+ xCursorProps.setPropertyValue("CharLocale", new Locale("zxx", "", ""));
+
+ // See if we should format the citation marker or not:
+ if (style.isFormatCitations()) {
+
+ if (style.getBooleanCitProperty("SuperscriptCitations")) {
+ xCursorProps.setPropertyValue("CharEscapement",
+ (byte)101);
+ xCursorProps.setPropertyValue("CharEscapementHeight",
+ (byte)58);
+ }
+ else if (style.getBooleanCitProperty("SubscriptCitations")) {
+ xCursorProps.setPropertyValue("CharEscapement",
+ (byte)-101);
+ xCursorProps.setPropertyValue("CharEscapementHeight",
+ (byte)58);
+ }
+ else {
+ xCursorProps.setPropertyValue("CharEscapement",
+ (byte)0);
+ xCursorProps.setPropertyValue("CharEscapementHeight",
+ (byte)0);
+ }
+
+ xCursorProps.setPropertyValue("CharPosture",
+ style.isItalicCitations() ? com.sun.star.awt.FontSlant.ITALIC :
+ com.sun.star.awt.FontSlant.NONE);
+ xCursorProps.setPropertyValue("CharWeight",
+ style.isBoldCitations() ? com.sun.star.awt.FontWeight.BOLD :
+ com.sun.star.awt.FontWeight.NORMAL);
+
+ }
+ }
+ else
+ position.setString("");
+
+
+ position.getText().insertTextContent(position, xTextContent, true);
+ }
+ position.collapseToEnd();
+
+ }
+
+ public void testFootnote() throws Exception {
+ XTextViewCursor xViewCursor = xViewCursorSupplier.getViewCursor();
+ insertFootnote("jabbes", "Cite text", xViewCursor);
+ }
+
+ public void insertFootnote(String name, String citText, XTextCursor position) throws Exception {
+ XFootnote xFootnote = (XFootnote) UnoRuntime.queryInterface( XFootnote.class,
+ mxDocFactory.createInstance("com.sun.star.text.Footnote"));
+ xFootnote.setLabel("");
+ XPropertySet props = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xFootnote);
+ props.setPropertyValue("ReferenceId", name); // doesn't work: short data type
+ System.out.println(props.getPropertyValue("ReferenceId"));
+ XTextContent xContent = (XTextContent)UnoRuntime.queryInterface(
+ XTextContent.class, xFootnote);
+ text.insertTextContent (position, xContent, false);
+ XSimpleText xSimple = (XSimpleText)UnoRuntime.queryInterface(XSimpleText.class, xFootnote);
+ XTextRange xRange = (XTextRange)UnoRuntime.queryInterface(XTextRange.class, xSimple.createTextCursor());
+ xSimple.insertString (xRange, citText, false);
+ }
+
+ public void removeBookMark(String name) throws Exception {
+ XBookmarksSupplier xBookmarksSupplier = (XBookmarksSupplier) UnoRuntime.queryInterface(
+ XBookmarksSupplier.class, xCurrentComponent);
+ if (xBookmarksSupplier.getBookmarks().hasByName(name)) {
+ Object o = xBookmarksSupplier.getBookmarks().getByName(name);
+ XTextContent bm = (XTextContent) UnoRuntime.queryInterface(
+ XTextContent.class, o);
+ text.removeTextContent(bm);
+ }
+ }
+
+ public void removeReferenceMark(String name) throws Exception {
+ XReferenceMarksSupplier xSupplier = (XReferenceMarksSupplier) UnoRuntime.queryInterface(
+ XReferenceMarksSupplier.class, xCurrentComponent);
+ if (xSupplier.getReferenceMarks().hasByName(name)) {
+ Object o = xSupplier.getReferenceMarks().getByName(name);
+ XTextContent bm = (XTextContent) UnoRuntime.queryInterface(
+ XTextContent.class, o);
+ text.removeTextContent(bm);
+ }
+ }
+
+ /**
+ * Get the XTextRange corresponding to the named bookmark.
+ * @param name The name of the bookmark to find.
+ * @return The XTextRange for the bookmark.
+ * @throws Exception
+ */
+ public XTextRange getBookmarkRange(String name) throws Exception {
+ // query XBookmarksSupplier from document model and get bookmarks collection
+ XBookmarksSupplier xBookmarksSupplier = (XBookmarksSupplier) UnoRuntime.queryInterface(
+ XBookmarksSupplier.class, xCurrentComponent);
+ XNameAccess xNamedBookmarks = xBookmarksSupplier.getBookmarks();
+
+ // retrieve bookmark by name
+ //System.out.println("Name="+name+" : "+xNamedBookmarks.hasByName(name));
+ if (!xNamedBookmarks.hasByName(name))
+ return null;
+ Object foundBookmark = xNamedBookmarks.getByName(name);
+ XTextContent xFoundBookmark = (XTextContent) UnoRuntime.queryInterface(
+ XTextContent.class, foundBookmark);
+ return xFoundBookmark.getAnchor();
+ }
+
+ public void printBookmarkNames() throws Exception {
+ XBookmarksSupplier xBookmarksSupplier = (XBookmarksSupplier) UnoRuntime.queryInterface(
+ XBookmarksSupplier.class, xCurrentComponent);
+ XNameAccess xNamedBookmarks = xBookmarksSupplier.getBookmarks();
+ String[] names = xNamedBookmarks.getElementNames();
+ for (int i = 0; i < names.length; i++) {
+ System.out.println(i+". "+names[i]);
+ }
+ }
+
+
+ /**
+ * Focus the active OO document.
+ */
+ public void setFocus() {
+ xDesktop.getCurrentFrame().getContainerWindow().setFocus();
+ }
+
+
+ public void combineCiteMarkers(BibtexDatabase database, OOBibStyle style) throws Exception {
+ XReferenceMarksSupplier supplier = (XReferenceMarksSupplier) UnoRuntime.queryInterface(
+ XReferenceMarksSupplier.class, xCurrentComponent);
+ XNameAccess nameAccess = supplier.getReferenceMarks();
+ // TODO: doesn't work for citations in footnotes/tables
+ String[] names = getSortedReferenceMarks(nameAccess);
+
+
+ final XTextRangeCompare compare = (XTextRangeCompare) UnoRuntime.queryInterface
+ (XTextRangeCompare.class, text);
+
+ int piv = 0;
+ boolean madeModifications = false;
+ while (piv < names.length-1) {
+ XTextRange r1 = ((XTextContent) UnoRuntime.queryInterface
+ (XTextContent.class, nameAccess.getByName(names[piv]))).getAnchor().getEnd();
+ XTextRange r2 = ((XTextContent) UnoRuntime.queryInterface
+ (XTextContent.class,
+ nameAccess.getByName(names[piv+1]))).getAnchor().getStart();
+ if (r1.getText() != r2.getText()) {
+ piv++;
+ continue;
+ }
+ XTextCursor mxDocCursor = r1.getText().createTextCursorByRange(r1);
+ mxDocCursor.goRight((short)1, true);
+ boolean couldExpand = true;
+ while (couldExpand && (compare.compareRegionEnds(mxDocCursor, r2) > 0)) {
+ couldExpand = mxDocCursor.goRight((short)1, true);
+ }
+ String text = mxDocCursor.getString();
+ // Check if the string contains no line breaks and only whitespace:
+ if ((text.indexOf('\n') == -1) && (text.trim().length() == 0)) {
+ List keys = parseRefMarkName(names[piv]);
+ keys.addAll(parseRefMarkName(names[piv+1]));
+ removeReferenceMark(names[piv]);
+ removeReferenceMark(names[piv+1]);
+ ArrayList entries = new ArrayList();
+ for (String key : keys) {
+ entries.add(OOUtil.createAdaptedEntry(database.getEntryByKey(key)));
+ }
+ Collections.sort(entries, new FieldComparator("year"));
+ StringBuilder sb = new StringBuilder();
+ int i=0;
+ for (BibtexEntry entry : entries) {
+ if (i > 0)
+ sb.append(",");
+ sb.append(entry.getCiteKey());
+ i++;
+ }
+ String keyString = sb.toString();
+ boolean inParenthesis = true;
+ // Insert bookmark:
+ String bName = getUniqueReferenceMarkName(keyString,
+ inParenthesis ? AUTHORYEAR_PAR : AUTHORYEAR_INTEXT);
+ insertReferenceMark(bName, "tmp", mxDocCursor, true, style);
+ names[piv+1] = bName;
+ madeModifications = true;
+ }
+ piv++;
+ }
+ if (madeModifications) {
+ updateSortedReferenceMarks();
+ refreshCiteMarkers(database, style);
+ }
+
+
+ }
+
+ public void testFrameHandling() throws Exception {
+
+ XController oldController = mxDoc.getCurrentController();
+ PropertyValue[] props = new PropertyValue[2];
+
+ props[0] = new PropertyValue();
+ props[0].Name = "Model";
+
+ props[0].Value = mxDoc.getCurrentController().getModel();
+ props[1] = new PropertyValue();
+ props[1].Name = "Hidden";
+ props[1].Value = true;
+
+ // argument xModel wins over URL.
+ System.out.println("her");
+ XComponent comp = xComponentLoader.loadComponentFromURL("private:factory/swriter",
+ "_blank", 0, props);
+ System.out.println("her2");
+
+ XTextDocument newDoc = (XTextDocument)UnoRuntime.queryInterface(
+ XTextDocument.class, comp);
+ System.out.println("newDoc = "+newDoc);
+
+ // Controller of the hidden frame
+ XController xController = newDoc.getCurrentController();
+
+ XFrame xFrame = xController.getFrame();
+ XWindow xContainerWindow = xFrame.getContainerWindow();
+ XWindow xComponentWindow = xFrame.getComponentWindow();
+
+ //xContainerWindow.setVisible(true);
+ //xComponentWindow.setFocus();
+ //xContainerWindow.setVisible(false);
+ xFrame.dispose();
+ }
+}
diff --git a/net/sf/jabref/oo/OOBibStyle.java b/net/sf/jabref/oo/OOBibStyle.java
new file mode 100755
index 0000000..3cf8b4d
--- /dev/null
+++ b/net/sf/jabref/oo/OOBibStyle.java
@@ -0,0 +1,840 @@
+package net.sf.jabref.oo;
+
+import net.sf.jabref.AuthorList;
+import net.sf.jabref.BibtexDatabase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.export.layout.Layout;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.LayoutHelper;
+import net.sf.jabref.export.layout.format.RemoveLatexCommands;
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * This class embodies a bibliography formatting for OpenOffice, which is composed
+ * of the following elements:
+ *
+ * 1) Each OO bib entry type must have a formatting. A formatting is an array of elements, each
+ * of which is either a piece of constant text, an entry field value, or a tab. Each element has
+ * a character format associated with it.
+ *
+ * 2) Many field values (e.g. author) need to be formatted before input to OpenOffice. The style
+ * has the responsibility of formatting all field values. Formatting is handled by 0-n
+ * JabRef LayoutFormatter classes.
+ *
+ * 3) If the entries are not numbered, a citation marker must be produced for each entry. This
+ * operation is performed for each JabRef BibtexEntry.
+ */
+public class OOBibStyle implements Comparable {
+
+ public static final String UNDEFINED_CITATION_MARKER = "??";
+ String name = null;
+ SortedSet journals = new TreeSet();
+
+ Layout defaultBibLayout;
+ // formatters mapped from field names. Each field can have no mapping, or a set of formatters:
+ HashMap formatters = new HashMap();
+ // 0-n formatters applied to all fields before field-speficic formatters:
+ LayoutFormatter[] allBeforeFormat, allAfterFormat;
+ // reference layout mapped from entry type number:
+ HashMap bibLayout = new HashMap();
+
+ HashMap properties = new HashMap();
+ HashMap citProperties = new HashMap();
+
+ Pattern numPattern = Pattern.compile("-?\\d+");
+
+ boolean valid = false;
+
+ List juks = new ArrayList();
+
+ final static int NONE = 0, LAYOUT = 1, PROPERTIES=2, CITATION=3, NAME=4, JOURNALS=5;
+ final static String LAYOUT_MRK = "LAYOUT",
+ PROPERTIES_MARK = "PROPERTIES",
+ CITATION_MARK = "CITATION",
+ NAME_MARK = "NAME",
+ JOURNALS_MARK = "JOURNALS",
+ DEFAULT_MARK = "default";
+ private File styleFile = null;
+ private static long styleFileModificationTime = Long.MIN_VALUE;
+ private String COMBINED_ENTRIES_SEPARATOR = "-";
+
+ public OOBibStyle(File styleFile) throws Exception {
+ this(new FileReader(styleFile));
+ this.styleFile = styleFile;
+ styleFileModificationTime = (styleFile).lastModified();
+ }
+
+ public OOBibStyle(Reader in) throws Exception {
+
+ // Set default property values:
+ properties.put("Title", "Bibliography");
+ properties.put("SortAlgorithm", "alphanumeric");
+ properties.put("IsSortByPosition", Boolean.FALSE);
+ properties.put("IsNumberEntries", Boolean.FALSE);
+ properties.put("BracketBefore", "[");
+ properties.put("BracketAfter", "]");
+ properties.put("ReferenceParagraphFormat", "Default");
+ properties.put("ReferenceHeaderParagraphFormat", "Heading 1");
+
+ // Set default properties for the citation marker:
+ citProperties.put("AuthorField", "author/editor");
+ citProperties.put("YearField", "year");
+ citProperties.put("MaxAuthors", 3);
+ citProperties.put("MaxAuthorsFirst", -1);
+ citProperties.put("AuthorSeparator", ", ");
+ citProperties.put("AuthorLastSeparator", " & ");
+ citProperties.put("AuthorLastSeparatorInText", null);
+ citProperties.put("EtAlString", " et al.");
+ citProperties.put("YearSeparator", ", ");
+ citProperties.put("InTextYearSeparator", " ");
+ citProperties.put("BracketBefore", "(");
+ citProperties.put("BracketAfter", ")");
+ citProperties.put("CitationSeparator", "; ");
+ citProperties.put("GroupedNumbersSeparator", "-");
+ citProperties.put("MinimumGroupingCount", 3);
+ citProperties.put("FormatCitations", Boolean.FALSE);
+ citProperties.put("ItalicCitations", Boolean.FALSE);
+ citProperties.put("BoldCitations", Boolean.FALSE);
+ citProperties.put("SuperscriptCitations", Boolean.FALSE);
+ citProperties.put("SubscriptCitations", Boolean.FALSE);
+ citProperties.put("MultiCiteChronological", Boolean.TRUE);
+
+ initialize(in);
+
+
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public File getFile() {
+ return styleFile;
+ }
+
+ public Set getJournals() {
+ return Collections.unmodifiableSet(journals);
+ }
+
+ private void initialize(Reader in) throws IOException {
+ name = null;
+ readFormatFile(in);
+ allBeforeFormat = new LayoutFormatter[] {new RemoveLatexCommands()};
+ }
+
+ /**
+ * If this style was initialized from a file on disk, reload the style
+ * if the file has been modified since it was read.
+ * @throws Exception
+ */
+ public void ensureUpToDate() throws Exception {
+ if (!isUpToDate())
+ reload();
+ }
+
+ /**
+ * If this style was initialized from a file on disk, reload the style
+ * information.
+ * @throws Exception
+ */
+ public void reload() throws Exception {
+ if (styleFile != null) {
+ styleFileModificationTime = (styleFile).lastModified();
+ initialize(new FileReader(styleFile));
+ }
+ }
+
+ /**
+ * If this style was initialized from a file on disk, check whether the file
+ * is unmodified since initialization.
+ * @return true if the file has not been modified, false otherwise.
+ */
+ public boolean isUpToDate() {
+ if (styleFile != null) {
+ return styleFile.lastModified() == styleFileModificationTime;
+ }
+ else return true;
+ }
+
+ private void readFormatFile(Reader in) throws IOException {
+
+ // First read all the contents of the file:
+ StringBuffer sb = new StringBuffer();
+ int c;
+ while ((c = in.read()) != -1) {
+ sb.append((char)c);
+ }
+ // Break into separate lines:
+ String[] lines = sb.toString().split("\n");
+ int mode = NONE;
+
+ for (int i = 0; i < lines.length; i++) {
+ String line = lines[i];
+ // Check for empty line or comment:
+ if ((line.trim().length() == 0) || (line.charAt(0) == '#'))
+ continue;
+ // Check if we should change mode:
+ if (line.equals(NAME_MARK)) {
+ mode = NAME;
+ continue;
+ }
+ else if (line.equals(LAYOUT_MRK)) {
+ mode = LAYOUT;
+ continue;
+ }
+ else if (line.equals(PROPERTIES_MARK)) {
+ mode = PROPERTIES;
+ continue;
+ }
+ else if (line.equals(CITATION_MARK)) {
+ mode = CITATION;
+ continue;
+ }
+ else if (line.equals(JOURNALS_MARK)) {
+ mode = JOURNALS;
+ continue;
+ }
+
+ switch (mode) {
+ case NAME:
+ if (line.trim().length() > 0)
+ name = line.trim();
+ case LAYOUT:
+ handleStructureLine(line);
+ break;
+ case PROPERTIES:
+ handlePropertiesLine(line, properties);
+ break;
+ case CITATION:
+ handlePropertiesLine(line, citProperties);
+ break;
+ case JOURNALS:
+ handleJournalsLine(line);
+ }
+
+ }
+
+ // Set validity boolean based on whether we found anything interesting
+ // in the file:
+ if (mode != NONE)
+ valid = true;
+
+ }
+
+ /**
+ * After initalizing this style from a file, this method can be used to check
+ * whether the file appeared to be a proper style file.
+ * @return true if the file could be parsed as a style file, false otherwise.
+ */
+ public boolean isValid() {
+ return valid;
+ }
+
+
+ /**
+ * Parse a line providing bibliography structure information for an entry type.
+ * @param line The string containing the structure description.
+ * @throws IOException
+ */
+ private void handleStructureLine(String line) throws IOException {
+ int index = line.indexOf("=");
+ if ((index > 0) && (index < line.length()-1)) {
+ String formatString = line.substring(index+1);
+ //System.out.println("'"+line.substring(0, index)+"' : '"+formatString+"'");
+ boolean setDefault = line.substring(0, index).equals(DEFAULT_MARK);
+ String type = line.substring(0, index);
+ Short typeS;
+ try {
+ /*typeS = new Short(Short.parseShort(type));
+ OOBibFormatParser parser = new OOBibFormatParser(new StringReader(formatString));
+ PropertyValue[][] layout = parser.parse();*/
+ Layout layout = new LayoutHelper(new StringReader(formatString)).
+ getLayoutFromText(Globals.FORMATTER_PACKAGE);
+ if (setDefault)
+ defaultBibLayout = layout;
+ else
+ bibLayout.put(type.toLowerCase(), layout);
+
+ } catch (Exception ex) {
+ ex.printStackTrace();
+
+ }
+ }
+ }
+
+
+ /**
+ * Parse a line providing a property name and value.
+ * @param line The line containing the formatter names.
+ * @throws IOException
+ */
+ private void handlePropertiesLine(String line, HashMap map) throws IOException {
+ int index = line.indexOf("=");
+ if ((index > 0) && (index <= line.length()-1)) {
+ String propertyName = line.substring(0, index).trim();
+ String value = line.substring(index+1);
+ Object toSet = value;
+ if (numPattern.matcher(value).matches()) {
+ toSet = Integer.parseInt(value);
+ }
+ else if (value.toLowerCase().trim().equals("true"))
+ toSet = Boolean.TRUE;
+ else if (value.toLowerCase().trim().equals("false"))
+ toSet = Boolean.FALSE;
+ map.put(propertyName, toSet);
+ }
+ }
+
+ /**
+ * Parse a line providing a journal name for which this style is valid.
+ * @param line
+ * @throws IOException
+ */
+ private void handleJournalsLine(String line) throws IOException {
+ if (line.trim().length() > 0)
+ journals.add(line.trim());
+ }
+
+ public Layout getReferenceFormat(String type) {
+ Layout l = bibLayout.get(type.toLowerCase());
+ if (l != null)
+ return l;
+ else
+ return defaultBibLayout;
+ }
+
+ /**
+ * Get the array of elements composing the reference for a given entry type.
+ * @param bibType The OO type number.
+ * @return The format definition.
+
+ public PropertyValue[][] getReferenceFormat(short bibType) {
+ Object o = bibLayout.get(new Short(bibType));
+ if (o != null)
+ return (PropertyValue[][])o;
+ else
+ return defaultBibLayout;
+ }*/
+
+ /**
+ * Format the given field value based on the rules of this bib style.
+ * @param field The name of the field.
+ * @param content The unformatted field content.
+ * @return The formatted field value.
+ */
+ public String formatField(String field, String content) {
+ if (allBeforeFormat != null)
+ for (int i = 0; i < allBeforeFormat.length; i++) {
+ LayoutFormatter formatter = allBeforeFormat[i];
+ content = formatter.format(content);
+ }
+
+ Object o = formatters.get(field);
+ if (o == null)
+ return content;
+ LayoutFormatter[] form = (LayoutFormatter[])o;
+ for (int i = 0; i < form.length; i++) {
+ LayoutFormatter formatter = form[i];
+ content = formatter.format(content);
+ }
+
+ if (allAfterFormat != null)
+ for (int i = 0; i < allAfterFormat.length; i++) {
+ LayoutFormatter formatter = allAfterFormat[i];
+ content = formatter.format(content);
+ }
+
+ return content;
+ }
+
+ /**
+ * Format a number-based citation marker for the given number.
+ * @param number The citation numbers.
+ * @return The text for the citation.
+ */
+ public String getNumCitationMarker(int[] number, int minGroupingCount, boolean inList) {
+ String bracketBefore = (String)citProperties.get("BracketBefore");
+ if (inList && (citProperties.get("BracketBeforeInList")!=null)) {
+ bracketBefore = (String)citProperties.get("BracketBeforeInList");
+ }
+ String bracketAfter = (String)citProperties.get("BracketAfter");
+ if (inList && (citProperties.get("BracketAfterInList")!=null)) {
+ bracketAfter = (String)citProperties.get("BracketAfterInList");
+ }
+ // Sort the numbers:
+ int[] lNum = new int[number.length];
+ for (int i = 0; i < lNum.length; i++) {
+ lNum[i] = number[i];
+
+ }
+ //Arrays.copyOf(number, number.length);
+ Arrays.sort(lNum);
+ StringBuilder sb = new StringBuilder(bracketBefore);
+ int combineFrom = -1, written = 0;
+ for (int i = 0; i < lNum.length; i++) {
+ int i1 = lNum[i];
+ if (combineFrom < 0) {
+ // Check if next entry is the next in the ref list:
+ if ((i < lNum.length-1) && (lNum[i+1] == i1+1))
+ combineFrom = i1;
+ else {
+ // Add single entry:
+ if (i>0)
+ sb.append((String)citProperties.get("CitationSeparator"));
+ sb.append(lNum[i] > 0 ? String.valueOf(lNum[i]) : UNDEFINED_CITATION_MARKER);
+ written++;
+ }
+ } else {
+ // We are building a list of combined entries.
+ // Check if it ends here:
+ if ((i == lNum.length-1) || (lNum[i+1] != i1+1)) {
+ if (written>0)
+ sb.append((String)citProperties.get("CitationSeparator"));
+ if ((minGroupingCount > 0) && (i1+1-combineFrom >= minGroupingCount)) {
+ sb.append(combineFrom);
+ sb.append((String)citProperties.get("GroupedNumbersSeparator"));
+ sb.append(i1);
+ written++;
+ }
+ else {
+ // Either we should never group, or there aren't enough
+ // entries in this case to group. Output all:
+ for (int jj=combineFrom; jj<=i1; jj++) {
+ sb.append(jj);
+ if (jj < i1)
+ sb.append((String)citProperties.get("CitationSeparator"));
+ written++;
+ }
+ }
+ combineFrom = -1;
+
+ }
+ // If it doesn't end here, just keep iterating.
+ }
+
+ }
+ sb.append(bracketAfter);
+ return sb.toString();
+ }
+
+ /**
+ * Format the marker for the in-text citation according to this bib style.
+ *
+ * @param entry The JabRef BibtexEntry providing the data.
+ * @param inParenthesis Signals whether a parenthesized citation or an in-text citation is wanted.
+ * @param uniquefier String to add behind the year in case it's needed to separate similar
+ * entries.
+ * @return The formatted citation.
+ */
+ public String getCitationMarker(BibtexEntry entry, BibtexDatabase database, boolean inParenthesis,
+ String uniquefier, int unlimAuthors) {
+ return getCitationMarker(new BibtexEntry[] {entry}, database, inParenthesis, new String[] {uniquefier},
+ new int[] {unlimAuthors});
+ }
+
+ /**
+ * Format the marker for the in-text citation according to this bib style. Uniquefier letters are added as
+ * provided by the uniquefiers argument. If successive entries within the citation are uniquefied from each other,
+ * this method will perform a grouping of these entries.
+ *
+ * @param entries The array of JabRef BibtexEntry providing the data.
+ * @param inParenthesis Signals whether a parenthesized citation or an in-text citation is wanted.
+ * @param uniquefiers Strings to add behind the year for each entry in case it's needed to separate similar
+ * entries.
+ * @param unlimAuthors Boolean for each entry. If true, we should not use "et al" formatting regardless
+ * of the number of authors. Can be null to indicate that no entries should have unlimited names.
+ * @return The formatted citation.
+ */
+ public String getCitationMarker(BibtexEntry[] entries, BibtexDatabase database, boolean inParenthesis,
+ String[] uniquefiers, int[] unlimAuthors) {
+
+ // Look for groups of uniquefied entries that should be combined in the output.
+ // E.g. (Olsen, 2005a, b) should be output instead of (Olsen, 2005a; Olsen, 2005b).
+ int piv = -1;
+ String tmpMarker = null;
+ if (uniquefiers != null) {
+ for (int i = 0; i < uniquefiers.length; i++) {
+
+ if ((uniquefiers[i] != null) && (uniquefiers[i].length() > 0)) {
+ String authorField = (String)citProperties.get("AuthorField");
+ int maxAuthors = (Integer)citProperties.get("MaxAuthors");
+ if (piv == -1) {
+ piv = i;
+ tmpMarker = getAuthorYearParenthesisMarker(new BibtexEntry[] {entries[i]}, database,
+ authorField,
+ (String)citProperties.get("YearField"),
+ maxAuthors,
+ (String)citProperties.get("AuthorSeparator"),
+ (String)citProperties.get("AuthorLastSeparator"),
+ (String)citProperties.get("EtAlString"),
+ (String)citProperties.get("YearSeparator"),
+ (String)citProperties.get("BracketBefore"),
+ (String)citProperties.get("BracketAfter"),
+ (String)citProperties.get("CitationSeparator"), null, unlimAuthors);
+ //System.out.println("piv="+piv+" tmpMarker='"+tmpMarker+"'");
+ }
+ else {
+ // See if this entry can go into a group with the previous one:
+ String thisMarker = getAuthorYearParenthesisMarker(new BibtexEntry[] {entries[i]}, database,
+ authorField,
+ (String)citProperties.get("YearField"),
+ maxAuthors,
+ (String)citProperties.get("AuthorSeparator"),
+ (String)citProperties.get("AuthorLastSeparator"),
+ (String)citProperties.get("EtAlString"),
+ (String)citProperties.get("YearSeparator"),
+ (String)citProperties.get("BracketBefore"),
+ (String)citProperties.get("BracketAfter"),
+ (String)citProperties.get("CitationSeparator"), null, unlimAuthors);
+
+ String author = getCitationMarkerField(entries[i], database,
+ authorField);
+ AuthorList al = AuthorList.getAuthorList(author);
+ //System.out.println("i="+i+" thisMarker='"+thisMarker+"'");
+ int prevALim = i > 0 ? unlimAuthors[i-1] : unlimAuthors[0];
+ if (!thisMarker.equals(tmpMarker) ||
+ ((al.size() > maxAuthors) && (unlimAuthors[i] != prevALim))) {
+ // No match. Update piv to exclude the previous entry. But first check if the
+ // previous entry was part of a group:
+ if ((piv > -1) && (i > piv+1)) {
+ // Do the grouping:
+ group(entries, uniquefiers, piv, i-1, (String)citProperties.get("UniquefierSeparator"));
+ }
+ tmpMarker = thisMarker;
+ piv = i;
+ }
+ }
+ }
+ else {
+ // This entry has no uniquefier.
+ // Check if we just passed a group of more than one entry with uniquefier:
+ if ((piv > -1) && (i > piv+1)) {
+ // Do the grouping:
+ group(entries, uniquefiers, piv, i-1, (String)citProperties.get("UniquefierSeparator"));
+ }
+
+ piv = -1;
+ }
+
+ }
+ // Finished with the loop. See if the last entries form a group:
+ if (piv >= 0) {
+ // Do the grouping:
+ group(entries, uniquefiers, piv, uniquefiers.length-1, (String)citProperties.get("UniquefierSeparator"));
+ }
+ }
+
+ if (inParenthesis)
+ return getAuthorYearParenthesisMarker(entries, database,
+ (String)citProperties.get("AuthorField"),
+ (String)citProperties.get("YearField"),
+ (Integer)citProperties.get("MaxAuthors"),
+ (String)citProperties.get("AuthorSeparator"),
+ (String)citProperties.get("AuthorLastSeparator"),
+ (String)citProperties.get("EtAlString"),
+ (String)citProperties.get("YearSeparator"),
+ (String)citProperties.get("BracketBefore"),
+ (String)citProperties.get("BracketAfter"),
+ (String)citProperties.get("CitationSeparator"),
+ uniquefiers, unlimAuthors);
+ else {
+ String authorLastSeparator = (String)citProperties.get("AuthorLastSeparator");
+ String alsInText = (String)citProperties.get("AuthorLastSeparatorInText");
+ if (alsInText != null)
+ authorLastSeparator = alsInText;
+ return getAuthorYearInTextMarker(entries, database,
+ (String)citProperties.get("AuthorField"),
+ (String)citProperties.get("YearField"),
+ (Integer)citProperties.get("MaxAuthors"),
+ (String)citProperties.get("AuthorSeparator"),
+ authorLastSeparator,
+ (String)citProperties.get("EtAlString"),
+ (String)citProperties.get("InTextYearSeparator"),
+ (String)citProperties.get("BracketBefore"),
+ (String)citProperties.get("BracketAfter"),
+ (String)citProperties.get("CitationSeparator"),
+ uniquefiers, unlimAuthors);
+ }
+ }
+
+ /**
+ * Modify entry and uniqiefier arrays to facilitate a grouped presentation of uniqiefied entries.
+ * @param entries The entry array.
+ * @param uniquefiers The uniquefier array.
+ * @param from The first index to group (inclusive)
+ * @param to The last index to group (inclusive)
+ * @param separator The separator for the uniquefier letters.
+ */
+ private void group(BibtexEntry[] entries, String[] uniquefiers, int from, int to, String separator) {
+ StringBuilder sb = new StringBuilder(uniquefiers[from]);
+ for (int i=from+1; i<=to; i++) {
+ sb.append(separator);
+ sb.append(uniquefiers[i]);
+ entries[i] = null;
+ }
+ uniquefiers[from] = sb.toString();
+ }
+
+ /**
+ * This method produces (Author, year) style citation strings in many different forms.
+ *
+ * @param entries The array of BibtexEntry to get fields from.
+ * @param authorField The bibtex field providing author names, e.g. "author" or "editor".
+ * @param yearField The bibtex field providing the year, e.g. "year".
+ * @param maxA The maximum number of authors to write out in full without using etal. Set to
+ * -1 to always write out all authors.
+ * @param authorSep The String to add between author names except the last two, e.g. ", ".
+ * @param andString The String to add between the two last author names, e.g. " & ".
+ * @param etAlString The String to represent authors that are not mentioned, e.g. " et al."
+ * @param yearSep The String to separate authors from year, e.g. "; ".
+ * @param startBrace The opening parenthesis.
+ * @param endBrace The closing parenthesis.
+ * @param citationSeparator The String to separate citations from each other.
+ * @param uniquifiers Optional parameter to separate similar citations. Elements can be null if not needed.
+ * @return The formatted citation.
+ */
+ public String getAuthorYearParenthesisMarker(BibtexEntry[] entries, BibtexDatabase database,
+ String authorField, String yearField,
+ int maxA, String authorSep,
+ String andString, String etAlString, String yearSep,
+ String startBrace, String endBrace, String citationSeparator,
+ String[] uniquifiers, int[] unlimAuthors) {
+
+
+ StringBuffer sb = new StringBuffer(startBrace);
+ for (int j=0; j 0 ? unlimA : maxA;
+
+ BibtexEntry entry = entries[j];
+
+ // Check if this entry has been nulled due to grouping with the previous entry(ies):
+ if (entry == null)
+ continue;
+
+ if (j > 0)
+ sb.append(citationSeparator);
+
+ String author = getCitationMarkerField(entry, database, authorField);
+
+ if (author != null) {
+ AuthorList al = AuthorList.getAuthorList(author);
+ sb.append(getAuthorLastName(al, 0));
+
+ if ((al.size() > 1) && ((al.size() <= maxAuthors) || (maxAuthors < 0))) {
+ int i=1;
+ while (i < al.size()-1) {
+ sb.append(authorSep);
+ sb.append(getAuthorLastName(al, i));
+ i++;
+ }
+ sb.append(andString);
+ sb.append(getAuthorLastName(al, al.size()-1));
+ } else if (al.size() > maxAuthors) {
+ sb.append(etAlString);
+ }
+ sb.append(yearSep);
+ }
+ String year = getCitationMarkerField(entry, database, yearField);
+ if (year != null)
+ sb.append(year);
+ if ((uniquifiers != null) && (uniquifiers[j] != null))
+ sb.append(uniquifiers[j]);
+ }
+ sb.append(endBrace);
+ return sb.toString();
+
+ }
+
+ /**
+ * This method produces "Author (year)" style citation strings in many different forms.
+ *
+ * @param entries The array of BibtexEntry to get fields from.
+ * @param authorField The bibtex field providing author names, e.g. "author" or "editor".
+ * @param yearField The bibtex field providing the year, e.g. "year".
+ * @param maxA The maximum number of authors to write out in full without using etal. Set to
+ * -1 to always write out all authors.
+ * @param authorSep The String to add between author names except the last two, e.g. ", ".
+ * @param andString The String to add between the two last author names, e.g. " & ".
+ * @param etAlString The String to represent authors that are not mentioned, e.g. " et al."
+ * @param yearSep The String to separate authors from year, e.g. "; ".
+ * @param startBrace The opening parenthesis.
+ * @param endBrace The closing parenthesis.
+ * @param uniquefiers Optional parameters to separate similar citations. Can be null if not needed.
+ * @return The formatted citation.
+ */
+ public String getAuthorYearInTextMarker(BibtexEntry[] entries, BibtexDatabase database, String authorField,
+ String yearField, int maxA, String authorSep,
+ String andString, String etAlString, String yearSep,
+ String startBrace, String endBrace, String citationSeparator,
+ String[] uniquefiers, int[] unlimAuthors) {
+ StringBuffer sb = new StringBuffer();
+ for (int i=0; i 0 ? unlimA : maxA;
+
+ // Check if this entry has been nulled due to grouping with the previous entry(ies):
+ if (entries[i] == null)
+ continue;
+
+ if (i > 0)
+ sb.append(citationSeparator);
+ String author = getCitationMarkerField(entries[i], database, authorField);
+ if (author != null) {
+ AuthorList al = AuthorList.getAuthorList(author);
+ if (al.size() > 0)
+ sb.append(getAuthorLastName(al, 0));
+ if ((al.size() > 1) && ((al.size() <= maxAuthors) || (maxAuthors < 0))) {
+ int j=1;
+ while (j < al.size()-1) {
+ sb.append(authorSep);
+ sb.append(getAuthorLastName(al, j));
+ j++;
+ }
+ sb.append(andString);
+ sb.append(getAuthorLastName(al, al.size()-1));
+ } else if (al.size() > maxAuthors) {
+ sb.append(etAlString);
+ }
+ sb.append(yearSep);
+ }
+ sb.append(startBrace);
+ String year = getCitationMarkerField(entries[i], database, yearField);
+ if (year != null)
+ sb.append(year);
+ if ((uniquefiers != null) && (uniquefiers[i] != null))
+ sb.append(uniquefiers[i]);
+ sb.append(endBrace);
+ }
+ return sb.toString();
+
+ }
+
+ /**
+ * This method looks up a field for en entry in a database. Any number of backup fields can be used
+ * if the primary field is empty.
+ * @param entry The entry.
+ * @param database The database the entry belongs to.
+ * @param field The field, or succession of fields, to look up. If backup fields are needed, separate
+ * field names by /. E.g. to use "author" with "editor" as backup, specify "author/editor".
+ * @return The resolved field content, or an empty string if the field(s) were empty.
+ */
+ public String getCitationMarkerField(BibtexEntry entry, BibtexDatabase database, String field) {
+ String[] fields = field.split("/");
+ for (int i = 0; i < fields.length; i++) {
+ String s = fields[i];
+ String content = BibtexDatabase.getResolvedField(s, entry, database);
+ if ((content != null) && (content.trim().length() > 0))
+ return content;
+ }
+ // No luck? Return an empty string:
+ return "";
+ }
+
+ /**
+ * Look up the nth author and return the proper last name for citation markers.
+ * @param al The author list.
+ * @param number The number of the author to return.
+ * @return The author name, or an empty String if inapplicable.
+ */
+ public String getAuthorLastName(AuthorList al, int number) {
+ StringBuilder sb = new StringBuilder();
+
+ if (al.size() > number) {
+ AuthorList.Author a = al.getAuthor(number);
+ if ((a.getVon() != null) && a.getVon().length() > 0) {
+ String von = a.getVon();
+ sb.append(von);
+ /*sb.append(von.substring(0, 1).toUpperCase());
+ if (von.length() > 1)
+ sb.append(von.substring(1));*/
+ sb.append(' ');
+ }
+ sb.append(a.getLast());
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Convenience method for checking the property for whether we use number citations or
+ * author-year citations.
+ * @return true if we use numbered citations, false otherwise.
+ */
+ public boolean isNumberEntries() {
+ return (Boolean)getProperty("IsNumberEntries");
+ }
+
+ /**
+ * Convenience method for checking the property for whether we sort the bibliography
+ * according to their order of appearance in the text.
+ * @return true to sort by appearance, false to sort alphabetically.
+ */
+ public boolean isSortByPosition() {
+ return (Boolean)getProperty("IsSortByPosition");
+ }
+
+ /**
+ * Convenience method for checking whether citation markers should be italicised.
+ * Will only be relevant if isFormatCitations() returns true.
+ * @return true to indicate that citations should be in italics.
+ */
+ public boolean isItalicCitations() {
+ return (Boolean)citProperties.get("ItalicCitations");
+ }
+
+ /**
+ * Convenience method for checking whether citation markers should be bold.
+ * Will only be relevant if isFormatCitations() returns true.
+ * @return true to indicate that citations should be in bold.
+ */
+ public boolean isBoldCitations() {
+ return (Boolean)citProperties.get("BoldCitations");
+ }
+
+ /**
+ * Convenience method for checking whether citation markers formatted
+ * according to the results of the isItalicCitations() and
+ * isBoldCitations() methods.
+ * @return true to indicate that citations should be in italics.
+ */
+ public boolean isFormatCitations() {
+ return (Boolean)citProperties.get("FormatCitations");
+ }
+
+ /**
+ * Get boolean property.
+ * @param key The property key
+ * @return the value
+ */
+ public boolean getBooleanCitProperty(String key) {
+ return (Boolean)citProperties.get(key);
+ }
+
+ public int getIntCitProperty(String key) {
+ return (Integer)citProperties.get(key);
+ }
+ /**
+ * Get a style property.
+ * @param name The property name.
+ * @return The property value, or null if it doesn't exist.
+ */
+ public Object getProperty(String name) {
+ return properties.get(name);
+ }
+
+ public int compareTo(Object o) {
+ OOBibStyle other = (OOBibStyle)o;
+ return getName().compareTo(other.getName());
+ }
+
+ public boolean equals(Object o) {
+ return styleFile.equals(((OOBibStyle)o).styleFile);
+ }
+}
diff --git a/net/sf/jabref/oo/OOUtil.java b/net/sf/jabref/oo/OOUtil.java
new file mode 100755
index 0000000..c2ca2e5
--- /dev/null
+++ b/net/sf/jabref/oo/OOUtil.java
@@ -0,0 +1,285 @@
+package net.sf.jabref.oo;
+
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.beans.Property;
+import com.sun.star.text.*;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.frame.XDesktop;
+import net.sf.jabref.BibtexDatabase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.BibtexFields;
+import net.sf.jabref.export.layout.Layout;
+
+import javax.swing.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.List;
+import java.util.Iterator;
+
+/**
+ * Utility methods for processing OO Writer documents.
+ */
+public class OOUtil {
+
+
+ static Pattern htmlTag = Pattern.compile("?[a-z]+>");
+
+ static OOPreFormatter postformatter = new OOPreFormatter();
+
+ /**
+ * Insert a reference, formatted using a Layout, at the position of a given cursor.
+ * @param text The text to insert in.
+ * @param cursor The cursor giving the insert location.
+ * @param layout The Layout to format the reference with.
+ * @param parStyle The name of the paragraph style to use.
+ * @param entry The entry to insert.
+ * @param database The database the entry belongs to.
+ * @param uniquefier Uniqiefier letter, if any, to append to the entry's year.
+ * @throws Exception
+ */
+ public static void insertFullReferenceAtCurrentLocation(XText text, XTextCursor cursor,
+ Layout layout, String parStyle, BibtexEntry entry, BibtexDatabase database, String uniquefier)
+ throws UndefinedParagraphFormatException, Exception {
+
+ final String UNIQUEFIER_FIELD = "uniq";
+
+ // Backup the value of the uniq field, just in case the entry already has it:
+ String oldUniqVal = (String)entry.getField(UNIQUEFIER_FIELD);
+
+ // Set the uniq field with the supplied uniquefier:
+ entry.setField(UNIQUEFIER_FIELD, uniquefier);
+
+ // Do the layout for this entry:
+ String lText = layout.doLayout(entry, database);
+
+ // Afterwards, reset the old value:
+ entry.setField(UNIQUEFIER_FIELD, oldUniqVal);
+
+ // Insert the formatted text:
+ insertOOFormattedTextAtCurrentLocation(text, cursor, lText, parStyle);
+ }
+
+ /**
+ * Insert a text with formatting indicated by HTML-like tags, into a text at
+ * the position given by a cursor.
+ * @param text The text to insert in.
+ * @param cursor The cursor giving the insert location.
+ * @param lText The marked-up text to insert.
+ * @param parStyle The name of the paragraph style to use.
+ * @throws Exception
+ */
+ public static void insertOOFormattedTextAtCurrentLocation(XText text, XTextCursor cursor,
+ String lText, String parStyle) throws UndefinedParagraphFormatException, Exception {
+
+ XParagraphCursor parCursor = (XParagraphCursor)UnoRuntime.queryInterface(
+ XParagraphCursor.class, cursor);
+ XPropertySet props = (XPropertySet) UnoRuntime.queryInterface(
+ XPropertySet.class, parCursor);
+
+ try {
+ props.setPropertyValue("ParaStyleName", parStyle);
+ } catch (com.sun.star.lang.IllegalArgumentException ex) {
+ throw new UndefinedParagraphFormatException(parStyle);
+ }
+
+ // We need to extract formatting. Use a simple regexp search iteration:
+ int piv = 0;
+ int italic = 0, bold = 0, sup = 0, sub = 0, mono = 0, smallCaps = 0;
+ //insertTextAtCurrentLocation(text, cursor, "_",
+ // false, false, false, false, false, false);
+ //cursor.goLeft((short)1, true);
+ Matcher m = htmlTag.matcher(lText);
+ while (m.find()) {
+ String ss = lText.substring(piv, m.start());
+ if (ss.length() > 0) {
+ insertTextAtCurrentLocation(text, cursor, ss, (bold % 2) > 0, (italic % 2) > 0,
+ mono > 0, smallCaps > 0, sup > 0, sub > 0);
+ }
+ String tag = m.group();
+ // Handle tags:
+ if (tag.equals(""))
+ bold++;
+ else if (tag.equals(""))
+ bold--;
+ else if (tag.equals("") || tag.equals(""))
+ italic++;
+ else if (tag.equals("") || tag.equals(""))
+ italic--;
+ else if (tag.equals(""))
+ mono = 0;
+ else if (tag.equals(""))
+ mono = 1;
+ else if (tag.equals(""))
+ smallCaps = 0;
+ else if (tag.equals(""))
+ smallCaps = 1;
+ else if (tag.equals(""))
+ sup = 0;
+ else if (tag.equals(""))
+ sup = 1;
+ else if (tag.equals(""))
+ sub = 0;
+ else if (tag.equals(""))
+ sub = 1;
+
+ piv = m.end();
+
+ }
+
+ if (piv < lText.length())
+ insertTextAtCurrentLocation(text, cursor,lText.substring(piv),
+ (bold % 2) > 0, (italic % 2) > 0, mono > 0, smallCaps > 0, sup > 0, sub > 0);
+
+
+
+ cursor.collapseToEnd();
+ }
+
+ public static void insertParagraphBreak(XText text, XTextCursor cursor) throws Exception {
+ text.insertControlCharacter(cursor, ControlCharacter.PARAGRAPH_BREAK, true);
+ cursor.collapseToEnd();
+ }
+
+ public static void insertTextAtCurrentLocation(XText text, XTextCursor cursor, String string,
+ boolean bold, boolean italic, boolean monospace, boolean smallCaps, boolean superscript,
+ boolean subscript) throws Exception {
+ text.insertString(cursor, string, true);
+ // Access the property set of the cursor, and set the currently selected text
+ // (which is the string we just inserted) to be bold
+ XPropertySet xCursorProps = (XPropertySet) UnoRuntime.queryInterface(
+ XPropertySet.class, cursor);
+ if (bold)
+ xCursorProps.setPropertyValue("CharWeight",
+ new Float(com.sun.star.awt.FontWeight.BOLD));
+ else
+ xCursorProps.setPropertyValue("CharWeight",
+ new Float(com.sun.star.awt.FontWeight.NORMAL));
+
+ if (italic)
+ xCursorProps.setPropertyValue("CharPosture",
+ com.sun.star.awt.FontSlant.ITALIC);
+ else
+ xCursorProps.setPropertyValue("CharPosture",
+ com.sun.star.awt.FontSlant.NONE);
+
+ if (smallCaps) {
+ xCursorProps.setPropertyValue("CharCaseMap",
+ com.sun.star.style.CaseMap.SMALLCAPS);
+ }
+ else {
+ xCursorProps.setPropertyValue("CharCaseMap",
+ com.sun.star.style.CaseMap.NONE);
+ }
+
+ // TODO: the tag doesn't work
+ /*
+ if (monospace) {
+ xCursorProps.setPropertyValue("CharFontPitch",
+ com.sun.star.awt.FontPitch.FIXED);
+ }
+ else {
+ xCursorProps.setPropertyValue("CharFontPitch",
+ com.sun.star.awt.FontPitch.VARIABLE);
+ } */
+ if (subscript) {
+ xCursorProps.setPropertyValue("CharEscapement",
+ (byte)-101);
+ xCursorProps.setPropertyValue("CharEscapementHeight",
+ (byte)58);
+ }
+ else if (superscript) {
+ xCursorProps.setPropertyValue("CharEscapement",
+ (byte)101);
+ xCursorProps.setPropertyValue("CharEscapementHeight",
+ (byte)58);
+ }
+ else {
+ xCursorProps.setPropertyValue("CharEscapement",
+ (byte)0);
+ xCursorProps.setPropertyValue("CharEscapementHeight",
+ (byte)100);
+ }
+
+ cursor.collapseToEnd();
+
+ }
+
+ public static void insertTextAtCurrentLocation(XText text, XTextCursor cursor, String string,
+ String parStyle) throws Exception {
+ text.insertString(cursor, string, true);
+ XParagraphCursor parCursor = (XParagraphCursor)UnoRuntime.queryInterface(
+ XParagraphCursor.class, cursor);
+ // Access the property set of the cursor, and set the currently selected text
+ // (which is the string we just inserted) to be bold
+ XPropertySet props = (XPropertySet) UnoRuntime.queryInterface(
+ XPropertySet.class, parCursor);
+ try {
+ props.setPropertyValue("ParaStyleName", parStyle);
+ } catch (com.sun.star.lang.IllegalArgumentException ex) {
+ throw new UndefinedParagraphFormatException(parStyle);
+ }
+ cursor.collapseToEnd();
+
+ }
+
+
+
+ public static Object getProperty(Object o, String property) throws Exception {
+ XPropertySet props = (XPropertySet) UnoRuntime.queryInterface(
+ XPropertySet.class, o);
+ return props.getPropertyValue(property);
+ }
+
+ public static void listProperties(Object o) throws Exception {
+ XPropertySet props = (XPropertySet) UnoRuntime.queryInterface(
+ XPropertySet.class, o);
+ Property[] pr = props.getPropertySetInfo().getProperties();
+ for (int i = 0; i < pr.length; i++) {
+ Property property1 = pr[i];
+ System.out.println(property1.Name+" : "+props.getPropertyValue(property1.Name));
+ }
+ }
+
+ public static XTextDocument selectComponent(JFrame parent, XDesktop xDesktop, List list) throws Exception {
+ String[] values = new String[list.size()];
+ int ii=0;
+ for (Iterator iterator = list.iterator(); iterator.hasNext();) {
+ XTextDocument doc = iterator.next();
+ values[ii++] = String.valueOf(getProperty(doc.getCurrentController().getFrame(), "Title"));
+ }
+ JList sel = new JList(values);
+ sel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ sel.setSelectedIndex(0);
+ int ans = JOptionPane.showConfirmDialog(parent, new JScrollPane(sel), Globals.lang("Select document"),
+ JOptionPane.OK_CANCEL_OPTION);
+ if (ans == JOptionPane.OK_OPTION) {
+ return list.get(sel.getSelectedIndex());
+ }
+ else return null;
+ }
+
+ /**
+ * Make a cloned BibtexEntry and do the necessary preprocessing for use by the plugin.
+ * If the running JabRef version doesn't support post-processing in Layout, this
+ * preprocessing includes running the OOPreFormatter formatter for all fields except the
+ * BibTeX key.
+ * @param entry the original entry
+ * @return the cloned and processed entry
+ */
+ public static BibtexEntry createAdaptedEntry(BibtexEntry entry) {
+ if (entry == null)
+ return null;
+ BibtexEntry e = (BibtexEntry)entry.clone();
+ for (String field : e.getAllFields()) {
+ if (field.equals(BibtexFields.KEY_FIELD))
+ continue;
+ String value = e.getField(field);
+ // If the running JabRef version doesn't support post-processing in Layout,
+ // preprocess fields instead:
+ if (!OOTestPanel.postLayoutSupported && (value != null))
+ e.setField(field, postformatter.format(value));
+ }
+ return e;
+ }
+}
diff --git a/plugin.xml b/plugin.xml
new file mode 100755
index 0000000..5f967c6
--- /dev/null
+++ b/plugin.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--
2.30.2